This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA
)
Tru64 UNIX
Alpha
7.4
2003-10-25, 5.1b, Peter Eisentraut (); 2003-10-29, 4.0g, Alessio Bragadini ( )
UnixWare
x86
7.4
2003-11-03, Larry Rosenman ()
2.8; veja também doc/FAQ_Solaris
2.6; veja também doc/FAQ_Solaris
7.1.3; teste de junção pode falhar, veja também doc/FAQ_SCO
Windows with Cygwin
x86
Windows
x86
7.4
7.4
2003-10-24, Peter Eisentraut ()
see
2003-10-27, Dave Page (
nativo somente no lado cliente, veja o Capítulo 15
housing.co.uk>)
doc/FAQ_MSWIN
Plataformas não suportadas: Nas seguintes plataformas ou não se sabe se funciona, ou funcionavam na versão anterior mas não foi recebida uma confirmação explícita de testes bem-sucedidos com a versão 7.4 quando esta relação foi compilada. Está incluído aqui para que você saiba que estas plataformas podem ser suportadas se for dada alguma atenção. S.O.
Processador
Versão
Relatado
Comentários
BeOS
x86
7.2
2001-11-29, Cyril Velter ()
necessita atualização para o código de semáforo
Linux
PlayStation 2
7.4
2003-11-02, Peter Eisentraut ()
necessita novo config.guess, -disable-spinlocks, #undef HAS_TEST_AND_SET,
desabilitar tas_dummy()
Linux
PA-RISC
7.4
2003-10-25, Noèl Köthe ( <[email protected]>)
necessita --disablespinlocks, fora isso OK
NetBSD
Alpha
7.2
2001-11-20, Thomas Thai ()
1.5W
NetBSD
MIPS
7.2.1
2002-06-13, Warwick Hunter
1.5.3
260
S.O.
Processador
Versão
Relatado
Comentários
(<[email protected]>) NetBSD
PPC
7.2
2001-11-28, Bill Studenmund ( <[email protected]>)
1.5
NetBSD
VAX
7.1
2001-03-30, Tom I. Helbekkmo ()
1.5
QNX 4 RTOS
x86
7.2
2001-12-10, Bernd Tegge ()
necessita atualização para o código de semáforo; veja também doc/FAQ_QNX4
QNX RTOS v6
x86
7.2
2001-11-20, Igor Kovalenko ()
correções disponíveis para cópias de segurança, mas muito tarde para a 7.2
SCO OpenServ er
x86
7.3.1
2002-12-11, Shibashish Satpathy ( <[email protected]>)
5.0.4, gcc; veja também doc/FAQ_SCO
SunOS 4
Sparc
7.2
2001-12-04, Tatsuo Ishii ()
Notas 1. No Debian 3.0r2 o make do GNU está instalado sob o nome make mesmo, e não gmake, e no Fedora Core 1 o gmake é um vínculo simbólico para o make. (N. do T.) 2. spinlock — em engenharia de software é um bloqueio onde cada segmento (thread) simplesmente aguarda em um laço (gira/spins) verificando repetidamente até que o bloqueio fique disponível. Free Online Dictionary and Thesaurus (http://encyclopedia.thefreedictionary.com/Spin%20lock) (N. do T.) 3. thread-safe — (programação) A descrição de um código que é reentrante ou protegido em várias execuções simultâneas por alguma forma de exclusão mútua. FOLDOC - Free On-Line Dictionary of Computing (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=thread-safe) (N. do T.) 4. asserção — do Lat. assertione — proposição que se apresenta como verdadeira. PRIBERAM - Língua Portuguesa On-Line (http://www.priberam.pt/dlpo/dlpo.aspx). (N. do T.) 5. strip — (comando do Unix) O comando strip remove a tabela de símbolos, informação de depuração e informação de número de linha de arquivos objeto ELF. Após ter sido realizado o processo de strip, não haverá nenhum acesso de depuração simbólica para este arquivo; normalmente este comando só é executado em módulos de produção que já foram depurados e testados. Man Page (http://www.cs.princeton.edu/cgi-bin/man2html?strip:1) (N. do T.) 6. ld.so — ligador em tempo de execução (run-time linker) para objetos dinâmicos. Página do Manual (http://mirrors.ccs.neu.edu/cgi-bin/unixhelp/man-cgi?ld.so.1+1) (N. do T.) 7. rld — ligador em tempo de execução (run-time (http://www.mcsr.olemiss.edu/cgi-bin/man-cgi?rld+1) (N. do T.)
linker).
Página
do
Manual
8. ldconfig — determina os vínculos de ligação em tempo de execução. Página do Manual (http://www.rt.com/man/ldconfig.8.html) (N. do T.)
261
Capítulo 15. Instalação no Windows Embora o PostgreSQL seja escrito para sistemas operacionais da família Unix, a biblioteca cliente C (libpq) e o terminal interativo (psql) podem ser compilados de forma nativa sob o Windows. Os arquivos de construção incluídos na distribuição do código fonte são escritos para o Microsoft Visual C++ e, provavelmente, não funcionam com outros compiladores. Deve ser possível compilar as bibliotecas manualmente nos demais casos. Dica: Se estiver sendo utilizado o Windows 98, ou uma versão mais recente, todo o PostgreSQL pode ser construído e utilizado da “maneira Unix”, se primeiro for instalado o conjunto de ferramentas Cygwin. Neste caso veja o Capítulo 14.
Para construir tudo que é possível no Windows, torne o diretório src o diretório corrente e execute o comando: nmake /f win32.mak
Este comando pressupõe a existência do Visual C++ no caminho de procura. Os seguintes arquivos serão construídos: interfaces\libpq\Release\libpq.dll
A biblioteca de vínculo dinâmico cliente. interfaces\libpq\Release\libpqdll.lib
A biblioteca de importação para vincular os programas a libpq.dll interfaces\libpq\Release\libpq.lib
A versão estática da biblioteca cliente bin\psql\Release\psql.exe
O terminal interativo do PostgreSQL O único arquivo que realmente há necessidade de ser instalado é a biblioteca libpq.dll. Na maioria dos casos este arquivo deve ser colocado no diretório WINNT\SYSTEM32 (ou no WINDOWS\SYSTEM no Windows 95/98/ME). Se este arquivo for instalado utilizando o programa de configuração, deve ser instalado com verificação de versão utilizando o recurso VERSIONINFO incluído no arquivo, para garantir que uma versão mais nova da biblioteca não seja sobrescrita. Se for planejado fazer desenvolvimento utilizando a libpq, é necessário adicionar os subdiretórios src\include e src\interfaces\libpq da árvore do código fonte ao caminho de inclusão na configuração
do compilador. Para utilizar a biblioteca, deve ser adicionado o arquivo libpqdll.lib ao projeto (No Visual C++ simplesmente dê um clique com o botão direito do mouse no projeto e escolha adicioná-lo). O psql é compilado como uma “aplicação console”. Como as janelas console do Windows utilizam uma codificação diferente do restante do sistema, deve ser tomado cuidado especial quando são utilizados caracteres de 8 bits no prompt do psql. Quando o psql detecta uma página de código da console problemática, é emitida uma advertência na inicialização. Para mudar a página de código da console são necessárias duas coisas: •
Definir a página de código entrando com cmd.exe /c chcp 1252 (1252 é a página de código apropriada para a Alemanha 1 ; substitua com o valor apropriado para suas necessidades). Se estiver sendo utilizado o Cygwin, este comando pode ser colocado em /etc/profile.
•
Defina a fonte da console como “Lucida Console”, porque a fonte de varredura (raster) não funciona com a página de código ANSI.
262
Notas 1. Microsoft Windows Codepage : 1252 (Latin I) (http://www.microsoft.com/globaldev/reference/sbcs/1252.htm) — Localização: Basco, Catalão, Dinamarquês, Holandês, Inglês, Finlandês, Francês, Alemão, Indonésio, Italiano, Norueguês, Português, Espanhol e Sueco. NLS Information for Microsoft Windows XP (http://www.microsoft.com/globaldev/nlsweb/) (N. do T.)
263
Capítulo 16. Ambiente do servidor em tempo de execução Este capítulo discute como configurar e executar os servidor de banco de dados e as interações com o sistema operacional.
16.1. A conta de usuário do PostgreSQL Assim como qualquer outro processo (daemon) servidor conectado ao mundo exterior, é aconselhável executar o PostgreSQL sob uma conta de usuário em separado. Esta conta de usuário somente deve possuir os dados gerenciados pelo servidor, não devendo ser compartilhada por outros processos; por exemplo, a utilização do usuário nobody é uma má idéia. Não é aconselhável instalar executáveis cujo dono seja este usuário, porque sistemas comprometidos poderiam modificar seus próprios binários. Para adicionar uma conta de usuário Unix ao sistema procure pelo comando useradd ou adduser. Normalmente o nome de usuário postgres é utilizado, mas isto não é requerido de forma alguma.
16.2. Criação do agrupamento de bancos de dados Antes de ser possível fazer qualquer coisa, deve ser inicializada a área de armazenamento dos bancos de dados no disco. Isto é chamado de agrupamento de bancos de dados (database cluster); em vez desse nome, o padrão SQL utiliza o termo agrupamento de catálogos (catalog cluster). Um agrupamento de bancos de dados é uma coleção de bancos de dados acessível por uma única instância de um servidor de banco de dados em execução. Após a inicialização, o agrupamento de bancos de dados contém um banco de dados chamado template1. Como o nome sugere (em inglês), este banco de dados é utilizado como modelo para os próximos bancos a serem criados; não deve ser utilizado para trabalho (Veja o Capítulo 18 para obter informações sobre a criação de bancos de dados). Em termos de sistema de arquivos, um agrupamento de bancos de dados é um único diretório sob o qual todos os dados são armazenados. É chamado de diretório de dados ou área de dados. Depende totalmente de quem instala a escolha do local onde os dados serão armazenados. Não existe nenhum padrão, embora locais como /usr/local/pgsql/data ou /var/lib/pgsql/data sejam comuns (/home/postgres/data também é comum, N. do T.). Para inicializar um agrupamento de bancos de dados deve ser utilizado o comando initdb, que é instalado junto com o PostgreSQL. O local no sistema de arquivos escolhido para o sistema de banco de dados é indicado pela opção -D como, por exemplo: $ initdb -D /usr/local/pgsql/data
Observe que este comando deve ser executado enquanto conectado na conta de usuário do PostgreSQL, conforme foi descrito na seção anterior. Dica: Como alternativa para a opção -D, pode ser definida a variável de ambiente PGDATA.
O comando initdb tenta criar o diretório especificado se este não existir. É provável que o usuário utilizado não tenha permissão para criar o diretório (se o conselho de criar um usuário sem privilégios foi seguido). Neste caso você deve criar o diretório por si próprio (como root) e mudar o dono do diretório para o usuário do PostgreSQL. Abaixo está mostrado como deve ser feito: root# mkdir /usr/local/pgsql/data root# chown postgres /usr/local/pgsql/data root# su - postgres postgres$ initdb -D /usr/local/pgsql/data
O comando initdb se recusa a executar quando o diretório de dados parecer que já foi inicializado. Como o diretório de dados contém todos os dados armazenados no banco de dados, é essencial que esteja seguro contra acessos não autorizados. Portanto, o comando initdb revoga as permissões de acesso de todos, menos do usuário do PostgreSQL.
264
Entretanto, embora o conteúdo do diretório esteja seguro, a configuração de autenticação de cliente permite qualquer usuário local se conectar ao banco de dados, e até mesmo se tornar o superusuário do banco de dados. Se os outros usuários locais não forem confiáveis, é recomendado utilizar a opção -W do initdb, ou a opção -pwprompt, para atribuir uma senha ao superusuário do banco de dados. Após executar o initdb deve ser modificado o arquivo pg_hba.conf para utilizar a autenticação md5 ou password, em vez de trust, antes de iniciar o servidor pela primeira vez (Outras abordagens incluem a utilização da autenticação ident ou permissões do sistema de arquivos para restringir as conexões. Veja o Capítulo 19 para obter mais informações). O comando initdb também inicializa a localização padrão para o agrupamento de bancos de dados. Normalmente, simplesmente pega as definições de localização do ambiente e as aplica ao banco de dados inicializado. É possível especificar uma localização diferente para o banco de dados; mais informações sobre este assunto podem ser encontradas na Seção 20.1. A ordem de classificação utilizada por um determinado agrupamento de bancos de dados é definida por initdb não podendo ser mudada posteriormente, a não ser fazendo cópia de segurança de todos os dados, executando novamente initdb e recarregando os dados. Portanto, é importante fazer a escolha correta da primeira vez.
16.3. Inicialização do servidor de banco de dados Antes que alguém possa acessar o banco de dados, o servidor de banco de dados deve ser inicializado. O programa servidor de banco de dados chama-se postmaster. O postmaster deve saber onde encontrar os dados a serem utilizados, o que é feito através da opção -D. Portanto, a maneira mais simples de inicializar o servidor é $ postmaster -D /usr/local/pgsql/data
que deixa o servidor processando em segundo plano. Deve ser executado enquanto conectado à conta de usuário do PostgreSQL. Sem a opção -D o servidor tenta utilizar o diretório de dados especificado na variável de ambiente PGDATA. Se nenhuma destas tentativas for bem-sucedida, então a inicialização falha. Para inicializar o postmaster em segundo plano, a sintaxe usual para o interpretador de comandos é: $ postmaster -D /usr/local/pgsql/data >logfile 2>&1 &
É importante armazenar as saídas stdout e stderr do servidor em algum lugar, conforme mostrado acima. Isto é útil para fins de auditoria e para o diagnóstio de problemas (Veja na Seção 21.3 uma explicação mais detalhada sobre o tratamento do arquivo de log). O postmaster também aceita várias outras opções de linha de comando. Para obter mais informações, veja a página de referência e a Seção 16.4 abaixo. Em particular, para o servidor aceitar conexões via TCP/IP (em vez de apenas através de soquetes do domínio Unix), deve ser especificada a opção -i. A sintaxe do interpretador de comandos pode se tornar entediante rapidamente. Por isso é fornecido o script pg_ctl para simplificar algumas tarefas. Por exemplo pg_ctl start -l logfile
inicializa o servidor em segundo plano, e envia a saída para o arquivo de log especificado. A opção -D possui o mesmo significado que no postmaster. O pg_ctl também pode parar o servidor. Normalmente, é desejado inicializar o servidor de banco de dados quando o computador é ligado. Os scripts de auto-inicialização são específicos do sistema operacional. Existem alguns distribuídos com o PostgreSQL no diretório contrib/start-scripts. Pode ser necessário privilégios de root. Sistemas diferentes possuem convenções diferentes para inicializar os processos durante a inicialização do sistema operacional. Muitos sistemas possuem o arquivo /etc/rc.local ou /etc/rc.d/rc.local. Outros utilizam diretórios rc.d. Seja da maneira que for, o servidor deve executar sob a conta de usuário do PostgreSQL, e não sob root ou qualquer outro usuário. Portanto, os comandos provavelmente devem ser formados utilizando su -c '...' postgres. Por exemplo: su -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog' postgres
265
Abaixo seguem algumas sugestões mais específicas dos sistemas operacionais (Sempre substitua pelo diretório de instalação e nome de usuário apropriados). •
No FreeBSD veja o arquivo contrib/start-scripts/freebsd na distribuição do código fonte do PostgreSQL.
•
No OpenBSD adicione as seguintes linhas ao arquivo /etc/rc.local: if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postmaster ]; then su - -c '/usr/local/pgsql/bin/pg_ctl start -l /var/postgresql/log -s' postgres echo -n ' postgresql' fi
•
Nos sistemas Linux adicione /usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data
ao arquivo /etc/rc.d/rc.local ou veja o arquivo contrib/start-scripts/linux na distribuição do código fonte do PostgreSQL. •
No NetBSD use o script de inicialização do FreeBSD ou do Linux, conforme preferir.
•
No Solaris crie um arquivo chamado /etc/init.d/postgresql contendo a seguinte linha: su - postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data"
Depois crie um vínculo simbólico para este arquivo em /etc/rc3.d como S99postgresql. Enquanto o postmaster está executando, seu identificador de processo (PID) fica armazenado no arquivo postmaster.pid no diretório de dados. É utilizado para impedir que vários processos postmaster executem com o mesmo diretório de dados e, também, pode ser utilizado para parar o processo postmaster.
16.3.1. Falhas na inicialização do servidor Existem vários motivos corriqueiros pelos quais a inicialização do servidor pode não ser bem-sucedida. Verifique o arquivo de log do servidor, ou faça a inicialização manualmente (sem redirecionar a saída padrão ou o erro padrão), e veja as mensagens de erro mostradas. Abaixo estão explicadas mais detalhadamente as mensagens de erro mais comuns. LOG: HINT: FATAL:
could not bind IPv4 socket: Address already in use Is another postmaster already running on port 5432? If not, wait a few seconds and retry. could not create TCP/IP listen socket
Normalmente significa o que sugere: tentou-se inicializar um postmaster na mesma porta que outro já estava usando. Entretanto, se o núcleo da mensagem de erro não for Endereço atualmente em uso (Address already in use) ou alguma variante desta, pode estar ocorrendo um problema diferente. Por exemplo, tentar inicializar o postmaster em um número de porta reservado pode levar a algo como: $ postmaster -i -p 666 LOG: could not bind IPv4 socket: Permission denied HINT: Is another postmaster already running on port 666? If not, wait a few seconds and retry. FATAL: could not create TCP/IP listen socket
Uma mensagem como FATAL: DETAIL:
could not create shared memory segment: Invalid argument Failed system call was shmget(key=5440001, size=4011376640, 03600).
provavelmente significa que o limite para o tamanho da memória compartilhada do núcleo (kernel) é menor do que a área de trabalho que o PostgreSQL está tentando criar (4011376640 bytes neste exemplo). Pode significar, também, que não há suporte de memória compartilhada estilo System-V configurado no núcleo. Como recurso temporário pode-se tentar inicializar o servidor com um número de buffers menor do que o número normal (sinalizador -B). Por fim será desejado reconfigurar o núcleo para aumentar o tamanho de
266
memória compartilhada permitido. Esta mensagem também pode ser vista quando se tenta inicializar vários servidores na mesma máquina, se o espaço total requisitado exceder o limite do núcleo. Um erro como FATAL: DETAIL:
could not create semaphores: No space left on device Failed system call was semget(5440126, 17, 03600).
não significa que o espaço em disco está esgotado. Significa que o limite do núcleo para o número de semáforos System V é menor do que o número que o PostgreSQL deseja criar. Como acima, este problema pode ser superado inicializando o servidor com um número reduzido de conexões permitidas (sinalizador -N), por fim será desejado aumentar o limite do núcleo. Se for recebida a mensagem de erro “chamada de sistema ilegal”, é provável que a memória compartilhada ou os semáforos não sejam suportados pelo núcleo. Neste caso, a única opção é reconfigurar o núcleo para habilitar estas funcionalidades. Detalhes sobre a configuração das facilidades de IPC do System V são fornecidas na Seção 16.5.1.
16.3.2. Problemas na conexão do cliente Embora as condições de erro possíveis no lado cliente sejam bastante variadas e dependentes da aplicação, algumas delas podem estar diretamente relacionadas com a maneira como o servidor foi inicializado. Outras condições que não sejam as mostradas abaixo devem estar documentadas na respectiva aplicação cliente. psql: could not connect to server: Connection refused Is the server running on host "server.joe.com" and accepting TCP/IP connections on port 5432?
Esta é uma falha genérica dizendo “Eu não pude encontrar o servidor para me comunicar”. Parece com a mostrada acima quando se tenta uma comunicação TCP/IP. Um engano comum é esquecer de configurar o servidor para aceitar conexões TCP/IP. Como alternativa, pode ser recebida esta mensagem ao se tentar uma comunicação através do soquete do domínio Unix com o servidor local: psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
A última linha é útil para verificar se o cliente está tentando se conectar ao local correto. Se exitir realmente um servidor executando neste local, o núcleo da mensagem de erro será normalmente Conexão recusada (Connection refused) ou Arquivo ou diretório inexistente (No such file or directory), como mostrado (É importante perceber que Conexão recusada neste contexto não significa que o servidor recebeu o pedido de conexão e o rejeitou. Este caso produz uma mensagem diferente, conforme mostrado na Seção 19.3). Outras mensagens de erro, tal como Tempo de conexão esgotado, podem indicar problemas mais básicos, como falta de conectividade da rede.
16.4. Configuração em tempo de execução Existem muitos parâmetros de configuração que afetam o comportamento do sistema de banco de dados. Nesta seção é descrito como são definidos os parâmetros de configuração; as subseções abaixo discutem cada parâmetro em detalhe. Os nomes dos parâmetros não são sensíveis a maiúsculas/minúsculas. Todo parâmetro recebe um valor de um destes quatro tipos: booleano, inteiro, ponto flutuante ou cadeia de caracteres. Os valores booleanos são ON, OFF, TRUE, FALSE, YES, NO, 1 ou 0 (não sensível a maiúsculas/minúsculas), ou qualquer prefixo não ambíguo destes. Uma forma de definir estes parâmetros é editar o arquivo postgresql.conf no diretório de dados (Um arquivo padrão é instalado neste diretório). Um exemplo de como este arquivo se parece é: # Isto é um comentário
267
log_connections = yes syslog = 2 search_path = '$user, public'
É especificado um parâmetro por linha. O sinal de igual entre o nome e o valor é opcional. Espaços em branco são insignificantes e linhas em branco são ignoradas. O caractere jogo-da-velha (#) insere comentários em qualquer lugar. O valor dos parâmetros que não são identificadores simples ou números deve estar entre apóstrofos ('). O arquivo de configuração é lido novamente sempre que o processo postmaster recebe do sistema o sinal SIGHUP (cuja forma mais fácil de enviar é através de pg_ctl reload). O postmaster também propaga este sinal para todos os processos servidor em execução, para que as sessões existentes também busquem o novo valor. Como alternativa, pode ser enviado o sinal a um único processo servidor diretamente. A segunda forma de definir estes parâmetros de configuração é fornecê-los como opção de linha de comando para o postmaster, como em: postmaster -c log_connections=yes -c syslog=2
As opções de linha de comando têm precedência sobre qualquer definição conflitante no arquivo postgresql.conf.
Ocasionalmente, também é útil fornecer uma opção de linha de comando para apenas uma determinada sessão. A variável de ambiente PGOPTIONS pode ser utilizada para esta finalidade no lado cliente: env PGOPTIONS='-c geqo=off' psql
(Funciona para toda aplicação cliente baseada na libpq, e não apenas para o psql). Observe que pode não funcionar para parâmetros estabelecidos quando o servidor é inicializado, tal como o número da porta. Além disso, é possível atribuir um conjunto de definições de opção para um usuário ou para um banco de dados. Sempre que uma sessão é iniciada, as definições padrão para o usuário ou para o banco de dados são carregadas. Os comandos ALTER DATABASE e ALTER USER, respectivamente, são utilizados para configurar estas definições. Definições para o banco de dados prevalecem sobre qualquer definição recebida pela linha de comando do postmaster ou no arquivo de configuração e, por sua vez, as definições para o usuário prevalecem sobre esta; as opções para a sessão prevalecem sobre as duas. Alguns parâmetros podem ser mudados nas sessões SQL individuais utilizando o comando SET como, por exemplo: SET ENABLE_SEQSCAN TO OFF;
Se SET for permitido, este prevalece sobre todas as outras fontes de valores para parâmetros. Os superusuários podem executar SET sobre mais valores do que os usuários comuns. O comando SHOW permite a inspeção dos valores correntes de todos os parâmetros. A tabela virtual pg_settings (descrita na Seção 43.34) também permite mostrar e atualizar parâmetros da sessão em tempo de execução. É equivalente ao SHOW e ao SET mas seu uso pode ser mais conveniente, porque pode ser feita a junção com outras tabelas, ou feita a seleção utilizando qualquer condição desejada.
16.4.1. Conexões e autenticação 16.4.1.1. Definições de conexão tcpip_socket (boolean)
Se for verdade, então o servidor aceita conexões TCP/IP. Senão, somente conexões oriundas do soquete do domínio Unix local são aceitas. Por padrão está desabilitada. Esta opção somente pode ser definida durante a inicialização do servidor. max_connections (integer)
Determina o número máximo de conexões simultâneas no servidor de banco de dados. Normalmente o valor padrão é 100, mas pode ser menos se a configuração do sistema operacional não suportar este valor
268
(conforme determinado durante o initdb). Este parâmetro somente pode ser definido durante a inicialização do servidor. Aumentar este parâmetro pode fazer com que o PostgreSQL requeira mais memória compartilhada ou semáforos System V do que a configuração padrão do sistema operacional permite. Veja a Seção 16.5.1 para obter informações sobre como ajustar estes parâmetros, caso seja necessário. superuser_reserved_connections (integer)
Determina o número de “encaixes de conexão” (connection slots) reservados para os superusuários do PostgreSQL se conectarem. Até max_connections conexões podem estar ativas simultaneamente. Sempre que o número de conexões simultâneas ativas for igual ou maior a max_connections menos superuser_reserved_connections somente serão aceitas novas conexões feitas pelos superusuários. O valor padrão é 2. O valor deve ser menor que o valor de max_connections. Este parâmetro somente pode ser definido durante a inicialização do servidor. port (integer)
A porta TCP onde o servidor está ouvindo; 5432 por padrão. Esta opção somente pode ser definida durante a inicialização do servidor. unix_socket_directory (string)
Especifica o diretório do soquete do domínio Unix no qual o servidor está ouvindo as conexões das aplicações cliente. Normalmente o valor padrão é /tmp, mas pode ser mudado em tempo de construção. unix_socket_group (string)
Define o dono do grupo do soquete do domínio Unix (O usuário dono do soquete é sempre o usuário que inicializa o servidor). Combinado com a opção unix_socket_permissions pode ser utilizada como um mecanismo de controle de acesso adicional para este tipo de soquete. Por padrão é uma cadeia de caracteres vazia, que utiliza o grupo padrão para o usuário corrente. Esta opção somente pode ser definida durante a inicialização do servidor. unix_socket_permissions (integer)
Define as permissões de acesso do soquete do domínio Unix. Os soquetes do domínio Unix utilizam o conjunto usual de permissões do sistema de arquivos do Unix. Para o valor desta opção é esperada uma especificação de modo numérica, na forma aceita pelas chamadas de sistema chmod e umask (Para utilizar o formato octal, como é de costume, o número deve começar por 0 (zero)). As permissões padrão são 0777, significando que qualquer um pode se conectar. Alternativas razoáveis são 0770 (somente o usuário e o grupo, veja também em unix_socket_group) e 0700 (somente o usuário); observe que, na verdade, para soquetes do domínio Unix somente a permissão de escrita tem importância, não fazendo sentido definir ou revogar permissões de leitura e de execução. Este mecanismo de controle de acesso é independente do descrito no Capítulo 19. Esta opção somente pode ser definida durante a inicialização do servidor. virtual_host (string)
Especifica o nome de hospedeiro ou endereço de IP no qual o servidor está ouvindo as conexões das aplicações cliente. O padrão é ouvir em todos os endereços configurados (incluindo localhost). rendezvous_name (string)
Especifica o nome de difusão Rendezvous. Por padrão é utilizado o nome do computador, especificado como ''. 16.4.1.2. Autenticação de segurança authentication_timeout (integer)
Tempo máximo, em segundos, para completar a autenticação do cliente. Se a tentativa de tornar-se cliente não completar o protocolo de autenticação nesta quantidade de tempo, o servidor derruba a conexão. Isto previne que clientes pendurados fiquem ocupando a conexão indefinidamente. Esta opção somente pode ser definida durante a inicialização do servidor ou no arquivo postgresql.conf. O valor padrão é 60.
269
ssl (boolean)
Habilita conexões SSL. Por favor leia a Seção 16.7 antes de usar. O valor padrão é desabilitado. password_encryption (boolean)
Quando uma senha é especificada em CREATE USER ou ALTER USER sem que seja escrito ENCRYPTED ou UNENCRYPTED, esta opção determina se a senha deve ser criptografada. O valor padrão é habilitado (criptografar a senha). krb_server_keyfile (string)
Define a localização do arquivo de chaves do servidor Kerberos. Veja a Seção 19.2.3 para obter detalhes. db_user_namespace (boolean)
Permite nomes de usuário por banco de dados. Está desabilitado por padrão. Se estiver habilitado devem ser criados usuários como nome_do_usuário@nome_bd. Quando o nome_do_usuário é passado por um cliente se conectando, @ e o nome do banco de dados são adicionados ao nome do usuário, e este nome de usuário específico do banco de dados é procurado pelo servidor. Observe que para se criar usuários com nomes contendo @ no ambiente SQL, é necessário colocar o nome do usuário entre aspas. Quando esta opção está habilitada ainda podem ser criados nomes comuns de usuários globais. Simplesmente deve ser adicionado @ ao especificar o nome do usuário no cliente. O @ será tirado fora antes do nome do usuário ser procurado pelo servidor. Nota: Esta funcionalidade foi criada como uma medida temporária até que uma solução completa seja encontrada, quando então esta opção será removida.
16.4.2. Consumo de recursos 16.4.2.1. Memória shared_buffers (integer)
Define o número de buffers de memória compartilhados utilizado pelo servidor de banco de dados. Normalmente o valor padrão é 1000, mas pode ser menos se as definições no núcleo não suportarem este valor (conforme determinado durante initdb). Cada buffer possui 8192 bytes, a menos que um valor diferente para BLCKSZ seja escolhido ao construir o servidor. O valor definido deve ser ao menos 16, assim como ao menos duas vezes o valor de max_connections; entretanto, geralmente é necessário definir bem mais do que o mínimo para obter um bom desempenho. Valores de alguns poucos milhares são recomendados para instalações em produção. Esta opção somente pode ser definida durante a inicialização do servidor. Aumentar este parâmetro pode fazer com que o PostgreSQL requeira mais memória compartilhada ou semáforos System V do que a configuração padrão do sistema operacional permite. Veja a Seção 16.5.1 para obter informações sobre como ajustar estes parâmetros, caso seja necessário. sort_mem (integer)
Especifica a quantidade de memória a ser utilizada pelas operações internas de classificação e tabelas de hash antes de trocar para arquivos temporários em disco. O valor é especificado em kilobytes, e o padrão é 1024 kilobytes (1 MB). Observe que em uma consulta complexa, várias classificações ou operações de hash podem ser executadas em paralelo; cada uma poderá utilizar tanta memória quanto for especificada por este valor antes de colocar os dados em arquivos temporários. Além disso, várias sessões em execução podem estar fazendo operações de classificação ao mesmo tempo. Portanto, a memória total utilizada pode ser várias vezes o valor de sort_mem. As operações de classificação são utilizadas por ORDER BY, junções de mesclagem e CREATE INDEX. As tabelas de hash são utilizadas em junções de hash, agregações baseadas em hash e no processamento de subconsultas IN baseado em hash. Como o comando CREATE INDEX é utilizado quando um banco de dados é restaurado, aumentar sort_mem antes de realizar uma operação de restauração grande pode melhorar o desempenho.
270
vacuum_mem (integer)
Especifica a quantidade máxima de memória a ser utilizada pelo comando VACUUM para manter informações sobre as linhas a serem reavidas. O valor é especificado em kilobytes, e o padrão é 8192 kB. Valores maiores podem melhorar a velocidade da limpeza de tabelas grandes contendo muitas linhas excluídas. 16.4.2.2. Mapa do espaço livre max_fsm_pages (integer)
Define o número máximo de páginas de disco para as quais o espaço livre será acompanhado no mapa de espaço livre compartilhado. São consumidos seis bytes de memória compartilhada para cada encaixe de página. O valor definido deve ser maior que 16 * max_fsm_relations. O valor padrão é 20000. Esta opção somente pode ser definida durante a inicialização do servidor. max_fsm_relations (integer)
Define o número máximo de relações (tabelas e índices) para as quais o espaço livre será acompanhado no mapa de espaço livre compartilhado. Aproximadamente 50 bytes de memória compartilhada são consumidos por cada encaixe. O valor padrão é 1000. Esta opção somente pode ser definida durante a inicialização do servidor. 16.4.2.3. Utilização de recursos do núcleo max_files_per_process (integer)
Define o número máximo permitido de arquivos abertos simultaneamente por cada subprocesso servidor. O valor padrão é 1000. O limite realmente utilizado pelo código é o menor valor entre esta definição e o resultado de sysconf(_SC_OPEN_MAX). Portanto, nos sistemas onde sysconf retorna um limite razoável não há necessidade de se preocupar com esta definição. Entretanto, em algumas plataformas (notadamente a maioria dos sistemas BSD), sysconf retorna um valor que é muito maior do que o sistema pode realmente suportar quando um grande número de processos tenta abrir ao mesmo tempo esta quantidade de arquivos. Se for vista a mensagem de erro “Muitos arquivos abertos” tente reduzir esta definição. Esta opção somente pode ser definida durante a inicialização do servidor, ou no arquivo de configuração postgresql.conf; se for mudado no arquivo de configuração somente serão afetados os subprocessos do servidor iniciados depois. preload_libraries (string)
Esta variável especifica uma ou mais bibliotecas compartilhadas a serem pré-carregadas durante a inicialização do servidor. Uma função de inicialização sem parâmetros pode, opcionalmente, ser chamada para cada biblioteca. Para especificá-la deve ser adicionado dois-pontos e o nome da função de inicialização após o nome da biblioteca. Por exemplo '$libdir/minha_bib:minha_bib_inic' faz com que minha_bib seja pré-carregada e minha_bib_inic seja executada. Para carregar mais de uma biblioteca, os nomes devem ser separados por vírgula. Se minha_bib ou minha_bib_inic não for encontrada, a inicialização do servidor não será bemsucedida. As bibliotecas de linguagem procedural do PostgreSQL são pré-carregadas desta maneira, usualmente utilizando a sintaxe '$libdir/plXXX:plXXX_init' onde XXX é pgsql, perl, tcl ou python. Fazendo a pré-carga da biblioteca compartilhada (e a inicializando, se for aplicável), o tempo de inicialização da biblioteca é evitado quando a biblioteca é utilizada pela primeira vez. Entretanto, o tempo para inicializar cada novo processo servidor pode aumentar, mesmo se o processo nunca utilizar a biblioteca.
16.4.3. Log de escrita prévia (WAL) Veja também a Seção 25.3 para obter detalhes sobre a sintonia do WAL.
271
16.4.3.1. Definições fsync (boolean)
Se esta opção estiver habilitada, o servidor PostgreSQL utiliza a chamada de sistema fsync() em vários locais para ter certeza que as atualizações estão fisicamente escritas no disco. Isto garante que o agrupamento de bancos de dados vai ser recuperado em um estado coerente após um problema de máquina ou do sistema operacional (Uma queda do próprio servidor de bancos de dados não se relaciona com este parâmetro). Entretanto, a utilização do fsync() produz uma degradação do desempenho: quando a transação é efetivada, o PostgreSQL deve aguardar o sistema operacional descarregar o log de escrita prévia no disco. Quando fsync está desabilitado, o sistema operacional pode desempenhar da melhor maneira a buferização, ordenação e atraso na escrita. Isto pode produzir uma melhora significativa no desempenho. Entretanto, se o sistema tiver problemas, os resultados das poucas últimas transações efetivadas podem ser perdidos em parte ou por inteiro. No pior caso, uma corrupção de dados não recuperável pode ocorrer. Devido aos riscos envolvidos não existe uma definição universalmente aceita para fsync. Alguns administradores sempre desabilitam fsync, enquanto outros só desabilitam para cargas pesadas, onde claramente existe um ponto de recomeço se alguma coisa errada acontecer, enquanto outros administradores sempre deixam fsync habilitado. O padrão é habilitar fsync, para obter o máximo de confiabilidade. Havendo confiança no sistema operacional, na máquina, e nos utilitários que acompanham (ou na bateria de reserva), desabilitar fsync pode ser levado em consideração. Esta opção somente pode ser definida durante a inicialização do servidor ou no arquivo postgresql.conf. wal_sync_method (string)
Método utilizado para forçar a colocação das atualizações do WAL no disco. Os valores possíveis são fsync (chamada à função fsync() a cada efetivação), fdatasync (chamada à função fdatasync() a cada efetivação), open_sync (escreve arquivos WAL com a opção O_SYNC do open()), e open_datasync (escreve arquivos WAL com a opção O_DSYNC do open()). Nem todas estas opções
estão disponíveis em todas as plataformas. Esta opção somente pode ser definida durante a inicialização do servidor ou no arquivo postgresql.conf. wal_buffers (integer)
Número de buffers de página de disco na memória compartilhada para o log do WAL. O valor padrão é 8. Esta opção somente pode ser definida durante a inicialização do servidor. 16.4.3.2. Pontos de controle checkpoint_segments (integer)
Distância máxima entre pontos de controle automático do WAL, em segmentos de arquivo (cada segmento possui normalmente 16 megabytes). O valor padrão é 3. Esta opção somente pode ser definida durante a inicialização do servidor ou no arquivo postgresql.conf. checkpoint_timeout (integer)
Tempo máximo, em segundos, entre pontos de controle automáticos do WAL. O valor padrão é 300 segundos. Esta opção somente pode ser definida durante a inicialização do servidor ou no arquivo postgresql.conf. checkpoint_warning (integer)
Escreve mensagem no log do servidor se pontos de controle causados pelo enchimento dos arquivos de segmento de ponto de controle acontecerem mais freqüentemente do que este número de segundos. O valor padrão é 30 segundos. Zero desabilita a advertência. commit_delay (integer)
Atraso no tempo entre a escrita do registro de efetivação no buffer do WAL e a descarga do buffer no disco, em microssegundos. Um atraso maior que zero permite que várias transações sejam efetivadas com
272
apenas uma chamada de sistema fsync(), se a carga do sistema for alta o suficiente para que transações adicionais fiquem prontas para serem efetivadas dentro do intervalo especificado. Entretanto, este atraso é simplesmente desperdício se nenhuma outra transação ficar pronta para ser efetivada. Portanto, o atraso somente é realizado se pelo menos outras commit_siblings transações estiverem ativas no instante que o processo servidor escrever seu registro de efetivação. O valor padrão é zero (nenhum atraso). commit_siblings (integer)
Número mínimo de transações simultâneas abertas requerido para realizar o atraso commit_delay. Um valor maior torna mais provável que ao menos uma outra transação fique pronta para ser efetivada durante o intervalo de atraso. O valor padrão é 5.
16.4.4. Planejamento de comando 16.4.4.1. Configuração do método de planejamento Nota: Estes parâmetros de configuração fornecem um método rudimentar para influenciar os planos de comando escolhidos pelo otimizador de comandos. Se o plano padrão escolhido pelo otimizador para um determinado comando não for o ideal, uma solução temporária pode ser obtida utilizando um destes parâmetros de configuração para forçar o otimizador a escolher um plano melhor. Outras formas de melhorar a qualidade dos planos escolhidos pelo otimizador incluem a configuração das Constantes de custo do planejador, execução do comando ANALYZE com mais freqüência, e aumento da quantidade de estatísticas coletadas para uma determinada coluna utilizando o comando ALTER TABLE SET STATISTICS. enable_hashagg (boolean)
Habilita ou desabilita a utilização dos planos do tipo agregação por hash pelo planejador de comandos. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. enable_hashjoin (boolean)
Habilita ou desabilita a utilização dos planos do tipo junção por hash pelo planejador de comandos. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. enable_indexscan (boolean)
Habilita ou desabilita a utilização dos planos do tipo varredura de índice pelo planejador de comandos. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. enable_mergejoin (boolean)
Habilita ou desabilita a utilização dos planos do tipo junção por mesclagem pelo planejador de comandos. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. enable_nestloop (boolean)
Habilita ou desabilita a utilização dos planos do tipo laço aninhado pelo planejador de comandos. Não é possível suprimir os laços aninhados completamente, mas tornando esta variável falsa desestimula sua utilização pelo planejador havendo outro método disponível. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. enable_seqscan (boolean)
Habilita ou desabilita a utilização dos planos do tipo varredura seqüencial pelo planejador de comandos. Não é possível suprimir as varreduras seqüenciais completamente, mas tornando esta variável falsa desestimula sua utilização pelo planejador havendo outro método disponível. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. enable_sort (boolean)
Habilita ou desabilita a utilização dos passos de classificação explícita pelo planejador de comandos. Não é possível suprimir as classificações explícitas completamente, mas tornando esta variável falsa desestimula sua utilização pelo planejador havendo outro método disponível. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos.
273
enable_tidscan (boolean)
Habilita ou desabilita a utilização dos planos do tipo varredura TID pelo planejador de comandos. O valor padrão é habilitado. É utilizado para depuração do planejador de comandos. 16.4.4.2. Constantes de custo do planejador Nota: Infelizmente, não existe nenhum método bem definido para determinar os valores ideais para a família de variáveis de “custo” mostradas abaixo. Incentivamos que sejam feitas experiências e compartilhadas as descobertas. effective_cache_size (floating point)
Define o tamanho efetivo assumido pelo planejador acerca do cache de disco (isto é, a porção de cache de disco do núcleo que será utilizada para os arquivos de dados do PostgreSQL). Medido em páginas de disco, normalmente com 8192 bytes cada. O valor padrão é 1000. random_page_cost (floating point)
Define a estimativa do planejador de comandos do custo da busca não seqüencial de uma página de disco. Medido como um múltiplo do custo da busca seqüencial de página. Um valor maior torna mais provável a utilização de uma varredura seqüencial, um valor menor torna mais provável a utilização de uma uma varredura de índice. O valor padrão é 4. cpu_tuple_cost (floating point)
Define a estimativa do planejador de comandos do custo de processamento de cada linha durante o comando. Medido como uma fração do custo da busca de página seqüencial. O valor padrão é 0.01. cpu_index_tuple_cost (floating point)
Define a estimativa do planejador de comandos do custo de processamento de cada linha de índice durante a varredura do índice. Medido como uma fração do custo da busca de página seqüencial. O valor padrão é 0.001. cpu_operator_cost (floating point)
Define a estimativa do planejador de comandos do custo de processamento de cada operador na cláusula WHERE. Medido como uma fração do custo da busca de página seqüencial. O valor padrão é 0.0025. 16.4.4.3. Otimização genética de comandos geqo (boolean)
Habilita ou desabilita a otimização genética de comandos, que é um algoritmo que tenta realizar um planejamento de comandos sem uma busca completa. O valor padrão é habilitado. Veja as várias outras definições geqo_. geqo_threshold (integer)
Utiliza a otimização genética de comandos para planejar comandos com pelo menos esta quantidade de itens envolvidos na cláusula FROM (Observe que uma construção de JOIN externa conta como apenas um item da cláusula FROM). O valor padrão é 11. Para comandos simples geralmente é melhor utilizar o planejamento determinístico completo, mas para comandos com muitas tabelas o planejamento determinístico toma muito tempo. geqo_effort (integer) geqo_generations (integer) geqo_pool_size (integer) geqo_selection_bias (floating point)
Vários parâmetros de sintonia para o algoritmo de otimização genética de comandos: O tamanho da amostra (pool size) é o número de indivíduos na população. Os valores válidos estão entre 128 e 1024. Se for definido igual a 0 (o padrão), é assumido o pool size de 2^(QS+1), onde QS é o número de itens na cláusula FROM do comando. O esforço é utilizado para calcular o padrão para gerações. Os valores válidos estão entre 1 e 80, sendo 40 o padrão. As gerações especificam o número de interações no algoritmo. O número deve ser um inteiro positivo. Se for especificado 0, então Effort *
274
Log2(PoolSize) é utilizado. O tempo de execução do algoritmo é aproximadamente proporcional à soma de pool size e gerações. A tendência da seleção (selection bias) é a pressão seletiva dentro
da população. O valores podem estar entre 1.50 e 2.00; o último é o padrão. 16.4.4.4. Outras opções do planejador default_statistics_target (integer)
Define a quantidade padrão de estatísticas para as colunas das tabelas que não possuem uma quantidade específica definida através do comando ALTER TABLE SET STATISTICS. Valores maiores aumentam o tempo necessário para executar o comando ANALYZE, mas podem melhorar a qualidade das estimativas do planejador. O valor padrão é 10. from_collapse_limit (integer)
O planejador mescla as subconsultas nas consultas superiores se o resultado da lista FROM não tiver mais do que esta quantidade de itens. Valores menores reduzem o tempo de planejamento, mas podem levar a planos de consultas inferiores. O valor padrão é 8. Geralmente é sensato manter este valor abaixo de geqo_threshold. join_collapse_limit (integer)
O planejador aplana construções JOIN internas explícitas em lista de itens da cláusula FROM, sempre que resultar em uma lista com não mais do que esta quantidade de itens. Geralmente é definido com valor igual a from_collapse_limit. Definindo como 1 evita qualquer aplanamento de JOIN interno, permitindo a sintaxe de JOIN explícita ser utilizada para controlar a ordem de junção. Valores intermediários podem ser úteis para tirar vantagem do tempo de planejamento contra a qualidade do plano.
16.4.5. Relatório de erro e registro de mensagens 16.4.5.1. Syslog syslog (integer)
O PostgreSQL permite utilizar o syslog para registrar as mensagens. Se esta opção for definida como 1, as mensagens vão para syslog e para a saída padrão. Definida como 2 a saída é enviada apenas para syslog (Algumas mensagens ainda irão para a saída/erro padrão). O valor padrão é zero, significando que syslog está desligado. Esta opção deve ser definida na inicialização do servidor. syslog_facility (string)
Esta opção determina a “facilidade” 1 a ser utilizada quando o registro via syslog está habilitado. Pode ser escolhido entre LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7; o valor padrão é LOCAL0. Veja também a documentação do syslog do sistema. syslog_ident (string)
Se o registro via syslog estiver habilitado, esta opção determina o nome do programa utilizado para identificar as mensagens do PostgreSQL nas mensagens de registro do syslog. O valor padrão é postgres. 16.4.5.2. Quando registrar client_min_messages (string)
Controla que níveis de mensagens são enviadas para o cliente. Os valores válidos são DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, LOG, NOTICE, WARNING e ERROR. Cada nível inclui todos os níveis seguintes. Quanto mais para o final estiver o nível, menos mensagens são enviadas. O valor padrão é NOTICE. Observe que aqui LOG possui um grau diferente que em log_min_messages. log_min_messages (string)
Controla que níveis de mensagens são escritas no log do servidor. Os valores válidos são DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL e PANIC. Cada nível inclui todos os níveis seguintes. Quanto mais para o final estiver o nível, menos mensagens são enviadas.
275
O valor padrão é NOTICE. Observe que aqui LOG possui um grau diferente que em client_min_messages. Somente os superusuários podem aumentar esta opção. log_error_verbosity (string)
Controla a quantidade de detalhes escrita no log do servidor para cada mensagem que é registrada. Os valores válidos são TERSE (sucinto), DEFAULT e VERBOSE, cada um adicionando mais campos às mensagens registradas. log_min_error_statement (string)
Controla se o comando SQL causador da condição de erro também será registrado no log do servidor. Todas as declarações SQL causadoras de um erro do nível especificado, ou de nível mais alto, são registradas. O valor padrão é PANIC (tornando de fato esta funcionalidade desabilitada para o uso normal). Os valores válidos são DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, FATAL e PANIC. Por exemplo, se for definido como ERROR então todas as declarações SQL causadoras de erro, erros fatais ou pânicos serão registradas. Habilitar esta opção pode ser útil para encontrar a origem de qualquer erro que apareça no log do servidor. Somente os superusuários podem aumentar esta opção. log_min_duration_statement (integer)
Define o tempo de execução mínimo da declaração (em milissegundos) para que a declaração seja registrada. Todas as declarações SQL que executarem no tempo especificado ou superior serão registradas com sua duração. Definir como zero registra todos os comandos e sua duração. Menos um (o padrão) desabilita esta funcionalidade. Por exemplo, se for definido como 250 então todas as declarações SQL que executarem em 250ms ou mais serão registradas. Habilitar esta opção pode ser útil para encontrar comandos não otimizados nas aplicações. Somente os superusuários podem aumentar esta opção ou definir como menos um se esta opção for definida pelo administrador. silent_mode (boolean)
Executa o servidor em silêncio. Se esta opção estiver definida, o servidor irá automaticamente executar em segundo plano e qualquer terminal de controle será desassociado. Portanto, nenhuma mensagem é escrita na saída padrão ou no erro padrão (o mesmo efeito da opção -S do postmaster. A menos que registrar em syslog esteja habilitado, a utilização desta opção é desencorajada uma vez que torna impossível ver as mensagens de erro. Abaixo está a relação dos vários níveis de severidade de mensagem utilizados nestas definições: DEBUG[1-5]
Fornece informações para uso pelos desenvolvedores. INFO
Fornece informações implicitamente requisitadas pelo usuário como, por exemplo, durante VACUUM VERBOSE. NOTICE
Fornece informações que podem ser úteis para os usuários como, por exemplo, truncamento de identificadores longos e a criação de índices como parte das chaves primárias. WARNING
Fornece advertências para o usuário como, por exemplo, COMMIT fora do bloco de transação. ERROR
Informa o erro que fez a transação corrente ser interrompida. LOG
Mostra informações de interesse dos administradores como, por exemplo, atividade de ponto de controle. FATAL
Informa o erro que fez a sessão corrente ser interrompida.
276
PANIC
Informa o erro que fez todas as sessões serem interrompidas. 16.4.5.3. O que registrar debug_print_parse (boolean) debug_print_rewritten (boolean) debug_print_plan (boolean) debug_pretty_print (boolean)
Estas opções habilitam várias saídas de depuração a serem enviadas para o cliente ou para o log do servidor. Para cada comando executado, imprimem a árvore de análise resultante, a saída do reescritor de comando, ou o plano de execução. O debug_pretty_print introduz recuos na exibição para produzir um formato de saída mais legível, mas muito mais longo. O client_min_messages ou log_min_messages deve estar em DEBUG1 ou inferior para enviar a saída para os logs do cliente ou do servidor. Estas opções estão desabilitadas por padrão. log_connections (boolean)
Esta opção gera uma linha para o log do servidor detalhando cada conexão bem-sucedida. Está desabilitada por padrão, embora provavelmente seja muito útil. Esta opção somente pode ser definida na inicialização do servidor ou no arquivo de configuração postgresql.conf. log_duration (boolean)
Faz com que a duração de toda declaração completada seja registrada. Para utilizar esta opção devem ser habilitados log_statement e log_pid para que possa ser ligada a declaração à duração utilizando o ID do processo. O valor padrão é desabilitado. Somente os superusuários podem desabilitar esta opção se estiver habilitada pelo administrador. log_pid (boolean)
Prefixa toda mensagem no arquivo de log do servidor com o ID de processo de cada processo servidor. É util para identificar qual mensagem pertence a qual conexão. O valor padrão é desabilitado. Este parâmetro não afeta as mensagens registradas via syslog, que sempre contêm o ID do processo. log_statement (boolean)
Faz com que a declaração SQL seja registrada. O valor padrão é desabilitado. Somente os superusuários podem desabilitar esta opção se estiver habilitada pelo administrador. log_timestamp (boolean)
Prefixa cada mensagem do log do servidor com um carimbo do tempo. O padrão é desabilitado. log_hostname (boolean)
Por padrão os registros de conexão mostram somente o endereço de IP do hospedeiro se conectando. Se for desejado mostrar o nome do hospedeiro esta opção pode ser habilitada, mas dependendo da configuração de resolução de nome de hospedeiro da máquina pode ser imposta uma penalidade de desempenho não negligenciável. Esta opção somente pode ser definida na inicialização do servidor. log_source_port (boolean)
Mostra o número da porta de saída do hospedeiro se conectando nas mensagens de log de conexão. É possível trilhar o número da porta para descobrir que usuário iniciou a conexão. Além desta não tem muita utilidade e, portanto, está desabilitado por padrão. Esta opção somente pode ser definida na inicialização do servidor.
277
16.4.6. Estatísticas de tempo de execução 16.4.6.1. Monitoramento das estatísticas log_statement_stats (boolean) log_parser_stats (boolean) log_planner_stats (boolean) log_executor_stats (boolean)
Para cada comando, grava estatísticas de desempenho do respectivo módulo no log do servidor. É um instrumento rudimentar para traçar um perfil. Todas estas opções estão desabilitadas por padrão. Somente os superusuários podem desabilitar qualquer uma destas opções caso tenha sido habilitada pelo administrador. 16.4.6.2. Coletor de estatísticas de comando e índice stats_start_collector (boolean)
Controla se o servidor deve inicializar o subprocesso coletor de estatísticas. Está habilitado por padrão, mas pode ser desabilitado quando se sabe que não há interesse em coletar estatísticas. Esta opção somente pode ser definida na inicialização do servidor. stats_command_string (boolean)
Habilita a coleta de estatísticas para o comando executando correntemente em cada sessão, junto com a hora em que o comando começou a executar. Esta opção está desabilitada por padrão. Observe que, mesmo quando está habilitada, esta informação não é visível por todos os usuários, mas somente pelos superusuários e o usuário dono da sessão sendo informada; portanto, não deve representar um risco à segurança. Este dado pode ser acessado através da visão do sistema pg_stat_activity; consulte o Capítulo 23 para obter mais informações. stats_block_level (boolean) stats_row_level (boolean)
Habilitam a coleta de estatísticas no nível de bloco e no nível de linha da atividade do banco de dados, respectivamente. Estas opções estão desabilitadas por padrão. Este dado pode ser acessado através da família de visões do sistema pg_stat e pg_statio; consulte o Capítulo 23 para obter mais informações. stats_reset_on_server_start (boolean)
Estando habilitada, as estatísticas coletadas são zeradas sempre que o servidor é reinicializado. Estando desabilitada, as estatísticas são acumuladas entre as reinicializações do servidor. O valor padrão é habilitado. Esta opção somente pode ser definida na inicialização do servidor.
16.4.7. Padrões de conexão do cliente 16.4.7.1. Comportamento da declaração search_path (string)
Esta variável especifica a ordem na qual os esquemas são pesquisados quando um objeto (tabela, tipo de dado, função, etc.) é referenciado por um nome simples, sem o componente do esquema. Quando existem objetos com nomes idênticos em esquemas diferentes, o que for encontrado primeiro no caminho de procura é utilizado. Um objeto que não está em nenhum dos esquemas do caminho de procura somente pode ser referenciado especificando o esquema que o contém com o nome qualificado (com ponto). O valor de search_path deve ser uma lista de nomes de esquemas separados por vírgula. Se um dos itens da lista for o valor especial $user, então o esquema que tem o nome retornado por SESSION_USER é substituído, caso este esquema exista (Caso contrário, $user é ignorado). O esquema do catálogo do sistema, pg_catalog, é sempre pesquisado, estando mencionado no caminho ou não. Se estiver mencionado no caminho então será pesquisado na ordem especificada. Se pg_catalog não estiver no caminho, então será pesquisado antes de pesquisar em qualquer um dos itens do caminho. Também deve ser observado que o esquema de tabela temporária, pg_temp_nnn, é pesquisado implicitamente antes de qualquer um dos outros.
278
Quando os objetos são criados sem especificar um determinado esquema de destino, são colocados no primeiro esquema listado no caminho de procura. Ocasiona erro quando o caminho de procura está vazio. O valor padrão para este parâmetro é '$user, public' (onde a segunda parte é ignorada quando não há um esquema chamado public). Apóia o uso compartilhado do banco de dados (onde nenhum usuário possui esquema privativo, e todos compartilham o esquema public), esquemas privativos por usuário, e a combinação destes. Outros efeitos podem ser obtidos alterando a definição do caminho de procura padrão, tanto globalmente quanto por usuário. O valor efetivo corrente do caminho de procura pode ser examinado através da função SQL current_schemas(). Não é exatamente o mesmo que examinar o valor de search_path, uma vez que current_schemas() mostra como as requisições que aparecem em search_path foram resolvidas.
Para obter mais informações sobre o tratamento de esquemas, veja a Seção 5.8. check_function_bodies (boolean)
Este parâmetro é normalmente definido como verdade. Quando definido como falso, desabilita a validação da cadeia de caracteres do corpo da função em CREATE FUNCTION. Desabilitar a validação ocasionalmente é útil, pois evita problemas como referências à frente ao restaurar definições de funções a partir de cópia de segurança. default_transaction_isolation (string)
Cada transação SQL possui um nível de isolamento, que pode ser tanto “read committed” quanto “serializable”. Este parâmetro controla o nível de isolamento padrão de cada nova transação. O valor padrão é “read committed”. Consulte o Capítulo 12 e SET TRANSACTION para obter mais informações. default_transaction_read_only (boolean)
Uma transação SQL somente para leitura não pode alterar tabelas que não sejam temporárias. Este parâmetro controla o status de somente para leitura de cada nova transação. O valor padrão é falso (leitura/escrita). Consulte SET TRANSACTION para obter mais informações. statement_timeout (integer)
Aborta qualquer declaração que ultrapassar o número de milissegundos especificado. O valor zero desliga o temporizador, sendo o valor padrão. 16.4.7.2. Localização e formatação datestyle (string)
Define o formato de exibição para os valores de data e hora, assim como as regras para interpretar valores de entrada de data ambíguos. Por motivos históricos esta variável contém dois componentes independentes: a especificação do formato de saída (ISO, Postgres, SQL ou German) e a especificação da ordem do campo data (DMY, MDY, ou YMD). Podem ser definidos separadamente ou juntos. As palavras chave Euro e European são sinônimos para DMY; as palavras chave US, NonEuro, e NonEuropean são sinônimos para MDY. Veja a Seção 8.5 para obter mais informações. O valor padrão é ISO, MDY. timezone (string)
Define a zona horária para exibir e interpretar os carimbos de tempo. O padrão é utilizar o que estiver especificado pelo ambiente do sistema para zona horária. Veja a Seção 8.5 para obter mais informações. australian_timezones (boolean)
Se estiver definido como verdade, ACST, CST, EST e SAT são interpretados como zonas horárias da Austrália, em vez de zonas horárias das Américas Norte/Sul e Sábado. O valor padrão é falso. extra_float_digits (integer)
Este parâmetro ajusta o número de dígitos exibidos para valores de ponto flutuante, incluindo float4, float8 e tipos de dado geométricos. O valor do parâmetro é adicionado ao número de dígitos padrão (FLT_DIG ou DBL_DIG conforme apropriado). O valor pode ser definido tão alto quanto 2, para incluir
279
dígitos parcialmente significativos; é especialmente útil para cópias de segurança de dados de ponto flutuante que precisam ser restaurados com exatidão. Também pode ser definido com valor negativo para suprimir dígitos não desejados. client_encoding (string)
Define a codificação do lado cliente (conjunto de caracteres). O padrão é utilizar a codificação do banco de dados. lc_messages (string)
Define a linguagem na qual as mensagens são mostradas. Os valores aceitos são dependentes do sistema; veja a Seção 20.1 para obter mais informações. Se esta variável estiver definida como uma cadeia de caracteres vazia (que é o padrão), então o valor é herdado do ambiente de execução do servidor de uma maneira dependente do sistema. Em alguns sistemas esta categoria de localização não existe; definir esta variável funciona, mas não produz nenhum efeito. Existe, também, a chance de não haver mensagens traduzidas para a língua desejada; neste caso, vão continuar sendo vistas mensagens em Inglês. lc_monetary (string)
Define a localização a ser utilizada para formatar quantias monetárias como, por exemplo, com a família de funções to_char. Os valores aceitos são dependentes do sistema; veja a Seção 20.1 para obter mais informações. Se esta variável estiver definida como uma cadeia de caracteres vazia (que é o padrão), então o valor é herdado do ambiente de execução do servidor de uma maneira dependente do sistema. lc_numeric (string)
Define a localização a ser utilizada para formatar números como, por exemplo, com a família de funções to_char(). Os valores aceitos são dependentes do sistema; veja a Seção 20.1 para obter mais
informações. Se esta variável estiver definida como uma cadeia de caracteres vazia (que é o padrão), então o valor é herdado do ambiente de execução do servidor de uma maneira dependente do sistema. lc_time (string)
Define a localização a ser utilizada para formatar valores de data e hora (Atualmente esta definição não faz nada, mas poderá fazer no futuro). Os valores aceitos são dependentes do sistema; veja a Seção 20.1 para obter mais informações. Se esta variável estiver definida como uma cadeia de caracteres vazia (que é o padrão), então o valor é herdado do ambiente de execução do servidor de uma maneira dependente do sistema. 16.4.7.3. Outros padrões explain_pretty_print (boolean)
Determina se EXPLAIN VERBOSE utiliza a formatação com recuos ou sem recuos para mostrar os dumps detalhados das árvores de comando. O valor padrão é habilitado. dynamic_library_path (string)
Se um módulo carregável dinamicamente precisa ser aberto, e o nome especificado não possui o componente de diretório (ou seja, o nome não contém barra), o sistema procura neste caminho pelo arquivo especificado (O nome utilizado é o nome especificado no comando CREATE FUNCTION ou no comando LOAD). O valor de dynamic_library_path deve ser uma lista de nomes absolutos de diretório separados por dois-pontos. Se o nome do diretório começar pelo valor especial $libdir, este valor é substituído pelo diretório de biblioteca do pacote PostgreSQL compilado. Este é o local onde os módulos fornecidos pela distribuição do PostgreSQL são instalados (Utilize pg_config --pkglibdir para ver o nome deste diretório 2 ). Por exemplo: dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
O valor padrão deste parâmetro é '$libdir'. Se o valor for definido como uma cadeia de caracteres vazia, a procura automática no caminho é desabilitada.
280
Este parâmetro pode ser modificado em tempo de execução pelos superusuários, mas a definição feita desta forma somente dura até o final da conexão cliente, portanto este método deve ser reservado para fins de desenvolvimento. A maneira recomendada para definir este parâmetro é no arquivo de configuração postgresql.conf. max_expr_depth (integer)
Define a profundidade máxima de aninhamento de expressão do analisador. O valor padrão igual a 10000 é alto o suficiente para qualquer comando normal, mas pode ser aumentado caso haja necessidade (Mas se for aumentado muito, há o risco de queda do servidor devido ao estouro da pilha).
16.4.8. Gerenciamento de bloqueio deadlock_timeout (integer)
Esta é a quantidade de tempo, em milissegundos, para aguardar um bloqueio antes de verificar a existência de uma condição de impasse (deadlock). A verificação de impasse é relativamente lenta e, portanto, o servidor não faz esta verificação toda vez que aguarda um bloqueio. Nós (otimistas?) assumimos que os bloqueios não são comuns em aplicações em produção e, simplesmente, aguardamos o bloqueio por um tempo antes de começar a verificar o impasse. O aumento deste valor reduz a quantidade de tempo desperdiçada em verificações de impasse desnecessárias, mas atrasa o relato de erros de impasse verdadeiros. O valor padrão é 1000 (ou seja, um segundo), que provavelmente é o menor valor desejado na prática. Em servidores pesadamente carregados pode ser desejado aumentar este tempo. A definição ideal deve ser superior ao tempo típico de uma transação, para melhorar a chance do bloqueio ser liberado antes do temporizador decidir verificar o impasse. max_locks_per_transaction (integer)
A tabela de bloqueio compartilhada é dimensionada pela hipótese de que é necessário, no máximo, bloquear max_locks_per_transaction * max_connections objetos distintos de uma vez. O padrão, 64, tem se mostrado historicamente suficiente, mas pode ser necessário aumentar este valor havendo clientes que acessam muitas tabelas diferentes em uma única transação. Esta opção somente pode ser definida na inicialização do servidor.
16.4.9. Compatibilidade de versão e de plataforma 16.4.9.1. Versões anteriores do PostgreSQL add_missing_from (boolean)
Quando true, as tabelas referenciadas por uma consulta são automaticamente adicionadas à cláusula FROM caso não estejam presentes. O valor padrão é true para compatibilidade com as versões anteriores do PostgreSQL. Entretanto, este comportamento não é SQL-padrão, e muitas pessoas não gostam porque pode esconder enganos. Defina como false para obter o comportamento SQL-padrão de rejeitar referências a tabelas não listadas na cláusula FROM. regex_flavor (string)
A “variedade” de expressão regular pode ser definida como advanced, extended ou basic. O valor padrão é advanced. A definição extended pode ser útil para uma compatibilidade exata com as versões do PostgreSQL anteriores a 7.4. sql_inheritance (boolean)
Controla a semântica da herança, em particular se as subtabelas são incluídas por padrão em vários comandos. Não eram incluídas nas versões anteriores a 7.1. Se for necessário o comportamento antigo esta variável pode ser definida como desabilitada, mas a longo prazo incentiva-se mudar as aplicações para que passem a utilizar a palavra chave ONLY para excluir as subtabelas. Veja a Seção 5.5 para obter mais informações sobre herança.
281
16.4.9.2. Compatibilidade de plataforma e cliente transform_null_equals (boolean)
Quando habilitado, as expressões da forma expr = NULL (ou NULL = expr) são tratadas como expr IS NULL, ou seja, retornam verdade se expr resultar em um valor nulo, e falso caso contrário. O comportamento correto de expr = NULL é sempre retornar nulo (desconhecido). Portanto, o valor padrão desta opção é desabilitado. Entretanto, formulários filtrados no Microsoft Access produzem consultas que parecem utilizar expr = NULL para testar valores nulos e, portanto, se for utilizada esta interface para acessar o banco de dados pode ser desejado habilitar esta opção. Uma vez que as expressões da forma expr = NULL sempre retornam o valor nulo (utilizando a interpretação correta), não são muito úteis e não aparecem freqüentemente em aplicações normais, portanto esta opção produz pouco dano na prática. Porém, os novos usuários ficam freqüentemente confusos sobre a semântica das expressões que envolvem valores nulos, portanto esta opção não está habilitada por padrão. Observe que esta opção afeta apenas o operador literal =, e não os outros operadores de comparação ou outras expressões computacionalmente equivalentes a alguma expressão envolvendo o operador de igual (tal como IN). Portanto, esta opção não é um conserto geral para má programação. Consulte a Seção 9.2 para ver informações relacionadas.
16.4.10. Opções do desenvolvedor As opções a seguir têm por finalidade serem utilizadas no fonte do PostgreSQL e, em alguns casos, ajudar na recuperação de bancos de dados seriamente danificados. Não deve haver razão para usá-las na configuração de um banco de dados de produção. Desta forma, foram excluídas do arquivo postgresql.conf de amostra. Observe que muitas destas opções requerem sinalizadores especiais na compilação do fonte para que funcionem. debug_assertions (boolean)
Habilita várias verificações de asserção. É uma ajuda de depuração. Se estiver acontecendo problemas estranhos ou quedas pode ser desejado habilitá-la, porque podem ser mostrados enganos de programação. Para utilizar esta opção a macro USE_ASSERT_CHECKING deve estar definida quando o PostgreSQL for construído (obtida pela opção --enable-cassert do configure). Observe que DEBUG_ASSERTIONS está habilitado por padrão se o PostgreSQL tiver sido construído com as asserções habilitadas. pre_auth_delay (integer)
Se for diferente de zero, um atraso desta quantidade de segundos ocorre logo após um novo processo servidor ser lançado (forked), antes de realizar o processo de autenticação. Tem por finalidade permitir a oportunidade de ligar o processo servidor a um depurador para acompanhar um mal comportamento na autenticação. trace_notify (boolean)
Gera uma grande quantidade de saída de depuração para os comandos LISTEN e NOTIFY. client_min_messages ou log_min_messages devem ser DEBUG1 ou inferior para enviar esta saída para o log do cliente ou do servidor, respectivamente. trace_locks (boolean) trace_lwlocks (boolean) trace_userlocks (boolean) trace_lock_oidmin (boolean) trace_lock_table (boolean) debug_deadlocks (boolean) log_btree_build_stats (boolean)
Várias outras opções de rastreamento de código e depuração. wal_debug (integer)
Se for diferente de zero habilita a saída de depuração relacionada com o WAL.
282
zero_damaged_pages (boolean)
A detecção de um cabeçalho de página danificado normalmente faz com que o PostgreSQL relate um erro e interrompa a transação corrente. Definir zero_damaged_pages como verdade faz com que em vez disto o sistema relate uma advertência, limpe a página danificada, e continue o processamento. Este comportamento destrói os dados, especificamente todas as linhas na página danificada, mas permite prosseguir após o erro e recuperar as linhas da tabela que podem estar presentes em páginas não danificadas. Portanto, é útil para recuperar dados se a corrupção ocorrer devido à máquina ou erro de software. Geralmente esta opção não deve ser definida como verdade, até que se perca a esperança de recuperar os dados das páginas danificadas da tabela. A definição padrão é desabilitado, e somente pode ser modificado por um superusuário.
16.4.11. Opções curtas Por conveniência também existem chaves de opção de linha de comando de uma única letra disponíveis para alguns parâmetros. Estão descritas na Tabela 16-1. Tabela 16-1. Chave de opção curta Opção curta
Equivalente
-B x
shared_buffers = x
-d x
log_min_messages = DEBUGx
-F
fsync = off
-h x
virtual_host = x
-i
tcpip_socket = on
-k x
unix_socket_directory = x
-l
ssl = on
-N x
max_connections = x
-p x
port = x
-fi, -fh, -fm, fn, -fs, -fta
enable_indexscan=off, enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=off, enable_seqscan=off, enable_tidscan=off
-sa
log_statement_stats = on
-S xa
sort_mem = x
-tpa, -tpl, -tea
log_parser_stats=on, log_planner_stats=on, log_executor_stats=on
Notas: a. Por motivos históricos estas opções devem ser passadas individualmente ao processo servidor através da opção -o do postmaster como, por exemplo, $ postmaster -o '-S 1024 -s'
ou através da variável de ambiente PGOPTIONS no lado cliente, conforme explicado acima.
16.5. Gerenciamento dos recursos do núcleo Uma instalação grande do PostgreSQL pode exaurir rapidamente vários limites de recursos do sistema operacional (Em alguns sistemas, os padrões de distribuição são tão baixos que não é na verdade necessário realmente uma instalação “grande”). Se você esbarrou neste tipo de problema continue lendo.
283
16.5.1. Memória compartilhada e semáforos Memória compartilhada e semáforos são referenciados coletivamente como “System V IPC” (juntamente com as filas de mensagens, que não são relevantes para o PostgreSQL). Quase todo sistema operacional moderno fornece estas funcionalidades, mas nem todos os têm ativos ou com tamanho suficiente por padrão, especialmente os sistemas herdados do BSD (Para os ports para o QNX e para o BeOS, o PostgreSQL fornece sua própria implementação de substituição destas funcionalidades). A falta total destas funcionalidades é geralmente manifestada por um erro de Chamada de sistema ilegal na inicialização do servidor. Neste caso não existe nada a ser feito além de reconfigurar o núcleo. O PostgreSQL não funciona sem os mesmos. Quando o PostgreSQL excede um dos vários limites rígidos do IPC o servidor se recusa a inicializar, devendo deixar uma mensagem de erro instrutiva descrevendo o problema encontrado e o que fazer sobre o mesmo (Veja também a Seção 16.3.1.) Os parâmetros relevantes do núcleo possuem nomes coerentes entre sistemas diferentes; A Tabela 16-2 mostra uma visão geral. Entretanto, os métodos para defini-los variam. Sugestões para algumas plataformas são fornecidas abaixo. Fique advertido que geralmente é necessário reinicializar o computador e, possivelmente, até recompilar o núcleo para mudar estas definições. Tabela 16-2. Parâmetros do IPC do System V Nome
Descrição
Valores razoáveis
SHMMAX
Tamanho máximo de um segmento de memória compartilhada (bytes) a
250 kB + 8.2 kB * shared_buffers + 14.2 kB * max_connections até o infinito
SHMMIN
Tamanho mínimo de um segmento de memória compartilhada (bytes)
1
SHMALL
Quantidade total de memória compartilhada disponível (bytes ou páginas)
se em bytes, o mesmo que SHMMAX; se em páginas,
SHMSEG
Número máximo de segmentos de memória compartilhada por processo
somente 1 segmento é necessário, mas o padrão é muito maior
SHMMNI
Número máximo de segmentos de memória compartilhada para todo o sistema
como SHMSEG mais espaço para outras aplicações
SEMMNI
Número máximo de identificadores de semáforos (ou seja, conjuntos)
pelo menos ceil(max_connections / 16)
SEMMNS
Número máximo de semáforos para todo o sistema
ceil(SHMMAX/PAGE_SIZE)
ceil(max_connections / 16) * 17 mais
espaço para outras aplicações
SEMMSL
Número máximo de semáforos por conjunto
pelo menos 17
SEMMAP
Número de entradas no mapa de semáforos b
veja o texto
SEMVMX
Valor máximo de um semáforo
pelo menos 1000 (O padrão é geralmente 32767; não mude a não ser quando solicitado)
Notas: a. A função shmget() é utilizada para obter acesso a um segmento de memória compartilhada. Esta função falha se o valor do tamanho for menor que SHMMIN ou maior do que SHMMAX. Sun Product Documentation (http://docs.sun.com/db/doc/801-6736/6i13fom0j?a=view) (N. do T.) b. SEMMAP deve ser definido como o produto de SEMMNI e SEMMSL: (SEMMAP = SEMMNI * SEMMSL). Setting our sights on semaphores (http://www.carumba.com/talk/random/swol-10insidesolaris-2.html) (N. do T.)
284
O parâmetro de memória compartilhada mais importante é SHMMAX, o tamanho máximo, em bytes, de um segmento de memória compartilhada. Se for recebida uma mensagem de erro de shmget como Argumento inválido, é possível que este limite tenha sido excedido. O tamanho requerido do segmento de memória compartilhada varia tanto com o número de buffers requisitados (opção -B) quanto com o número de conexões permitidas (opção -N), embora a última seja a mais significativa (É possível, como um recurso temporário, diminuir estas definições para eliminar o problema). Como uma aproximação grosseira, pode ser estimado o tamanho de segmento requerido multiplicando o número de buffers pelo tamanho do bloco (8 kB por padrão), mais uma ampla margem (pelo menos meio megabyte). Toda mensagem de erro que pode ser recebida contém o tamanho da alocação requisitada que falhou. Menos provável de causar problema é o tamanho mínimo para os segmentos de memória compartilhados (SHMMIN), que deve ser no máximo aproximadamente 256 kB para o PostgreSQL (geralmente é apenas 1). O número máximo de segmentos para todo o sistema (SHMMNI) ou por processo (SHMSEG) não devem causar problemas a menos que o sistema os tenha definido como zero. Alguns sistemas também possuem um limite para a quantidade total de memória compartilhada no sistema; veja abaixo as instruções específicas para a plataforma. O PostgreSQL utiliza um semáforo por conexão permitida (opção -N), em conjuntos de 16. Cada um destes conjuntos também contém um 17º semáforo contendo um “número mágico”, para detectar colisões com conjuntos de semáforos utilizados por outras aplicações. O número máximo de semáforos no sistema é definido por SEMMNS que, conseqüentemente, deve ser pelo menos tão alto quanto max_connections mais um adicional para cada 16 conexões permitidas (veja a fórmula na Tabela 16-2). O parâmetro SEMMNI determina o limite do número de conjuntos de semáforos que podem existir no sistema de uma vez. Portanto, este parâmetro deve ser pelo menos igual a ceil(max_connections / 16). Diminuir o número de conexões permitidas é um recurso temporário para evitar falhas, geralmente informadas pela mensagem da função semget Nenhum espaço disponível na unidade, que confunde. Em alguns casos também pode ser necessário aumentar SEMMAP para que fique pelo menos proporcional a SEMMNS. Este parâmetro determina o número máximo de entradas no mapa de semáforos, no qual cada bloco contíguo de semáforos disponível precisa uma entrada. Quando um conjunto de semáforos é liberado este é adicionado a uma entrada existente que seja adjacente ao bloco liberado ou é registrado sob uma nova entrada no mapa. Se o mapa estiver cheio, os semáforos liberados serão perdidos (até a reinicialização do servidor). A fragmentação do espaço de semáforos pode, em algum tempo, levar a menos semáforos disponíveis do que deveriam haver. O parâmetro SEMMSL, que determina quantos semáforos podem existir em um conjunto, deve ser pelo menos igual a 17 para o PostgreSQL. Várias outras definições relacionadas com “desfazer semáforo”, tais como SEMMNU e SEMUME, não têm relação com o PostgreSQL. BSD/OS Memória compartilhada. Por padrão, somente 4 MB de memória compartilhada é suportada. Tenha em mente que a memória compartilhada não é paginável; fica bloqueada na RAM. Para aumentar a quantidade de memória compartilhada suportada pelo sistema, devem ser adicionadas ao arquivo de configuração do núcleo as linhas abaixo. Um valor de SHMALL igual a 1024 representa 4 MB de memória compartilhada. Esta linhas aumentam a memória compartilhada máxima para 32 MB: options "SHMALL=8192" options "SHMMAX=\(SHMALL*PAGE_SIZE\)"
Para
os
usuários
da
versão
4.3
ou
posterior,
provavelmente
será
necessário
aumentar
KERNEL_VIRTUAL_MB para um valor acima do padrão de 248. Uma vez que as alterações tenham sido
efetuadas, o núcleo deve ser recompilado e o sistema reinicializado. Para os usuários da versão 4.0 ou anterior, deve ser utilizado bpatch para descobrir o valor de sysptsize do núcleo corrente. É computado dinamicamente durante a inicialização do sistema operacional. $ bpatch -r sysptsize 0x9 = 9
285
A seguir, deve ser adicionado SYSPTSIZE como um valor fixo no arquivo de configuração do núcleo. Aumente o valor encontrado utilizando bpatch; adicione 1 para cada 4 MB adicionais de memória compartilhada desejada. options "SYSPTSIZE=16" sysptsize não pode ser mudado por sysctl.
Semáforos. Pode ser necessário aumentar o número de semáforos. Por padrão, o PostgreSQL aloca 34 semáforos, que é mais da metade do total padrão do sistema de 60. Defina os valores desejados no arquivo de configuração do núcleo como, por exemplo: options "SEMMNI=40" options "SEMMNS=240"
FreeBSD NetBSD OpenBSD As opções SYSVSHM e SYSVSEM precisam estar habilitadas quando o núcleo é compilado (Estão por padrão). O tamanho máximo da memória compartilhada é determinado pela opção SHMMAXPGS (em páginas). A seguir está mostrado um exemplo de como definir os vários parâmetros: options options options
SYSVSHM SHMMAXPGS=4096 SHMSEG=256
options options options options options
SYSVSEM SEMMNI=256 SEMMNS=512 SEMMNU=256 SEMMAP=256
(No NetBSD e no OpenBSD a palavra chave é na verdade option no singular). Também pode ser desejado configurar o núcleo para bloquear a memória compartilhada na RAM, evitando que seja paginada para a área de troca (swap). Utilize a definição kern.ipc.shm_use_phys do sysctl. . HP-UX A definição padrão tende a ser suficiente para as instalações normais. No HP-UX 10, o padrão de fábrica para SEMMNS é 128, que pode ser muito baixo para servidores de bancos de dados grandes. Os parâmetros do IPC podem ser definidos no System Administration Manager (SAM) sob Kernel Configuration→Configurable Parameters. Clique Create A New Kernel ao terminar. Linux O limite padrão de memória compartilhada (tanto SHMMAX quanto SHMALL) é de 32 MB nos núcleos 2.2, mas pode ser modificado no arquivo de sistema proc (sem reinicializar o Linux). Por exemplo, para permitir 128 MB: $ echo 134217728 >/proc/sys/kernel/shmall $ echo 134217728 >/proc/sys/kernel/shmmax
Estes comandos podem ser colocados em um script executado durante a inicialização. Como alternativa, pode ser utilizado sysctl, se estiver disponível, para controlar estes parâmetros. Procure pelo arquivo chamado /etc/sysctl.conf e adicione linhas como as mostradas abaixo: kernel.shmall = 134217728 kernel.shmmax = 134217728
Este arquivo geralmente é processado durante a inicialização, mas sysctl também pode ser chamada explicitamente depois.
286
Os outros parâmetros possuem tamanho adequado para qualquer aplicação. Se desejar ver por si próprio olhe em /usr/src/linux/include/asm-xxx/shmpara m.h e /usr/src/linux/include/linux/sem.h. MacOS X No OS X 10.2 e posterior, deve ser editado o arquivo /System/Library/StartupItems/SystemTuning/SystemTuning e modificados os valores nos
seguintes comandos: sysctl sysctl sysctl sysctl sysctl
-w -w -w -w -w
kern.sysv.shmmax kern.sysv.shmmin kern.sysv.shmmni kern.sysv.shmseg kern.sysv.shmall
No OS X 10.3, estes comandos foram movidos para /etc/rc devendo ser editados neste local. SCO OpenServer Na configuração padrão, somente 512 kB de memória compartilhada por segmento é permitida, suficiente para cerca de -B 24 -N 12. Para aumentar esta definição, primeiro torne o diretório /etc/conf/cf.d o diretório corrente. Para exibir o valor corrente de SHMMAX, execute ./configure -y SHMMAX
Para definir um novo valor para SHMMAX, execute ./configure SHMMAX=valor
onde valor é o novo valor que se deseja utilizar (em bytes). Após definir SHMMAX, o núcleo deve ser reconstruído: ./link_unix
e o sistema operacional reinicializado. Solaris Pelo menos na versão 2.6, o tamanho máximo padrão dos segmentos de memória compartilhada é muito baixo para o PostgreSQL. As definições relevantes podem ser mudadas em /etc/system como, por exemplo: set set set set
shmsys:shminfo_shmmax=0x2000000 shmsys:shminfo_shmmin=1 shmsys:shminfo_shmmni=256 shmsys:shminfo_shmseg=256
set set set set
semsys:seminfo_semmap=256 semsys:seminfo_semmni=512 semsys:seminfo_semmns=512 semsys:seminfo_semmsl=32
O sistema operacional deve ser reinicializado para as modificações serem efetivadas. Veja também http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html para obter informações sobre memória compartilhada sob o Solaris. UnixWare No UnixWare 7, o tamanho máximo para os segmentos de memória compartilhada é de 512 kB na configuração padrão. É suficiente para cerca de -B 24 -N 12. Para exibir o valor corrente de SHMMAX, execute /etc/conf/bin/idtune -g SHMMAX
que mostra os valores corrente, padrão, mínimo e máximo. Para definir um novo valor para SHMMAX, execute /etc/conf/bin/idtune SHMMAX valor
287
onde valor é o novo valor que se deseja utilizar (em bytes). Após definir SHMMAX, o núcleo deve ser reconstruído: /etc/conf/bin/idbuild -B
e o sistema operacional reinicializado.
16.5.2. Limites de recursos Os sistemas operacionais da família Unix obrigam respeitar vários tipos de limites de recursos que podem interferir com a operação do servidor PostgreSQL. Particularmente mais importantes são os limites do número de processos por usuário, o número de arquivos abertos por processo, e a quantidade de memória disponível para cada processo. Cada um destes possui um limite “rígido” e um “flexível”. O limite flexível é o que conta na verdade, podendo ser modificado pelo usuário até o limite rígido. O limite rígido somente pode ser mudado pelo usuário root. A chamada de sistema setrlimit é responsável pela definição destes parâmetros. O comando interno do interpretador de comandos ulimit (interpretadores de comando Bourne) ou limit (csh) são utilizados para controlar os limites de recursos a partir da linha de comandos. Nos sistemas derivados do BSD o arquivo /etc/login.conf controla os limites dos vários recursos definidos durante a autenticação. Veja a documentação do sistema operacional para obter detalhes. Os parâmetros relevantes são maxproc, openfiles e datasize. Por exemplo: default:\ ... :datasize-cur=256M:\ :maxproc-cur=256:\ :openfiles-cur=256:\ ...
(-cur é o limite flexível. Anexe -max para definir o limite rígido). Os núcleos também podem ter limites para todo o sistema em alguns recursos. •
No Linux /proc/sys/fs/file-max determina o número máximo de arquivos abertos que o núcleo pode suportar. Pode ser mudado escrevendo um número diferente no arquivo, ou adicionando uma atribuição em /etc/sysctl.conf. O limite máximo de arquivos por processo é fixado quando o núcleo é compilado; veja /usr/src/linux/Documentation/proc.txt para obter mais informações.
O servidor PostgreSQL utiliza um processo por conexão e, portanto, devem ser especificados pelo menos tantos processos quantas forem as conexões permitidas, em adição ao que for necessário para o restante do sistema. Normalmente não é um problema, mas se forem executados vários servidores em uma máquina pode ficar apertado. O limite original padrão para o número de arquivos abertos é geralmente definido como um valor “socialmente amigável”, para permitir a coexistência de muitos usuários em uma mesma máquina sem utilizar uma fração não apropriada dos recursos do sistema. Se forem executados muitos servidores em uma máquina provavelmente é o que se deseja, mas para servidores dedicados pode ser desejado elevar este limite. No outro lado da moeda, alguns sistemas podem permitir processos individuais abrirem um grande número de arquivos; se mais que uns poucos processos o fizerem, então o limite para todo o sistema pode ser facilmente excedido. Se isto estiver acontecendo, e não for desejado alterar o limite para todo o sistema, pode ser definido o parâmetro de configuração max_files_per_process do PostgreSQL para limitar o consumo de arquivos abertos.
16.5.3. Sobre-utilização de memória no Linux No Linux 2.4 e posteriores, o comportamento de memória virtual padrão não é o melhor para o PostgreSQL. Devido à maneira como o núcleo implementa a sobre-utilização (overcommit) de memória, o núcleo pode terminar o servidor PostgreSQL (o processo postmaster) se a demanda de memória de um outro processo fizer com que o sistema esgote a memória virtual. Se isto acontecer, será vista uma mensagem do núcleo parecida com esta (procure na documentação e configuração do sistema onde pode ser visto este tipo de mensagem):
288
Out of Memory: Killed process 12345 (postmaster).
Esta mensagem indica que o processo postmaster foi terminado devido ao aperto de memória. Embora as conexões existentes ao banco de dados continuarão funcionando, não será aceita nenhuma nova conexão. Para recuperar, será necessário reinicializar o PostgreSQL. Uma forma de evitar este problema é executar o PostgreSQL em uma máquina onde se tenha certeza que outros processos não vão deixar a máquina sem memória. No Linux 2.6 e posteriores, uma solução melhor é modificar o comportamento do núcleo para que não haja “sobre-utilização” de memória. Isto é feito selecionando um modo estrito de sobre-utilização através do sysctl: sysctl -w vm.overcommit_memory=2
ou colocando uma entrada equivalente em /etc/sysctl.conf. Também pode ser desejado modificar a definição relacionada vm.overcommit_ratio. Para obter detalhes veja o arquivo de documentação do núcleo Documentation/vm/overcommit-accounting. Alguns distribuidores do núcleo 2.4 do Linux dizem possuir uma versão inicial do parâmetro overcommit do sysctl da versão 2.6. Entretanto, definir vm.overcommit_memory como 2 em um núcleo que não possui o código relevante torna as coisas piores, e não melhores. Recomenda-se a inspeção do código fonte do núcleo utilizado (veja a função vm_enough_memory no arquivo mm/mmap.c), para verificar o que é suportado na cópia utilizada antes de tentar utilizar numa instalação 2.4. A presença do arquivo de documentação overcommit-accounting não deve ser tomada como um indício que a funcionalidade está presente. Em caso de dúvida, consulte um especialista no núcleo ou o distribuidor do núcleo utilizado.
16.6. Parando o servidor Existem várias formas de parar o servidor de banco de dados. O tipo de parada pode ser controlada pelo envio de sinais diferentes para o processo postmaster. SIGTERM Após receber o sinal SIGTERM o servidor não aceita novas conexões, mas deixa as sessões existentes terminarem seu trabalho normalmente. A parada é realizada apenas depois de todas as sessões terminarem normalmente. Esta é a Parada Elegante (Smart Shutdown). SIGINT O servidor não aceita novas conexões e envia para todos os processos servidores existentes o sinal SIGTERM, fazendo com que estes interrompam suas transações correntes e terminem imediatamente. Depois aguarda o processo servidor sair e, finalmente, pára. Esta é a Parada Rápida (Fast Shutdown). SIGQUIT Esta é a Parada Imediata (Immediate Shutdown), que faz o processo postmaster enviar um sinal SIGQUIT para todos os processos descendentes e sair imediatamente (sem que o próprio seja parado de forma apropriada). Da mesma maneira, os processos descendentes saem imediatamente após receberem o sinal SIGQUIT. Provoca uma recuperação (refazendo o log do WAL) na próxima inicialização. Somente é recomendado em caso de emergência.
Importante: É melhor não utilizar o SIGKILL para parar o servidor. Este sinal impede que o servidor libere a memória compartilhada e os semáforos, o que poderá então ter de ser feito manualmente.
O PID do processo postmaster pode ser encontrado utilizando o programa ps, ou no arquivo postmaster.pid no diretório de dados. Portanto, por exemplo, para efetuar uma parada rápida: $ kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`
O programa pg_ctl é um script do interpretador de comandos que fornece uma interface mais conveniente para parar o servidor.
289
16.7. Conexões TCP/IP seguras com SSL O PostgreSQL possui suporte nativo para utilizar conexões SSL para criptografar as comunicações cliente/servidor para aumentar a segurança. Necessita que o OpenSSL esteja instalado tanto no cliente quanto no servidor, e que o suporte no PostgreSQL esteja habilitado em tempo de construção (veja o Capítulo 14). Com o suporte ao SSL compilado, o servidor PostgreSQL pode ser inicializado com SSL habilitado definindo o parâmetro ssl como habilitado no arquivo postgresql.conf. Quando inicializado no modo SSL, o servidor procura pelos arquivos server.key e server.crt no diretório de dados, que devem conter a chave privada do servidor e o certificado, respectivamente. Estes arquivos devem estar configurados corretamente antes do servidor com o SSL habilitado ser inicializado. Se a chave privada estiver protegida por uma frasesenha (passphrase) o servidor solicita esta frase-senha, não inicializando até que seja fornecida. O servidor fica ouvindo tanto as conexões comuns quanto as SSL na mesma porta TCP, negociando com todo cliente se conectando se vai usar ou não o SSL. Veja no Capítulo 19 como forçar o servidor a requerer a utilização do SSL para determinadas conexões. Para obter detalhes sobre como criar a chave privada do servidor e o certificado, consulte a documentação do OpenSSL. Um certificado simples auto-assinado pode ser utilizado para iniciar os testes, mas um certificado assinado por uma autoridade certificadora (CA) (tanto uma CA global como uma local) deve ser utilizado no ambiente de produção para que o cliente possa verificar a identidade do servidor. Para criar rapidamente um certificado auto-assinado utilize o seguinte comando do OpenSSL: openssl req -new -text -out server.req
Forneça as informações solicitadas pelo openssl. Tenha certeza de fornecer o nome do hospedeiro local como “Common Name”; a senha desafio (challenge password) pode ser deixada em branco. O programa gera uma chave que é protegida por uma frase-senha; não é aceita uma frase-senha com menos de quatro caracteres. para remover a frase-senha (o que deve ser feito se for desejada uma inicialização automática do servidor), execute os comandos openssl rsa -in privkey.pem -out server.key rm privkey.pem
Entre com a frase-senha antiga e desbloqueie a chave existente. Agora execute openssl req -x509 -in server.req -text -key server.key -out server.crt chmod og-rwx server.key
para tornar o certificado um certificado auto-assinado, e para copiar a chave e o certificado para onde o servidor procura por estes.
16.8. Conexões TCP/IP seguras por túneis SSH Pode ser utilizado o SSH para criptografar a conexão de rede entre os clientes e o servidor PostgreSQL. Feito de forma apropriada produz uma conexão de rede adequadamente segura. Primeiro certifique-se que o servidor SSH está executando de forma apropriada na mesma máquina onde está o servidor PostgreSQL, e que é possível se conectar utilizando o ssh como algum usuário. Depois pode ser estabelecido um túnel seguro com um comando como o mostrado abaixo a partir da máquina cliente: ssh -L 3333:foo.com:5432 [email protected]
O primeiro número no argumento -L, 3333, é o número da porta do seu lado do túnel; pode ser escolhido livremente. O segundo número, 5432, é o fim remoto do túnel: o número da porta que seu servidor está utilizando. O nome ou o endereço entre os números das portas é o hospedeiro do servidor de banco de dados onde vai ser feita a conexão. Para ser possível se conectar ao servidor de banco de dados utilizando este túnel, é feita a conexão à porta 3333 na máquina local: psql -h localhost -p 3333 template1
290
Para o servidor de banco de dados vai parecer como se você fosse na realidade o usuário [email protected], e vai utilizar o procedimento de autenticação que estiver configurado para este usuário. Para que a configuração do túnel seja bem-sucedida, deve ser permitida a conexão através do ssh como [email protected], da mesma maneira como se tivesse tentado utilizar o ssh para estabelecer uma sessão de terminal. Dica: Existem diversas outras aplicações que podem fornecer túneis seguros utilizando procedimentos conceitualmente semelhantes ao que foi descrito.
Notas 1. O syslog, originalmente escrito por Eric Allman, é um sistema de log abrangente. Possui duas funções importantes: liberar os programadores da mecânica entediante de escrever arquivos de log, e colocar os administradores controlando o log. O formato do arquivo de configuração é “seletoração”, onde o seletor identifica o programa (facilidade) que envia a mensagem de log e o nível de severidade da mensagem. Linux Administration Handbook - Evi Nemeth e outros - Prentice Hall PTR. (N. do T.) 2. Também pode ser utilizado o comando locate plpgsql.so para ver o nome deste diretório, se pg_config não estiver disponível. (N. do T.)
291
Capítulo 17. Usuários do banco de dados e privilégios Todo agrupamento de banco de dados contém um conjunto de usuários do banco de dados. Estes usuários são distintos dos usuários gerenciados pelo sistema operacional onde o servidor executa. Os usuários possuem objetos no banco de dados (por exemplo, tabelas), e podem conceder privilégios nestes objetos para outros usuários, controlando quem pode acessar qual objeto. Este capítulo descreve como criar e gerenciar usuários e introduz o sistema de privilégios. Mais informações sobre os vários tipos de objetos do banco de dados e os efeitos dos privilégios podem ser encontrados no Capítulo 5.
17.1. Usuários do banco de dados Conceitualmente, os usuários do banco de dados são completamente distintos dos usuários do sistema operacional. Na prática, pode ser conveniente manter a correspondência, mas não é requerido. Os nomes dos usuários do banco de dados são globais através da instalação de agrupamento de bancos de dados (e não por banco de dados individualmente). Para criar um usuário deve ser utilizado o comando SQL CREATE USER: CREATE USER nome;
Onde nome segue as regras dos identificadores SQL: ou não contém caracteres especiais, ou está entre aspas. Para remover um usuário existente deve ser utilizado o comando análogo DROP USER: DROP USER nome;
Por conveniência, os programas createuser e dropuser são fornecidos na forma de scripts englobando estes comandos SQL, podendo ser chamados a partir do interpretador de comandos: createuser nome dropuser nome
Para ser possível carregar o sistema de banco de dados, um sistema recém inicializado sempre contém um usuário pré-definido. Este usuário tem o ID fixado como 1 e, por padrão (a menos que seja alterado ao executar o initdb), tem o mesmo nome do usuário do sistema operacional que inicializou o agrupamento de bancos de dados. Geralmente este usuário se chama postgres. Para poder criar mais usuários primeiro é necessário se conectar como este usuário inicial. Está ativa a identidade de exatamente um usuário em uma conexão com o servidor de banco de dados. O nome do usuário a ser utilizado em uma determinada conexão com o banco de dados é indicado pelo cliente que está iniciando a requisição de conexão, de uma forma específica da aplicação. Por exemplo, o programa psql utiliza a opção -U na linha de comando indicar o usuário a ser utilizado na conexão. Muitas aplicações assumem o nome do usuário corrente do sistema operacional por padrão (inclusive o createuser e o psql). Portanto, é conveniente manter uma correspondência de nomes entre os dois conjuntos de usuários. O conjunto de usuários do banco de dados que podem ser utilizados em determinada conexão cliente é determinado pela configuração da autenticação de clientes, conforme explicado no Capítulo 19 (Portanto, um cliente não está necessariamente limitado a se conectar com o mesmo nome do usuário do sistema operacional, da mesma maneira que uma pessoa não está restrita no nome de login ao seu nome verdadeiro). Uma vez que a identificação do usuário determina o conjunto de privilégios disponíveis para o cliente conectado, é importante sua definição cuidadosa ao se configurar um ambiente multiusuário.
17.2. Atributos do usuário Um usuário de banco de dados pode possuir vários atributos que definem seus privilégios e a interação com o sistema de autenticação de clientes.
292
superusuário Um superusuário do banco de dados não está sujeito a verificações de permissão. Também, somente um superusuário pode criar novos usuários. Para criar um superusuário deve ser utilizado o comando CREATE USER nome CREATEUSER. criação de banco de dados Deve ser dada uma permissão explícita para o usuário poder criar bancos de dados (exceto para os superusuários, uma vez que estes não estão sujeitos a verificações de permissão). Para criar um usuário deste tipo, deve ser utilizado o comando CREATE USER nome CREATEDB. senha A senha só possui importância se o método de autenticação do cliente requerer que o usuário forneça a senha para se conectar ao banco de dados. Os métodos de autenticação password, md5 e crypt fazem uso da senha. As senhas do banco de dados são distintas das senhas do sistema operacional. A senha deve ser especificada na hora da criação do usuário através do comando CREATE USER nome PASSWORD 'cadeia de caracteres'. Os atributos do usuário podem ser modificados após este ter sido criado utilizando o comando ALTER USER. Veja as páginas de referência dos comandos CREATE USER e ALTER USER para obter mais detalhes. O usuário também pode definir padrões pessoais para muitas das definições de configuração em tempo de execução, conforme descrito na Seção 16.4. Por exemplo, se por alguma razão for desejado desabilitar varreduras de índice toda vez que se conectar (conselho: não é uma boa idéia), pode ser utilizado o comando: ALTER USER meu_usuário SET enable_indexscan TO off;
Este comando salva a definição (mas não define imediatamente) e nas próximas conexões vai parecer que o comando SET enable_indexscan TO off; foi chamado logo antes da sessão começar. Continua sendo possível alterar esta definição durante a sessão; apenas será o padrão. Para desfazer esta definição deve ser utilizado ALTER USER meu_usuário RESET nome_da_variável;.
17.3. Grupos Como no Unix, os grupos são uma forma lógica de agrupar usuários para facilitar o gerenciamento de privilégios; os privilégios podem ser concedidos, ou revogados, para o grupo como um todo. Para criar um grupo deve ser utilizado o comando: CREATE GROUP nome;
Para adicionar e remover usuários de um grupo devem ser utilizados os comandos: ALTER GROUP nome ADD USER nome_usuário_1, ... ; ALTER GROUP nome DROP USER nome_usuário_1, ... ;
17.4. Privilégios Quando um objeto do banco de dados é criado, é atribuído um dono ao mesmo. O dono é o usuário que executou a declaração de criação. Para mudar o dono de uma tabela, índice, seqüência ou visão deve ser utilizado o comando ALTER TABLE. Por padrão, somente o dono (ou um superusuário) pode fazer qualquer coisa com o objeto. Para permitir o uso por outros usuários, devem ser concedidos privilégios. Existem vários privilégios distintos: SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES, TRIGGER, CREATE, TEMPORARY, EXECUTE, USAGE e ALL PRIVILEGES. Para obter mais informações sobre os diferentes tipos de privilégio suportados pelo PostgreSQL, veja a página de referência do comando GRANT. O direito de modificar ou destruir um objeto é sempre um privilégio apenas do dono. Para atribuir privilégios, é utilizado o comando GRANT. Portanto, se joe for um usuário existente, e tbl_contas for uma tabela existente, o privilégio de atualizar a tabela pode ser concedido pelo comando: GRANT UPDATE ON tbl_contas TO joe;
293
O usuário que executa este comando deve ser o dono da tabela. Para conceder privilégios para um grupo deve ser utilizado o comando: GRANT SELECT ON tbl_contas TO GROUP grp_pagamento;
O nome especial de “usuário” PUBLIC pode ser utilizado para conceder o privilégio para todos os usuários do sistema. Escrevendo-se ALL no lugar do privilégio especifica que todos os privilégios serão concedidos. Para revogar um privilégio deve ser utilizado o comando REVOKE: REVOKE ALL ON tbl_contas FROM PUBLIC;
Os privilégios especiais do dono da tabela (ou seja, o direito de DROP (remover), GRANT (conceder), REVOKE (revogar), etc.) são sempre implícitos ao fato de ser o dono, não podendo ser concedidos ou revogados. Mas o dono da tabela pode decidir revogar seus próprios privilégios comuns como, por exemplo, tornar a tabela somente para leitura para o próprio assim como para os outros.
17.5. Funções e gatilhos As funções e os gatilhos permitem que usuários insiram código no servidor que outros usuários podem executar sem conhecer. Portanto, os dois mecanismos permitem a criação de “Cavalos de Tróia” com relativa impunidade. A única proteção real é um controle rígido sobre quem pode definir funções. As funções escritas em qualquer linguagem, exceto SQL, executam dentro de um processo servidor com as permissões do sistema operacional para o processo servidor do banco de dado. É possível mudar as estruturas de dado internas do servidor a partir de funções confiáveis (trusted). Portanto, entre outras coisas, tais funções podem driblar todo controle de acesso do sistema. Este é um problema inerente às funções definidas pelo usuário escritas na linguagem C.
294
Capítulo 18. Gerenciamento de bancos de dados Cada instância em execução do servidor PostgreSQL gerencia um ou mais bancos de dados. Os bancos de dados são, portanto, o nível hierárquico mais alto da organização dos objetos SQL (“objetos de banco de dados”). Este capítulo descreve as propriedades dos bancos de dados, e como criar, gerenciar e destruir os mesmos.
18.1. Visão geral Um banco de dados é uma coleção nomeada de objetos SQL (“objetos de banco de dados”). Geralmente, todos os objetos de banco de dados (tabelas, funções, etc.) pertencem a um e somente um banco de dados (Mas existem alguns poucos catálogos do sistema como, por exemplo, pg_database, que pertencem a todo o agrupamento sendo acessíveis por todos os bancos de dados do agrupamento). Mais precisamente um banco de dados é uma coleção de esquemas, e os esquemas contêm as tabelas, funções, etc. Portanto, a hierarquia completa é: servidor, banco de dados, esquema, tabela (ou outra coisa em vez da tabela). Uma aplicação se conectando ao servidor de banco de dados especifica na requisição de conexão o nome do banco de dados que deseja se conectar. Não é possível acessar mais de um banco de dados por conexão (Mas uma aplicação não tem restrição do número de conexões abertas no mesmo ou em outros bancos de dados). É possível, entretanto, acessar mais de um esquema a partir da mesma conexão. Os esquemas são estruturas puramente lógicas, e o que pode ser acessado é gerenciado pelo sistema de privilégios. Os bancos de dados são fisicamente separados e o controle de acesso é gerenciado no nível de conexão. Se uma instância do servidor PostgreSQL serve para abrigar usuários que devem estar separados e, em sua maioria, desconhecendo um ao outro, é recomendável colocá-los em bancos de dados separados. Se os projetos ou os usuários estão interrelacionados, devendo um poder utilizar os recursos do outro, devem ser colocados no mesmo banco de dados, mas possivelmente em esquemas separados. Mais informações sobre o gerenciamento de esquemas pode ser encontrado no Seção 5.8. Nota: O padrão SQL chama os bancos de dados de “catálogos”, mas na prática não há diferença.
18.2. Criação de banco de dados Para se poder criar um banco de dados o servidor PostgreSQL deve estar operacional (veja a Seção 16.3). Os bancos de dados são criados através do comando SQL CREATE DATABASE: CREATE DATABASE nome_do_banco_de_dados;
onde nome_do_banco_de_dados segue as regras usuais para identificadores SQL. O usuário corrente se torna automaticamente o dono do novo banco de dados. É um privilégio do dono do banco de dados removê-lo posteriormente (o que também remove todos os objetos contidos no banco de dados, mesmo sendo de outro dono). A criação de bancos de dados é uma operação restringida. Veja na Seção 17.2 como conceder permissão. Uma vez que é necessário estar conectado ao servidor de banco de dados para poder executar o comando CREATE DATABASE, a questão é como o primeiro banco de dados de um determinado agrupamento pode ser criado. O primeiro banco de dados é sempre criado pelo comando initdb quando a área de armazenamento de dados é inicializada (Veja a Seção 16.2.) Este banco de dados se chama template1. Portanto, para criar o primeiro banco de dados “de verdade” deve-se conectar à template1.
O nome template1 (modelo1) não é um acidente: Quando é criado um banco de dados novo, o banco de dados modelo é essencialmente clonado. Isto significa que qualquer mudança feita em template1 é propagada para todos os bancos de dados criados depois. Implica que o banco de dados modelo não deve ser utilizado para trabalho, mas esta funcionalidade usada com bom senso pode ser conveniente. Mais detalhes podem ser vistos na Seção 18.3.
295
Como uma conveniência adicional, também existe um programa que pode ser chamado a partir do interpretador de comandos para criar novos bancos de dados, o createdb. createdb nome_do_banco_de_dados
O comando createdb não realiza nenhuma mágica. Se conecta ao banco de dados template1 e executa o comando CREATE DATABASE, exatamente como descrito acima. A página de referência do createdb contém os detalhes da chamada. Observe que createdb sem nenhum argumento cria um banco de dados com o nome do usuário corrente, que pode ser o desejado, ou não. Nota: O Capítulo 19 contém informações sobre como restringir quem pode se conectar a um determinado banco de dados.
Algumas vezes se deseja criar um banco de dados para outra pessoa. Este usuário deve se tornar o dono do novo banco de dados e, portanto, poder configurá-lo e gerenciá-lo por si próprio. Para se fazer isto deve ser utilizado um dos seguintes comandos: CREATE DATABASE nome_do_banco_de_dados OWNER nome_do_usuário;
a partir do ambiente SQL, ou createdb -O nome_do_usuário nome_do_banco_de_dados
É necessário ser um superusuário para poder criar bancos de dados para outros usuários.
18.3. Bancos de dado modelo Na verdade o comando CREATE DATABASE funciona copiando um banco de dados existente. Por padrão, copia o banco de dados padrão do sistema chamado template1. Portanto, este banco de dados é um “modelo” a partir do qual os novos bancos de dados são criados. Se forem adicionados objetos ao template1, estes objetos serão copiados nos próximos bancos de dados de usuários criados. Este comportamento permite modificações locais do conjunto padrão de objetos nos bancos de dados. Por exemplo, se for instalada a linguagem procedural PL/pgSQL em template1, esta estará automaticamente disponível nos bancos de dados dos usuários sem que qualquer procedimento extra precise ser feito. Existe um segundo banco de dados padrão do sistema chamado template0. Este banco de dados contém os mesmos dados contidos inicialmente em template1, ou seja, somente os objetos pré-definidos pela versão do PostgreSQL. O template0 nunca deve ser modificado após o initdb. Instruindo o CREATE DATABASE para copiar template0, em vez de template1, pode ser criado um banco de dados de usuário “virgem”, não contendo nenhuma adição da instalação local feita em template1. É particularmente útil ao se restaurar uma cópia de segurança feita pelo pg_dump: o script da cópia de segurança deve ser restaurado em um banco de dados virgem para garantir a recriação do conteúdo correto da cópia de segurança do banco de dados, sem conflitos com as adições que podem estar presentes em template1. Para criar um banco de dados copiando template0 deve ser utilizado: CREATE DATABASE nome_do_banco_de_dados TEMPLATE template0;
a partir do ambiente SQL, ou createdb -T template0 nome_do_banco_de_dados
a partir do interpretador de comandos. É possível criar bancos de dados modelo adicionais, e na verdade pode ser copiado qualquer banco de dados do agrupamento especificando seu nome como modelo no comando CREATE DATABASE. É importante compreender, entretanto, que não se pretende (ainda) que esta seja uma facilidade “COPY DATABASE” de uso geral. Em particular, é essencial que o banco de dados de origem esteja ocioso (nenhuma transação em andamento alterando dados) durante a operação de cópia. O comando CREATE DATABASE verifica se nenhuma sessão (além da própria) está conectada ao banco de dados de origem no início da operação, mas não garante que mudanças possam ocorrer durante a execução da cópia, resultando em um banco de dados copiado
296
incoerente. Portanto, recomenda-se que os bancos de dados utilizados como modelo sejam tratados como somente para leitura. Dois sinalizadores úteis existem no banco de dados pg_database para cada banco de dados: as colunas datistemplate e datallowconn. A coluna datistemplate pode ser definida para indicar que o banco de dados se destina a servir de modelo para o comando CREATE DATABASE. Se este sinalizador estiver ativo, o banco de dados pode ser clonado por qualquer usuário com privilégio de CREATEDB; se não estiver ativo, somente os superusuários e o dono do banco de dados podem cloná-lo. Se datallowconn for falso, então não é permitida nenhuma nova conexão ao banco de dados (mas as sessões existentes não são interrompidas simplesmente definindo o sinalizador como falso). O banco de dados template0 normalmente é marcado com datallowconn = false para evitar que seja modificado. Tanto template0 quanto template1 devem sempre ser marcados com datistemplate = true. Após preparar um banco de dados modelo, ou fazer alguma mudança em um, é recomendado executar VACUUM FREEZE ou VACUUM FULL FREEZE neste banco de dados. Se for feito quando não houver nenhuma outra transação aberta no mesmo banco de dados, é garantido que todas as linhas no banco de dados serão “congeladas” e não estarão sujeitas a problemas de recomeço do ID de transação. Isto é particularmente importante em um banco de dados que terá datallowconn definido como falso, uma vez que será impossível executar a rotina de manutenção VACUUM neste banco de dados. Veja a Seção 21.1.3 para obter mais informações. Nota: template1 e template0 não possuem qualquer status especial além do fato do nome template1 ser o nome de banco de dados de origem padrão do comando CREATE DATABASE e o banco de dados padrão para se conectar utilizado por vários programas, tal como createdb. Por exemplo, template1 pode ser removido e recriado a partir de template0 sem qualquer efeito prejudicial. Esta forma de agir pode ser aconselhável se forem adicionadas, por descuido, coisas inúteis ao template1.
18.4. Configuração do banco de dados Se lembre da Seção 16.4 que o servidor PostgreSQL dispõe de um grande número de variáveis de configuração em tempo de execução. Podem ser definidos valores padrão específicos para o banco de dados para muitas destas definições. Por exemplo, se por algum motivo for desejado desabilitar o otimizador GEQO para um determinado banco de dados, normalmente seria necessário desabilitá-lo para todos os bancos de dados, ou ter certeza que cada cliente ao se conectar a este banco de dados execute SET geqo TO off;. Para tornar esta definição a definição padrão, pode ser executado o comando: ALTER DATABASE meu_banco_de_dados SET geqo TO off;
Este comando salva a definição (mas não a define imediatamente), e nas próximas conexões vai parecer que SET geqo TO off; foi executado logo após a sessão iniciar. Observe que os usuários continuarão podendo
alterar esta definição durante a sessão; apenas será o padrão. Para desfazer esta definição deve ser utilizado ALTER DATABASE nome_do_banco_de_dados RESET nome_da_variável;.
18.5. Locais alternativos É possível criar bancos de dados em outros locais além do local padrão para a instalação. Deve ser lembrado que todos os acessos aos bancos de dados são realizados pelo servidor de banco de dados e, portanto, qualquer local especificado deve poder ser acessado pelo servidor. Um local alternativo para bancos de dados é referenciado por uma variável de ambiente que fornece o caminho absoluto para o local de armazenamento pretendido. Esta variável de ambiente deve estar presente no ambiente do servidor e, portanto, deve ser definida antes do servidor ser inicializado (Portanto, o conjunto de locais alternativos está sob controle do administrador; os usuários comuns não podem mudar). Qualquer nome válido de variável de ambiente pode ser utilizado para referenciar um local alternativo, embora a utilização de nomes de variáveis com o prefixo PGDATA seja recomendado para evitar confusão e conflito com outras variáveis.
297
Para criar a variável no ambiente do processo servidor primeiro o servidor deve ser parado, a variável definida, inicializada a área de dados e, finalmente, reinicializado o servidor (veja também a Seção 16.6 e a Seção 16.3). Para definir uma variável de ambiente execute PGDATA2=/home/postgres/data export PGDATA2
nos interpretadores de comando Bourne, ou setenv PGDATA2 /home/postgres/data
no csh ou no tcsh. Deve haver certeza que esta variável de ambiente estará sempre definida no ambiente do servidor, senão não será possível acessar o banco de dados. Portanto, provavelmente será necessário definir a variável em algum arquivo de inicialização do interpretador de comandos, ou em algum script de inicialização do servidor. Para criar uma área de armazenamento de dados em PGDATA2 garanta que o diretório que esta contém (neste caso /home/postgres) já existe, e pode ser escrito pela conta de usuário que executa o servidor (veja a Seção 16.1). Então, a partir da linha de comando execute: initlocation PGDATA2
(não initlocation $PGDATA2). Depois o servidor pode ser inicializado. Para criar um banco de dados no novo local deve ser utilizado o comando: CREATE DATABASE nome_do_banco_de_dados WITH LOCATION 'local';
onde local é a variável de ambiente utilizada, neste exemplo PGDATA2. O comando createdb possui a opção -D para esta finalidade. Os bancos de dados criados em locais alternativos podem ser acessados e removidos como qualquer outro banco de dados. Nota: Também é possível especificar caminhos absolutos no comando CREATE DATABASE diretamente, sem definir as variáveis de ambiente. Esta funcionalidade está desabilitada por padrão, porque é um risco à segurança. Para que seja habilitada o PostgreSQL deve ser compilado com a macro do pré-processador C ALLOW_ABSOLUTE_DBPATHS definida. Uma forma de fazer é executar o passo de compilação da seguinte maneira: gmake CPPFLAGS=-DALLOW_ABSOLUTE_DBPATHS all
18.6. Remoção do banco de dados Os bancos de dados são removidos pelo comando DROP DATABASE: DROP DATABASE nome_do_banco_de_dados;
Somente o dono do banco de dados (ou seja, o usuário que o criou) ou um superusuário podem remover um banco de dados. A remoção do banco de dados remove todos os objetos contidos no banco de dados. A remoção do banco de dados não pode ser desfeita. Não é possível executar o comando DROP DATABASE estando conectado ao banco de dados a ser removido. É possível, entretanto, estar conectado a qualquer outro banco de dados, inclusive o banco de dados template1. O banco de dados template1 é a única opção para remover o último banco de dados de usuário de um determinado agrupamento. Por conveniência existe um programa executável pelo interpretador de comandos para remover bancos de dados: dropdb nome_do_banco_de_dados
(Diferentemente do createdb, a ação padrão não é remover o banco de dados que tem o nome do usuário corrente).
298
Capítulo 19. Autenticação de clientes Quando uma aplicação cliente se conecta ao servidor de banco de dados especifica o nome de usuário do PostgreSQL que deseja usar na conexão, da mesma maneira como é feita a conexão no sistema operacional Unix como um determinado usuário. Dentro do ambiente SQL o nome de usuário do banco de dados determina os privilégios de acesso aos objetos do banco de dados -- veja o Capítulo 17 para obter mais informações. Portanto, é essencial restringir quais usuários de banco de dados podem se conectar. Autenticação é o processo pelo qual o servidor de banco de dados estabelece a identidade do cliente e, por extensão, determina se a aplicação cliente (ou o usuário executando a aplicação cliente) tem permissão para se conectar com o nome de usuário que foi informado. O PostgreSQL disponibiliza vários métodos diferentes para autenticação de clientes. O método utilizado para autenticar uma determinada conexão cliente pode ser selecionado tomando por base o endereço de hospedeiro (do cliente), o banco de dados ou o usuário. Os nomes de usuário do PostgreSQL são logicamente distintos dos nomes de usuário do sistema operacional onde o servidor executa. Se todos os usuários de um determinado servidor de banco de dados também possuem conta no sistema operacional do servidor, faz sentido atribuir nomes de usuário do banco de dados correspondentes aos nomes de usuário do sistema operacional. Entretanto, um servidor que aceita conexões remotas pode possuir muitos usuários de banco de dados que não possuem conta no sistema operacional local e, nestes casos, não há necessidade de haver associação entre os nomes de usuário do banco de dados e os nomes de usuário do sistema operacional.
19.1. O arquivo pg_hba.conf A autenticação do cliente é controlada pelo arquivo pg_hba.conf presente no diretório de dados como, por exemplo, /usr/local/pgsql/data/pg_hba.conf. HBA significa autenticação baseada no hospedeiro (host-based authentication). Um arquivo pg_hba.conf padrão é instalado quando o diretório de dados é inicializado pelo initdb. O formato geral do arquivo pg_hba.conf é um conjunto de registros, um por linha. As linhas em branco são ignoradas, da mesma forma que qualquer texto após o caractere de comentário#. Um registro é constituído por vários campos separados por espaços ou tabulações. Os campos podem conter espaços em branco se o valor do campo estiver entre aspas. Os registros não podem ocupar mais de uma linha. Cada registro especifica um tipo de conexão, um intervalo de endereços de IP de cliente (se for relevante para o tipo de conexão), um nome de banco de dados, um nome de usuário e o método de autenticação a ser utilizado nas conexões que correspondem a estes parâmetros. O primeiro registro com o tipo de conexão, endereço do cliente, banco de dados e nome de usuário requisitado correspondente é utilizado para realizar a autenticação. Não existe fall-through (exaustão) ou backup: se um registro for escolhido e a autenticação não for bem-sucedida, os próximos registros não são levados em consideração. Se nenhum registro corresponder, então o acesso é negado. O registro pode ter um dos sete formatos a seguir: local host
banco_de_dados usuário método_de_autenticação [opção_de_autenticação] banco_de_dados usuário endereço_de_IP máscara_de_IP método_de_autenticação\ [opção_de_autenticação] hostssl banco_de_dados usuário endereço_de_IP máscara_de_IP método_de_autenticação\ [opção_de_autenticação] hostnossl banco_de_dados usuário endereço_de_IP máscara_de_IP método_de_autenticação\ [opção_de_autenticação] host banco_de_dados usuário endereço_de_IP/tamanho_da_máscara_de_IP\ método_de_autenticação [opção_de_autenticação] hostssl banco_de_dados usuário endereço_de_IP/tamanho_da_máscara_de_IP método_de_autenticação [opção_de_autenticação] hostnossl banco_de_dados usuário endereço_de_IP/tamanho_da_máscara_de_IP\ método_de_autenticação [opção_de_autenticação]
299
O significado de cada campo está descrito abaixo: local
Este registro corresponde às tentativas de conexão feitas utilizando soquete do domínio Unix. Sem um registro deste tipo não são permitidas conexões oriundas de soquete do domínio Unix. host
Este registro corresponde às tentativas de conexão feitas utilizando redes TCP/IP. Observe que as conexões TCP/IP não são permitidas a menos que o servidor seja inicializado com a opção -i, ou com o parâmetro de configuração tcpip_socket habilitado. hostssl
Este registro corresponde às tentativas de conexão feitas utilizando SSL no TCP/IP. Os registros host correspondem tanto às tentativas de conexão SSL quanto às não SSL, mas os registros hostssl requerem conexões SSL. Para esta opção poder ser utilizada o servidor deve ter sido construído com o suporte a SSL habilitado. Além disso, o SSL deve ser habilitado pelo parâmetro de configuração ssl (veja a Seção 16.4 para obter mais informações). hostnossl
Este registro é semelhante a hostssl, mas com uma lógica inversa: corresponde somente às tentativas de conexão regulares que não utilizam SSL. banco_de_dados Especifica quais bancos de dados este registro corresponde. O valor all especifica que corresponde a todos os bancos de dados. O valor sameuser especifica que o registro corresponde se o banco de dados tiver o mesmo nome do usuário da requisição de conexão. O valor samegroup especifica que o usuário deve ser membro do grupo com mesmo nome do banco de dados da requisição de conexão. Senão, é o nome de um banco de dados do PostgreSQL específico. Vários nomes de banco de dados podem ser fornecidos separados por vírgula. Um arquivo contendo nomes de banco de dados pode ser especificado precedendo o nome do arquivo por @. O arquivo deve estar no mesmo diretório de pg_hba.conf. usuário Especifica quais usuários do PostgreSQL este registro corresponde. O valor all especifica que corresponde a todos os usuários. Senão, é o nome de um usuário específico do PostgreSQL. Vários nomes de usuário podem ser fornecidos separados por vírgula. Nomes de grupos podem ser especificados precedendo o nome do grupo por +. Um arquivo contendo nomes de usuário pode ser especificado precedendo o nome do arquivo por @. O arquivo deve estar no mesmo diretório de pg_hba.conf. endereço_de_IP máscara_de_IP Estes campos contêm endereços de IP e valores de máscara na dotação padrão utilizando ponto (Os endereços de IP somente podem ser especificados numericamente, e não como nomes de domínios ou de hospedeiros). Tomados junto especificam os endereços de IP da máquina aos quais este registro corresponde. A lógica precisa é (endereço_verdadeiro_de_IP xor campo_de_endereço_de_IP) and campo_de_máscara_de_IP
devendo ser igual a zero para o registro corresponder. Um endereço de IP fornecido no formato IPv4 corresponde às conexões IPv6 que possuem um endereço correspondente; por exemplo 127.0.0.1 corresponde ao endereço de IPv6 ::ffff:127.0.0.1. Uma entrada especificando um formato IPv6 somente corresponde às conexões IPv6, mesmo que o endereço representado esteja no intervalo IPv4-em-IPv6. Observe que as entradas no formato IPv6 serão rejeitadas se a biblioteca C do sistema não tiver suporte para endereços IPv6. Estes campos somente se aplicam aos registros host, hostssl e hostnossl.
300
tamanho_da_máscara_de_IP Este campo pode ser utilizado como uma alternativa para a notação de máscara_de_IP. É um valor inteiro especificando o número de bits de alta-ordem usados para definir a máscara. O número deve estar entre 0 e 32 (no caso de um endereço IPv4) ou 128 (no caso de um endereço IPv6), inclusive. Zero corresponde a qualquer endereço, enquanto 32 (ou 128, respectivamente) corresponde somente ao hospedeiro especificado. A mesma lógica de correspondência é utilizada para a notação com pontos máscara_de_IP. Não deve haver espaços em branco entre o endereço_de_IP e a /, nem entre a / e o tamanho_da_máscara_de_IP, ou o arquivo não será analisado corretamente. Este campo somente se aplica aos registros host, hostssl e hostnossl. método_de_autenticação Especifica o método de autenticação a ser utilizado ao se conectar através deste registro. O sumário das escolhas possíveis está mostrado aqui; os detalhes podem ser encontrados na Seção 19.2. trust
A conexão é permitida incondicionalmente. Este método permite a qualquer um se conectar ao servidor de banco de dados PostgreSQL se autenticando como o usuário do PostgreSQL que for desejado, sem necessidade de senha. Veja a Seção 19.2.1 para obter detalhes. reject
A conexão é rejeitada incondicionalmente. É útil para “eliminar por filtragem” certos hospedeiros de um grupo. md5
Requer que o cliente forneça uma senha criptografada pelo método md5 para autenticação. Este é o único método que permite o armazenamento de senhas criptografadas em pg_shadow. Veja a Seção 19.2.2 para obter detalhes. crypt
Como o método md5, mas utiliza a antiga criptografia crypt(), sendo necessário para clientes pré7.2. O md5 é preferível para os clientes 7.2 e posteriores. Veja a Seção 19.2.2 para obter detalhes. password
O mesmo que md5, mas a senha é enviada em texto puro pela rede. Não deve ser utilizado em redes não confiáveis. Veja a Seção 19.2.2 para obter detalhes. krb4
Kerberos V4 é utilizado para autenticar o usuário. Somente disponível para conexões TCP/IP. Veja a Seção 19.2.3 para obter detalhes. krb5
Kerberos V5 é utilizado para autenticar o usuário. Somente disponível para conexões TCP/IP. Veja a Seção 19.2.3 para obter detalhes. ident
Obtém o nome de usuário do sistema operacional do cliente (para conexões TCP/IP fazendo contato com o servidor de identificação no cliente, para conexões locais obtendo a partir do sistema operacional) e verificando se o usuário possui permissão para se conectar no banco de dados requisitado consultando o mapa especificado após a palavra chave ident. Se for utilizado o mapa sameuser, é requerido que os nomes dos usuários sejam idênticos. Se não for, o nome do mapa é procurado no arquivo pg_ident.conf no mesmo diretório de pg_hba.conf. A conexão é aceita se este arquivo contiver uma entrada para este nome de mapa com o nome de usuário do sistema operacional e o nome de usuário do PostgreSQL requisitado. Para conexões locais somente funciona nas máquinas que suportam credenciais de soquete do domínio Unix (atualmente Linux, FreeBSD, NetBSD, OpenBSD e BSD/OS).
301
Veja a Seção 19.2.4 abaixo para obter detalhes. pam
Autenticação utilizando o serviço Pluggable Authentication Modules (PAM) fornecido pelo sistema operacional. Veja a Seção 19.2.5 para obter detalhes. opção_de_autenticação O significado deste campo opcional depende do método de autenticação escolhido, estando descrito na próxima seção. Uma vez que os registros de pg_hba.conf são examinados seqüencialmente para cada tentativa de conexão, a ordem dos registros têm significado. Normalmente, os primeiros registros possuem parâmetros de correspondência de conexão mais rigorosos e métodos de autenticação mais flexíveis, enquanto os últimos registros possuem parâmetros de correspondência mais flexíveis e métodos de autenticação mais rigorosos. Por exemplo, pode ser desejado utilizar a autenticação trust para conexões TCP/IP locais mas requerer o uso de senha para conexões TCP/IP remotas. Neste caso, o registro especificando a autenticação trust para conexões a partir de 127.0.0.1 deve aparecer antes do registro especificando autenticação por senha para uma faixa permitida mais ampla de endereços de IP de cliente. Importante: Não impeça o acesso do superusuário ao banco de dados template1. Vários comandos utilitários precisam acessar template1.
O arquivo pg_hba.conf é lido na inicialização e quando o processo servidor principal (postmaster) recebe um sinal SIGHUP. Se o arquivo for editado com o sistema ativo, será necessário enviar este sinal para o postmaster (utilizando pg_ctl reload ou kill -HUP) para fazer o arquivo ser lido novamente. Um exemplo do arquivo pg_hba.conf está mostrado no Exemplo 19-1. Veja a próxima seção para obter detalhes sobre os diferentes métodos de autenticação. Exemplo 19-1. Um exemplo do arquivo pg_hba.conf # Permitir qualquer usuário do sistema local se conectar a qualquer banco # de dados sob qualquer nome de usuário utilizando os soquetes do domínio # Unix (o padrão para conexões locais). # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD local all all trust # A mesma coisa utilizando conexões locais TCP/IP retornantes (loopback). # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host all all 127.0.0.1 255.255.255.255 trust # O mesmo que o exemplo anterior mas utilizando máscara CIDR. # # TYPE DATABASE USER IP-ADDRESS/CIDR-mask METHOD host all all 127.0.0.1/32 trust # Permitir qualquer usuário de qualquer hospedeiro com endereço de IP 192.168.93.x # se conectar ao banco de dados "template1" com o mesmo nome de usuário que "ident" # informa para a conexão (normalmente o nome de usuário do Unix). # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host template1 all 192.168.93.0 255.255.255.0 ident sameuser # O mesmo que o exemplo anterior mas utilizando máscara CIDR. # # TYPE DATABASE USER IP-ADDRESS/CIDR-mask METHOD host template1 all 192.168.93.0/24 ident sameuser # Permite ao usuário do hospedeiro 192.168.12.10 se conectar ao banco de dados # "template1" se a senha do usuário for fornecida corretamente.
302
# # TYPE host
DATABASE template1
USER all
IP-ADDRESS 192.168.12.10
IP-MASK 255.255.255.255
METHOD md5
# Na ausência das linhas "host" precedentes, estas duas linhas # rejeitam todas as conexões oriundas de 192.168.54.1 (uma vez que esta entrada # será correspondida primeiro), mas permite conexões Kerberos V de qualquer ponto # da Internet. A máscara zero significa que nenhum bit do endereço de IP # do hospedeiro é considerado e, portanto, corresponde a qualquer hospedeiro. # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host all all 192.168.54.1 255.255.255.255 reject host all all 0.0.0.0 0.0.0.0 krb5 # Permite os usuários dos hospedeiros 192.168.x.x se conectarem a qualquer # banco de dados se passarem na verificação de "ident". Se, por exemplo, "ident" # informar que o usuário é "oliveira" e este requerer se conectar como o usuário # do PostgreSQL "guest1", a conexão será permitida se houver uma entrada # em pg_ident.conf para o mapa "omicron" informando que "oliveira" pode se # conectar como "guest1". # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD host all all 192.168.0.0 255.255.0.0 ident omicron # Se as linhas abaixo forem as únicas três linhas para conexão local, vão # permitir os usuários locais se conectarem somente aos seus próprios bancos de # dados (bancos de dados com o mesmo nome de seus nomes de usuário), exceto para # os administradores e membros do grupo "suporte" que podem se conectar a todos # os bancos de dados. O arquivo $PGDATA/admins contém a relação de nomes de # usuários. São requeridas senhas em todos os casos. # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD local sameuser all md5 local all @admins md5 local all +suporte md5 # As duas últimas acima podem ser combinadas em uma única linha: local all @admins,+suporte
md5
# A coluna banco de dados também pode utilizar listas e nomes de arquivos, # mas não grupos: local db1,db2,@demodbs all md5
19.2. Métodos de autenticação Abaixo estão descritos os métodos de autenticação mais detalhadamente.
19.2.1. Autenticação confiável Quando a autenticação trust é especificada, o PostgreSQL assume que qualquer um que possa se conectar ao servidor está autorizado a acessar o banco de dados como qualquer usuário que seja especificado (incluindo o superusuário do banco de dados). Este método deve ser utilizado somente quando existe uma proteção adequada no nível de sistema operacional para as conexões ao servidor. A autenticação trust é apropriada e muito conveniente para conexões locais em uma estação de trabalho com um único usuário. Geralmente não é apropriada em um máquina multiusuária. Entretanto, é possível utilizar o trust mesmo em uma máquina multiusuária, se for restringido o acesso ao arquivo de soquete do domínio Unix utilizando permissões do sistema de arquivos. Para fazer isto, deve ser definido o parâmetro de configuração unix_socket_permissions (e, possivelmente, unix_socket_group) conforme descrito na Seção 16.4.1. Também pode ser definido o parâmetro de configuração unix_socket_directory para colocar o arquivo de soquete em um diretório com restrição adequada.
303
Definir as permissões do sistema de arquivos somente serve para as conexões através dos soquetes do Unix. As conexões locais TCP/IP não são restritas desta maneira; portanto, se for desejado utilizar permissões do sistema de arquivos para segurança local, deve ser removida a linha host ... 127.0.0.1 ... do arquivo pg_hba.conf, ou mudá-la para que use um método de autenticação diferente de trust. A autenticação trust somente é adequada para as conexões TCP/IP, quando se confia em todos os usuários de todas as máquinas que podem se conectar ao servidor de banco de dados pelas linhas do arquivo pg_hba.conf que especificam trust. Raramente faz sentido utilizar trust para conexões TCP/IP, a não ser as oriundas do localhost (127.0.0.1).
19.2.2. Autenticação por senha Os métodos de autenticação baseados em senha são md5, crypt e password. Estes métodos operam de forma semelhante exceto com relação à forma como a senha é enviada através da conexão. Se houver preocupação com relação aos ataques de “farejamento” (sniffing) de senhas, então o md5 é o preferido, com crypt como a segunda opção se for necessário suportar clientes pré-7.2. O método password deve ser evitado, especialmente em conexões pela Internet aberta (a menos que seja utilizado SSL, SSH ou outro método de segurança para proteger a comunicação). As senhas de banco de dados do PostgreSQL são distintas das senhas de usuário do sistema operacional. As senhas de todos os usuários do banco de dados são armazenadas na tabela do catálogo do sistema pg_shadow. As senhas podem ser gerenciadas através dos comandos SQL CREATE USER e ALTER USER; por exemplo, CREATE USER foo WITH PASSWORD 'segredo';. Por padrão, ou seja, se nenhuma senha for definida, a senha armazenada é nula e a autenticação da senha sempre falha para este usuário. Para restringir o conjunto de usuários que podem se conectar a um determinado banco de dados, os usuários devem ser relacionados na coluna usuário do arquivo pg_hba.conf, conforme explicado na seção anterior.
19.2.3. Autenticação Kerberos Kerberos é um sistema de autenticação segura, padrão da indústria, adequado para computação distribuída em redes públicas. A descrição do sistema Kerberos está muito acima do escopo deste documento; de forma geral pode ser bastante complexo (porém poderoso). As páginas Kerberos: The Network Authentication Protocol (http://web.mit.edu/kerberos/) e MIT Project Athena (ftp://athena-dist.mit.edu) podem ser um bom ponto de partida para estudá-lo. Existem diversas fontes de distribuição do Kerberos. Embora o PostgreSQL suporte tanto o Kerberos 4 quanto o Kerberos 5, somente o Kerberos 5 é recomendado. O Kerberos 4 é considerado inseguro não sendo mais recomendado para uso geral. Para o Kerberos poder ser utilizado, o seu suporte deve estar ativo em tempo de construção. Veja o Capítulo 14 para obter mais informações. Tanto o Kerberos 4 quanto 5 são suportados, mas apenas uma versão pode ser suportada em uma construção. O PostgreSQL opera como um serviço Kerberos normal. O nome do serviço principal é nome_do_serviço/nome_do_hospedeiro@domínio, onde nome_do_serviço é postgres (a menos que um nome de serviço diferente tenha sido selecionado em tempo de configuração utilizando ./configure --with-krb-srvnam=qualquer_coisa). O nome_do_hospedeiro é o nome de hospedeiro totalmente qualificado da máquina servidora. O domínio do serviço principal é o domínio preferido da máquina servidora. Os principais 1 dos clientes devem ter seu nome de usuário do PostgreSQL como primeiro componente como, por exemplo, pgusername/otherstuff@dominio. Atualmente o domínio do cliente não é verificado pelo PostgreSQL; portanto, havendo autenticação entre domínios ativa, então todo principal de qualquer domínio que puder se comunicar com o utilizado será aceito. Certifique-se que o arquivo de chaves do servidor é legível (e preferencialmente somente legível) pela conta do servidor PostgreSQL (Veja também a Seção 16.1). O local do arquivo de chaves é especificado pelo parâmetro de configuração em tempo de execução krb_server_keyfile (Veja também a Seção 16.4). O padrão é /etc/srvtab se estiver sendo utilizado o Kerberos 4, e FILE:/usr/local/pgsql/etc/krb5.keytab (o ou diretório especificado como sysconfdir em tempo de construção) no Kerberos 5. Para gerar o arquivo keytab deve ser utilizado, por exemplo (com a versão 5): kadmin% ank -randkey postgres/server.my.domain.org
304
kadmin% ktadd -k krb5.keytab postgres/server.my.domain.org
Leia a documentação do Kerberos para obter detalhes. Ao se conectar ao banco de dados tenha certeza de possuir um tíquete para o principal correspondendo ao nome de usuário do banco de dados. Como exemplo: Para o nome de usuário do banco de dados cecilia, tanto o principal [email protected] ou cecilia/[email protected] podem ser utilizados para se autenticar ao servidor de banco de dados. Se for utilizado o módulo mod_auth_kerb de Kerberos Module for Apache (http://modauthkerb.sf.net) e mod_perl no servidor Web Apache, pode ser utilizado AuthType KerberosV5SaveCredentials no script mod_perl, proporcionando um acesso seguro ao banco de dados através da Web, sem necessidade de senhas extras.
19.2.4. Autenticação baseada no Ident O método de autenticação ident funciona inspecionando o nome de usuário do sistema operacional do cliente, e determinando os nomes de usuário do banco de dados permitidos utilizando um arquivo de mapa que relaciona os pares de nomes de usuários correspondentes permitidos. A determinação do nome de usuário do cliente é o ponto crítico da segurança, funcionando de forma diferente dependendo do tipo de conexão. 19.2.4.1. Autenticação Ident através de TCP/IP O “Protocolo de Identificação” está descrito no RFC 1413. Virtualmente todo sistema operacional da família Unix é fornecido com um servidor ident que ouve a porta TCP 113 por padrão. A funcionalidade básica do servidor ident é responder a perguntas como “Que usuário inicializou a conexão saindo pela sua porta X se conectando na minha porta Y?”. Uma vez que o PostgreSQL conhece tanto X quanto Y quando a conexão física é estabelecida, pode fazer a pergunta ao servidor ident no hospedeiro do cliente se conectando e pode, teoricamente, determinar o usuário do sistema operacional para uma determinada conexão desta maneira. O problema deste procedimento é que depende da integridade do cliente: se a máquina cliente não for confiável ou estiver comprometida, alguém querendo fazer um ataque pode executar algum programa na porta 113 e retornar qualquer nome de usuário desejado. Este método de autenticação é, portanto, apropriado apenas para redes fechadas onde toda máquina cliente está sob controle rígido, e onde os administradores do sistema e do banco de dados trabalham de forma integrada. Em outras palavras, é necessário confiar na máquina executando o servidor ident. Observe a advertência: RFC 1413 O Protocolo de Identificação não tem intenção de ser um protocolo de autorização ou de controle de acesso.
19.2.4.2. Autenticação Ident através de soquetes locais Nos sistemas que suportam as requisições SO_PEERCRED para os soquetes do domínio Unix (atualmente Linux, FreeBSD, NetBSD, OpenBSD e BSD/OS), a autenticação ident também pode ser aplicada para as conexões locais. Neste caso nenhum risco à segurança é introduzido pela utilização da autenticação ident; na verdade, é a escolha preferida para as conexões locais nestes sistemas. Em sistemas que não aceitam a requisição SO_PEERCRED, a autenticação ident está disponível somente através das conexões TCP/IP. Para superar este problema, é possível especificar o endereço do localhost 127.0.0.1, e se conectar a este endereço. 19.2.4.3. Mapas de Ident Ao utilizar a autenticação baseada no ident, após determinar o nome de usuário do sistema operacional que iniciou a conexão, o PostgreSQL verifica se este usuário pode se conectar como o usuário de banco de dados que está sendo requisitado na conexão. Isto é controlado pelo argumento do mapa de ident que segue a palavra chave ident no arquivo pg_hba.conf. Existe um mapa pré-definido de ident chamado sameuser, que permite todo usuário do sistema operacional se conectar como o usuário de banco de dados com o mesmo nome (se o último existir). Os outros mapas devem ser criados manualmente. Os mapas de ident além do sameuser são definidos no arquivo pg_ident.conf no diretório de dados, contendo linhas com a forma geral:
305
nome_do_mapa nome_de_usuário_do_ident nome_de_usuário_do_banco_de_dados
Os comentários e os espaços em branco são tratados da maneira habitual. O nome_do_mapa é um nome arbitrário a ser utilizado para fazer referência ao mapa em pg_hba.conf. Os outros dois campos especificam qual usuário do sistema operacional é permitido se conectar como qual usuário do banco de dados. O mesmo nome_do_mapa pode ser utilizado repetidamente para especificar mais mapeamentos de usuários dentro de um único mapa. Não existe restrição com respeito a quantos usuários do banco de dados um determinado usuário do sistema operacional pode corresponder, nem vice-versa. O arquivo pg_ident.conf é lido na inicialização e quando o processo servidor principal (postmaster) recebe um sinal SIGHUP. Se o arquivo for editado com o sistema ativo, será necessário enviar este sinal para o postmaster (utilizando pg_ctl reload ou kill -HUP) para fazer o arquivo ser lido novamente. O arquivo pg_ident.conf que pode ser utilizado em conjunto com o arquivo pg_hba.conf do Exemplo 191 está mostrado no Exemplo 19-2. Nesta configuração de exemplo, qualquer um logado em uma máquina da rede 192.168 que não possua o nome de usuário Unix oliveira, lia ou andre não vai ter o acesso concedido. O usuário Unix andre somente poderá acessar quando tentar se conectar como o usuário do PostgreSQL pacheco, e não como andre ou algum outro. A usuária lia somente poderá se conectar como lia. O usuário oliveira poderá se conectar como o próprio oliveira ou como guest1. Exemplo 19-2. Arquivo pg_ident.conf de exemplo # MAPNAME
IDENT-USERNAME
PG-USERNAME
omicron oliveira oliveira omicron lia lia # pacheco possui o nome de usuário andre nestas máquinas omicron andre pacheco # oliveira também pode se conectar como guest1 omicron oliveira guest1
19.2.5. Autenticação PAM Este método de autenticação opera de forma semelhante ao método password, exceto por utilizar o mecanismo de autenticação PAM (Pluggable Authentication Modules). O nome padrão do serviço PAM é postgresql. É possível, opcionalmente, fornecer um outro nome de serviço após a palavra chave pam no arquivo pg_hba.conf. Para obter mais informações sobre o PAM por favor leia a Página Linux-PAM (http://www.kernel.org/pub/linux/libs/pam/) e a Página Solaris PAM (http://www.sun.com/software/solaris/pam/).
19.3. Problemas de autenticação Falhas de autenticação genuínas e problemas correlatos geralmente se manifestam através de mensagens de erro como as que se seguem. FATAL:
no pg_hba.conf entry for host "123.123.123.123", user "andym", database "testdb"
Esta é a mensagem mais provável de ocorrer quando o contato com o servidor for bem-sucedido, mas este não desejar falar com o cliente. Como a própria mensagem sugere, o servidor recusou a requisição de conexão porque não encontrou uma entrada autorizando esta conexão no arquivo de configuração pg_hba.conf. FATAL:
Password authentication failed for user "andym"
As mensagens deste tipo indicam que o servidor foi contactado, e este deseja se comunicar com o cliente, mas não até que seja transposto o método de autorização especificado no arquivo pg_hba.conf. Verifique a senha sendo fornecida, ou verifique o programa Kerberos ou ident se for mencionado algum destes tipos de autenticação na mensagem de erro. FATAL:
user "andym" does not exist
306
O nome de usuário indicado não foi encontrado. FATAL:
database "testdb" does not exist
Tentativa de conectar a um banco de dados que não existe. Observe que se não for especificado o nome do banco de dados é usado, por padrão, o banco de dados com mesmo nome do usuário, o que poder ser correto ou não. Dica: O log do servidor pode conter mais informações sobre uma falha de autenticação do que o informado ao cliente. Estando confuso sobre o motivo da falha, verifique o log.
Notas 1. O Kerberos é um sistema de autenticação de terceiros confiável, cuja finalidade principal é permitir pessoas e processos (conhecidos no Kerberos como principais) provarem suas identidades de uma maneira confiável através de redes não seguras. Em vez de transmitir as senhas secretas em aberto, que podem ser interceptadas e lidas por pessoas não autorizadas, os principais obtêm vouchers (conhecidos como tíquetes) do Kerberos, utilizados para se autenticar. Kerberos Concepts and Terms (http://www.net.berkeley.edu/kerberos/k5concepts.html). (N. do T.)
307
Capítulo 20. Localização Este capítulo descreve as funcionalidades de localização disponíveis do ponto de vista do administrador. O PostgreSQL suporta a localização com base em dois enfoques: •
Utilizando as funcionalidades de localização do sistema operacional para fornecer ordem de classificação, formatação de números, tradução das mensagens, e outros aspectos específicos da localização.
•
Fornecendo vários conjuntos de caracteres diferentes definidos no servidor PostgreSQL, incluindo conjuntos de caracteres de vários bytes, para suportar textos em todos os tipos de linguagem, e fornecendo a tradução de conjuntos de caracteres entre o cliente e o servidor.
20.1. Suporte a localização O suporte a localização se refere a uma aplicação respeitando as preferências culturais com relação ao alfabeto, classificação, formatação de número, etc. O PostgreSQL utiliza as facilidades de localização padrão ISO C e POSIX fornecidas pelo sistema operacional do servidor. Para obter informações adicionais consulte a documentação do sistema.
20.1.1. Visão geral O suporte a localização é inicializado automaticamente quando o agrupamento de bancos de dados é criado utilizando o initdb. O initdb inicializa o agrupamento de bancos de dados com a definição de localização do ambiente onde executa; portanto, se o sistema operacional estiver definido para utilizar a mesma localização que se deseja no agrupamento de bancos de dados, então não precisa ser feito mais nada. Se for desejado utilizar uma localização diferente (ou não há certeza de qual localização está definida no sistema operacional), pode ser informado ao initdb qual é a localização desejada através da opção --locale. Por exemplo: initdb --locale=pt_BR
Este exemplo define a localização para Português (pt) conforme falado no Brasil (BR). Outras possibilidades são en_US (Inglês dos Estados Unidos) e fr_CA (Francês do Canadá). Se puder ser utilizado mais de um conjunto de caracteres para a localização, então a especificação ficará parecida com esta: pt_BR.ISO8859-1. Quais localizações estão disponíveis sob quais nomes no sistema operacional depende do que é disponibilizado pelo distribuidor do sistema operacional e do que foi instalado. Ocasionalmente é útil a mistura de regras de várias localizações como, por exemplo, regras de classificação do Inglês com mensagens em Português. Para ser possível, existe um conjunto de subcategorias de localização que controlam somente certos aspectos das regras de localização. LC_COLLATE
Ordem de agrupamento das cadeias de caracteres a b
LC_CTYPE
Classificação dos caracteres (O que é letra? A letra maiúscula equivalente?) c
LC_MESSAGES
Linguagem das mensagens
LC_MONETARY
Formatação das quantias monetárias
LC_NUMERIC
Formatação dos números
LC_TIME
Formatação das data e das horas
Notas: a. collation; collating sequence — Um método para comparar duas cadeias de caracteres comparáveis. Todo conjunto de caracteres possui seu collation padrão. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992. (N. do T.) b. SQL Server — collation: se refere ao conjunto de regras que determinam como os dados são classificados e comparados. Microsoft SQL Server 2000 Introduction - Part No. X05-88268. (N. do T.) c. LC_CTYPE — Define a classificação do caractere, conversão maiúscula/minúscula, e outros atributos do caractere. LC_CTYPE Category for the Locale Definition Source File Format (http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/files/aixfiles/LC_CTYPE.htm) (N. do T.)
308
Os nomes das categorias se traduzem em nomes de opção do initdb, que substituem a escolha de localização para uma determinada categoria. Por exemplo, para definir a localização Francês do Canadá, mas utilizar as regras dos E.U.A para formatar valores monetários, deve ser utilizado initdb --locale=fr_CA --lcmonetary=en_US. Se for desejado que o sistema se comporte como se não tivesse suporte a localização, devem ser utilizadas as localizações especiais C ou POSIX. A propriedade de algumas categorias de localização é que seus valores devem ser fixos por toda a existência do agrupamento de bancos de dados. Ou seja, uma vez executado o initdb, estas não podem mais ser mudadas. Estas categorias são LC_COLLATE e LC_CTYPE. Afetam a ordem de classificação dos índices e, portanto, devem permanecer fixas, ou os índices das colunas texto se tornarão corrompidos. O PostgreSQL garante isto registrando os valores de LC_COLLATE e LC_CTYPE em tempo de initdb. O servidor adota, automaticamente, estes valores quando é inicializado. As outras categorias de localização podem ser modificadas, conforme se desejar, definindo as variáveis de configuração em tempo de execução que possuem o mesmo nome das categorias de localização (veja a Seção 16.4 para obter detalhes). Os padrões escolhidos pelo initdb na verdade são apenas escritos no arquivo de configuração postgresql.conf para servir como padrão quando o servidor é inicializado. Se forem removidas as atribuições presentes no arquivo postgresql.conf, então o servidor herdará as definições do ambiente de execução. Observe que o comportamento de localização do servidor é determinado pelas variáveis de ambiente enxergadas pelo servidor, e não pelo ambiente de qualquer um dos clientes. Portanto, tome o cuidado de configurar definições corretas de localização antes de inicializar o servidor. Uma conseqüência deste fato é que, se o cliente e o servidor forem configurados com localizações diferentes, as mensagens poderão aparecer em linguagens diferentes dependendo de onde forem originadas. Nota: Quando se fala em herdar a localização do ambiente de execução, isto significa o seguinte para a maioria dos sistemas operacionais: Para uma determinada categoria de localização, como o agrupamento, as seguintes variáveis de ambiente são consultadas, nesta ordem, até ser encontrada uma com valor definido: LC_ALL, LC_COLLATE (a variável correspondente à respectiva categoria) e LANG. Se nenhuma destas variáveis de ambiente estiver definida, então a localização usada é a C por padrão. Algumas bibliotecas de localização de mensagem também examinam a variável de ambiente LANGUAGE, que prevalece sobre todas as outras definições de localização para a finalidade de definir a linguagem das mensagens. Em caso de dúvida, por favor consulte a documentação do sistema operacional, em particular a documentação sobre gettext, para obter mais informações.
Para habilitar mensagens traduzidas para a linguagem preferida do usuário, o NLS (suporte a linguagem nacional) deve estar habilitado em tempo de construção. Esta escolha independe de outros suportes a localização.
20.1.2. Benefícios O suporte a localização influencia particularmente as seguintes funcionalidades: •
Ordem de classificação nas consultas utilizando ORDER BY.
•
A família de funções to_char.
O único problema sério na utilização do suporte a localização no PostgreSQL é o seu desempenho. Portanto, a utilização da localização somente deve ser feita se for realmente necessária.
20.1.3. Problemas Se o suporte a localização não funcionar a despeito do que foi explicado acima, verifique se o suporte a localização no sistema operacional está corretamente configurado. Para verificar quais localizações estão instaladas no sistema operacional, pode ser utilizado o comando locale -a se o sistema operacional disponibilizá-lo. 1 Verifique se o PostgreSQL está realmente utilizando a localização que se pensa que está utilizando. As definições de LC_COLLATE e LC_CTYPE são determinadas em tempo de initdb não podendo ser mudadas sem executar o initdb novamente. Outras definições de localização, incluindo LC_MESSAGES e LC_MONETARY são
309
determinadas inicialmente a partir do ambiente onde o servidor é inicializado. Podem ser verificadas as definições de LC_COLLATE e LC_CTYPE do banco de dados utilizando o programa utilitário pg_controldata. O diretório src/test/locale na distribuição do código fonte contém um conjunto de testes para o suporte a localização do PostgreSQL. As aplicações cliente que tratam os erros do lado servidor analisando o texto da mensagem de erro, obviamente terão problemas quando as mensagens do servidor estiverem em outra linguagem. Os autores destas aplicações ficam avisados que devem utilizar o esquema de códigos de erro em seu lugar. A manutenção de catálogos de mensagens traduzidas requer o esforço contínuo de muitos voluntários que desejam ver o PostgreSQL falando bem a sua língua. Se as mensagens na sua língua não estiverem disponíveis atualmente, ou se não estiverem totalmente traduzidas, sua ajuda será apreciada. Se desejar ajudar, consulte o Capítulo 46 ou escreva para a lista de discussão dos desenvolvedores.
20.2. Suporte a conjuntos de caracteres O suporte no PostgreSQL a conjuntos de caracteres permite o armazenamento de texto usando vários conjuntos de caracteres, incluindo conjuntos de caracteres de um único byte tal como a série ISO 8859, e conjuntos de caracteres com múltiplos bytes tais como o EUC (Extended Unix Code), Unicode e o código interno Mule. Todos os conjuntos de caracteres podem ser utilizados de forma transparente no servidor (Se forem utilizadas funções de extensão de terceiros, vai depender se o código foi escrito da forma correta). O conjunto de caracteres padrão é selecionado durante a inicialização do agrupamento de bancos de dados do PostgreSQL utilizando o initdb. Pode ser mudado ao se criar o banco de dados utilizando o comando createdb ou utilizando o comando SQL CREATE DATABASE. Portanto, podem haver vários bancos de dados, cada um com um conjunto de caracteres diferentes.
20.2.1. Conjuntos de caracteres suportados A Tabela 20-1 mostra os conjuntos de caracteres disponíveis para uso no servidor. Tabela 20-1. Conjuntos de caractere do servidor Nome
Descrição
SQL_ASCII
ASCII
EUC_JP
EUC Japonês
EUC_CN
EUC Chinês
EUC_KR
EUC Coreano
JOHAB
EUC Coreano (baseado em Hangle)
EUC_TW
EUC Tailandês
UNICODE
Unicode (UTF-8) a
MULE_INTERNAL
Código interno Mule
LATIN1
ISO 8859-1/ECMA 94 (Alfabeto latino nº 1)
LATIN2
ISO 8859-2/ECMA 94 (Alfabeto latino nº 2)
LATIN3
ISO 8859-3/ECMA 94 (Alfabeto latino nº 3)
LATIN4
ISO 8859-4/ECMA 94 (Alfabeto latino nº 4)
LATIN5
ISO 8859-9/ECMA 128 (Alfabeto latino nº 5)
LATIN6
ISO 8859-10/ECMA 144 (Alfabeto latino nº 6)
LATIN7
ISO 8859-13 (Alfabeto latino nº 7)
LATIN8
ISO 8859-14 (Alfabeto latino nº 8)
310
Nome
Descrição
LATIN9
ISO 8859-15 (Alfabeto latino nº 9)
LATIN10
ISO 8859-16/ASRO SR 14111 (Alfabeto latino nº 10)
ISO_8859_5
ISO 8859-5/ECMA 113 (Latino/Cirílico)
ISO_8859_6
ISO 8859-6/ECMA 114 (Latino/Arábico)
ISO_8859_7
ISO 8859-7/ECMA 118 (Latino/Grego)
ISO_8859_8
ISO 8859-8/ECMA 121 (Latino/Hebreu)
KOI8
KOI8-R(U)
WIN
Windows CP1251
ALT
Windows CP866
WIN1256
Windows CP1256 (Arábico)
TCVN
TCVN-5712/Windows CP1258 (Vietnamês)
WIN874
Windows CP874 (Thai)
Notas: a. UTF8 é a forma de codificação de caractere especificada na ISO/IEC 10646-1, Anexo D, na qual cada caractere é codificado de um a quatro octetos. (ISO-ANSI Working Draft) Foundation (SQL/Foundation), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.) Importante: Antes do PostgreSQL 7.2, LATIN5 por engano significava ISO 8859-5. A partir da versão 7.2 LATIN5 passou a significar ISO 8859-9. Havendo um banco de dados LATIN5 criado na versão 7.1 ou anterior, e se deseja migrar para a versão 7.2 ou posterior, deve ser tomado cuidado com relação a esta modificação.
Nem todas as APIs suportam todos os conjuntos de caracteres relacionados. Por exemplo, o driver de JDBC do PostgreSQL não suporta MULE_INTERNAL, LATIN6, LATIN8 e LATIN10.
20.2.2. Definição do conjunto de caracteres O initdb define o conjunto de caracteres padrão para o agrupamento do PostgreSQL. Por exemplo, initdb -E EUC_JP
define o conjunto de caracteres padrão (codificação) como EUC_JP (Código Unix Estendido para Japonês). Pode ser utilizado --encoding em vez de -E, se for preferido digitar as cadeias de caracteres das opções longas. Se nem a opção -E nem a opção --encoding for fornecida, é utilizado SQL_ASCII. Pode ser criado um banco de dados com um conjunto de caracteres diferente: createdb -E EUC_KR coreano
Este comando cria um banco de dados chamado coreano que utiliza o conjunto de caracteres EUC_KR. Outra forma de se fazer é através do comando SQL: CREATE DATABASE coreano WITH ENCODING 'EUC_KR';
A codificação para o banco de dados é armazenada no catálogo do sistema pg_database. Pode ser vista utilizando a opção -l ou o comando \l do psql. $ psql -l
311
List of databases Database | Owner | Encoding ---------------+---------+--------------euc_cn | t-ishii | EUC_CN euc_jp | t-ishii | EUC_JP euc_kr | t-ishii | EUC_KR euc_tw | t-ishii | EUC_TW mule_internal | t-ishii | MULE_INTERNAL regression | t-ishii | SQL_ASCII template1 | t-ishii | EUC_JP test | t-ishii | EUC_JP unicode | t-ishii | UNICODE (9 linhas)
20.2.3. Conversão automática do conjunto de caracteres entre cliente e servidor O PostgreSQL suporta conversão automática do conjunto de caracteres entre o cliente e o servidor para determinados conjuntos de caracteres. A informação de conversão é armazenada no catálogo do sistema pg_conversion. Podem ser criadas novas conversões utilizando o comando CREATE CONVERSION. O PostgreSQL vem com algumas conversões pré-definidas, conforme listado na Tabela 20-2. Tabela 20-2. Conversões de conjuntos de caracteres cliente/servidor Conjunto de caracteres do servidor
Conjuntos de caracteres do cliente disponíveis
SQL_ASCII
SQL_ASCII, UNICODE, MULE_INTERNAL
EUC_JP
EUC_JP, SJIS, UNICODE, MULE_INTERNAL
EUC_CN
EUC_CN, UNICODE, MULE_INTERNAL
EUC_KR
EUC_KR, UNICODE, MULE_INTERNAL
JOHAB
JOHAB, UNICODE
EUC_TW
EUC_TW, BIG5, UNICODE, MULE_INTERNAL
LATIN1
LATIN1, UNICODE MULE_INTERNAL
LATIN2
LATIN2, WIN1250, UNICODE, MULE_INTERNAL
LATIN3
LATIN3, UNICODE, MULE_INTERNAL
LATIN4
LATIN4, UNICODE, MULE_INTERNAL
LATIN5
LATIN5, UNICODE
LATIN6
LATIN6, UNICODE, MULE_INTERNAL
LATIN7
LATIN7, UNICODE, MULE_INTERNAL
LATIN8
LATIN8, UNICODE, MULE_INTERNAL
LATIN9
LATIN9, UNICODE, MULE_INTERNAL
LATIN10
LATIN10, UNICODE, MULE_INTERNAL
ISO_8859_5
ISO_8859_5, UNICODE, MULE_INTERNAL, WIN, ALT, KOI8
ISO_8859_6
ISO_8859_6, UNICODE
ISO_8859_7
ISO_8859_7, UNICODE
ISO_8859_8
ISO_8859_8, UNICODE
312
Conjunto de caracteres do servidor
Conjuntos de caracteres do cliente disponíveis
UNICODE
EUC_JP, SJIS, EUC_KR, UHC, JOHAB, EUC_CN, GBK, EUC_TW, BIG5, LATIN1 to LATIN10, ISO_8859_5, ISO_8859_6, ISO_8859_7, ISO_8859_8, WIN, ALT, KOI8, WIN1256, TCVN, WIN874, GB18030, WIN1250
MULE_INTERNAL
EUC_JP, SJIS, EUC_KR, EUC_CN, EUC_TW, BIG5, LATIN1 to LATIN5, WIN, ALT, WIN1250, BIG5, ISO_8859_5, KOI8
KOI8
ISO_8859_5, WIN, ALT, KOI8, UNICODE, MULE_INTERNAL
WIN
ISO_8859_5, WIN, ALT, KOI8, UNICODE, MULE_INTERNAL
ALT
ISO_8859_5, WIN, ALT, KOI8, UNICODE, MULE_INTERNAL
WIN1256
WIN1256, UNICODE
TCVN
TCVN, UNICODE
WIN874
WIN874, UNICODE
Para habilitar a conversão automática entre os conjuntos de caracteres, deve ser informado ao PostgreSQL o conjunto de caracteres (codificação) que se deseja utilizar no cliente. Existem diversas maneiras de fazer: •
Utilizando o comando \encoding no psql. O \encoding permite mudar a codificação do cliente dinamicamente. Por exemplo, para mudar a codificação para SJIS deve ser executado: \encoding SJIS
•
Utilizando as funções da libpq. O \encoding na verdade chama PQsetClientEncoding() para esta finalidade. int PQsetClientEncoding(PGconn *conn, const char *encoding);
onde conn é a conexão com o servidor, e encoding é a codificação que se deseja utilizar. Se for bemsucedida a definição da codificação pela função, esta retorna 0, senão -1. A codificação corrente para a conexão pode ser obtida utilizando: int PQclientEncoding(const PGconn *conn);
Observe que é retornado o ID da codificação, e não uma cadeia de caracteres simbólica como EUC_JP. Para converter o ID da codificação no nome da codificação, deve ser utilizado: char *pg_encoding_to_char(int encoding_id); •
Utilizando o comando SET client_encoding TO. A definição da codificação do cliente pode ser feita através do comando SQL: SET CLIENT_ENCODING TO 'valor';
Também pode ser utilizada a sintaxe padrão SQL SET NAMES para esta finalidade: SET NAMES 'valor';
Para consultar a codificação corrente do cliente: SHOW client_encoding;
Para voltar à codificação padrão: RESET client_encoding; •
Utilizando a variável de ambiente PGCLIENTENCODING. Se a variável de ambiente PGCLIENTENCODING estiver definida no ambiente do cliente, esta codificação de cliente é automaticamente selecionada quando a conexão ao servidor é feita (Pode ser mudada depois utilizando um dos métodos mencionados acima).
•
Utilizando a variável de configuração client_encoding. Se a variável client_encoding estiver definida no arquivo postgresql.conf, esta codificação do cliente é automaticamente selecionada quando é feita a conexão ao servidor (Pode ser mudada depois utilizando um dos métodos mencionados acima).
313
Se a conversão de um determinado caractere não for possível -- suponha que seja escolhido EUC_JP para o servidor e LATIN1 para o cliente, então alguns caracteres Japoneses não poderão ser convertidos em LATIN1 -este é transformado nos valores hexadecimais dos bytes entre parênteses como, por exemplo, (826C).
20.2.4. Leitura adicional Abaixo estão mostradas várias fontes boas para começar a aprender os vários tipos de sistema de codificação. ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/cjk.inf Explicações detalhadas sobre EUC_JP, EUC_CN, EUC_KR, EUC_TW estão mostradas na seção 3.2. http://www.unicode.org/ O sítio na Web do Consórcio Unicode RFC 2044 Onde o UTF-8 é definido.
Notas 1. O comando locale -a executado no Fedora Core 1 mostrou a seguinte relação: af_ZA, af_ZA.iso88591, an_ES, an_ES.iso885915, ..., portuguese, POSIX, pt_BR, pt_BR.iso88591, pt_BR.utf8, pt_PT, pt_PT@euro, pt_PT.iso88591, pt_PT.iso885915@euro, pt_PT.utf8, pt_PT.utf8@euro, ..., zu_ZA, zu_ZA.iso88591, zu_ZA.utf8. (N. do T.)
314
Capítulo 21. Rotinas de manutenção do banco de dados Existem poucas rotinas de manutenção que precisam ser realizadas regularmente para manter o servidor PostgreSQL funcionando adequadamente. As tarefas mostradas neste capítulo são repetitivas por natureza, podendo ser facilmente automatizadas utilizando as ferramentas padrão do Unix como os scripts do cron. É responsabilidade do administrador do banco de dados configurar os scripts apropriados, e verificar se a execução está sendo bem-sucedida. Uma tarefa de manutenção óbvia é a criação das cópias de segurança dos dados em períodos regulares. Sem uma cópia de segurança recente, não há como fazer a recuperação após uma catástrofe (falha de disco, incêndio, remoção por engano de uma tabela crítica, etc.). Os mecanismos de cópia de segurança e restauração disponíveis no PostgreSQL estão mostrados de forma abrangente no Capítulo 22. Outra categoria principal de tarefa de manutenção é a limpeza periódica do banco de dados. Esta atividade está mostrada na Seção 21.1. Outro item que pode precisar de atenção periódica é o gerenciamento do arquivo de log. Isto está mostrado na Seção 21.3. O PostgreSQL necessita de pouca manutenção se comparado com outros sistemas gerenciadores de bancos de dados. Apesar disso, uma atenção apropriada a estas tarefas vai muito além de garantir uma experiência agradável e produtiva do sistema.
21.1. Rotina de Limpeza O comando VACUUM do PostgreSQL deve ser executado regularmente por diversos motivos: 1. Para recuperar o espaço em disco ocupado pelas linhas atualizadas e removidas. 2. Para atualizar as estatísticas utilizadas pelo planejador de comandos do PostgreSQL. 3. Para proteger contra perda de dados muito antigos devido ao recomeço do ID de transação. A freqüência e a abrangência das operações de VACUUM, realizadas por causa dos motivos acima, variam dependendo das necessidades da instalação. Portanto, os administradores de bancos de dados devem compreender estas questões e desenvolver uma estratégia de manutenção apropriada. Esta seção se concentra em explicar questões de alto nível; para obter detalhes sobre a sintaxe do comando e outras informações veja a página de referência do comando VACUUM. A partir do PostgreSQL 7.2 a forma padrão do comando VACUUM pode executar em paralelo com as operações normais do banco de dados (seleções, inserções, atualizações, exclusões, mas sem modificação das definições das tabelas). Portanto, a rotina de limpeza não é mais tão intrusiva como era nas versões anteriores, não sendo mais tão crítico tentar agendá-la para as horas do dia com baixa utilização.
21.1.1. Recuperação do espaço em disco Na operação normal do PostgreSQL, um comando UPDATE ou DELETE executado em uma linha não remove imediatamente a versão antiga da linha. Este enfoque é necessário para obter os benefícios do controle de simultaneidade multi-versão (veja o Capítulo 12): a versão da linha não pode ser removida enquanto houver possibilidade de ser enxergada por outras transações. Mas por fim uma versão de linha desatualizada ou excluída não tem mais interesse para nenhuma transação. O espaço ocupado deve ser recuperado para ser reutilizado pelas novas linhas, para evitar um crescimento sem fim da necessidade de espaço em disco. Isto é feito executando o comando VACUUM. Obviamente, uma tabela que sofre atualizações ou exclusões freqüentes necessita ser limpa mais vezes do que uma tabela que é atualizada raramente. Pode ser útil definir tarefas periódicas no cron para limpar apenas determinadas tabelas, omitindo as tabelas sabidamente pouco modificadas. Provavelmente, este procedimento é útil apenas quando há tanto tabelas muito atualizadas quanto tabelas raramente atualizadas --- o custo extra para limpar uma tabela pequena não é suficiente para valer a pena se preocupar.
315
A forma padrão do comando VACUUM é melhor empregada com o objetivo de manter o nível de utilização de espaço em disco razoavelmente estável. A forma padrão encontra as versões antigas das linhas e torna seus espaços disponíveis para ser utilizado novamente dentro da tabela, mas não faz muito esforço para diminuir o tamanho do arquivo da tabela e devolver o espaço em disco para o sistema operacional. Se for necessário devolver espaço em disco para o sistema operacional deve ser utilizado o comando VACUUM FULL --- mas qual é a vantagem de liberar espaço em disco que deverá ser alocado novamente em breve? Execuções do comando VACUUM padrão com freqüência moderada é uma abordagem melhor do que a execução do comando VACUUM FULL com baixa freqüência, para manutenção das tabelas muito atualizadas. A prática recomendada para a maioria das instalações é agendar o comando VACUUM para todo o banco de dados uma vez por dia em horário de pouca utilização, suplementado por limpezas mais freqüentes das tabelas muito atualizadas se for necessário (Havendo vários bancos de dados em uma agregação, não se esqueça de limpar todos; o programa vacuumdb pode ser útil). Deve ser utilizado o VACUUM simples, e não o VACUUM FULL, para recuperação rotineira de espaço. O comando VACUUM FULL é recomendado para os casos onde se sabe que foi excluída a maior parte das linhas da tabela e, portanto, o tamanho da tabela pode ser reduzido substancialmente pela abordagem mais agressiva do comando VACUUM FULL. Havendo uma tabela cujo conteúdo é excluído completamente com freqüência, deve ser considerada a execução do comando TRUNCATE em vez de utilizar DELETE seguido por VACUUM.
21.1.2. Atualização das estatísticas do planejador O planejador de comandos do PostgreSQL confia nas informações estatísticas sobre os conteúdos das tabelas para poder gerar bons planos para os comandos. Estas estatísticas são coletadas pelo comando ANALYZE, que pode ser chamado isoladamente ou como um passo opcional do comando VACUUM. É importante que as estatísticas estejam razoavelmente precisas, senão planos mal escolhidos poderão degradar o desempenho do banco de dados. Assim como a execução do comando VACUUM para recuperar espaço, atualizações freqüentes das estatísticas são mais úteis em tabelas muito atualizadas do que em as tabelas raramente atualizadas, mas mesmo em uma tabela muito atualizada pode não haver necessidade de atualizar as estatísticas, se a distribuição dos dados não mudar muito. Uma regra empírica simples é pensar sobre quanto os valores mínimo e máximo das colunas da tabela mudam. Por exemplo, uma coluna timestamp contendo a data e hora da atualização da linha terá um valor máximo aumentando constantemente enquanto existirem linhas sendo atualizadas ou adicionadas; este tipo de coluna, provavelmente, precisa de atualizações mais freqüentes das estatísticas do que, digamos, uma coluna contendo URLs de páginas acessadas em sítios da Web. A coluna URL pode ser modificada com a mesma freqüência, mas a distribuição estatística de seus valores provavelmente muda de forma relativamente lenta. É possível executar o comando ANALYZE em tabelas específicas, e mesmo em colunas específicas da tabela. Portanto, existe flexibilidade para atualizar algumas estatísticas mais freqüentemente do que outras se for requerido pela aplicação. Na prática, entretanto, a utilidade desta funcionalidade é duvidosa. A partir do PostgreSQL 7.2 o comando ANALYZE se tornou uma operação bem rápida, mesmo em tabelas grandes, porque utiliza amostragem estatística randômica das linhas da tabela em vez de ler todas as linhas. Portanto, provavelmente é muito mais fácil simplesmente executá-lo para todo o banco de dados na freqüência necessária. Dica: Embora variar a freqüência da execução do comando ANALYZE por coluna não seja muito produtivo, pode valer muito a pena fazer ajustes por coluna no nível de detalhe das estatísticas coletadas pelo comando ANALYZE. As colunas muito utilizadas na cláusula WHERE, contendo distribuição dos dados muito irregular, podem requerer um histograma dos dados com granulação mais fina do que as outras colunas. Veja o comando ALTER TABLE SET STATISTICS.
A prática recomendada, para a maioria das instalações, é agendar a execução do comando ANALYZE para todo o banco de dados uma vez por dia, em horário de pouca utilização; é útil sua combinação com a execução do comando VACUUM todas as noites. Entretanto, nas instalações onde as estatísticas das tabelas mudam de forma relativamente lenta pode-se achar que seja em demasia, e que a execução do comando ANALYZE com freqüência mais baixa seja suficiente.
316
21.1.3. Prevenção de falhas devido ao reinício do ID de transação A semântica da transação do MVCC do PostgreSQL depende de poder comparar números de ID de transação (XID): uma versão de linha com XID de inserção maior do que o XID da transação corrente está “no futuro”, não devendo ser visível pela transação corrente. Como os IDs de transação possuem tamanho limitado (32 bits quando esta documentação foi escrita), um agrupamento em funcionamento por um longo período de tempo (mais de 4 bilhões de transações) sofre um reinício do ID de transação: o contador do XID volta a zero e, de repente, a transações que estavam no passado parecem estar no futuro --- o que significa que suas saídas se tornam invisíveis. Em resumo, uma perda de dados catastrófica (Na verdade os dados ainda estão lá, mas isto não serve de consolo se não for possível acessá-los). Antes do PostgreSQL 7.2 a única defesa contra o reinício do XID era executar novamente o initdb pelo menos a cada 4 bilhões de transações. É claro que não era muito satisfatório para instalações com alto tráfego, portanto uma solução melhor foi concebida. A nova abordagem permite o servidor permanecer ativo indefinidamente, sem executar o initdb ou qualquer forma de reinício. O preço é esta necessidade de manutenção: todas as tabelas do banco de dados devem ser VACUUM-nizadas pelo menos uma vez a cada um bilhão de transações. Na prática este não é um requisito oneroso, mas uma vez que a conseqüência de não respeitá-lo pode ser a perda total dos dados (e não apenas desperdício de espaço em disco ou degradação do desempenho), foram introduzidos alguns dispositivos especiais para ajudar os administradores de bancos de dados a controlar quando o comando VACUUM foi executado pela última vez. O restante desta seção fornece os detalhes. A nova abordagem para comparação de XID faz distinção de dois XIDs especiais, os de número 1 e 2 (BootstrapXID e FrozenXID). Estes dois XIDs são sempre considerados mais antigos do que qualquer XID normal. Os XIDs normais (aqueles maiores que 2) são comparados utilizando a aritmética módulo-231. Isto significa que para todo XID normal existem dois bilhões de XIDs que são “mais antigos” e dois bilhões que são “mais novos”; outra maneira de dizer é que o espaço do XID normal é circular, sem ponto de fim. Portanto, ao ser criada uma versão de linha com um determinado XID normal, esta versão de linha vai parecer estar “no passado” para as próximas dois bilhões de transações, não importando de qual XID normal está se falando. Se a versão da linha ainda existir após mais de dois bilhões transações, de repente vai parecer estar no futuro. Para prevenir contra perda de dados, deve ser atribuído o XID FrozenXID para as versões antigas das linhas algum tempo antes de atingirem a marca “antiga-dois-bilhões-de-transações”. Uma vez que seja atribuído este XID especial, vão parecer estar “no passado” para todas as transações normais, sem levar em consideração os problemas de reinício, e esta versão de linha será válida até ser excluída, não importando quanto demore. Esta reatribuição de XID é tratada pelo comando VACUUM. A política normal do comando VACUUM é atribuir o FrozenXID para toda versão de linha que possua um XID normal antigo com mais de um bilhão de transações de diferença. Esta política preserva o XID original de inserção até que, provavelmente, não seja mais de interesse (Na verdade, a maioria das versões de linha provavelmente vivem e morrem sem que jamais tenham sido “congeladas”). Com esta política, o intervalo máximo seguro entre execuções do comando VACUUM em qualquer tabela é de exatamente um bilhão de transações: se for esperado mais tempo, é possível que uma versão de linha que não era antiga o suficiente para ser congelada da ultima vez, seja agora antiga mais de dois bilhões de transações, e tenha passado para o futuro --- ou seja, foi perdida para você (É claro que vai reaparecer após outros dois bilhões de transações, mas isto não ajuda). Uma vez que a execução periódica do comando VACUUM é necessária de qualquer forma devido aos motivos descritos anteriormente, é improvável que não tenha sido executado o comando VACUUM em qualquer tabela pelo tempo de um bilhão de transações. Para ajudar os administradores a garantir que esta restrição é obedecida, o comando VACUUM armazena estatísticas sobre o ID de transação na tabela do sistema pg_database. Em particular, a coluna datfrozenxid da linha do banco de dados em pg_database é atualizada ao término de toda operação de limpeza de todo o banco de dados (ou seja, o comando VACUUM que não especifica uma determinada tabela). O valor armazenado neste campo é o XID do limite de congelamento que foi utilizado por este comando VACUUM. Para todos os XIDs mais antigos do que este XID limite é garantido que foram substituídos pelo FrozenXID dentro deste banco de dados. Uma maneira conveniente de examinar esta informação é executar a consulta SELECT datname, age(datfrozenxid) FROM pg_database;
317
A coluna age (idade) mede o número de transações desde o XID limite de congelamento até o XID da transação corrente. Usando a política de congelamento padrão, a coluna age começa em um bilhão para um banco de dados onde o comando VACUUM acabou de ser executado. Quando age se aproxima de dois bilhões, deve ser executado novamente o comando VACUUM no banco de dados para evitar o risco da falha devido ao reinício. A prática recomendada é executar o comando VACUUM em todos os bancos de dados pelo menos uma vez a cada meio bilhão (500 milhões) de transações, para que se tenha uma ampla margem de segurança. Para ajudar a seguir esta regra, cada execução do comando VACUUM de todo o banco de dados automaticamente envia uma mensagem se houver alguma entrada em pg_database mostrando uma idade de mais 1,5 bilhões de transações. Por exemplo: play=# VACUUM; WARNING: some databases have not been vacuumed in 1613770184 transactions HINT: Better vacuum them within 533713463 transactions, or you may have a wraparound failure. VACUUM
O comando VACUUM com a opção FREEZE utiliza uma política de congelamento mais agressiva: as versões das linhas são congeladas se forem antigas o suficiente para serem consideradas boas por todas as transações em aberto. Em particular, se o comando VACUUM FREEZE for executado em um banco de dados não utilizado de outra forma, é garantido que todas as versões de linha neste banco de dados serão congeladas. Portanto, enquanto o banco de dados não for modificado de forma alguma, não haverá necessidade de executar o comando VACUUM para evitar o problema de reinício do ID de transação. Esta técnica é utilizada pelo initdb para preparar o banco de dados template0. Também deve ser utilizada para preparar todos os bancos de dados criados pelo usuário a serem marcados com datallowconn = false em pg_database, uma vez que não há nenhuma maneira conveniente de executar o comando VACUUM em um banco de dados em que não se pode conectar. Observe que a mensagem de advertência automática do comando VACUUM sobre bancos de dados não limpos ignoram as entradas de pg_database com datallowconn = false, para evitar emitir falsas advertências sobre estes bancos de dados; portanto, é sua responsabilidade garantir que estes bancos de dados sejam congelados corretamente.
21.2. Rotina de reindexação Em algumas situações vale a pena reconstruir índices periodicamente utilizando o comando REINDEX (Existe, também, a aplicação contrib/reindexdb que pode reindexar todo o banco de dados). Entretanto, o PostgreSQL 7.4 reduziu de forma substancial a necessidade desta atividade se comparado às versões anteriores.
21.3. Manutenção do arquivo de log É uma boa idéia salvar a saída do log do servidor de banco de dados em algum lugar, em vez de simplesmente direcionar para /dev/null. A saída do log é valiosa para fazer o diagnóstico de problemas. Entretanto, a saída do log tende a se tornar volumosa (especialmente nos níveis de depuração altos), e não será desejado salvá-la indefinidamente. É necessário fazer a “rotação” dos arquivos de log, para que novos arquivos de log sejam iniciados e os antigos jogados fora periodicamente. Se simplesmente for direcionada a stderr do postmaster para um arquivo, a única maneira de truncar o arquivo de log é parando e reiniciando o postmaster, o que pode ser adequado para uma configuração de desenvolvimento, mas não será desejado operar um servidor de produção desta maneira. No grau de produção a abordagem mais simples para gerenciar a saída do log é enviá-la toda para o syslog, e deixar o syslog tratar a rotação do arquivo. Para isto ser feito, é definido o parâmetro de configuração syslog igual 2 (para registrar apenas no syslog) no arquivo postgresql.conf. Então, pode ser enviado o sinal SIGHUP para o processo (daemon) syslog sempre que se desejar forçá-lo a escrever um novo arquivo de log. Se for desejado automatizar a rotação do log, o programa logrotate pode ser configurado para trabalhar com os arquivos de syslog. Entretanto, em muitos sistemas o syslog não é muito confiável, particularmente com mensagens de log grandes; pode truncar ou remover as mensagens justamente quando forem mais necessárias. Pode ser considerado mais útil enviar a stderr do postmaster para algum tipo de programa de rotação do log. Se o
318
servidor for inicializado com pg_ctl, então a stderr do postmaster já estará redirecionada para stdout e, portanto, somente será necessário utilizar o pipe: pg_ctl start | logrotate
A distribuição do PostgreSQL não inclui um programa adequado para rotação do log, mas existem vários disponíveis na Internet; um deles, por exemplo, está incluído na distribuição do Apache.
319
Capítulo 22. Cópias de segurança e restauração Da mesma forma que tudo que contém dados valiosos, devem ser feitas cópias de segurança dos bancos de dados do PostgreSQL regularmente. Embora este procedimento seja essencialmente simples, é importante possuir uma compreensão básica das técnicas e premissas que estão por trás. Existem duas abordagens diferentes em seus fundamentos para fazer cópias de segurança dos dados do PostgreSQL: •
Método SQL-dump
•
Cópia de segurança no nível do sistema operacional
22.1. Método SQL-dump A idéia por trás do Método SQL-dump é gerar um arquivo texto contendo comandos SQL que, ao serem processados pelo servidor, recriam o banco de dados no mesmo estado em que se encontrava quando o arquivo foi gerado. O PostgreSQL disponibiliza o programa utilitário pg_dump para esta finalidade. A utilização básica deste comando é: pg_dump nome_do_banco_de_dados > arquivo_de_saída
Conforme pode ser visto, o pg_dump escreve o seu resultado na saída padrão. Será visto abaixo como isto pode ser útil. O pg_dump é uma aplicação cliente normal do PostgreSQL (embora seja particularmente astuta). Isto significa que o procedimento de cópia de segurança pode ser realizado a partir de qualquer hospedeiro remoto que possua acesso ao banco de dados. Porém, deve ser lembrado que o pg_dump não opera com permissão especial. Em particular, é necessário possuir acesso de leitura a todas as tabelas que se deseja fazer cópia de segurança portanto, na prática, quase sempre é necessário ser um superusuário do banco de dados. Para especificar qual servidor de banco de dados o pg_dump deve se conectar, devem ser utilizadas as opções de linha de comando -h hospedeiro e -p porta. O hospedeiro padrão é o hospedeiro local ou o que estiver especificado na variável de ambiente PGHOST. Da mesma maneira, a porta padrão é indicada pela variável de ambiente PGPORT ou, na falta desta, pelo padrão de compilação (De forma conveniente, o servidor normalmente possui o mesmo padrão de compilação). Assim como qualquer outra aplicação cliente do PostgreSQL, o pg_dump se conecta por padrão ao banco de dados cujo nome é igual ao nome do usuário corrente do sistema operacional. Para mudar, deve ser especificada a opção -U ou definida a variável de ambiente PGUSER. Lembre-se que as conexões do pg_dump estão sujeitas aos mecanismos usuais de autenticação de cliente (os quais estão descritos no Capítulo 19). As cópias de segurança criadas pelo pg_dump são coerentes internamente, ou seja, as atualizações feitas no banco de dados enquanto o pg_dump está executando não estarão presentes na cópia de segurança. O pg_dump não bloqueia outras operações no banco de dados enquanto está executando (Exceto as operações que precisam operar com modo de bloqueio exclusivo, como o VACUUM FULL). Importante: Quando o esquema do banco de dados é dependente dos OIDs (como chaves estrangeiras, por exemplo) deve-se instruir o pg_dump para que também inclua os OIDs. Para que isto seja feito, deve ser utilizada a opção de linha de comando -o. Também não são feitas cópias de segurança dos “objetos grandes” por padrão. Veja a página de referência do comando pg_dump se forem utilizados objetos grandes.
22.1.1. Restauração da cópia de segurança Os arquivos texto criados pelo pg_dump são feitos para serem lidos pelo programa psql. A forma geral do comando para restaurar uma cópia de segurança é: psql nome_do_banco_de_dados < arquivo_de_entrada
320
onde o arquivo_de_entrada é o que foi utilizado como arquivo_de_saída pelo comando pg_dump. O banco de dados nome_do_banco_de_dados não será criado por este comando, devendo ser criado a partir de template0 antes de executar o psql (por exemplo, com createdb -T template0 nome_do_banco_de_dados). O psql possui opções semelhantes às do pg_dump para controlar a localização do servidor de banco de dados e o nome do usuário. Veja a página de referência para obter mais informações. Se os objetos no banco de dados original pertencem a usuários diferentes, então a cópia de segurança instrui o psql a se conectar como cada usuário afetado por vez, e depois criar os objetos relevantes. Desta forma o dono original é preservado. Entretanto, isto também significa que todos estes usuários devem existir, e que é possível se conectar como cada um deles. Portanto, pode ser necessário fazer um relaxamento temporário das definições de autenticação de clientes. Uma vez feita a restauração, é sensato executar o comando ANALYZE em cada um dos bancos de dados para que o otimizador possua estatísticas úteis. Também pode ser executado vacuumdb -a -z para efetuar o ANALYZE de todos os bancos de dados. A capacidade do pg_dump e do psql de escreverem ou lerem de pipes torna possível replicar diretamente o banco de dados de um servidor em outro; por exemplo: pg_dump -h hospedeiro1 nome_do_banco_de_dados
nome_do_banco_de_dados
|
psql
-h
hospedeiro2
Importante: As cópias de segurança produzidas pelo pg_dump são relativas a template0. Isto significa que todas as linguagens, procedimentos, etc. adicionados a template1 também serão incluídos pelo pg_dump. Como resultado, se estiver sendo utilizado um template1 personalizado, ao restaurar deve ser criado um banco de dados vazio a partir de template0, conforme feito no exemplo acima. Dica: O desempenho da restauração pode ser melhorado pelo aumento do parâmetro de configuração sort_mem (veja a Seção 16.4.2.1).
22.1.2. Utilização do comando pg_dumpall O mecanismo mostrado acima é complicado e não é apropriado para fazer a cópia de segurança de um agrupamento de bancos de dados. Por este motivo é disponibilizado o programa pg_dumpall. O pg_dumpall faz a cópia de segurança de todos os bancos de dados de um agrupamento, e também salva dados de todo o agrupamento, como os usuários e grupos. A seqüência de chamada para pg_dumpall é simplesmente pg_dumpall > arquivo_de_saída
A cópia de segurança gerada pode ser restaurada pelo psql: psql template1 < arquivo_de_entrada
(Na verdade, pode ser especificado qualquer nome de banco de dados existente para começar, mas se estiver sendo feita a restauração em um agrupamento vazio então template1 é a única escolha disponível). É sempre necessário possuir acesso de superusuário do banco de dados para fazer a restauração de uma cópia de segurança gerada pelo pg_dumpall, porque isto é necessário para restaurar as informações de usuário e de grupo.
22.1.3. Bancos de dados grandes Uma vez que o PostgreSQL permite a existência de tabelas maiores do que o tamanho máximo de arquivo do sistema operacional, pode ser problemático realizar a cópia de segurança de uma tabela como esta em um arquivo, uma vez que o arquivo resultante provavelmente será maior do que o tamanho máximo permitido. Como o pg_dump pode escrever na saída padrão, podem ser utilizadas as ferramentas padrão do Unix para superar este possível problema. Utilização de cópias de segurança comprimidas. Pode ser utilizado o programa de compressão favorito como, por exemplo, o gzip. pg_dump nome_do_banco_de_dados | gzip > nome_do_arquivo.gz
321
Restaurar com createdb nome_do_banco_de_dados gunzip -c nome_do_arquivo.gz | psql nome_do_banco_de_dados
ou cat nome_do_arquivo.gz | gunzip | psql nome_do_banco_de_dados
Utilização do comando split. O comando split permite dividir a saída em pedaços de tamanho aceitável para o sistema de arquivos. Por exemplo, para fazer quebras de 1 megabyte: pg_dump nome_do_banco_de_dados | split -b 1m - nome_do_arquivo
Restaurar com createdb nome_do_banco_de_dados cat nome_do_arquivo* | psql nome_do_banco_de_dados
Utilização de formatos personalizados de cópia de segurança. Se o PostgreSQL foi construído em um sistema com a biblioteca de compressão zlib instalada, o formato personalizado de cópia de segurança comprime os dados ao escrever no arquivo de saída. Para bancos de dados grandes, produz cópias de segurança com tamanhos semelhantes às produzidas utilizando o gzip, mas possui a vantagem adicional de permitir a restauração seletiva das tabelas. O comando abaixo gera a cópia de segurança de um banco de dados utilizando o formato personalizado (custom): pg_dump -Fc nome_do_banco_de_dados > nome_do_arquivo
Veja as páginas de referência do pg_dump e do pg_restore para obter detalhes.
22.1.4. Precauções O pg_dump (e conseqüentemente o pg_dumpall) possui algumas poucas limitações causadas pela dificuldade de reconstruir certas informações a partir dos catálogos do sistema. Especificamente, a ordem utilizada pelo pg_dump para escrever os objetos não é muito sofisticada. Isto pode causar problemas como, por exemplo, quando funções são utilizadas como valor padrão de colunas. A única solução é reorganizar manualmente a cópia de segurança. Se forem criadas dependências circulares no esquema então haverá mais trabalho a ser feito. Por razões de compatibilidade com as versões anteriores, o pg_dump não faz cópias de segurança dos objetos grandes por padrão. Para fazer cópias de segurança dos objetos grandes deve ser utilizado o formato de saída personalizado ou o TAR, e utilizada a opção -b do pg_dump. Veja a página de referência para obter mais detalhes. O diretório contrib/pg_dumplo da árvore do código fonte do PostgreSQL também contém um programa que pode ser utilizado para fazer cópias de segurança dos objetos grandes. Por favor se familiarize com a página de referência do pg_dump.
22.2. Cópia de segurança no nível de arquivo Uma estratégia alternativa para realizar cópias de segurança é copiar diretamente os arquivos utilizados pelo PostgreSQL para armazenar os dados nos bancos de dados. Na Seção 16.2 é explicado onde estes arquivos estão localizados, mas provavelmente você já os encontrou se está interessado neste método. Pode ser utilizada a forma preferida para fazer as cópias de segurança usuais dos arquivos do sistema como, por exemplo: tar -cf backup.tar /usr/local/pgsql/data
Entretanto, existem duas restrições que fazem com que este método não seja prático, ou que seja no mínimo inferior ao método pg_dump: 1. O servidor de banco de dados deve estar parado para que se possa obter uma cópia de segurança utilizável. Meias medidas como impedir todas as conexões não funcionam, porque sempre existe alguma buferização em andamento. Por esta razão também não é aconselhável confiar em sistemas de arquivo
322
que dizem suportar “instantâneos coerentes” (consistent snapshots). Informações sobre como parar o servidor podem ser encontradas na Seção 16.6. É desnecessário dizer que também é necessário parar o servidor antes de restaurar os dados. 2. Caso tenha se aprofundado nos detalhes da organização do sistema de arquivos dos dados, você poderá cair na tentação de fazer cópias de segurança ou restaurar apenas algumas determinadas tabelas ou bancos de dados a partir de seus respectivos arquivos ou diretórios. Isto não funciona, porque as informações contidas nestes arquivos possuem apenas a metade da verdade. A outra metade está nos arquivos de log de efetivação pg_clog/*, que contêm o status de efetivação de todas as transações. O arquivo da tabela somente possui utilidade com esta informação. É claro que também é impossível restaurar apenas uma tabela e seus dados associados em pg_clog, porque isto torna todas as outras tabelas do agrupamento de banco de dados inutilizadas. Uma abordagem alternativa para cópias de segurança do sistema de arquivos é fazer um “instantâneo coerente” do diretório de dados, se o sistema de arquivos suportar esta funcionalidade. Este tipo de instantâneo salva os arquivos do banco de dados em um estado onde o servidor de banco de dados não foi parado de forma apropriada; portanto, quando o servidor de banco de dados for inicializado no diretório restaurado a partir de uma cópia de segurança deste tipo, vai achar que o servidor caiu e o log do WAL será refeito. Isto não é um problema, mas esteja atento a este fato. Observe que a cópia de segurança do sistema de arquivos não será necessariamente menor do que no Método SQL-dump. Ao contrário, é mais provável que seja maior (O pg_dump não precisa fazer cópia de segurança dos índices, por exemplo, mas apenas dos comandos para recriá-los).
22.3. Migração entre versões Como regra geral, o formato interno de armazenamento dos dados está sujeito a mudanças entre versões principais do PostgreSQL (onde muda o número após o primeiro ponto). Isto não se aplica às versões secundárias sob a mesma versão principal (onde muda o número após o segundo ponto); estas sempre possuem formatos de armazenamento compatíveis. Por exemplo, as versões 7.0.1, 7.1.2 e 7.2 não são compatíveis, enquanto as versões 7.1.1 e 7.1.2 são. Quando é feita a atualização entre versões compatíveis, pode ser simplesmente reutilizada a área de dados no disco pelos novos executáveis. Caso contrário, é necessário realizar uma “cópia de segurança” dos dados e “restaurá-la” no novo servidor, utilizando o pg_dump (Existem verificações realizadas para impedir que seja feito de forma errada, portanto nenhum dano pode ser causado por confundir estas instruções). O procedimento de instalação preciso não é assunto desta seção; os detalhes estão no Capítulo 14. O menor tempo de parada pode ser obtido instalando o novo servidor em um diretório diferente e executando tanto o servidor novo quanto o antigo em paralelo, em portas diferentes. Depois pode ser executado algo como pg_dumpall -p 5432 | psql -d template1 -p 6543
para transferir os dados. Também pode ser utilizado um arquivo intermediário se for desejado. Depois se pode parar o servidor antigo e inicializar o novo servidor na porta que o servidor antigo estava utilizando. Deve haver certeza de que o servidor de banco de dados não foi atualizado após ser executado o pg_dumpall, senão obviamente serão perdidos dados. Veja o Capítulo 19 para obter informações sobre como proibir o acesso. Na prática provavelmente será desejado testar as aplicações cliente na nova configuração antes de realizar a mudança. Se não for possível ou não for desejado executar dois servidores em paralelo, pode ser realizada a etapa de cópia de segurança antes de instalar a nova versão, parar o servidor, mover a versão antiga para outro lugar, instalar a nova versão, inicializar o novo servidor, e restaurar os dados. Por exemplo: pg_dumpall > backup pg_ctl stop mv /usr/local/pgsql /usr/local/pgsql.old cd ~/postgresql-7.4.1 gmake install initdb -D /usr/local/pgsql/data postmaster -D /usr/local/pgsql/data psql template1 < backup
323
Veja no Capítulo 16 as formas de parar e inicializar o servidor e outros detalhes. As instruções de instalação aconselham as localizações estratégicas para realizar estes passos. Nota: Quando é “movida a instalação antiga para outro lugar” esta não é mais totalmente utilizável. Algumas partes da instalação contêm informações sobre onde as outras partes estão localizadas. Isto normalmente não é um grande problema, mas se for planejada a utilização das duas instalações em paralelo por um período de tempo devem ser atribuídos diretórios de instalação diferentes em tempo de construção.
324
Capítulo 23. Monitoramento das atividades do banco de dados Freqüentemente o administrador de banco de dados deseja saber, “O que o sistema está fazendo agora?”. Este capítulo discute o que se deve fazer para descobrir. Estão disponíveis várias ferramentas para monitorar a atividade do banco de dados e analisar o desempenho. A maior parte deste capítulo é dedicada a descrever o coletor de estatísticas do PostgreSQL, mas não devem ser desprezados os programas regulares de monitoramento do Unix, tais como ps e top. Também, uma vez que tenha sido identificado um comando com baixo desempenho, podem ser necessárias outras investigações utilizando o comando EXPLAIN do PostgreSQL. A Seção 13.1 discute o EXPLAIN e outros métodos para compreender o comportamento individual dos comandos.
23.1. Ferramentas padrão do Unix Na maioria das plataformas, o PostgreSQL modifica o título de seu comando conforme mostrado pelo ps, para que processos individuais do servidor possam ser rapidamente identificados. Um exemplo do que é mostrado é: $ ps auxww | grep ^postgres postgres postgres
960 963
0.0 0.0
1.1 1.1
6104 1480 pts/1 7084 1472 pts/1
SN SN
13:17 13:17
postgres
965
0.0
1.1
6152 1512 pts/1
SN
13:17
postgres
998
0.0
2.3
6532 2992 pts/1
SN
13:18
postgres
1003
0.0
2.4
6532 3128 pts/1
SN
13:19
postgres
1016
0.1
2.4
6532 3080 pts/1
SN
13:19
0:00 postmaster -i 0:00 postgres: stats buffer process 0:00 postgres: stats collector process 0:00 postgres: tgl runbug 127.0.0.1 idle 0:00 postgres: tgl regression [local] SELECT waiting 0:00 postgres: tgl regression [local] idle in transaction
(A forma apropriada para chamar o ps varia entre plataformas diferentes, assim como os detalhes mostrados. Este exemplo foi tirado de um sistema Linux recente). O primeiro processo listado neste exemplo é o postmaster, o processo servidor mestre. Os argumentos do comando mostrados são os mesmos que foram fornecidos quando este foi chamado. Os dois processos seguintes implementam o coletor de estatísticas, que será descrito detalhadamente na próxima seção (Não estarão presentes se o sistema foi configurado para não inicializar o coletor de estatísticas). Cada um dos demais processos é um processo servidor tratando uma conexão cliente. Cada um destes processos define a exibição da sua linha de comando na forma postgres: usuário banco_de_dados hospedeiro atividade
Os itens usuário, banco de dados e hospedeiro origem da conexão permanecem o mesmo durante toda a existência da conexão cliente, mas o indicador de atividade muda. A atividade pode ser idle (ou seja, ociosa, aguardando por um comando do cliente), idle in transaction (aguardando pelo cliente dentro do bloco BEGIN), ou o nome de um tipo de comando tal como SELECT. Também, waiting é anexado se o processo servidor estiver no momento aguardando por um bloqueio mantido por outro processo servidor. No exemplo acima pode ser inferido que o processo 1003 está aguardando o processo 1016 completar sua transação e, portanto, liberar algum bloqueio. Dica: O Solaris requer tratamento especial. Deve ser utilizado /usr/ucb/ps em vez de /bin/ps. Também devem ser utilizados dois sinalizadores w, e não apenas um. Além disso, a chamada original do comando postmaster deve possuir um status exibido pelo ps mais curto do que o de cada processo servidor. Se não acontecerem estas três coisas, a saída do ps para cada processo servidor será a linha de comando do postmaster.
325
23.2. O coletor de estatísticas O coletor de estatísticas do PostgreSQL é um subsistema de apoio a coleta e relatório de informações sobre as atividades do servidor. Atualmente, o coletor pode contar acessos a tabelas e índices em termos de blocos de disco e linhas individuais. Também apóia a determinação exata do comando sendo executado atualmente pelos outros processos servidor.
23.2.1. Configuração da coleta de estatísticas Uma vez que a coleta de estatísticas ocasiona alguma sobrecarga à execução do comando, o sistema pode ser configurado para coletar ou não coletar informações. Isto é controlado pelos parâmetros de configuração, normalmente definidos no arquivo postgresql.conf (Veja a Seção 16.4 para obter detalhes sobre como definir os parâmetros de configuração). O parâmetro stats_start_collector deve ser definido como true para que o coletor de estatísticas seja lançado. Esta é a definição padrão e recomendada, mas pode ser desabilitada se não houver interesse nas estatísticas e for desejado eliminar até a última gota de sobrecarga (Entretanto, provavelmente o ganho será pequeno). Observe que esta opção não pode ser mudada enquanto o servidor está executando. Os parâmetros stats_command_string, stats_block_level, e stats_row_level controlam a quantidade de informação realmente enviada para o coletor e, portanto, determinam quanta sobrecarga ocorre em tempo de execução. Definem se o processo servidor envia a cadeia de caracteres do comando corrente, as estatísticas de acesso no nível de bloco de disco e as estatísticas de acesso no nível de linha para o coletor, respectivamente. Normalmente estes parâmetros são definidos no arquivo postgresql.conf e, portanto, são aplicados a todos os processos servidor, mas é possível ativá-los ou desativá-los para sessões individuais utilizando o comando SET (Para evitar que os usuários comuns escondam suas atividades do administrador, somente os superusuários podem alterar estes parâmetros através do comando SET). Nota: Uma vez que os parâmetros stats_command_string, stats_block_level e stats_row_level são false por padrão, muito poucas estatísticas são coletadas na configuração padrão. Habilitar uma ou mais destas variáveis de configuração aumenta significativamente a quantidade de dados úteis produzidos pelo coletor de estatísticas, ao custo de uma sobrecarga adicional em tempo de execução.
23.2.2. Ver as estatísticas coletadas Diversas visões pré-definidas estão disponíveis para mostrar os resultados das estatísticas coletadas, conforme listado na Tabela 23-1. Como alternativa, podem ser construídas visões personalizadas utilizando as funções de estatísticas subjacentes. Ao se utilizar as estatísticas para monitorar a atividade corrente, é importante ter em mente que as informações não são atualizadas instantaneamente. Cada processo servidor individual transmite novos contadores de acesso para o coletor logo antes de aguardar pelo próximo comando do cliente; portanto, um comando ainda em progresso não afeta os totais exibidos. Também, o próprio coletor emite novos totais no máximo uma vez a cada pgstat_stat_interval milissegundos (500 por padrão). Portanto, os totais mostrados são anteriores à atividade corrente. Outro ponto importante é que quando se solicita a um processo servidor para mostrar uma destas estatísticas, primeiro são buscados os totais mais recentes emitidos pelo processo coletor, e depois continua sendo utilizado este instantâneo por todas as visões e funções de estatística até o término da transação corrente. Portanto, as estatísticas parecem não mudar enquanto se permanece na transação corrente. Isto é uma característica, e não um erro, porque permite realizar várias consultas às estatísticas e correlacionar os resultados sem se preocupar com a variação dos números que estão por trás. Se for desejado ver novos resultados a cada consulta, deve haver certeza de que as consultas estão fora de qualquer bloco de transação.
326
Tabela 23-1. Visões de estatísticas padrão Nome da visão
Descrição
pg_stat_activity
Uma linha por processo servidor, mostrando o ID do processo, o banco de dados, o usuário, o comando corrente e a hora em que o comando corrente começou a executar. As colunas que mostram os dados do comando corrente somente estão disponíveis quando o parâmetro stats_command_string está habilitado. Além disso, estas colunas mostram o valor nulo a menos que o usuário consultando a visão seja um superusuário ou o mesmo usuário dono do processo sendo mostrado (Observe que devido ao retardo do que é informado pelo coletor, o comando corrente somente estará atualizado no caso dos comandos com longo tempo de execução).
pg_stat_database
Uma linha por banco de dados, mostrando o número de processos servidor ativos, total de transações efetivadas e total de transações desfeitas neste banco de dados, total de blocos de disco lidos e total de acertos no buffer (ou seja, requisições de leitura de bloco evitadas por encontrar o bloco no cache do buffer).
pg_stat_all_tables
Para cada tabela do banco de dados corrente, os totais de: varreduras seqüencial e de índice; linhas retornadas por cada tipo de varredura; linhas inseridas, atualizadas e excluídas.
pg_stat_sys_tables
O mesmo que pg_stat_all_tables, exceto que somente as tabelas do sistema são mostradas.
pg_stat_user_tables
O mesmo que pg_stat_all_tables, exceto que somente as tabelas de usuário são mostradas.
pg_stat_all_indexes
Para cada índice do banco de dados corrente, o total de varreduras de índice que utilizaram este índice, o número de linhas do índice lidas, e o número de linhas da tabela trazidas com sucesso (Pode ser menor quando existem entradas do índice apontando para linhas da tabela expiradas)
pg_stat_sys_indexes
O mesmo que pg_stat_all_indexes, exceto que somente os índices das tabelas do sistema são mostrados.
pg_stat_user_indexes
O mesmo que pg_stat_all_indexes, exceto que somente os índices das tabelas de usuário são mostrados.
pg_statio_all_tables
Para cada tabela do banco de dados corrente, o total de blocos de disco lidos e o número de acertos no buffer para a tabela, o número de blocos de disco lidos e acertos no buffer para todos os índices da tabela, o número de blocos de disco lidos e acertos no buffer para a tabela auxiliar TOAST da tabela (se houver), e o número de blocos de disco lidos e acertos no buffer para o índice da tabela TOAST.
pg_statio_sys_tables
O mesmo que pg_statio_all_tables, exceto que somente as tabelas do sistema são mostradas.
pg_statio_user_tables
O mesmo que pg_statio_all_tables, exceto que somente as tabelas de usuário são mostradas.
pg_statio_all_indexes
Para cada índice do banco de dados corrente, o número de blocos de disco lidos e o número de acertos no buffer para o índice.
pg_statio_sys_indexes
O mesmo que pg_statio_all_indexes, exceto que somente os índices das tabelas do sistema são mostrados.
327
Nome da visão
Descrição
pg_statio_user_indexes
O mesmo que pg_statio_all_indexes, exceto que somente os índices das tabelas de usuário são mostrados.
pg_statio_all_sequences
Para cada objeto de seqüência do banco de dados corrente, o número de blocos de disco lidos e o número de acertos no buffer para a seqüência.
pg_statio_sys_sequences
O mesmo que pg_statio_all_sequences, exceto que somente as seqüências do sistema são mostradas (Atualmente nenhuma seqüência do sistema está definida e, portanto, esta visão está sempre vazia).
pg_statio_user_sequences
O mesmo que pg_statio_all_sequences, exceto que somente as seqüências de usuário são mostradas.
As estatísticas por índice são particularmente úteis para determinar quais índices estão sendo utilizados e quão efetivos são. As visões pg_statio_ são úteis, principalmente, para determinar a efetividade do cache do buffer. Quando o número de leituras físicas no disco é muito menor do que o número de acertos no buffer, então o cache está satisfazendo a maioria das requisições de leitura evitando chamadas ao núcleo. Entretanto, estas estatísticas não fornecem toda a história: devido à forma como o PostgreSQL trata a entrada e saída em disco, um dado que não esteja no cache do buffer do PostgreSQL pode residir no cache do núcleo e, portanto, pode ser trazido sem que haja necessidade de uma leitura física. Os usuários interessados em obter informações mais detalhadas sobre o comportamento de entrada e saída do PostgreSQL são aconselhados a utilizar o coletor de estatísticas do PostgreSQL em combinação com os utilitários do sistema operacional que permitem uma percepção profunda do tratamento da entrada e saída pelo núcleo. Outras formas de ver as estatísticas podem ser desenvolvidas escrevendo consultas utilizando as mesmas funções que estão por trás das visões padrão de acesso às estatísticas. Esta funções estão listadas na Tabela 232. As funções de acesso por banco de dados recebem como argumento o OID do banco de dados para identificar qual banco de dados se referir. As funções por tabela e por índice recebem o OID da tabela ou do índice, respectivamente (Observe que somente as tabelas e índices presentes no banco de dados corrente podem ser vistos por estas funções). As funções de acesso por processo servidor recebem o número de ID do processo servidor, que pode variar de um ao número de processos servidor ativos em um determinado instante. Tabela 23-2. Funções de estatísticas de acesso Função
Tipo retornado
Descrição
pg_stat_get_db_numbackends (oid)
integer
Número de processos servidor ativos para o banco de dados
pg_stat_get_db_xact_commit (oid)
bigint
Transações efetivadas no banco de dados
pg_stat_get_db_xact_rollback (oid)
bigint
Transações desfeitas no banco de dados
pg_stat_get_db_blocks_fetched
bigint
Número de requisições de busca de blocos de disco para o banco de dados
pg_stat_get_db_blocks_hit (oid)
bigint
Número de requisições de busca de blocos de disco encontradas no cache para o banco de dados
pg_stat_get_numscans (oid)
bigint
Número de varreduras seqüenciais realizadas quando o argumento é uma tabela, ou o número de varreduras de índice quando o argumento é um índice
pg_stat_get_tuples_returned (oid)
bigint
Número de linhas lidas por varreduras seqüenciais quando o argumento é uma tabela,
(oid)
328
Função
Tipo retornado
Descrição ou o número de linhas do índice lidas quando o argumento é um índice
pg_stat_get_tuples_fetched (oid)
bigint
Número de linhas válidas (não expiradas) da tabela buscadas por varreduras seqüenciais quando o argumento é uma tabela, ou buscadas por varreduras de índice utilizando este índice quando o argumento é um índice
pg_stat_get_tuples_inserted (oid)
bigint
Número de linhas inseridas na tabela
pg_stat_get_tuples_updated (oid)
bigint
Número de linhas atualizadas na tabela
pg_stat_get_tuples_deleted (oid)
bigint
Número de linhas excluídas da tabela
pg_stat_get_blocks_fetched (oid)
bigint
Número de requisições de busca de bloco de disco para a tabela ou o índice
pg_stat_get_blocks_hit (oid)
bigint
Número de requisições de busca de bloco de disco encontradas no cache para a tabela ou o índice
pg_stat_get_backend_idset ()
conjunto de integer
Conjunto de IDs de processos servidor ativos no momento (de 1 ao número de processos servidor ativos). Veja o exemplo de utilização no texto.
pg_backend_pid ()
integer
ID de processo do processo servidor conectado à sessão corrente
pg_stat_get_backend_pid (integer)
integer
ID de processo do processo servidor especificado
pg_stat_get_backend_dbid (integer)
oid
ID de banco de dados do processo servidor especificado
pg_stat_get_backend_userid
oid
ID de usuário do processo servidor especificado
text
Comando ativo do processo servidor especificado (nulo se o usuário corrente não for um superusuário nem o mesmo usuário da sessão sendo consultada, ou se stats_command_string não estiver ativo)
(integer)
timestamp with time zone
A hora em que o comando executando no momento, no processo servidor especificado, começou (nulo se o usuário corrente não for um superusuário nem o mesmo usuário da sessão sendo consultada, ou se stats_command_string não estiver ativo)
pg_stat_reset()
boolean
Redefine todas as estatísticas correntemente coletadas
(integer) pg_stat_get_backend_activity
(integer)
pg_stat_get_backend_activity_start
Nota: pg_stat_get_db_blocks_fetched menos pg_stat_get_db_blocks_hit fornece o número de chamadas à função read() do núcleo feitas para a tabela, índice ou banco de dados; mas o número verdadeiro de leituras físicas é geralmente menor por causa da buferização no nível do núcleo.
329
A função pg_stat_get_backend_idset fornece uma maneira conveniente de gerar uma linha para cada processo servidor ativo. Por exemplo, para mostrar o PID e os comandos correntes de todos os processos servidor: SELECT pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_activity(s.backendid) AS current_query FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;
23.3. Ver os bloqueios Outra ferramenta útil para monitorar a atividade do banco de dados é a tabela do sistema pg_locks. Esta tabela permite ao administrador do banco de dados ver informações sobre os bloqueios ativos no gerenciador de bloqueios. Por exemplo, esta capacidade pode ser utilizada para: •
Ver todos os bloqueios ativos no momento, todos os bloqueios nas relações em um determinado banco de dados, todos os bloqueios em uma determinada relação, ou todos os bloqueios mantidos por uma determinada sessão do PostgreSQL.
•
Determinar a relação no banco de dados corrente com mais bloqueios não concedidos (que pode ser uma origem de contenção entre clientes do banco de dados).
•
Determinar o efeito da contenção de bloqueio sobre o desempenho do banco de dados como um todo, assim como até que ponto a contenção varia com tráfego global do banco de dados.
Detalhes da visão pg_locks são mostrados na Seção 43.32. Para obter mais informações sobre bloqueio e gerenciamento de simultaneidade no PostgreSQL, veja o Capítulo 12.
330
Capítulo 24. Monitoramento de espaço em disco Este capítulo discute como monitorar a utilização de disco por um sistema de banco de dados PostgreSQL. Na versão corrente o administrador de banco de dados realmente possui muito controle para organizar o armazenamento em disco, portanto este capítulo é em sua maior parte informativo podendo proporcionar boas idéias sobre como gerenciar a utilização de disco com as ferramentas do sistema operacional.
24.1. Determinação da utilização de disco Cada tabela possui um arquivo de pilha primário em disco onde a maior parte dos dados são armazenados. Para armazenar os valores longos das colunas existe, também, um arquivo TOAST associado à tabela, cujo nome tem por base o OID da tabela (na verdade pg_class.relfilenode) e um índice na tabela TOAST. Também podem existir índices associados à tabela base. O espaço em disco pode ser monitorado a partir de três lugares: do psql utilizando as informações do VACUUM, do psql utilizando as ferramentas em contrib/dbsize, e da linha de comando utilizando as ferramentas em contrib/oid2name. Utilizando o psql em um banco de dados onde o comando VACUUM ou ANALYZE acabou de ser executado, podem ser efetuadas consultas para ver a utilização do espaço em disco de qualquer tabela: SELECT relfilenode, relpages FROM pg_class WHERE relname = 'cliente'; relfilenode | relpages -------------+---------16806 | 60 (1 linha)
cada página possui, normalmente, 8 kilobytes (Lembre-se, relpages somente é atualizado por VACUUM e ANALYZE). Para ver o espaço utilizado pelas tabelas TOAST deve ser utilizada uma consulta como a mostrada abaixo, substituindo o número do relfilenode da pilha (determinado pela consulta acima): SELECT relname, relpages FROM pg_class WHERE relname = 'pg_toast_16806' OR relname = 'pg_toast_16806_index' ORDER BY relname; relname | relpages ----------------------+---------pg_toast_16806 | 0 pg_toast_16806_index | 1
Os tamanhos dos índices também podem ser facilmente exibidos: SELECT c2.relname, c2.relpages FROM pg_class c, pg_class c2, pg_index i WHERE c.relname = 'cliente' AND c.oid = i.indrelid AND c2.oid = i.indexrelid ORDER BY c2.relname; relname | relpages ----------------------+---------cliente_id_indexdex | 26
É fácil descobrir quais são as maiores tabelas e índices utilizando esta consulta: SELECT relname, relpages FROM pg_class ORDER BY relpages DESC;
331
relname | relpages ----------------------+---------tabela_grande | 3290 cliente | 3144 contrib/dbsize carrega funções no banco de dados que permitem descobrir o tamanho da tabela ou do banco de dados a partir do psql sem necessidade do VACUUM ou do ANALYZE.
Também pode ser utilizado contrib/oid2name para mostrar utilização de disco. Veja exemplo em README.oid2name neste diretório. Está incluído um script que mostra utilização de disco para cada banco de dados.
24.2. Falha de disco cheio A tarefa mais importante de monitoramento de disco do administrador de banco de dados é garantir que o disco não vai ficar cheio. Um disco de dados cheio pode resultar em uma corrupção subseqüente dos índices do banco de dados, mas não das próprias tabelas. Se os arquivos WAL estiverem no mesmo disco (como é o caso na configuração padrão), então o disco cheio durante a inicialização do servidor de banco de dados pode ocasionar em arquivos WAL corrompidos ou incompletos. Esta condição de falha é detectada, e o servidor se banco de dados se recusa a inicializar. Se não for possível liberar espaço adicional no disco removendo outras coisas, podem ser movidos alguns arquivos do banco de dados para outros sistemas de arquivos e criados vínculos simbólicos a partir do local original. Entretanto, deve ser observado que o pg_dump não pode salvar as informações de arrumação da localização neste tipo de configuração; uma restauração coloca tudo de volta em um lugar. Para evitar ficar sem espaço em disco podem ser colocados os arquivos do WAL ou bancos de dados individuais em outros locais ao serem criados. Veja a documentação do initdb e a Seção 18.5 para obter mais informações. Dica: Alguns sistemas de arquivos têm desempenho degradado quando estão praticamente cheios, portanto não espere o disco ficar cheio para agir.
332
Capítulo 25. Log de escrita prévia (WAL) O log de escrita prévia (WAL) é uma abordagem padrão para registrar transações. A descrição detalhada pode ser encontrada na maioria (se não em todos) os livros sobre processamento de transação. Em poucas palavras, o conceito central do WAL é que as mudanças nos arquivos de dados (onde as tabelas e os índices residem) devem ser escrita somente após estas mudanças terem sido registradas, ou seja, quando os registros de log tiverem sido descarregados em um armazenamento permanente. Se este procedimento for seguido, não será necessário descarregar as páginas de dados no disco quando a transação for efetivada, porque se sabe que no evento de uma queda será possível recuperar o banco de dados utilizando o log: inicialmente todas as mudanças que não foram aplicadas às páginas de dados serão refeitas a partir dos registros de log (isto é a recuperação de rolar para a frente, roll-forward, também conhecida como REDO), e depois as modificações feitas pelas transações não efetivadas são removidas das páginas de dados (recuperação de rolar para trás, roll-backward, UNDO).
25.1. Benefícios do WAL O primeiro benefício óbvio da utilização do WAL é a redução significativa do número de escritas em disco, uma vez que somente os arquivos de log precisam ser descarregados em disco na hora em que a transação é efetivada; em ambientes multiusuário, a efetivação de várias transações pode ser feita através de um único fsync() do arquivo de log. Além disso, o arquivo de log é escrito seqüencialmente e, portanto, o custo de sincronizar o log é muito menor do quer o custo de descarregar as páginas de dados. O benefício seguinte é a consistência das páginas de dados. A verdade é que antes do WAL o PostgreSQL nunca foi capaz de garantir a consistência no caso de uma queda. Antes do WAL, qualquer queda durante a escrita poderia resultar em: 1. linhas de índice apontando para linhas que não existem na tabela 2. perda de linhas de índice nas operações de quebra de página (split) 3. conteúdo da página da tabela ou do índice totalmente corrompido, por causa das páginas de dados parcialmente escritas Os problemas com os índices (problemas 1 e 2) possivelmente poderiam ser resolvidos através de chamadas adicionais à função fsync(), mas não é óbvio como tratar o último caso sem o WAL; O WAL salva todo o conteúdo da página de dados no log se isto for necessário para garantir a consistência da página na recuperação após a queda.
25.2. Benefícios futuros A operação de UNDO não está implementada. Isto significa que as mudanças feitas por transações interrompidas continuam a ocupar espaço em disco, e que o arquivo pg_clog permanente, para guardar o status das transações, ainda é necessário, uma vez que os identificadores das transações não podem ser reutilizados. Uma vez que o UNDO tenha sido implementado, não será mais necessário que o o arquivo pg_clog seja permanente; será possível remover o arquivo pg_clog quando o servidor for parado (Entretanto, a preocupação com este problema diminuiu muito com a adoção do método de armazenamento segmentado para o arquivo pg_clog: não é mais necessário manter as entradas antigas no arquivo pg_clog para sempre). Com o UNDO também será possível implementar savepoints para permitir desfazer parcialmente as operações inválidas na transação (erros do analisador causados pela digitação errada de comandos, inserção de chaves primárias ou únicas duplicadas, etc.) com a possibilidade de continuar ou efetivar as operações válidas feitas pela transação antes do erro. No momento, qualquer erro invalida toda a transação, requerendo que esta seja interrompida. O WAL oferece oportunidade para um novo método de cópia de segurança e restauração de bancos de dados on-line (BAR). Para utilizar este método os arquivos de dados devem ser salvos periodicamente em outro disco, numa fita ou em outro hospedeiro e, também, serem salvos os arquivos de log do WAL. As cópias dos arquivos do banco de dados juntamente com os arquivos de log salvos podem ser utilizadas para restaurar, da
333
mesma maneira como é feita a restauração após uma queda. Cada vez que uma nova cópia dos arquivos do banco de dados for feita, os arquivos antigos de log podem ser removidos. A implementação desta facilidade necessita do registro de criação e remoção dos arquivos de dados e de índices; também requer o desenvolvimento de um método para copiar os arquivos de dados (os comandos de cópia do sistema operacional não são adequados). A dificuldade existente para transformar estes benefícios em realidade é a necessidade de salvar as entradas no WAL por um considerável período de tempo (por exemplo, tanto tempo quanto a mais longa transação possível se o UNDO de transação for desejado). O formato atual do WAL é extremamente grande, porque inclui muitos instantâneos de páginas de disco. Isto não é uma preocupação séria neste momento, uma vez que as entradas somente precisam ser mantidas por um ou dois intervalos de ponto de controle (checkpoint); mas para obter estes benefícios futuros algum tipo de formato comprimido do WAL será necessário.
25.3. Configuração do WAL Existem diversos parâmetros de configuração relacionados com o WAL que afetam o desempenho do banco de dados. Esta seção explica como usá-los. Consulte a Seção 16.4 para obter detalhes sobre como definir os parâmetros de configuração. Os pontos de controle são pontos na seqüência de transações nos quais se garante que os arquivos de dados foram atualizados, e contêm todas as informações registradas antes do ponto de controle. No momento do ponto de controle, todas as páginas de dados modificadas (dirty) são descarregadas no disco e um registro especial de ponto de controle é escrito no arquivo de log. Como resultado, no caso de uma queda o recuperador sabe a partir de qual registro do log (chamado de registro de redo) deve ser iniciada a operação de REDO, uma vez que todas as mudanças feitas nos arquivos de dados antes deste registro já se encontram no disco. Após o ponto de controle ter sido feito, quaisquer segmentos de log escritos antes dos registros de redo não são mais necessários, podendo ser reciclados ou removidos (Quando o BAR baseado no WAL é implementado, devem ser feitas cópias de segurança dos segmentos de log antes destes serem reciclados ou removidos). O servidor lança um processo especial periodicamente para criar o próximo ponto de controle. Um ponto de controle é criado a cada checkpoint_segments segmentos do log, ou a cada checkpoint_timeout segundos, o que ocorrer primeiro. As definições padrão são 3 segmentos e 300 segundos, respectivamente. Também é possível forçar o ponto de controle utilizando o comando SQL CHECKPOINT. Reduzir o checkpoint_segments e/ou checkpoint_timeout faz os pontos de controle serem feitos com maior freqüência, permitindo uma recuperação mais rápida após a queda (uma vez que haverá menos trabalho para ser refeito). Entretanto, deve haver um balanço entre isto e o aumento de custo causado pela descarga das páginas modificadas com maior freqüência. Além disso, para garantir a consistência das páginas de dados, a primeira modificação feita em uma página de dados após cada ponto de controle resulta em registrar todo o conteúdo desta página. Por isso, um intervalo de ponto de controle menor aumenta o volume de saída para o log, negando parcialmente o objetivo de utilizar um intervalo menor e, em qualquer caso, causando mais entrada e saída em disco. Há pelo menos um arquivo de segmento de 16 MB e, normalmente, não mais de 2 * checkpoint_segments + 1 arquivos. Isto pode ser utilizado para estimar a necessidade de espaço do WAL. Normalmente, quando os arquivos antigos de segmento do log não são mais necessários, estes são reciclados (os nome são mudados para se tornarem os próximos segmentos da seqüência numerada). Se, por causa de um pico de pouca duração da taxa de saída para o log, existirem mais de 2 * checkpoint_segments + 1 arquivos de segmento, os arquivos de segmento desnecessários serão removidos em vez de reciclados até o sistema voltar a ficar abaixo deste limite. Existem duas funções do WAL utilizadas com freqüência: LogInsert e LogFlush. A função LogInsert é utilizada para colocar um novo registro nos buffers do WAL na memória compartilhada. Se não houver espaço para o novo registro, LogInsert terá que escrever (mover para o cache do núcleo) uns poucos buffers do WAL cheios. Isto não é desejado, porque LogInsert é utilizada em todas as modificações de baixo nível do banco de dados (por exemplo, inserção de linha) de cada vez quando um bloqueio exclusivo é obtido nas páginas de dados afetadas, portanto esta operação precisa ser tão rápida quanto for possível. O que é pior, escrever os buffers do WAL pode também forçar a criação de um novo segmento do log, que toma
334
mais tempo ainda. Normalmente, os buffers do WAL devem ser escritos e descarregados pela requisição LogFlush que é feita, geralmente, em tempo de efetivação da transação para garantir que os registros da transação sejam descarregados no armazenamento permanente. Nos sistemas com saída de log alta, as requisições LogFlush podem não ocorrer com uma freqüência suficiente para impedir que os buffers do WAL sejam escritos pelo LogInsert. Nestes sistemas, deve ser aumentado o número de buffers do WAL pela modificação do parâmetro wal_buffers. O número padrão de buffers do WAL é 8. O aumento deste valor aumenta de forma correspondente a utilização da memória compartilhada. Os pontos de controle são muito dispendiosos, porque forçam todos os buffers do núcleo modificados serem enviados para o disco utilizando a chamada do sistema operacional sync(). Servidores ocupados podem encher os arquivos de segmento de ponto de controle muito rapidamente, produzindo um número excessivo de pontos de controle. Se tais pontos de controle forçados acontecerem com freqüência maior do que checkpoint_warning segundos, uma mensagem será enviada para o log do servidor recomendando aumentar checkpoint_segments. O parâmetro commit_delay define a quantidade de microssegundos que o processo servidor vai dormir após escrever um registro de efetivação no log com LogInsert mas antes de realizar o LogFlush. Este atraso permite que outros processos servidor adicionem seus registros de efetivação ao log para que todos eles sejam descarregados em uma única sincronização do log. A dormida não ocorre quando fsync não está habilitado, nem quando menos de outras commit_siblings sessões estão no instante com transações ativas; isto evita a dormida quando não é provável que outras seções efetivem em breve. Observe que na maioria das plataformas a resolução de uma solicitação de dormir é de dez milissegundos, portanto qualquer definição de commit_delay diferente de zero e entre 1 e 10000 microssegundos possuem o mesmo efeito. Ainda não está claro quais são os bons valores para estes parâmetros; incentiva-se que sejam feitas experiências. O parâmetro wal_sync_method determina como o PostgreSQL vai solicitar o núcleo para forçar o envio das atualizações do WAL para o disco. Todas as opções devem ser idênticas em termos de confiabilidade, mas é totalmente específico da plataforma qual delas é a mais rápida. Observe que este parâmetro é irrelevante se fsync estiver desabilitado. Definir o parâmetro wal_debug com qualquer valor diferente de zero faz com que todas as chamadas a LogInsert e LogFlush do WAL sejam registradas no log do servidor. No momento, não faz diferença qual é o valor diferente de zero. Esta opção poderá ser substituída por um mecanismo mais geral no futuro.
25.4. Internals O WAL é habilitado automaticamente; nenhuma ação por parte do administrador é requerida, exceto garantir que a necessidade adicional de espaço em disco para o log do WAL seja atendida, e que qualquer ajuste necessário seja feito (veja a Seção 25.3). Os logs do WAL são armazenados no diretório pg_xlog sob o diretório de dados como um conjunto de arquivos de segmento, cada um com o tamanho de 16 MB. Cada segmento é dividido em páginas de 8 kB. Os cabeçalhos dos registro de log estão descritos em access/xlog.h; o conteúdo do registro depende do tipo de evento que está sendo registrado. São atribuídos para nomes dos arquivos de segmento números que sempre aumentam, começando por 0000000000000000. Atualmente os números não recomeçam, mas demora muito tempo até que seja exaurido o estoque de números disponíveis. Os buffers do WAL e estruturas de controle ficam na memória compartilhada e são tratados pelos processos servidor descendentes; são protegidos por bloqueios de peso leve. A demanda por memória compartilhada é dependente do número de buffers. O tamanho padrão dos buffers do WAL é de 8 buffers de 8 kB cada um, ou um total de 64 kB. É vantajoso o log não ficar localizado no mesmo disco dos principais arquivos do banco de dados. Isto pode ser obtido movendo o diretório pg_xlog para outro local (enquanto o servidor estiver parado, é óbvio), e criando um vínculo simbólico do local original no diretório de dados principal para o novo local. A finalidade do WAL, garantir que o log seja escrito antes dos registros do banco de dados serem alterados, pode ser subvertida pelos drives de disco que informam ao núcleo uma escrita bem-sucedida falsa, quando na verdade os dados estão apenas no cache e ainda não foram gravados no disco. Uma queda de energia nesta situação pode conduzir a uma corrupção dos dados não recuperável. Os administradores devem tentar garantir que os discos de armazenamento dos arquivos de log do WAL do PostgreSQL não fazem estes falsos relatos.
335
Após um ponto de controle ter sido feito e o log descarregado, a posição do ponto de controle é salva no arquivo pg_control. Portanto, quando uma recuperação vai ser feita o servidor lê primeiro pg_control e depois o registro de ponto de controle; em seguida realiza a operação de REDO varrendo para frente a partir da posição do log indicada pelo registro de ponto de controle. Como todo o conteúdo das páginas de dados é salvo no log na primeira modificação feita na página após o ponto de controle, todas as páginas modificadas desde o último ponto de controle serão restauradas para um estado coerente. A utilização do pg_control para obter a posição do ponto de controle acelera o processo de recuperação, mas para tratar uma possível corrupção do pg_control deve ser implementada uma leitura dos segmentos de log existentes em ordem inversa (do mais novo para o mais antigo) para poder encontrar o último ponto de controle. Isto ainda não foi implementado.
336
Capítulo 26. Testes de regressão Os testes de regressão compõem um extenso conjunto de testes da implementação do SQL no PostgreSQL. São testadas as operações SQL padrão, assim como as funcionalidades estendidas do PostgreSQL. Do PostgreSQL 6.1 em diante, os testes de regressão estão presentes em todas as distribuições oficiais.
26.1. Execução dos testes Os testes de regressão podem ser executados em um servidor já instalado e em funcionamento, ou utilizando uma instalação temporária dentro da árvore de construção. Além disso, existem os modos “paralelo” e “seqüencial” para execução dos testes. O método seqüencial executa cada um dos scripts de teste por vez, enquanto o método paralelo inicia vários processos servidor para executar grupos de teste em paralelo. Os testes em paralelo dão a confiança de que a comunicação entre processos e bloqueios estão funcionando de forma correta. Por motivos históricos, os testes seqüenciais são geralmente executados em uma instalação existente, e o método paralelo em uma instalação temporária, mas não há motivos técnicos para ser feito assim. Para executar os testes de regressão após construir, mas antes de instalar, digite gmake check
no diretório de nível mais alto (Ou o diretório src/test/regress pode ser tornado o diretório corrente e o comando executado neste diretório). Primeiro serão construídos vários arquivos auxiliares, tais como algumas funções de gatilho de exemplo definidas pelo usuário e, depois, executado o script condutor do teste. Ao final deve ser visto algo parecido com ====================== All 93 tests passed. ======================
ou, senão, uma nota sobre quais testes falharam. Veja a Seção 26.2 abaixo para obter mais informações. Uma vez que este método executa um servidor temporário, não funciona quando se está logado como o usuário root (uma vez que o servidor não inicializa como root). Se foi feita a construção como root, não será
necessário começar tudo novamente. Em vez disto, faça com que o diretório do teste de regressão possa ser escrito por algum outro usuário, se conecte como este usuário, e recomece os testes. Por exemplo: root# chmod -R a+w src/test/regress root# chmod -R a+w contrib/spi root# su - joeuser joeuser$ cd diretório_de_construção_de_nível_mais_alto joeuser$ gmake check
(O único “risco de segurança” possível neste caso é a possibilidade de outro usuário alterar os resultados do teste de regressão sem que se saiba. Use o bom senso ao gerenciar permissões para usuários). Como alternativa, podem ser executados os testes após a instalação. O teste de regressão paralelo inicializa muitos processos sob o ID do usuário. Atualmente, a simultaneidade máxima são vinte scripts de teste em paralelo, o que significa sessenta processos: existe um processo servidor, o psql e, geralmente, o processo ancestral do interpretador de comandos que chamou o psql, para cada script de teste. Portanto, se o sistema impuser um limite no número de processos por usuário, certifique-se que este limite é de setenta e cinco ou maior, senão podem acontecer falhas aleatórias no teste paralelo. Se não houver condição de aumentar este limite, pode ser diminuído o grau de paralelismo definindo o parâmetro MAX_CONNECTIONS. Por exemplo, gmake MAX_CONNECTIONS=10 check
não executa mais de dez testes ao mesmo tempo.
337
Em alguns sistemas o interpretador de comandos padrão compatível com o Bourne (/bin/sh) se confunde ao gerenciar tantos processos descendentes em paralelo, podendo fazer com que o teste paralelo trave ou falhe. Nestes casos, deve ser especificado um interpretador de comandos compatível com o Bourne diferente na linha de comandos como, por exemplo: gmake SHELL=/bin/ksh check
Se não estiver disponível nenhum interpretador de comandos que não apresente este problema, então este problema poderá ser superado limitando o número de conexões, conforme mostrado acima. Para executar os testes após a instalação (veja o Capítulo 14), deve ser inicializada a área de dados e ativado o servidor, conforme explicado no Capítulo 16, e depois digitado: gmake installcheck
Os testes esperam fazer contato com o servidor no hospedeiro local no número de porta padrão, a menos que esteja especificado o contrário nas variáveis de ambiente PGHOST e PGPORT.
26.2. Avaliação dos testes Algumas instalações do PostgreSQL, devidamente instaladas e totalmente funcionais, podem “falhar” em alguns testes de regressão por causa de algumas peculiaridades específicas da plataforma, tais como o ponto flutuante representado de maneira diferente ou o suporte a zona horária. Atualmente a avaliação dos testes é feita simplesmente usando o programa diff para comparar os resultados obtidos pelos testes com os resultados produzidos no sistema de referência e, portanto, os testes são sensíveis a pequenas diferenças entre os sistemas. Quando for informado que o teste “falhou”, sempre deve ser examinada a diferença entre o resultado esperado e o resultado obtido; pode ser descoberto que as diferenças não são significativas. Ainda assim, são feitos esforços para manter os arquivos de referência idênticos entre todas as plataformas suportadas, portanto deve ser esperado que todos os testes passem. As
saídas
produzidas
pelos
testes
de
regressão
ficam
nos
arquivos
do
diretório
src/test/regress/results. Os scripts dos testes utilizam o programa diff para comparar cada arquivo de saída produzido com a saída de referência armazenada no diretório src/test/regress/expected. Todas as diferenças são salvas em src/test/regress/regression.diffs para poderem ser inspecionadas (ou você mesmo pode executar o programa diff, se preferir).
26.2.1. Diferenças nas mensagens de erro Alguns testes de regressão envolvem, intencionalmente, valores de entrada inválidos. As mensagens de erro podem ser originadas pelo código do PostgreSQL ou pelas rotinas do sistema da plataforma hospedeira. No último caso, as mensagens podem variar entre plataformas, mas devem conter informações semelhantes. Estas diferenças nas mensagens resultam em testes de regressão que “falham”, mas que podem ser validados por inspeção.
26.2.2. Diferenças na localização Se os testes forem executados em um servidor já instalado, que foi inicializado com informação de agrupamento (LC_COLLATE) em uma localização que não seja C, então podem haver diferenças por causa da ordem de classificação e falhas posteriores. O conjunto de testes de regressão é configurado para tratar este problema mediante arquivos de resultado alternativos, que juntos podem tratar um grande número de localizações. Por exemplo, para o teste char o arquivo esperado char.out trata as localizações C e POSIX, e o arquivo char_1.out trata várias outras localizações. O condutor do teste de regressão pega automaticamente o melhor arquivo para fazer a comparação ao verificar se foi bem-sucedido e para computar as diferenças da falha (Isto significa que os testes de regressão não conseguem detectar se os resultados são apropriados para a localização configurada. Os testes simplesmente pegam o arquivo de resultado que melhor se adequar). Se por alguma razão os arquivos esperados existentes não incluírem alguma localização, é possível adicionar um novo arquivo. O esquema de nomes é nomedoteste_dígito.out. O dígito utilizado não tem importância. Lembre-se que o condutor do teste de regressão considera todos os arquivos deste tipo como
338
sendo resultados de teste igualmente válidos. Se os resultados do teste forem específicos para alguma plataforma, em vez dessa abordagem deve ser utilizada a técnica descrita na Seção 26.3.
26.2.3. Diferenças na data e hora Uns poucos testes horology 1 falham se forem executados próximo do início do horário de verão, ou próximo do término de um. Estas consultas esperam que os intervalos entre a meia-noite de ontem, a meia noite de hoje e a meia-noite de amanhã sejam de exatamente vinte e quatro horas --- o que não acontece se o início ou o fim do horário de verão ocorrer neste intervalo. Nota: Uma vez que são utilizadas as regras de horário de verão (daylight-saving time) dos EUA, este problema sempre ocorre no primeiro domingo de abril, no último domingo de outubro, e nas segundasfeiras seguintes, não importando quando o horário de verão começa ou termina onde se mora. Observe, também, que este problema aparece ou desaparece à meia-noite do Horário do Pacífico (UTC-7 ou UTC8), e não à meia-noite do horário local. Portanto, a falha pode ocorrer no sábado ou durar até terça-feira dependendo de onde se mora.
A maior parte dos resultados de data e hora são dependentes da zona horária do ambiente. Os arquivos de referência são gerados para a zona horária PST8PDT (Berkeley, Califórnia), havendo falhas aparentes se os testes não forem executados com esta definição de zona horária. O condutor do teste de regressão define a variável de ambiente PGTZ como PST8PDT, o que normalmente garante resultados apropriados. Entretanto, o sistema operacional deve prover suporte a zona horária PST8PDT, ou os testes dependentes da zona horária falham. Para verificar se a máquina possui este suporte, digite: env TZ=PST8PDT date # Resultado no Fedora Core 3 (N. do T.) # (GMT-8) - (GMT-3) = -5 horas Sáb Fev 26 03:23:45 PST 2005 $ date Sáb Fev 26 08:23:45 BRT 2005
O comando acima deve retornar a hora corrente do sistema na zona horária PST8PDT. Se a zona horária PST8PDT não estiver disponível, então o sistema pode retornar a hora em UTC. Se a zona horária PST8PDT não estiver presente, podem ser definidas as regras de zona horária explicitamente: PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
Parece haver alguns sistemas que não aceitam a sintaxe recomendada para a definição explícita das regras de zona horária local; pode ser necessário utilizar uma definição diferente de PGTZ nestas máquinas. Alguns sistemas que utilizam bibliotecas antigas de zona horária falham ao aplicar as correções do horário de verão em datas anteriores a 1970, fazendo com que as horas PDT anteriores 1970 sejam mostradas em PST. Este problema ocasiona diferenças localizadas nos resultados do teste.
26.2.4. Diferenças no ponto flutuante Alguns testes incluem calcular números de ponto flutuante de 64 bits (double precision) a partir de colunas das tabelas. Foram observadas diferenças nos resultados quando estão envolvidas funções matemáticas aplicadas a colunas do tipo double precision. Os testes float8 e geometry são particularmente propensos a apresentar pequenas diferenças entre plataformas, ou por causa das diferentes opções de otimização do compilador. São necessárias comparações utilizando o olho humano para determinar se estas diferenças, que geralmente estão dez casas à direita do ponto decimal, são significativas. Alguns sistemas mostram menos zero como -0, enquanto outros simplesmente mostram 0. Alguns sistemas sinalizam erros das funções pow() e exp() de forma diferente da esperada pelo código corrente do PostgreSQL.
26.2.5. Diferenças na ordem das linhas Podem ser encontradas diferenças onde as mesmas linhas são geradas em uma ordem diferente da esperada pelo arquivo de comparação. Na maior parte das vezes isto não é, a rigor, um erro. Os scripts de teste de
339
regressão, em sua maioria, não são tão precisos a ponto de utilizar a cláusula ORDER BY em todos os comandos SELECT e, portanto, a ordem das linhas do resultado não é bem definida, de acordo com o texto de especificação do padrão SQL. Na prática, uma vez que se está examinando as mesmas consultas sendo executadas nos mesmos dados pelo mesmo programa, são obtidos resultados na mesma ordem em todas as plataformas e, por isso, a ausência do ORDER BY não se torna um problema. Entretanto, algumas consultas apresentam diferenças na ordem das linhas entre plataformas (Diferenças na ordem das linhas também podem ser ocasionadas pela definição de uma localização diferente de C). Portanto, se houver diferença na ordem das linhas isto não é algo com que devamos nos preocupar, a menos que o resultado da consulta possua uma cláusula ORDER BY que esteja sendo violada. Mas, por favor, relate de qualquer forma para que possamos adicionar a cláusula ORDER BY a esta consulta em particular e, com isso, eliminar a falsa “falha” nas próximas versões. Deve-se estar querendo saber porque todas as consultas dos testes de regressão não são ordenadas explicitamente, para acabar com este problema de uma vez e para sempre. A razão é que isto torna os testes de regressão menos úteis, e não mais úteis, porque vão tender a utilizar tipos de plano de consulta que produzem resultados ordenados, prejudicando àqueles que não o fazem.
26.2.6. O teste “random” Existe pelo menos um caso no script de teste random que tem por finalidade produzir resultados randômicos. Isto faz com que random falhe no teste de regressão de vez em quando (talvez uma a cada cinco ou dez tentativas). Ao ser digitado diff results/random.out expected/random.out
deve ser mostrada uma ou poucas linhas diferentes. Não há necessidade de se preocupar, a menos que o teste random sempre falhe em tentativas sucessivas (Por outro lado, se o teste random nunca informar falha, mesmo
após muitas execuções dos testes de regressão, então provavelmente você deve se preocupar).
26.3. Arquivos de comparação específicos de plataformas Como alguns testes produzem resultados inerentes a uma determinada plataforma, é disponibilizada uma maneira de fornecer arquivos de comparação de resultados específicos para a plataforma. Com freqüência a mesma discrepância se aplica a várias plataformas; em vez de fornecer arquivos de comparação distintos para todas as plataformas, existe um arquivo de mapeamento que define o arquivo de comparação a ser utilizado. Portanto, para eliminar falsas “falhas” nos testes para uma determinada plataforma, deve ser escolhido ou desenvolvido um arquivo de resultado alternativo, e depois adicionada uma linha no arquivo de mapeamento, que é o src/test/regress/resultmap. Cada uma das linhas do arquivo de mapeamento possui a forma: nome_do_teste/padrão_de_plataforma=nome_do_arquivo_de_comparação
O nome do teste é simplesmente o nome do módulo de teste de regressão específico. O padrão de plataforma é o padrão no estilo da ferramenta Unix expr (ou seja, uma expressão regular com uma âncora ^ implícita no início). É comparado com o nome da plataforma conforme exibido por config.guess seguido por :gcc ou :cc, dependendo se for utilizado o compilador GNU ou o compilador nativo do sistema (nos sistemas onde há diferença). O nome do arquivo de comparação é o nome do arquivo de comparação de resultado alternativo. Por exemplo: alguns sistemas que utilizam bibliotecas antigas de zona horária falham ao aplicar as correções do horário de verão em datas anteriores a 1970, fazendo com que horas PDT anteriores a 1970 sejam mostradas em PST. Isto causa uma pequena diferença no teste de regressão horology. Portanto, é disponibilizado um arquivo de comparação alternativo, horology-no-DST-before-1970.out, que inclui os resultados esperados nestes sistemas. Para silenciar as mensagens falsas de “falha” nas plataformas HPUX, o arquivo resultmap inclui horology/.*-hpux=horology-no-DST-before-1970
340
que será disparado em toda máquina para a qual a saída de config.guess incluir -hpux. Outras linhas no arquivo resultmap selecionam arquivos de comparação alternativos para outras plataformas conforme apropriado.
Notas 1. horology — A ciência da medição do tempo, ou os princípios e a arte da construção de instrumentos para medir e indicar porções do tempo, como relógios, cronômetros, etc. Webster's Revised Unabridged Dictionary (1913) (N. do T.)
341
IV. Interfaces cliente Esta parte descreve as interfaces de programação cliente distribuídas com o PostgreSQL. Cada um destes capítulos pode ser lido de forma independente. Observe que existem muitas outras interfaces de programação para programas cliente distribuídas separadamente, cada uma contendo sua própria documentação. Os leitores desta parte devem estar familiarizados com a utilização dos comandos SQL usados para manipular e consultar os bancos de dados (veja a Parte II) e, naturalmente, com a linguagem de programação utilizada pela interface.
342
Capítulo 27. libpq - C Library libpq is the C application programmer's interface to PostgreSQL. libpq is a set of library functions that allow client programs to pass queries to the PostgreSQL backend server and to receive the results of these queries. libpq is also the underlying engine for several other PostgreSQL application interfaces, including libpq++ (C++), libpgtcl (Tcl), Perl, and ECPG. So some aspects of libpq's behavior will be important to you if you use one of those packages. Some short programs are included at the end of this chapter (Seção 27.14) to show how to write programs that use libpq. There are also several complete examples of libpq applications in the directory src/test/examples in the source code distribution. Client programs that use libpq must include the header file libpq-fe.h and must link with the libpq library.
27.1. Database Connection Control Functions The following functions deal with making a connection to a PostgreSQL backend server. An application program can have several backend connections open at one time. (One reason to do that is to access more than one database.) Each connection is represented by a PGconn object which is obtained from the function PQconnectdb or PQsetdbLogin. Note that these functions will always return a non-null object pointer, unless perhaps there is too little memory even to allocate the PGconn object. The PQstatus function should be called to check whether a connection was successfully made before queries are sent via the connection object. PQconnectdb
Makes a new connection to the database server. PGconn *PQconnectdb(const char *conninfo);
This function opens a new database connection using the parameters taken from the string conninfo. Unlike PQsetdbLogin below, the parameter set can be extended without changing the function signature, so use of this function (or its nonblocking analogues PQconnectStart and PQconnectPoll) is preferred for new application programming. The passed string can be empty to use all default parameters, or it can contain one or more parameter settings separated by whitespace. Each parameter setting is in the form keyword = value. (To write an empty value or a value containing spaces, surround it with single quotes, e.g., keyword = 'a value'. Single quotes and backslashes within the value must be escaped with a backslash, i.e., \' and \\.) Spaces around the equal sign are optional. The currently recognized parameter key words are: host
Name of host to connect to. If this begins with a slash, it specifies Unix-domain communication rather than TCP/IP communication; the value is the name of the directory in which the socket file is stored. The default is to connect to a Unix-domain socket in /tmp. hostaddr
Numeric IP address of host to connect to. This should be in the standard IPv4 address format, e.g., 172.28.40.9. If your machine supports IPv6, you can also use those addresses. TCP/IP
communication is always used when a nonempty string is specified for this parameter. Using hostaddr instead of host allows the application to avoid a host name look-up, which may be important in applications with time constraints. However, Kerberos authentication requires the host name. The following therefore applies: If host is specified without hostaddr, a host name lookup occurs. If hostaddr is specified without host, the value for hostaddr gives the remote address. When Kerberos is used, a reverse name query occurs to obtain the host name for Kerberos. If both host and hostaddr are specified, the value for hostaddr gives the remote address; the value for host is ignored, unless Kerberos is used, in which case that value is used for Kerberos authentication. (Note that authentication is likely to fail if libpq is passed a host name that is not the
343
name of the machine at hostaddr.) Also, host rather than hostaddr is used to identify the connection in $HOME/.pgpass. Without either a host name or host address, libpq will connect using a local Unix domain socket. port
Port number to connect to at the server host, or socket file name extension for Unix-domain connections. dbname
The database name. Defaults to be the same as the user name. user
PostgreSQL user name to connect as. password
Password to be used if the server demands password authentication. connect_timeout
Maximum wait for connection, in seconds (write as a decimal integer string). Zero or not specified means wait indefinitely. It is not recommended to use a timeout of less than 2 seconds. options
Command-line options to be sent to the server. tty
Ignored (formerly, this specified where to send server debug output). sslmode
This option determines whether or with what priority an SSL connection will be negotiated with the server. There are four modes: disable will attempt only an unencrypted SSL connection; allow will negotiate, trying first a non-SSL connection, then if that fails, trying an SSL connection; prefer (the default) will negotiate, trying first an SSL connection, then if that fails, trying a regular non-SSL connection; require will try only an SSL connection. If PostgreSQL is compiled without SSL support, using option require will cause an error, and options allow and prefer will be tolerated but libpq will be unable to negotiate an SSL connection. requiressl
This option is deprecated in favor of the sslmode setting. If set to 1, an SSL connection to the server is required (this is equivalent to sslmode require). libpq will then refuse to connect if the server does not accept an SSL connection. If set to 0 (default), libpq will negotiate the connection type with the server (equivalent to sslmode prefer). This option is only available if PostgreSQL is compiled with SSL support. service
Service name to use for additional parameters. It specifies a service name in pg_service.conf that holds additional connection parameters. This allows applications to specify only a service name so connection parameters can be centrally maintained. See PREFIX/share/pg_service.conf.sample for information on how to set up the file. If any parameter is unspecified, then the corresponding environment variable (see Seção 27.10) is checked. If the environment variable is not set either, then built-in defaults are used. PQsetdbLogin
Makes a new connection to the database server.
344
PGconn *PQsetdbLogin(const const const const const const const
char char char char char char char
*pghost, *pgport, *pgoptions, *pgtty, *dbName, *login, *pwd);
This is the predecessor of PQconnectdb with a fixed set of parameters. It has the same functionality except that the missing parameters will always take on default values. Write NULL or an empty string for any one of the fixed parameters that is to be defaulted. PQsetdb
Makes a new connection to the database server. PGconn *PQsetdb(char char char char char
*pghost, *pgport, *pgoptions, *pgtty, *dbName);
This is a macro that calls PQsetdbLogin with null pointers for the login and pwd parameters. It is provided for backward compatibility with very old programs. PQconnectStart PQconnectPoll
Make a connection to the database server in a nonblocking manner. PGconn *PQconnectStart(const char *conninfo); PostgresPollingStatusType PQconnectPoll(PGconn *conn);
These two functions are used to open a connection to a database server such that your application's thread of execution is not blocked on remote I/O whilst doing so. The point of this approach is that the waits for I/O to complete can occur in the application's main loop, rather than down inside PQconnectdb, and so the application can manage this operation in parallel with other activities. The database connection is made using the parameters taken from the string conninfo, passed to PQconnectStart. This string is in the same format as described above for PQconnectdb. Neither PQconnectStart nor PQconnectPoll will block, so long as a number of restrictions are met: •
The hostaddr and host parameters are used appropriately to ensure that name and reverse name queries are not made. See the documentation of these parameters under PQconnectdb above for details.
•
If you call PQtrace, ensure that the stream object into which you trace will not block.
•
You ensure that the socket is in the appropriate state before calling PQconnectPoll, as described below.
To
begin a nonblocking connection request, call conn = PQconnectStart( "connection_info_string"). If conn is null, then libpq has been unable to allocate a new PGconn structure. Otherwise, a valid PGconn pointer is returned (though not yet representing a valid connection to the database). On return from PQconnectStart, call status = PQstatus(conn). If status equals CONNECTION_BAD, PQconnectStart has failed. If PQconnectStart succeeds, the next stage is to poll libpq so that it may proceed with the connection sequence. Use PQsocket(conn) to obtain the descriptor of the socket underlying the database connection. Loop thus: If PQconnectPoll(conn) last returned PGRES_POLLING_READING, wait until the socket is ready to read (as indicated by select(), poll(), or similar system function). Then call PQconnectPoll(conn) again. Conversely, if PQconnectPoll(conn) last returned PGRES_POLLING_WRITING, wait until the socket is ready to write, then call PQconnectPoll(conn) again. If you have yet to call PQconnectPoll, i.e., just after the call to PQconnectStart, behave as if it last returned PGRES_POLLING_WRITING. Continue this loop until PQconnectPoll(conn) returns
345
PGRES_POLLING_FAILED, indicating the connection procedure has failed, or PGRES_POLLING_OK,
indicating the connection has been successfully made. At any time during connection, the status of the connection may be checked by calling PQstatus. If this gives CONNECTION_BAD, then the connection procedure has failed; if it gives CONNECTION_OK, then the connection is ready. Both of these states are equally detectable from the return value of PQconnectPoll, described above. Other states may also occur during (and only during) an asynchronous connection procedure. These indicate the current stage of the connection procedure and may be useful to provide feedback to the user for example. These statuses are: CONNECTION_STARTED
Waiting for connection to be made. CONNECTION_MADE
Connection OK; waiting to send. CONNECTION_AWAITING_RESPONSE
Waiting for a response from the server. CONNECTION_AUTH_OK
Received authentication; waiting for backend start-up to finish. CONNECTION_SSL_STARTUP
Negotiating SSL encryption. CONNECTION_SETENV
Negotiating environment-driven parameter settings. Note that, although these constants will remain (in order to maintain compatibility), an application should never rely upon these appearing in a particular order, or at all, or on the status always being one of these documented values. An application might do something like this: switch(PQstatus(conn)) { case CONNECTION_STARTED: feedback = "Connecting..."; break; case CONNECTION_MADE: feedback = "Connected to server..."; break; . . . default: feedback = "Connecting..."; }
The connect_timeout connection parameter is ignored when using PQconnectPoll; it is the application's responsibility to decide whether an excessive amount of time has elapsed. Otherwise, PQconnectStart followed by a PQconnectPoll loop is equivalent to PQconnectdb. Note that if PQconnectStart returns a non-null pointer, you must call PQfinish when you are finished with it, in order to dispose of the structure and any associated memory blocks. This must be done even if the connection attempt fails or is abandoned.
346
PQconndefaults
Returns the default connection options. PQconninfoOption *PQconndefaults(void); typedef struct { char *keyword; char *envvar; char *compiled; char *val; char *label; char *dispchar;
int dispsize; } PQconninfoOption;
/* /* /* /* /* /*
The keyword of the option */ Fallback environment variable name */ Fallback compiled in default value */ Option's current value, or NULL */ Label for field in connect dialog */ Character to display for this field in a connect dialog. Values are: "" Display entered value as is "*" Password field - hide value "D" Debug option - don't show by default */ /* Field size in characters for dialog */
Returns a connection options array. This may be used to determine all possible PQconnectdb options and their current default values. The return value points to an array of PQconninfoOption structures, which ends with an entry having a null keyword pointer. Note that the current default values (val fields) will depend on environment variables and other context. Callers must treat the connection options data as read-only. After processing the options array, free it by passing it to PQconninfoFree. If this is not done, a small amount of memory is leaked for each call to PQconndefaults. PQfinish
Closes the connection to the server. Also frees memory used by the PGconn object. void PQfinish(PGconn *conn);
Note that even if the server connection attempt fails (as indicated by PQstatus), the application should call PQfinish to free the memory used by the PGconn object. The PGconn pointer must not be used again after PQfinish has been called. PQreset
Resets the communication channel to the server. void PQreset(PGconn *conn);
This function will close the connection to the server and attempt to reestablish a new connection to the same server, using all the same parameters previously used. This may be useful for error recovery if a working connection is lost. PQresetStart PQresetPoll
Reset the communication channel to the server, in a nonblocking manner. int PQresetStart(PGconn *conn); PostgresPollingStatusType PQresetPoll(PGconn *conn);
These functions will close the connection to the server and attempt to reestablish a new connection to the same server, using all the same parameters previously used. This may be useful for error recovery if a working connection is lost. They differ from PQreset (above) in that they act in a nonblocking manner. These functions suffer from the same restrictions as PQconnectStart and PQconnectPoll. To initiate a connection reset, call PQresetStart. If it returns 0, the reset has failed. If it returns 1, poll the reset using PQresetPoll in exactly the same way as you would create the connection using PQconnectPoll.
347
27.2. Connection Status Functions These functions may be used to interrogate the status of an existing database connection object. Dica: libpq application programmers should be careful to maintain the PGconn abstraction. Use the accessor functions described below to get at the contents of PGconn. Avoid directly referencing the fields of the PGconn structure because they are subject to change in the future. (Beginning in PostgreSQL release 6.4, the definition of the struct behind PGconn is not even provided in libpq-fe.h. If you have old code that accesses PGconn fields directly, you can keep using it by including libpq-int.h too, but you are encouraged to fix the code soon.)
The following functions return parameter values established at connection. These values are fixed for the life of the PGconn object. PQdb
Returns the database name of the connection. char *PQdb(const PGconn *conn); PQuser
Returns the user name of the connection. char *PQuser(const PGconn *conn); PQpass
Returns the password of the connection. char *PQpass(const PGconn *conn); PQhost
Returns the server host name of the connection. char *PQhost(const PGconn *conn); PQport
Returns the port of the connection. char *PQport(const PGconn *conn); PQtty
Returns the debug TTY of the connection. (This is obsolete, since the server no longer pays attention to the TTY setting, but the function remains for backwards compatibility.) char *PQtty(const PGconn *conn); PQoptions
Returns the command-line options passed in the connection request. char *PQoptions(const PGconn *conn);
The following functions return status data that can change as operations are executed on the PGconn object. PQstatus
Returns the status of the connection. ConnStatusType PQstatus(const PGconn *conn);
The status can be one of a number of values. However, only two of these are seen outside of an asynchronous connection procedure: CONNECTION_OK and CONNECTION_BAD. A good connection to the database has the status CONNECTION_OK. A failed connection attempt is signaled by status CONNECTION_BAD. Ordinarily, an OK status will remain so until PQfinish, but a communications failure might result in the status changing to CONNECTION_BAD prematurely. In that case the application could try to recover by calling PQreset. See the entry for PQconnectStart and PQconnectPoll with regards to other status codes that might be seen.
348
PQtransactionStatus
Returns the current in-transaction status of the server. PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
The status can be PQTRANS_IDLE (currently idle), PQTRANS_ACTIVE (a command is in progress), PQTRANS_INTRANS (idle, in a valid transaction block), or PQTRANS_INERROR (idle, in a failed transaction block). PQTRANS_UNKNOWN is reported if the connection is bad. PQTRANS_ACTIVE is reported only when a query has been sent to the server and not yet completed.
Cuidado PQtransactionStatus will give incorrect results when using a PostgreSQL 7.3 server that has the parameter autocommit set to off. The server-side autocommit feature has been deprecated
and does not exist in later server versions. PQparameterStatus
Looks up a current parameter setting of the server. const char *PQparameterStatus(const PGconn *conn, const char *paramName);
Certain parameter values are reported by the server automatically at connection startup or whenever their values change. PQparameterStatus can be used to interrogate these settings. It returns the current value of a parameter if known, or NULL if the parameter is not known. Parameters reported as of the current release include server_version (cannot change after startup); client_encoding, is_superuser, session_authorization, and DateStyle. Pre-3.0-protocol servers do not report parameter settings, but libpq includes logic to obtain values for server_version, and client_encoding. Applications are encouraged to use PQparameterStatus
rather than ad-hoc code to determine these values. (Beware however that on a pre-3.0 connection, changing client_encoding via SET after connection startup will not be reflected by PQparameterStatus.) PQprotocolVersion
Interrogates the frontend/backend protocol being used. int PQprotocolVersion(const PGconn *conn);
Applications may wish to use this to determine whether certain features are supported. Currently, the possible values are 2 (2.0 protocol), 3 (3.0 protocol), or zero (connection bad). This will not change after connection startup is complete, but it could theoretically change during a reset. The 3.0 protocol will normally be used when communicating with PostgreSQL 7.4 or later servers; pre-7.4 servers support only protocol 2.0. (Protocol 1.0 is obsolete and not supported by libpq.) PQerrorMessage
Returns the error message most recently generated by an operation on the connection. char *PQerrorMessage(const PGconn* conn);
Nearly all libpq functions will set a message for PQerrorMessage if they fail. Note that by libpq convention, a nonempty PQerrorMessage result will include a trailing newline. PQsocket
Obtains the file descriptor number of the connection socket to the server. A valid descriptor will be greater than or equal to 0; a result of -1 indicates that no server connection is currently open. (This will not change during normal operation, but could change during connection setup or reset.) int PQsocket(const PGconn *conn); PQbackendPID
Returns the process ID (PID) of the backend server process handling this connection. int PQbackendPID(const PGconn *conn);
349
The backend PID is useful for debugging purposes and for comparison to NOTIFY messages (which include the PID of the notifying backend process). Note that the PID belongs to a process executing on the database server host, not the local host! PQgetssl
Returns the SSL structure used in the connection, or null if SSL is not in use. SSL *PQgetssl(const PGconn *conn);
This structure can be used to verify encryption levels, check server certificates, and more. Refer to the OpenSSL documentation for information about this structure. You must define USE_SSL in order to get the prototype for this function. Doing this will also automatically include ssl.h from OpenSSL.
27.3. Command Execution Functions Once a connection to a database server has been successfully established, the functions described here are used to perform SQL queries and commands.
27.3.1. Main Functions PQexec
Submits a command to the server and waits for the result. PGresult *PQexec(PGconn *conn, const char *command);
Returns a PGresult pointer or possibly a null pointer. A non-null pointer will generally be returned except in out-of-memory conditions or serious errors such as inability to send the command to the server. If a null pointer is returned, it should be treated like a PGRES_FATAL_ERROR result. Use PQerrorMessage to get more information about the error. It is allowed to include multiple SQL commands (separated by semicolons) in the command string. Multiple queries sent in a single PQexec call are processed in a single transaction, unless there are explicit BEGIN/COMMIT commands included in the query string to divide it into multiple transactions. Note however that the returned PGresult structure describes only the result of the last command executed from the string. Should one of the commands fail, processing of the string stops with it and the returned PGresult describes the error condition. PQexecParams
Submits a command to the server and waits for the result, with the ability to pass parameters separately from the SQL command text. PGresult *PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat); PQexecParams is like PQexec, but offers additional functionality: parameter values can be specified
separately from the command string proper, and query results can be requested in either text or binary format. PQexecParams is supported only in protocol 3.0 and later connections; it will fail when using protocol 2.0. If parameters are used, they are referred to in the command string as $1, $2, etc. nParams is the number of parameters supplied; it is the length of the arrays paramTypes[], paramValues[], paramLengths[], and paramFormats[]. (The array pointers may be NULL when nParams is zero.) paramTypes[] specifies, by OID, the data types to be assigned to the parameter symbols. If paramTypes is NULL, or any particular element in the array is zero, the server assigns a data type to the parameter symbol in the same way it would do for an untyped literal string. paramValues[] specifies the actual values of the parameters. A null pointer in this array means the corresponding parameter is null;
350
otherwise the pointer points to a zero-terminated text string (for text format) or binary data in the format expected by the server (for binary format). paramLengths[] specifies the actual data lengths of binary-format parameters. It is ignored for null parameters and text-format parameters. The array pointer may be null when there are no binary parameters. paramFormats[] specifies whether parameters are text (put a zero in the array) or binary (put a one in the array). If the array pointer is null then all parameters are presumed to be text. resultFormat is zero to obtain results in text format, or one to obtain results in binary format. (There is not currently a provision to obtain different result columns in different formats, although that is possible in the underlying protocol.) The primary advantage of PQexecParams over PQexec is that parameter values may be separated from the command string, thus avoiding the need for tedious and error-prone quoting and escaping. Unlike PQexec, PQexecParams allows at most one SQL command in the given string. (There can be semicolons in it, but not more than one nonempty command.) This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks. PQexecPrepared
Sends a request to execute a prepared statement with given parameters, and waits for the result. PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat); PQexecPrepared is like PQexecParams, but the command to be executed is specified by naming a
previously-prepared statement, instead of giving a query string. This feature allows commands that will be used repeatedly to be parsed and planned just once, rather than each time they are executed. PQexecPrepared is supported only in protocol 3.0 and later connections; it will fail when using protocol 2.0. The parameters are identical to PQexecParams, except that the name of a prepared statement is given instead of a query string, and the paramTypes[] parameter is not present (it is not needed since the prepared statement's parameter types were determined when it was created). Presently, prepared statements for use with PQexecPrepared must be set up by executing an SQL PREPARE command, which is typically sent with PQexec (though any of libpq's query-submission functions may be used). A lower-level interface for preparing statements may be offered in a future release. The PGresult structure encapsulates the result returned by the server. libpq application programmers should be careful to maintain the PGresult abstraction. Use the accessor functions below to get at the contents of PGresult. Avoid directly referencing the fields of the PGresult structure because they are subject to change in the future. PQresultStatus
Returns the result status of the command. ExecStatusType PQresultStatus(const PGresult *res); PQresultStatus can return one of the following values: PGRES_EMPTY_QUERY
The string sent to the server was empty. PGRES_COMMAND_OK
Successful completion of a command returning no data. PGRES_TUPLES_OK
Successful completion of a command returning data (such as a SELECT or SHOW). PGRES_COPY_OUT
Copy Out (from server) data transfer started.
351
PGRES_COPY_IN
Copy In (to server) data transfer started. PGRES_BAD_RESPONSE
The server's response was not understood. PGRES_NONFATAL_ERROR
A nonfatal error (a notice or warning) occurred. PGRES_FATAL_ERROR
A fatal error occurred. If the result status is PGRES_TUPLES_OK, then the functions described below can be used to retrieve the rows returned by the query. Note that a SELECT command that happens to retrieve zero rows still shows PGRES_TUPLES_OK. PGRES_COMMAND_OK is for commands that can never return rows (INSERT, UPDATE, etc.). A response of PGRES_EMPTY_QUERY may indicate a bug in the client software. A result of status PGRES_NONFATAL_ERROR will never be returned directly by PQexec or other query execution functions; results of this kind are instead passed to the notice processor (see Seção 27.9). PQresStatus
Converts the enumerated type returned by PQresultStatus into a string constant describing the status code. char *PQresStatus(ExecStatusType status); PQresultErrorMessage
Returns the error message associated with the command, or an empty string if there was no error. char *PQresultErrorMessage(const PGresult *res);
If there was an error, the returned string will include a trailing newline. Immediately following a PQexec or PQgetResult call, PQerrorMessage (on the connection) will return the same string as PQresultErrorMessage (on the result). However, a PGresult will retain its error message until destroyed, whereas the connection's error message will change when subsequent operations are done. Use PQresultErrorMessage when you want to know the status associated with a particular PGresult; use PQerrorMessage when you want to know the status from the latest operation on the connection. PQresultErrorField
Returns an individual field of an error report. char *PQresultErrorField(const PGresult *res, int fieldcode);
fieldcode is an error field identifier; see the symbols listed below. NULL is returned if the PGresult is not an error or warning result, or does not include the specified field. Field values will normally not include a trailing newline. The following field codes are available: PG_DIAG_SEVERITY
The severity; the field contents are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a localized translation of one of these. Always present. PG_DIAG_SQLSTATE
The SQLSTATE code for the error (see Apêndice A). Not localizable. Always present. PG_DIAG_MESSAGE_PRIMARY
The primary human-readable error message (typically one line). Always present.
352
PG_DIAG_MESSAGE_DETAIL
Detail: an optional secondary error message carrying more detail about the problem. May run to multiple lines. PG_DIAG_MESSAGE_HINT
Hint: an optional suggestion what to do about the problem. This is intended to differ from detail in that it offers advice (potentially inappropriate) rather than hard facts. May run to multiple lines. PG_DIAG_STATEMENT_POSITION
A string containing a decimal integer indicating an error cursor position as an index into the original statement string. The first character has index 1, and positions are measured in characters not bytes. PG_DIAG_CONTEXT
An indication of the context in which the error occurred. Presently this includes a call stack traceback of active PL functions. The trace is one entry per line, most recent first. PG_DIAG_SOURCE_FILE
The file name of the source-code location where the error was reported. PG_DIAG_SOURCE_LINE
The line number of the source-code location where the error was reported. PG_DIAG_SOURCE_FUNCTION
The name of the source-code function reporting the error. The client is responsible for formatting displayed information to meet its needs; in particular it should break long lines as needed. Newline characters appearing in the error message fields should be treated as paragraph breaks, not line breaks. Errors generated internally by libpq will have severity and primary message, but typically no other fields. Errors returned by a pre-3.0-protocol server will include severity and primary message, and sometimes a detail message, but no other fields. Note that error fields are only available from PGresult objects, not PGconn objects; there is no PQerrorField function. PQclear
Frees the storage associated with a PGresult. Every command result should be freed via PQclear when it is no longer needed. void PQclear(PQresult *res);
You can keep a PGresult object around for as long as you need it; it does not go away when you issue a new command, nor even if you close the connection. To get rid of it, you must call PQclear. Failure to do this will result in memory leaks in your application. PQmakeEmptyPGresult
Constructs an empty PGresult object with the given status. PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
This is libpq's internal function to allocate and initialize an empty PGresult object. It is exported because some applications find it useful to generate result objects (particularly objects with error status) themselves. If conn is not null and status indicates an error, the current error message of the specified connection is copied into the PGresult. Note that PQclear should eventually be called on the object, just as with a PGresult returned by libpq itself.
27.3.2. Retrieving Query Result Information These functions are used to extract information from a PGresult object that represents a successful query result (that is, one that has status PGRES_TUPLES_OK). For objects with other status values they will act as though the result has zero rows and zero columns.
353
PQntuples
Returns the number of rows (tuples) in the query result. int PQntuples(const PGresult *res); PQnfields
Returns the number of columns (fields) in each row of the query result. int PQnfields(const PGresult *res); PQfname
Returns the column name associated with the given column number. Column numbers start at 0. char *PQfname(const PGresult *res, int column_number); NULL is returned if the column number is out of range. PQfnumber
Returns the column number associated with the given column name. int PQfnumber(const PGresult *res, const char *column_name);
-1 is returned if the given name does not match any column. The given name is treated like an identifier in an SQL command, that is, it is downcased unless doublequoted. For example, given a query result generated from the SQL command select 1 as FOO, 2 as "BAR";
we would have the results: PQfname(res, 0) PQfname(res, 1) PQfnumber(res, "FOO") PQfnumber(res, "foo") PQfnumber(res, "BAR") PQfnumber(res, "\"BAR\"")
foo BAR 0 0 -1 1
PQftable
Returns the OID of the table from which the given column was fetched. Column numbers start at 0. Oid PQftable(const PGresult *res, int column_number); InvalidOid is returned if the column number is out of range, or if the specified column is not a simple reference to a table column, or when using pre-3.0 protocol. You can query the system table pg_class to
determine exactly which table is referenced. The type Oid and the constant InvalidOid will be defined when you include the libpq header file. They will both be some integer type. PQftablecol
Returns the column number (within its table) of the column making up the specified query result column. Result column numbers start at 0. int PQftablecol(const PGresult *res, int column_number);
Zero is returned if the column number is out of range, or if the specified column is not a simple reference to a table column, or when using pre-3.0 protocol. PQfformat
Returns the format code indicating the format of the given column. Column numbers start at 0. int PQfformat(const PGresult *res, int column_number);
354
Format code zero indicates textual data representation, while format code one indicates binary representation. (Other codes are reserved for future definition.) PQftype
Returns the data type associated with the given column number. The integer returned is the internal OID number of the type. Column numbers start at 0. Oid PQftype(const PGresult *res, int column_number);
You can query the system table pg_type to obtain the names and properties of the various data types. The OIDs of the built-in data types are defined in the file src/include/catalog/pg_type.h in the source tree. PQfmod
Returns the type modifier of the column associated with the given column number. Column numbers start at 0. int PQfmod(const PGresult *res, int column_number);
The interpretation of modifier values is type-specific; they typically indicate precision or size limits. The value -1 is used to indicate “no information available”. Most data types do not use modifiers, in which case the value is always -1. PQfsize
Returns the size in bytes of the column associated with the given column number. Column numbers start at 0. int PQfsize(const PGresult *res, int column_number); PQfsize returns the space allocated for this column in a database row, in other words the size of the server's internal representation of the data type. (Accordingly, it is not really very useful to clients.) A negative value indicates the data type is variable-length. PQbinaryTuples
Returns 1 if the PGresult contains binary data and 0 if it contains text data. int PQbinaryTuples(const PGresult *res);
This function is deprecated (except for its use in connection with COPY), because it is possible for a single PGresult to contain text data in some columns and binary data in others. PQfformat is preferred. PQbinaryTuples returns 1 only if all columns of the result are binary (format 1). PQgetvalue
Returns a single field value of one row of a PGresult. Row and column numbers start at 0. char* PQgetvalue(const PGresult *res, int row_number, int column_number);
For data in text format, the value returned by PQgetvalue is a null-terminated character string representation of the field value. For data in binary format, the value is in the binary representation determined by the data type's typsend and typreceive functions. (The value is actually followed by a zero byte in this case too, but that is not ordinarily useful, since the value is likely to contain embedded nulls.) An empty string is returned if the field value is null. See PQgetisnull to distinguish null values from empty-string values. The pointer returned by PQgetvalue points to storage that is part of the PGresult structure. One should not modify the data it points to, and one must explicitly copy the data into other storage if it is to be used past the lifetime of the PGresult structure itself.
355
PQgetisnull
Tests a field for a null value. Row and column numbers start at 0. int PQgetisnull(const PGresult *res, int row_number, int column_number);
This function returns 1 if the field is null and 0 if it contains a non-null value. (Note that PQgetvalue will return an empty string, not a null pointer, for a null field.) PQgetlength
Returns the actual length of a field value in bytes. Row and column numbers start at 0. int PQgetlength(const PGresult *res, int row_number, int column_number);
This is the actual data length for the particular data value, that is, the size of the object pointed to by PQgetvalue. For text data format this is the same as strlen(). For binary format this is essential information. Note that one should not rely on PQfsize to obtain the actual data length. PQprint
Prints out all the rows and, optionally, the column names to the specified output stream. void PQprint(FILE* fout, /* output stream */ const PGresult *res, const PQprintOpt *po); typedef struct { pqbool header;
/* print output field headings and row count */ pqbool align; /* fill align the fields */ pqbool standard; /* old brain dead format */ pqbool html3; /* output HTML tables */ pqbool expanded; /* expand tables */ pqbool pager; /* use pager for output if needed */ char *fieldSep; /* field separator */ char *tableOpt; /* attributes for HTML table element */ char *caption; /* HTML table caption */ char **fieldName; /* null-terminated array of replacement field names */ } PQprintOpt;
This function was formerly used by psql to print query results, but this is no longer the case. Note that it assumes all the data is in text format.
27.3.3. Retrieving Result Information for Other Commands These functions are used to extract information from PGresult objects that are not SELECT results. PQcmdStatus
Returns the command status tag from the SQL command that generated the PGresult. char * PQcmdStatus(PGresult *res);
Commonly this is just the name of the command, but it may include additional data such as the number of rows processed. PQcmdTuples
Returns the number of rows affected by the SQL command. char * PQcmdTuples(PGresult *res);
If the SQL command that generated the PGresult was INSERT, UPDATE, DELETE, MOVE, or FETCH, this returns a string containing the number of rows affected. If the command was anything else, it returns the empty string.
356
PQoidValue
Returns the OID of the inserted row, if the SQL command was an INSERT that inserted exactly one row into a table that has OIDs. Otherwise, returns InvalidOid. Oid PQoidValue(const PGresult *res); PQoidStatus
Returns a string with the OID of the inserted row, if the SQL command was an INSERT. (The string will be 0 if the INSERT did not insert exactly one row, or if the target table does not have OIDs.) If the command was not an INSERT, returns an empty string. char * PQoidStatus(const PGresult *res);
This function is deprecated in favor of PQoidValue. It is not thread-safe.
27.3.4. Escaping Strings for Inclusion in SQL Commands PQescapeString escapes a string for use within an SQL command. This is useful when inserting data values as literal constants in SQL commands. Certain characters (such as quotes and backslashes) must be escaped to prevent them from being interpreted specially by the SQL parser. PQescapeString performs this operation. Dica: It is especially important to do proper escaping when handling strings that were received from an untrustworthy source. Otherwise there is a security risk: you are vulnerable to “SQL injection” attacks wherein unwanted SQL commands are fed to your database.
Note that it is not necessary nor correct to do escaping when a data value is passed as a separate parameter in PQexecParams or its sibling routines. size_t PQescapeString (char *to, const char *from, size_t length);
The parameter from points to the first character of the string that is to be escaped, and the length parameter gives the number of characters in this string. A terminating zero byte is not required, and should not be counted in length. (If a terminating zero byte is found before length bytes are processed, PQescapeString stops at the zero; the behavior is thus rather like strncpy.) to shall point to a buffer that is able to hold at least one more character than twice the value of length, otherwise the behavior is undefined. A call to PQescapeString writes an escaped version of the from string to the to buffer, replacing special characters so that they cannot cause any harm, and adding a terminating zero byte. The single quotes that must surround PostgreSQL string literals are not included in the result string; they should be provided in the SQL command that the result is inserted into. PQescapeString returns the number of characters written to to, not including the terminating zero byte.
Behavior is undefined if the to and from strings overlap.
27.3.5. Escaping Binary Strings for Inclusion in SQL Commands PQescapeBytea
Escapes binary data for use within an SQL command with the type bytea. As with PQescapeString, this is only used when inserting data directly into an SQL command string. unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length);
Certain byte values must be escaped (but all byte values may be escaped) when used as part of a bytea literal in an SQL statement. In general, to escape a byte, it is converted into the three digit octal number equal to the octet value, and preceded by two backslashes. The single quote (') and backslash (\) characters have special alternative escape sequences. See Seção 8.4 for more information. PQescapeBytea performs this operation, escaping only the minimally required bytes. The from parameter points to the first byte of the string that is to be escaped, and the from_length parameter gives the number of bytes in this binary string. (A terminating zero byte is neither necessary nor
357
counted.) The to_length parameter points to a variable that will hold the resultant escaped string length. The result string length includes the terminating zero byte of the result. PQescapeBytea returns an escaped version of the from parameter binary string in memory allocated with malloc(). This memory must be freed using PQfreemem when the result is no longer needed. The return string has all special characters replaced so that they can be properly processed by the PostgreSQL string literal parser, and the bytea input function. A terminating zero byte is also added. The single quotes that must surround PostgreSQL string literals are not part of the result string. PQunescapeBytea
Converts an escaped string representation of binary data into binary data --- the reverse of PQescapeBytea. This is needed when retrieving bytea data in text format, but not when retrieving it in
binary format. unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
The from parameter points to an escaped string such as might be returned by PQgetvalue when applied to a bytea column. PQunescapeBytea converts this string representation into its binary representation. It returns a pointer to a buffer allocated with malloc(), or null on error, and puts the size of the buffer in to_length. The result must be freed using PQfreemem when it is no longer needed. PQfreemem
Frees memory allocated by libpq. void PQfreemem(void *ptr);
Frees memory allocated by libpq, particularly PQescapeBytea, PQunescapeBytea, and PQnotifies. It is needed by Microsoft Windows, which cannot free memory across DLLs, unless multithreaded DLLs (/MD in VC6) are used. On other platforms, this function is the same as the standard library function free().
27.4. Asynchronous Command Processing The PQexec function is adequate for submitting commands in normal, synchronous applications. It has a couple of deficiencies, however, that can be of importance to some users: waits for the command to be completed. The application may have other work to do (such as maintaining a user interface), in which case it won't want to block waiting for the response.
• PQexec
•
Since the execution of the client application is suspended while it waits for the result, it is hard for the application to decide that it would like to try to cancel the ongoing command. (It can be done from a signal handler, but not otherwise.) can return only one PGresult structure. If the submitted command string contains multiple SQL commands, all but the last PGresult are discarded by PQexec.
• PQexec
Applications that do not like these limitations can instead use the underlying functions that PQexec is built from: PQsendQuery and PQgetResult. There are also PQsendQueryParams and PQsendQueryPrepared, which can be used with PQgetResult to duplicate the functionality of PQexecParams and PQexecPrepared respectively. PQsendQuery
Submits a command to the server without waiting for the result(s). 1 is returned if the command was successfully dispatched and 0 if not (in which case, use PQerrorMessage to get more information about the failure). int PQsendQuery(PGconn *conn, const char *command);
After successfully calling PQsendQuery, call PQgetResult one or more times to obtain the results. PQsendQuery may not be called again (on the same connection) until PQgetResult has returned a null pointer, indicating that the command is done. PQsendQueryParams
Submits a command and separate parameters to the server without waiting for the result(s).
358
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
This is equivalent to PQsendQuery except that query parameters can be specified separately from the query string. The function's parameters are handled identically to PQexecParams. Like PQexecParams, it will not work on 2.0-protocol connections, and it allows only one command in the query string. PQsendQueryPrepared
Sends a request to execute a prepared statement with given parameters, without waiting for the result(s). int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
This is similar to PQsendQueryParams, but the command to be executed is specified by naming a previously-prepared statement, instead of giving a query string. The function's parameters are handled identically to PQexecPrepared. Like PQexecPrepared, it will not work on 2.0-protocol connections. PQgetResult
Waits for the next result from a prior PQsendQuery, PQsendQueryParams, or PQsendQueryPrepared call, and returns it. A null pointer is returned when the command is complete and there will be no more results. PGresult *PQgetResult(PGconn *conn); PQgetResult must be called repeatedly until it returns a null pointer, indicating that the command is done. (If called when no command is active, PQgetResult will just return a null pointer at once.) Each non-null result from PQgetResult should be processed using the same PGresult accessor functions previously described. Don't forget to free each result object with PQclear when done with it. Note that PQgetResult will block only if a command is active and the necessary response data has not yet been read by PQconsumeInput.
Using PQsendQuery and PQgetResult solves one of PQexec's problems: If a command string contains multiple SQL commands, the results of those commands can be obtained individually. (This allows a simple form of overlapped processing, by the way: the client can be handling the results of one command while the server is still working on later queries in the same command string.) However, calling PQgetResult will still cause the client to block until the server completes the next SQL command. This can be avoided by proper use of two more functions: PQconsumeInput
If input is available from the server, consume it. int PQconsumeInput(PGconn *conn); PQconsumeInput normally returns 1 indicating “no error”, but returns 0 if there was some kind of trouble (in which case PQerrorMessage can be consulted). Note that the result does not say whether any input data was actually collected. After calling PQconsumeInput, the application may check PQisBusy and/or PQnotifies to see if their state has changed. PQconsumeInput may be called even if the application is not prepared to deal with a result or notification just yet. The function will read available data and save it in a buffer, thereby causing a select() readready indication to go away. The application can thus use PQconsumeInput to clear the select()
condition immediately, and then examine the results at leisure.
359
PQisBusy
Returns 1 if a command is busy, that is, PQgetResult would block waiting for input. A 0 return indicates that PQgetResult can be called with assurance of not blocking. int PQisBusy(PGconn *conn); PQisBusy will not itself attempt to read data from the server; therefore PQconsumeInput must be
invoked first, or the busy state will never end. A typical application using these functions will have a main loop that uses select() or poll() to wait for all the conditions that it must respond to. One of the conditions will be input available from the server, which in terms of select() means readable data on the file descriptor identified by PQsocket. When the main loop detects input ready, it should call PQconsumeInput to read the input. It can then call PQisBusy, followed by PQgetResult if PQisBusy returns false (0). It can also call PQnotifies to detect NOTIFY messages (see Seção 27.6). A client that uses PQsendQuery/PQgetResult can also attempt to cancel a command that is still being processed by the server. PQrequestCancel
Requests that the server abandon processing of the current command. int PQrequestCancel(PGconn *conn);
The return value is 1 if the cancel request was successfully dispatched and 0 if not. (If not, PQerrorMessage tells why not.) Successful dispatch is no guarantee that the request will have any effect, however. Regardless of the return value of PQrequestCancel, the application must continue with the normal result-reading sequence using PQgetResult. If the cancellation is effective, the current command will terminate early and return an error result. If the cancellation fails (say, because the server was already done processing the command), then there will be no visible result at all. Note that if the current command is part of a transaction block, cancellation will abort the whole transaction. PQrequestCancel can safely be invoked from a signal handler. So, it is also possible to use it in conjunction with plain PQexec, if the decision to cancel can be made in a signal handler. For example, psql invokes PQrequestCancel from a SIGINT signal handler, thus allowing interactive cancellation of commands that it issues through PQexec.
By using the functions described above, it is possible to avoid blocking while waiting for input from the database server. However, it is still possible that the application will block waiting to send output to the server. This is relatively uncommon but can happen if very long SQL commands or data values are sent. (It is much more probable if the application sends data via COPY IN, however.) To prevent this possibility and achieve completely nonblocking database operation, the following additional functions may be used. PQsetnonblocking
Sets the nonblocking status of the connection. int PQsetnonblocking(PGconn *conn, int arg);
Sets the state of the connection to nonblocking if arg is 1, or blocking if arg is 0. Returns 0 if OK, -1 if error. In the nonblocking state, calls to PQsendQuery, PQputline, PQputnbytes, and PQendcopy will not block but instead return an error if they need to be called again. Note that PQexec does not honor nonblocking mode; if it is called, it will act in blocking fashion anyway. PQisnonblocking
Returns the blocking status of the database connection. int PQisnonblocking(const PGconn *conn);
Returns 1 if the connection is set to nonblocking mode and 0 if blocking.
360
PQflush
Attempts to flush any queued output data to the server. Returns 0 if successful (or if the send queue is empty), -1 if it failed for some reason, or 1 if it was unable to send all the data in the send queue yet (this case can only occur if the connection is nonblocking). int PQflush(PGconn *conn);
After sending any command or data on a nonblocking connection, call PQflush. If it returns 1, wait for the socket to be write-ready and call it again; repeat until it returns 0. Once PQflush returns 0, wait for the socket to be read-ready and then read the response as described above.
27.5. The Fast-Path Interface PostgreSQL provides a fast-path interface to send simple function calls to the server. Dica: This interface is somewhat obsolete, as one may achieve similar performance and greater functionality by setting up a prepared statement to define the function call. Then, executing the statement with binary transmission of parameters and results substitutes for a fast-path function call.
The function PQfn requests execution of a server function via the fast-path interface: PGresult* PQfn(PGconn* conn, int fnid, int *result_buf, int *result_len, int result_is_int, const PQArgBlock *args, int nargs); typedef struct { int len; int isint; union { int *ptr; int integer; } u; } PQArgBlock;
The fnid argument is the OID of the function to be executed. args and nargs define the parameters to be passed to the function; they must match the declared function argument list. When the isint field of a parameter structure is true, the u.integer value is sent to the server as an integer of the indicated length (this must be 1, 2, or 4 bytes); proper byte-swapping occurs. When isint is false, the indicated number of bytes at *u.ptr are sent with no processing; the data must be in the format expected by the server for binary transmission of the function's argument data type. result_buf is the buffer in which to place the return value. The caller must have allocated sufficient space to store the return value. (There is no check!) The actual result length will be returned in the integer pointed to by result_len. If a 1, 2, or 4-byte integer result is expected, set result_is_int to 1, otherwise set it to 0. Setting result_is_int to 1 causes libpq to byte-swap the value if necessary, so that it is delivered as a proper int value for the client machine. When result_is_int is 0, the binary-format byte string sent by the server is returned unmodified. PQfn always returns a valid PGresult pointer. The result status should be checked before the result is used. The caller is responsible for freeing the PGresult with PQclear when it is no longer needed.
Note that it is not possible to handle null arguments, null results, nor set-valued results when using this interface.
27.6. Asynchronous Notification PostgreSQL offers asynchronous notification via the LISTEN and NOTIFY commands. A client session registers its interest in a particular notification condition with the LISTEN command (and can stop listening with the UNLISTEN command). All sessions listening on a particular condition will be notified asynchronously when a NOTIFY command with that condition name is executed by any session. No additional information is passed from the notifier to the listener. Thus, typically, any actual data that needs to be communicated is transferred
361
through a database table. Commonly, the condition name is the same as the associated table, but it is not necessary for there to be any associated table. libpq applications submit LISTEN and UNLISTEN commands as ordinary SQL commands. The arrival of NOTIFY messages can subsequently be detected by calling PQnotifies. The function PQnotifies returns the next notification from a list of unhandled notification messages received from the server. It returns a null pointer if there are no pending notifications. Once a notification is returned from PQnotifies, it is considered handled and will be removed from the list of notifications. PGnotify* PQnotifies(PGconn *conn); typedef struct pgNotify { char *relname; /* notification condition name */ int be_pid; /* process ID of server process */ char *extra; /* notification parameter */ } PGnotify;
After processing a PGnotify object returned by PQnotifies, be sure to free it with PQfreemem. It is sufficient to free the PGnotify pointer; the relname and extra fields do not represent separate allocations. (At present, the extra field is unused and will always point to an empty string.) Nota: In PostgreSQL 6.4 and later, the be_pid is that of the notifying server process, whereas in earlier versions it was always the PID of your own server process.
Exemplo 27-2 gives a sample program that illustrates the use of asynchronous notification. PQnotifies does not actually read data from the server; it just returns messages previously absorbed by another libpq function. In prior releases of libpq, the only way to ensure timely receipt of NOTIFY messages was to constantly submit commands, even empty ones, and then check PQnotifies after each PQexec. While
this still works, it is deprecated as a waste of processing power. A better way to check for NOTIFY messages when you have no useful commands to execute is to call PQconsumeInput, then check PQnotifies. You can use select() to wait for data to arrive from the server, thereby using no CPU power unless there is something to do. (See PQsocket to obtain the file descriptor number to use with select().) Note that this will work OK whether you submit commands with PQsendQuery/PQgetResult or simply use PQexec. You should, however, remember to check PQnotifies after each PQgetResult or PQexec, to see if any notifications came in during the processing of the command.
27.7. Functions Associated with the COPY Command The COPY command in PostgreSQL has options to read from or write to the network connection used by libpq. The functions described in this section allow applications to take advantage of this capability by supplying or consuming copied data. The overall process is that the application first issues the SQL COPY command via PQexec or one of the equivalent functions. The response to this (if there is no error in the command) will be a PGresult object bearing a status code of PGRES_COPY_OUT or PGRES_COPY_IN (depending on the specified copy direction). The application should then use the functions of this section to receive or transmit data rows. When the data transfer is complete, another PGresult object is returned to indicate success or failure of the transfer. Its status will be PGRES_COMMAND_OK for success or PGRES_FATAL_ERROR if some problem was encountered. At this point further SQL commands may be issued via PQexec. (It is not possible to execute other SQL commands using the same connection while the COPY operation is in progress.) If a COPY command is issued via PQexec in a string that could contain additional commands, the application must continue fetching results via PQgetResult after completing the COPY sequence. Only when PQgetResult returns NULL is it certain that the PQexec command string is done and it is safe to issue more commands. The functions of this section should be executed only after obtaining a result status of PGRES_COPY_OUT or PGRES_COPY_IN from PQexec or PQgetResult.
362
A PGresult object bearing one of these status values carries some additional data about the COPY operation that is starting. This additional data is available using functions that are also used in connection with query results: PQnfields
Returns the number of columns (fields) to be copied. PQbinaryTuples
0 indicates the overall copy format is textual (rows separated by newlines, columns separated by separator characters, etc). 1 indicates the overall copy format is binary. See COPY for more information. PQfformat
Returns the format code (0 for text, 1 for binary) associated with each column of the copy operation. The per-column format codes will always be zero when the overall copy format is textual, but the binary format can support both text and binary columns. (However, as of the current implementation of COPY, only binary columns appear in a binary copy; so the per-column formats always match the overall format at present.) Nota: These additional data values are only available when using protocol 3.0. When using protocol 2.0, all these functions will return 0.
27.7.1. Functions for Sending COPY Data These functions are used to send data during COPY FROM STDIN. They will fail if called when the connection is not in COPY_IN state. PQputCopyData
Sends data to the server during COPY_IN state. int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
Transmits the COPY data in the specified buffer, of length nbytes, to the server. The result is 1 if the data was sent, zero if it was not sent because the attempt would block (this case is only possible if the connection is in nonblocking mode), or -1 if an error occurred. (Use PQerrorMessage to retrieve details if the return value is -1. If the value is zero, wait for write-ready and try again.) The application may divide the COPY data stream into buffer loads of any convenient size. Buffer-load boundaries have no semantic significance when sending. The contents of the data stream must match the data format expected by the COPY command; see COPY for details. PQputCopyEnd
Sends end-of-data indication to the server during COPY_IN state. int PQputCopyEnd(PGconn *conn, const char *errormsg);
Ends the COPY_IN operation successfully if errormsg is NULL. If errormsg is not NULL then the COPY is forced to fail, with the string pointed to by errormsg used as the error message. (One should not assume that this exact error message will come back from the server, however, as the server might have already failed the COPY for its own reasons. Also note that the option to force failure does not work when using pre-3.0-protocol connections.) The result is 1 if the termination data was sent, zero if it was not sent because the attempt would block (this case is only possible if the connection is in nonblocking mode), or -1 if an error occurred. (Use PQerrorMessage to retrieve details if the return value is -1. If the value is zero, wait for write-ready and try again.) After successfully calling PQputCopyEnd, call PQgetResult to obtain the final result status of the COPY command. One may wait for this result to be available in the usual way. Then return to normal operation.
363
27.7.2. Functions for Receiving COPY Data These functions are used to receive data during COPY TO STDOUT. They will fail if called when the connection is not in COPY_OUT state. PQgetCopyData
Receives data from the server during COPY_OUT state. int PQgetCopyData(PGconn *conn, char **buffer, int async);
Attempts to obtain another row of data from the server during a COPY. Data is always returned one data row at a time; if only a partial row is available, it is not returned. Successful return of a data row involves allocating a chunk of memory to hold the data. The buffer parameter must be non-NULL. *buffer is set to point to the allocated memory, or to NULL in cases where no buffer is returned. A non-NULL result buffer must be freed using PQfreemem when no longer needed. When a row is successfully returned, the return value is the number of data bytes in the row (this will always be greater than zero). The returned string is always null-terminated, though this is probably only useful for textual COPY. A result of zero indicates that the COPY is still in progress, but no row is yet available (this is only possible when async is true). A result of -1 indicates that the COPY is done. A result of -2 indicates that an error occurred (consult PQerrorMessage for the reason). When async is true (not zero), PQgetCopyData will not block waiting for input; it will return zero if the COPY is still in progress but no complete row is available. (In this case wait for read-ready before trying again; it does not matter whether you call PQconsumeInput.) When async is false (zero), PQgetCopyData will block until data is available or the operation completes. After PQgetCopyData returns -1, call PQgetResult to obtain the final result status of the COPY command. One may wait for this result to be available in the usual way. Then return to normal operation.
27.7.3. Obsolete Functions for COPY These functions represent older methods of handling COPY. Although they still work, they are deprecated due to poor error handling, inconvenient methods of detecting end-of-data, and lack of support for binary or nonblocking transfers. PQgetline
Reads a newline-terminated line of characters (transmitted by the server) into a buffer string of size length. int PQgetline(PGconn *conn, char *buffer, int length);
This function copies up to length-1 characters into the buffer and converts the terminating newline into a zero byte. PQgetline returns EOF at the end of input, 0 if the entire line has been read, and 1 if the buffer is full but the terminating newline has not yet been read. Note that the application must check to see if a new line consists of the two characters \., which indicates that the server has finished sending the results of the COPY command. If the application might receive lines that are more than length-1 characters long, care is needed to be sure it recognizes the \. line correctly (and does not, for example, mistake the end of a long data line for a terminator line). PQgetlineAsync
Reads a row of COPY data (transmitted by the server) into a buffer without blocking. int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
This function is similar to PQgetline, but it can be used by applications that must read COPY data asynchronously, that is, without blocking. Having issued the COPY command and gotten a
364
PGRES_COPY_OUT response, the application should call PQconsumeInput and PQgetlineAsync until
the end-of-data signal is detected. Unlike PQgetline, this function takes responsibility for detecting end-of-data. On each call, PQgetlineAsync will return data if a complete data row is available in libpq's input buffer. Otherwise, no data is returned until the rest of the row arrives. The function returns -1 if the end-of-copydata marker has been recognized, or 0 if no data is available, or a positive number giving the number of bytes of data returned. If -1 is returned, the caller must next call PQendcopy, and then return to normal processing. The data returned will not extend beyond a data-row boundary. If possible a whole row will be returned at one time. But if the buffer offered by the caller is too small to hold a row sent by the server, then a partial data row will be returned. With textual data this can be detected by testing whether the last returned byte is \n or not. (In a binary COPY, actual parsing of the COPY data format will be needed to make the equivalent determination.) The returned string is not null-terminated. (If you want to add a terminating null, be sure to pass a bufsize one smaller than the room actually available.) PQputline
Sends a null-terminated string to the server. Returns 0 if OK and EOF if unable to send the string. int PQputline(PGconn *conn, const char *string);
The COPY data stream sent by a series of calls to PQputline has the same format as that returned by PQgetlineAsync, except that applications are not obliged to send exactly one data row per PQputline call; it is okay to send a partial line or multiple lines per call. Nota: Before PostgreSQL protocol 3.0, it was necessary for the application to explicitly send the two characters \. as a final line to indicate to the server that it had finished sending COPY data. While this still works, it is deprecated and the special meaning of \. can be expected to be removed in a future release. It is sufficient to call PQendcopy after having sent the actual data. PQputnbytes
Sends a non-null-terminated string to the server. Returns 0 if OK and EOF if unable to send the string. int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
This is exactly like PQputline, except that the data buffer need not be null-terminated since the number of bytes to send is specified directly. Use this procedure when sending binary data. PQendcopy
Synchronizes with the server. int PQendcopy(PGconn *conn);
This function waits until the server has finished the copying. It should either be issued when the last string has been sent to the server using PQputline or when the last string has been received from the server using PGgetline. It must be issued or the server will get “out of sync” with the client. Upon return from this function, the server is ready to receive the next SQL command. The return value is 0 on successful completion, nonzero otherwise. (Use PQerrorMessage to retrieve details if the return value is nonzero.) When using PQgetResult, the application should respond to a PGRES_COPY_OUT result by executing PQgetline repeatedly, followed by PQendcopy after the terminator line is seen. It should then return to the PQgetResult loop until PQgetResult returns a null pointer. Similarly a PGRES_COPY_IN result is processed by a series of PQputline calls followed by PQendcopy, then return to the PQgetResult loop. This arrangement will ensure that a COPY command embedded in a series of SQL commands will be executed correctly. Older applications are likely to submit a COPY via PQexec and assume that the transaction is done after PQendcopy. This will work correctly only if the COPY is the only SQL command in the command string.
365
27.8. Control Functions These functions control miscellaneous details of libpq's behavior. PQsetErrorVerbosity
Determines the verbosity of messages returned by PQerrorMessage and PQresultErrorMessage. typedef enum { PQERRORS_TERSE, PQERRORS_DEFAULT, PQERRORS_VERBOSE } PGVerbosity; PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); PQsetErrorVerbosity sets the verbosity mode, returning the connection's previous setting. In terse
mode, returned messages include severity, primary text, and position only; this will normally fit on a single line. The default mode produces messages that include the above plus any detail, hint, or context fields (these may span multiple lines). The VERBOSE mode includes all available fields. Changing the verbosity does not affect the messages available from already-existing PGresult objects, only subsequently-created ones. PQtrace
Enables tracing of the client/server communication to a debugging file stream. void PQtrace(PGconn *conn, FILE *stream); PQuntrace
Disables tracing started by PQtrace. void PQuntrace(PGconn *conn);
27.9. Notice Processing Notice and warning messages generated by the server are not returned by the query execution functions, since they do not imply failure of the query. Instead they are passed to a notice handling function, and execution continues normally after the handler returns. The default notice handling function prints the message on stderr, but the application can override this behavior by supplying its own handling function. For historical reasons, there are two levels of notice handling, called the notice receiver and notice processor. The default behavior is for the notice receiver to format the notice and pass a string to the notice processor for printing. However, an application that chooses to provide its own notice receiver will typically ignore the notice processor layer and just do all the work in the notice receiver. The function PQsetNoticeReceiver sets or examines the current notice receiver for a connection object. Similarly, PQsetNoticeProcessor sets or examines the current notice processor. typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res); PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg); typedef void (*PQnoticeProcessor) (void *arg, const char *message); PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg);
Each of these functions returns the previous notice receiver or processor function pointer, and sets the new value. If you supply a null function pointer, no action is taken, but the current pointer is returned. When a notice or warning message is received from the server, or generated internally by libpq, the notice receiver function is called. It is passed the message in the form of a PGRES_NONFATAL_ERROR PGresult.
366
(This allows the receiver to extract individual fields using PQresultErrorField, or the complete preformatted message using PQresultErrorMessage.) The same void pointer passed to PQsetNoticeReceiver is also passed. (This pointer can be used to access application-specific state if needed.) The default notice receiver simply extracts the message (using PQresultErrorMessage) and passes it to the notice processor. The notice processor is responsible for handling a notice or warning message given in text form. It is passed the string text of the message (including a trailing newline), plus a void pointer that is the same one passed to PQsetNoticeProcessor. (This pointer can be used to access application-specific state if needed.) The default notice processor is simply static void defaultNoticeProcessor(void * arg, const char * message) { fprintf(stderr, "%s", message); }
Once you have set a notice receiver or processor, you should expect that that function could be called as long as either the PGconn object or PGresult objects made from it exist. At creation of a PGresult, the PGconn's current notice handling pointers are copied into the PGresult for possible use by functions like PQgetvalue.
27.10. Environment Variables The following environment variables can be used to select default connection parameter values, which will be used by PQconnectdb, PQsetdbLogin and PQsetdb if no value is directly specified by the calling code. These are useful to avoid hard-coding database connection information into simple client applications, for example. •
PGHOST sets the database server name. If this begins with a slash, it specifies Unix-domain communication
rather than TCP/IP communication; the value is the name of the directory in which the socket file is stored (default /tmp). •
PGHOSTADDR specifies the numeric IP address of the database server. This can be set instead of PGHOST to avoid DNS lookup overhead. See the documentation of these parameters, under PQconnectdb above, for
details on their interaction. •
PGPORT sets the TCP port number or Unix-domain socket file extension for communicating with the
PostgreSQL server. •
PGDATABASE sets the PostgreSQL database name.
•
PGUSER sets the user name used to connect to the database.
•
PGPASSWORD sets the password used if the server demands password authentication. This environment variable is deprecated for security reasons; consider migrating to use the $HOME/.pgpass file (see Seção 27.11).
•
PGSERVICE sets the service name to be looked up in pg_service.conf. This offers a shorthand way of
setting all the parameters. •
• •
PGREALM sets the Kerberos realm to use with PostgreSQL, if it is different from the local realm. If PGREALM is set, libpq applications will attempt authentication with servers for this realm and use separate ticket files to avoid conflicts with local ticket files. This environment variable is only used if Kerberos authentication is selected by the server. PGOPTIONS sets additional run-time options for the PostgreSQL server. PGSSLMODE determines whether and with what priority an SSL connection will be negotiated with the server. There are four modes: disable will attempt only an unencrypted SSL connection; allow will negotiate, trying first a non-SSL connection, then if that fails, trying an SSL connection; prefer (the default) will negotiate, trying first an SSL connection, then if that fails, trying a regular non-SSL connection; require will try only an SSL connection. If PostgreSQL is compiled without SSL support, using option
367
require will cause an error, and options allow and prefer will be tolerated but libpq will be unable to
negotiate an SSL connection. •
PGREQUIRESSL sets whether or not the connection must be made over SSL. If set to “1”, libpq will refuse to connect if the server does not accept an SSL connection (equivalent to sslmode prefer). This option is deprecated in favor of the sslmode setting, and is only available if PostgreSQL is compiled with SSL support.
•
PGCONNECT_TIMEOUT sets the maximum number of seconds that libpq will wait when attempting to
connect to the PostgreSQL server. If unset or set to zero, libpq will wait indefinitely. It is not recommended to set the timeout to less than 2 seconds. The following environment variables can be used to specify default behavior for each PostgreSQL session. (See also the ALTER USER and ALTER DATABASE commands for ways to set default behavior on a per-user or perdatabase basis.) •
PGDATESTYLE sets the default style of date/time representation. (Equivalent to SET datestyle TO ....)
•
PGTZ sets the default time zone. (Equivalent to SET timezone TO ....)
•
•
PGCLIENTENCODING sets the default client character set encoding. (Equivalent to SET client_encoding TO ....) PGGEQO sets the default mode for the genetic query optimizer. (Equivalent to SET geqo TO ....)
Refer to the SQL command SET for information on correct values for these environment variables.
27.11. The Password File The file .pgpass in a user's home directory is a file that can contain passwords to be used if the connection requires a password (and no password has been specified otherwise). This file should have lines of the following format: hostname:port:database:username:password
Each of the first four fields may be a literal value, or *, which matches anything. The password field from the first line that matches the current connection parameters will be used. (Therefore, put more-specific entries first when you are using wildcards.) If an entry needs to contain : or \, escape this character with \. The permissions on .pgpass must disallow any access to world or group; achieve this by the command chmod 0600 ~/.pgpass. If the permissions are less strict than this, the file will be ignored.
27.12. Behavior in Threaded Programs libpq is reentrant and thread-safe if the configure command-line option --enable-thread-safety has been used when the PostgreSQL distribution was built. In addition, you might need to use additional compiler command-line options when you compile your application code. Refer to your system's documentation for information about how to build thread-enabled applications. One restriction is that no two threads attempt to manipulate the same PGconn object at the same time. In particular, you cannot issue concurrent commands from different threads through the same connection object. (If you need to run concurrent commands, start up multiple connections.) PGresult objects are read-only after creation, and so can be passed around freely between threads.
The deprecated functions PQoidStatus and fe_setauthsvc are not thread-safe and should not be used in multithread programs. PQoidStatus can be replaced by PQoidValue. There is no good reason to call fe_setauthsvc at all. libpq applications that use the crypt authentication method rely on the crypt() operating system function, which is often not thread-safe. It is better to use the md5 method, which is thread-safe on all platforms.
368
27.13. Building libpq Programs To build (i.e., compile and link) your libpq programs you need to do all of the following things: •
Include the libpq-fe.h header file: #include
If you failed to do that then you will normally get error messages from your compiler similar to foo.c: In foo.c:34: foo.c:35: foo.c:54: foo.c:68: foo.c:95: •
function `main': `PGconn' undeclared (first use in this function) `PGresult' undeclared (first use in this function) `CONNECTION_BAD' undeclared (first use in this function) `PGRES_COMMAND_OK' undeclared (first use in this function) `PGRES_TUPLES_OK' undeclared (first use in this function)
Point your compiler to the directory where the PostgreSQL header files were installed, by supplying the Idirectory option to your compiler. (In some cases the compiler will look into the directory in question by default, so you can omit this option.) For instance, your compile command line could look like: cc -c -I/usr/local/pgsql/include testprog.c
If you are using makefiles then add the option to the CPPFLAGS variable: CPPFLAGS += -I/usr/local/pgsql/include
If there is any chance that your program might be compiled by other users then you should not hardcode the directory location like that. Instead, you can run the utility pg_config to find out where the header files are on the local system: $ pg_config --includedir /usr/local/include
Failure to specify the correct option to the compiler will result in an error message such as testlibpq.c:8:22: libpq-fe.h: No such file or directory •
When linking the final program, specify the option -lpq so that the libpq library gets pulled in, as well as the option -Ldirectory to point the compiler to the directory where the libpq library resides. (Again, the compiler will search some directories by default.) For maximum portability, put the -L option before the lpq option. For example: cc -o testprog testprog1.o testprog2.o -L/usr/local/pgsql/lib -lpq
You can find out the library directory using pg_config as well: $ pg_config --libdir /usr/local/pgsql/lib
Error messages that point to problems in this area could look like the following. testlibpq.o: In function testlibpq.o(.text+0x60): testlibpq.o(.text+0x71): testlibpq.o(.text+0xa4):
`main': undefined reference to `PQsetdbLogin' undefined reference to `PQstatus' undefined reference to `PQerrorMessage'
This means you forgot -lpq. /usr/bin/ld: cannot find -lpq
This means you forgot the -L option or did not specify the right directory. If your codes references the header file libpq-int.h and you refuse to fix your code to not use it, starting in PostgreSQL 7.2, this file will be found in includedir/postgresql/internal/libpq-int.h, so you need to add the appropriate -I option to your compiler command line.
27.14. Example Programs These examples and others can be found in the directory src/test/examples in the source code distribution.
369
Exemplo 27-1. libpq Example Program 1 /* * testlibpq.c * * Test the C version of LIBPQ, the POSTGRES frontend library. */ #include <stdio.h> #include <stdlib.h> #include "libpq-fe.h" static void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } int main(int argc, char **argv) { const char *conninfo; PGconn *conn; PGresult *res; int int
nFields; i, j;
/* * If the user supplies a parameter on the command line, use it as * the conninfo string; otherwise default to setting dbname=template1 * and using environment variables or defaults for all other * connection parameters. */ if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = template1"; /* Make a connection to the database */ conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); } /* * Our test case here involves using a cursor, for which we must be * inside a transaction block. We could do the whole thing with a * single PQexec() of "select * from pg_database", but that's too * trivial to make a good example. */ /* Start a transaction block */ res = PQexec(conn, "BEGIN"); if (PQresultStatus(res) != PGRES_COMMAND_OK) {
370
fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } /* * Should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res); /* * Fetch rows from pg_database, the system catalog of databases */ res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); res = PQexec(conn, "FETCH ALL in myportal"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } /* first, print out the attribute names */ nFields = PQnfields(res); for (i = 0; i < nFields; i++) printf("%-15s", PQfname(res, i)); printf("\n\n"); /* next, print out the rows */ for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%-15s", PQgetvalue(res, i, j)); printf("\n"); } PQclear(res); /* close the portal ... we don't bother to check for errors ... */ res = PQexec(conn, "CLOSE myportal"); PQclear(res); /* end the transaction */ res = PQexec(conn, "END"); PQclear(res); /* close the connection to the database and cleanup */ PQfinish(conn); return 0;
371
}
Exemplo 27-2. libpq Example Program 2 /* * testlibpq2.c * Test of the asynchronous notification interface * * Start this program, then from psql in another window do * NOTIFY TBL2; * Repeat four times to get this program to exit. * * Or, if you want to get fancy, try this: * populate a database with the following commands * (provided in src/test/examples/testlibpq2.sql): * * CREATE TABLE TBL1 (i int4); * * CREATE TABLE TBL2 (i int4); * * CREATE RULE r1 AS ON INSERT TO TBL1 DO * (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2); * * and do this four times: * * INSERT INTO TBL1 VALUES (10); */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/time.h> #include "libpq-fe.h" static void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } int main(int argc, char **argv) { const char *conninfo; PGconn *conn; PGresult *res; PGnotify *notify; int
nnotifies;
/* * If the user supplies a parameter on the command line, use it as * the conninfo string; otherwise default to setting dbname=template1 * and using environment variables or defaults for all other * connection parameters. */ if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = template1"; /* Make a connection to the database */ conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn);
372
} /* * Issue LISTEN command to enable notifications from the rule's * NOTIFY. */ res = PQexec(conn, "LISTEN TBL2"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } /* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res); /* Quit after four notifies are received. */ nnotifies = 0; while (nnotifies < 4) { /* * Sleep until something happens on the connection. * We use select(2) to wait for input, but you could * also use poll() or similar facilities. */ int sock; fd_set input_mask; sock = PQsocket(conn); if (sock < 0) break;
/* shouldn't happen */
FD_ZERO(&input_mask); FD_SET(sock, &input_mask); if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) { fprintf(stderr, "select() failed: %s\n", strerror(errno)); exit_nicely(conn); } /* Now check for input */ PQconsumeInput(conn); while ((notify = PQnotifies(conn)) != NULL) { fprintf(stderr, "ASYNC NOTIFY of '%s' received from backend pid %d\n", notify->relname, notify->be_pid); PQfreemem(notify); nnotifies++; } } fprintf(stderr, "Done.\n"); /* close the connection to the database and cleanup */ PQfinish(conn); return 0; }
Exemplo 27-3. libpq Example Program 3 /*
373
* testlibpq3.c * Test out-of-line parameters and binary I/O. * * Before running this, populate a database with the following commands * (provided in src/test/examples/testlibpq3.sql): * * CREATE TABLE test1 (i int4, t text, b bytea); * * INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004'); * INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000'); * * The expected output is: * * tuple 0: got * i = (4 bytes) 1 * t = (11 bytes) 'joe's place' * b = (5 bytes) \000\001\002\003\004 * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include "libpq-fe.h" /* for ntohl/htonl */ #include#include <arpa/inet.h>
static void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } int main(int argc, char **argv) { const char *conninfo; PGconn *conn; PGresult *res; const char *paramValues[1]; int i, j; int i_fnum, t_fnum, b_fnum; /* * If the user supplies a parameter on the command line, use it as * the conninfo string; otherwise default to setting dbname=template1 * and using environment variables or defaults for all other * connection parameters. */ if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = template1"; /* Make a connection to the database */ conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn)); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn);
374
} /* * The point of this program is to illustrate use of PQexecParams() * with out-of-line parameters, as well as binary transmission of * results. By using out-of-line parameters we can avoid a lot of * tedious mucking about with quoting and escaping. Notice how we * don't have to do anything special with the quote mark in the * parameter value. */ /* Here is our out-of-line parameter value */ paramValues[0] = "joe's place"; res = PQexecParams(conn, "SELECT * FROM test1 WHERE t = $1", 1, /* one param */ NULL, /* let the backend deduce param type */ paramValues, NULL, /* don't need param lengths since text */ NULL, /* default to all text params */ 1); /* ask for binary results */ if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } /* Use i_fnum t_fnum b_fnum
PQfnumber to avoid assumptions about field order in result */ = PQfnumber(res, "i"); = PQfnumber(res, "t"); = PQfnumber(res, "b");
for (i = 0; i < PQntuples(res); i++) { char *iptr; char *tptr; char *bptr; int blen; int ival; /* Get the field values (we ignore possibility they are null!) */ iptr = PQgetvalue(res, i, i_fnum); tptr = PQgetvalue(res, i, t_fnum); bptr = PQgetvalue(res, i, b_fnum); /* * The binary representation of INT4 is in network byte order, * which we'd better coerce to the local byte order. */ ival = ntohl(*((uint32_t *) iptr)); /* * The binary representation of TEXT is, well, text, and since * libpq was nice enough to append a zero byte to it, it'll * work just fine as a C string. * * The binary representation of BYTEA is a bunch of bytes, * which could include embedded nulls so we have to pay * attention to field length. */ blen = PQgetlength(res, i, b_fnum); printf("tuple %d: got\n", i); printf(" i = (%d bytes) %d\n", PQgetlength(res, i, i_fnum), ival); printf(" t = (%d bytes) '%s'\n", PQgetlength(res, i, t_fnum), tptr);
375
printf(" b = (%d bytes) ", blen); for (j = 0; j < blen; j++) printf("\\%03o", bptr[j]); printf("\n\n"); } PQclear(res); /* close the connection to the database and cleanup */ PQfinish(conn); return 0; }
376
Capítulo 28. Objetos grandes Nas versões do PostgreSQL anteriores a 7.1, o tamanho de qualquer linha do banco de dado não podia exceder o tamanho de uma página de dados. Uma vez que o tamanho da página de dados é de 8192 bytes (por padrão, podendo ser aumentado até 32768), o limite superior do tamanho do valor do dado era relativamente baixo. Para dar suporte ao armazenamento de valores atômicos maiores, o PostgreSQL forneceu e continua fornecendo a interface de objeto grande. Esta interface fornece acesso orientado a arquivos para os dados do usuário, que são armazenados em uma estrutura especial de objeto grande. Este capítulo descreve a implementação, e as interfaces de programação e de linguagem de consulta dos dados objeto grande no PostgreSQL. É utilizada a biblioteca C libpq nos exemplos deste capítulo, mas a maioria das interfaces de programação nativas do PostgreSQL suportam funcionalidades equivalentes. Outras interfaces podem utilizar a interface de objeto grande internamente para fornecer suporte genérico para valores grandes, mas não são descritas aqui.
28.1. Histórico O POSTGRES 4.2, predecessor indireto do PostgreSQL, suportava três implementações padrão para objetos grandes: como arquivos externos ao servidor POSTGRES, como arquivos externos gerenciados pelo servidor POSTGRES, e como dados armazenados dentro do banco de dados POSTGRES. Esta situação causava uma confusão considerável entre os usuários. Como resultado, somente o suporte aos objetos grandes armazenados como dado dentro do banco de dados permaneceu no PostgreSQL. Embora o acesso seja mais lento, fornece uma integridade de dados mais rigorosa. Por motivos históricos, este esquema de armazenamento é referido como Inversão de objetos grandes (Inversion large objects) (Será encontrado o termo Inversão utilizado ocasionalmente, significando a mesma coisa que objeto grande). Desde o PostgreSQL 7.1 todos os objetos grandes são armazenados em uma tabela do sistema chamada pg_largeobject. O PostgreSQL 7.1 introduziu o mecanismo (apelidado de “TOAST” (torrada)) que permite as linhas de dado serem muito maiores que as páginas de dados. Isto tornou a interface de objeto grande parcialmente obsoleta. Uma vantagem da interface de objeto grande que permaneceu é permitir valores com tamanho de até 2 GB, enquanto TOAST pode tratar apenas 1 GB.
28.2. Características de implementação A implementação de objeto grande divide os objetos grandes em “pedaços” (chunks), e armazena estes pedaços em linhas no banco de dados. Um índice B-tree garante a procura rápida do número correto do pedaço quando são feitos acessos aleatórios de leitura e escrita.
28.3. Interfaces cliente Esta seção descreve as facilidades que as bibliotecas de interface cliente do PostgreSQL fornecem para acessar objetos grandes. Toda manipulação de objeto grande que utiliza estas funções deve acontecer dentro de um bloco de transação SQL (Este requisito é obrigatório desde o PostgreSQL 6.5, embora tenha sido um requisito implícito nas versões anteriores, resultando em um mal comportamento se fosse ignorado). A interface de objeto grande do PostgreSQL é modelada segundo a interface do sistema de arquivos do Unix, com funções open, read, write, lseek, etc. análogas. As aplicações cliente que utilizam a interface de objeto grande da libpq devem incluir o arquivo de cabeçalho libpq/libpq-fs.h e ligar com a biblioteca libpq.
28.3.1. Criar objeto grande A função Oid lo_creat(PGconn *conn, int modo);
377
cria um objeto grande novo. O modo é uma máscara de bits que descreve vários atributos diferentes do novo objeto. As constantes simbólicas usadas aqui são definidas no arquivo de cabeçalho libpq/libpq-fs.h. O tipo de acesso (leitura, escrita ou ambos) é controlado pelo OU lógico dos bits de INV_READ e INV_WRITE. Os dezesseis bits de mais baixa ordem da máscara tem sido utilizado em Berkeley, historicamente, para designar o número do gerenciador de armazenamento no qual o objeto grande deve residir. Agora estes bits devem ser sempre zero. O valor retornado é o OID atribuído ao novo objeto grande. Exemplo: inv_oid = lo_creat(INV_READ|INV_WRITE);
28.3.2. Importar objeto grande Para importar um arquivo do sistema operacional como um objeto grande é chamada a função: Oid lo_import(PGconn *conn, const char *nome_do_arquivo);
O nome_do_arquivo especifica o nome do arquivo do sistema operacional a ser importado como objeto grande. O valor retornado é o OID atribuído ao novo objeto grande.
28.3.3. Exportar objeto grande Para exportar um objeto grande para um arquivo do sistema operacional é chamada a função: int lo_export(PGconn *conn, Oid lobjId, const char *nome_do_arquivo);
O argumento lobjId especifica o OID do objeto grande a ser exportado, e o argumento nome_do_arquivo especifica o nome do arquivo no sistema operacional.
28.3.4. Abrir objeto grande existente Para abrir um objeto grande existente é chamada a função: int lo_open(PGconn *conn, Oid lobjId, int modo);
O argumento lobjId especifica o OID do objeto grande a ser aberto. Os bits de modo controlam se o objeto deve ser aberto para leitura (INV_READ), escrita (INV_WRITE), ou ambos. Um objeto grande não pode ser aberto antes de ser criado. A função lo_open retorna o descritor do objeto grande para uso posterior em lo_read, lo_write, lo_lseek, lo_tell e lo_close. O descritor é válido apenas pela duração da transação corrente.
28.3.5. Escrever dados em objeto grande A função int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
escreve len bytes de buf no objeto grande fd. O argumento fd deve ter sido retornado por uma chamada anterior a lo_open. É retornado o número de bytes realmente escritos. Caso aconteça algum erro, o valor retornado é negativo.
28.3.6. Ler dados de objeto grande A função int lo_read(PGconn *conn, int fd, char *buf, size_t len);
lê len bytes do objeto grande fd colocando-os em buf. O argumento fd deve ter sido retornado por uma chamada anterior a lo_open. É retornado o número de bytes realmente lidos. Caso aconteça algum erro, o valor retornado é negativo.
378
28.3.7. Procurar no objeto grande Para mudar a posição atual de leitura ou de escrita em um objeto grande é chamada a função: int lo_lseek(PGconn *conn, int fd, int deslocamento, int donde);
Esta função move o ponteiro de localização corrente do objeto grande descrito por fd, para a nova localização especificada por deslocamento. Os valores válidos para donde são SEEK_SET (procurar a partir do início do objeto), SEEK_CUR (procurar a partir da localização corrente), e SEEK_END (procurar a partir do fim do objeto). O valor retornado é o novo ponteiro de localização.
28.3.8. Obter a posição de procura no objeto grande Para obter a localização corrente de leitura ou escrita no objeto grande é chamada a função: int lo_tell(PGconn *conn, int fd);
Se houver erro retorna um valor negativo.
28.3.9. Fechar o descritor do objeto grande O objeto grande pode ser fechado chamando a função int lo_close(PGconn *conn, int fd);
onde fd é o descritor do objeto grande retornado por lo_open. Se for bem-sucedida, lo_close retorna zero. Se houver um erro retorna um valor negativo. Todo descritor de objeto grande que esteja aberto no final da transação é fechado automaticamente.
28.3.10. Remover o objeto grande Para remover um objeto do grande do banco de dados é chamada a função: int lo_unlink(PGconn *conn, Oid lobjId);
O argumento lobjId especifica o OID do objeto grande a ser removido. No caso de erro é retornado um valor negativo.
28.4. Funções do lado servidor Existem duas funções nativas do lado servidor, lo_import e lo_export, para acessar objetos grandes, disponíveis para uso nos comandos SQL. Abaixo está um exemplo de utilização: CREATE TABLE imagem ( nome text, raster oid ); INSERT INTO imagem (nome, raster) VALUES ('uma linda imagem', lo_import('/etc/motd')); SELECT lo_export(image.raster, '/tmp/motd') FROM imagem WHERE nome = 'uma linda imagem';
Estas funções fazem leitura e escrita de arquivos no sistema de arquivos do servidor, utilizando as permissões do usuário dono do banco de dados. Portanto, só podem ser utilizadas por superusuários (Em oposição, as funções de importação e exportação do lado cliente fazem a leitura e escrita de arquivos no sistema de arquivos do cliente, utilizando as permissões do programa cliente, não tendo seu uso restringido).
379
28.5. Programa exemplo O Exemplo 28-1 é um programa simples, que mostra como a interface de objeto grande da libpq pode ser utilizada. Partes do programa foram transformadas em comentário, mas foram deixadas no código fonte para benefício do leitor. Este programa também pode ser encontrado em src/test/examples/testlo.c na distribuição do código fonte. Exemplo 28-1. Programa de exemplo objeto grande com libpq /*-------------------------------------------------------------* * testlo.c-* teste de utilização de objetos grandes com libpq * * Copyright (c) 1994, Regents of the University of California * *-------------------------------------------------------------*/ #include <stdio.h> #include "libpq-fe.h" #include "libpq/libpq-fs.h" #define BUFSIZE
1024
/* * importFile * importar o arquivo "in_filename" para o banco de dados * como o objeto grande "lobjOid" * */ Oid importFile(PGconn *conn, char *filename) { Oid lobjId; int lobj_fd; char buf[BUFSIZE]; int nbytes, tmp; int fd; /* * abrir o arquivo a ser lido */ fd = open(filename, O_RDONLY, 0666); if (fd < 0) { /* erro */ fprintf(stderr, "impossível abrir o arquivo Unix %s\n", filename); } /* * criar o objeto grande */ lobjId = lo_creat(conn, INV_READ | INV_WRITE); if (lobjId == 0) fprintf(stderr, "can't create large object\n"); lobj_fd = lo_open(conn, lobjId, INV_WRITE); /* * ler do arquivo Unix e escrever no arquivo de inversão */
380
while ((nbytes = read(fd, buf, BUFSIZE)) > 0) { tmp = lo_write(conn, lobj_fd, buf, nbytes); if (tmp < nbytes) fprintf(stderr, "error while reading large object\n"); } (void) close(fd); (void) lo_close(conn, lobj_fd); return lobjId; } void pickout(PGconn *conn, Oid lobjId, int start, int len) { int lobj_fd; char *buf; int nbytes; int nread; lobj_fd = lo_open(conn, lobjId, INV_READ); if (lobj_fd < 0) { fprintf(stderr, "can't open large object %d\n", lobjId); } lo_lseek(conn, lobj_fd, start, SEEK_SET); buf = malloc(len + 1); nread = 0; while (len - nread > 0) { nbytes = lo_read(conn, lobj_fd, buf, len - nread); buf[nbytes] = ' '; fprintf(stderr, ">>> %s", buf); nread += nbytes; } free(buf); fprintf(stderr, "\n"); lo_close(conn, lobj_fd); } void overwrite(PGconn *conn, Oid lobjId, int start, int len) { int lobj_fd; char *buf; int nbytes; int nwritten; int i; lobj_fd = lo_open(conn, lobjId, INV_READ); if (lobj_fd < 0) { fprintf(stderr, "can't open large object %d\n", lobjId); } lo_lseek(conn, lobj_fd, start, SEEK_SET); buf = malloc(len + 1);
381
for (i = 0; i < len; i++) buf[i] = 'X'; buf[i] = ' '; nwritten = 0; while (len - nwritten > 0) { nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten); nwritten += nbytes; } free(buf); fprintf(stderr, "\n"); lo_close(conn, lobj_fd); } /* * exportFile * exportar o objeto grande "lobjOid" * para o arquivo "out_filename" * */ void exportFile(PGconn *conn, Oid lobjId, char *filename) { int lobj_fd; char buf[BUFSIZE]; int nbytes, tmp; int fd; /* * criar um "objeto" inversão */ lobj_fd = lo_open(conn, lobjId, INV_READ); if (lobj_fd < 0) { fprintf(stderr, "impossível abrir o objeto grande %d\n", lobjId); } /* * abrir o arquivo a ser escrito */ fd = open(filename, O_CREAT | O_WRONLY, 0666); if (fd < 0) { /* erro */ fprintf(stderr, "impossível abrir o arquivo unix %s\n", filename); } /* * ler do arquivo Unix e escrever no arquivo de inversão */ while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0) { tmp = write(fd, buf, nbytes); if (tmp < nbytes) { fprintf(stderr, "erro ao escrever %s\n", filename); }
382
} (void) lo_close(conn, lobj_fd); (void) close(fd); return; } void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } int main(int argc, char **argv) { char *in_filename, *out_filename; char *database; Oid lobjOid; PGconn *conn; PGresult *res; if (argc != 4) { fprintf(stderr, "Utilização: %s nome_do_banco_de_dados\ nome_do_arquivo de entrada\ nome_do_arquivo_de_saída\n", argv[0]); exit(1); } database = argv[1]; in_filename = argv[2]; out_filename = argv[3]; /* * estabelecer a conexão */ conn = PQsetdb(NULL, NULL, NULL, NULL, database); /* verificar se a conexão com o servidor foi bem-sucedida */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr, "Conexão com o banco de dados '%s' falhou.\n", database); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); } res = PQexec(conn, "begin"); PQclear(res);
/*
printf("importing file %s\n", in_filename); lobjOid = importFile(conn, in_filename); */ lobjOid = lo_import(conn, in_filename);
/* printf("as large object %d.\n", lobjOid); printf("picking out bytes 1000-2000 of the large object\n");
383
pickout(conn, lobjOid, 1000, 1000); printf("overwriting bytes 1000-2000 of the large object with X's\n"); overwrite(conn, lobjOid, 1000, 1000); */
/*
printf("exporting large object to file %s\n", out_filename); exportFile(conn, lobjOid, out_filename); */ lo_export(conn, lobjOid, out_filename); res = PQexec(conn, "end"); PQclear(res); PQfinish(conn); exit(0);
}
384
Capítulo 29. pgtcl - Tcl Binding Library pgtcl is a Tcl package for client programs to interface with PostgreSQL servers. It makes most of the functionality of libpq available to Tcl scripts.
29.1. Visão geral Tabela 29-1 gives an overview over the commands available in pgtcl. These commands are described further on subsequent pages. Tabela 29-1. pgtcl Commands Command
Description
pg_connect
open a connection to the server
pg_disconnect
close a connection to the server
pg_conndefaults
get connection options and their defaults
pg_exec
send a command to the server
pg_result
get information about a command result
pg_select
loop over the result of a query
pg_execute
send a query and optionally loop over the results
pg_listen
set or change a callback for asynchronous notification messages
pg_on_connection_loss
set or change a callback for unexpected connection loss
pg_lo_creat
create a large object
pg_lo_open
open a large object
pg_lo_close
close a large object
pg_lo_read
read from a large object
pg_lo_write
write to a large object
pg_lo_lseek
seek to a position in a large object
pg_lo_tell
return the current seek position of a large object
pg_lo_unlink
delete a large object
pg_lo_import
import a large object from a file
pg_lo_export
export a large object to a file
The pg_lo_* commands are interfaces to the large object features of PostgreSQL. The functions are designed to mimic the analogous file system functions in the standard Unix file system interface. The pg_lo_* commands should be used within a BEGIN/COMMIT transaction block because the descriptor returned by pg_lo_open is only valid for the current transaction. pg_lo_import and pg_lo_export must be used in a BEGIN/COMMIT transaction block.
385
29.2. Loading pgtcl into an Application Before using pgtcl commands, you must load the libpgtcl library into your Tcl application. This is normally done with the Tcl load command. Here is an example: load libpgtcl[info sharedlibextension]
The use of info sharedlibextension is recommended in preference to hard-wiring .so or .sl into the program. The load command will fail unless the system's dynamic loader knows where to look for the libpgtcl shared library file. You may need to work with ldconfig, or set the environment variable LD_LIBRARY_PATH, or use some equivalent facility for your platform to make it work. Refer to the PostgreSQL installation instructions for more information. libpgtcl in turn depends on libpq, so the dynamic loader must also be able to find the libpq shared library. In practice this is seldom an issue, since both of these shared libraries are normally stored in the same directory, but it can be a stumbling block in some configurations.
If you use a custom executable for your application, you might choose to statically bind libpgtcl into the executable and thereby avoid the load command and the potential problems of dynamic linking. See the source code for pgtclsh for an example.
386
29.3. pgtcl Command Referencepg_connect Nome pg_connect — open a connection to the server
Sinopse pg_connect -conninfo connectOptions pg_connect dbName ?-host hostName? ?-port portNumber? ?-tty tty? ?-options serverOptions?
Descrição pg_connect opens a connection to the PostgreSQL server.
Two syntaxes are available. In the older one, each possible option has a separate option switch in the pg_connect command. In the newer form, a single option string is supplied that can contain multiple option values. pg_conndefaults can be used to retrieve information about the available options in the newer syntax.
Argumentos Novo estilo connectOptions A string of connection options, each written in the form keyword = value. A list of valid options can be found in the description of the libpq function PQconnectdb.
Estilo antigo dbName The name of the database to connect to. -host hostName
The host name of the database server to connect to. -port portNumber
The TCP port number of the database server to connect to. -tty tty
A file or TTY for optional debug output from the server. -options serverOptions
Additional configuration options to pass to the server.
Valor retornado If successful, a handle for a database connection is returned. Handles start with the prefix pgsql.
387
pg_disconnect Nome pg_disconnect — close a connection to the server
Sinopse pg_disconnect conn
Descrição pg_disconnect closes a connection to the PostgreSQL server.
Argumentos conn The handle of the connection to be closed.
Valor retornado None
388
pg_conndefaults Nome pg_conndefaults — get connection options and their defaults
Sinopse pg_conndefaults
Descrição pg_conndefaults returns information about the connection options available in pg_connect -conninfo and the current default value for each option.
Argumentos None
Valor retornado The result is a list describing the possible connection options and their current default values. Each entry in the list is a sublist of the format: {optname label dispchar dispsize value}
where the optname is usable as an option in pg_connect -conninfo.
389
pg_exec Nome pg_exec — send a command to the server
Sinopse pg_exec conn commandString
Descrição pg_exec submits a command to the PostgreSQL server and returns a result. Command result handles start with the connection handle and add a period and a result number.
Note that lack of a Tcl error is not proof that the command succeeded! An error message returned by the server will be processed as a command result with failure status, not by generating a Tcl error in pg_exec.
Argumentos conn The handle of the connection on which to execute the command. commandString The SQL command to execute.
Valor retornado A result handle. A Tcl error will be returned if pgtcl was unable to obtain a server response. Otherwise, a command result object is created and a handle for it is returned. This handle can be passed to pg_result to obtain the results of the command.
390
pg_result Nome pg_result — get information about a command result
Sinopse pg_result resultHandle resultOption
Descrição pg_result returns information about a command result created by a prior pg_exec.
You can keep a command result around for as long as you need it, but when you are done with it, be sure to free it by executing pg_result -clear. Otherwise, you have a memory leak, and pgtcl will eventually start complaining that you have created too many command result objects.
Argumentos resultHandle The handle of the command result. resultOption One of the following options, specifying which piece of result information to return: -status
The status of the result. -error
The error message, if the status indicates an error, otherwise an empty string. -conn
The connection that produced the result. -oid
If the command was an INSERT, the OID of the inserted row, otherwise 0. -numTuples
The number of rows (tuples) returned by the query. -cmdTuples
The number of rows (tuples) affected by the command. -numAttrs
The number of columns (attributes) in each row. -assign arrayName
Assign the results to an array, using subscripts of the form (rowNumber, columnName). -assignbyidx arrayName ?appendstr?
Assign the results to an array using the values of the first column and the names of the remaining column as keys. If appendstr is given then it is appended to each key. In short, all but the first column of each row are stored into the array, using subscripts of the form (firstColumnValue, columnNameAppendStr). -getTuple rowNumber
Returns the columns of the indicated row in a list. Row numbers start at zero.
391
-tupleArray rowNumber arrayName
Stores the columns of the row in array arrayName, indexed by column names. Row numbers start at zero. -attributes
Returns a list of the names of the columns in the result. -lAttributes
Returns a list of sublists, {name typeOid typeSize} for each column. -clear
Clear the command result object.
Valor retornado The result depends on the selected option, as described above.
392
pg_select Nome pg_select — loop over the result of a query
Sinopse pg_select conn commandString arrayVar procedure
Descrição pg_select submits a query (SELECT statement) to the PostgreSQL server and executes a given chunk of code for each row in the result. The commandString must be a SELECT statement; anything else returns an error. The arrayVar variable is an array name used in the loop. For each row, arrayVar is filled in with the row values, using the column names as the array indices. Then the procedure is executed.
In addition to the column values, the following special entries are made in the array: .headers
A list of the column names returned by the query. .numcols
The number of columns returned by the query. .tupno
The current row number, starting at zero and incrementing for each iteration of the loop body.
Argumentos conn The handle of the connection on which to execute the query. commandString The SQL query to execute. arrayVar An array variable for returned rows. procedure The procedure to run for each returned row.
Valor retornado None
Exemplos This examples assumes that the table table1 has columns control and name (and perhaps others): pg_select $pgconn "SELECT * FROM table1;" array { puts [format "%5d %s" $array(control) $array(name)] }
393
pg_execute Nome pg_execute — send a query and optionally loop over the results
Sinopse pg_execute ?-array arrayVar? ?-oid oidVar? conn commandString ?procedure?
Descrição pg_execute submits a command to the PostgreSQL server.
If the command is not a SELECT statement, the number of rows affected by the command is returned. If the command is an INSERT statement and a single row is inserted, the OID of the inserted row is stored in the variable oidVar if the optional -oid argument is supplied. If the command is a SELECT statement, then, for each row in the result, the row values are stored in the arrayVar variable, if supplied, using the column names as the array indices, else in variables named by the column names, and then the optional procedure is executed if supplied. (Omitting the procedure probably makes sense only if the query will return a single row.) The number of rows selected is returned. The procedure can use the Tcl commands break, continue, and return with the expected behavior. Note that if the procedure executes return, then pg_execute does not return the number of affected rows. pg_execute is a newer function which provides a superset of the features of pg_select and can replace pg_exec in many cases where access to the result handle is not needed.
For server-handled errors, pg_execute will throw a Tcl error and return a two-element list. The first element is an error code, such as PGRES_FATAL_ERROR, and the second element is the server error text. For more serious errors, such as failure to communicate with the server, pg_execute will throw a Tcl error and return just the error message text.
Argumentos -array arrayVar
Specifies the name of an array variable where result rows are stored, indexed by the column names. This is ignored if commandString is not a SELECT statement. -oid oidVar
Specifies the name of a variable into which the OID from an INSERT statement will be stored. conn The handle of the connection on which to execute the command. commandString The SQL command to execute. procedure Optional procedure to execute for each result row of a SELECT statement.
Valor retornado The number of rows affected or returned by the command.
Exemplos In the following examples, error checking with catch has been omitted for clarity.
394
Insert a row and save the OID in result_oid: pg_execute -oid result_oid $pgconn "INSERT INTO mytable VALUES (1);"
Print the columns item and value from each row: pg_execute -array d $pgconn "SELECT item, value FROM mytable;" { puts "Item=$d(item) Value=$d(value)" }
Find the maximum and minimum values and store them in $s(max) and $s(min): pg_execute -array s $pgconn "SELECT max(value) AS max, min(value) AS min FROM mytable;"
Find the maximum and minimum values and store them in $max and $min: pg_execute $pgconn "SELECT max(value) AS max, min(value) AS min FROM mytable;"
395
pg_listen Nome pg_listen — set or change a callback for asynchronous notification messages
Sinopse pg_listen conn notifyName ?callbackCommand?
Descrição pg_listen creates, changes, or cancels a request to listen for asynchronous notification messages from the PostgreSQL server. With a callbackCommand parameter, the request is established, or the command string of an already existing request is replaced. With no callbackCommand parameter, a prior request is canceled.
After a pg_listen request is established, the specified command string is executed whenever a notification message bearing the given name arrives from the server. This occurs when any PostgreSQL client application issues a NOTIFY command referencing that name. The command string is executed from the Tcl idle loop. That is the normal idle state of an application written with Tk. In non-Tk Tcl shells, you can execute update or vwait to cause the idle loop to be entered. You should not invoke the SQL statements LISTEN or UNLISTEN directly when using pg_listen. pgtcl takes care of issuing those statements for you. But if you want to send a notification message yourself, invoke the SQL NOTIFY statement using pg_exec.
Argumentos conn The handle of the connection on which to listen for notifications. notifyName The name of the notification condition to start or stop listening to. callbackCommand If present, provides the command string to execute when a matching notification arrives.
Valor retornado None
396
pg_on_connection_loss Nome pg_on_connection_loss — set or change a callback for unexpected connection loss
Sinopse pg_on_connection_loss conn ?callbackCommand?
Descrição pg_on_connection_loss creates, changes, or cancels a request to execute a callback command if an unexpected loss of connection to the database occurs. With a callbackCommand parameter, the request is established, or the command string of an already existing request is replaced. With no callbackCommand parameter, a prior request is canceled.
The callback command string is executed from the Tcl idle loop. That is the normal idle state of an application written with Tk. In non-Tk Tcl shells, you can execute update or vwait to cause the idle loop to be entered.
Argumentos conn The handle to watch for connection losses. callbackCommand If present, provides the command string to execute when connection loss is detected.
Valor retornado None
397
pg_lo_creat Nome pg_lo_creat — create a large object
Sinopse pg_lo_creat conn mode
Descrição pg_lo_creat creates a large object.
Argumentos conn The handle of a connection to the database in which to create the large object. mode The access mode for the large object. It can be any or'ing together of INV_READ and INV_WRITE. The “or” operator is |. For example: [pg_lo_creat $conn "INV_READ|INV_WRITE"]
Valor retornado The OID of the large object created.
398
pg_lo_open Nome pg_lo_open — open a large object
Sinopse pg_lo_open conn loid mode
Descrição pg_lo_open opens a large object.
Argumentos conn The handle of a connection to the database in which the large object exists. loid The OID of the large object. mode Specifies the access mode for the large object. Mode can be either r, w, or rw.
Valor retornado A descriptor for use in later large-object commands.
399
pg_lo_close Nome pg_lo_close — close a large object
Sinopse pg_lo_close conn descriptor
Descrição pg_lo_close closes a large object.
Argumentos conn The handle of a connection to the database in which the large object exists. descriptor A descriptor for the large object from pg_lo_open.
Valor retornado None
400
pg_lo_read Nome pg_lo_read — read from a large object
Sinopse pg_lo_read conn descriptor bufVar len
Descrição pg_lo_read reads at most len bytes from a large object into a variable named bufVar.
Argumentos conn The handle of a connection to the database in which the large object exists. descriptor A descriptor for the large object from pg_lo_open. bufVar The name of a buffer variable to contain the large object segment. len The maximum number of bytes to read.
Valor retornado The number of bytes actually read is returned; this could be less than the number requested if the end of the large object is reached first. In event of an error, the return value is negative.
401
pg_lo_write Nome pg_lo_write — write to a large object
Sinopse pg_lo_write conn descriptor buf len
Descrição pg_lo_write writes at most len bytes from a variable buf to a large object.
Argumentos conn The handle of a connection to the database in which the large object exists. descriptor A descriptor for the large object from pg_lo_open. buf The string to write to the large object (not a variable name, but the value itself). len The maximum number of bytes to write. The number written will be the smaller of this value and the length of the string.
Valor retornado The number of bytes actually written is returned; this will ordinarily be the same as the number requested. In event of an error, the return value is negative.
402
pg_lo_lseek Nome pg_lo_lseek — seek to a position of a large object
Sinopse pg_lo_lseek conn descriptor offset whence
Descrição pg_lo_lseek moves the current read/write position to offset bytes from the position specified by
whence.
Argumentos conn The handle of a connection to the database in which the large object exists. descriptor A descriptor for the large object from pg_lo_open. offset The new seek position in bytes. whence Specified from where to calculate the new seek position: SEEK_CUR (from current position), SEEK_END (from end), or SEEK_SET (from start).
Valor retornado None
403
pg_lo_tell Nome pg_lo_tell — return the current seek position of a large object
Sinopse pg_lo_tell conn descriptor
Descrição pg_lo_tell returns the current read/write position in bytes from the beginning of the large object.
Argumentos conn The handle of a connection to the database in which the large object exists. descriptor A descriptor for the large object from pg_lo_open.
Valor retornado A zero-based offset in bytes suitable for input to pg_lo_lseek.
404
pg_lo_unlink Nome pg_lo_unlink — delete a large object
Sinopse pg_lo_unlink conn loid
Descrição pg_lo_unlink deletes the specified large object.
Argumentos conn The handle of a connection to the database in which the large object exists. loid The OID of the large object.
Valor retornado None
405
pg_lo_import Nome pg_lo_import — import a large object from a file
Sinopse pg_lo_import conn filename
Descrição pg_lo_import reads the specified file and places the contents into a new large object.
Argumentos conn The handle of a connection to the database in which to create the large object. filename Specified the file from which to import the data.
Valor retornado The OID of the large object created.
Observações pg_lo_import must be called within a BEGIN/COMMIT transaction block.
406
pg_lo_export Nome pg_lo_export — export a large object to a file
Sinopse pg_lo_export conn loid filename
Descrição pg_lo_export writes the specified large object into a file.
Argumentos conn The handle of a connection to the database in which the large object exists. loid The OID of the large object. filename Specifies the file into which the data is to be exported.
Valor retornado None
Observações pg_lo_export must be called within a BEGIN/COMMIT transaction block.
29.4. Example Program Exemplo 29-1 shows a small example of how to use the pgtcl commands. Exemplo 29-1. pgtcl Example Program # getDBs : # get the names of all the databases at a given host and port number # with the defaults being the localhost and port 5432 # return them in alphabetical order proc getDBs { {host "localhost"} {port "5432"} } { # datnames is the list to be result set conn [pg_connect template1 -host $host -port $port] set res [pg_exec $conn "SELECT datname FROM pg_database ORDER BY datname;"] set ntups [pg_result $res -numTuples] for {set i 0} {$i < $ntups} {incr i} { lappend datnames [pg_result $res -getTuple $i] } pg_result $res -clear pg_disconnect $conn return $datnames }
407
Capítulo 30. ECPG - Embedded SQL in C This chapter describes the embedded SQL package for PostgreSQL. It works with C and C++. It was written by Linus Tolke () and Michael Meskes (<[email protected]>). Admittedly, this documentation is quite incomplete. But since this interface is standardized, additional information can be found in many resources about SQL.
30.1. The Concept An embedded SQL program consists of code written in an ordinary programming language, in this case C, mixed with SQL commands in specially marked sections. To build the program, the source code is first passed to the embedded SQL preprocessor, which converts it to an ordinary C program, and afterwards it can be processed by a C compilation tool chain. Embedded SQL has advantages over other methods for handling SQL commands from C code. First, it takes care of the tedious passing of information to and from variables in your C program. Second, the SQL code in the program is checked at build time for syntactical correctness. Third, embedded SQL in C is specified in the SQL standard and supported by many other SQL database systems. The PostgreSQL implementation is designed to match this standard as much as possible, and it is usually possible to port embedded SQL programs written for other SQL databases to PostgreSQL with relative ease. As indicated, programs written for the embedded SQL interface are normal C programs with special code inserted to perform database-related actions. This special code always has the form EXEC SQL ...;
These statements syntactically take the place of a C statement. Depending on the particular statement, they may appear in the global context or within a function. Embedded SQL statements follow the case-sensitivity rules of normal SQL code, and not those of C. The following sections explain all the embedded SQL statements.
30.2. Connecting to the Database Server One connects to a database using the following statement: EXEC SQL CONNECT TO target [AS connection-name] [USER user-name];
The target can be specified in the following ways: • dbname[@hostname][:port] • tcp:postgresql://hostname[:port][/dbname][?options] • unix:postgresql://hostname[:port][/dbname][?options] •
an SQL string literal containing one of the above forms
•
a reference to a character variable containing one of the above forms (see examples)
• DEFAULT
If you specify the connection target literally (that is, not through a variable reference) and you don't quote the value, then the case-insensitivity rules of normal SQL are applied. In that case you can also double-quote the individual parameters separately as needed. In practice, it is probably less error-prone to use a (single-quoted) string literal or a variable reference. The connection target DEFAULT initiates a connection to the default database under the default user name. No separate user name or connection name may be specified in that case. There are also different ways to specify the user name: • username • username/password
408
• username IDENTIFIED BY password • username USING password
As above, the parameters username and password may be an SQL identifier, an SQL string literal, or a reference to a character variable. The connection-name is used to handle multiple connections in one program. It can be omitted if a program uses only one connection. The most recently opened connection becomes the current connection, which is used by default when an SQL statement is to be executed (see later in this chapter). Here are some examples of CONNECT statements: EXEC SQL CONNECT TO [email protected]; EXEC SQL CONNECT TO 'unix:postgresql://sql.mydomain.com/mydb' AS myconnection USER john; EXEC SQL BEGIN DECLARE SECTION; const char *target = "[email protected]"; const char *user = "john"; EXEC SQL END DECLARE SECTION; ... EXEC SQL CONNECT TO :target USER :user;
The last form makes use of the variant referred to above as character variable reference. You will see in later sections how C variables can be used in SQL statements when you prefix them with a colon. Be advised that the format of the connection target is not specified in the SQL standard. So if you want to develop portable applications, you might want to use something based on the last example above to encapsulate the connection target string somewhere.
30.3. Closing a Connection To close a connection, use the following statement: EXEC SQL DISCONNECT [connection];
The connection can be specified in the following ways: • connection-name • DEFAULT • CURRENT • ALL
If no connection name is specified, the current connection is closed. It is good style that an application always explicitly disconnect from every connection it opened.
30.4. Running SQL Commands Any SQL command can be run from within an embedded SQL application. Below are some examples of how to do that. Creating a table: EXEC SQL CREATE TABLE foo (number integer, ascii char(16)); EXEC SQL CREATE UNIQUE INDEX num1 ON foo(number); EXEC SQL COMMIT;
Inserting rows: EXEC SQL INSERT INTO foo (number, ascii) VALUES (9999, 'doodad'); EXEC SQL COMMIT;
409
Deleting rows: EXEC SQL DELETE FROM foo WHERE number = 9999; EXEC SQL COMMIT;
Single-row select: EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad';
Select using cursors: EXEC SQL DECLARE foo_bar CURSOR FOR SELECT number, ascii FROM foo ORDER BY ascii; EXEC SQL OPEN foo_bar; EXEC SQL FETCH foo_bar INTO :FooBar, DooDad; ... EXEC SQL CLOSE foo_bar; EXEC SQL COMMIT;
Updates: EXEC SQL UPDATE foo SET ascii = 'foobar' WHERE number = 9999; EXEC SQL COMMIT;
The tokens of the form :something are host variables, that is, they refer to variables in the C program. They are explained in Seção 30.6. In the default mode, statements are committed only when EXEC SQL COMMIT is issued. The embedded SQL interface also supports autocommit of transactions (as known from other interfaces) via the -t command-line option to ecpg (see below) or via the EXEC SQL SET AUTOCOMMIT TO ON statement. In autocommit mode, each command is automatically committed unless it is inside an explicit transaction block. This mode can be explicitly turned off using EXEC SQL SET AUTOCOMMIT TO OFF.
30.5. Choosing a Connection The SQL statements shown in the previous section are executed on the current connection, that is, the most recently opened one. If an application needs to manage multiple connections, then there are two ways to handle this. The first option is to explicitly choose a connection for each SQL statement, for example EXEC SQL AT connection-name SELECT ...;
This option is particularly suitable if the application needs to use several connections in mixed order. The second option is to execute a statement to switch the current connection. That statement is: EXEC SQL SET CONNECTION connection-name;
This option is particularly convenient if many statements are to be executed on the same connection. It is not thread-aware.
30.6. Using Host Variables In Seção 30.4 you saw how you can execute SQL statements from an embedded SQL program. Some of those statements only used fixed values and did not provide a way to insert user-supplied values into statements or have the program process the values returned by the query. Those kinds of statements are not really useful in real applications. This section explains in detail how you can pass data between your C program and the embedded SQL statements using a simple mechanism called host variables.
410
30.6.1. Overview Passing data between the C program and the SQL statements is particularly simple in embedded SQL. Instead of having the program paste the data into the statement, which entails various complications, such as properly quoting the value, you can simply write the name of a C variable into the SQL statement, prefixed by a colon. For example: EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);
This statements refers to two C variables named v1 and v2 and also uses a regular SQL string literal, to illustrate that you are not restricted to use one kind of data or the other. This style of inserting C variables in SQL statements works anywhere a value expression is expected in an SQL statement. In the SQL environment we call the references to C variables host variables.
30.6.2. Declare Sections To pass data from the program to the database, for example as parameters in a query, or to pass data from the database back to the program, the C variables that are intended to contain this data need to be declared in specially marked sections, so the embedded SQL preprocessor is made aware of them. This section starts with EXEC SQL BEGIN DECLARE SECTION;
and ends with EXEC SQL END DECLARE SECTION;
Between those lines, there must be normal C variable declarations, such as int char
x; foo[16], bar[16];
You can have as many declare sections in a program as you like. The declarations are also echoed to the output file as a normal C variables, so there's no need to declare them again. Variables that are not intended to be used with SQL commands can be declared normally outside these special sections. The definition of a structure or union also must be listed inside a DECLARE section. Otherwise the preprocessor cannot handle these types since it does not know the definition. The special type VARCHAR is converted into a named struct for every variable. A declaration like VARCHAR var[180];
is converted into struct varchar_var { int len; char arr[180]; } var;
This structure is suitable for interfacing with SQL datums of type varchar.
30.6.3. SELECT INTO and FETCH INTO Now you should be able to pass data generated by your program into an SQL command. But how do you retrieve the results of a query? For that purpose, embedded SQL provides special variants of the usual commands SELECT and FETCH. These commands have a special INTO clause that specifies which host variables the retrieved values are to be stored in. Here is an example:
411
/* * assume this table: * CREATE TABLE test1 (a int, b varchar(50)); */ EXEC SQL BEGIN DECLARE SECTION; int v1; VARCHAR v2; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT a, b INTO :v1, :v2 FROM test;
So the INTO clause appears between the select list and the FROM clause. The number of elements in the select list and the list after INTO (also called the target list) must be equal. Here is an example using the command FETCH: EXEC SQL BEGIN DECLARE SECTION; int v1; VARCHAR v2; EXEC SQL END DECLARE SECTION; ... EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test; ... do { ... EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2; ... } while (...);
Here the INTO clause appears after all the normal clauses. Both of these methods only allow retrieving one row at a time. If you need to process result sets that potentially contain more than one row, you need to use a cursor, as shown in the second example.
30.6.4. Indicators The examples above do not handle null values. In fact, the retrieval examples will raise an error if they fetch a null value from the database. To be able to pass null values to the database or retrieve null values from the database, you need to append a second host variable specification to each host variable that contains data. This second host variable is called the indicator and contains a flag that tells whether the datums is null, in which case the value of the real host variable is ignored. Here is an example that handles the retrieval of null values correctly: EXEC SQL BEGIN DECLARE SECTION; VARCHAR val; int val_ind; EXEC SQL END DECLARE SECTION: ... EXEC SQL SELECT b INTO :val :val_ind FROM test1;
The indicator variable val_ind will be zero if the value was not null, and it will be negative if the value was null. The indicator has another function: if the indicator value is positive, it means that the value is not null, but it was truncated when it was stored in the host variable.
412
30.7. Dynamic SQL In many cases, the particular SQL statements that an application has to execute are known at the time the application is written. In some cases, however, the SQL statements are composed at run time or provided by an external source. In these cases you cannot embed the SQL statements directly into the C source code, but there is a facility that allows you to call arbitrary SQL statements that you provide in a string variable. The simplest way to execute an arbitrary SQL statement is to use the command EXECUTE IMMEDIATE. For example: EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1 (...);"; EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt;
You may not execute statements that retrieve data (e.g., SELECT) this way. A more powerful way to execute arbitrary SQL statements is to prepare them once and execute the prepared statement as often as you like. It is also possible to prepare a generalized version of a statement and then execute specific versions of it by substituting parameters. When preparing the statement, write question marks where you want to substitute parameters later. For example: EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "INSERT INTO test1 VALUES(?, ?);"; EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE mystmt FROM :stmt; ... EXEC SQL EXECUTE mystmt USING 42, 'foobar';
If the statement you are executing returns values, then add an INTO clause: EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?"; int v1, v2; VARCHAR v3; EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE mystmt FROM :stmt; ... EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;
An EXECUTE command may have an INTO clause, a USING clause, both, or neither. When you don't need the prepared statement anymore, you should deallocate it: EXEC SQL DEALLOCATE PREPARE name;
30.8. Using SQL Descriptor Areas An SQL descriptor area is a more sophisticated method for processing the result of a SELECT or FETCH statement. An SQL descriptor area groups the data of one row of data together with metadata items into one data structure. The metadata is particularly useful when executing dynamic SQL statements, where the nature of the result columns may not be known ahead of time. An SQL descriptor area consists of a header, which contains information concerning the entire descriptor, and one or more item descriptor areas, which basically each describe one column in the result row. Before you can use an SQL descriptor area, you need to allocate one: EXEC SQL ALLOCATE DESCRIPTOR identifier;
The identifier serves as the “variable name” of the descriptor area. When you don't need the descriptor anymore, you should deallocate it:
413
EXEC SQL DEALLOCATE DESCRIPTOR identifier;
To use a descriptor area, specify it as the storage target in an INTO clause, instead of listing host variables: EXEC SQL FETCH NEXT FROM mycursor INTO DESCRIPTOR mydesc;
Now how do you get the data out of the descriptor area? You can think of the descriptor area as a structure with named fields. To retrieve the value of a field from the header and store it into a host variable, use the following command: EXEC SQL GET DESCRIPTOR name :hostvar = field;
Currently, there is only one header field defined: COUNT, which tells how many item descriptor areas exist (that is, how many columns are contained in the result). The host variable needs to be of an integer type. To get a field from the item descriptor area, use the following command: EXEC SQL GET DESCRIPTOR name VALUE num :hostvar = field;
num can be a literal integer or a host variable containing an integer. Possible fields are: CARDINALITY (integer)
number of rows in the result set DATA
actual data item (therefore, the data type of this field depends on the query) DATETIME_INTERVAL_CODE (integer)
? DATETIME_INTERVAL_PRECISION (integer)
not implemented INDICATOR (integer)
the indicator (indicating a null value or a value truncation) KEY_MEMBER (integer)
not implemented LENGTH (integer)
length of the datum in characters NAME (string)
name of the column NULLABLE (integer)
not implemented OCTET_LENGTH (integer)
length of the character representation of the datum in bytes PRECISION (integer)
precision (for type numeric) RETURNED_LENGTH (integer)
length of the datum in characters RETURNED_OCTET_LENGTH (integer)
length of the character representation of the datum in bytes SCALE (integer)
scale (for type numeric)
414
TYPE (integer)
numeric code of the data type of the column
30.9. Error Handling This section describes how you can handle exceptional conditions and warnings in an embedded SQL program. There are several nonexclusive facilities for this.
30.9.1. Setting Callbacks One simple method to catch errors and warnings is to set a specific action to be executed whenever a particular condition occurs. In general: EXEC SQL WHENEVER condition action;
condition can be one of the following: SQLERROR
The specified action is called whenever an error occurs during the execution of an SQL statement. SQLWARNING
The specified action is called whenever a warning occurs during the execution of an SQL statement. NOT FOUND
The specified action is called whenever an SQL statement retrieves or affects zero rows. (This condition is not an error, but you might be interested in handling it specially.) action can be one of the following: CONTINUE
This effectively means that the condition is ignored. This is the default. GOTO label GO TO label
Jump to the specified label (using a C goto statement). SQLPRINT
Print a message to standard error. This is useful for simple programs or during prototyping. The details of the message cannot be configured. STOP
Call exit(1), which will terminate the program. BREAK
Execute the C statement break. This should only be used in loops or switch statements. CALL name (args) DO name (args)
Call the specified C functions with the specified arguments. The SQL standard only provides for the actions CONTINUE and GOTO (and GO TO). Here is an example that you might want to use in a simple program. It prints a simple message when a warning occurs and aborts the program when an error happens. EXEC SQL WHENEVER SQLWARNING SQLPRINT; EXEC SQL WHENEVER SQLERROR STOP;
The statement EXEC SQL WHENEVER is a directive of the SQL preprocessor, not a C statement. The error or warning actions that it sets apply to all embedded SQL statements that appear below the point where the handler is set, unless a different action was set for the same condition between the first EXEC SQL WHENEVER
415
and the SQL statement causing the condition, regardless of the flow of control in the C program. So neither of the two following C program excerpts will have the desired effect. /* * WRONG */ int main(int argc, char *argv[]) { ... if (verbose) { EXEC SQL WHENEVER SQLWARNING SQLPRINT; } ... EXEC SQL SELECT ...; ... } /* * WRONG */ int main(int argc, char *argv[]) { ... set_error_handler(); ... EXEC SQL SELECT ...; ... } static void set_error_handler(void) { EXEC SQL WHENEVER SQLERROR STOP; }
30.9.2. sqlca For a more powerful error handling, the embedded SQL interface provides a global variable with the name sqlca that has the following structure: struct { char sqlcaid[8]; long sqlabc; long sqlcode; struct { int sqlerrml; char sqlerrmc[70]; } sqlerrm; char sqlerrp[8]; long sqlerrd[6]; char sqlwarn[8]; char sqlstate[5]; } sqlca;
(In a multithreaded program, every thread automatically gets its own copy of sqlca. This works similar to the handling of the standard C global variable errno.) sqlca covers both warnings and errors. If multiple warnings or errors occur during the execution of a statement, then sqlca will only contain information about the last one.
If no error occurred in the last SQL statement, sqlca.sqlcode will be 0 and sqlca.sqlstate will be "00000". If a warning or error occurred, then sqlca.sqlcode will be negative and sqlca.sqlstate will
416
be different from "00000". A positive sqlca.sqlcode indicates a harmless condition, such as that the last query returned zero rows. sqlcode and sqlstate are two different error code schemes; details appear below. If the last SQL statement was successful, then sqlca.sqlerrd[1] contains the OID of the processed row, if applicable, and sqlca.sqlerrd[2] contains the number of processed or returned rows, if applicable to the command. In case of an error or warning, sqlca.sqlerrm.sqlerrmc will contain a string that describes the error. The field sqlca.sqlerrm.sqlerrml contains the length of the error message that is stored in sqlca.sqlerrm.sqlerrmc (the result of strlen(), not really interesting for a C programmer). In case of a warning, sqlca.sqlwarn[2] is set to W. (In all other cases, it is set to something different from W.) If sqlca.sqlwarn[1] is set to W, then a value was truncated when it was stored in a host variable. sqlca.sqlwarn[0] is set to W if any of the other elements are set to indicate a warning. The fields sqlcaid, sqlcabc, sqlerrp, and the remaining elements of sqlerrd and sqlwarn currently contain no useful information. The structure sqlca is not defined in the SQL standard, but is implemented in several other SQL database systems. The definitions are similar in the core, but if you want to write portable applications, then you should investigate the different implementations carefully.
30.9.3. SQLSTATE vs SQLCODE The fields sqlca.sqlstate and sqlca.sqlcode are two different schemes that provide error codes. Both are specified in the SQL standard, but SQLCODE has been marked deprecated in the 1992 edition of the standard and has been dropped in the 1999 edition. Therefore, new applications are strongly encouraged to use SQLSTATE. SQLSTATE is a five-character array. The five characters contain digits or upper-case letters that represent codes of various error and warning conditions. SQLSTATE has a hierarchical scheme: the first two characters indicate the general class of the condition, the last three characters indicate a subclass of the general condition. A successful state is indicated by the code 00000. The SQLSTATE codes are for the most part defined in the SQL standard. The PostgreSQL server natively supports SQLSTATE error codes; therefore a high degree of consistency can be achieved by using this error code scheme throughout all applications. For further information see Apêndice A. SQLCODE, the deprecated error code scheme, is a simple integer. A value of 0 indicates success, a positive value indicates success with additional information, a negative value indicates an error. The SQL standard only defines the positive value +100, which indicates that the last command returned or affected zero rows, and no specific negative values. Therefore, this scheme can only achieve poor portability and does not have a hierarchical code assignment. Historically, the embedded SQL processor for PostgreSQL has assigned some specific SQLCODE values for its use, which are listed below with their numeric value and their symbolic name. Remember that these are not portable to other SQL implementations. To simplify the porting of applications to the SQLSTATE scheme, the corresponding SQLSTATE is also listed. There is, however, no one-to-one or one-tomany mapping between the two schemes (indeed it is many-to-many), so you should consult the global SQLSTATE listing in Apêndice A in each case.
These are the assigned SQLCODE values: -12 (ECPG_OUT_OF_MEMORY) Indicates that your virtual memory is exhausted. (SQLSTATE YE001) -200 (ECPG_UNSUPPORTED) Indicates the preprocessor has generated something that the library does not know about. Perhaps you are running incompatible versions of the preprocessor and the library. (SQLSTATE YE002) -201 (ECPG_TOO_MANY_ARGUMENTS) This means that the command specified more host variables than the command expected. (SQLSTATE 07001 or 07002)
417
-202 (ECPG_TOO_FEW_ARGUMENTS) This means that the command specified fewer host variables than the command expected. (SQLSTATE 07001 or 07002) -203 (ECPG_TOO_MANY_MATCHES) This means a query has returned multiple rows but the statement was only prepared to store one result row (for example, because the specified variables are not arrays). (SQLSTATE 21000) -204 (ECPG_INT_FORMAT) The host variable is of type int and the datum in the database is of a different type and contains a value that cannot be interpreted as an int. The library uses strtol() for this conversion. (SQLSTATE 42804) -205 (ECPG_UINT_FORMAT) The host variable is of type unsigned int and the datum in the database is of a different type and contains a value that cannot be interpreted as an unsigned int. The library uses strtoul() for this conversion. (SQLSTATE 42804) -206 (ECPG_FLOAT_FORMAT) The host variable is of type float and the datum in the database is of another type and contains a value that cannot be interpreted as a float. The library uses strtod() for this conversion. (SQLSTATE 42804) -207 (ECPG_CONVERT_BOOL) This means the host variable is of type bool and the datum in the database is neither 't' nor 'f'. (SQLSTATE 42804) -208 (ECPG_EMPTY) The statement sent to the PostgreSQL server was empty. (This cannot normally happen in an embedded SQL program, so it may point to an internal error.) (SQLSTATE YE002) -209 (ECPG_MISSING_INDICATOR) A null value was returned and no null indicator variable was supplied. (SQLSTATE 22002) -210 (ECPG_NO_ARRAY) An ordinary variable was used in a place that requires an array. (SQLSTATE 42804) -211 (ECPG_DATA_NOT_ARRAY) The database returned an ordinary variable in a place that requires array value. (SQLSTATE 42804) -220 (ECPG_NO_CONN) The program tried to access a connection that does not exist. (SQLSTATE 08003) -221 (ECPG_NOT_CONN) The program tried to access a connection that does exist but is not open. (This is an internal error.) (SQLSTATE YE002) -230 (ECPG_INVALID_STMT) The statement you are trying to use has not been prepared. (SQLSTATE 26000) -240 (ECPG_UNKNOWN_DESCRIPTOR) The descriptor specified was not found. The statement you are trying to use has not been prepared. (SQLSTATE 33000) -241 (ECPG_INVALID_DESCRIPTOR_INDEX) The descriptor index specified was out of range. (SQLSTATE 07009) -242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM) An invalid descriptor item was requested. (This is an internal error.) (SQLSTATE YE002)
418
-243 (ECPG_VAR_NOT_NUMERIC) During the execution of a dynamic statement, the database returned a numeric value and the host variable was not numeric. (SQLSTATE 07006) -244 (ECPG_VAR_NOT_CHAR) During the execution of a dynamic statement, the database returned a non-numeric value and the host variable was numeric. (SQLSTATE 07006) -400 (ECPG_PGSQL) Some error caused by the PostgreSQL server. The message contains the error message from the PostgreSQL server. -401 (ECPG_TRANS) The PostgreSQL server signaled that we cannot start, commit, or rollback the transaction. (SQLSTATE 08007) -402 (ECPG_CONNECT) The connection attempt to the database did not succeed. (SQLSTATE 08001) 100 (ECPG_NOT_FOUND) This is a harmless condition indicating that the last command retrieved or processed zero rows, or that you are at the end of the cursor. (SQLSTATE 02000)
30.10. Including Files To include an external file into your embedded SQL program, use: EXEC SQL INCLUDE filename;
The embedded SQL preprocessor will look for a file named filename.h, preprocess it, and include it in the resulting C output. Thus, embedded SQL statements in the included file are handled correctly. Note that this is not the same as #include
because this file would not be subject to SQL command preprocessing. Naturally, you can continue to use the C #include directive to include other header files. Nota: The include file name is case-sensitive, even though the rest of the EXEC SQL INCLUDE command follows the normal SQL case-sensitivity rules.
30.11. Processing Embedded SQL Programs Now that you have an idea how to form embedded SQL C programs, you probably want to know how to compile them. Before compiling you run the file through the embedded SQL C preprocessor, which converts the SQL statements you used to special function calls. After compiling, you must link with a special library that contains the needed functions. These functions fetch information from the arguments, perform the SQL command using the libpq interface, and put the result in the arguments specified for output. The preprocessor program is called ecpg and is included in a normal PostgreSQL installation. Embedded SQL programs are typically named with an extension .pgc. If you have a program file called prog1.pgc, you can preprocess it by simply calling ecpg prog1.pgc
This will create a file called prog1.c. If your input files do not follow the suggested naming pattern, you can specify the output file explicitly using the -o option. The preprocessed file can be compiled normally, for example:
419
cc -c prog1.c
The generated C source files include headers files from the PostgreSQL installation, so if you installed PostgreSQL in a location that is not searched by default, you have to add an option such as I/usr/local/pgsql/include to the compilation command line. To link an embedded SQL program, you need to include the libecpg library, like so: cc -o myprog prog1.o prog2.o ... -lecpg
Again, you might have to add an option like -L/usr/local/pgsql/lib to that command line. If you manage the build process of a larger project using make, it may be convenient to include the following implicit rule to your makefiles: ECPG = ecpg %.c: %.pgc $(ECPG) $<
The complete syntax of the ecpg command is detailed in ecpg. ecpg is thread-safe if it is compiled using the --enable-thread-safety configure command-line option. (You might need to use other threading command-line options to compile your client code.)
30.12. Library Functions The libecpg library primarily contains “hidden” functions that are used to implement the functionality expressed by the embedded SQL commands. But there are some functions that can usefully be called directly. Note that this makes your code unportable. turns on debug logging if called with the first argument non-zero. Debug logging is done on stream. The log contains all SQL statements with all the input variables inserted, and the results from the PostgreSQL server. This can be very useful when searching for errors in your SQL statements.
• ECPGdebug(int on, FILE *stream)
• ECPGstatus()
returns true if you are connected to a database and false if not.
30.13. Internals This section explain how ECPG works internally. This information can occasionally be useful to help users understand how to use ECPG. The first four lines written by ecpg to the output are fixed lines. Two are comments and two are include lines necessary to interface to the library. Then the preprocessor reads through the file and writes output. Normally it just echoes everything to the output. When it sees an EXEC SQL statement, it intervenes and changes it. The command starts with EXEC SQL and ends with ;. Everything in between is treated as an SQL statement and parsed for variable substitution. Variable substitution occurs when a symbol starts with a colon (:). The variable with that name is looked up among the variables that were previously declared within a EXEC SQL DECLARE section. The most important function in the library is ECPGdo, which takes care of executing most commands. It takes a variable number of arguments. This can easily add up to 50 or so arguments, and we hope this will not be a problem on any platform. The arguments are: A line number This is the line number of the original line; used in error messages only.
420
A string This is the SQL command that is to be issued. It is modified by the input variables, i.e., the variables that where not known at compile time but are to be entered in the command. Where the variables should go the string contains ?. Input variables Every input variable causes ten arguments to be created. (See below.) ECPGt_EOIT An enum telling that there are no more input variables. Output variables Every output variable causes ten arguments to be created. (See below.) These variables are filled by the function. ECPGt_EORT An enum telling that there are no more variables. For every variable that is part of the SQL command, the function gets ten arguments: 1. The type as a special symbol. 2. A pointer to the value or a pointer to the pointer. 3. The size of the variable if it is a char or varchar. 4. The number of elements in the array (for array fetches). 5. The offset to the next element in the array (for array fetches). 6. The type of the indicator variable as a special symbol. 7. A pointer to the indicator variable. 8. 0 9. The number of elements in the indicator array (for array fetches). 10. The offset to the next element in the indicator array (for array fetches). Note that not all SQL commands are treated in this way. For instance, an open cursor statement like EXEC SQL OPEN cursor;
is not copied to the output. Instead, the cursor's DECLARE command is used at the position of the OPEN command because it indeed opens the cursor. Here is a complete example describing the output of the preprocessor of a file foo.pgc (details may change with each particular version of the preprocessor): EXEC SQL BEGIN DECLARE SECTION; int index; int result; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;
421
is translated into: /* Processed by ecpg (2.6.0) */ /* These two include files are added by the preprocessor */ #include <ecpgtype.h>; #include <ecpglib.h>; /* exec sql begin declare section */ #line 1 "foo.pgc" int index; int result; /* exec sql end declare section */ ... ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ? ECPGt_int,&(index),1L,1L,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_int,&(result),1L,1L,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); #line 147 "foo.pgc"
",
(The indentation here is added for readability and not something the preprocessor does.)
422
Capítulo 31. A interface JDBC O JDBC é uma API núcleo do Java 1.1 e posteriores. Fornece um conjunto padrão de interfaces para bancos de dados em conformidade com o SQL. O PostgreSQL fornece um driver JDBC tipo 4. O tipo 4 indica que o driver é escrito inteiramente em Java, e se comunica utilizando o protocolo de rede nativo do sistema de banco de dados. Por causa disto, o driver é independente da plataforma; uma vez compilado, o driver pode ser utilizado em qualquer sistema. Este capítulo não tem por intenção ser um guia completo de programação JDBC, mas deve ajudar a começar. Para obter mais informações veja a documentação da API JDBC. Também devem ser vistos os exemplos incluídos com o fonte.
31.1. Definição do driver JDBC Esta seção descreve os passos a serem realizados antes de se poder escrever ou executar programas que utilizam a interface JDBC.
31.1.1. Obtenção do driver As versões pré-compiladas do driver podem ser baixadas da página PostgreSQL JDBC Drivers (http://jdbc.postgresql.org) 1 . Como alternativa, o driver pode ser construído a partir do código fonte, mas isso somente deve ser feito quando são feitas alterações no código fonte. Para obter detalhes, consulte as instruções de instalação do PostgreSQL. Após a instalação o driver deverá estar em PREFIX/share/java/postgresql.jar. O driver produzido será construído para a versão do Java sendo executada. Se for construído com o JDK 1.1 será produzida uma versão que suporta a especificação JDBC 1, se for construído com o JDK 1.2 ou 1.3 será produzida uma versão que suporta a especificação JDBC 2 e, finalmente, se for construído com o JDK 1.4 será produzida uma versão que suporta a especificação JDBC 3.
31.1.2. Definição do caminho de classe Para o driver poder ser utilizado, o arquivo JAR (chamado postgresql.jar se for construído a partir do fonte ou então chamado, provavelmente, pg7.4jdbc1.jar, pg7.4jdbc2.jar ou pg7.4jdbc3.jar para as versões JDBC 1, JDBC 2 e JDBC 3, respectivamente) precisa ser incluído no caminho de classe, seja colocando-o na variável de ambiente CLASSPATH, ou utilizando sinalizadores na linha de comando do java. Por exemplo, assumindo haver uma aplicação que utiliza o driver JDBC para acessar o banco de dados, que esta aplicação esteja instalada como /usr/local/lib/myapp.jar, e que o driver JDBC do PostgreSQL esteja instalado como /usr/local/pgsql/share/java/postgresql.jar, para executar esta aplicação deve ser utilizado 2 : export CLASSPATH=/usr/local/lib/myapp.jar:/usr/local/pgsql/share/java/postgresql.jar:. java MyApp
A carga do driver dentro da aplicação está descrita na Seção 31.2.
31.1.3. Preparação do servidor de banco de dados para o JDBC Uma vez que o Java utiliza somente conexões TCP/IP, o servidor PostgreSQL deve estar configurado para aceitar conexões TCP/IP. Isto pode ser feito definindo tcpip_socket = true no arquivo postgresql.conf ou através da opção -i ao inicializar o postmaster. Também precisa ser configurada a definição da autenticação do cliente no arquivo pg_hba.conf . Consulte o Capítulo 19 para obter detalhes. O driver JDBC suporta os métodos de autenticação trust, ident, senha, md5 e crypt.
423
31.2. Inicialização do driver Esta seção descreve como carregar e inicializar o driver JDBC nos programas.
31.2.1. Importação do JDBC Todo fonte que utiliza o JDBC precisa importar o pacote java.sql, utilizando: import java.sql.*; Nota: Não deve ser importado o pacote org.postgresql. Se isto for feito o fonte não vai compilar, porque o javac vai se confundir.
31.2.2. Carga do driver Antes de ser possível fazer a conexão com o banco de dados é necessário carregar o driver. Estão disponíveis dois métodos, e depende do código qual é o melhor para ser utilizado. No primeiro método, o código carrega implicitamente o driver utilizando o método Class.forName(). Para o PostgreSQL é utilizado: Class.forName("org.postgresql.Driver");
Este método carrega o driver e, enquanto carrega, o driver automaticamente se registra no gerenciador de driver JDBC. Nota: O método forName() pode lançar a exceção ClassNotFoundException se o driver não estiver disponível.
Este é o método usado mais comumente, mas restringe o código a usar apenas o PostgreSQL. Se houver possibilidade do código acessar outro sistema de banco de dados no futuro, e não se deseja utilizar nenhuma extensão específica do PostgreSQL, então o segundo método é mais aconselhável. O segundo método passa o driver como um parâmetro para a JVM quando esta é inicializada, utilizando o argumento -D. Por exemplo: java -Djdbc.drivers=org.postgresql.Driver exemplo.VerImagem
Neste exemplo a JVM tenta carregar o driver como parte de sua inicialização. Uma vez isto feito, VerImagem é iniciado.
Este método é o melhor, porque permite o código ser utilizado com outros gerenciadores de banco de dados sem a necessidade de ser recompilado. A única coisa que também mudaria é a URL da conexão, é coberta a seguir. Para terminar: Quando o código utiliza a classe Connection para abrir uma conexão, e é lançada uma exceção SQLException com a mensagem Nenhum driver disponível, provavelmente isto foi causado pelo fato do driver não estar no caminho de classe, ou o valor do parâmetro não estar correto.
31.2.3. Conexão com o banco de dados No JDBC, o banco de dados é representado por uma URL (Uniform Resource Locator). No PostgreSQL, a URL possui uma das seguintes formas: • jdbc:postgresql:banco_de_dados • jdbc:postgresql://hospedeiro/banco_de_dados • jdbc:postgresql://hospedeiro:porta/banco_de_dados
Os parâmetros possuem o seguinte significado: hospedeiro O nome de hospedeiro do servidor. O padrão é localhost. Para se especificar um endereço de IPv6 o parâmetro hospedeiro deve estar entre colchetes como, por exemplo:
424
jdbc:postgresql://[::1]:5740/contabilidade
porta O número da porta onde o servidor está ouvindo as conexões. O padrão é o número de porta padrão do PostgreSQL (5432). banco_de_dados O nome do banco de dados. Para se conectar é necessário obter uma instância Connection do JDBC. Para isto é utilizado DriverManager.getConnection(): Connection db = DriverManager.getConnection(url, nome_do_usuário, senha);
31.2.4. Fechamento da conexão Para fechar a conexão com o banco de dados simplesmente deve ser chamado o método close() da classe Connection: db.close();
31.3. Realização de consultas e processamento dos resultados Para enviar uma declaração SQL para o banco de dados é necessária uma instância de Statement ou de PreparedStatement. Uma vez obtida, a consulta pode ser enviada. É retornada uma instância de ResultSet contendo todo o resultado (veja como alterar este comportamento na Seção 31.3.1 abaixo). O Exemplo 31-1 mostra este processo. Exemplo 31-1. Processamento de consulta simples usando JDBC Este exemplo envia uma consulta simples e mostra a primeira coluna de cada linha utilizando Statement. Statement st = db.createStatement(); ResultSet rs = st.executeQuery("SELECT * " + "FROM minha_tabela " + "WHERE coluna_foo = 500"); while (rs.next()) { System.out.print("Coluna 1 retornada "); System.out.println(rs.getString(1)); } rs.close(); st.close();
Este exemplo usa a mesma consulta anterior, mas utiliza PreparedStatement e um valor vinculado na consulta. int valor_foo = 500; PreparedStatement st = db.prepareStatement("SELECT * " + "FROM minha_tabela " + "WHERE coluna_foo = ?"); st.setInt(1, valor_foo); ResultSet rs = st.executeQuery(); while (rs.next()) { System.out.print("Coluna 1 retornada "); System.out.println(rs.getString(1)); } rs.close(); st.close();
425
31.3.1. Busca dos resultados com base em um cursor Por padrão o driver traz todos os resultados da consulta de uma só vez. Esta forma pode não ser conveniente para conjuntos grandes de dados e, por isso, o driver JDBC fornece uma maneira de basear o ResultSet em um cursor do banco de dados, e somente trazer um pequeno número de linhas. Um pequeno número de linhas é armazenado no lado cliente da conexão, e quando exauridas o próximo bloco de linhas é trazido reposicionando o cursor. Exemplo 31-2. Definição do tamanho de busca para habilitar e desabilitar o cursor Alterar o código para o modo cursor é tão simples quanto definir o tamanho de busca de Statement para o valor apropriado. Definir o tamanho de busca novamente como 0 faz com que todas as linhas seja trazidas (o comportamento padrão). Statement st = db.createStatement(); // Habilitar o uso do cursor. st.setFetchSize(50); ResultSet rs = st.executeQuery("SELECT * FROM minha_tabela"); while (rs.next()) { System.out.print("uma linha foi retornada."); } rs.close(); // Desabilitar o uso do cursor. st.setFetchSize(0); ResultSet rs = st.executeQuery("SELECT * FROM minha_tabela"); while (rs.next()) { System.out.print("muitas linhas foram retornadas."); } rs.close(); // Fechar a declaração. st.close();
31.3.2. Utilização da interface Statement ou PreparedStatement As seguintes informações devem ser consideradas quando for utilizada a interface Statement ou PreparedStatement: •
Pode ser utilizada uma única instância de Statement quantas vezes se desejar. Esta instância pode ser criada tão logo a conexão seja aberta e utilizada durante toda a existência da conexão. Mas deve ser lembrado que pode existir somente um ResultSet por Statement ou PreparedStatement em um determinado momento.
•
Se for necessário executar uma consulta enquanto estiver processando o ResultSet, pode-se simplesmente criar e utilizar outro Statement.
•
Se forem utilizadas threads (linhas de execução), com várias delas acessando o banco de dados, deve ser utilizado um Statement para cada linha de execução. Consulte a Seção 31.9 se houver intenção de utilizar threads, uma vez que são cobertos pontos importantes.
•
Quando Statement e PreparedStatement não tiverem mais utilidade, devem ser fechados.
31.3.3. Utilização da interface ResultSet As seguintes informações devem ser consideradas quando for utilizada a interface ResultSet: •
Antes de ler qualquer valor deve-se chamar next(), que retorna verdade se houver um resultado e, mais importante ainda, prepara a linha para ser processada.
•
De acordo com a especificação do JDBC o campo deve ser acessado somente uma vez. É mais seguro seguir esta regra, embora atualmente o driver do PostgreSQL permita acessar o campo quantas vezes se desejar.
•
O ResultSet deve ser fechado chamando close() quando não for mais ser utilizado.
•
Ao ser feita uma nova consulta utilizando um Statement já utilizado para criar um ResultSet, a instância do ResultSet aberta no momento é fechada automaticamente.
426
31.4. Realização de atualizações Para alterar os dados (realizar um INSERT, UPDATE ou DELETE) é utilizado o método executeUpdate(), Este método é semelhante ao método executeQuery() utilizado para executar uma declaração SELECT, porém não retorna um ResultSet; em vez disso, é retornado o número de linhas afetadas pela declaração INSERT, UPDATE ou DELETE. O Exemplo 31-3 mostra esta utilização. Exemplo 31-3. Exclusão de linhas no JDBC Este exemplo executa uma declaração DELETE simples e mostra o número de linhas excluídas. int valor_foo = 500; PreparedStatement st = db.prepareStatement("DELETE FROM minha_tabela " + "WHERE coluna_foo = ?"); st.setInt(1, valor_foo); int linhasExcluidas = st.executeUpdate(); System.out.println(linhasExcluidas + " linhas excluídas"); st.close();
31.5. Chamadas de procedimentos armazenados O driver JDBC do PostgreSQL suporta integralmente as chamadas de procedimentos armazenados do PostgreSQL. Exemplo 31-4. Chamada de procedimento armazenado incorporado Este exemplo mostra como chamar uma função incorporada do PostgreSQL, upper, que simplesmente converte as letras da cadeia de caracteres fornecida como argumento em maiúsculas. // Desabilitar as transações. conn.setAutoCommit(false); // Chamada do procedimento. CallableStatement procMaiusc = conn.prepareCall("{ ? = call upper( ? ) }"); procMaiusc.registerOutParameter(1, Types.VARCHAR); procMaiusc.setString(2, "minusculas em maiusculas"); procMaiusc.execute(); System.out.println(procMaiusc.getString(1)); procMaiusc.close();
31.5.1. Utilização da interface CallableStatement Todas as considerações que se aplicam a Statement e a PreparedStatement também se aplicam a CallableStatement, mas além destas deve ser considerada uma restrição extra: •
Uma função armazenada somente pode ser chamada de dentro de uma transação.
31.5.2. Obtenção de um ResultSet a partir de uma função armazenada A função armazenada do PostgreSQL pode retornar resultados através de um valor do tipo refcursor. Como uma extensão ao JDBC, o driver JDBC do PostgreSQL pode retornar valores refcursor como valores ResultSet. Exemplo 31-5. Obtenção de valores refcursor a partir de uma função Quando se chama uma função que retorna refcursor, o tipo retornado por getObject deve ser transformado em ResultSet
427
// Desabilitar as transações. conn.setAutoCommit(false); // Chamada do procedimento. CallableStatement proc = conn.prepareCall("{ ? = call doquery ( ? ) }"); proc.registerOutParameter(1, Types.Other); proc.setInt(2, -1); proc.execute(); ResultSet results = (ResultSet) proc.getObject(1); while (results.next()) { // fazer alguma coisa com os resultados... } results.close(); proc.close();
Também é possível tratar o valor refcursor retornado como um tipo distinto. O driver JDBC fornece a classe org.postgresql.PGRefCursorResultSet para esta finalidade. Exemplo 31-6. Tratamento do refcursor como um tipo distinto conn.setAutoCommit(false); CallableStatement proc = conn.prepareCall("{ ? = call doquery ( ? ) }"); proc.registerOutParameter(1, Types.Other); proc.setInt(2, 0); org.postgresql.PGRefCursorResultSet refcurs = (PGRefCursorResultSet) conn.getObject(1); String cursorName = refcurs.getRefCursor(); proc.close();
31.6. Criação e modificação de objetos do banco de dados Para criar, modificar ou remover um objeto de banco de dados, como uma tabela ou uma visão, é utilizado o método execute(). Este método é semelhante ao método executeQuery(), mas não retorna um resultado. O Exemplo 31-7 mostra sua utilização. Exemplo 31-7. Remoção de uma tabela no JDBC Este exemplo remove uma tabela. Statement st = db.createStatement(); st.execute("DROP TABLE minha_tabela"); st.close();
31.7. Armazenamento de dados binários O PostgreSQL provê duas formas distintas para armazenar dados binários. Os dados binários podem ser armazenados em uma tabela utilizando o tipo de dado bytea, ou através da funcionalidade de objeto grande que armazena os dados binários em uma tabela a parte em um formato especial, e faz referência a esta tabela armazenando um valor do tipo oid na tabela do usuário. Para ser possível determinar qual é o método apropriado é necessário compreender as limitações de cada método. O tipo de dado bytea não é muito adequado para armazenar quantidades muito grande de dados binários. Embora uma coluna do tipo bytea possa conter até 1 GB de dados binários, é necessária uma grande quantidade de memória para processar um valor tão grande. O método objeto grande para armazenar dados binários é mais adequado para armazenar valores muito grandes, mas possui suas próprias limitações. Especificamente, a exclusão da linha que contém a referência ao objeto grande não exclui o objeto grande. A exclusão do objeto grande é uma operação a parte que precisa ser realizada. Os objetos grandes também possuem alguns problemas de segurança, uma vez que qualquer um que se conecte ao banco de dados pode ver e/ou modificar qualquer objeto grande, mesmo que não possua permissão para ver/atualizar a linha que faz referência ao objeto grande. A primeira versão do driver JDBC com suporte ao tipo de dado bytea foi a 7.2. A introdução desta funcionalidade na versão 7.2 ocasionou uma mudança de comportamento em comparação com as versões
428
anteriores. Desde a versão 7.2, os métodos getBytes(), setBytes(), getBinaryStream() e setBinaryStream() operam no tipo de dado bytea. Na versão 7.1, e nas anteriores, estes métodos operavam no tipo de dado oid associado ao objeto grande. É possível fazer com que o driver volte a ter o comportamento antigo da versão 7.1, definindo a propriedade compatible do objeto Connection com o valor 7.1. Para utilizar o tipo de dado bytea deve-se simplesmente utilizar os métodos getBytes(), setBytes(), getBinaryStream() e setBinaryStream(). Para utilizar a funcionalidade de objeto grande pode ser utilizada a classe LargeObject fornecida pelo driver JDBC do PostgreSQL, ou utilizar os métodos getBLOB() e setBLOB(). Importante: Os Objetos Grandes devem ser acessados dentro de um bloco de transação do SQL. Um bloco de transação pode ser iniciado chamando setAutoCommit(false). Nota: Em uma versão futura do driver JDBC, os métodos getBLOB() e setBLOB() poderão não mais interagir com os Objetos Grandes e, em vez disso, trabalharem com o tipo de dado bytea. Portanto, recomenda-se a utilização da API LargeObject para trabalhar com Objetos Grandes.
O Exemplo 31-8 contém alguns exemplos de como processar dados binários utilizando o driver JDBC do PostgreSQL. Exemplo 31-8. Processamento de dados binários no JDBC Por exemplo, supondo haver uma tabela contendo nomes de arquivos de imagem, e que se deseje armazenar estas imagens em uma coluna bytea: CREATE TABLE tbl_imagem (nome_da_imagem text, imagem bytea);
Para inserir a imagem seria utilizado: File file = new File("minha_imagem.jpg"); InputStream fis = new FileInputStream(file); PreparedStatement ps = conn.prepareStatement( "INSERT INTO tbl_imagem VALUES (?, ?)"); ps.setString(1, file.getName()); ps.setBinaryStream(2, fis, (int)file.length()); ps.executeUpdate(); ps.close(); fis.close();
No exemplo acima, setBinaryStream() transfere um determinado número de bytes do arquivo para a coluna do tipo bytea. Também poderia ter sido feito utilizando o método setBytes(), se o conteúdo da imagem estivesse armazenado como byte[]. Trazer a imagem é mais fácil ainda (Foi utilizado PreparedStatement neste exemplo, mas a classe Statement também poderia ter sido utilizada). PreparedStatement ps = conn.prepareStatement("SELECT imagem " + "FROM tbl_imagem " + "WHERE nome_da_imagem = ?"); ps.setString(1, "minha_imagem.jpg"); ResultSet rs = ps.executeQuery(); if (rs != null) { while (rs.next()) { byte[] imgBytes = rs.getBytes(1); // utilizar os dados de alguma maneira System.out.println("Tamanho da imagem: " + imgBytes.length); } rs.close(); } ps.close();
No exemplo acima os dados binários foram trazidos como byte[]. Em vez disso, poderia ser utilizado um objeto InputStream.
429
Como alternativa, se estiver sendo armazenado um arquivo muito grande pode ser utilizada a API LargeObject para armazenar o arquivo: CREATE TABLE tbl_imagem_lo (nome_da_imagem text, oid_da_imagem oid);
Para inserir a imagem seria utilizado: // Todas as chamadas à API do LargeObject devem // ser feitas dentro de um bloco de transação conn.setAutoCommit(false); // Obter o Gerenciador de Objeto Grande para realizar operações com os mesmos LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI(); // Criar o novo objeto grande int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE); // Abrir o objeto grande para escrita LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE); // Abrir o arquivo File file = new File("minha_imagem.jpg"); FileInputStream fis = new FileInputStream(file); // Copiar os dados do arquivo para o objeto grande byte buf[] = new byte[2048]; int s, tl = 0; while ((s = fis.read(buf, 0, 2048)) > 0) { obj.write(buf, 0, s); tl += s; } // Fechar o objeto grande obj.close(); // Inserir a linha na tabela tbl_imagem_lo PreparedStatement ps = conn.prepareStatement("INSERT INTO tbl_imagem_lo " + "VALUES (?, ?)"); ps.setString(1, file.getName()); ps.setInt(2, oid); ps.executeUpdate(); ps.close(); fis.close(); conn.commit();
Trazer a imagem armazenada no objeto grande: // Todas as chamadas à API LargeObject devem // ser feitas dentro de um bloco de transação conn.setAutoCommit(false); // Obter o Gerenciador de Objeto Grande para realizar operações com os mesmos LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI(); PreparedStatement ps = conn.prepareStatement("SELECT oid_da_imagem " + "FROM tbl_imagem_lo " + "WHERE nome_da_imagem = ?"); ps.setString(1, "minha_imagem.jpg"); ResultSet rs = ps.executeQuery(); if (rs != null) { while (rs.next()) { // Abrir o objeto grande para leitura
430
int oid = rs.getInt(1); LargeObject obj = lobj.open(oid, LargeObjectManager.READ); // Ler os dados byte buf[] = new byte[obj.size()]; obj.read(buf, 0, obj.size()); // utilizar os dados de alguma maneira System.out.println("Tamanho da imagem: " + buf.length); // Fechar o objeto obj.close(); } rs.close(); } ps.close(); conn.rollback();
31.8. Extensões do PostgreSQL à API JDBC O PostgreSQL é um sistema de banco de dados extensível. Os usuários podem adicionar ao servidor funções que podem ser chamadas nas consultas, e até mesmo adicionar tipos de dado. Como estas facilidades existem apenas no PostgreSQL, as mesmas são suportadas no Java através de um conjunto de APIs de extensão. Algumas funcionalidades dentro do núcleo do driver padrão usam estas extensões para implementar Objetos Grandes, etc.
31.8.1. Acesso às extensões Para
acessar
algumas
das
extensões
é
necessário
utilizar
alguns
métodos
extras
da
classe
org.postgresql.PGConnection. Neste caso, será necessário transformar o valor retornado por Driver.getConnection(). Por exemplo: Connection db = Driver.getConnection(url, nome_do_usuário, senha); // ... // depois Fastpath fp = ((org.postgresql.PGConnection)db).getFastpathAPI();
31.8.1.1. Classe org.postgresql.PGConnection public class PGConnection
Abaixo estão os métodos extra utilizados para obter acesso às extensões do PostgreSQL. 31.8.1.1.1. Métodos • public Fastpath getFastpathAPI() throws SQLException
Retorna a API de caminho rápido (fast-path) para a conexão corrente. É utilizada principalmente pela API LargeObject. A melhor forma de utilizar é a mostrada a seguir: import org.postgresql.fastpath.*; ... Fastpath fp = ((org.postgresql.PGConnection)conn).getFastpathAPI();
onde conn é uma Connection com o PostgreSQL aberta. Retorna: O objeto Fastpath que permite acessar funções no servidor PostgreSQL. Lança: SQLException por Fastpath ao inicializar pela primeira vez •
public LargeObjectManager getLargeObjectAPI() throws SQLException
431
Retorna a API LargeObject para a conexão corrente. A melhor forma de utilizar é a mostrada a seguir: import org.postgresql.largeobject.*; ... LargeObjectManager lo ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
=
onde conn é uma Connection com o PostgreSQL aberta. Retorna: O objeto LargeObject que implementa a API Lança: SQLException por LargeObject ao inicializar pela primeira vez •
public void addDataType(String tipo, String nome)
Permite o código cliente adicionar tratador para um dos tipos de dado únicos do PostgreSQL. Normalmente, um tipo de dado desconhecido pelo driver é retornado por ResultSet.getObject() como uma instância de PGobject. Este método permite escrever uma classe que estende PGobject, e informar ao driver o nome do tipo e o nome da classe a ser utilizada. O problema é que este método deve ser chamado toda vez que for feita uma conexão. A melhor forma de utilizar é a mostrada a seguir: ... ((org.postgresql.PGConnection)conn).addDataType("meu_tipo","minha.classe.nome"); ...
onde conn é uma Connection aberta com o PostgreSQL. A classe tratadora deve estender org.postgresql.util.PGobject. 31.8.1.2. Classe org.postgresql.Fastpath public class Fastpath extends Object java.lang.Object | +----org.postgresql.fastpath.Fastpath Fastpath é uma API que existe dentro da interface C da libpq, que permite a máquina cliente executar
funções no servidor de banco de dados. A maior parte dos códigos cliente não precisa utilizar este método, mas é fornecido porque é utilizado pela API LargeObject. Para usá-lo é necessário importar o pacote org.postgresql.fastpath, utilizando a linha: import org.postgresql.fastpath.*;
Depois, no código, é necessário obter um objeto FastPath: Fastpath fp = ((org.postgresql.PGConnection)conn).getFastpathAPI();
A linha acima retorna uma instância associada à conexão com o banco de dados, que pode ser utilizada para executar comandos. A conversão de Connection em org.postgresql.PGConnection é necessária, porque getFastpathAPI() é um método de extensão, e não parte do JDBC. Uma vez obtida uma instância de Fastpath, podem ser utilizados os métodos fastpath() para executar uma função do servidor. Veja também: FastpathFastpathArg, LargeObject 31.8.1.2.1. Métodos • public Object fastpath(int fnid,
boolean resulttype, FastpathArg args[]) throws SQLException
Envia uma chamada de função para o servidor PostgreSQL.
432
Parâmetros: fnid - Identificador da função; resulttype - Verdade se o resultado for um inteiro, falso para os outros resultados; args - FastpathArguments a serem passados para a chamada de fast-path. Retorna: nulo se não houver dado, Integer para um resultado inteiro, ou byte[] nos demais casos. • public Object fastpath(String nome,
boolean resulttype, FastpathArg args[]) throws SQLException
Envia uma chamada para o servidor PostgreSQL por nome. Nota: O mapeamento entre nome de procedimento e identificador de função precisa existir, geralmente é feito através de uma chamada prévia a addfunction(). Este é o método preferido para chamar, porque os identificadores de função podem mudar entre versões do servidor. Para ver um exemplo mostrando como funciona, consulte org.postgresql.LargeObject
Parâmetros: nome - Nome da função; resulttype - Verdade se o resultado for um inteiro, falso para os outros resultados; args - FastpathArguments a serem passados para a chamada de fast-path. Retorna: nulo se não houver dado, Integer para um resultado inteiro, ou byte[] nos demais casos. Veja também: LargeObject • public int getInteger(String nome,
FastpathArg args[]) throws SQLException
Este método assume que o valor retornado é um Integer Parâmetros: nome - Nome da função args - Argumentos da função Retorna: resultado inteiro Lança: SQLException se ocorrer um erro de acesso ao banco de dados ou não houver resultado • public byte[] getData(String nome,
FastpathArg args[]) throws SQLException
Este método assume que o valor retornado é binário Parâmetros: nome - Nome da função args - Argumentos da função Retorna: matriz byte[] contendo o resultado Lança: SQLException se ocorrer um erro de acesso ao banco de dados ou não houver resultado • public void addFunction(String nome,
int fnid)
Adiciona uma função à tabela de procura. Pode ser utilizado o método addFunctions, que tem por base uma consulta, em vez de especificar diretamente o OID. Não há garantia que o OID da função permaneça estático, mesmo entre servidores diferentes com a mesma versão. • public void addFunctions(ResultSet rs) throws SQLException
Recebe um ResultSet contendo duas colunas. A coluna 1 contém o nome da função e a coluna 2 o OID. Todo o ResultSet é lido e os valores são carregados na tabela de função. Importante: Lembre-se de fechar (close()) o ResultSet após a chamada! Notas de implementação sobre a procura de nome de função: O PostgreSQL armazena os identificadores das funções e seus nomes correspondentes na tabela pg_proc. Para acelerar o processamento local, em vez de consultar cada função na tabela toda vez que for necessário, é utilizada uma Hashtable. Também, somente as funções necessárias são colocadas nesta tabela, tornando o tempo de conexão o mais rápido possível. A classe org.postgresql.LargeObject realiza a consulta ao ser inicializada, e passa o ResultSet retornado para o método addFunctions(). Após o término, a API LargeObject faz referência às funções por nome. Não se deve supor que vai funcionar se forem convertidos manualmente nos OIDs. Está certo, por ora funcionam, mas podem mudar durante o desenvolvimento (existia alguma explicação sobre este
433
assunto para a versão V7.0) e, portanto, isto é implementado para prevenir contra dores de cabeça futuras.
Veja também: LargeObjectManager • public int getID(String nome) throws SQLException
Retorna o identificador de função associado a partir do nome. Se addFunction() ou addFunctions() ainda não tiver sido chamada para este nome, então é lançada uma exceção SQLException. 31.8.1.3. Classe org.postgresql.fastpath.FastpathArg public class FastpathArg extends Object java.lang.Object | +----org.postgresql.fastpath.FastpathArg
Cada chamada de fast-path requer uma matriz de argumentos, o número e o tipo dependendo da função sendo chamada. Esta classe implementa os métodos necessários para fornecer esta capacidade. Para ver um exemplo de sua utilização consulte o pacote org.postgresql.LargeObject. Veja também: Fastpath, LargeObjectManager, LargeObject 31.8.1.3.1. Construtores • public FastpathArg(int valor)
Constrói um argumento que consiste em um valor inteiro Parâmetros: valor - valor inteiro a ser definido • public FastpathArg(byte bytes[])
Constrói um argumento que consiste em uma matriz de bytes Parâmetros: bytes - matriz para armazenar • public FastpathArg(byte buf[],
int off, int len)
Constrói um argumento que consiste em uma parte de uma matriz de bytes Parâmetros: buf matriz fonte off deslocamento dentro da matriz len comprimento dos dados a serem incluídos
• public FastpathArg(String s)
Constrói um argumento que consiste em uma cadeia de caracteres.
31.8.2. Tipos de dado geométricos O PostgreSQL possui um conjunto de tipos de dado que podem armazenar características geométricas em uma tabela. Fazem parte pontos, linhas e polígonos. Estes tipos são suportados no Java através do pacote org.postgresql.geometric, que contém classes que estendem a classe org.postgresql.util.PGobject. Consulte esta classe para obter detalhes sobre como implementar seus próprios tratadores de tipo de dado.
434
Class org.postgresql.geometric.PGbox java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGbox public class PGbox extends PGobject implements Serializable, Cloneable Representa o tipo de dado caixa no PostgreSQL. Variáveis public PGpoint point[] Dois pontos do canto da caixa. Construtores public PGbox(double double double double Parâmetros: x1 y1 x2 y2 -
x1, y1, x2, y2)
primeira coordenada x primeira coordenada y segunda coordenada x segunda coordenada y
public PGbox(PGpoint p1, PGpoint p2) Parâmetros: p1 - primeiro ponto p2 - segundo ponto public PGbox(String s) throws SQLException Parâmetros: s - definição da caixa na sintaxe do PostgreSQL Lança: SQLException se a definição não for válida public PGbox() Construtor requerido Métodos public void setValue(String valor) throws SQLException Este método define o valor deste objeto. Deve ser sobreposta, mas ainda chamada por subclasses. Parâmetros: valor - a representação do valor do objeto em uma cadeia de caracteres
435
Lança: SQLException lançado se o valor for inválido para este tipo Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado Retorna: verdade se as duas caixas forem idênticas Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna: PGbox na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject Class org.postgresql.geometric.PGcircle java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGcircle public class PGcircle extends PGobject implements Serializable, Cloneable Representa o tipo de dado círculo do PostgreSQL, que consiste em um ponto e o raio Variáveis public PGpoint center O ponto do centro double radius O raio Construtores public PGcircle(double x, double y, double r)
436
Parâmetros: x - coordenada do centro y - coordenada do centro r - raio do círculo public PGcircle(PGpoint c, double r) Parâmetros: c - PGpoint descrevendo o centro do círculo r - raio do círculo public PGcircle(String s) throws SQLException Parâmetros: s - definição do círculo na sintaxe do PostgreSQL. Lança: SQLException na falha de conversão public PGcircle() Este construtor é utilizado pelo driver. Métodos public void setValue(String s) throws SQLException Parâmetros: s - definição do círculo na sintaxe do PostgreSQL. Lança: SQLException na falha de conversão Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado Retorna: verdade se os dois círculos forem idênticos Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna: PGcircle na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject
437
Class org.postgresql.geometric.PGline java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGline public class PGline extends PGobject implements Serializable, Cloneable Implementa uma linha consistindo em dois pontos. Atualmente linha ainda não está implementada no servidor, mas esta classe garante que quando for feito estaremos pronto para isso. Variáveis public PGpoint point[] São os dois pontos. Construtores public PGline(double double double double Parâmetros: x1 y1 x2 y2 -
x1, y1, x2, y2)
coordenada coordenada coordenada coordenada
do do do do
primeiro ponto primeiro ponto segundo ponto segundo ponto
public PGline(PGpoint p1, PGpoint p2) Parâmetros: p1 - primeiro ponto p2 - segundo ponto public PGline(String s) throws SQLException Parâmetros: s - definição da linha na sintaxe do PostgreSQL. Lança: SQLException na falha de conversão public PGline() requerido pelo driver Métodos public void setValue(String s) throws SQLException Parâmetros: s - Definição do segmento de linha na sintaxe do PostgreSQL
438
Lança: SQLException na falha de conversão Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado Retorna: verdade se as duas linhas fore idênticas Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna: PGline na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject Class org.postgresql.geometric.PGlseg java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGlseg public class PGlseg extends PGobject implements Serializable, Cloneable Implementa lseg (segmento de linha) consistindo em dois pontos Variáveis public PGpoint point[] Os dois pontos. Construtores public PGlseg(double double double double
x1, y1, x2, y2)
Parâmetros: x1 - coordenada do primeiro ponto y1 - coordenada do primeiro ponto
439
x2 - coordenada do segundo ponto y2 - coordenada do segundo ponto public PGlseg(PGpoint p1, PGpoint p2) Parâmetros: p1 - primeiro ponto p2 - segundo ponto public PGlseg(String s) throws SQLException Parâmetros: s - Definição do segmento de linha na sintaxe do PostgreSQL. Lança: SQLException na falha de conversão public PGlseg() requerido pelo driver Métodos public void setValue(String s) throws SQLException Parâmetros: s - Definição do segmento de linha na sintaxe do PostgreSQL Lança: SQLException na falha de conversão Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado Retorna: verdade se os dois segmentos de linha forem idênticos Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna: PGlseg na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject
440
Class org.postgresql.geometric.PGpath java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGpath public class PGpath extends PGobject implements Serializable, Cloneable Implementa o caminho (uma linha com vários segmentos, que pode ser fechada) Variáveis public boolean open Verdade se o caminho for aberto, falso se for fechado public PGpoint points[] Os pontos que definem o caminho Construtores public PGpath(PGpoint points[], boolean open) Parâmetros: points - os PGpoints que definem o caminho open - Verdade se o caminho for aberto, falso se for fechado public PGpath() Requerido pelo driver public PGpath(String s) throws SQLException Parâmetros: s - definição do caminho na sintaxe do PostgreSQL. Lança: SQLException na falha de conversão Métodos public void setValue(String s) throws SQLException Parâmetros: s - definição do caminho na sintaxe do PostgreSQL Lança: SQLException na falha de conversão Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado
441
Retorna: verdade se os dois caminhos forem idênticos Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna o caminho na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject public boolean isOpen() Retorna verdade se o caminho for aberto public boolean isClosed() Retorna verdade se o caminho for fechado public void closePath() Marca o caminho como fechado public void openPath() Marca o caminho como aberto Class org.postgresql.geometric.PGpoint java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGpoint public class PGpoint extends PGobject implements Serializable, Cloneable Implementa a versão de java.awt.Point, exceto por utilizar precisão dupla para representar as coordenadas. Mapeia para o tipo de dado ponto do PostgreSQL. Variáveis public double x coordenada X do ponto public double y coordenada Y do ponto
442
Construtores public PGpoint(double x, double y) Parâmetros: x - coordenada y - coordenada public PGpoint(String valor) throws SQLException Chamado principalmente pelos outros tipos geométricos, quando o ponto está incorporado na sua definição. Parâmetros: valor - Definição do ponto na sintaxe do PostgreSQL public PGpoint() Requerido pelo driver Métodos public void setValue(String s) throws SQLException Parâmetros: s - Definição do ponto na sintaxe do PostgreSQL Lança: SQLException na falha de conversão Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado Retorna: verdade se os dois pontos forem idênticos Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna: PGpoint na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject
443
public void translate(int x, int y) Translação do ponto na quantidade especificada Parâmetros: x - quantidade inteira a ser adicionada ao eixo x y - quantidade inteira a ser adicionada ao eixo y public void translate(double x, double y) Translação do ponto na quantidade especificada Parâmetros: x - quantidade em precisão dupla a ser adicionada ao eixo x y - quantidade em precisão dupla a ser adicionada ao eixo y public void move(int x, int y) Move o ponto para as coordenadas fornecidas. Parâmetros: x - coordenada inteira y - coordenada inteira public void move(double x, double y) Move o ponto para as coordenadas fornecidas. Parâmetros: x - coordenada em precisão dupla y - coordenada em precisão dupla public void setLocation(int x, int y) Move o ponto para as coordenadas fornecidas. Consulte java.awt.Point para obter a descrição Parâmetros: x - coordenada inteira y - coordenada inteira Veja também: Point public void setLocation(Point p) Move o ponto para as coordenadas java.awt.Point fornecidas. Consulte java.awt.Point para obter a descrição Parâmetros: p - Ponto para mover para Veja também: Point
444
Class org.postgresql.geometric.PGpolygon java.lang.Object | +----org.postgresql.util.PGobject | +----org.postgresql.geometric.PGpolygon public class PGpolygon extends PGobject implements Serializable, Cloneable Implementa o tipo de dado polígono no PostgreSQL. Variáveis public PGpoint points[] Os pontos que definem o polígono Construtores public PGpolygon(PGpoint points[]) Cria um polígono utilizando uma matriz de PGpoints Parâmetros: points - os pontos que definem o polígono public PGpolygon(String s) throws SQLException Parâmetros: s - definição do polígono na sintaxe do PostgreSQL. Lança: SQLException na falha de conversão public PGpolygon() Requerido pelo driver Métodos public void setValue(String s) throws SQLException Parâmetros: s - definição do polígono na sintaxe do PostgreSQL Lança: SQLException na falha de conversão Sobrepõe: setValue na classe PGobject public boolean equals(Object obj) Parâmetros: obj - Objeto a ser comparado Retorna: verdade se os dois polígonos forem idênticos
445
Sobrepõe: equals na classe PGobject public Object clone() Deve ser sobreposta para permitir a clonagem do objeto Sobrepõe: clone na classe PGobject public String getValue() Retorna: PGpolygon na sintaxe esperada pelo PostgreSQL Sobrepõe: getValue na classe PGobject
31.8.3. Objetos Grandes Os Objetos Grandes são suportados na especificação padrão do JDBC. Entretanto, a interface é limitada e a API fornecida pelo PostgreSQL permite o acesso aleatório ao conteúdo do objeto, como se fosse um arquivo local. O pacote org.postgresql.largeobject fornece ao Java a interface C da API de objeto grande da libpq. Consiste em duas classes, LargeObjectManager, que trata da criação, abertura e exclusão de objetos grandes, e LargeObject que trata individualmente os objetos. 31.8.3.1. Class org.postgresql.largeobject.LargeObject public class LargeObject extends Object java.lang.Object | +----org.postgresql.largeobject.LargeObject
Esta classe implementa a interface de objeto grande do PostgreSQL. Fornece os métodos básicos requeridos para executar a interface, mais um par de métodos que fornecem as classes InputStream e OutputStream para o objeto. Normalmente, o código cliente utiliza os métodos de BLOB para acessar os objetos grandes. Entretanto, algumas vezes é necessário acesso de baixo nível aos Objetos Grandes que não são suportados pela especificação do JDBC. Consulte org.postgresql.largeobject.LargeObjectManager para ver como obter acesso aos Objetos Grandes, ou como criar um. Veja também: LargeObjectManager 31.8.3.1.1. Variáveis public static final int SEEK_SET Indica uma procura a partir do início do arquivo public static final int SEEK_CUR Indica uma procura a partir da posição corrente public static final int SEEK_END Indica uma procura a partir do fim do arquivo 31.8.3.1.2. Métodos • public int getOID()
446
Retorna o OID deste LargeObject • public void close() throws SQLException
Este método fecha o objeto. Não devem ser chamados métodos do objeto após este método ter sido chamado. • public byte[] read(int len) throws SQLException
Lê alguns dados do objeto, retornando uma matriz de byte[] • public int read(byte buf[],
int off, int len) throws SQLException
Lê alguns dados do objeto para dentro de uma matriz existente Parâmetros: buf matriz de destino off deslocamento dentro da matriz len número de bytes a serem lidos • public void write(byte buf[]) throws SQLException
Escreve uma matriz em um objeto • public void write(byte buf[],
int off, int len) throws SQLException
Escreve alguns dados da matriz no objeto Parâmetros: buf matriz de destino off deslocamento dentro da matriz len número de bytes a serem escritos 31.8.3.2. Classe org.postgresql.largeobject.LargeObjectManager
public class LargeObjectManager extends Object java.lang.Object | +----org.postgresql.largeobject.LargeObjectManager
Esta classe implementa a interface de objeto grande do PostgreSQL. Fornece métodos que permitem o código cliente criar, abrir e excluir objetos grandes no banco de dados. Ao se abrir um objeto, é retornada uma instância de org.postgresql.largeobject.LargeObject e, então, seus métodos permitem acessar o objeto. Esta classe somente pode ser criada por org.postgresql.PGConnection. Para obter acesso a esta classe, deve ser utilizado o seguinte segmento de código:
447
import org.postgresql.largeobject.*; Connection conn; LargeObjectManager lobj; // ... código que abre a conexão... lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
Normalmente, o código cliente utiliza os métodos de BLOB para acessar os objetos grandes. Entretanto, algumas vezes é necessário acesso de baixo nível aos Objetos Grandes que não são suportados pela especificação do JDBC. Consulte org.postgresql.largeobject.LargeObjectManager para ver como manipular o conteúdo dos Objetos Grandes. 31.8.3.2.1. Variáveis public static final int WRITE
Este modo indica que se deseja escrever no objeto. public static final int READ
Este modo indica que se deseja ler o objeto. public static final int READWRITE
Este modo é o padrão. Indica que se deseja acesso de leitura e escrita no objeto grande. 31.8.3.2.2. Métodos • public LargeObject open(int oid) throws SQLException
Abre um objeto grande existente com base em seu OID. Este método assume que está sendo requerido acesso de READ e de WRITE (o padrão). • public LargeObject open(int oid,
int mode) throws SQLException
Abre um objeto grande existente com base em seu OID. Permite definir o método de acesso. • public int create() throws SQLException
Cria um objeto grande e retorna o seu OID. O padrão é READWRITE para atributos do novo objeto. • public int create(int mode) throws SQLException
Cria um objeto grande e retorna o seu OID. Define o modo de acesso. • public void delete(int oid) throws SQLException
Remove um objeto grande. • public void unlink(int oid) throws SQLException
Remove um objeto grande. É idêntico ao método acima. É fornecido porque a API C utiliza “unlink”.
31.9. Utilização do driver em um ambiente Multithread ou Servlet O problema com os drivers JDBC é que uma conexão somente pode ser utilizada por uma thread de cada vez, senão uma thread poderia enviar uma consulta enquanto outra estivesse recebendo os resultados, o que causaria uma grande confusão. O driver JDBC do PostgreSQL é seguro para threads. Conseqüentemente, não há necessidade do usuário se preocupar com algoritmos complexos para garantir que somente uma thread vai utilizar o banco de dados de cada vez, quando a aplicação utiliza várias threads. Se uma thread tentar utilizar a conexão enquanto outra está utilizando, vai aguardar até que a outra thread termine a operação corrente. Se a operação for uma declaração SQL comum, a operação consiste em enviar a declaração e receber algum ResultSet (completo). Se for uma chamada fast-path (por exemplo, leitura de um bloco de um objeto grande) então consiste em enviar e receber o respectivo dado.
448
Esta forma é boa para aplicações e applets, mas pode causar problemas de desempenho com servlets. Havendo várias threads realizando consultas então todas elas, com exceção de uma, vão ficar aguardando. Para resolver este problema aconselha-se a criação de um pool de conexões. Sempre que uma thread precisa utilizar o banco de dados solicita a classe gerenciadora um objeto Connection. A classe gerenciadora entrega uma conexão livre para a thread e a marca como ocupada. Se não existir uma conexão livre disponível, então uma é aberta. Quando a thread terminar de utilizar a conexão vai devolvê-la para a classe gerenciadora, que vai fechá-la ou adicioná-la ao pool. A classe gerenciadora também pode verificar se a conexão ainda está viva, e removê-la do pool se estiver morta. O problema do pool de conexão é que aumenta a carga no servidor, porque uma nova sessão é criada para cada objeto Connection, por isso seu uso fica a critério do desenvolvedor ou dos requisitos da aplicação.
31.10. Pools de conexão e fontes de dado O JDBC 2 introduziu funcionalidades de pooling de conexão padrão em uma API complementar conhecida por “JDBC 2.0 Optional Package” (também conhecida como “JDBC 2.0 Standard Extension”). Estas funcionalidades foram incorporadas ao núcleo a partir da API JDBC 3 . O driver JDBC do PostgreSQL suporta estas funcionalidades caso tenha sido compilado pelo JDK 1.3.x em combinação com o “JDBC 2.0 Optional Package” (JDBC 2), ou pelo JDK 1.4 ou posterior (JDBC 3). A maior parte dos servidores de aplicação incluem o “JDBC 2.0 Optional Package”, mas também está disponível em separado na página JDBC downloads and specification (http://java.sun.com/products/jdbc/download.html#spec) da Sun.
31.10.1. Visão geral A API JDBC fornece uma interface cliente e uma interface servidor para pooling de conexão. A interface cliente é a javax.sql.DataSource, utilizada habitualmente pelo código da aplicação para obter no pool uma conexão de banco de dados. A interface servidor é a javax.sql.ConnectionPoolDataSource, utilizada pela maioria dos servidores de aplicação para fazer a interface com o driver JDBC do PostgreSQL. Em um ambiente de servidor de aplicação, a configuração do servidor de aplicação normalmente faz referência à implementação do ConnectionPoolDataSource do PostgreSQL, enquanto o código componente da aplicação normalmente obtém uma implementação do DataSource fornecida pelo servidor de aplicação (e não pelo PostgreSQL). Em um ambiente sem servidor de aplicação, o PostgreSQL disponibiliza duas implementações de DataSource que a aplicação pode utilizar diretamente. Uma implementação realiza o pooling de conexão,
enquanto a outra simplesmente fornece acesso às conexões de banco de dados através da interface DataSource sem qualquer pooling. Repetindo, estas implementações não devem ser utilizadas em um ambiente de servidor de aplicação, a menos que o servidor de aplicação não dê suporte à interface ConnectionPoolDataSource.
31.10.2. Servidores de aplicação: ConnectionPoolDataSource O PostgreSQL inclui uma implementação de ConnectionPoolDataSource para o JDBC 2 e outra para o JDBC 3, conforme mostrado na Tabela 31-1. Tabela 31-1. Implementações de ConnectionPoolDataSource JDBC
Classe de implementação
2
org.postgresql.jdbc2.optional.ConnectionPool
3
org.postgresql.jdbc3.Jdbc3ConnectionPool
As duas implementações utilizam o mesmo esquema de configuração. O JDBC requer que o ConnectionPoolDataSource seja configurado através das propriedades JavaBean, mostradas na Tabela 312, portanto existem métodos get e set para cada uma destas propriedades.
449
Tabela 31-2. Propriedades de configuração do ConnectionPoolDataSource Propriedade
Tipo
Descrição
serverName
String
nome do hospedeiro do servidor de banco de dados PostgreSQL
databaseName
String
nome do banco de dados do PostgreSQL
portNumber
int
porta TCP onde o servidor de banco de dados PostgreSQL está ouvindo (ou 0 para utilizar a porta padrão)
user
String
usuário utilizado para fazer as conexões com o banco de dados
password
String
senha utilizada para fazer as conexões com o banco de dados
defaultAutoCommit
boolean
indica se as conexões devem possuir a efetivação automática habilitada ou desabilitada quando forem fornecidas por quem chama. O padrão é false, que desabilita a efetivação automática.
Diversos servidores de aplicação utilizam uma sintaxe no estilo de propriedades para configurar estas propriedades, portanto não é incomum fornecer as propriedades como um bloco de texto. Se o servidor de aplicação fornecer uma única área para especificar todas as propriedades, esta área deve ficar parecida com: serverName=localhost databaseName=teste user=teste_usuário password=teste_senha
Ou, se for utilizado ponto-e-vírgula como separador em vez de nova-linha, deve ficar parecida com: serverName=localhost;databaseName=teste;user=teste_usuário;password=teste_senha
31.10.3. Aplicações: DataSource O PostgreSQL inclui duas implementações de DataSource para o JDBC 2 e duas para o JDBC 3, conforme mostrado na Tabela 31-3. As implementações de pooling na verdade não fecham a conexão quando o cliente chama o método close, em vez disso retornam a conexão para o pool de conexões disponíveis para poder ser utilizada por outros clientes. Este procedimento evita a sobrecarga de abrir e fechar conexões repetidamente, e permite um grande número de clientes compartilharem um pequeno número de conexões com o banco de dados. A implementação de pooling de fonte de dados aqui fornecida não é a mais rica do mundo em funcionalidades. Entre outras coisa, as conexões nunca são fechadas até que o próprio pool seja fechado; não há maneira de encolher o pool. Também, as conexões solicitadas para um usuário que não seja o usuário padrão configurado não fazem parte do pool. Muitos servidores de aplicação fornecem funcionalidades de pooling mais avançadas e, em vez desta, utilizam a implementação de ConnectionPoolDataSource. Tabela 31-3. Implementações de DataSource JDBC
Pooling
Classe de implementação
2
Não
org.postgresql.jdbc2.optional.SimpleDataSource
2
Sim
org.postgresql.jdbc2.optional.PoolingDataSource
3
Não
org.postgresql.jdbc3.Jdbc3SimpleDataSource
3
Sim
org.postgresql.jdbc3.Jdbc3PoolingDataSource
Todas as implementações utilizam o mesmo esquema de configuração. O JDBC requer que o DataSource seja configurado através das propriedades de JavaBean, conforme mostrado na Tabela 31-4, portanto existem métodos get e set para cada uma destas propriedades.
450
Tabela 31-4. Propriedades de configuração do DataSource Propriedade
Tipo
Descrição
serverName
String
nome do hospedeiro do servidor de banco de dados PostgreSQL
databaseName
String
nome do banco de dados do PostgreSQL
portNumber
int
porta TCP onde o servidor de banco de dados PostgreSQL está ouvindo (ou 0 para utilizar a porta padrão)
user
String
usuário utilizado para fazer as conexões com o banco de dados
password
String
senha utilizada para fazer as conexões com o banco de dados
As implementações de pooling requerem algumas propriedades de configuração adicionais, conforme mostrado na Tabela 31-5. Tabela 31-5. Propriedades adicionais de configuração de pooling de DataSource Propriedade
Tipo
Descrição
dataSourceName
String
Todo pooling de DataSource deve possuir um nome único.
initialConnections
int
O número de conexões de banco de dados a serem criadas quando o pool é inicializado.
maxConnections
int
O número máximo permitido de conexões de banco de dados abertas. Quando são solicitadas mais conexões, quem chama aguarda até que uma conexão retorne para o pool.
O Exemplo 31-9 mostra um código de aplicação que utiliza um pooling de DataSource. Exemplo 31-9. Exemplo de código de DataSource O código para inicializar o pooling de DataSource deve se parecer com: Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource(); source.setDataSourceName("Uma fonte de dados"); source.setServerName("localhost"); source.setDatabaseName("teste"); source.setUser("teste_usuario"); source.setPassword("teste_senha"); source.setMaxConnections(10);
O código para utilizar uma conexão do pool deve ficar parecido com o mostrado abaixo. Observe que é crítico fechar as conexões, senão as conexões do pool serão “esvaziadas” e, possivelmente, todos os clientes serão bloqueados. Connection conn = null; try { conn = source.getConnection(); // utilizar a conexão } catch (SQLException e) { // registrar o erro } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) {} } }
451
31.10.4. Fontes de dados e JNDI Todas as implementações de ConnectionPoolDataSource e DataSource podem ser armazenadas no JNDI. No caso das implementações sem pooling, uma nova instância é criada toda vez que o objeto é trazido do JNDI, com as mesmas definições da instância que foi armazenada. Para as implementações com pooling, a mesma instância é trazida se estiver disponível (por exemplo, não for uma JVM diferente trazendo o pool do JNDI), senão é criada uma nova instância com as mesmas definições. Em um ambiente de servidor de aplicação, normalmente a instância DataSource do servidor de aplicação é armazenada no JNDI, e não na na implementação do ConnectionPoolDataSource do PostgreSQL. Em um ambiente de servidor de aplicação, a aplicação pode armazenar o DataSource no JNDI para não ter que fazer uma referência ao DataSource disponível para todos os componentes da aplicação que possam precisar utilizá-lo. Um exemplo é mostrado no Exemplo 31-10. Exemplo 31-10. Exemplo de código de DataSource JNDI O código da aplicação para inicializar o pooling do DataSource e adicioná-lo ao JNDI deve ficar parecido com: Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource(); source.setDataSourceName("Uma fonte de dados"); source.setServerName("localhost"); source.setDatabaseName("teste"); source.setUser("teste_usuario"); source.setPassword("teste_senha"); source.setMaxConnections(10); new InitialContext().rebind("DataSource", source);
O código para utilizar uma conexão do pool deve ficar parecido com: Connection conn = null; try { DataSource source = (DataSource)new InitialContext().lookup("DataSource"); conn = source.getConnection(); // utilizar a conexão } catch (SQLException e) { // registrar o erro } catch (NamingException e) { // DataSource não foi encontrada no JNDI } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) {} } }
31.11. Exemplo de utilização básica do JDBC Nota: Seção escrita pelo tradutor, não fazendo parte do manual original.
Este exemplo serve para testar os componentes básicos do driver JDBC, e mostrar a implementação de comandos simples. É fornecido junto com a distribuição do código fonte do PostgreSQL, no arquivo src/interfaces/jdbc/example/basic.java. Além da tradução, foram introduzidas pequenas alterações com relação ao código original. No Fedora Core 2 foi utilizado “export CLASSPATH=/usr/share/java/pg74.1jdbc3.jar:.” para executar o programa a partir da linha de comando, e “/usr/share/java/pg74.1jdbc3.jar” na configuração de Bibliotecas do Usuário do BlueJ (http://www.bluej.org) para o programa ser executado nesta IDE.
452
import java.io.*; import java.sql.*; /* * * $Id: Basico.java,v 1.1.1.1 2005/02/04 08:08:27 halleypo Exp $ * * Este exemplo testa os componentes básicos do driver JDBC, * e mostra a implementação de comandos simples. * * Para utilizar este exemplo é necessário um banco de dados * existente, onde é criada uma tabela chamada tbl_basica. * * Nota: Somente funciona nos drivers pós-7.0. * */ public class Basico { Connection db; // Conexão com o servidor de banco de dados Statement st; // Declaração para executar os comandos public void go() throws ClassNotFoundException, FileNotFoundException, IOException, SQLException { // Banco de dados, usuário e senha igual a "teste" // CREATE USER teste WITH password 'teste'; // CREATE DATABASE teste WITH OWNER teste ENCODING 'LATIN1'; String url = "jdbc:postgresql://localhost/teste?charSet=LATIN1"; String usr = "teste"; String pwd = "teste"; // Carregar o driver Class.forName("org.postgresql.Driver"); // Conectar com o servidor de banco de dados System.out.println("Conectando ao banco de dados\nURL = " + url); db = DriverManager.getConnection(url, usr, pwd); System.out.println("Conectado...Criando a declaração"); st = db.createStatement(); // Limpar o banco de dados (no caso de uma falha anterior) // e inicializar cleanup(); // Executar os testes utilizando os métodos do JDBC doexample(); // Limpar o banco de dados cleanup(); // Fechar a conexão System.out.println("Fechando a conexão"); st.close(); db.close(); //throw postgresql.Driver.notImplemented(); }
453
/* * Remover a tabela (caso exista). Nenhum erro é mostrado. */ public void cleanup() { try { st.executeUpdate("drop table tbl_basica"); } catch (Exception ex) { // Ignorar todos os erros } } /* * Criar a tabela e manipular os dados */ public void doexample() throws SQLException { System.out.println("\nExecutando os testes:"); // Criar a tabela que armazena os dados st.executeUpdate("create table tbl_basica (a int2, b int2)"); // Inserir alguns dados utilizando Statement st.executeUpdate("insert into tbl_basica values (1,1)"); st.executeUpdate("insert into tbl_basica values (2,1)"); st.executeUpdate("insert into tbl_basica values (3,1)"); // Mostrar como obter o OID da linha recém inserida st.executeUpdate("insert into tbl_basica values (4,1)"); long insertedOID = ((org.postgresql.PGStatement)st).getLastOID(); System.out.println("Linha inserida com o OID " + insertedOID); // Mudar o valor da coluna b de 1 para 8 st.executeUpdate("update tbl_basica set b=8"); System.out.println("Atualizadas " + st.getUpdateCount() + " linhas"); // Excluir linhas st.executeUpdate("delete from tbl_basica where a<3"); System.out.println("Excluídas " + st.getUpdateCount() + " linhas"); // Havendo muitas inserções o PreparedStatement é mais eficiente, por // causa da pré-compilação da declaração SQL e do armazenamento direto // do objeto Java na coluna. O PostgreSQL não faz pré-compilação, mas // permite armazenar em uma coluna o valor do objeto Java (como Date, // String, etc). // // Também, esta é a única maneira de escrever a data de uma maneira // independente do estilo da data (DateStyle), usado pelo PostgreSQL // para interpretar valores de entrada de data ambíguos. PreparedStatement ps = db.prepareStatement("insert into tbl_basica values (?,?)"); for (int i = 2;i < 5;i++) { ps.setInt(1, 4); // "coluna a" = 4 ps.setInt(2, i); // "coluna b" = i ps.executeUpdate(); // porque o insert não retorna dados } ps.close(); // Sempre fechar ao terminar // Consultar a tabela
454
System.out.println("Realizando uma consulta"); ResultSet rs = st.executeQuery("select a, b from tbl_basica"); if (rs != null) { // Percorrer o conjunto de resultados mostrando os valores. // É necessário chamar .next() antes de ler qualquer resultado. while (rs.next()) { int a = rs.getInt("a"); // Nome da coluna int b = rs.getInt(2); // Número da coluna System.out.println(" a=" + a + " b=" + b); } rs.close(); // é necessário fechar o resultado ao terminar } // Consultar a tabela novamente, mostrando uma forma mais // eficiente de obter os resultados quando não se sabe o // número da coluna do resultado. System.out.println("Realizando outra consulta"); rs = st.executeQuery("select * from tbl_basica where b>1"); if (rs != null) { // Descobrir os números das colunas. // // É melhor ser feito neste ponto, porque os métodos chamados // passando os nomes das colunas realizam internamente esta // chamada toda toda vez que são chamados. Esta forma realmente // melhora o desempenho em consultas grandes. // int col_a = rs.findColumn("a"); int col_b = rs.findColumn("b"); // Percorrer o conjunto de resultados mostrando os valores. // É necessário chamar .next() antes de ler qualquer resultado. while (rs.next()) { int a = rs.getInt(col_a); // Número da coluna int b = rs.getInt(col_b); // Número da coluna System.out.println(" a=" + a + " b=" + b); } rs.close(); // é necessário fechar o resultado ao terminar. } // Testar 'maxrows' definindo-o como 3 linhas st.setMaxRows(3); System.out.println("Realizando uma consulta limitada a " + st.getMaxRows() + " linhas."); rs = st.executeQuery("select a, b from tbl_basica"); while (rs.next()) { int a = rs.getInt("a"); // Obter o valor pelo nome da coluna int b = rs.getInt(2); // Obter o valor pelo número da coluna System.out.println(" a=" + a + " b=" + b); } rs.close(); // repetindo, é necessário fechar o resultado ao terminar. // A última tarefa a ser realizada é remover a tabela, // o que é feito pelo método cleanup(). } /*
455
* Testar o driver JDBC */ public static void main(String args[]) { System.out.println("PostgreSQL - Teste básico v6.3 rev 1\n"); try { Basico objBasico = new Basico(); objBasico.go(); } catch (Exception ex) { System.err.println("Exceção capturada.\n" + ex); ex.printStackTrace(); } } }
31.12. Exemplo de utilização de BLOB no JDBC Nota: Esta seção foi escrita pelo tradutor, não fazendo parte do manual original.
Este exemplo serve para testar o acesso aos objetos grandes pelo driver JDBC, usando tanto a API proprietária quanto a API padrão. É fornecido junto com a distribuição do código fonte do PostgreSQL, no arquivo src/interfaces/jdbc/example/blobtest.java. Além da tradução, foram introduzidas pequenas alterações com relação ao código original. No Fedora Core 2 foi utilizado “export CLASSPATH=/usr/share/java/pg74.1jdbc3.jar:.” para executar o programa a partir da linha de comando, e “/usr/share/java/pg74.1jdbc3.jar” na configuração de Bibliotecas do Usuário do BlueJ (http://www.bluej.org) para o programa ser executado nesta IDE. import java.io.*; import java.sql.*; import org.postgresql.largeobject.*; /* * Este teste tem por objetivo criar um BLOB no banco de dados, e depois * ler o mesmo. * * Foi utilizada a imagem "/usr/share/backgrounds/images/dragonfly.jpg" * do Fedora Core 2 para fazer o teste. Deve ser substituída por outra * caso esta imagem não exista no sistema. * * Nota importante: Observe que é importado o pacote * org.postgresql.largeobject, * mas não é importado o pacote org.postgresql. A razão disto é que a * importação deste último confunde o javac (existe conflito entre nomes de * classes em org.postgresql.* e java.sql.*). Isto não causa nenhum problema, * desde que o código não importe org.postgresql. * * Nas circustâncias normais, o código que utiliza qualquer driver de jdbc * somente precisa importar java.sql e, portanto, isto não é um problema. * * Somente quando são utilizadas funcionalidades não-jdbc é que isto deve * ser levado em consideração. * */
456
public class BlobTest { Connection db; Statement s; LargeObjectManager lobj; String strImagem = "/usr/share/backgrounds/images/dragonfly.jpg"; public void go() throws ClassNotFoundException, FileNotFoundException, IOException, SQLException { // Banco de dados, usuário e senha igual a "teste" // CREATE USER teste WITH password 'teste'; // CREATE DATABASE teste WITH OWNER teste ENCODING 'LATIN1'; String url = "jdbc:postgresql://localhost/teste?charSet=LATIN1"; String usr = "teste"; String pwd = "teste"; // Carregar o driver Class.forName("org.postgresql.Driver"); // Conectar com o servidor de banco de dados System.out.println("Conectando ao banco de dados\nURL = " + url); db = DriverManager.getConnection(url, usr, pwd); // Necessário para todas as chamadas a LargeObject System.out.println("Conectado... Primeiro desabilitar autoCommit()"); db.setAutoCommit(false); System.out.println("Criando a declaração"); s = db.createStatement(); // Executar os testes utilizando a API LargeObject do PostgreSQL. // NOTA: Os métodos mostrados neste exemplo NÃO são JDBC, mas são // implementações de chamadas encontradas na libpq. A menos que // estas funcionalidades sejam necessárias, veja nos testes de // JDBC como acessar os BLOBS. ownapi(); // Fechar o banco de dados System.out.println("Fechando a conexão"); s.close(); db.close(); } /* * Esta é uma extensão do JDBC única do PostgreSQL. É trazido um * objeto PGlobj, que fornece as funcionalidades da API LargeObject * PostgreSQL. */ public void ownapi() throws FileNotFoundException, IOException, SQLException { System.out.println("\n--------------------------------------" + "\nTeste da API LargeObject do PostgreSQL" + "\n--------------------------------------"); // Internamente o driver JDBC fornece métodos para acessar // objetos grandes em conformidade com a especificação do // JDBC, entretanto os métodos disponíveis unicamente para // o PostgreSQL tornam o acesso um pouco mais fácil. System.out.println("Obtendo acesso à API LargeObject"); lobj = ((org.postgresql.PGConnection)db).getLargeObjectAPI();
457
int oid = ownapi_test1(); ownapi_test2(oid); // Chamar o teste jdbc2api jdbc2api(oid); // Remover o Objeto Grande ownapi_test3(oid); System.out.println("\n\nOID=" + oid); } private int ownapi_test1() throws FileNotFoundException, IOException, SQLException { System.out.println("Teste 1 - Criação do objeto grande\n"); // O teste 1 se destina a criar o objeto grande. // A criação é feita utilizado o método "create". System.out.println("Criando o Objeto Grande"); int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE); DriverManager.println("OID do Objeto Grande criado=" + oid); LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE); DriverManager.println("got large object obj=" + obj); // Abrir o arquivo de teste System.out.println("Abrindo o arquivo de teste"); FileInputStream fis = new FileInputStream(strImagem); // copiar os dados System.out.println("Copiando o arquivo para o objeto grande"); byte buf[] = new byte[2048]; int s, tl = 0; while ((s = fis.read(buf, 0, 2048)) > 0) { System.out.println("Tamanho do bloco=" + s + " deslocamento=" + tl); obj.write(buf, 0, s); tl += s; } DriverManager.println("Copied " + tl + " bytes"); // Fechar o objeto System.out.println("Fechando o objeto"); obj.close(); return oid; } private void ownapi_test2(int oid) throws FileNotFoundException, IOException, SQLException { System.out.println( "Teste 2 - Ler o objeto grande e salvar num arquivo\n"); // Abrir o objeto grande System.out.println("Abrindo o objeto grande " + oid); LargeObject obj = lobj.open(oid, LargeObjectManager.READ); DriverManager.println("got obj=" + obj); // Abrir um arquivo de teste
458
System.out.println("Abrindo o objeto de destino do teste"); FileOutputStream fos = new FileOutputStream("blob_teste_saida"); // Copiar os dados System.out.println("Copiando o objeto grande para o arquivo"); byte buf[] = new byte[512]; int s = obj.size(); int tl = 0; while (s > 0) { int rs = buf.length; if (s < rs) rs = s; obj.read(buf, 0, rs); fos.write(buf, 0, rs); tl += rs; s -= rs; } DriverManager.println("Copied " + tl + "/" + obj.size() + " bytes"); // Fechar o objeto System.out.println("Fechando o objeto"); obj.close(); } private void ownapi_test3(int oid) throws SQLException { System.out.println("Teste 3 - Remoção do objeto grande\n"); // Remover o objeto grande System.out.println("Removendo o objeto grande " + oid); lobj.unlink(oid); } // Testar a interface BLOB da especificação JDBC 2.0 public void jdbc2api(int oid) throws SQLException, IOException { System.out.println("Testando a interface JDBC2:"); jdbc2api_cleanup(); System.out.println("Criando um BLOB no objeto grande " + oid); s.executeUpdate("create table basic (a oid)"); System.out.println("Inserindo a linha"); s.executeUpdate("insert into basic values (" + oid + ")"); System.out.println("Selecionando a linha"); ResultSet rs = s.executeQuery("select a from basic"); if (rs != null) { while (rs.next()) { System.out.println("Buscando o BLOB"); Blob b = rs.getBlob("a"); System.out.println("Tamanho do BLOB = " + b.length()); System.out.println("Caracteres 400-500:"); System.out.write(b.getBytes(400, 100)); System.out.println(); } rs.close(); }
459
System.out.println("Limpeza"); jdbc2api_cleanup(); } private void jdbc2api_cleanup() throws SQLException { db.setAutoCommit(true); try { s.executeUpdate("drop table basic"); } catch (Exception ex) { // Ignorar todos os erros } db.setAutoCommit(false); } public static void main(String args[]) { System.out.println("PostgreSQL - Teste de BLOB v7.0 rev 1\n"); // Executar os testes try { BlobTest blobtest = new BlobTest(); blobtest.go(); } catch (Exception ex) { System.err.println("Exceção capturada.\n" + ex); ex.printStackTrace(); } } }
31.13. Exemplo de utilização de Thread no JDBC Nota: Esta seção foi escrita pelo tradutor, não fazendo parte do manual original.
Este exemplo serve para testar a segurança das threads no driver JDBC, usando tanto a API proprietária quanto a API padrão. É fornecido junto com a distribuição do código fonte do PostgreSQL, no arquivo src/interfaces/jdbc/example/threadsafe.java. Além da tradução, foram introduzidas pequenas alterações com relação ao código original. No Fedora Core 2 foi utilizado “export CLASSPATH=/usr/share/java/pg74.1jdbc3.jar:.” para executar o programa a partir da linha de comando, e “/usr/share/java/pg74.1jdbc3.jar” na configuração de Bibliotecas do Usuário do BlueJ (http://www.bluej.org) para o programa ser executado nesta IDE.
460
import java.io.*; import java.sql.*; // Embora não seja comum no código do usuário, será // utilizada a API LargeObject neste exemplo. import org.postgresql.largeobject.*; /* * Este exemplo testa a segurança de thread do driver. * * Isto é feito executando várias comandos, em threads diferentes. * Cada thread possui o seu próprio objeto Statement, o que é (na * minha compreensão da especificação do jdbc) o requerimento mínimo. * * Foi utilizada a imagem "/usr/share/backgrounds/images/dragonfly.jpg" * do Fedora Core 2 para fazer o teste. Deve ser substituída por outra * caso esta imagem não exista no sistema. * */ public class ThreadSafe { Connection db; // Conexão com o servidor de banco de dados Statement st; // Declaração para executar os comandos String strImagem = "/usr/share/backgrounds/images/dragonfly.jpg"; public void go() throws ClassNotFoundException, FileNotFoundException, IOException, SQLException { // Banco de dados, usuário e senha igual a "teste" // CREATE USER teste WITH password 'teste'; // CREATE DATABASE teste WITH OWNER teste ENCODING 'LATIN1'; String url = "jdbc:postgresql://localhost/teste?charSet=LATIN1"; String usr = "teste"; String pwd = "teste"; // Carregar o driver Class.forName("org.postgresql.Driver"); // Conectar com o servidor de banco de dados System.out.println("Conectando ao banco de dados\nURL = " + url); db = DriverManager.getConnection(url, usr, pwd); System.out.println("Conectado...Criando a declaração"); st = db.createStatement(); // Limpar o banco de dados (no caso de uma falha anterior) // e inicializar cleanup(); // Como são utilizados LargeObjects, devem ser utilizadas Transações db.setAutoCommit(false); // Executar os testes usando os métodos do JDBC, // e depois do LargeObjects doexample(); // Limpar o banco de dados cleanup();
461
// Fechar a conexão System.out.println("Fechando a conexão"); st.close(); db.close(); } /* * Remover a tabela (caso exista). Nenhum erro é mostrado. */ public void cleanup() { try { st.executeUpdate("drop table tbl_basica1"); } catch (Exception ex) { // Ignorar todos os erros } try { st.executeUpdate("drop table tbl_basica2"); } catch (Exception ex) { // Ignorar todos os erros } } /* * Executar o exemplo */ public void doexample() throws SQLException { System.out.println("\n---------------------------------------" + "\nEste teste executa três Threads." + "\nDuas simplesmente inserem dados na" + "\ntabela e depois realizam uma consulta.\n" + "\nEnquanto estas duas threads executam," + "\numa terceira thread executa carregando" + "\ne depois lendo dados de um LargeObject.\n" + "\nSe tudo der certo será executado sem" + "\nnenhum erro, e o driver é Thread Safe.\n" + "\nPorque utilizar LargeObject?" + "\nPorque ambos utilizam a conexão de rede," + "\ne se o bloqueio no fluxo não for feito" + "\nde forma correta o servidor ficará" + "\nconfuso!" + "\n---------------------------------------"); thread3 thread3 = null; try { // Criar duas threads novas Thread thread0 = Thread.currentThread(); Thread thread1 = new thread1(db); Thread thread2 = new thread2(db); thread3 = new thread3(db);
462
// Executar e aguardar por elas thread1.start(); thread2.start(); thread3.start(); // Fazer uma pausa temporária no objeto thread em execução, // para permitir que as outras threads executem. System.out.println("Aguardando a execução das threads"); while (thread1.isAlive() || thread2.isAlive() || thread3.isAlive()) Thread.yield(); } finally { // Limpar após thread3 (o finally garante que é executado // mesmo ocorrendo uma excessão dentro do bloco try { }) if (thread3 != null) thread3.cleanup(); } System.out.println( "Nenhuma excessão ocorreu. Isto é um bom sinal,\n" + "porque significa que estamos tão seguros para\n" + "thread quanto podemos conseguir."); } // Esta é a primeira thread. É igual ao teste básico class thread1 extends Thread { Connection c; Statement st; public thread1(Connection c) throws SQLException { this.c = c; st = c.createStatement(); } public void run() { try { System.out.println("Thread 1 executando..."); // Criar a tabela que armazena os dados st.executeUpdate("create table tbl_basica1 (a int2, b int2)"); // Inserir alguns dados utilizando Statement st.executeUpdate("insert into tbl_basica1 values (1,1)"); st.executeUpdate("insert into tbl_basica1 values (2,1)"); st.executeUpdate("insert into tbl_basica1 values (3,1)"); // Utilizar PreparedStatement para fazer muitas inserções PreparedStatement ps = db.prepareStatement( "insert into tbl_basica1 values (?,?)"); for (int i = 2; i < 2000; i++) { ps.setInt(1, 4); // "coluna a" = 4 ps.setInt(2, i); // "coluna b" = i ps.executeUpdate(); // porque insert não retorna dados
463
if ((i % 50) == 0) DriverManager.println( "Thread 1 executou " + i + " inserções"); } ps.close();
// Sempre fechar ao terminar
// Consultar a tabela DriverManager.println("Thread 1 realizando a consulta"); ResultSet rs = st.executeQuery( "select a, b from tbl_basica1"); int cnt = 0; if (rs != null) { // Percorrer o conjunto de resultados mostrando os // valores. // Observe que é necessário chamar .next() // antes de ler qualquer resultado. while (rs.next()) { int a = rs.getInt("a"); // Nome da coluna int b = rs.getInt(2); // Número da coluna //System.out.println(" a="+a+" b="+b); cnt++; } rs.close(); // é necessário fechar ao terminar } DriverManager.println("Thread 1 leu " + cnt + " linhas"); // O método cleanup() remove a tabela. System.out.println("Thread 1 terminou"); } catch (SQLException se) { System.err.println("Thread 1: " + se.toString()); se.printStackTrace(); System.exit(1); } } } // Esta é a segunda thread. É semelhante ao teste básico e a thread1, // exceto por utilizar outra tabela. class thread2 extends Thread { Connection c; Statement st; public thread2(Connection c) throws SQLException { this.c = c; st = c.createStatement(); } public void run() { try { System.out.println("Thread 2 executando..."); // Criar a tabela que armazena os dados st.executeUpdate("create table tbl_basica2 (a int2, b int2)");
464
// Utilizar PreparedStatement para fazer muitas inserções PreparedStatement ps = db.prepareStatement( "insert into tbl_basica2 values (?,?)"); for (int i = 2; i < 2000; i++) { ps.setInt(1, 4); // "coluna a" = 4 ps.setInt(2, i); // "coluna b" = i ps.executeUpdate(); // porque insert não retorna dados // c.commit(); if ((i % 50) == 0) DriverManager.println( "Thread 2 executou " + i + " inserções"); } ps.close(); // Sempre fechar ao terminar // Consultar a tabela DriverManager.println("Thread 2 realizando a consulta"); ResultSet rs = st.executeQuery( "select * from tbl_basica2 where b>1"); int cnt = 0; if (rs != null) { // Descobrir os números das colunas. // // É melhor fazer neste ponto, porque os métodos chamados // passando os nomes das colunas realizam internamente // esta chamada toda toda vez que são chamados. Isto // realmente melhora o desempenho em consultas grandes. // int col_a = rs.findColumn("a"); int col_b = rs.findColumn("b"); // Percorrer o conjunto de resultados mostrando os // valores. // Repetindo, é necessário chamar .next() // antes de ler qualquer resultado. while (rs.next()) { int a = rs.getInt(col_a); // Número da coluna int b = rs.getInt(col_b); // Número da coluna //System.out.println(" a="+a+" b="+b); cnt++; } rs.close(); // é necessário fechar o resultado ao terminar } DriverManager.println("Thread 2 leu " + cnt + " linhas"); // O método cleanup() remove a tabela. System.out.println("Thread 2 terminou"); } catch (SQLException se) { System.err.println("Thread 2: " + se.toString()); se.printStackTrace(); System.exit(1); } } } // Esta é a terceira thread. Carrega e lê um LargeObject // utilizando a API LargeObject do PostgreSQL.
465
// // A finalidade é testar se FastPath funciona junto com // consultas JDBC normais. class thread3 extends Thread { Connection c; Statement st; LargeObjectManager lom; LargeObject lo; int oid; public thread3(Connection c) throws SQLException { this.c = c; //st = c.createStatement(); // Criar o BLOB lom = ((org.postgresql.PGConnection)c).getLargeObjectAPI(); oid = lom.create(); System.out.println("Thread 3 criou o BLOB com oid " + oid); } public void run() { try { System.out.println("Thread 3 executando..."); DriverManager.println( "Thread 3: Carregando dados no BLOB " + oid); lo = lom.open(oid); FileInputStream fis = new FileInputStream(strImagem); // Utilizar um buffer pequeno para dar chance às outras // threads byte buf[] = new byte[128]; int rc, bc = 1, bs = 0; while ((rc = fis.read(buf)) > 0) { DriverManager.println("Thread 3 leu o bloco " + bc + " " + bs + " bytes"); lo.write(buf, 0, rc); bc++; bs += rc; } lo.close(); fis.close(); DriverManager.println("Thread 3: Lendo o BLOB " + oid); lo = lom.open(oid); bc = 0; while (buf.length > 0) { buf = lo.read(buf.length); if (buf.length > 0) { String s = new String(buf); bc++; DriverManager.println("Thread 3 bloco " + bc); DriverManager.println("Bloco " + bc + " obteve " + s); } } lo.close();
466
System.out.println("Thread 3 terminou"); } catch (Exception se) { System.err.println("Thread 3: " + se.toString()); se.printStackTrace(); System.exit(1); } } public void cleanup() throws SQLException { if (lom != null && oid != 0) { System.out.println("Thread 3: Removendo BLOB com oid=" + oid); lom.delete(oid); } } } public static void main(String args[]) { System.out.println( "PostgreSQL - Teste de Segurança de Thread v6.4 rev 1\n"); try { ThreadSafe threadsafe = new ThreadSafe(); threadsafe.go(); } catch (Exception ex) { System.err.println("Exceção capturada.\n" + ex); ex.printStackTrace(); } } }
31.14. Leitura adicional Caso ainda não tenha sido feito, aconselha-se a leitura da Documentação da API JDBC (fornecida junto com o JDK da Sun) e a Especificação do JDBC. Ambos estão disponíveis em http://java.sun.com/products/jdbc/index.html. A página http://jdbc.postgresql.org contém informações atualizadas não incluídas neste capítulo e, também, oferece versões pré-compiladas dos drivers.
Notas 1. No Fedora Core 2 o driver JDBC pode ser instalado a partir do arquivo postgresql-jdbc-7.4.21.i386.rpm (N. do T.) 2. No Fedora Core 2 o caminho de classe para acessar o driver JDBC instalado a partir do RPM é “export CLASSPATH=/usr/share/java/pg74.1jdbc3.jar:.” quando se utiliza o JDK 1.4 (N. do T.)
467
Capítulo 32. O esquema de informações O esquema de informações consiste em uma série de visões contendo informações sobre os objetos definidos no banco de dados corrente. O esquema de informações é definido no padrão SQL e, portanto, pode-se esperar que seja portável e permaneça estável; 1 2 diferentemente dos catálogos do sistema, que são específicos do PostgreSQL e modelados segundo interesses de implementação. Entretanto, as visões do esquema de informações não contêm informações sobre funcionalidades específicas do PostgreSQL; para obter este tipo de informação é necessário consultar os catálogos do sistema e outras visões específicas do PostgreSQL.
32.1. O esquema Em si, o esquema de informações é um esquema chamado information_schema. Este esquema é criado, automaticamente, em todos os bancos de dados. O dono deste esquema é o usuário de banco de dados inicial do agrupamento e, naturalmente, este usuário possui todos os privilégios neste esquema, incluindo a capacidade de removê-lo (mas o ganho de espaço obtido com a remoção é mínimo). Por padrão, o esquema de informações não está no caminho de procura de esquemas e, portanto, todos os seus objetos devem ser acessados através de nomes qualificados. Uma vez que os nomes de alguns objetos do esquema de informações são nomes genéricos, que podem ocorrer nas aplicações dos usuários, deve-se tomar cuidado se for desejado colocar o esquema de informações no caminho de procura.
32.2. Tipos de dado As colunas das visões do esquema de informações utilizam tipos de dado especiais, definidos no esquema de informações. São definidos como domínios simples sobre tipos nativos comuns. Estes tipos não devem ser utilizados para trabalho fora do esquema de informações, mas as aplicações devem estar preparadas para trabalhar com os mesmos, caso façam consultas ao esquema de informações. Os tipos são: cardinal_number
Inteiro não negativo. character_data
Uma cadeia de caracteres (sem tamanho máximo especificado). sql_identifier
Uma cadeia de caracteres. Este tipo é utilizado para os identificadores do SQL, enquanto o tipo character_data é utilizado para todos os outros tipos de dado de texto. time_stamp
Um domínio sobre timestamp Todas as colunas do esquema de informações possuem um destes quatro tipos. O tipo de dado booleano (verdade/falso) é representado no esquema de informações por uma coluna do tipo character_data contendo YES ou NO (O esquema de informações foi inventado antes do tipo boolean ser
adicionado ao padrão SQL e, portanto, esta convenção é necessária para manter o esquema de informações retroativamente compatível).
32.3. information_schema_catalog_name information_schema_catalog_name é uma tabela que sempre possui uma linha e uma coluna contendo o
nome do banco de dados corrente (catálogo corrente, na terminologia SQL) 3 .
468
Tabela 32-1. Colunas da tabela information_schema_catalog_name Nome
Tipo de dado
Descrição
catalog_name
sql_identifier
Nome do banco de dados que contém este esquema de informações
Exemplo de utilização: SELECT * FROM information_schema.information_schema_catalog_name; catalog_name -------------template1 (1 linha)
32.4. applicable_roles A visão applicable_roles identifica todos os grupos dos quais o usuário corrente é membro (Uma role é a mesma coisa que um grupo). Geralmente é melhor utilizar a visão enabled_roles em vez desta. 4 Tabela 32-2. Colunas da visão applicable_roles Nome
Tipo de dado
Descrição
grantee
sql_identifier
Sempre o nome do usuário corrente
role_name
sql_identifier
Nome do grupo
is_grantable
character_data
Se aplica a uma funcionalidade que não está presente no PostgreSQL
32.5. check_constraints A visão check_constraints contém todas as restrições de verificação, tanto as definidas nas tabelas quanto as definidas nos domínios, que pertencem ao usuário corrente (O dono da tabela ou do domínio é o dono da restrição) 5 6 7 . Tabela 32-3. Colunas da visão check_constraints Nome
Tipo de dado
Descrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
check_clause
character_data
A expressão de verificação da restrição de verificação
Exemplo de utilização: SELECT * FROM information_schema.check_constraints; constraint_catalog | constraint_schema | constraint_name | check_clause --------------------+--------------------+------------------------------+---------------template1 | information_schema | cardinal_number_domain_check | ((VALUE >= 0)) (1 linha)
469
32.6. column_domain_usage A visão column_domain_usage identifica todas as colunas (da tabela ou da visão) que fazem uso de algum domínio definido no banco de dados corrente e que pertence ao usuário corrente 8 9 10 . Tabela 32-4. Colunas da visão column_domain_usage Nome
Tipo de dado
Descrição
domain_catalog
sql_identifier
Nome do banco de dados que contém o domínio (sempre o banco de dados corrente)
domain_schema
sql_identifier
Nome do esquema que contém o domínio
domain_name
sql_identifier
Nome do domínio
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
column_name
sql_identifier
Nome da coluna
32.7. column_privileges A visão column_privileges identifica todos os privilégios concedidos em colunas para o usuário corrente ou pelo usuário corrente. Existe uma linha para cada combinação de coluna, quem concedeu e a quem foi concedido. Os privilégios concedidos aos grupos são identificados na visão role_column_grants. No PostgreSQL só é possível conceder privilégios para toda a tabela, e não para colunas individualmente. Portanto, esta visão contém as mesmas informações da visão table_privileges, apenas representadas por uma linha para cada coluna da respectiva tabela, mas somente abrangendo os tipos de privilégio onde a granularidade de coluna é possível: SELECT, INSERT, UPDATE, REFERENCES. Se for desejado tornar as aplicações adequadas para desenvolvimentos futuros o uso desta visão geralmente é a escolha correta, em vez de table_privileges, havendo preocupação com um destes tipos de privilégio 11 12 . Tabela 32-5. Colunas da visão column_privileges Nome
Tipo de dado
Descrição
grantor
sql_identifier
Nome do usuário que concedeu o privilégio
grantee
sql_identifier
Nome do usuário ou do grupo para o qual o privilégio foi concedido
table_catalog
sql_identifier
Nome do banco de dados contendo a tabela que contém a coluna (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema contendo a tabela que contém a coluna
table_name
sql_identifier
Nome da tabela que contém a coluna
column_name
sql_identifier
Nome da coluna
privilege_type
character_data
Tipo do privilégio: SELECT, INSERT, UPDATE ou REFERENCES
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
Observe que a coluna grantee não faz distinção entre usuários e grupos. Havendo usuários e grupos com o mesmo nome, infelizmente não há maneira de diferenciá-los. Provavelmente a existência de usuários e grupos com o mesmo nome será proibida numa versão futura do PostgreSQL.
470
32.8. column_udt_usage A visão column_udt_usage identifica todas as colunas que utilizam tipos de dado pertencentes ao usuário corrente. Deve ser observado que no PostgreSQL os tipos de dado nativos se comportam como os tipos definidos pelo usuário e, portanto, também são incluídos. Veja também a Seção 32.9 para obter mais detalhes. Tabela 32-6. Colunas da visão column_udt_usage Nome
Tipo de dado
Descrição
udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado da coluna (o tipo que está por baixo do domínio, quando aplicável) está definido (sempre o banco de dados corrente)
udt_schema
sql_identifier
Nome do esquema onde o tipo de dado da coluna (o tipo que está por baixo do domínio, quando aplicável) está definido
udt_name
sql_identifier
Nome do tipo de dado da coluna (o tipo que está por baixo do domínio, quando aplicável)
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
column_name
sql_identifier
Nome da coluna
32.9. columns A visão columns mostra informações sobre todas as colunas das tabelas (ou colunas das visões) do banco de dados. As colunas do sistema (oid, etc.) não são incluídas. Somente são mostradas as colunas que o usuário corrente tem acesso (por ser o dono ou por ter algum privilégio) 13 14 15 . Tabela 32-7. Colunas da visão columns Nome
Tipo de dado
Descrição
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
column_name
sql_identifier
Nome da coluna
ordinal_position
cardinal_number
Posição ordinal da coluna na tabela (contada a partir de 1)
column_default
character_data
Expressão padrão da coluna (nulo se o usuário corrente não for o dono da tabela que contém a coluna)
is_nullable
character_data
YES se a coluna puder ser nula, NO se não puder ser nula. Uma restrição de não-nulo é um meio de saber que a coluna não pode ser nula, mas podem haver outros meios.
data_type
character_data
Tipo de dado da coluna, se for um tipo nativo, ou ARRAY se for uma matriz (neste caso veja a visão element types), senão será USER-DEFINED
471
Nome
Tipo de dado
Descrição (neste caso o tipo é identificado em udt_name e nas colunas associadas). Se a coluna for baseada em um domínio, esta coluna se refere ao tipo por baixo do domínio (e o domínio é identificado em domain_name e nas colunas associadas).
character_maximum_length
cardinal_number
Quando data_type identifica um tipo cadeia de caracteres ou de bits, o comprimento máximo declarado; nulo para todos os outros tipos de dado, ou se o comprimento máximo não for especificado.
character_octet_length
cardinal_number
Quando data_type identifica um tipo caractere, o comprimento máximo possível em octetos (bytes) do datum (os usuários do PostgreSQL não devem se preocupar com isto); nulo para todos os outros tipos de dado.
numeric_precision
cardinal_number
Quando data_type identifica um tipo numérico, esta coluna contém a precisão (declarada ou implícita) do tipo de dado desta coluna. A precisão indica o número de dígitos significativos. Pode ser expresso em decimal (base 10) ou em binário (base 2), conforme especificado na coluna numeric_precision_radix. Para todos ou outros tipos de dado esta coluna é nula.
numeric_precision_radix
cardinal_number
Quando data_type identifica um tipo numérico, esta coluna indica em que base os valores nas colunas numeric_precision e numeric_scale estão expressos. O valor é 2 ou 10. Para todos ou outros tipos de dado esta coluna é nula.
numeric_scale
cardinal_number
Quando data_type identifica um tipo numérico exato, esta coluna contém a escala (declarada ou implícita) do tipo desta coluna. A escala indica o número de dígitos significativos à direita do ponto decimal. Pode ser expresso em decimal (base 10) ou em binário (base 2), conforme especificado na coluna numeric_precision_radix. Para todos ou outros tipos de dado esta coluna é nula.
datetime_precision
cardinal_number
Quando data_type identifica um tipo data, hora ou intervalo, a precisão declarada; nulo para todos os outros tipos de dado, ou se a precisão não for declarada.
interval_type
character_data
Ainda não implementado
interval_precision
character_data
Ainda não implementado
character_set_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
472
Nome
Tipo de dado
Descrição
collation_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
domain_catalog
sql_identifier
Quando a coluna possui um tipo domínio, o nome do banco de dados onde o domínio está definido (sempre o banco de dados corrente), senão nulo.
domain_schema
sql_identifier
Quando a coluna possui um tipo domínio o nome do esquema onde o domínio está definido, senão nulo.
domain_name
sql_identifier
Quando a coluna possui um tipo domínio o nome do domínio, senão nulo.
udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado da coluna (o tipo por baixo do domínio, quando aplicável) está definido (sempre o o banco de dados corrente) (udt = tipo definido pelo usuário. N. do T.)
udt_schema
sql_identifier
Nome do esquema onde o tipo de dado da coluna (o tipo por baixo do domínio, quando aplicável) está definido
udt_name
sql_identifier
Nome tipo de dado da coluna (o tipo por baixo do domínio, quando aplicável)
scope_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
maximum_cardinality
cardinal_number
Sempre nulo, porque as matrizes sempre possuem uma cardinalidade a máxima não definida no PostgreSQL
dtd_identifier
sql_identifier
O identificador do descritor do tipo de dado da coluna, único entre todos os descritores b de tipo de dado pertencentes à tabela. O uso principal é para fazer junção com outras instâncias de identificadores deste tipo (O formato específico do identificador não é definido, e também não há garantia que permaneça o mesmo nas versões futuras).
is_self_referencing
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
Notas: a. cardinalidade — O número de elementos da coleção. Os elementos não precisam necessariamente possuirem valores distintos. Os objetos aos quais este conceito se aplica incluem as tabelas e os valores
473
Nome
Tipo de dado
Descrição
dos tipos coleção. (ISO-ANSI Working Draft) Foundation (SQL/Foundation), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E).(N. do T.) b. descritor — Uma descrição codificada de um objeto SQL. Inclui todas as informações sobre o objeto requeridas por uma implementação em conformidade com o SQL. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) Uma vez que os tipos de dado são definidos de várias formas no SQL, e o PostgreSQL possui formas adicionais de definir tipos de dado, sua representação no esquema de informações pode se tornar um tanto difícil. Presume-se que o data_type da coluna identifique o tipo nativo por baixo da coluna. No PostgreSQL isto significa que o tipo é definido no catálogo do sistema pg_catalog. Esta coluna pode ser útil se a aplicação puder dar um tratamento especial aos tipos de dado nativos bem conhecidos (por exemplo, formatar tipos numéricos de forma diferente, ou utilizar os dados nas colunas de precisão). As colunas udt_name, udt_schema e udt_catalog sempre identificam o tipo de dado por baixo da coluna, mesmo quando a coluna se baseia em um domínio (Uma vez que o PostgreSQL trata os tipos nativos da mesma maneira que os tipos definidos pelo usuário, os tipos nativos também aparecem aqui. É uma extensão ao padrão SQL). Estas colunas devem ser utilizadas se a aplicação desejar processar os dados de forma diferente conforme o tipo, porque neste caso não vai importar se a coluna realmente se baseia em um domínio. Se a coluna for baseada em um domínio, a identidade do domínio é armazenada nas colunas domain_name, domain_schema e domain_catalog. Se for desejado agrupar as colunas com seus tipos de dado associados e tratar os domínios como tipos separados, pode ser utilizado coalesce(domain_name, udt_name), etc.
32.10. constraint_column_usage A visão constraint_column_usage identifica todas as colunas no banco de dados corrente utilizadas por uma restrição. Somente são mostradas as colunas pertencentes às tabelas que pertencem ao usuário corrente. Para as restrições de verificação, esta visão identifica as colunas utilizadas na expressão de verificação. Para as restrições de chave estrangeira, esta visão identifica as colunas referenciadas pela chave estrangeira. Para as restrições de unicidade ou de chave primária, esta visão identifica as colunas restringidas 16 17 18 . Tabela 32-8. Colunas da visão constraint_column_usage Nome
Tipo de dado
Descrição
table_catalog
sql_identifier
Nome do banco de dados contendo a tabela que contém a coluna utilizada pela restrição (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema contendo a tabela que contém a coluna utilizada pela restrição
table_name
sql_identifier
Nome da tabela que contém a coluna utilizada pela restrição
column_name
sql_identifier
Nome da coluna utilizada pela restrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
32.11. constraint_table_usage A visão constraint_table_usage identifica todas as tabelas do banco de dados corrente utilizadas por uma restrição, e que pertencem ao usuário corrente (Esta visão é diferente da visão table_constraints, que identifica todas as restrições de tabela junto com a tabela onde são definidas). Para as restrições de chave estrangeira, esta visão identifica a tabela referenciada pela chave estrangeira. Para as restrições de unicidade ou
474
de chave primária, esta visão identifica a tabela que possui a restrição. As restrições de verificação e de nãonulo não são incluídas nesta visão 19 20 21 . Tabela 32-9. Colunas da visão constraint_table_usage Nome
Tipo de dado
Descrição
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela utilizada pela restrição (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela utilizada pela restrição
table_name
sql_identifier
Nome da tabela utilizada pela restrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
32.12. data_type_privileges A visão data_type_privileges identifica todos os descritores de tipo de dado que o usuário corrente pode acessar, seja por ser o dono do objeto descrito ou por ter algum privilégio sobre o mesmo. O descritor de tipo de dado é gerado sempre que o tipo de dado é utilizado na definição da coluna de uma tabela, de um domínio ou de uma função (como parâmetro ou retorno), e armazena alguma informação sobre como o tipo de dado é utilizado nesta instância (por exemplo, o comprimento máximo declarado, se for aplicável). Para cada descritor de tipo de dado é atribuído um identificador arbitrário único entre os identificadores de descritor de tipo de dado atribuídos ao mesmo objeto (tabela, domínio, função). Provavelmente esta visão não tem utilidade para aplicações, mas é utilizada para definir algumas outras visões do esquema de informações. Tabela 32-10. Colunas da visão data_type_privileges Nome
Tipo de dado
Descrição
object_catalog
sql_identifier
Nome do banco de dados que contém o objeto descrito (sempre o banco de dados corrente)
object_schema
sql_identifier
Nome do esquema que contém o objeto descrito
object_name
sql_identifier
Nome do objeto descrito
object_type
character_data
Tipo do objeto descrito: um entre TABLE (o descritor do tipo de dado pertence a uma coluna desta tabela), DOMAIN (o descritor do tipo de dado pertence a este domínio) ou ROUTINE (o descritor do tipo de dado pertence ao tipo de um parâmetro ou do valor retornado pela função).
dtd_identifier
sql_identifier
O descritor do identificador do tipo de dado, que é único entre os descritores de tipo de dado para o mesmo objeto.
32.13. domain_constraints A visão domain_constraints contém todas as restrições pertencentes aos domínios que pertencem ao usuário corrente 22 23 .
475
Tabela 32-11. Colunas da visão domain_constraints Nome
Tipo de dado
Descrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
domain_catalog
sql_identifier
Nome do banco de dados que contém o domínio (sempre o banco de dados corrente)
domain_schema
sql_identifier
Nome do esquema que contém o domínio
domain_name
sql_identifier
Nome do domínio
is_deferrable
character_data
YES se a restrição for postergável, NO caso contrário
initially_deferred
character_data
YES se a restrição for postergável e inicialmente postergada, NO caso contrário
32.14. domain_udt_usage A visão domain_udt_usage identifica todas as colunas que utilizam um tipo de dado que pertence ao usuário corrente. Observe que no PostgreSQL os tipos de dado nativos se comportam como os tipos definidos pelo usuário e, portanto, também são incluídos. Tabela 32-12. Colunas da visão domain_udt_usage Nome
Tipo de dado
Descrição
udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado do domínio está definido (sempre o banco de dados corrente)
udt_schema
sql_identifier
Nome do esquema onde o tipo de dado do domínio está definido
udt_name
sql_identifier
Nome do tipo de dado do domínio
domain_catalog
sql_identifier
Nome do banco de dados que contém o domínio (sempre o banco de dados corrente)
domain_schema
sql_identifier
Nome do esquema que contém o domínio
domain_name
sql_identifier
Nome do domínio
32.15. domains A visão domains contém todos os domínios definidos no banco de dados corrente 24 25 . Tabela 32-13. Colunas da visão domains Nome
Tipo de dado
Descrição
domain_catalog
sql_identifier
Nome do banco de dados que contém o domínio (sempre o banco de dados corrente)
domain_schema
sql_identifier
Nome do esquema que contém o domínio
domain_name
sql_identifier
Nome do domínio
data_type
character_data
Tipo de dado do domínio, se for um tipo nativo, ou ARRAY se for uma matriz (neste caso veja a
476
Nome
Tipo de dado
Descrição visão element_types), senão será USERDEFINED (neste caso o tipo é identificado em udt_name e nas colunas associadas).
character_maximum_length
cardinal_number
Quando o domínio possui o tipo cadeia de caracteres ou de bits, o comprimento máximo declarado; nulo para todos os outros tipos de dado, ou se o comprimento máximo não for especificado.
character_octet_length
cardinal_number
Quando o domínio possui o tipo caractere, o comprimento máximo possível em octetos (bytes) do datum (os usuários do PostgreSQL não devem se preocupar com isto); nulo para todos os outros tipos de dado.
character_set_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
numeric_precision
cardinal_number
Quando o domínio possui um tipo numérico, esta coluna contém a precisão (declarada ou implícita) do tipo de dado desta coluna. A precisão indica o número de dígitos significativos. Pode ser expressa em decimal (base 10) ou em binário (base 2), conforme especificado na coluna numeric_precision_radix. Para todos os outros tipos de dado esta coluna é nula.
numeric_precision_radix
cardinal_number
Quando o domínio possui um tipo numérico, esta coluna indica em que base os valores das colunas numeric_precision e numeric_scale estão expressos. O valor é 2 ou 10. Para todos os outros tipos de dado esta coluna é nula.
numeric_scale
cardinal_number
Quando o domínio possui um tipo numérico exato, esta coluna contém a escala (declarada ou implícita) do tipo desta coluna. A escala indica o número de dígitos significativos à direita do ponto decimal. Pode ser expressa em decimal (base 10) ou em binário (base 2), conforme especificado na coluna numeric_precision_radix. Para todos os outros tipos de dado esta coluna é nula.
datetime_precision
cardinal_number
Quando o domínio possui um tipo data, hora ou
477
Nome
Tipo de dado
Descrição intervalo, a precisão declarada; nulo para todos os outros tipos de dado ou se a precisão não for declarada.
interval_type
character_data
Ainda não implementado
interval_precision
character_data
Ainda não implementado
domain_default
character_data
Expressão padrão do domínio
udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado do domínio está definido (sempre o banco de dados corrente)
udt_schema
sql_identifier
Nome do esquema onde o tipo de dado do domínio está definido
udt_name
sql_identifier
Nome do tipo de dado do domínio
scope_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
maximum_cardinality
cardinal_number
Sempre nulo, porque a matrizes sempre possuem uma cardinalidade máxima não definida no PostgreSQL
dtd_identifier
sql_identifier
O identificador do descritor do tipo de dado do domínio, único entre todos os descritores de tipo de dado pertencentes ao domínio (o que é óbvio, porque o domínio somente contém um descritor de tipo de dado). A utilidade principal é para fazer junção com outras instâncias deste tipo de identificador (O formato específico do identificador não é definido, e também não há garantia que permaneça o mesmo nas versões futuras)
32.16. element_types A visão element_types contém os descritores do tipo de dado dos elementos das matrizes. Quando uma coluna de tabela, domínio, parâmetro de função ou valor retornado por uma função é definido como sendo do tipo matriz, a visão columns somente mostra ARRAY na coluna data_type. Para obter informações sobre o tipo do elemento da matriz pode ser feita a junção da visão columns com esta visão. Por exemplo, para mostrar as colunas da tabela pg_group com os tipos de dado das colunas e o tipo dos elementos da matriz pode ser executado:
478
SELECT c.column_name, c.data_type, e.data_type AS element_type FROM information_schema.columns c LEFT JOIN information_schema.element_types e ON ((c.table_catalog, c.table_schema, c.table_name, 'TABLE', c.dtd_identifier) = (e.object_catalog, e.object_schema, e.object_name, e.object_type, e.array_type_identifier)) WHERE c.table_schema = 'pg_catalog' AND c.table_name = 'pg_group' ORDER BY c.ordinal_position; -- Produzindo o resultado: column_name | data_type | element_type -------------+-----------+-------------groname | name | grosysid | integer | grolist | ARRAY | integer (3 linhas)
Esta visão somente inclui os objetos que o usuário corrente pode acessar, seja por ser o dono ou por possuir algum privilégio. Tabela 32-14. Colunas da visão element_types Nome
Tipo de dado
Descrição
object_catalog
sql_identifier
Nome do banco de dados que contém o objeto que utiliza a matriz sendo descrita (sempre o banco de dados corrente)
object_schema
sql_identifier
Nome do esquema que contém o objeto que utiliza a matriz sendo descrita
object_name
sql_identifier
Nome do objeto que utiliza a matriz sendo descrita
object_type
character_data
O tipo do objeto que utiliza a matriz sendo descrita: um entre TABLE (a matriz é utilizada por uma coluna de tabela), DOMAIN (a matriz é utilizada por um domínio), ROUTINE (a matriz é utilizada pelo tipo de dado de um parâmetro ou do valor retornado de uma função).
array_type_identifier
sql_identifier
O identificador do descritor do tipo de dado da matriz sendo descrita. Utilizado para fazer junção com as colunas dtd_identifier de outras visões do esquema de informações.
data_type
character_data
Tipo de dado dos elementos da matriz, se for um tipo nativo, senão USER-DEFINED (neste caso o tipo é identificado em udt_name e nas colunas associadas).
character_maximum_length
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
character_octet_length
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
479
Nome
Tipo de dado
Descrição
character_set_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
numeric_precision
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
numeric_precision_radix
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
numeric_scale
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
datetime_precision
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
interval_type
character_data
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
interval_precision
character_data
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de elementos de matriz no PostgreSQL
domain_default
character_data
Ainda não implementado
udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado dos elementos está definido (sempre o banco de dados corrente)
udt_schema
sql_identifier
Nome do esquema onde o tipo de dado dos elementos está definido
udt_name
sql_identifier
Nome do tipo de dado dos elementos
scope_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
480
Nome
Tipo de dado
Descrição
maximum_cardinality
cardinal_number
Sempre nulo, porque as matrizes sempre possuem uma cardinalidade máxima não definida no PostgreSQL
dtd_identifier
sql_identifier
O identificador do descritor do tipo de dado do elemento. Atualmente não tem utilidade.
32.17. enabled_roles A visão enabled_roles identifica todos os grupos dos quais o usuário corrente é membro (Uma role é a mesma coisa que um grupo). A diferença entre esta visão e a visão applicable_roles é que, no futuro, poderá haver um mecanismo para habilitar e desabilitar grupos durante a sessão. Neste caso, esta visão vai identificar os grupos que estão ativos no momento. Tabela 32-15. Colunas da visão enabled_roles Nome
Tipo de dado
Descrição
role_name
sql_identifier
Nome do grupo
32.18. key_column_usage A visão key_column_usage identifica todas as colunas do banco de dados corrente com restrição de unicidade, chave primária, ou de chave estrangeira. As restrições de verificação não são incluídas nesta visão. Somente são mostradas as colunas pertencentes às tabelas que pertencem ao usuário corrente 26 27 28 . Tabela 32-16. Colunas da visão key_column_usage Nome
Tipo de dado
Descrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
table_catalog
sql_identifier
Nome do banco de dados contendo a tabela que contém a coluna que é restringida pela restrição (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema contendo a tabela que contém a coluna que é restringida pela restrição
table_name
sql_identifier
Nome da tabela que contém a coluna que é restringida pela restrição
column_name
sql_identifier
Nome da coluna que é restringida pela restrição
ordinal_position
cardinal_number
Posição ordinal da coluna dentro da chave de restrição (contada a partir de 1)
32.19. parameters A visão parameters contém informações sobre os parâmetros (argumentos) de todas as funções no banco de dados corrente. Somente são mostradas as funções que o usuário corrente pode acessar (seja por ser o dono ou por possuir algum privilégio) 29 .
481
Tabela 32-17. Colunas da visão parameters Nome
Tipo de dado
Descrição
specific_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
specific_schema
sql_identifier
Nome do esquema que contém a função
specific_name
sql_identifier
O “nome específico” da função. Veja a Seção 32.26 para obter mais informações.
ordinal_position
cardinal_number
Posição ordinal do parâmetro na lista de argumentos da função (contada a partir de 1)
parameter_mode
character_data
Sempre IN, indicando um parâmetro de entrada (Futuramente poderão haver outros modos de parâmetro).
is_result
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
as_locator
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
parameter_name
sql_identifier
Sempre nulo, porque o PostgreSQL não dá suporte a parâmetros com nome
data_type
character_data
Tipo de dado do parâmetro, se for um tipo nativo, ou ARRAY se for uma matriz (neste caso veja a visão element_types), senão USER-DEFINED (neste caso, o tipo é identificado em udt_name e nas colunas associadas).
character_maximum_length
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
character_octet_length
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
character_set_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
numeric_precision
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
482
Nome
Tipo de dado
Descrição
numeric_precision_radix
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
numeric_scale
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
datetime_precision
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
interval_type
character_data
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
interval_precision
character_data
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado de parâmetro no PostgreSQL
udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado do parâmetro está definido (sempre o banco de dados corrente)
udt_schema
sql_identifier
Nome do esquema onde o tipo de dado do parâmetro está definido
udt_name
sql_identifier
Nome do tipo de dado do parâmetro
scope_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
maximum_cardinality
cardinal_number
Sempre nulo, porque as matrizes sempre possuem uma cardinalidade máxima não definida no PostgreSQL
dtd_identifier
sql_identifier
O identificador do descritor do tipo de dado do parâmetro, único entre os descritores de tipo de dado pertencentes à função. O uso principal é para fazer junção com outras instâncias de identificadores deste tipo (O formato específico do identificador não é definido, e também não há garantia que permaneça o mesmo nas versões futuras).
32.20. referential_constraints A visão referential_constraints contém todas as restrições referenciais (chaves estrangeiras) no banco de dados corrente pertencentes a uma tabela que pertence ao usuário corrente 30 31 32 .
483
Tabela 32-18. Colunas da visão referential_constraints Nome
Tipo de dado
Descrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
unique_constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição de unicidade ou de chave primária que a restrição de chave estrangeira faz referência (sempre o banco de dados corrente)
unique_constraint_schema
sql_identifier
Nome do esquema que contém a restrição de unicidade ou de chave primária que a restrição de chave estrangeira faz referência
unique_constraint_name
sql_identifier
Nome da restrição de unicidade ou de chave primária que a restrição de chave estrangeira faz referência
match_option
character_data
Opção de correspondência da restrição de chave estrangeira: FULL, PARTIAL ou NONE.
update_rule
character_data
Regra de atualização da restrição de chave estrangeira: CASCADE, SET NULL, SET DEFAULT, RESTRICT ou NO ACTION.
delete_rule
character_data
Regra de exclusão da restrição de chave estrangeira: CASCADE, SET NULL, SET DEFAULT, RESTRICT ou NO ACTION.
32.21. role_column_grants A visão role_column_grants identifica os privilégios concedidos em colunas para um grupo do qual o usuário corrente é membro. Mais informações podem ser encontradas em column_privileges. Tabela 32-19. Colunas da visão role_column_grants Nome
Tipo de dado
Descrição
grantor
sql_identifier
Nome do usuário que concedeu o privilégio
grantee
sql_identifier
Nome do grupo para o qual o privilégio foi concedido
table_catalog
sql_identifier
Nome do banco de dados contendo a tabela que contém a coluna (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema contendo a tabela que contém a coluna
table_name
sql_identifier
Nome da tabela que contém a coluna
column_name
sql_identifier
Nome da coluna
privilege_type
character_data
Tipo do privilégio: SELECT, INSERT, UPDATE ou REFERENCES
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
484
32.22. role_routine_grants A visão role_routine_grants identifica todos os privilégios concedidos em funções para um grupo do qual o usuário corrente é membro. Mais informações podem ser encontradas em routine_privileges. Tabela 32-20. Colunas da visão role_routine_grants Nome
Tipo de dado
Descrição
grantor
sql_identifier
Nome do usuário que concedeu o privilégio
grantee
sql_identifier
Nome do grupo para o qual o privilégio foi concedido
specific_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
specific_schema
sql_identifier
Nome do esquema que contém a função
specific_name
sql_identifier
O “nome específico” da função. Veja a Seção 32.26 para obter mais informações.
routine_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
routine_schema
sql_identifier
Nome do esquema que contém a função
routine_name
sql_identifier
Nome da função (pode ser duplicada em caso de sobrecarga)
privilege_type
character_data
Sempre EXECUTE (o único tipo de privilégio para funções)
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
32.23. role_table_grants A visão role_table_grants identifica todos os privilégios concedidos em tabelas ou visões para um grupo do qual o usuário corrente é membro. Mais informações podem ser encontradas em table_privileges. Tabela 32-21. Colunas da visão role_table_grants Nome
Tipo de dado
Descrição
grantor
sql_identifier
Nome do usuário que concedeu o privilégio
grantee
sql_identifier
Nome do grupo para o qual o privilégio foi concedido
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
privilege_type
character_data
Tipo do privilégio: SELECT, DELETE, INSERT, UPDATE, REFERENCES, RULE ou TRIGGER
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
with_hierarchy
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
32.24. role_usage_grants A visão role_usage_grants tem por finalidade identificar os privilégios USAGE concedidos a vários tipos de objetos para um grupo do qual o usuário corrente é membro. Atualmente no PostgreSQL somente se aplica aos domínios, e uma vez que os domínios não possuem privilégios reais no PostgreSQL, esta visão é vazia.
485
Mais informações podem ser encontradas em usage_privileges. No futuro, esta informação vai conter informações úteis. Tabela 32-22. Colunas da visão role_usage_grants Nome
Tipo de dado
Descrição
grantor
sql_identifier
No futuro, o nome do usuário que concedeu o privilégio
grantee
sql_identifier
No futuro, o nome do grupo para o qual o privilégio foi concedido
object_catalog
sql_identifier
Nome do banco de dados que contém o objeto (sempre o banco de dados corrente)
object_schema
sql_identifier
Nome do esquema que contém o objeto
object_name
sql_identifier
Nome do objeto
object_type
character_data
No futuro, o tipo do objeto
privilege_type
character_data
Sempre USAGE
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
32.25. routine_privileges A visão routine_privileges identifica todos os privilégios concedidos em funções para o usuário corrente ou pelo usuário corrente. Existe uma linha para cada combinação de função, quem concedeu e a quem foi concedido. Os privilégios concedidos aos grupos são identificados na visão role_routine_grants. Tabela 32-23. Colunas da visão routine_privileges Nome
Tipo de dado
Descrição
grantor
sql_identifier
Nome do usuário que concedeu o privilégio
grantee
sql_identifier
Nome do usuário ou do grupo para o qual o privilégio foi concedido
specific_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
specific_schema
sql_identifier
Nome do esquema que contém a função
specific_name
sql_identifier
O “nome específico” da função. Veja a Seção 32.26 para obter mais informações.
routine_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
routine_schema
sql_identifier
Nome do esquema que contém a função
routine_name
sql_identifier
Nome da função (pode ser duplicada em caso de sobrecarga)
privilege_type
character_data
Sempre EXECUTE (o único tipo de privilégio para funções)
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
Observe que a coluna grantee não faz distinção entre usuários e grupos. Havendo usuários e grupos com o mesmo nome, infelizmente não há maneira de diferenciá-los. Provavelmente a existência de usuários e grupos com o mesmo nome será proibida numa versão futura do PostgreSQL.
486
32.26. routines A visão routines contém todas as funções no banco de dados corrente. Somente são mostradas as funções que o usuário corrente pode acessar (seja por ser o dono ou por possuir algum privilégio) 33 . Tabela 32-24. Colunas da visão routines Nome
Tipo de dado
Descrição
specific_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
specific_schema
sql_identifier
Nome do esquema que contém a função
specific_name
sql_identifier
O “nome específico” da função. É um nome que identifica unicamente a função no esquema, mesmo quando o nome verdadeiro da função é sobrecarregado. O formato do nome específico não é definido, devendo ser utilizado apenas para comparar com outras instâncias de nomes específicos de rotinas.
routine_catalog
sql_identifier
Nome do banco de dados que contém a função (sempre o banco de dados corrente)
routine_schema
sql_identifier
Nome do esquema que contém a função
routine_name
sql_identifier
Nome da função (pode ser duplicada em caso de sobrecarga)
routine_type
character_data
Sempre FUNCTION (No futuro poderão existir outros tipos de rotina).
module_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
module_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
module_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
udt_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
udt_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
udt_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
data_type
character_data
Tipo de dado retornado pela função, se for um tipo nativo, ou ARRAY se for uma matriz (neste caso veja a visão element_types), senão USERDEFINED (neste caso o tipo é identificado em type_udt_name e nas colunas associadas).
character_maximum_length
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
character_octet_length
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
character_set_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no
487
Nome
Tipo de dado
Descrição PostgreSQL
character_set_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
character_set_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
collation_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
numeric_precision
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
numeric_precision_radix
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
numeric_scale
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
datetime_precision
cardinal_number
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
interval_type
character_data
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
interval_precision
character_data
Sempre nulo, uma vez que esta informação não se aplica a tipos de dado retornados no PostgreSQL
type_udt_catalog
sql_identifier
Nome do banco de dados onde o tipo de dado retornado pela função está definido (sempre o banco de dados corrente)
type_udt_schema
sql_identifier
Nome do esquema onde o tipo de dado retornado pela função está definido
type_udt_name
sql_identifier
Nome do tipo de dado retornado pela função
scope_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
scope_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
maximum_cardinality
cardinal_number
Sempre nulo, porque as matrizes sempre possuem uma cardinalidade máxima não definida no PostgreSQL
dtd_identifier
sql_identifier
O identificador do descritor do tipo de dado retornado pela função, único entre os descritores de tipo de dado que pertencem à função. O uso principal é para fazer junção com outras instâncias de identificadores deste tipo (O formato específico do identificador não é definido, e também não há
488
Nome
Tipo de dado
Descrição garantia que permaneça o mesmo nas versões futuras). (dtd = descritor do tipo de dado - N. do T.)
routine_body
character_data
Se a função for uma função SQL então SQL, senão EXTERNAL.
routine_definition
character_data
O texto fonte da função (nulo se o usuário corrente não for o dono da função) (De acordo com o padrão SQL, esta coluna somente se aplica se routine_body for SQL, mas no PostgreSQL contém o texto fonte especificado quando a função foi criada, seja qual for a linguagem).
external_name
character_data
Se a função for uma função C, então o nome externo (símbolo de ligação) da função; senão nulo (Se torna o mesmo valor mostrado em routine_definition).
external_language
character_data
A linguagem na qual a função foi escrita
parameter_style
character_data
Sempre GENERAL (O padrão SQL define outros estilos de parâmetro, que não estão disponíveis no PostgreSQL).
is_deterministic
character_data
Se a função for declarada como imutável (chamado de determinística no padrão SQL) então YES, senão NO (Não é possível consultar os demais níveis de volatilidade disponíveis no PostgreSQL através do esquema de informações).
sql_data_access
character_data
Sempre MODIFIES, significando que a função possivelmente modifica dados SQL. Esta informação não é útil para o PostgreSQL.
is_null_call
character_data
Se a função retorna nulo automaticamente quando um de seus argumentos é nulo então YES, senão NO.
sql_path
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
schema_level_routine
character_data
Sempre YES (O oposto seria um método de um tipo definido pelo usuário, que é uma funcionalidade não disponível no PostgreSQL.)
max_dynamic_result_sets
cardinal_number
Se aplica a uma funcionalidade não disponível no PostgreSQL
is_user_defined_cast
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
is_implicitly_invocable
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
security_type
character_data
Se a função executa com os privilégios do usuário corrente então INVOKER, se a função executa com os privilégios do usuário que a definiu então DEFINER.
to_sql_specific_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no
489
Nome
Tipo de dado
Descrição PostgreSQL
to_sql_specific_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
to_sql_specific_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
as_locator
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
32.27. schemata A visão schemata contém todos os esquemas no banco de dados corrente pertencentes ao usuário corrente 34 .
35
Tabela 32-25. Colunas da visão schemata Nome
Tipo de dado
Descrição
catalog_name
sql_identifier
Nome do banco de dados que contém o esquema (sempre o banco de dados corrente)
schema_name
sql_identifier
Nome do esquema
schema_owner
sql_identifier
Nome do dono do esquema
default_character_set_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
default_character_set_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
default_character_set_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
sql_path
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
Exemplo de utilização: SELECT catalog_name,schema_name,schema_owner FROM information_schema.schemata; catalog_name | schema_name | schema_owner --------------+--------------------+-------------template1 | pg_toast | postgres template1 | pg_temp_1 | postgres template1 | pg_catalog | postgres template1 | public | postgres template1 | information_schema | postgres (5 linhas)
32.28. sql_features A tabela sql_features contém informações sobre quais funcionalidades formais definidas no padrão SQL são suportadas pelo PostgreSQL. É a mesma informação presente no Apêndice D, onde também podem ser encontradas informações adicionais.
490
Tabela 32-26. Colunas da tabela sql_features Nome
Tipo de dado
Descrição
feature_id
character_data
Cadeia de caracteres identificadora da funcionalidade
feature_name
character_data
Nome descritivo da funcionalidade
sub_feature_id
character_data
Cadeia de caracteres identificadora da subfuncionalidade, ou uma cadeia de caracteres com comprimento zero se não for uma subfuncionalidade
sub_feature_name
character_data
Nome descritivo da subfuncionalidade, ou uma cadeia de caracteres com comprimento zero se não for uma subfuncionalidade
is_supported
character_data
YES se a funcionalidade for inteiramente suportada pela versão corrente do PostgreSQL, NO caso contrário
is_verified_by
character_data
Sempre nulo, uma vez que o grupo de desenvolvimento do PostgreSQL não efetua testes formais de conformidade das funcionalidades
comments
character_data
Possivelmente um comentário sobre o status do suporte à funcionalidade
32.29. sql_implementation_info A tabela sql_information_info contém informações sobre vários aspectos que o padrão SQL deixa para serem definidos pela implementação. A finalidade básica destas informações é serem utilizadas no contexto da interface ODBC; provavelmente os usuários das outras interfaces vão encontrar pouca utilidade nestas informações. Por esta razão, a implementação individual dos itens de informação não são descritos nesta visão; se encontram na descrição da interface ODBC. Tabela 32-27. Colunas da tabela sql_implementation_info Nome
Tipo de dado
Descrição
implementation_info_id
character_data
Cadeia de caracteres identificadora da informação de implementação do item
implementation_info_name
character_data
Nome descritivo da informação de implementação do item
integer_value
cardinal_number
Valor da informação de implementação do item, ou nulo se o valor estiver contido na coluna character_value
character_value
character_data
Valor da informação de implementação do item, ou nulo se o valor estiver contido na coluna integer_value
comments
character_data
Possivelmente um comentário pertencente à informação de implementação do item
32.30. sql_languages A tabela sql_languages contém uma linha para cada ligação com linguagem SQL suportada pelo PostgreSQL. O PostgreSQL suporta SQL direto e SQL incorporado na linguagem C; isto é tudo o que se pode saber a partir desta tabela 36 37 .
491
Tabela 32-28. Colunas da tabela sql_languages Nome
Tipo de dado
Descrição
sql_language_source
character_data
O nome de origem da definição da linguagem; sempre ISO 9075, ou seja, o padrão SQL
sql_language_year
character_data
O ano em que o padrão referenciado em sql_language_source foi aprovado; atualmente 1999
sql_language_comformance
character_data
O nível de conformidade com o padrão desta ligação com a linguagem. Para ISO 9075:1999 é sempre CORE.
sql_language_integrity
character_data
Sempre nulo (Este valor tem relevância para uma versão anterior do padrão SQL)
sql_language_implementation
character_data
Sempre nulo
sql_language_binding_style
character_data
O estilo de ligação da linguagem, DIRECT (direto) ou EMBEDDED
(incorporado) sql_language_programming_language
character_data
A linguagem de programação, se o estilo de ligação for EMBEDDED, senão nulo. O PostgreSQL somente suporta a linguagem C.
Exemplo de utilização: SELECT sql_language_source AS sql_language_year AS sql_language_binding_style AS sql_language_programming_language AS FROM information_schema.sql_languages;
source, year, binding_style, programming_language
source | year | binding_style | programming_language ----------+------+---------------+---------------------ISO 9075 | 1999 | DIRECT | ISO 9075 | 1999 | EMBEDDED | C (2 linhas)
32.31. sql_packages A tabela sql_packages contém informações sobre quais pacotes de funcionalidades definidos no padrão SQL são suportados pelo PostgreSQL. Consulte o Apêndice D para obter mais informações sobre pacotes de funcionalidades.
492
Tabela 32-29. Colunas da tabela sql_packages Nome
Tipo de dado
Descrição
feature_id
character_data
Cadeia de caracteres identificadora do pacote
feature_name
character_data
Nome descritivo do pacote
is_supported
character_data
YES se o pacote for inteiramente suportado pela versão corrente do PostgreSQL, NO caso contrário
is_verified_by
character_data
Sempre nulo, uma vez que o grupo de desenvolvimento do PostgreSQL não efetua testes formais de conformidade das funcionalidades
comments
character_data
Possivelmente um comentário sobre o status do suporte ao pacote
32.32. sql_sizing A tabela sql_sizing contém informações sobre vários limites de tamanho e valores máximos no PostgreSQL. A finalidade básica destas informações é serem utilizadas no contexto da interface ODBC; provavelmente os usuários das outras interfaces vão encontrar pouca utilidade nestas informações. Por esta razão, os itens de tamanhos individuais não são descritos nesta visão; se encontram na descrição da interface ODBC. Tabela 32-30. Colunas da tabela sql_sizing Nome
Tipo de dado
Descrição
sizing_id
cardinal_number
O identificador do item de tamanho
sizing_name
character_data
Nome descritivo do item de tamanho
supported_value
cardinal_number
Valor do item de tamanho, ou 0 se o tamanho não for limitado ou não puder ser determinado, ou nulo se a funcionalidade para a qual o item de tamanho se aplica não é suportada
comments
character_data
Possivelmente um comentário pertencente ao item de tamanho
32.33. sql_sizing_profiles A tabela sql_sizing_profiles contém informações sobre os valores sql_sizing requeridos por vários perfis do padrão SQL. O PostgreSQL não segue qualquer perfil do SQL, portanto esta tabela é vazia. Tabela 32-31. Colunas da tabela sql_sizing_profiles Nome
Tipo de dado
Descrição
sizing_id
cardinal_number
Identificador do item de tamanho
sizing_name
character_data
Nome descritivo do item de tamanho
profile_id
character_data
Cadeia de caracteres identificadora do perfil
required_value
cardinal_number
O valor requerido pelo perfil SQL para o item de tamanho, ou 0 se o perfil não coloca nenhum limite para o item de tamanho, ou nulo se o perfil não requer nenhuma das funcionalidades para as quais o item de tamanho se aplica
comments
character_data
Possivelmente um comentário pertencente ao item de tamanho no perfil
493
32.34. table_constraints A visão table_constraints contém todas as restrições pertencentes às tabelas que pertencem ao usuário corrente 38 39 40 . Tabela 32-32. Colunas da visão table_constraints Nome
Tipo de dado
Descrição
constraint_catalog
sql_identifier
Nome do banco de dados que contém a restrição (sempre o banco de dados corrente)
constraint_schema
sql_identifier
Nome do esquema que contém a restrição
constraint_name
sql_identifier
Nome da restrição
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
constraint_type
character_data
Tipo da restrição: CHECK, FOREIGN KEY, PRIMARY KEY ou UNIQUE
is_deferrable
character_data
YES se a restrição for postergável, NO caso contrário
initially_deferred
character_data
YES se a restrição for postergável e inicialmente postergada, NO caso contrário
32.35. table_privileges A visão table_privileges identifica todos os privilégios concedidos em tabelas ou visões para o usuário corrente ou pelo usuário corrente. Existe uma linha para cada combinação de coluna, quem concedeu e a quem foi concedido. Os privilégios concedidos aos grupos são identificados na visão role_column_grants 41 42 43 . Tabela 32-33. Colunas da visão table_privileges Nome
Tipo de dado
Descrição
grantor
sql_identifier
Nome do usuário que concedeu o privilégio
grantee
sql_identifier
Nome do usuário ou do grupo para o qual o privilégio foi concedido
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
privilege_type
character_data
Tipo do privilégio: SELECT, DELETE, INSERT, UPDATE, REFERENCES, RULE ou TRIGGER
is_grantable
character_data
YES se o privilégio pode ser concedido, NO caso contrário
with_hierarchy
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
Observe que a coluna grantee não faz distinção entre usuários e grupos. Havendo usuários e grupos com o mesmo nome, infelizmente não há maneira de diferenciá-los. Provavelmente a existência de usuários e grupos com o mesmo nome será proibida numa versão futura do PostgreSQL.
494
32.36. tables A visão tables contém todas as tabelas e visões definidas no banco de dados corrente. Somente são mostradas as tabelas e visões que o usuário corrente pode acessar (seja por ser o dono ou por possuir algum privilégio) 44 45 46 . Tabela 32-34. Colunas da visão tables Nome
Tipo de dado
Descrição
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela
table_name
sql_identifier
Nome da tabela
table_type
character_data
Tipo da tabela: BASE TABLE para uma tabela base persistente a (o tipo normal de tabela), VIEW para uma visão, ou LOCAL TEMPORARY para uma tabela temporária
self_referencing_column_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
reference_generation
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
user_defined_type_catalog
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
user_defined_type_schema
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
user_defined_type_name
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
Notas: a. persistente: que permanece existindo indefinidamente, até ser destruído deliberadamente. Ações referenciais e em cascata são consideradas como deliberadas. Ações ligadas ao término da transação SQL ou da sessão SQL não são consideradas como deliberadas. (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
32.37. triggers A visão triggers contém todos os gatilhos definidos no banco de dados corrente que pertencem ao usuário corrente (O dono da tabela é o dono do gatilho.)
495
Tabela 32-35. Colunas da visão triggers Nome
Tipo de dado
Descrição
trigger_catalog
sql_identifier
Nome do banco de dados que contém o gatilho (sempre o banco de dados corrente)
trigger_schema
sql_identifier
Nome do esquema que contém o gatilho
trigger_name
sql_identifier
Nome do gatilho
event_manipulation
character_data
O evento que dispara o gatilho (INSERT, UPDATE ou DELETE)
event_object_catalog
sql_identifier
Nome do banco de dados que contém a tabela onde o gatilho está definido (sempre o banco de dados corrente)
event_object_schema
sql_identifier
Nome do esquema que contém a tabela onde o gatilho está definido
event_object_name
sql_identifier
Nome da tabela onde o gatilho está definido
action_order
cardinal_number
Ainda não implementado
action_condition
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
action_statement
character_data
Declaração executada pelo gatilho (atualmente sempre EXECUTE PROCEDURE função(...))
action_orientation
character_data
Identifica se o gatilho dispara uma vez para cada linha processada ou para cada declaração (ROW ou STATEMENT)
condition_timing
character_data
Hora em que o gatilho dispara (BEFORE ou AFTER)
condition_reference_old_table
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
condition_reference_new_table
sql_identifier
Se aplica a uma funcionalidade não disponível no PostgreSQL
Os gatilhos no PostgreSQL possuem duas incompatibilidades com o padrão SQL que afetam a representação no esquema de informações: Em primeiro lugar, no PostgreSQL os nomes dos gatilhos são locais às tabelas, em vez de objetos independentes no esquema. Portanto, podem haver nomes de gatilhos duplicados definidos em um esquema, desde que pertençam a tabelas diferentes (trigger_catalog e trigger_schema são, na verdade, valores que pertencem à tabela onde o gatilho está definido); Em segundo lugar, os gatilhos podem ser definidos para disparar em vários eventos no PostgreSQL (por exemplo, ON INSERT OR UPDATE), enquanto o padrão SQL só permite um. Se o gatilho for definido para disparar em vários eventos, isto é representado por várias linhas no esquema de informações, uma para cada tipo de evento. Como conseqüência destas incompatibilidades, a chave primária da visão triggers na verdade é (trigger_catalog, trigger_schema, trigger_name, event_object_name, event_manipulation), em vez de (trigger_catalog, trigger_schema, trigger_name), conforme especificado pelo padrão SQL. Apesar disso, se os gatilhos forem definidos em conformidade com o padrão SQL (nomes de gatilho únicos no esquema e somente um evento por gatilho), estas incompatibilidades não trarão conseqüências.
496
32.38. usage_privileges A visão usage_privileges tem por finalidade identificar os privilégios USAGE concedidos em vários tipos de objeto para o usuário corrente ou pelo usuário corrente. Atualmente, no PostgreSQL, se aplica somente aos domínios e, uma vez que os domínios não possuem privilégios reais no PostgreSQL, esta visão mostra os privilégios USAGE implícitos concedidos a PUBLIC para todos os domínios. No futuro esta visão poderá conter informações mais úteis 47 48 . Tabela 32-36. Colunas da visão usage_privileges Nome
Tipo de dado
Descrição
grantor
sql_identifier
Atualmente definido como o nome do dono do objeto
grantee
sql_identifier
Atualmente sempre PUBLIC
object_catalog
sql_identifier
Nome do banco de dados que contém o objeto (sempre o banco de dados corrente)
object_schema
sql_identifier
Nome do esquema que contém o objeto
object_name
sql_identifier
Nome do objeto
object_type
character_data
Atualmente sempre DOMAIN
privilege_type
character_data
Sempre USAGE
is_grantable
character_data
Atualmente sempre NO
32.39. view_column_usage A visão view_column_usage identifica todas as colunas utilizadas na expressão de consulta da visão (a declaração SELECT que define a visão). A coluna somente é incluída quando o usuário corrente é o dono da tabela que contém a coluna 49 50 51 . Nota: As colunas das tabelas do sistema não são incluídas. Isto será corrigido alguma hora.
Tabela 32-37. Colunas da visão view_column_usage Nome
Tipo de dado
Descrição
view_catalog
sql_identifier
Nome do banco de dados que contém a visão (sempre o banco de dados corrente)
view_schema
sql_identifier
Nome do esquema que contém a visão
view_name
sql_identifier
Nome da visão
table_catalog
sql_identifier
Nome do banco de dados contendo a tabela que contém a coluna utilizada pela visão (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema contendo a tabela que contém a coluna utilizada pela visão
table_name
sql_identifier
Nome da tabela que contém a coluna utilizada pela visão
column_name
sql_identifier
Nome da coluna utilizada pela visão
32.40. view_table_usage A visão view_table_usage identifica todas as tabelas utilizadas na expressão de consulta da visão (a declaração SELECT que define a visão). A tabela somente é incluída quando o usuário corrente é o dono da tabela 52 53 54 .
497
Nota: As tabelas do sistema não são incluídas. Isto será corrigido alguma hora.
Tabela 32-38. Colunas da visão view_table_usage Nome
Tipo de dado
Descrição
view_catalog
sql_identifier
Nome do banco de dados que contém a visão (sempre o banco de dados corrente)
view_schema
sql_identifier
Nome do esquema que contém a visão
view_name
sql_identifier
Nome da visão
table_catalog
sql_identifier
Nome do banco de dados que contém a tabela que é utilizada pela visão (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a tabela que é utilizada pela visão
table_name
sql_identifier
Nome da tabela que é utilizada pela visão
32.41. views A visão views contém todas visões definidas no banco de dados corrente. Somente são mostradas as visões que o usuário corrente pode acessar (seja por ser o dono ou por possuir algum privilégio) 55 56 57 . Tabela 32-39. Colunas da visão views Nome
Tipo de dado
Descrição
table_catalog
sql_identifier
Nome do banco de dados que contém a visão (sempre o banco de dados corrente)
table_schema
sql_identifier
Nome do esquema que contém a visão
table_name
sql_identifier
Nome da visão
view definition
character_data
Expressão de consulta que define a visão (nulo se o usuário corrente não for o dono da visão)
check_option
character_data
Se aplica a uma funcionalidade não disponível no PostgreSQL
is_updatable
character_data
Ainda não implementado
is_insertable_into
character_data
Ainda não implementado
Notas 1. Oracle — o Oracle não possui nenhuma das visões do esquema de informações, entretanto estas informações podem ser obtidas em outras visões de metadados. Em vez de TABLES é usado ALL_TABLES, em vez de COLUMNS é usado ALL_TAB_COLUMNS, e em vez de VIEWS é usado ALL_VIEWS. Oracle and Standard SQL (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96540/ap_standard_sql.htm#7518) (N. do T.) 2. SQL Server — o Microsoft® SQL Server 2000 fornece dois métodos para obter metadados: procedimentos armazenados do sistema e visões do esquema de informações. Estas visões fornecem uma visão interna, independente das tabelas do sistema, dos metadados do SQL Server. As visões do esquema de informações permitem que as aplicações trabalhem de forma apropriada, mesmo quando mudanças significativas são feitas nas tabelas do sistema. As visões do esquema de informações incluídas no SQL Server estão em conformidade com as definições do padrão SQL-92 para o INFORMATION_SCHEMA. SQL Server Books Online (N. do T.)
498
3. A tabela INFORMATION_SCHEMA_CATALOG_NAME identifica o catálogo que contém o Esquema de Informações. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 4. Também pode ser utilizada a consulta SELECT groname FROM pg_group WHERE (SELECT usesysid FROM pg_user WHERE usename = CAST(current_user AS TEXT)) = ANY (grolist); para identificar os grupos dos quais o usuário corrente é membro. (N. do T.) 5. A visão CHECK_CONSTRAINTS identifica as restrições de verificação definidas neste catálogo que pertencem a um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 6. O rowset CHECK_CONSTRAINTS identifica as restrições de verificação definidas no catálogo que pertencem a um determinado uuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 7. A visão CHECK_CONSTRAINTS contém uma linha para cada restrição CHECK no banco de dados corrente. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.CHECK_CONSTRAINTS é baseada nas tabelas do sistema sysobjects e syscomments. SQL Server Books Online (N. do T.) 8. A visão COLUMN_DOMAIN_USAGE identifica as colunas definidas neste catálogo dependentes de um domínio definido neste catálogo, e que pertencem a um usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 9. O rowset COLUMN_DOMAIN_USAGE identifica as colunas definidas no catálogo dependentes de um domínio definido no catálogo, e que pertencem a um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/enus/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 10. A visão COLUMN_DOMAIN_USAGE contém uma linha para cada coluna, no banco de dados corrente, que possui um tipo de dado definido pelo usuário. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.COLUMN_DOMAIN_USAGE é baseada nas tabelas do sistema sysobjects, syscolumns e systypes. SQL Server Books Online (N. do T.) 11. O rowset COLUMN_PRIVILEGES identifica os privilégios em colunas de tabelas definidos no catálogo, que estão disponíveis para, ou foram concedidos por, um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/enus/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 12. A visão COLUMN_PRIVILEGES contém uma linha para cada coluna com privilégio concedido por, ou para, o usuário corrente no banco de dados corrente. A visão INFORMATION_SCHEMA.COLUMN_PRIVILEGES baseada nas tabelas do sistema sysprotects, sysobjects e syscolumns. SQL Server Books Online (N. do T.) 13. A visão COLUMNS identifica as colunas das tabelas definidas neste catálogo que podem ser acessadas por um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQLJuly 30, 1992 (N. do T.) 14. O rowset COLUMNS identifica as colunas das tabelas (incluindo as visões) definidas no catálogo que podem ser acessadas por um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 15. A visão COLUMNS contém uma linha para cada coluna que pode ser acessada pelo usuário corrente no banco de dados corrente. A visão INFORMATION_SCHEMA.COLUMNS é baseada nas tabelas do sistema sysobjects, spt_data type_info, systypes, syscolumns, syscomments, sysconfigures e syscharsets. SQL Server Books Online (N. do T.) 16. A visão CONSTRAINT_COLUMN_USAGE identifica as colunas utilizadas por restrições referenciais, restrições de unicidade, restrições de verficação e asserções definidas neste catálogo e que pertencem a um
499
determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 17. O rowset CONSTRAINT_COLUMN_USAGE identifica todas as colunas utilizadas por restrições referenciais, restrições de unicidade, restrições de verificação e asserções definidas no catálogo, e que pertencem a um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 18. A visão CONSTRAINT_COLUMN_USAGE contém uma linha para cada coluna, no banco de dados corrente, que possui uma restriçao definida nela. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE é baseada nas tabelas do sistema sysobjects, syscolumns e systypes. SQL Server Books Online (N. do T.) 19. A visão CONSTRAINT_TABLE_USAGE identifica as tabelas utilizadas por restrições referenciais, restrições de unicidade, restrições de verificação e asserções, definidas neste catálogo e que pertencem a um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQLJuly 30, 1992 (N. do T.) 20. O rowset CONSTRAINT_TABLE_USAGE identifica as tabelas utilizadas por restrições referenciais, restrições de unicidade, restrições de verificação e asserções que estão definidas no catálogo, e que pertencem a um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 21. A visão CONSTRAINT_TABLE_USAGE contém uma linha para cada tabela, no banco de dados corrente, que possui uma restrição definida nela. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE é baseada na tabela do sistema sysobjects. SQL Server Books Online (N. do T.) 22. A tabela DOMAIN_CONSTRAINTS possui uma linha para cada restrição de domínio associada com o domínio. Contém, de fato, a representação dos descritores de restrição do domínio. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 23. A visão DOMAIN_CONSTRAINTS contém uma linha para cada tipo de dado definido por usuário, que pode ser acessado pelo usuário corrente no banco de dados corrente, com uma regra ligada ao mesmo. A visão INFORMATION_SCHEMA.DOMAIN_CONSTRAINTS é baseada nas tabelas do sistema sysobjects e systypes. SQL Server Books Online (N. do T.) 24. A visão DOMAINS identifica os domínios definidos neste catálogo que podem ser acessados por um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 25. A visão DOMAINS contém uma linha para cada tipo de dado definido por usuário, que pode ser acessado pelo usuário corrente no banco de dados corrente. A visão INFORMATION_SCHEMA.DOMAINS é baseada nas tabelas do sistema spt_data type_info, systypes, syscomments, sysconfigures e syscharsets. SQL Server Books Online (N. do T.) 26. A visão KEY_COLUMN_USAGE identifica as colunas definidas neste catálogo restringidas como chave por um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 27. O rowsetKEY_COLUMN_USAGE identifica as colunas definidas no catálogo restringidas como chave por um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 28. A visão KEY_COLUMN_USAGE contém uma linha para cada coluna no banco de dados corrente que é restringida por uma chave. Esta visão do esquema de informações retorna informações sobre objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.KEY_COLUMN_USAGE é
500
baseada nas tabelas do sistema sysobjects, syscolumns, sysreferences, spt_values e sysindexes. SQL Server Books Online (N. do T.) 29. A visão PARAMETERS contém uma linha para cada parâmetro de função ou de procedimento armazenado definido por usuário, que pode ser acessado pelo usuário corrente no banco de dados corrente. Para as funções, esta visão também retorna uma linha com informações sobre o valor retornado. A visão INFORMATION_SCHEMA.PARAMETERS é baseada nas tabelas do sistema sysobjects e syscolumns. SQL Server Books Online (N. do T.) 30. A visão REFERENTIAL_CONSTRAINTS identifica as restrições referenciais definidas neste catálogo que pertencem a um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 31. O rowset REFERENTIAL_CONSTRAINTS identifica as restrições referenciais definidas no catálogo que pertencem a um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 32. A visão REFERENTIAL_CONSTRAINTS contém uma linha para cada restrição de chave estrangeira no banco de dados corrente. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS é baseada nas tabelas do sistema sysreferences, sysindexes e sysobjects. SQL Server Books Online (N. do T.) 33. A visão ROUTINES contém uma linha para cada procedimento armazenado e função que pode ser acessada pelo usuário corrente no banco de dados corrente. As colunas que descrevem o valor retornado se aplicam apenas às funções. Para os procedimentos armazenados estas colunas têm o valor NULL. A visão INFORMATION_SCHEMA.ROUTINES é baseada nas tabelas do sistema sysobjects e syscolumns. SQL Server Books Online (N. do T.) 34. O rowsetSCHEMATA identifica os esquemas que pertencem a um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/enus/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 35. A visão SCHEMATA contém uma linha para cada banco de dados com permissão para o usuário corrente. A visão INFORMATION_SCHEMA.SCHEMATA é baseada nas tabelas do sistema sysdatabases, sysconfigures e syscharsets. SQL Server Books Online (N. do T.) 36. A visão SQL_LANGUAGES identifica os níveis de conformidade, opções e dialetos suportados pela implementação de processamento de dados SQL definida neste catálogo. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 37. O rowset SQL_LANGUAGES identifica os níveis de conformidade, opções e dialetos suportados pela implementação de processamento de dados SQL definida no catálogo. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/enus/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 38. A visão TABLE_CONSTRAINTS identifica as restrições de tabela definidas neste catálogo e que pertencem a um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 39. O rowset TABLE_CONSTRAINTS identifica as restrições de tabela definidas no catálogo que pertencem a um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 40. A visão TABLE_CONSTRAINTS contém uma linha para cada restrição de tabela no banco de dados corrente. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.TABLE_CONSTRAINTS é baseada na tabela do sistema sysobjects. SQL Server Books Online (N. do T.) 41. A tabela TABLE_PRIVILEGES possui uma linha para cada descritor de privilégio de tabela. Contém, de fato, a representação dos descritores de privilégio de tabela. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.)
501
42. O rowset TABLE_PRIVILEGES identifica os privilégios em tabelas definidos no catálogo, que estão disponíveis para, ou foram concedidos por, um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/enus/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 43. A visão TABLE_PRIVILEGES contém uma linha para cada privilégio de tabela concedido para, ou pelo, usuário corrente no banco de dados corrente. A visão INFORMATION_SCHEMA.TABLE_PRIVILEGES é baseada nas tabelas do sistema sysprotects e sysobjects. SQL Server Books Online (N. do T.) 44. A visão TABLES identifica as tabelas definidas neste catálogo que podem ser acessadas por um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 45. O rowset TABLES identifica todas as tabelas (incluindo as visões) definidas no catálogo que podem ser acessadas por um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 46. A visão TABLES contém uma linha para cada tabela do banco de dados corrente na qual o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.TABLES é baseada na tabela do sistema sysobjects. SQL Server Books Online (N. do T.) 47. A visão USAGE_PRIVILEGES identifica os privilégios USAGE em objetos definidos neste catálogo, que estão disponíveis para, ou foram concedidos por, um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 48. O rowset USAGE_PRIVILEGES identifica os privilégios USAGE em objetos definidos no catálogo, que estão disponíveis para, ou foram concedidos por, um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/enus/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 49. A visão VIEW_COLUMN_USAGE identifica as colunas que as visões definidas neste catálogo e que pertencem a um determinado usuário são dependentes. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 50. O rowset VIEW_COLUMN_USAGE identifica as colunas que as visões definidas no catálogo, e que pertencem a um determinado usuário, são dependentes. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 51. A visão VIEW_COLUMN_USAGE contém uma linha para cada coluna, no banco de dados corrente, usada em uma definição de visão. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.VIEW_COLUMN_USAGE é baseada nas tabelas do sistema sysobjects e sysdepends. SQL Server Books Online (N. do T.) 52. A tabela VIEW_TABLE_USAGE possui uma linha para cada tabela referenciada na expressão de consulta da visão. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 53. O rowset VIEW_TABLE_USAGE identifica as tabelas que as visões definidas no catálogo, e que pertencem a um determinado usuário, dependem. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 54. A visão VIEW_TABLE_USAGE contém uma linha para cada tabela, no banco de dados corrente, usada em uma visão. Esta visão do esquema de informações retorna informações sobre os objetos que o usuário corrente possui permissões. A visão INFORMATION_SCHEMA.VIEW_TABLE_USAGE é baseada nas tabelas do sistema sysobjects e sysdepends. SQL Server Books Online (N. do T.) 55. A visão VIEWS identifica as visões definidas neste catálogo que podem ser acessadas por um determinado usuário. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.)
502
56. O rowset VIEWS identifica as visões definidas no catálogo que podem ser acessadas por um determinado usuário. Microsoft OLE DB Programmer's Reference (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbschema_rowsets.asp) (N. do T.) 57. A visão VIEWS contém uma linha para cada visão que pode ser acessada pelo usuário corrente no banco de dados corrente. A visão INFORMATION_SCHEMA.VIEWS é baseada nas tabelas do sistema sysobjects e syscomments. SQL Server Books Online (N. do T.)
503
V. Programação servidor Esta parte diz respeito à extensão das funcionalidades do servidor através de funções, tipos de dado, gatilhos, etc. definidos pelo usuário. Estes tópicos são avançados e, provavelmente, somente deverão ser estudados após as demais partes da documentação do PostgreSQL para usuários tiver sido compreendida. Nesta parte também estão descritas as linguagens de programação do lado servidor disponíveis na distribuição do PostgreSQL, assim como questões gerais a respeito das linguagens de programação do lado servidor. Estas informações são úteis apenas para os leitores que tenham lido ao menos os primeiros capítulos desta parte.
504
Capítulo 33. Estendendo o SQL Nas próximas seções será mostrado como se pode estender a linguagem de comandos SQL do PostgreSQL pela adição de: • funções (começando na Seção 33.3) • agregações (começando na Seção 33.9) • tipos de dado (começando na Seção 33.10) • operadores (começando na Seção 33.11) • classes de operador para índices (começando na Seção 33.13)
33.1. Como funciona a extensibilidade O PostgreSQL é extensível, porque sua operação é dirigida pelo catálogo (catalog-driven). Se estiver familiarizado com sistemas de banco de dados relacionais, com certeza você sabe que estes armazenam informações sobre bancos de dados, tabelas, colunas, etc., no que é comumente conhecido por catálogos do sistema (Alguns sistemas chamam de dicionário de dados e vem de catálogos do sistema). Os catálogos são vistos pelo usuário como qualquer outra tabela, mas o SGBD armazena suas informações internas nestas tabelas. Uma diferença chave entre o PostgreSQL e os sistemas de banco de dados relacionais comuns é que o PostgreSQL armazena muito mais informação em seus catálogos: não apenas informações sobre tabelas e colunas, mas também informações sobre tipos de dados, funções, métodos de acesso, etc. Estas tabelas podem ser modificadas pelo usuário e, uma vez que as operações do PostgreSQL estão baseadas nestas tabelas, isto significa que o PostgreSQL pode ser estendido pelos usuários. Em comparação, os sistemas de banco de dados convencionais só podem ser estendidos pela alteração dos procedimentos colocados diretamente no código fonte, ou pela carga de módulos escritos especialmente para o SGBD pelo fornecedor. O servidor PostgreSQL pode, além disso, incorporar código escrito pelo usuário através de carregamento dinâmico, ou seja, o usuário pode criar um arquivo contendo código objeto (por exemplo, uma biblioteca compartilhada) implementando um novo tipo de dado ou função, e o PostgreSQL carrega este módulo quando requisitado. O código escrito em SQL é ainda mais simples de ser adicionado ao servidor. Esta capacidade de modificar sua operação em tempo de execução (on the fly) torna o PostgreSQL especialmente adequado para a prototipação rápida de novas aplicações e estruturas de armazenamento.
33.2. O sistema de tipos de dado do PostgreSQL Os tipos de dado do PostgreSQL são divididos em tipos base, tipos compostos e pseudotipos.
33.2.1. Tipos base Os tipos base são aqueles, como o int4, que estão implementados abaixo do nível da linguagem SQL (tipicamente em uma linguagem de baixo nível, como a linguagem C). Correspondem, geralmente, ao que normalmente é conhecido como tipo de dado abstratos (ADT 1 ). O PostgreSQL somente pode operar sobre estes tipos de dado através das funções fornecidas pelo usuário, e somente entende o comportamento destes tipos de dado no grau em que foram descritos pelo usuário. Os tipos de dado base são subdivididos em escalar e matriz. Para cada tipo escalar é criado, automaticamente, um tipo matriz correspondente podendo conter matrizes de tamanho variável deste tipo escalar.
33.2.2. Tipos compostos Os tipos compostos, ou tipos linha, são criados sempre que o usuário cria uma tabela; também é possível definir um tipo composto “autônomo” sem nenhuma tabela associada. Um tipo composto é simplesmente um conjunto de tipos base com nomes de campo associados. O valor de um tipo composto é uma linha ou registro de valores de campo. O usuário pode acessar os campos componentes a partir de consultas SQL.
505
33.2.3. Domínios Um domínio se baseia em um determinado tipo base e, para muitas finalidades, é intercambiável com o seu tipo base. Entretanto, o domínio pode ter restrições limitando os valores válidos a um subconjunto dos valores permitidos pelo tipo base que está por baixo. Os domínios podem ser criados utilizando o comando CREATE DOMAIN do SQL. A criação e uso de domínios não são mostrados neste capítulo.
33.2.4. Pseudotipos Existem alguns poucos “pseudotipos” para finalidades especiais. Os pseudotipos não podem aparecer em colunas de tabela ou em atributos de tipo composto, mas podem ser usados para declarar tipos de dado dos argumentos e dos resultados das funções. Fornecem um mecanismo dentro do sistema de tipos para identificar classes especiais de funções. A Tabela 8-20 relaciona os pseudotipos existentes.
33.2.5. Tipos polimórficos Dois pseudotipos de especial interesse são anyelement e anyarray, chamados coletivamente de tipos polimórficos. Qualquer função declarada utilizando um destes tipos é dita como sendo uma função polimórfica. Uma função polimórfica pode operar sobre muitos tipos de dado diferentes, sendo o tipo de dado específico determinado pelo tipo de dado passado para a função na hora da chamada. Os argumentos e resultados polimórficos estão presos um ao outro, sendo determinados como um tipo de dado específico quando o comando que faz a chamada à função polimórfica é analisado. Para cada posição (tanto argumento como valor retornado) declarada como anyelement pode ser especificado qualquer tipo de dado, mas em uma determinada chamada todas as posições devem ser do mesmo tipo. Cada posição declarada como anyarray pode ter qualquer tipo de dado matriz, mas de forma análoga todas as posições devem ser do mesmo tipo. Havendo posições declaradas como anyarray e outras declaradas como anyelement, o tipo matriz nas posições anyarray devem ser matrizes cujos elementos são do mesmo tipo aparecendo nas posições anyelement. Portanto, quando argumentos de tipo polimórfico são declarados em mais de uma posição, resulta em que apenas certas combinações de tipos de argumento são permitidas. Por exemplo, uma função declarada como foo(anyelement, anyelement) recebe quaisquer dois valores de entrada, desde que ambos sejam do mesmo tipo de dado. Quando o valor retornado por uma função é declarado como sendo do tipo polimórfico, deve haver pelo menos uma posição de argumento que também seja polimórfica, e o tipo de dado fornecido como argumento determina o verdadeiro tipo de dado do resultado para a chamada. Por exemplo, se já não houvesse um mecanismo de índice para matriz, este poderia ser implementado por uma função como subscript(anyarray, integer) returns anyelement. Esta declaração restringe o primeiro argumento como sendo do tipo matriz, permitindo ao analisador inferir o tipo correto do resultado como sendo o tipo do primeiro argumento.
33.3. Funções definidas pelo usuário O PostgreSQL aceita quatro tipos de função: •
funções na linguagem de comando (funções escritas em SQL) (Seção 33.4)
•
funções nas linguagens procedurais (funções escritas em, por exemplo, PL/Tcl ou PL/pgSQL) (Seção 33.5)
•
funções internas (Seção 33.6)
•
funções na linguagem C (Seção 33.7)
Todos os tipos de função aceitam tipos base, tipos compostos, ou alguma combinação destes tipos como argumentos (parâmetros). Além disso, todos os tipos de função podem retornar um tipo base ou um tipo composto.
506
Vários tipos de função podem receber ou retornar certos pseudotipos (tal como os tipos polimórficos), mas as funcionalidades disponíveis podem variar. Consulte a descrição de cada tipo de função para obter mais detalhes. As funções SQL são mais fáceis de serem definidas e, portanto, começaremos por estas. A maior parte dos conceitos apresentados para as funções SQL podem ser transportados para os outros tipos de função. Durante a leitura deste capítulo pode ser útil consultar a página de referência do comando CREATE FUNCTION para compreender melhor os exemplos. Alguns exemplos deste capítulo podem ser encontrados nos arquivos funcs.sql e funcs.c no diretório src/tutorial da distribuição do código fonte do PostgreSQL.
33.4. Funções na linguagem de comando (SQL) As funções SQL executam uma lista arbitrária de declarações SQL, retornando o resultado da última consulta da lista. No caso mais simples (não-conjunto), a primeira linha do resultado da última consulta é retornada. (Tenha em mente que a “primeira linha” de um resultado de várias linhas não é bem definido, a menos que seja utilizada a cláusula ORDER BY). Se acontecer da última consulta não retornar nenhuma linha, é retornado o valor nulo. Como alternativa, a função SQL pode ser declarada como retornando um conjunto, especificando o tipo retornado pela função como SETOF algum_tipo. Neste caso, todas as linhas do resultado da última consulta são retornadas. Abaixo são mostrados mais detalhes. O corpo de uma função SQL deve ser uma lista contendo uma ou mais declarações SQL separadas por pontoe-vírgula (;). Deve ser observado que a sintaxe do comando CREATE FUNCTION requer que o corpo da função esteja envolto por apóstrofos (') e, por isso, os apóstrofos utilizados no corpo da função devem ser precedidos por outro caractere apóstrofo ('') ou por uma contrabarra (\'), onde um apóstrofo for desejado. Os argumentos da função SQL podem ser referenciados no corpo da função utilizando a sintaxe $n: $1 se refere ao primeiro argumento, $2 ao segundo, e assim por diante. Se o argumento for de um tipo composto, então a “notação de ponto”, por exemplo, $1.nome, pode ser utilizada para acessar os atributos do argumento.
33.4.1. Funções SQL com tipos base O tipo mais simples possível de função SQL não possui argumentos e simplesmente retorna um tipo base, tal como integer: CREATE FUNCTION um() RETURNS integer AS ' SELECT 1 AS resultado; ' LANGUAGE SQL; SELECT um(); um ----1 (1 linha)
Observe que foi definido um aliás de coluna dentro do corpo da função para o resultado da função (com o nome resultado), mas este aliás de coluna não é visível fora da função. Portanto, o rótulo do resultado é um em vez de resultado. É quase tão fácil quanto isto definir funções SQL que recebem tipos base como argumentos. No exemplo abaixo devem ser observadas as referências feitas aos argumentos dentro da função como $1 e $2: CREATE FUNCTION somar(integer, integer) RETURNS integer AS ' SELECT $1 + $2; ' LANGUAGE SQL; SELECT somar(1, 2) AS resposta;
507
resposta ---------3 (1 linha)
Abaixo está mostrada uma função mais útil, que pode ser utilizada para debitar de uma conta corrente no banco: CREATE FUNCTION tp1 (integer, numeric) RETURNS integer AS ' UPDATE conta_corrente SET saldo = saldo - $2 WHERE numero_da_conta = $1; SELECT 1; ' LANGUAGE SQL;
O usuário pode executar esta função para debitar $100.00 da conta 17, conforme mostrado abaixo: SELECT tf1(17, 100.0);
Provavelmente, na prática seria desejado que a função retornasse um resultado mais útil do que a constante “1” e, portanto, uma definição mais provável seria CREATE FUNCTION tp1 (integer, numeric) RETURNS numeric AS ' UPDATE conta_corrente SET saldo = saldo - $2 WHERE numero_da_conta = $1; SELECT saldo FROM conta_corrente WHERE numero_da_conta = $1; ' LANGUAGE SQL;
que atualiza o saldo e retorna o novo saldo. Qualquer coleção de comandos da linguagem SQL pode ser pego e definido como uma função. Além dos comandos SELECT, podem ser incluídos comandos de modificação de dados (ou seja, INSERT, UPDATE e DELETE). Entretanto, o comando final deve ser um SELECT retornando o que foi especificado como tipo retornado pela função. Como alternativa, se for desejado definir uma função SQL que realiza ações mas que não retorna nenhum valor útil, a função pode ser definida como retornando void. Neste caso, o corpo a função não deve terminar por um comando SELECT. Por exemplo: CREATE FUNCTION limpar_emp () RETURNS void AS ' DELETE FROM emp WHERE emp.salario <= 0; ' LANGUAGE SQL; SELECT limpar_emp(); limpar_emp ----------(1 linha)
33.4.2. Funções SQL com tipos compostos Ao ser especificada uma função com argumentos de tipo composto, não pode ser especificado simplesmente o argumento desejado (como foi feito acima com $1 e $2), devendo ser incluído também o atributo do argumento. Por exemplo, supondo que emp seja uma tabela contendo os dados dos empregados e, portanto, também o nome do tipo composto de cada linha da tabela. Abaixo está mostrada a função dobrar_salario que calcula como ficaria o salário de alguém caso fosse dobrado: CREATE TABLE emp ( nome text, salario integer, idade integer, cubiculo point );
508
CREATE FUNCTION dobrar_salario(emp) RETURNS integer AS ' SELECT $1.salario * 2 AS salario; ' LANGUAGE SQL; SELECT nome, dobrar_salario(emp) AS sonho FROM emp WHERE emp.cubiculo ~= point '(2,1)'; nome | sonho ------+------Sam | 2400
Observe a utilização da sintaxe $1.salario para especificar um campo da linha passada como argumento. Observe, também, como o comando SELECT utiliza o nome da tabela indicando toda a linha corrente da tabela como um valor composto. Como alternativa, a linha da tabela pode ser referenciada da seguinte maneira: SELECT nome, dobrar_salario(emp.*) AS sonho FROM emp WHERE emp.cubiculo ~= point '(2,1)';
dando ênfase à natureza de linha. Também é possível construir uma função que retorna um tipo composto. Abaixo está mostrado como exemplo uma função que retorna uma única linha da tabela emp: CREATE FUNCTION novo_empregado() RETURNS emp AS ' SELECT text ''Nenhum'' AS nome, 1000 AS salario, 25 AS idade, point ''(2,2)'' AS cubiculo; ' LANGUAGE SQL;
Neste exemplo foi especificado cada um dos atributos através de um valor constante, mas estas constantes poderiam ser substituídas por qualquer cálculo. Observe dois fatos importantes sobre a definição da função: •
A ordem da lista de seleção da consulta deve ser exatamente a mesma em que as colunas aparecem na tabela associada ao tipo composto (Dar nome às colunas, como foi feito acima, é irrelevante para o sistema).
•
Deve ser feita a conversão de tipo nas expressões para haver correspondência com a definição do tipo composto, ou acontecerá um erro deste tipo: ERRO: função declarada como retornando emp retorna varchar em vez de text para a coluna 1
A função que retorna uma linha (tipo composto) pode ser utilizada como uma função de tabela, conforme descrito abaixo. Também pode ser chamada no contexto de uma expressão SQL, mas somente quando é extraído um único atributo da linha ou passada toda a linha para outra função que aceita o mesmo tipo composto. Abaixo está mostrado um exemplo da extração de um atributo de um tipo linha: SELECT (novo_empregado()).nome; nome -------Nenhum
São necessários os parênteses adicionais para evitar que o analisador se confunda: SELECT novo_empregado().nome; ERRO: erro de sintaxe em ou perto de "." no caractere 23
509
Outra opção é utilizar a notação de função para referenciar o atributo. A forma mais fácil de explicar isto é dizer que pode ser utilizada tanto a notação atributo(tabela) quanto a notação tabela.atributo, indiferentemente: SELECT nome(novo_empregado()); nome -------Nenhum -- isto é o mesmo que: -- SELECT emp.nome AS jovens FROM emp WHERE emp.idade < 30 SELECT nome(emp) AS jovens FROM emp WHERE idade(emp) < 30; jovens ----------Sam
Uma outra maneira de utilizar uma função que retorna uma linha como resultado é declarar uma segunda função que aceita uma linha como argumento, e passar o resultado da primeira função para esta: CREATE FUNCTION obtem_nome(emp) RETURNS text AS 'SELECT $1.nome;' LANGUAGE SQL; SELECT obtem_nome(novo_empregado()); obtem_nome ----------Nenhum (1 linha)
33.4.3. Funções SQL como fontes de tabela Todas as funções SQL podem ser utilizadas na cláusula FROM da consulta, mas esta situação é particularmente útil no caso das funções que retornam tipos compostos. Se a função for definida como retornando um tipo base, a função de tabela produz uma tabela de uma coluna. Se a função for definida como retornando um tipo composto, a função de tabela produz uma coluna para cada atributo do tipo composto. Abaixo segue um exemplo: CREATE INSERT INSERT INSERT
TABLE foo (fooid int, foosubid int, fooname text); INTO foo VALUES (1, 1, 'Joe'); INTO foo VALUES (1, 2, 'Ed'); INTO foo VALUES (2, 1, 'Mary');
CREATE FUNCTION getfoo(int) RETURNS foo AS ' SELECT * FROM foo WHERE fooid = $1; ' LANGUAGE SQL; SELECT *, upper(fooname) FROM getfoo(1) AS t1; fooid | foosubid | fooname | upper -------+----------+---------+------1 | 1 | Joe | JOE (2 linhas)
Conforme mostrado neste exemplo, podem ser utilizadas as colunas do resultado da função da mesma maneira como se fossem colunas de uma tabela comum.
510
Observe que a função somente retornou uma linha. Isto se deve à não utilização do SETOF, que será descrito na próxima seção.
33.4.4. Funções SQL retornando conjuntos Quando uma função SQL é declarada como retornando SETOF algum_tipo, a consulta SELECT no final da função é executada até o fim, e cada linha produzida é retornada como um elemento do conjunto resultado. Esta funcionalidade normalmente é utilizada quando se chama a função na cláusula FROM. Neste caso, cada linha retornada pela função se torna uma linha da tabela vista pela consulta. Por exemplo, assumindo que a tabela foo possui o mesmo conteúdo mostrado acima, então: CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS ' SELECT * FROM foo WHERE fooid = $1; ' LANGUAGE SQL; SELECT * FROM getfoo(1) AS t1;
Resultaria em: fooid | foosubid | fooname -------+----------+--------1 | 1 | Joe 1 | 2 | Ed (2 linhas)
Atualmente as funções que retornam conjuntos também podem ser chamadas na lista de seleção da consulta. Para cada linha que a consulta gera por si própria a função que retorna o conjunto é chamada, e uma linha de saída é gerada para cada elemento do conjunto resultado da função. Observe, entretanto, que esta funcionalidade está obsoleta (deprecated), podendo ser removida em uma versão futura. Abaixo está mostrada, como exemplo, uma função retornando um conjunto colocada na lista de seleção: CREATE FUNCTION listar_filhos(text) RETURNS SETOF text AS 'SELECT nome FROM nodos WHERE pai = $1' LANGUAGE SQL; SELECT * FROM nodos; nome | pai -----------+-------Topo | Filho1 | Topo Filho2 | Topo Filho3 | Topo SubFilho1 | Filho1 SubFilho2 | Filho1 (6 linhas) SELECT listar_filhos('Topo'); listar_filhos -------------Filho1 Filho2 Filho3 (3 linhas) SELECT nome, listar_filhos(nome) FROM nodos;
511
nome | listar_filhos --------+-------------Top | Filho1 Top | Filho2 Top | Filho3 Filho1 | SubFilho1 Filho1 | SubFilho2 (5 linhas)
No último SELECT observe que nenhuma linha de saída é mostrada para Filho2, Filho3, etc. Isto acontece porque listar_filhos retorna um conjunto vazio para estes argumentos e, portanto, nenhuma linha de resultado é gerada.
33.4.5. Funções SQL polimórficas As funções SQL podem ser declaradas como aceitando e retornando os tipos polimórficos anyelement e anyarray. Veja na Seção 33.2.5 uma explicação mais detalhada sobre funções polimórficas. Abaixo está mostrada a função polimórfica constroi_matriz, que constrói uma matriz a partir de elementos com tipo de dado arbitrário: CREATE FUNCTION constroi_matriz(anyelement, anyelement) RETURNS anyarray AS ' SELECT ARRAY[$1, $2]; ' LANGUAGE SQL; SELECT constroi_matriz(1, 2) AS intarray, constroi_matriz('a'::text, 'b') AS textarray; intarray | textarray ----------+----------{1,2} | {a,b} (1 linha)
Observe a utilização da conversão de tipo 'a'::text para especificar que o argumento é do tipo text. Isto é necessário quando o argumento é apenas um literal cadeia de caracteres, uma vez que de outra forma seria tratado como do tipo unknown, e uma matriz de unknown não é um tipo válido. Sem a conversão de tipo aconteceria um erro como o seguinte: ERRO: impossível determinar o tipo para "anyarray"/"anyelement" porque a entrada é do tipo "unknown"
É permitido ter argumentos polimórficos com tipo retornado determinado, mas o contrário não é permitido. Por exemplo: CREATE FUNCTION eh_maior(anyelement, anyelement) RETURNS boolean AS ' SELECT $1 > $2; ' LANGUAGE SQL; SELECT eh_maior(1, 2); eh_maior -----------f (1 linha) CREATE FUNCTION funcao_invalida() RETURNS anyelement AS ' SELECT 1; ' LANGUAGE SQL; ERRO: impossível retornar o tipo de dado do resultado DETALHE: Uma função retornando "anyarray" ou "anyelement" deve ter pelo menos um argumento do mesmo tipo.
512
-- As funções abaixo são válidas (N. do T.) CREATE FUNCTION funcao_valida(anyelement) RETURNS anyelement AS ' SELECT $1' LANGUAGE SQL; SELECT funcao_valida(1); funcao_valida --------------1 (1 linha)
CREATE FUNCTION funcao_valida(anyarray) RETURNS anyarray AS ' SELECT $1' LANGUAGE SQL; SELECT funcao_valida(array [1,2,3]); funcao_valida --------------{1,2,3} (1 linha) -- A função abaixo não é válida (N. do T.) CREATE FUNCTION funcao_invalida(anyelement) RETURNS anyarray AS ' SELECT $1' LANGUAGE SQL; SELECT funcao_invalida(1); ERRO: tipo retornado não corresponde na função declarada como retornando integer[] DETALHE: Tipo retornado é integer. CONTEXTO: função SQL "funcao_invalida" durante a execução
33.5. Funções nas linguagens procedurais As linguagens procedurais não estão construídas dentro do servidor PostgreSQL; são oferecidas como módulos carregáveis. Por favor consulte a documentação da linguagem procedural em questão para obter detalhes sobre sua sintaxe e sobre como o corpo da função é interpretado em cada linguagem. Existem, atualmente, quatro linguagens procedurais disponíveis na distribuição padrão do PostgreSQL: PL/pgSQL, PL/Tcl, PL/Perl e PL/Python. Consulte o Capítulo 36 para obter mais informações. Outras linguagens podem ser definidas pelos usuários. O básico sobre como desenvolver uma nova linguagem procedural é coberto pelo Capítulo 47.
33.6. Funções internas As funções internas são funções escritas em C que foram ligadas estaticamente ao servidor PostgreSQL. O “corpo” da definição da função especifica o nome da função na linguagem C, que não precisa ser o mesmo nome declarado para uso no SQL (Por razões de compatibilidade com versões anteriores, um corpo vazio é aceito significando que o nome da função na linguagem C é o mesmo nome do SQL). Normalmente, todas as funções internas presentes no servidor são declaradas durante a inicialização do agrupamento de bancos de dados (initdb), mas o usuário pode utilizar o comando CREATE FUNCTION para criar nomes adicionais (aliás) para as funções internas. As funções internas são declaradas em CREATE FUNCTION com o nome de linguagem internal. Por exemplo, para criar um aliás para a função sqrt:
513
CREATE FUNCTION raiz_quadrada(double precision) RETURNS double precision AS 'dsqrt' LANGUAGE internal STRICT; SELECT raiz_quadrada(1024); raiz_quadrada --------------32 (1 linha)
(A maioria das funções internas esperam ser declaradas como “strict”) Nota: Nem todas as funções “pré-definidas” são “internas” no sentido acima. Algumas funções prédefinidas são escritas em SQL.
33.7. Funções na linguagem C As funções definidas pelo usuário podem ser escritas em C (ou numa linguagem que possa ser tornada compatível com a linguagem C, como C++). Estas funções são compiladas em objetos carregáveis dinamicamente (também chamados de bibliotecas compartilhadas), sendo carregadas pelo servidor conforme haja necessidade. A funcionalidade de carregamento dinâmico é o que distingue as funções na “linguagem C” das funções “internas” --- as convenções de codificação são essencialmente as mesmas para as duas (portanto, a biblioteca padrão de funções internas é uma preciosa fonte de exemplos de codificação para funções definidas pelo usuário na linguagem C). Atualmente, são utilizadas duas convenções diferentes de chamada para as funções em C. A convenção de chamada mais nova, “versão 1”, é indicada escrevendo a chamada de macro PG_FUNCTION_INFO_V1() na função, conforme mostrado abaixo. A ausência desta macro indica uma função no estilo antigo (“versão 0”). O nome da linguagem especificado em CREATE FUNCTION nos dois casos é C. As funções no estilo antigo estão obsoletas por causa de problemas de portabilidade e ausência de funcionalidades, mas ainda são aceitas por motivo de compatibilidade.
33.7.1. Carregamento dinâmico Na primeira vez que uma função definida pelo usuário, em um determinado arquivo objeto carregável, é chamada em uma sessão, o carregador dinâmico carrega o arquivo objeto na memória para que a função possa ser chamada. O comando CREATE FUNCTION para uma função C definida pelo usuário deve, portanto, especificar duas informações para a função: o nome do arquivo objeto carregável, e o nome C (símbolo de ligação) da função especificada a ser chamada dentro do arquivo objeto. Se o nome C não for especificado explicitamente, então é assumido como sendo o mesmo nome da função SQL. O algoritmo a seguir é utilizado para localizar o arquivo objeto compartilhado baseado no nome fornecido no comando CREATE FUNCTION: 1. Se o nome for um caminho absoluto, o arquivo especificado é carregado. 2. Se o nome começar pela cadeia de caracteres $libdir, esta parte é substituída pelo nome do diretório contendo a biblioteca do pacote PostgreSQL, determinado em tempo de construção. 3. Se o nome não contiver a parte do diretório, o arquivo é procurado no caminho especificado pela variável de configuração dynamic_library_path. 4. Senão (o arquivo não foi encontrado no caminho, ou contém a parte de diretório não-absoluta), o carregador dinâmico tenta usar o nome conforme especificado, o que quase certamente não vai ser bemsucedido (Não é confiável depender do diretório de trabalho corrente). Se esta seqüência não tiver sucesso, a extensão de nome de arquivo de biblioteca compartilhada específica da plataforma (geralmente .so) é adicionada ao nome fornecido, e esta seqüência é tentada novamente. Se também não for bem-sucedida, então o carregamento falha.
514
O ID do usuário sob o qual o PostgreSQL executa deve ser capaz de percorrer o caminho até o arquivo que se deseja carregar. Tornar o arquivo ou um diretório de nível mais alto não legível e/ou não executável pelo usuário postgres é um engano comum. De qualquer forma, o nome do arquivo fornecido no comando CREATE FUNCTION é gravado literalmente nos catálogos do sistema e, portanto, se for necessário carregar o arquivo novamente o mesmo procedimento é aplicado. Nota: O PostgreSQL não compila uma função C automaticamente. O arquivo objeto deve ser compilado antes de ser referenciado no comando CREATE FUNCTION. Consulte a Seção 33.7.6 para obter informações adicionais.
Após ter sido utilizado pela primeira vez, o arquivo objeto carregável dinamicamente é mantido em memória. Chamadas posteriores, na mesma sessão, às funções presentes neste arquivo somente envolvem um pequeno trabalho extra de procura na tabela de símbolos. Se for necessário forçar carregar novamente o arquivo objeto, por exemplo após recompilá-lo, deve ser utilizado o comando LOAD, ou iniciada uma nova sessão. Recomenda-se que as bibliotecas compartilhadas fiquem localizadas relativamente à $libdir, ou no caminho de biblioteca dinâmica, simplificando atualizações de versão se a nova instalação estiver em um local diferente. O diretório real representado por $libdir pode ser descoberto através do comando pg_config -pkglibdir 2 . Antes do PostgreSQL versão 7.2, somente podiam ser especificados caminhos absolutos exatos para os arquivos objeto em CREATE FUNCTION. Esta modalidade está obsoleta, uma vez que torna a definição da função não portável sem necessidade. É melhor especificar apenas o nome da biblioteca compartilhada sem caminho nem extensão, e deixar para o mecanismo de procura o fornecimento destas informações.
33.7.2. Tipos base em funções na linguagem C Para saber como escrever funções na linguagem C é necessário saber como o PostgreSQL representa internamente os tipos de dado base, e como estes podem ser passados de/para as funções. Internamente, o PostgreSQL considera o tipo base como um “bloco grande de memória” (blob of memory). Por sua vez, as funções definidas pelo usuário para o tipo definem a maneira como o PostgreSQL pode operar o tipo, ou seja, o PostgreSQL somente armazena e traz os dados do disco, e usa as funções definidas pelo usuário para entrada, processamento e saída dos dados. Os tipos base podem ter um destes três formatos internos: •
passado por valor, tamanho fixo
•
passado por referência, tamanho fixo
•
passado por referência, tamanho variável
Os tipos passados por valor podem ter comprimento de 1, 2 ou 4 bytes apenas (também de 8 bytes, se na máquina sizeof(Datum) for 8). Deve-se tomar cuidado para que os tipos definidos sejam de uma forma que possuam o mesmo tamanho (em bytes) em todas as arquiteturas. Por exemplo, o tipo long é perigoso, porque possui 4 bytes em algumas arquiteturas e 8 bytes em outras, enquanto o tipo int possui 4 bytes na maioria das máquinas Unix. Uma implementação razoável do tipo int4 em uma máquina Unix pode ser: /* inteiro de 4 bytes, passado por valor */ typedef int int4;
Por outro lado, tipos de comprimento fixo de qualquer tamanho podem ser passados por referência. Por exemplo, abaixo está uma amostra de implementação de um tipo do PostgreSQL: /* estrutura de 16 bytes, passada por referência */ typedef struct { double x, y; } Point;
Para estes tipos somente podem ser utilizados ponteiros para passá-los de/para as funções do PostgreSQL. Para retornar o valor de um tipo como este, é alocada a quantidade correta de memória com palloc, preenchida a
515
memória alocada, e retornado um ponteiro para a memória alocada (Também pode ser retornado um valor de entrada que possua o mesmo tipo do valor retornado, retornando o ponteiro para o valor de entrada. Entretanto, nunca deve ser modificado o conteúdo de um valor passado por referência). Por fim, todos os tipos de comprimento variável também devem ser passados por referência. Todos os tipos de comprimento variável devem começar pelo campo de comprimento contendo exatamente 4 bytes, e todos os dados a serem armazenados dentro deste tipo devem estar localizados na memória logo após o campo de comprimento. O campo de comprimento contém o comprimento total da estrutura, ou seja, inclui também o tamanho do próprio campo de comprimento. Como exemplo, pode ser definido o tipo text da seguinte forma: typedef struct { int4 comprimento; char dado[1]; } text;
Obviamente, o campo dado declarado não possui comprimento suficiente para armazenar todas as cadeias de caracteres possíveis. Como é impossível declarar estruturas de tamanho variável em C, dependemos do conhecimento de que o compilador C não verifica o intervalo dos índices das matrizes. Simplesmente é alocada a quantidade necessária de espaço, e depois a matriz é acessada como se tivesse sido declarada com o comprimento correto (Este é um truque comum, que pode ser visto em muitos livros sobre C). Ao se manipular tipos de comprimento variável, deve ser tomado o cuidado de alocar a quantidade correta de memória e definir o campo de comprimento corretamente. Por exemplo, se for desejado armazenar 40 bytes em uma estrutura text, pode ser utilizado um fragmento de código como este: #include "postgres.h" ... char buffer[40]; /* nosso dado de origem */ ... text *destino = (text *) palloc(VARHDRSZ + 40); destino->comprimento = VARHDRSZ + 40; memcpy(destino->dado, buffer, 40); ... VARHDRSZ é o mesmo que sizeof(int4), mas é considerado um bom estilo utilizar a macro VARHDRSZ para
fazer referência ao tamanho adicional para o tipo de comprimento variável. A Tabela 33-1 especifica qual tipo C corresponde a qual tipo SQL, quando se escreve uma função na linguagem C que utiliza um tipo nativo do PostgreSQL. A coluna “Definido em” informa o arquivo de cabeçalho que deve ser incluído para obter a definição do tipo (Na verdade, a definição pode estar em um outro arquivo incluído pelo arquivo informado. Recomenda-se aos usuários aderir à interface definida). Observe que sempre deve ser incluído primeiro postgres.h em todos os arquivos fonte, porque este declara várias outras coisas que serão sempre necessárias de alguma forma. Tabela 33-1. Tipos C equivalentes aos tipos SQL nativos Tipo SQL
Tipo C
Definido em
abstime
AbsoluteTime
utils/nabstime.h
boolean
bool
postgres.h (talvez nativo do compilador)
box
BOX*
utils/geo_decls.h
bytea
bytea*
postgres.h
"char"
char
(nativo do compilador)
character
BpChar*
postgres.h
cid
CommandId
postgres.h
516
Tipo SQL
Tipo C
Definido em
date
DateADT
utils/date.h
smallint (int2)
int2 or int16
postgres.h
int2vector
int2vector*
postgres.h
integer (int4)
int4 or int32
postgres.h
real (float4)
float4*
postgres.h
double precision (float8)
float8*
postgres.h
interval
Interval*
utils/timestamp.h
lseg
LSEG*
utils/geo_decls.h
name
Name
postgres.h
oid
Oid
postgres.h
oidvector
oidvector*
postgres.h
path
PATH*
utils/geo_decls.h
point
POINT*
utils/geo_decls.h
regproc
regproc
postgres.h
reltime
RelativeTime
utils/nabstime.h
text
text*
postgres.h
tid
ItemPointer
storage/itemptr.h
time
TimeADT
utils/date.h
time with time zone
TimeTzADT
utils/date.h
timestamp
Timestamp*
utils/timestamp.h
tinterval
TimeInterval
utils/nabstime.h
varchar
VarChar*
postgres.h
xid
TransactionId
postgres.h
Agora que já foram examinadas todas as estruturas possíveis para os tipos base, podem ser mostrados alguns exemplos verdadeiros de funções.
33.7.3. Convenções de chamada Versão-0 para funções na linguagem C Será apresentado primeiro o “estilo antigo” de convenção de chamada; embora esta modalidade esteja obsoleta, é mais fácil começar por ela. No método versão-0 os argumentos e o resultado da função C são simplesmente declarados no estilo C usual, mas tomando cuidado para utilizar a representação C de cada tipo de dado SQL conforme mostrado acima. Abaixo estão mostrados alguns exemplos:
517
#include "postgres.h" #include <string.h> /* Por valor */ int somar_um(int arg) { return arg + 1; } /* Por referência, comprimento fixo */ float8 * somar_um_float8(float8 *arg) { float8 *resultado = (float8 *) palloc(sizeof(float8)); *resultado = *arg + 1.0; return resultado; } Point * construir_ponto(Point *pontox, Point *pontoy) { Point *novo_ponto = (Point *) palloc(sizeof(Point)); novo_ponto->x = pontox->x; novo_ponto->y = pontoy->y; return novo_ponto; } /* Por referência, comprimento variável */ text * copiar_texto(text *t) { /* * VARSIZE é o tamanho total da estrutura em bytes. */ text *novo_t = (text *) palloc(VARSIZE(t)); VARATT_SIZEP(novo_t) = VARSIZE(t); /* * VARDATA é o ponteiro para a região dos dados da estrutura. */ memcpy((void *) VARDATA(novo_t), /* destino */ (void *) VARDATA(t), /* origem */ VARSIZE(t)-VARHDRSZ); /* quantidade de bytes */ return novo_t; } text * concatenar_texto(text *arg1, text *arg2) { int32 tamanho_novo_texto = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ; text *novo_texto = (text *) palloc(tamanho_novo_texto); VARATT_SIZEP(novo_texto) = tamanho_novo_texto; memcpy(VARDATA(novo_texto), VARDATA(arg1), VARSIZE(arg1)-VARHDRSZ);
518
memcpy(VARDATA(novo_texto) + (VARSIZE(arg1)-VARHDRSZ), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ); return novo_texto; }
Supondo que o código acima tenha sido escrito no arquivo funcs.c e compilado dentro de um objeto compartilhado, as funções poderiam ser definidas no PostgreSQL usando comandos como estes: CREATE FUNCTION somar_um(integer) RETURNS integer AS 'DIRETÓRIO/funcs', 'somar_um' LANGUAGE C STRICT; -- observe a sobrecarga do nome de função SQL "somar_um" CREATE FUNCTION somar_um(double precision) RETURNS double precision AS 'DIRETÓRIO/funcs', 'somar_um_float8' LANGUAGE C STRICT; CREATE FUNCTION construir_ponto(point, point) RETURNS point AS 'DIRETÓRIO/funcs', 'construir_ponto' LANGUAGE C STRICT; CREATE FUNCTION copiar_texto(text) RETURNS text AS 'DIRETÓRIO/funcs', 'copiar_texto' LANGUAGE C STRICT; CREATE FUNCTION concatenar_texto(text, text) RETURNS text AS 'DIRETÓRIO/funcs', 'concatenar_texto', LANGUAGE C STRICT;
Neste caso, DIRETÓRIO representa o diretório do arquivo de biblioteca compartilhada (por exemplo, o diretório do tutorial do PostgreSQL que contém o código dos exemplos utilizados nesta seção) (Um estilo melhor seria utilizar apenas 'funcs' na cláusula AS, após adicionar DIRETÓRIO ao caminho de procura. Em todo caso, pode ser omitida a extensão específica do sistema para a biblioteca compartilhada, normalmente .so ou .sl). Observe que as funções foram especificadas como “strict”, significando que o sistema deve assumir, automaticamente, um resultado nulo se algum valor de entrada for nulo. Fazendo assim, evitamos a necessidade de verificar entradas nulas no código da função. Sem isto, haveria necessidade de verificar os valores nulos explicitamente como, por exemplo, verificando a existência de um ponteiro nulo para cada argumento passado por referência (Para os argumentos passados por valor, não haveria nem como verificar!). Embora esta convenção de chamada seja simples de usar, não é muito portável; em algumas arquiteturas existem problemas ao passar tipos de dado menores que int desta forma. Também, não existe nenhuma forma simples de retornar um resultado nulo, nem para lidar com argumentos nulos de alguma outra forma que não seja fazendo a função estrita. A convenção versão-1, apresentada a seguir, elimina estas objeções.
33.7.4. Convenções de chamada Versão-1 para as funções na linguagem C A convenção de chamada versão-1 se baseia em macros que suprimem a maior parte da complexidade da passagem de argumentos e resultados. A declaração C de uma função versão-1 é sempre Datum nome_da_função(PG_FUNCTION_ARGS)
Além disso, a chamada de macro PG_FUNCTION_INFO_V1(nome_da_função);
deve aparecer no mesmo arquivo fonte (por convenção é escrita logo antes da própria função). Esta chamada de macro não é necessária para as funções na linguagem internal, uma vez que o PostgreSQL assume que todas as funções internas usam a convenção versão-1. Entretanto, é requerido nas funções carregadas dinamicamente.
519
Em uma função versão-1, cada argumento é trazido utilizando a macro PG_GETARG_xxx() correspondente ao tipo de dado do argumento, e o resultado é retornado utilizando a macro PG_RETURN_xxx() para o tipo retornado. PG_GETARG_xxx() recebe como argumento o número do argumento da função a ser trazido, contado a partir de 0. PG_RETURN_xxx() recebe como argumento o valor a ser retornado. Abaixo estão mostradas as mesmas funções vistas acima, codificadas no estilo versão-1: #include "postgres.h" #include <string.h> #include "fmgr.h" /* Por valor */ PG_FUNCTION_INFO_V1(somar_um); Datum somar_um(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); PG_RETURN_INT32(arg + 1); } /* Por referência, comprimento fixo */ PG_FUNCTION_INFO_V1(somar_um_float8); Datum somar_um_float8(PG_FUNCTION_ARGS) { /* As macros para FLOAT8 escondem sua natureza de passado por referência. */ float8 arg = PG_GETARG_FLOAT8(0); PG_RETURN_FLOAT8(arg + 1.0); } PG_FUNCTION_INFO_V1(construir_ponto); Datum construir_ponto(PG_FUNCTION_ARGS) { /* Aqui a natureza de passado por referência de Point não é escondida. */ Point *pontox = PG_GETARG_POINT_P(0); Point *pontoy = PG_GETARG_POINT_P(1); Point *novo_ponto = (Point *) palloc(sizeof(Point)); novo_ponto->x = pontox->x; novo_ponto->y = pontoy->y; PG_RETURN_POINT_P(novo_ponto); } /* Por referência, comprimento variável */ PG_FUNCTION_INFO_V1(copiar_texto); Datum copiar_texto(PG_FUNCTION_ARGS) { text *t = PG_GETARG_TEXT_P(0); /*
520
* VARSIZE é o tamanho total da estrutura em bytes. */ text *novo_t = (text *) palloc(VARSIZE(t)); VARATT_SIZEP(novo_t) = VARSIZE(t); /* * VARDATA é o ponteiro para a região dos dados da estrutura. */ memcpy((void *) VARDATA(novo_t), /* destino */ (void *) VARDATA(t), /* origem */ VARSIZE(t)-VARHDRSZ); /* quantidade de bytes */ PG_RETURN_TEXT_P(novo_t); } PG_FUNCTION_INFO_V1(concatenar_texto); Datum concatenar_texto(PG_FUNCTION_ARGS) { text *arg1 = PG_GETARG_TEXT_P(0); text *arg2 = PG_GETARG_TEXT_P(1); int32 tamanho_novo_texto = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ; text *novo_texto = (text *) palloc(tamanho_novo_texto); VARATT_SIZEP(novo_texto) = tamanho_novo_texto; memcpy(VARDATA(novo_texto), VARDATA(arg1), VARSIZE(arg1)-VARHDRSZ); memcpy(VARDATA(novo_texto) + (VARSIZE(arg1)-VARHDRSZ), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ); PG_RETURN_TEXT_P(novo_texto); }
Os comandos CREATE FUNCTION são os mesmos das funções versão-0 equivalentes. À primeira vista, a convenção de codificação versão-1 pode parecer apenas um obscurantismo sem sentido. Entretanto, oferece várias melhorias porque as macros podem esconder detalhes desnecessários. Como exemplo podemos citar a codificação de somar_um_float8, onde não é mais necesário se preocupar com float8 ser um tipo passado por referência. Outro exemplo são as macros GETARG para tipos de comprimento variável, que permitem trazer valores “toasted” (comprimidos ou fora de linha) de forma mais eficiente. Uma grande melhoria nas funções versão-1 é o tratamento melhor das entradas e resultados nulos. A macro PG_ARGISNULL(n) permite à função testar se cada um dos valores de entrada é nulo (obviamente, só é necessário nas função não declaradas como “strict”). Nas macros PG_GETARG_xxx() os argumentos de entrada são contados a partir de zero. Observe que deve ser evitado executar PG_GETARG_xxx() até que tenha
sido constatado que o argumento não é nulo. Para retornar um resultado nulo deve ser executado PG_RETURN_NULL(); que funciona tanto nas funções estritas como não estritas. Outra opções fornecidas para a interface no novo estilo são duas variantes das macros PG_GETARG_xxx(). A primeira delas, PG_GETARG_xxx_COPY() guarante retornar uma cópia do argumento especificado onde é possível escrever com segurança (As macros comuns, algumas vezes, retornam um ponteiro para um valor que está fisicamente armazenado em uma tabela e, portanto, não é possível escrever neste local. A utilização das macros PG_GETARG_xxx_COPY() garante ser possível escrever no resultado). A segunda variante consiste nas macros PG_GETARG_xxx_SLICE() que recebem três parâmetros. O primeiro é o número do argumento da função (como acima). O segundo e o terceiro são o deslocamento e o comprimento do segmento a ser retornado. Os deslocamentos são contados a partir de zero, e um comprimento negativo requer que o restante do valor seja retornado. Estas macros proporcionam um acesso mais eficiente às partes de valores grandes, caso estes possuam um tipo de armazenamento “external” (O tipo de armazenamento de uma coluna pode ser especificado utilizando ALTER TABLE nome_da_tabela ALTER COLUMN nome_da_coluna SET STORAGE tipo_de_armazenamento. O tipo_de_armazenamento é um entre plain, external, extended ou main). Por fim, as convenções de chamada de função versão-1 tornam possível retornar “conjuntos” (set) como resultados (Seção 33.7.9), implementar funções de gatilho (Capítulo 35) e tratadores de chamada de linguagem
521
procedural (Capítulo 47). Também, o código versão-1 é mais portável do que o versão-0, porque não quebra as restrições do protocolo de chamada de função padrão da linguagem C. Para obter mais informações veja o arquivo src/backend/utils/fmgr/README na distribuição do código fonte.
33.7.5. Escrever código Antes de passar para os tópicos mais avançados, devem ser mostradas algumas regras de codificação para funções escritas na linguagem C no PostgreSQL. Embora seja possível carregar funções escritas em outras linguagens diferentes da linguagem C no PostgreSQL, geralmente é difícil (quando não é impossível) porque as outras linguagens, como C++, FORTRAN e Pascal, geralmente não seguem a mesma convenção de chamada da linguagem C. Ou seja, as outras linguagens não passam argumentos e retornam os valores das funções da mesma maneira. Por este motivo, será assumido que suas funções escritas na linguagem C são realmente escritas em C. As regras básicas para construir funções na linguagem C são as seguintes: •
Utilizar pg_config --includedir-server para descobrir onde os arquivos de cabeçalho do servidor PostgreSQL estão instalados no sistema (ou no sistema utilizado pelos seus usuários) 3 . Esta opção existe a partir do PostgreSQL 7.2. Para o PostgreSQL 7.1 deve ser utilizada a opção --includedir (o comando pg_config termina com status diferente de zero quando encontra uma opção desconhecida). Para as versões anteriores a 7.1 você deve descobrir por si próprio, mas como estas versões são anteriores à introdução das convenções de chamada corrente, não é provável que se deseje dar suporte a estas versões.
•
Para alocar memória devem ser utilizadas as funções palloc e pfree do PostgreSQL, em vez das funções correspondentes da biblioteca C malloc e free. A memória alocada por palloc é liberada automaticamente ao término de cada transação, evitando perda de memória.
•
Os bytes das estruturas devem ser sempre zerados utilizando memset. Se isto não for feito, ficará difícil suportar índices hash ou junções hash, uma vez que devem ser pegos somente os bits significativos da estrutura de dados para calcular o hash. Mesmo se inicializando todos os campos da estrutura, pode haver preenchimento de alinhamento (buracos na estrutura) contendo sujeira.
•
A maior parte dos tipos internos do PostgreSQL estão declarados em postgres.h, enquanto as interfaces de gerência de função (PG_FUNCTION_ARGS, etc.) estão em fmgr.h, portanto é necessário incluir ao menos estes dois arquivos. Por motivo de portabilidade é melhor incluir primeiro postgres.h, antes de qualquer outro arquivo de cabeçalho do sistema ou do usuário. Ao incluir postgres.h também são incluídos elog.h e palloc.h.
•
Os nomes dos símbolos definidos dentro dos arquivos objeto não devem conflitar entre si ou com os símbolos definidos no executável do servidor PostgreSQL. As funções e variáveis deverão ser renomeadas se aparecerem mensagens de erro neste sentido.
•
Compilar e ligar o código objeto para que possa ser carregado dinamicamente no PostgreSQL sempre requer sinalizadores especiais. Veja a Seção 33.7.6 para obter uma explicação detalhada sobre como isto é feito no seu sistema operacional em particular.
33.7.6. Compilar e ligar as funções carregadas dinamicamente Antes que as funções para estender o PostgreSQL escritas em C possam ser utilizadas, estas funções precisam ser compiladas e ligadas de uma forma especial para produzir um arquivo que possa ser carregado dinamicamente pelo servidor. Para ser preciso, uma biblioteca compartilhada precisa ser criada. Para obter informações além das contidas nesta seção deve ser lida a documentação do sistema operacional, em particular as páginas do manual do compilador C, gcc, e do editor de ligação, ld. Além disso, o código fonte do PostgreSQL contém vários exemplos funcionais no diretório contrib. Entretanto, a dependência destes exemplos torna os módulos dependentes da disponibilidade do código fonte do PostgreSQL. Criar bibliotecas compartilhadas geralmente é análogo a ligar executáveis: primeiro os arquivos fonte são compilados em arquivos objetos e, então, os arquivos objeto são ligados. Os arquivos objeto precisam ser criados como código independente de posição o que (PIC), conceitualmente significa que podem ser colocados em uma posição de memória arbitrária ao serem carregados pelo executável (Os arquivos objeto destinados a executáveis geralmente não são compilados deste modo). O comando para ligar uma biblioteca compartilhada
522
contém sinalizadores especiais para distinguir da ligação de um executável. --- Ao menos esta é a teoria. Em alguns sistemas a prática é muito mais feia. Nos exemplos a seguir é assumido que o código fonte está no arquivo foo.c e que será criada a biblioteca compartilhada foo.so. O arquivo objeto intermediário se chama foo.o a não ser que seja dito o contrário. A biblioteca compartilhada pode conter mais de um arquivo objeto, mas aqui é utilizado apenas um arquivo. BSD/OS O sinalizador do compilador para criar PIC é -fpic. O sinalizador do ligador para criar biblioteca compartilhada é -shared. gcc -fpic -c foo.c ld -shared -o foo.so foo.o
Isto se aplica desde a versão 4.0 do BSD/OS. FreeBSD O sinalizador do compilador para criar PIC é -fpic. Para criar bibliotecas compartilhadas o sinalizador do compilador é -shared. gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
Isto se aplica desde a versão 3.0 do FreeBSD. HP-UX O sinalizador do compilador do sistema para criar PIC é +z. Quando se utiliza o GCC é -fpic. O sinalizador do ligador para criar biblioteca compartilhada é -b. Portanto cc +z -c foo.c
ou gcc -fpic -c foo.c
e depois ld -b -o foo.sl foo.o
O HP-UX utiliza a extensão .sl para bibliotecas compartilhadas, diferentemente da maioria dos outros sistemas. IRIX PIC é o padrão, nenhum sinalizador especial do compilador é necessário. O sinalizador do ligador para criar biblioteca compartilhada é -shared. cc -c foo.c ld -shared -o foo.so foo.o
Linux O sinalizador do compilador para criar PIC é -fpic. Em agumas situações em algumas plataformas deve ser utilizado -fPIC se -fpic não funcionar. Consulte o manual do GCC para obter mais informações. O sinalizador do compilador para criar a biblioteca compartilhada é -shared. Um exemplo completo se parece com: cc -fpic -c foo.c cc -shared -o foo.so foo.o
MacOS X Abaixo segue um exemplo. É assumido que as ferramentas de desenvolvimento estão instaladas. cc -c foo.c cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o
523
NetBSD O sinalizador do compilador para criar PIC é -fpic. Para os sistemas ELF, o compilador com o sinalizador -shared é utilizado para ligar as bibliotecas compartilhadas. Nos sistemas antigos, não-ELF, é utilizado ld -Bshareable. gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
OpenBSD O sinalizador do compilador para criar PIC é -fpic. É utilizado ld -Bshareable para ligar bibliotecas compartilhadas. gcc -fpic -c foo.c ld -Bshareable -o foo.so foo.o
Solaris O sinalizador do compilador para criar PIC é -KPIC quando é utilizado o compilador da Sun, e -fpic quando é utilizado o GCC. Para ligar bibliotecas compartilhadas o sinalizador do compilador é -G para os dois compiladores ou, como alternativa, -shared quando é utilizado o GCC. cc -KPIC -c foo.c cc -G -o foo.so foo.o
ou gcc -fpic -c foo.c gcc -G -o foo.so foo.o
Tru64 UNIX PIC é o padrão e, portanto, o comando para compilar é o usual. É utilizado ld com sinalizadores especiais para ligar: cc -c foo.c ld -shared -expect_unresolved '*' -o foo.so foo.o
O mesmo procedimento é empregado quando GCC é utilizado no lugar do compilador do sistema; nenhuma opção especial é necessária. UnixWare O sinalizador do compilador para criar PIC é -K PIC quando é utilizado o compilador da SCO, e -fpic no GCC. Para ligar bibliotecas compartilhadas, o sinalizador do compilador é -G quando é utilizado o compilador da SCO e -shared no GCC. cc -K PIC -c foo.c cc -G -o foo.so foo.o
ou gcc -fpic -c foo.c gcc -shared -o foo.so foo.o Dica: Se estiver achando muito complicado, poderá levar em consideração utilizar a GNU Libtool (http://www.gnu.org/software/libtool/), que esconde as diferenças entre as plataformas atrás de uma interface uniforme.
O arquivo de biblioteca compartilhada produzido pode então ser carregado no PostgreSQL. Ao se especificar o nome do arquivo no comando CREATE FUNCTION, deve ser especificado o nome do arquivo da biblioteca compartilhada, e não do arquivo objeto intermediário. Observe que a extensão de biblioteca compartilhada padrão do sistema (geralmente .so ou .sl) pode ser omitida no comando CREATE FUNCTION, e normalmente deve ser omitida para uma melhor portabilidade. Veja na Seção 33.7.1 onde o servidor espera encontrar os arquivos de biblioteca compartilhada.
524
33.7.7. Argumentos de tipo composto em funções na linguagem C Os tipos compostos não possuem uma arrumação fixa como as estruturas C. As instâncias de um tipo composto podem conter campos nulos. Além disso, os tipos compostos que são parte de uma hierarquia de herança podem possuir campos diferentes dos outros membros da mesma hierarquia de herança. Portanto, o PostgreSQL fornece uma função de interface para acessar os campos dos tipos compostos a partir do C. Suponha que desejamos escrever uma função para responder a consulta SELECT name, c_sobrepago(emp, 1500) AS sobrepago FROM emp WHERE nome = 'Bill' OR nome = 'Sam';
Utilizando as convenções de chamada versão 0, c_sobrepago poderia ser definida como: #include "postgres.h" #include "executor/executor.h"
/* para GetAttributeByName() */
bool c_sobrepago(TupleTableSlot *t, /* a linha corrente de emp */ int32 limite) { bool isnull; int32 salario; salario = DatumGetInt32(GetAttributeByName(t, "salario", &isnull)); if (isnull) return false; return salario > limite; }
Na codificação versão-1, o código acima ficaria parecido com: #include "postgres.h" #include "executor/executor.h"
/* para GetAttributeByName() */
PG_FUNCTION_INFO_V1(c_sobrepago); Datum c_sobrepago(PG_FUNCTION_ARGS) { TupleTableSlot *t = (TupleTableSlot *) PG_GETARG_POINTER(0); int32 limite = PG_GETARG_INT32(1); bool isnull; int32 salario; salario = DatumGetInt32(GetAttributeByName(t, "salario", &isnull)); if (isnull) PG_RETURN_BOOL(false); /* Como alternativa poderia se preferir usar PG_RETURN_NULL() para salário nulo. */ PG_RETURN_BOOL(salario > limite); } GetAttributeByName é a função de sistema do PostgreSQL que retorna atributos da linha especificada. Possui três argumentos: o argumento do tipo TupleTableSlot* passado para a função, o nome do atributo desejado e o parâmetro retornado que informa se o atributo é nulo. GetAttributeByName retorna um valor do tipo Datum que pode ser convertido no tipo de dado adequado utilizando a macro DatumGetXXX() apropriada.
O comando a seguir declara a função c_sobrepago no SQL:
525
CREATE FUNCTION c_sobrepago(emp, integer) RETURNS boolean AS 'DIRETÓRIO/funcs', 'c_sobrepago' LANGUAGE C;
33.7.8. Retorno de linhas (tipos compostos) por funções na linguagem C Para retornar uma linha ou valor de tipo composto por uma função na linguagem C, pode ser utilizada uma API especial que fornece macros e funções que escondem a maior parte da complexidade envolvida na construção de tipos de dado compostos. Para utilizar esta API, deve ser incluído no código fonte: #include "funcapi.h"
O suporte ao retorno de tipos de dado compostos (ou linhas) começa pela estrutura AttInMetadata. Esta estrutura mantém matrizes contendo informações individuais dos atributos, necessárias para criar uma linha a partir de cadeias de caracteres C. A informação contida nesta estrutura é derivada da estrutura TupleDesc, mas é armazenada para evitar processamento redundante em cada chamada à função que retorna conjunto (veja a próxima seção). No caso da função que retorna conjunto a estrutura AttInMetadata deve ser processada uma vez durante a primeira chamada, e salva para ser usada novamente nas próximas chamadas. AttInMetadata também mantém um ponteiro para a TupleDesc original. typedef struct AttInMetadata { /* TupleDesc completa */ TupleDesc tupdesc; /* matriz de tipo de atributo da função de entrada finfo */ FmgrInfo *attinfuncs; /* matriz de tipo do atributo typelem */ Oid *attelems;
}
/* matriz de atributo typmod */ int32 *atttypmods; AttInMetadata;
Para ajudar no preenchimento desta estrutura estão disponíveis diversas funções e macros. Use TupleDesc RelationNameGetTupleDesc(const char *relname)
para obter a TupleDesc para uma relação nomeada, ou TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
para obter a TupleDesc baseada em um OID de tipo. Pode ser utilizado para obter a TupleDesc para um tipo base ou composto. Então AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
retorna um ponteiro para uma estrutura AttInMetadata, inicializada com base na TupleDesc fornecida. AttInMetadata pode ser utilizada em conjunto com cadeias de caracteres C para produzir um valor de linha formado apropriadamente (tupla chamada internamente). Para retornar uma tupla deve ser criado um encaixe (slot) de tupla baseado em TupleDesc. Pode ser utilizado TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc)
para inicializar o encaixe da tupla, ou ser obtido um através de outro (fornecido pelo usuário) meio. O encaixe da tupla é necessário para criar o tipo Datum a ser retornado pela função O mesmo encaixe pode (e deve) ser reutilizado a cada chamada. Após construir a estrutura AttInMetadata,
526
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **valores)
pode ser utilizada para construir a HeapTuple a partir de dados dos usuários fornecidos na forma de cadeias de caracteres C. valores é uma matriz de cadeias de caracteres C, uma para cada atributo da linha retornada. Cada cadeia de caracteres C deve estar na forma esperada pela função de entrada do tipo de dado do atributo. Para retornar o valor nulo para um dos atributos, o ponteiro correspondente na matriz valores deve ser definido como NULL. É necessário chamar esta função novamente para cada linha retornada. A construção da tupla utilizando TupleDescGetAttInMetadata e BuildTupleFromCStrings somente é conveniente quando a função computa naturalmente os valores a serem retornados como textos em cadeias de caractere. Se o código computar naturalmente os valores como um conjunto de valores Datum, deve ser utilizada a função que está por baixo heap_formtuple para converter os valores Datum diretamente na tupla. Ainda serão necessárias TupleDesc e TupleTableSlot, mas não AttInMetadata. Após ter sido construída a tupla a ser retornada pela função, esta deve ser convertida em Datum. Use TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple)
para obter Datum a partir de uma tupla e um encaixe. Este Datum pode ser retornado diretamente se houver intenção de retornar uma única linha, ou pode ser utilizado como o valor de retorno corrente em uma função que retorna conjunto. Na próxima seção é mostrado um exemplo.
33.7.9. Retorno de conjuntos a partir de funções na linguagem C Existe, também, uma API especial que fornece suporte ao retorno de conjuntos (várias linhas) a partir de função na linguagem C. Uma função que retorna conjunto deve seguir as convenções de chamada versão-1. Além disso, os arquivos fonte devem incluir funcapi.h, conforme mostrado acima. Uma função que retorna conjunto (SRF) é chamada uma vez para cada item retornado. A SRF deve, portanto, salvar as informações de estado necessárias para se lembrar do que estava fazendo e retornar o próximo item a cada chamada. A estrutura FuncCallContext é fornecida para ajudar a controlar este processo. Dentro da função, fcinfo->flinfo->fn_extra é utilizado para manter um ponteiro para FuncCallContext entre as chamadas. typedef struct { /* * Número de vezes que foi chamada anteriormente * * call_cntr é inicializada com 0 por SRF_FIRSTCALL_INIT(), e * incrementada toda vez que SRF_RETURN_NEXT() é chamada. */ uint32 call_cntr; /* * OPCIONAL número máximo de chamadas * * max_calls existe apenas por conveniência e sua definição é opcional. * Se não for definida, deve ser fornecida uma forma alternativa * para saber quando a função terminou. */ uint32 max_calls; /* * OPCIONAL ponteiro para o encaixe do resultado * * o encaixe é utilizado para retornar tuplas (ou seja, tipos de dado * compostos), não sendo necessário para retornar tipos de dado base. */ TupleTableSlot *slot;
527
/* * OPCIONAL ponteiro para informações diversas fornecidas pelo usuário * * user_fctx é utilizado como ponteiro para os dados do usuário para * reter informações arbitrárias de contexto entre chamadas à função. */ void *user_fctx; /* * OPCIONAL ponteiro para a estrutura contendo metadados do tipo do * atributo de entrada * * attinmeta é utilizado para retornar tuplas (ou seja, tipos de dado * compostos) não sendo necessário para retornar tipos de dado base. * Somente é necessário quando há intenção de usar * BuildTupleFromCStrings() para criar a tupla a ser retornada. */ AttInMetadata *attinmeta; /* * contexto de memória utilizado para estruturas que devem permanecer * por várias chamadas * * multi_call_memory_ctx é definido por SRF_FIRSTCALL_INIT() e utilizado * por SRF_RETURN_DONE() para limpeza. É o contexto de memória mais * apropriado para qualquer memória a ser reutilizada em várias chamadas * à SRF. */ MemoryContext multi_call_memory_ctx; } FuncCallContext;
Uma SRF utiliza várias funções e macros que manipulam, automaticamente, a estrutura FuncCallContext (e esperam encontrá-la via fn_extra). Use SRF_IS_FIRSTCALL()
para determinar se a função está sendo chamada pela primeira vez ou se está sendo chamada novamente. Na primeira chamada (apenas) use SRF_FIRSTCALL_INIT()
para inicializar FuncCallContext. Em todas as chamadas à função, incluindo a primeira, use SRF_PERCALL_SETUP()
para configurar de forma apropriada para usar FuncCallContext, e limpar os dados retornados deixados pela passagem anterior. Se a função tiver dados a serem retornados, use SRF_RETURN_NEXT(funcctx, resultado)
para retornar a quem chamou (resultado deve ser do tipo Datum, tanto para um único valor quanto para uma tupla preparada conforme descrito acima). Por fim, quando a função terminar de retornar dados, use SRF_RETURN_DONE(funcctx)
para limpar e terminar a SRF. O contexto de memória corrente quando a SRF é chamada é um contexto transiente que é limpo entre as chamadas. Isto significa que não é necessário chamar pfree para tudo que foi alocado usando palloc; vai desaparecer de qualquer forma. Entretanto, se for desejado alocar estrutura de dados que sobrevivam entre as
528
chamadas, é necessário colocá-las em outro lugar. O contexto de memória referenciado por multi_call_memory_ctx é um local apropriado para todos os dados que precisam sobreviver até que a SRF termine sua execução. Na maioria dos casos, isto significa que é necessário comutar para multi_call_memory_ctx ao ser feita a configuração na primeira chamada. Um exemplo de pseudocódigo completo se parece com o seguinte: Datum minha_funcao_retornando_conjunto(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum resultado; MemoryContext contexto_antigo; outras declarações conforme necessário if (SRF_IS_FIRSTCALL()) { funcctx = SRF_FIRSTCALL_INIT(); contexto_antigo = MemoryContextSwitchTo( funcctx->multi_call_memory_ctx); /* Código de configuração de uma única vez aparece aqui: */ código do usuário se retorna tipo composto preparar TupleDesc e, talvez, AttInMetadata obter o encaixe funcctx->encaixe = encaixe; fim-se retorna tipo composto código do usuário MemoryContextSwitchTo(contexto_antigo); } /* Código código do funcctx = código do
de configuração para cada uma das chamadas aparece aqui: */ usuário SRF_PERCALL_SETUP(); usuário
/* esta é apenas uma forma possível de testar se terminou: */ if (funcctx->call_cntr < funcctx->max_calls) { /* Aqui se deseja retornar outro item: */ código do usuário obter o Datum resultado SRF_RETURN_NEXT(funcctx, resultado); } else { /* Aqui terminou o retorno de itens e só é necessário fazer a limpeza: */ código do usuário SRF_RETURN_DONE(funcctx); } }
Um exemplo completo de uma SRF simples retornando um tipo composto se parece com: PG_FUNCTION_INFO_V1(teste_de_passado_por_valor); Datum teste_de_passado_por_valor(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; int call_cntr; int max_calls;
529
TupleDesc TupleTableSlot AttInMetadata
tupdesc; *slot; *attinmeta;
/* código executado apenas na primeira chamada a esta função */ if (SRF_IS_FIRSTCALL()) { MemoryContext contexto_antigo; /* criar o contexto da função para persistência entre chamadas */ funcctx = SRF_FIRSTCALL_INIT(); /* mudar para o contexto de memória apropriado para várias chamadas à função */ contexto_antigo = MemoryContextSwitchTo( funcctx->multi_call_memory_ctx); /* número total de tuplas a serem retornadas */ funcctx->max_calls = PG_GETARG_UINT32(0); /* construir a descrição de tupla para a tupla __teste_de_passado_por_valor */ tupdesc = RelationNameGetTupleDesc("__teste_de_passado_por_valor"); /* alocar um encaixe para a tupla com esta tupdesc */ slot = TupleDescGetSlot(tupdesc); /* atribuir o encaixe ao contexto da função */ funcctx->slot = slot; /* * gerar metadados de atributos necessários posteriormente * para produzir tuplas a partir de cadeias de caractere C */ attinmeta = TupleDescGetAttInMetadata(tupdesc); funcctx->attinmeta = attinmeta; MemoryContextSwitchTo(contexto_antigo); } /* código executado em toda chamada a esta função */ funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; slot = funcctx->slot; attinmeta = funcctx->attinmeta; if (call_cntr < max_calls) { char **values; HeapTuple tuple; Datum resultado;
/* fazer quando há mais a enviar */
/* * Preparar a matriz de valores para armazenamento no encaixe. * Deve ser uma matriz de cadeias de caracteres C a serem * processadas posteriormente pelas funções de entrada do tipo. */ values = (char **) palloc(3 * sizeof(char *)); values[0] = (char *) palloc(16 * sizeof(char)); values[1] = (char *) palloc(16 * sizeof(char));
530
values[2] = (char *) palloc(16 * sizeof(char)); snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1)); snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1)); snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1)); /* construir a tupla */ tuple = BuildTupleFromCStrings(attinmeta, values); /* colocar a tupla dentro do datum */ resultado = TupleGetDatum(slot, tuple); /* limpeza (não é realmente necessário) */ pfree(values[0]); pfree(values[1]); pfree(values[2]); pfree(values); SRF_RETURN_NEXT(funcctx, resultado); } else /* fazer quando não há mais nada deixado */ { SRF_RETURN_DONE(funcctx); } }
O código SQL para declarar esta função é: CREATE TYPE __teste_de_passado_por_valor AS (f1 integer, f2 integer, f3 integer); CREATE OR REPLACE FUNCTION teste_de_passado_por_valor(integer, integer) RETURNS SETOF __teste_de_passado_por_valor AS 'filename', 'teste_de_passado_por_valor' LANGUAGE C IMMUTABLE STRICT;
O diretório contrib/tablefunc na distribuição do código fonte contém mais exemplos de funções que retornam conjunto.
33.7.10. Tipos polimórficos em argumentos e retorno As funções na linguagem C podem ser declaradas aceitando e retornando os tipos polimórficos anyelement e anyarray. Veja a Seção 33.2.5 para obter uma explicação mais detalhada das funções polimórficas. Quando os tipos dos argumentos da função ou do valor retornado são definidos como tipos polimórficos, o autor da função não pode saber antecipadamente com que tipo de dado será chamada, ou usado no retorno. Existem duas rotinas fornecidas em fmgr.h que permitem uma função versão-1 descobrir os tipos de dado verdadeiros de seus argumentos, e o tipo de dado esperado no retorno. As rotinas se chamam get_fn_expr_rettype(FmgrInfo *flinfo) e get_fn_expr_argtype(FmgrInfo *flinfo, int argnum). Retornam o OID do tipo do argumento ou do resultado, ou InvalidOid se a informação não estiver disponível. A estrutura flinfo normalmente é acessada por fcinfo->flinfo. O parâmetro argnum começa por zero. Por exemplo, suponha que se deseje escrever uma função que aceite um único elemento de qualquer tipo, e retorne uma matriz unidimensional deste tipo:
531
PG_FUNCTION_INFO_V1(constroi_matriz); Datum constroi_matriz(PG_FUNCTION_ARGS) { ArrayType *resultado; Oid tipo_do_elemento = get_fn_expr_argtype(fcinfo->flinfo, 0); Datum elemento; int16 typlen; bool typbyval; char typalign; int ndims; int dims[MAXDIM]; int lbs[MAXDIM]; if (!OidIsValid(tipo_do_elemento)) elog(ERROR, "impossível determinar o tipo de dado de entrada"); /* obter o elemento fornecido */ elemento = PG_GETARG_DATUM(0); /* temos uma dimensão */ ndims = 1; /* e um elemento */ dims[0] = 1; /* e o limite inferior é 1 */ lbs[0] = 1; /* obter as informações requeridas sobre o tipo do elemento */ get_typlenbyvalalign(tipo_do_elemento, &typlen, &typbyval, &typalign); /* construir a matriz */ resultado = construct_md_array(&elemento, ndims, dims, lbs, tipo_do_elemento, typlen, typbyval, typalign); PG_RETURN_ARRAYTYPE_P(resultado); }
O camando abaixo declara a função constroi_matriz no SQL: CREATE FUNCTION constroi_matriz(anyelement) RETURNS anyarray AS 'DIRETÓRIO/funcs', 'constroi_matriz' LANGUAGE C STRICT;
Observe a utilização de STRICT; isto é essencial uma vez que código não se importa em testar entrada nula.
33.7.11. Exemplos de funções escritas em C Nota: Esta seção foi escrita pelo tradutor, não fazendo parte do manual original.
Exemplo 33-1. Funções C para cálculo de dígitos verificadores- FEBRABAN Neste exemplo são mostradas duas funções para cálculo do dígito verificador. A primeira função calcula o dígito verificador módulo 11 e a segunda módulo 10. As duas funções são sobrecarregadas (veja a Seção 33.8): recebem um parâmetro, o número, e retornam o dígito verificador; ou recebem dois parâmetros, o número e o dígito verificador, e retornam verdade ou falso caso o dígito esteja correto ou errado, respectivamente. O cálculo do dígito verificador módulo 11 é feito da seguinte forma: os dígitos são multiplicados da direita para a esquerda pela seqüência de 2 a 9, ou seja, por 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, e assim por diante; os resultados do produto dos dígitos pelos valores da seqüência são somados; a soma é dividida por 11, e o resto da divisão é obtido; o dígito verificador é calculado subtraindo o resto de 11; quando o resto for igual a 0 ou 1 o dígito verificador será igual a 0. Segundo o Manual Técnico Operacional - Bloquetos de Cobrança FEBRABAN (http://www.bradesco.com.br/br/pj/conteudo/sol_rec/pdf/manualtecnico.pdf), deve ser utilizado o
532
dígito 1 quando o resto for 0, 10 ou 1. Existem Secretarias de Fazenda onde no cálculo do dígito verificador a seqüência retorna a 2 antes de chegar a 9. Tome cuidado antes de utilizar esta função. O cálculo do dígito verificador módulo 10 é feito da seguinte forma: os dígitos são multiplicados da direita para a esquerda pela seqüência 2, 1, 2, 1, e assim por diante; os “algarismos” dos resultados do produto dos dígitos pelos valores da seqüência são somados individualmente; a soma é dividida por 10, e o resto da divisão é obtido; o dígito verificador é calculado subtraindo o resto de 10; quando o resto for igual a 0 o dígito verificador será igual a 0. Fonte: Manual Técnico Operacional - Bloquetos de Cobrança - FEBRABAN. Existe outra forma de calcular este dígito verificador onde os resultados dos produtos, e não os dígitos dos resultados dos produtos, são somados. Tome cuidado antes de utilizar esta função. Este exemplo mostra o código fonte C da biblioteca compartilhada para cálculo de dígitos verificadores conforme o Manual Técnico Operacional - Bloquetos de Cobrança - FEBRABAN. #include "postgres.h" /* declarações gerais do PostgreSQL */ #include "fmgr.h" /* macros dos argumentos/resultados */ #define VALOR(char) ((char) - '0') #define DIGITO(val) ((val) + '0') #define VARLAST(__PTR) (VARDATA(__PTR) + VARSIZE(__PTR) - VARHDRSZ - 1) /* Protótipo para prevenir contra possíveis advertências do gcc. */ Datum Datum
dv11(PG_FUNCTION_ARGS); dv11dig(PG_FUNCTION_ARGS);
Datum Datum
dv10(PG_FUNCTION_ARGS); dv10dig(PG_FUNCTION_ARGS);
/* * * * * */
Rotina para cálculo do dígito verificador módulo 11. Recebe dois argumentos, número e dígito verificador. Retorna verdade se o dígito verificador estiver correto, ou falso caso contrário.
PG_FUNCTION_INFO_V1(dv11); Datum dv11(PG_FUNCTION_ARGS) { int digito=0, fator=2; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número text *dv = PG_GETARG_TEXT_P(1); // Segundo argumento = dígito verif. /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar dígito verificador não dígito */ if (!isdigit(*VARDATA(dv))) PG_RETURN_NULL(); /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito digito += VALOR(*c) * fator; if (++fator > 9) fator = 2; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 dígito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*VARDATA(dv))); }
533
/* * Rotina para cálculo do dígito verificador módulo 11. * Recebe um argumento, o número. Retorna o dígito verificador. */ PG_FUNCTION_INFO_V1(dv11dig); Datum dv11dig(PG_FUNCTION_ARGS) { int digito=0, fator=2; text *num = PG_GETARG_TEXT_P(0); // Único argumento = número /* Verificar o recebimento de argumento vazio */ if (VARATT_SIZEP(num) == VARHDRSZ) { PG_RETURN_NULL(); } /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito digito += VALOR(*c) * fator; if (++fator > 9) fator = 2; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 dígito = 0 /* Retornar o dígito verificador */ int32 tamanho = VARHDRSZ + sizeof(char); text *resultado = (text *) palloc(tamanho); memset((void *) resultado, 0, tamanho); VARATT_SIZEP(resultado) = tamanho; *VARDATA(resultado) = (char) DIGITO(digito); PG_RETURN_TEXT_P(resultado); } /* * * * * */
Rotina para cálculo do dígito verificador módulo 10 - FEBRABAN Recebe dois argumentos, número e dígito verificador. Retorna verdade se o dígito verificador estiver correto, ou falso caso contrário.
PG_FUNCTION_INFO_V1(dv10); Datum dv10(PG_FUNCTION_ARGS) { int digito=0, fator=2, produto; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número text *dv = PG_GETARG_TEXT_P(1); // Segundo argumento = dígito verif. /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar dígito verificador não dígito */ if (!isdigit(*VARDATA(dv))) PG_RETURN_NULL(); /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito produto = VALOR(*c) * fator; digito+= produto/10 + produto%10; if (--fator < 1) fator = 2; } digito = 10 - ( digito % 10 );
534
if (digito == 10) digito = 0; /* Retornar verdade ou falso */ PG_RETURN_BOOL (digito == VALOR(*VARDATA(dv))); } /* * Rotina para cálculo do dígito verificador módulo 10 - FEBRABAN. * Recebe um argumento, o número. Retorna o dígito verificador. */ PG_FUNCTION_INFO_V1(dv10dig); Datum dv10dig(PG_FUNCTION_ARGS) { int digito=0, fator=2, produto; text *num = PG_GETARG_TEXT_P(0); // Único argumento = número /* Verificar o recebimento de argumento vazio */ if (VARATT_SIZEP(num) == VARHDRSZ) { PG_RETURN_NULL(); } /* Calcular o dígito verificador */ char *c; for (c = VARLAST(num); c >= VARDATA(num); c--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Verificar se é dígito produto = VALOR(*c) * fator; digito+= produto/10 + produto%10; if (--fator < 1) fator = 2; } digito = 10 - ( digito % 10 ); if (digito == 10) digito = 0; /* Retornar o dígito verificador */ int32 tamanho = VARHDRSZ + sizeof(char); text *resultado = (text *) palloc(tamanho); memset((void *) resultado, 0, tamanho); VARATT_SIZEP(resultado) = tamanho; *VARDATA(resultado) = (char) DIGITO(digito); PG_RETURN_TEXT_P(resultado); }
Os exemplos foram elaborados com o arquivo fonte (funcoes.c), o arquivo objeto intermediário (funcoes.o), e o arquivo de biblioteca compartilhada (funcoes.so) colocados em /usr/lib/pgsql/. O código fonte da distribuição do PostgreSQL foi descompactado sob o diretório /root. Com isto, a geração do arquivo de biblioteca compartilhada foi feita usando os comandos: cd /usr/lib/pgsql/ gcc -fpic -c funcoes.c -I /root/postgresql-7.4.1/src/include/ gcc -shared -o funcoes.so funcoes.o
O código SQL para declarar estas funções é: CREATE FUNCTION dv11(text,text) RETURNS boolean AS '$libdir/funcoes', 'dv11' LANGUAGE C STRICT; CREATE FUNCTION dv11(text) RETURNS text AS '$libdir/funcoes', 'dv11dig' LANGUAGE C STRICT; CREATE FUNCTION dv10(text,text) RETURNS boolean AS '$libdir/funcoes', 'dv10' LANGUAGE C STRICT;
535
CREATE FUNCTION dv10(text) RETURNS text AS '$libdir/funcoes', 'dv10dig' LANGUAGE C STRICT;
Utilização das funções com informações retiradas do código de barras de bloquetos de cobrança bancária: SELECT dv11('3419112820459284738210122301001623770000034439','7'); dv11 -----t (1 linha) SELECT dv11('3419112820459284738210122301001623770000034439'); dv11 -----7 (1 linha) SELECT dv10('0063504142','9'); dv10 -----t (1 linha) SELECT dv10('0063504142'); dv10 -----9 (1 linha)
Exemplo 33-2. Funções C para validar o número do CPF e do CNPJ Neste exemplo são mostradas funções para validar o número do CPF e do CNPJ. A primeira função recebe o número do CPF com 11 dígitos, e a segunda recebe o número do CNPJ com 14 dígitos. Ambas retornam o valor booleano verdade se os dígitos verificadores estiverem corretos, ou falso caso contrário. Se o argumento for nulo, não tiver o número de dígitos esperado, ou contiver um dígito não numérico, as funções retornam nulo. #include "postgres.h" /* declarações gerais do PostgreSQL */ #include "fmgr.h" /* macros dos argumentos/resultados */ #define VALOR(char) ((char) - '0') #define DIGITO(val) ((val) + '0') #define VARLAST(__PTR) (VARDATA(__PTR) + VARSIZE(__PTR) - VARHDRSZ - 1) /* Protótipo para prevenir contra possíveis advertências do gcc. */ Datum Datum /* * * * * * * */
cpf(PG_FUNCTION_ARGS); cnpj(PG_FUNCTION_ARGS);
Rotina para validação do CPF. Recebe um argumento, o número do CPF com onze dígitos. Retorna verdade se os dígitos verificadores do CPF estiverem corretos, ou falso caso contrário. Se o argumento for nulo, não tiver 11 dígitos, ou contiver um dígito não numérico, retorna nulo.
536
PG_FUNCTION_INFO_V1(cpf); Datum cpf(PG_FUNCTION_ARGS) { int fator, digito; char *c; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número do CPF /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar se o CPF tem 11 dígitos */ if ( (VARSIZE(num) - VARHDRSZ) != 11 ) { PG_RETURN_NULL(); } /* Verificar o primeiro dígito verificador */ for (c=VARDATA(num), digito=0, fator=10; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * fator; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar falso se o primeiro dígito não estiver correto if (digito != VALOR(*c)) PG_RETURN_BOOL(false); /* Verificar o segundo dígito verificador */ for (c=VARDATA(num), digito=0, fator=11; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * fator; } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*c)); } /* * * * * * * */
Rotina para validação do CNPJ. Recebe um argumento, o número do CNPJ com quatorze dígitos. Retorna verdade se os dígitos verificadores do CNPJ estiverem corretos, ou falso caso contrário. Se o argumento for nulo, não tiver 14 dígitos, ou contiver um dígito não numérico, retorna nulo.
PG_FUNCTION_INFO_V1(cnpj); Datum cnpj(PG_FUNCTION_ARGS) { int fator, digito; char *c; text *num = PG_GETARG_TEXT_P(0); // Primeiro argumento = número do CNPJ /* Verificar o recebimento de argumento vazio */ if ((VARATT_SIZEP(num) == VARHDRSZ) || (VARATT_SIZEP(num) == VARHDRSZ)) { PG_RETURN_NULL(); } /* Verificar se o CNPJ tem 14 dígitos */ if ( (VARSIZE(num) - VARHDRSZ) != 14 ) { PG_RETURN_NULL(); } /* Verificar o primeiro dígito verificador */ for (c=VARDATA(num), digito=0, fator=13; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito
537
digito += VALOR(*c++) * (fator>9 ? fator-8 : fator); } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar falso se o primeiro dígito não estiver correto if (digito != VALOR(*c)) PG_RETURN_BOOL(false); /* Verificar o segundo dígito verificador */ for (c=VARDATA(num), digito=0, fator=14; fator>=2; fator--) { if (!isdigit(*c)) PG_RETURN_NULL(); // Retornar nulo se não for dígito digito += VALOR(*c++) * (fator>9 ? fator-8 : fator); } digito = 11 - ( digito % 11 ); if (digito >= 10) digito = 0; // Restos 0 ou 1 digito = 0 // Retornar verdade ou falso PG_RETURN_BOOL (digito == VALOR(*c)); }
Os exemplos foram elaborados com o arquivo fonte (funcoes.c), o arquivo objeto intermediário (funcoes.o), e o arquivo de biblioteca compartilhada (funcoes.so), os mesmos das funções acima, colocados em /usr/lib/pgsql/. O código fonte da distribuição do PostgreSQL foi descompactado sob o diretório /root. Com isto, a geração do arquivo de biblioteca compartilhada foi feita usando os comandos: cd /usr/lib/pgsql/ gcc -fpic -c funcoes.c -I /root/postgresql-7.4.1/src/include/ gcc -shared -o funcoes.so funcoes.o
O código SQL para declarar estas funções é: LOAD 'funcoes'; CREATE FUNCTION cpf(text) RETURNS boolean AS '$libdir/funcoes', 'cpf' LANGUAGE C STRICT; CREATE FUNCTION cnpj(text) RETURNS boolean AS '$libdir/funcoes', 'cnpj' LANGUAGE C STRICT;
Os CNPJ usados para testar a função são de órgãos públicos. SELECT cnpj('42498634000166'); cnpj -----t (1 linha) SELECT cnpj('42498733000148'); cnpj -----t (1 linha)
Listar o nome, número de argumentos e o tipo retornado por todas as funções C definidas pelo usuário.
538
SELECT n.nspname, p.proname, p.pronargs, format_type(t.oid, null) as return_type FROM pg_namespace n, pg_proc p, pg_language l, pg_type t WHERE p.pronamespace = n.oid and n.nspname not like 'pg\\_%' -- sem catálogos and n.nspname != 'information_schema' -- sem information_schema and p.prolang = l.oid and p.prorettype = t.oid and l.lanname = 'c' ORDER BY nspname, proname, pronargs, return_type; nspname | proname | pronargs | return_type ---------+----------------------+----------+-----------------public | cnpj | 1 | boolean public | cpf | 1 | boolean public | dv10 | 1 | text public | dv10 | 2 | boolean public | dv11 | 1 | text public | dv11 | 2 | boolean public | plpgsql_call_handler | 0 | language_handler (7 linhas)
33.8. Sobrecarga de função Pode ser definida mais de uma função possuindo o mesmo nome SQL, desde que os argumentos recebidos sejam diferentes. Em outras palavras, os nomes das funções podem ser sobrecarregados. Quando um comando é executado, o servidor determina a função a ser chamada a partir dos tipos de dado e do número de argumentos fornecidos. A sobrecarga também pode ser utilizada para simular funções com número variável de argumentos, até um número máximo finito. A função também pode ter o mesmo nome de um atributo (Lembre-se que atributo(tabela) equivale a tabela.atributo). No caso de haver ambigüidade entre função em um tipo complexo e atributo de um tipo complexo, sempre será utilizado o atributo. Ao ser criada uma família de funções sobrecarregadas, deve ser tomado cuidado para não criar ambigüidades. Por exemplo, dadas as funções CREATE FUNCTION teste(int, real) RETURNS ... CREATE FUNCTION teste(smallint, double precision) RETURNS ...
não fica imediatamente claro qual das duas funções deve ser chamada por uma entrada trivial como teste(1, 1.5). As regras de resolução implementadas atualmente estão descritas no Capítulo 10, mas não é prudente projetar um sistema dependente deste comportamento delicado. Ao sobrecarregar funções na linguagem C, existe uma restrição adicional: o nome C de cada uma das funções da família de funções sobrecarregadas deve ser diferente dos nomes C de todas as outras funções, sejam internas ou carregadas dinamicamente. Se esta regra for violada, o comportamento não é portável. Deve ser recebido um erro de ligação em tempo de execução, ou uma das funções será chamada (geralmente a interna). A forma alternativa da cláusula AS para o comando SQL CREATE FUNCTION separa o nome SQL da função do nome da função no código fonte C. Por exemplo, CREATE FUNCTION teste(int) RETURNS int AS 'nome_do_arquivo', 'teste_1arg' LANGUAGE C; CREATE FUNCTION teste(int, int) RETURNS int AS 'nome_do_arquivo', 'teste_2arg' LANGUAGE C;
Os nomes das funções C neste exemplo refletem uma das várias convenções possíveis.
539
33.9. User-Defined Aggregates Aggregate functions in PostgreSQL are expressed as state values and state transition functions. That is, an aggregate can be defined in terms of state that is modified whenever an input item is processed. To define a new aggregate function, one selects a data type for the state value, an initial value for the state, and a state transition function. The state transition function is just an ordinary function that could also be used outside the context of the aggregate. A final function can also be specified, in case the desired result of the aggregate is different from the data that needs to be kept in the running state value. Thus, in addition to the argument and result data types seen by a user of the aggregate, there is an internal state-value data type that may be different from both the argument and result types. If we define an aggregate that does not use a final function, we have an aggregate that computes a running function of the column values from each row. sum is an example of this kind of aggregate. sum starts at zero and always adds the current row's value to its running total. For example, if we want to make a sum aggregate to work on a data type for complex numbers, we only need the addition function for that data type. The aggregate definition would be: CREATE AGGREGATE complex_sum ( sfunc = complex_add, basetype = complex, stype = complex, initcond = '(0,0)' ); SELECT complex_sum(a) FROM test_complex; complex_sum ------------(34,53.9)
(In practice, we'd just name the aggregate sum and rely on PostgreSQL to figure out which kind of sum to apply to a column of type complex.) The above definition of sum will return zero (the initial state condition) if there are no nonnull input values. Perhaps we want to return null in that case instead --- the SQL standard expects sum to behave that way. We can do this simply by omitting the initcond phrase, so that the initial state condition is null. Ordinarily this would mean that the sfunc would need to check for a null state-condition input, but for sum and some other simple aggregates like max and min, it is sufficient to insert the first nonnull input value into the state variable and then start applying the transition function at the second nonnull input value. PostgreSQL will do that automatically if the initial condition is null and the transition function is marked “strict” (i.e., not to be called for null inputs). Another bit of default behavior for a “strict” transition function is that the previous state value is retained unchanged whenever a null input value is encountered. Thus, null values are ignored. If you need some other behavior for null inputs, just do not define your transition function as strict, and code it to test for null inputs and do whatever is needed. avg (average) is a more complex example of an aggregate. It requires two pieces of running state: the sum of the inputs and the count of the number of inputs. The final result is obtained by dividing these quantities. Average is typically implemented by using a two-element array as the state value. For example, the built-in implementation of avg(float8) looks like: CREATE AGGREGATE avg ( sfunc = float8_accum, basetype = float8, stype = float8[], finalfunc = float8_avg, initcond = '{0,0}' );
540
Aggregate functions may use polymorphic state transition functions or final functions, so that the same functions can be used to implement multiple aggregates. See Seção 33.2.5 for an explanation of polymorphic functions. Going a step further, the aggregate function itself may be specified with a polymorphic base type and state type, allowing a single aggregate definition to serve for multiple input data types. Here is an example of a polymorphic aggregate: CREATE AGGREGATE array_accum ( sfunc = array_append, basetype = anyelement, stype = anyarray, initcond = '{}' );
Here, the actual state type for any aggregate call is the array type having the actual input type as elements. Here's the output using two different actual data types as arguments: SELECT attrelid::regclass, array_accum(attname) FROM pg_attribute WHERE attnum > 0 AND attrelid = 'pg_user'::regclass GROUP BY attrelid; attrelid | array_accum ----------+----------------------------------------------------------------------------pg_user | {usename,usesysid,usecreatedb,usesuper,usecatupd,passwd,valuntil,useconfig} (1 linha)
SELECT attrelid::regclass, array_accum(atttypid) FROM pg_attribute WHERE attnum > 0 AND attrelid = 'pg_user'::regclass GROUP BY attrelid; attrelid | array_accum ----------+-----------------------------pg_user | {19,23,16,16,16,25,702,1009} (1 linha)
For further details see the CREATE AGGREGATE command.
33.10. User-Defined Types As described in Seção 33.2, PostgreSQL can be extended to support new data types. This section describes how to define new base types, which are data types defined below the level of the SQL language. Creating a new base type requires implementing functions to operate on the type in a low-level language, usually C. The examples in this section can be found in complex.sql and complex.c in the src/tutorial directory of the source distribution. See the README file in that directory for instructions about running the examples. A user-defined type must always have input and output functions. These functions determine how the type appears in strings (for input by the user and output to the user) and how the type is organized in memory. The input function takes a null-terminated character string as its argument and returns the internal (in memory) representation of the type. The output function takes the internal representation of the type as argument and returns a null-terminated character string. If we want to do anything more with the type than merely store it, we must provide additional functions to implement whatever operations we'd like to have for the type. Suppose we want to define a type complex that represents complex numbers. A natural way to represent a complex number in memory would be the following C structure: typedef struct Complex { double x; double y; } Complex;
541
We will need to make this a pass-by-reference type, since it's too large to fit into a single Datum value. As the external string representation of the type, we choose a string of the form (x,y). The input and output functions are usually not hard to write, especially the output function. But when defining the external string representation of the type, remember that you must eventually write a complete and robust parser for that representation as your input function. For instance: PG_FUNCTION_INFO_V1(complex_in); Datum complex_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); double x, y; Complex *result; if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for complex: \"%s\"", str))); result = (Complex *) palloc(sizeof(Complex)); result->x = x; result->y = y; PG_RETURN_POINTER(result); }
The output function can simply be: PG_FUNCTION_INFO_V1(complex_out); Datum complex_out(PG_FUNCTION_ARGS) { Complex *complex = (Complex *) PG_GETARG_POINTER(0); char *result; result = (char *) palloc(100); snprintf(result, 100, "(%g,%g)", complex->x, complex->y); PG_RETURN_CSTRING(result); }
You should be careful to make the input and output functions inverses of each other. If you do not, you will have severe problems when you need to dump your data into a file and then read it back in. This is a particularly common problem when floating-point numbers are involved. Optionally, a user-defined type can provide binary input and output routines. Binary I/O is normally faster but less portable than textual I/O. As with textual I/O, it is up to you to define exactly what the external binary representation is. Most of the built-in data types try to provide a machine-independent binary representation. For complex, we will piggy-back on the binary I/O converters for type float8:
542
PG_FUNCTION_INFO_V1(complex_recv); Datum complex_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Complex *result; result = (Complex *) palloc(sizeof(Complex)); result->x = pq_getmsgfloat8(buf); result->y = pq_getmsgfloat8(buf); PG_RETURN_POINTER(result); } PG_FUNCTION_INFO_V1(complex_send); Datum complex_send(PG_FUNCTION_ARGS) { Complex *complex = (Complex *) PG_GETARG_POINTER(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendfloat8(&buf, complex->x); pq_sendfloat8(&buf, complex->y); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
To define the complex type, we need to create the user-defined I/O functions before creating the type: CREATE FUNCTION complex_in(cstring) RETURNS complex AS 'filename' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION complex_out(complex) RETURNS cstring AS 'filename' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION complex_recv(internal) RETURNS complex AS 'filename' LANGUAGE C IMMUTABLE STRICT; CREATE FUNCTION complex_send(complex) RETURNS bytea AS 'filename' LANGUAGE C IMMUTABLE STRICT;
Notice that the declarations of the input and output functions must reference the not-yet-defined type. This is allowed, but will draw warning messages that may be ignored. The input function must appear first. Finally, we can declare the data type:
543
CREATE TYPE complex ( internallength = 16, input = complex_in, output = complex_out, receive = complex_recv, send = complex_send, alignment = double );
When you define a new base type, PostgreSQL automatically provides support for arrays of that type. For historical reasons, the array type has the same name as the base type with the underscore character (_) prepended. Once the data type exists, we can declare additional functions to provide useful operations on the data type. Operators can then be defined atop the functions, and if needed, operator classes can be created to support indexing of the data type. These additional layers are discussed in following sections. If the values of your data type might exceed a few hundred bytes in size (in internal form), you should make the data type TOAST-able. To do this, the internal representation must follow the standard layout for variablelength data: the first four bytes must be an int32 containing the total length in bytes of the datum (including itself). The C functions operating on the data type must be careful to unpack any toasted values they are handed (this detail can normally be hidden in the GETARG macros). Then, when running the CREATE TYPE command, specify the internal length as variable and select the appropriate storage option. For further details see the description of the CREATE TYPE command.
33.11. User-Defined Operators Every operator is “syntactic sugar” for a call to an underlying function that does the real work; so you must first create the underlying function before you can create the operator. However, an operator is not merely syntactic sugar, because it carries additional information that helps the query planner optimize queries that use the operator. The next section will be devoted to explaining that additional information. PostgreSQL supports left unary, right unary, and binary operators. Operators can be overloaded; that is, the same operator name can be used for different operators that have different numbers and types of operands. When a query is executed, the system determines the operator to call from the number and types of the provided operands. Here is an example of creating an operator for adding two complex numbers. We assume we've already created the definition of type complex (see Seção 33.10). First we need a function that does the work, then we can define the operator: CREATE FUNCTION complex_add(complex, complex) RETURNS complex AS 'filename', 'complex_add' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR + ( leftarg = complex, rightarg = complex, procedure = complex_add, commutator = + );
Now we could execute a query like this: SELECT (a + b) AS c FROM test_complex; c ----------------(5.2,6.05) (133.42,144.95)
544
We've shown how to create a binary operator here. To create unary operators, just omit one of leftarg (for left unary) or rightarg (for right unary). The procedure clause and the argument clauses are the only required items in CREATE OPERATOR. The commutator clause shown in the example is an optional hint to the query optimizer. Further details about commutator and other optimizer hints appear in the next section.
33.12. Operator Optimization Information A PostgreSQL operator definition can include several optional clauses that tell the system useful things about how the operator behaves. These clauses should be provided whenever appropriate, because they can make for considerable speedups in execution of queries that use the operator. But if you provide them, you must be sure that they are right! Incorrect use of an optimization clause can result in server process crashes, subtly wrong output, or other Bad Things. You can always leave out an optimization clause if you are not sure about it; the only consequence is that queries might run slower than they need to. Additional optimization clauses might be added in future versions of PostgreSQL. The ones described here are all the ones that release 7.4.1 understands.
33.12.1. COMMUTATOR The COMMUTATOR clause, if provided, names an operator that is the commutator of the operator being defined. We say that operator A is the commutator of operator B if (x A y) equals (y B x) for all possible input values x, y. Notice that B is also the commutator of A. For example, operators < and > for a particular data type are usually each others' commutators, and operator + is usually commutative with itself. But operator - is usually not commutative with anything. The left operand type of a commutable operator is the same as the right operand type of its commutator, and vice versa. So the name of the commutator operator is all that PostgreSQL needs to be given to look up the commutator, and that's all that needs to be provided in the COMMUTATOR clause. It's critical to provide commutator information for operators that will be used in indexes and join clauses, because this allows the query optimizer to “flip around” such a clause to the forms needed for different plan types. For example, consider a query with a WHERE clause like tab1.x = tab2.y, where tab1.x and tab2.y are of a user-defined type, and suppose that tab2.y is indexed. The optimizer cannot generate an index scan unless it can determine how to flip the clause around to tab2.y = tab1.x, because the index-scan machinery expects to see the indexed column on the left of the operator it is given. PostgreSQL will not simply assume that this is a valid transformation --- the creator of the = operator must specify that it is valid, by marking the operator with commutator information. When you are defining a self-commutative operator, you just do it. When you are defining a pair of commutative operators, things are a little trickier: how can the first one to be defined refer to the other one, which you haven't defined yet? There are two solutions to this problem: •
One way is to omit the COMMUTATOR clause in the first operator that you define, and then provide one in the second operator's definition. Since PostgreSQL knows that commutative operators come in pairs, when it sees the second definition it will automatically go back and fill in the missing COMMUTATOR clause in the first definition.
•
The other, more straightforward way is just to include COMMUTATOR clauses in both definitions. When PostgreSQL processes the first definition and realizes that COMMUTATOR refers to a nonexistent operator, the system will make a dummy entry for that operator in the system catalog. This dummy entry will have valid data only for the operator name, left and right operand types, and result type, since that's all that PostgreSQL can deduce at this point. The first operator's catalog entry will link to this dummy entry. Later, when you define the second operator, the system updates the dummy entry with the additional information from the second definition. If you try to use the dummy operator before it's been filled in, you'll just get an error message.
33.12.2. NEGATOR The NEGATOR clause, if provided, names an operator that is the negator of the operator being defined. We say that operator A is the negator of operator B if both return Boolean results and (x A y) equals NOT (x B y) for
545
all possible inputs x, y. Notice that B is also the negator of A. For example, < and >= are a negator pair for most data types. An operator can never validly be its own negator. Unlike commutators, a pair of unary operators could validly be marked as each others' negators; that would mean (A x) equals NOT (B x) for all x, or the equivalent for right unary operators. An operator's negator must have the same left and/or right operand types as the operator to be defined, so just as with COMMUTATOR, only the operator name need be given in the NEGATOR clause. Providing a negator is very helpful to the query optimizer since it allows expressions like NOT (x = y) to be simplified into x <> y. This comes up more often than you might think, because NOT operations can be inserted as a consequence of other rearrangements. Pairs of negator operators can be defined using the same methods explained above for commutator pairs.
33.12.3. RESTRICT The RESTRICT clause, if provided, names a restriction selectivity estimation function for the operator. (Note that this is a function name, not an operator name.) RESTRICT clauses only make sense for binary operators that return boolean. The idea behind a restriction selectivity estimator is to guess what fraction of the rows in a table will satisfy a WHERE-clause condition of the form column OP constant
for the current operator and a particular constant value. This assists the optimizer by giving it some idea of how many rows will be eliminated by WHERE clauses that have this form. (What happens if the constant is on the left, you may be wondering? Well, that's one of the things that COMMUTATOR is for...) Writing new restriction selectivity estimation functions is far beyond the scope of this chapter, but fortunately you can usually just use one of the system's standard estimators for many of your own operators. These are the standard restriction estimators: eqsel for = neqsel for <> scalarltsel for < or <= scalargtsel for > or >=
It might seem a little odd that these are the categories, but they make sense if you think about it. = will typically accept only a small fraction of the rows in a table; <> will typically reject only a small fraction. < will accept a fraction that depends on where the given constant falls in the range of values for that table column (which, it just so happens, is information collected by ANALYZE and made available to the selectivity estimator). <= will accept a slightly larger fraction than < for the same comparison constant, but they're close enough to not be worth distinguishing, especially since we're not likely to do better than a rough guess anyhow. Similar remarks apply to > and >=. You can frequently get away with using either eqsel or neqsel for operators that have very high or very low selectivity, even if they aren't really equality or inequality. For example, the approximate-equality geometric operators use eqsel on the assumption that they'll usually only match a small fraction of the entries in a table. You can use scalarltsel and scalargtsel for comparisons on data types that have some sensible means of being converted into numeric scalars for range comparisons. If possible, add the data type to those understood by the function convert_to_scalar() in src/backend/utils/adt/selfuncs.c. (Eventually, this function should be replaced by per-data-type functions identified through a column of the pg_type system catalog; but that hasn't happened yet.) If you do not do this, things will still work, but the optimizer's estimates won't be as good as they could be. There
are
additional
selectivity
estimation
functions
designed
for
geometric
operators
in
src/backend/utils/adt/geo_selfuncs.c: areasel, positionsel, and contsel. At this writing
these are just stubs, but you may want to use them (or even better, improve them) anyway.
546
33.12.4. JOIN The JOIN clause, if provided, names a join selectivity estimation function for the operator. (Note that this is a function name, not an operator name.) JOIN clauses only make sense for binary operators that return boolean. The idea behind a join selectivity estimator is to guess what fraction of the rows in a pair of tables will satisfy a WHERE-clause condition of the form table1.column1 OP table2.column2
for the current operator. As with the RESTRICT clause, this helps the optimizer very substantially by letting it figure out which of several possible join sequences is likely to take the least work. As before, this chapter will make no attempt to explain how to write a join selectivity estimator function, but will just suggest that you use one of the standard estimators if one is applicable: eqjoinsel for = neqjoinsel for <> scalarltjoinsel for < or <= scalargtjoinsel for > or >= areajoinsel for 2D area-based comparisons positionjoinsel for 2D position-based comparisons contjoinsel for 2D containment-based comparisons
33.12.5. HASHES The HASHES clause, if present, tells the system that it is permissible to use the hash join method for a join based on this operator. HASHES only makes sense for a binary operator that returns boolean, and in practice the operator had better be equality for some data type. The assumption underlying hash join is that the join operator can only return true for pairs of left and right values that hash to the same hash code. If two values get put in different hash buckets, the join will never compare them at all, implicitly assuming that the result of the join operator must be false. So it never makes sense to specify HASHES for operators that do not represent equality. To be marked HASHES, the join operator must appear in a hash index operator class. This is not enforced when you create the operator, since of course the referencing operator class couldn't exist yet. But attempts to use the operator in hash joins will fail at runtime if no such operator class exists. The system needs the operator class to find the data-type-specific hash function for the operator's input data type. Of course, you must also supply a suitable hash function before you can create the operator class. Care should be exercised when preparing a hash function, because there are machine-dependent ways in which it might fail to do the right thing. For example, if your data type is a structure in which there may be uninteresting pad bits, you can't simply pass the whole structure to hash_any. (Unless you write your other operators and functions to ensure that the unused bits are always zero, which is the recommended strategy.) Another example is that on machines that meet the IEEE floating-point standard, negative zero and positive zero are different values (different bit patterns) but they are defined to compare equal. If a float value might contain negative zero then extra steps are needed to ensure it generates the same hash value as positive zero. Nota: The function underlying a hash-joinable operator must be marked immutable or stable. If it is volatile, the system will never attempt to use the operator for a hash join. Nota: If a hash-joinable operator has an underlying function that is marked strict, the function must also be complete: that is, it should return true or false, never null, for any two nonnull inputs. If this rule is not followed, hash-optimization of IN operations may generate wrong results. (Specifically, IN might return false where the correct answer according to the standard would be null; or it might yield an error complaining that it wasn't prepared for a null result.)
33.12.6. MERGES (SORT1, SORT2, LTCMP, GTCMP) The MERGES clause, if present, tells the system that it is permissible to use the merge-join method for a join based on this operator. MERGES only makes sense for a binary operator that returns boolean, and in practice the operator must represent equality for some data type or pair of data types.
547
Merge join is based on the idea of sorting the left- and right-hand tables into order and then scanning them in parallel. So, both data types must be capable of being fully ordered, and the join operator must be one that can only succeed for pairs of values that fall at the “same place” in the sort order. In practice this means that the join operator must behave like equality. But unlike hash join, where the left and right data types had better be the same (or at least bitwise equivalent), it is possible to merge-join two distinct data types so long as they are logically compatible. For example, the smallint-versus-integer equality operator is merge-joinable. We only need sorting operators that will bring both data types into a logically compatible sequence. Execution of a merge join requires that the system be able to identify four operators related to the merge-join equality operator: less-than comparison for the left operand data type, less-than comparison for the right operand data type, less-than comparison between the two data types, and greater-than comparison between the two data types. (These are actually four distinct operators if the merge-joinable operator has two different operand data types; but when the operand types are the same the three less-than operators are all the same operator.) It is possible to specify these operators individually by name, as the SORT1, SORT2, LTCMP, and GTCMP options respectively. The system will fill in the default names <, <, <, > respectively if any of these are omitted when MERGES is specified. Also, MERGES will be assumed to be implied if any of these four operator options appear, so it is possible to specify just some of them and let the system fill in the rest. The operand data types of the four comparison operators can be deduced from the operand types of the mergejoinable operator, so just as with COMMUTATOR, only the operator names need be given in these clauses. Unless you are using peculiar choices of operator names, it's sufficient to write MERGES and let the system fill in the details. (As with COMMUTATOR and NEGATOR, the system is able to make dummy operator entries if you happen to define the equality operator before the other ones.) There are additional restrictions on operators that you mark merge-joinable. These restrictions are not currently checked by CREATE OPERATOR, but errors may occur when the operator is used if any are not true: •
A merge-joinable equality operator must have a merge-joinable commutator (itself if the two operand data types are the same, or a related equality operator if they are different).
•
If there is a merge-joinable operator relating any two data types A and B, and another merge-joinable operator relating B to any third data type C, then A and C must also have a merge-joinable operator; in other words, having a merge-joinable operator must be transitive.
•
Bizarre results will ensue at runtime if the four comparison operators you name do not sort the data values compatibly. Nota: The function underlying a merge-joinable operator must be marked immutable or stable. If it is volatile, the system will never attempt to use the operator for a merge join. Nota: In PostgreSQL versions before 7.3, the MERGES shorthand was not available: to make a mergejoinable operator one had to write both SORT1 and SORT2 explicitly. Also, the LTCMP and GTCMP options did not exist; the names of those operators were hardwired as < and > respectively.
33.13. Interfacing Extensions To Indexes The procedures described thus far let you define new types, new functions, and new operators. However, we cannot yet define an index on a column of a new data type. To do this, we must define an operator class for the new data type. Later in this section, we will illustrate this concept in an example: a new operator class for the B-tree index method that stores and sorts complex numbers in ascending absolute value order. Nota: Prior to PostgreSQL release 7.3, it was necessary to make manual additions to the system catalogs pg_amop, pg_amproc, and pg_opclass in order to create a user-defined operator class. That approach is now deprecated in favor of using CREATE OPERATOR CLASS, which is a much simpler and less error-prone way of creating the necessary catalog entries.
33.13.1. Index Methods and Operator Classes The pg_am table contains one row for every index method (internally known as access method). Support for regular access to tables is built into PostgreSQL, but all index methods are described in pg_am. It is possible to add a new index method by defining the required interface routines and then creating a row in pg_am --- but that is far beyond the scope of this chapter.
548
The routines for an index method do not directly know anything about the data types that the index method will operate on. Instead, an operator class identifies the set of operations that the index method needs to use to work with a particular data type. Operator classes are so called because one thing they specify is the set of WHERE-clause operators that can be used with an index (i.e., can be converted into an index-scan qualification). An operator class may also specify some support procedures that are needed by the internal operations of the index method, but do not directly correspond to any WHERE-clause operator that can be used with the index. It is possible to define multiple operator classes for the same data type and index method. By doing this, multiple sets of indexing semantics can be defined for a single data type. For example, a B-tree index requires a sort ordering to be defined for each data type it works on. It might be useful for a complex-number data type to have one B-tree operator class that sorts the data by complex absolute value, another that sorts by real part, and so on. Typically, one of the operator classes will be deemed most commonly useful and will be marked as the default operator class for that data type and index method. The same operator class name can be used for several different index methods (for example, both B-tree and hash index methods have operator classes named oid_ops), but each such class is an independent entity and must be defined separately.
33.13.2. Index Method Strategies The operators associated with an operator class are identified by “strategy numbers”, which serve to identify the semantics of each operator within the context of its operator class. For example, B-trees impose a strict ordering on keys, lesser to greater, and so operators like “less than” and “greater than or equal to” are interesting with respect to a B-tree. Because PostgreSQL allows the user to define operators, PostgreSQL cannot look at the name of an operator (e.g., < or >=) and tell what kind of comparison it is. Instead, the index method defines a set of “strategies”, which can be thought of as generalized operators. Each operator class specifies which actual operator corresponds to each strategy for a particular data type and interpretation of the index semantics. The B-tree index method defines five strategies, shown in Tabela 33-2. Tabela 33-2. B-tree Strategies Operation
Strategy Number
less than
1
less than or equal
2
equal
3
greater than or equal
4
greater than
5
Hash indexes express only bitwise equality, and so they use only one strategy, shown in Tabela 33-3. Tabela 33-3. Hash Strategies Operation
Strategy Number
equal
1
R-tree indexes express rectangle-containment relationships. They use eight strategies, shown in Tabela 33-4. Tabela 33-4. R-tree Strategies Operation
Strategy Number
left of
1
left of or overlapping
2
549
Operation
Strategy Number
overlapping
3
right of or overlapping
4
right of
5
same
6
contains
7
contained by
8
GiST indexes are even more flexible: they do not have a fixed set of strategies at all. Instead, the “consistency” support routine of each particular GiST operator class interprets the strategy numbers however it likes. Note that all strategy operators return Boolean values. In practice, all operators defined as index method strategies must return type boolean, since they must appear at the top level of a WHERE clause to be used with an index. By the way, the amorderstrategy column in pg_am tells whether the index method supports ordered scans. Zero means it doesn't; if it does, amorderstrategy is the strategy number that corresponds to the ordering operator. For example, B-tree has amorderstrategy = 1, which is its “less than” strategy number.
33.13.3. Index Method Support Routines Strategies aren't usually enough information for the system to figure out how to use an index. In practice, the index methods require additional support routines in order to work. For example, the B-tree index method must be able to compare two keys and determine whether one is greater than, equal to, or less than the other. Similarly, the R-tree index method must be able to compute intersections, unions, and sizes of rectangles. These operations do not correspond to operators used in qualifications in SQL commands; they are administrative routines used by the index methods, internally. Just as with strategies, the operator class identifies which specific functions should play each of these roles for a given data type and semantic interpretation. The index method defines the set of functions it needs, and the operator class identifies the correct functions to use by assigning them to the “support function numbers”. B-trees require a single support function, shown in Tabela 33-5. Tabela 33-5. B-tree Support Functions Function
Support Number
Compare two keys and return an integer less than zero, zero, or greater than zero, indicating whether the first key is less than, equal to, or greater than the second.
1
Hash indexes likewise require one support function, shown in Tabela 33-6. Tabela 33-6. Hash Support Functions Function
Support Number
Compute the hash value for a key
1
R-tree indexes require three support functions, shown in Tabela 33-7. Tabela 33-7. R-tree Support Functions Function
Support Number
union
1
550
Function
Support Number
intersection
2
size
3
GiST indexes require seven support functions, shown in Tabela 33-8. Tabela 33-8. GiST Support Functions Function
Support Number
consistent
1
union
2
compress
3
decompress
4
penalty
5
picksplit
6
equal
7
Unlike strategy operators, support functions return whichever data type the particular index method expects, for example in the case of the comparison function for B-trees, a signed integer.
33.13.4. An Example Now that we have seen the ideas, here is the promised example of creating a new operator class. (You can find a working copy of this example in src/tutorial/complex.c and src/tutorial/complex.sql in the source distribution.) The operator class encapsulates operators that sort complex numbers in absolute value order, so we choose the name complex_abs_ops. First, we need a set of operators. The procedure for defining operators was discussed in Seção 33.11. For an operator class on B-trees, the operators we require are: • • • • •
absolute-value less-than (strategy 1) absolute-value less-than-or-equal (strategy 2) absolute-value equal (strategy 3) absolute-value greater-than-or-equal (strategy 4) absolute-value greater-than (strategy 5)
The least error-prone way to define a related set of comparison operators is to write the B-tree comparison support function first, and then write the other functions as one-line wrappers around the support function. This reduces the odds of getting inconsistent results for corner cases. Following this approach, we first write #define Mag(c)
((c)->x*(c)->x + (c)->y*(c)->y)
static int complex_abs_cmp_internal(Complex *a, Complex *b) { double amag = Mag(a), bmag = Mag(b); if (amag < return if (amag > return return 0;
bmag) -1; bmag) 1;
}
Now the less-than function looks like
551
PG_FUNCTION_INFO_V1(complex_abs_lt); Datum complex_abs_lt(PG_FUNCTION_ARGS) { Complex *a = (Complex *) PG_GETARG_POINTER(0); Complex *b = (Complex *) PG_GETARG_POINTER(1); PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) < 0); }
The other four functions differ only in how they compare the internal function's result to zero. Next we declare the functions and the operators based on the functions to SQL: CREATE FUNCTION complex_abs_lt(complex, complex) RETURNS bool AS 'filename', 'complex_abs_lt' LANGUAGE C IMMUTABLE STRICT; CREATE OPERATOR < ( leftarg = complex, rightarg = complex, procedure = complex_abs_lt, commutator = > , negator = >= , restrict = scalarltsel, join = scalarltjoinsel );
It is important to specify the correct commutator and negator operators, as well as suitable restriction and join selectivity functions, otherwise the optimizer will be unable to make effective use of the index. Note that the less-than, equal, and greater-than cases should use different selectivity functions. Other things worth noting are happening here: •
There can only be one operator named, say, = and taking type complex for both operands. In this case we don't have any other operator = for complex, but if we were building a practical data type we'd probably want = to be the ordinary equality operation for complex numbers (and not the equality of the absolute values). In that case, we'd need to use some other operator name for complex_abs_eq.
•
Although PostgreSQL can cope with functions having the same name as long as they have different argument data types, C can only cope with one global function having a given name. So we shouldn't name the C function something simple like abs_eq. Usually it's a good practice to include the data type name in the C function name, so as not to conflict with functions for other data types.
•
We could have made the PostgreSQL name of the function abs_eq, relying on PostgreSQL to distinguish it by argument data types from any other PostgreSQL function of the same name. To keep the example simple, we make the function have the same names at the C level and PostgreSQL level.
The next step is the registration of the support routine required by B-trees. The example C code that implements this is in the same file that contains the operator functions. This is how we declare the function: CREATE FUNCTION complex_abs_cmp(complex, complex) RETURNS integer AS 'filename' LANGUAGE C IMMUTABLE STRICT;
Now that we have the required operators and support routine, we can finally create the operator class:
552
CREATE OPERATOR CLASS complex_abs_ops DEFAULT FOR TYPE complex USING btree AS OPERATOR 1 < , OPERATOR 2 <= , OPERATOR 3 = , OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 complex_abs_cmp(complex, complex);
And we're done! It should now be possible to create and use B-tree indexes on complex columns. We could have written the operator entries more verbosely, as in OPERATOR
1
< (complex, complex) ,
but there is no need to do so when the operators take the same data type we are defining the operator class for. The above example assumes that you want to make this new operator class the default B-tree operator class for the complex data type. If you don't, just leave out the word DEFAULT.
33.13.5. System Dependencies on Operator Classes PostgreSQL uses operator classes to infer the properties of operators in more ways than just whether they can be used with indexes. Therefore, you might want to create operator classes even if you have no intention of indexing any columns of your data type. In particular, there are SQL features such as ORDER BY and DISTINCT that require comparison and sorting of values. To implement these features on a user-defined data type, PostgreSQL looks for the default B-tree operator class for the data type. The “equals” member of this operator class defines the system's notion of equality of values for GROUP BY and DISTINCT, and the sort ordering imposed by the operator class defines the default ORDER BY ordering. Comparison of arrays of user-defined types also relies on the semantics defined by the default B-tree operator class. If there is no default B-tree operator class for a data type, the system will look for a default hash operator class. But since that kind of operator class only provides equality, in practice it is only enough to support array equality. When there is no default operator class for a data type, you will get errors like “could not identify an ordering operator” if you try to use these SQL features with the data type. Nota: In PostgreSQL versions before 7.4, sorting and grouping operations would implicitly use operators named =, <, and >. The new behavior of relying on default operator classes avoids having to make any assumption about the behavior of operators with particular names.
33.13.6. Special Features of Operator Classes There are two special features of operator classes that we have not discussed yet, mainly because they are not useful with the most commonly used index methods. Normally, declaring an operator as a member of an operator class means that the index method can retrieve exactly the set of rows that satisfy a WHERE condition using the operator. For example, SELECT * FROM table WHERE integer_column < 4;
can be satisfied exactly by a B-tree index on the integer column. But there are cases where an index is useful as an inexact guide to the matching rows. For example, if an R-tree index stores only bounding boxes for objects, then it cannot exactly satisfy a WHERE condition that tests overlap between nonrectangular objects such as polygons. Yet we could use the index to find objects whose bounding box overlaps the bounding box of the target object, and then do the exact overlap test only on the objects found by the index. If this scenario applies, the index is said to be “lossy” for the operator, and we add RECHECK to the OPERATOR clause in the CREATE
553
OPERATOR CLASS command. RECHECK is valid if the index is guaranteed to return all the required rows, plus
perhaps some additional rows, which can be eliminated by performing the original operator invocation. Consider again the situation where we are storing in the index only the bounding box of a complex object such as a polygon. In this case there's not much value in storing the whole polygon in the index entry --- we may as well store just a simpler object of type box. This situation is expressed by the STORAGE option in CREATE OPERATOR CLASS: we'd write something like CREATE OPERATOR CLASS polygon_ops DEFAULT FOR TYPE polygon USING gist AS ... STORAGE box;
At present, only the GiST index method supports a STORAGE type that's different from the column data type. The GiST compress and decompress support routines must deal with data-type conversion when STORAGE is used.
Notas 1. abstract data type (ADT) — Um tipo de abstração de dado onde a forma interna do tipo fica escondida atrás de um conjunto de funções de acesso. Os valores do tipo são criados e inspecionados apenas pelas chamadas às funções de acesso, permitindo que a implementação do tipo seja modificada sem haver necessidade de qualquer modificação fora do módulo onde está definida. Os objetos e as ADTs são formas de abstração de dados, mas os objetos não são ADTs. Os objetos utilizam abstração procedural (métodos), e não abstração de tipo. Um exemplo clássico de ADT é o tipo de dado pilha, para o qual devem ser fornecidas funções para criar uma pilha vazia, para colocar elementos na pilha e para tirar elementos da pilha. FOLDOC Free On-Line Dictionary of Computing (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=adt) (N. do T.) 2. pg_config --pkglibdir retorna /usr/local/lib/postgresql na plataforma utilizada. (N. do T.) 3. pg_config --includedir-server plataforma utilizada. (N. do T.)
retorna
/usr/local/include/postgresql/server
na
554
Capítulo 34. The Rule System This chapter discusses the rule system in PostgreSQL. Production rule systems are conceptually simple, but there are many subtle points involved in actually using them. Some other database systems define active database rules, which are usually stored procedures and triggers. In PostgreSQL, these can be implemented using functions and triggers as well. The rule system (more precisely speaking, the query rewrite rule system) is totally different from stored procedures and triggers. It modifies queries to take rules into consideration, and then passes the modified query to the query planner for planning and execution. It is very powerful, and can be used for many things such as query language procedures, views, and versions. The theoretical foundations and the power of this rule system are also discussed in On Rules, Procedures, Caching and Views in Database Systems and A Unified Framework for Version Modeling Using Production Rules in a Database System.
34.1. The Query Tree To understand how the rule system works it is necessary to know when it is invoked and what its input and results are. The rule system is located between the parser and the planner. It takes the output of the parser, one query tree, and the user-defined rewrite rules, which are also query trees with some extra information, and creates zero or more query trees as result. So its input and output are always things the parser itself could have produced and thus, anything it sees is basically representable as an SQL statement. Now what is a query tree? It is an internal representation of an SQL statement where the single parts that it is built from are stored separately. These query trees can be shown in the server log if you set the configuration parameters debug_print_parse, debug_print_rewritten, or debug_print_plan. The rule actions are also stored as query trees, in the system catalog pg_rewrite. They are not formatted like the log output, but they contain exactly the same information. Reading a raw query tree requires some experience. But since SQL representations of query trees are sufficient to understand the rule system, this chapter will not teach how to read them. When reading the SQL representations of the query trees in this chapter it is necessary to be able to identify the parts the statement is broken into when it is in the query tree structure. The parts of a query tree are the command type This is a simple value telling which command (SELECT, INSERT, UPDATE, DELETE) produced the query tree. the range table The range table is a list of relations that are used in the query. In a SELECT statement these are the relations given after the FROM key word. Every range table entry identifies a table or view and tells by which name it is called in the other parts of the query. In the query tree, the range table entries are referenced by number rather than by name, so here it doesn't matter if there are duplicate names as it would in an SQL statement. This can happen after the range tables of rules have been merged in. The examples in this chapter will not have this situation. the result relation This is an index into the range table that identifies the relation where the results of the query go. SELECT queries normally don't have a result relation. The special case of a SELECT INTO is mostly identical to a CREATE TABLE followed by a INSERT ... SELECT and is not discussed separately here.
For INSERT, UPDATE, and DELETE commands, the result relation is the table (or view!) where the changes take effect.
555
the target list The target list is a list of expressions that define the result of the query. In the case of a SELECT, these expressions are the ones that build the final output of the query. They correspond to the expressions between the key words SELECT and FROM. (* is just an abbreviation for all the column names of a relation. It is expanded by the parser into the individual columns, so the rule system never sees it.) DELETE commands don't need a target list because they don't produce any result. In fact, the planner will add a special CTID entry to the empty target list, but this is after the rule system and will be discussed later; for the rule system, the target list is empty.
For INSERT commands, the target list describes the new rows that should go into the result relation. It consists of the expressions in the VALUES clause or the ones from the SELECT clause in INSERT ... SELECT. The first step of the rewrite process adds target list entries for any columns that were not assigned to by the original command but have defaults. Any remaining columns (with neither a given value nor a default) will be filled in by the planner with a constant null expression. For UPDATE commands, the target list describes the new rows that should replace the old ones. In the rule system, it contains just the expressions from the SET column = expression part of the command. The planner will handle missing columns by inserting expressions that copy the values from the old row into the new one. And it will add the special CTID entry just as for DELETE, too. Every entry in the target list contains an expression that can be a constant value, a variable pointing to a column of one of the relations in the range table, a parameter, or an expression tree made of function calls, constants, variables, operators, etc. the qualification The query's qualification is an expression much like one of those contained in the target list entries. The result value of this expression is a Boolean that tells whether the operation (INSERT, UPDATE, DELETE, or SELECT) for the final result row should be executed or not. It corresponds to the WHERE clause of an SQL statement. the join tree The query's join tree shows the structure of the FROM clause. For a simple query like SELECT ... FROM a, b, c, the join tree is just a list of the FROM items, because we are allowed to join them in any order. But when JOIN expressions, particularly outer joins, are used, we have to join in the order shown by the joins. In that case, the join tree shows the structure of the JOIN expressions. The restrictions associated with particular JOIN clauses (from ON or USING expressions) are stored as qualification expressions attached to those join-tree nodes. It turns out to be convenient to store the top-level WHERE expression as a qualification attached to the top-level join-tree item, too. So really the join tree represents both the FROM and WHERE clauses of a SELECT. the others The other parts of the query tree like the ORDER BY clause aren't of interest here. The rule system substitutes some entries there while applying rules, but that doesn't have much to do with the fundamentals of the rule system.
34.2. Views and the Rule System Views in PostgreSQL are implemented using the rule system. In fact, there is essentially no difference between CREATE VIEW myview AS SELECT * FROM mytab;
compared against the two commands CREATE TABLE myview (same column list as mytab); CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD SELECT * FROM mytab;
because this is exactly what the CREATE VIEW command does internally. This has some side effects. One of them is that the information about a view in the PostgreSQL system catalogs is exactly the same as it is for a
556
table. So for the parser, there is absolutely no difference between a table and a view. They are the same thing: relations.
34.2.1. How SELECT Rules Work Rules ON SELECT are applied to all queries as the last step, even if the command given is an INSERT, UPDATE or DELETE. And they have different semantics from rules on the other command types in that they modify the query tree in place instead of creating a new one. So SELECT rules are described first. Currently, there can be only one action in an ON SELECT rule, and it must be an unconditional SELECT action that is INSTEAD. This restriction was required to make rules safe enough to open them for ordinary users, and it restricts ON SELECT rules to real view rules. The examples for this chapter are two join views that do some calculations and some more views using them in turn. One of the two first views is customized later by adding rules for INSERT, UPDATE, and DELETE operations so that the final result will be a view that behaves like a real table with some magic functionality. This is not such a simple example to start from and this makes things harder to get into. But it's better to have one example that covers all the points discussed step by step rather than having many different ones that might mix up in mind. For the example, we need a little min function that returns the lower of 2 integer values. We create that as CREATE FUNCTION min(integer, integer) RETURNS integer AS ' SELECT CASE WHEN $1 < $2 THEN $1 ELSE $2 END ' LANGUAGE SQL STRICT;
The real tables we need in the first two rule system descriptions are these: CREATE TABLE shoe_data ( shoename text, sh_avail integer, slcolor text, slminlen real, slmaxlen real, slunit text );
-------
primary key available number of pairs preferred shoelace color minimum shoelace length maximum shoelace length length unit
CREATE TABLE shoelace_data ( sl_name text, sl_avail integer, sl_color text, sl_len real, sl_unit text );
------
primary key available number of pairs shoelace color shoelace length length unit
CREATE TABLE unit ( un_name text, un_fact real );
-- primary key -- factor to transform to cm
As you can see, they represent shoe-store data. The views are created as CREATE VIEW shoe AS SELECT sh.shoename, sh.sh_avail, sh.slcolor, sh.slminlen, sh.slminlen * un.un_fact AS slminlen_cm, sh.slmaxlen, sh.slmaxlen * un.un_fact AS slmaxlen_cm, sh.slunit
557
FROM shoe_data sh, unit un WHERE sh.slunit = un.un_name; CREATE VIEW shoelace AS SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit, s.sl_len * u.un_fact AS sl_len_cm FROM shoelace_data s, unit u WHERE s.sl_unit = u.un_name; CREATE VIEW shoe_ready AS SELECT rsh.shoename, rsh.sh_avail, rsl.sl_name, rsl.sl_avail, min(rsh.sh_avail, rsl.sl_avail) AS total_avail FROM shoe rsh, shoelace rsl WHERE rsl.sl_color = rsh.slcolor AND rsl.sl_len_cm >= rsh.slminlen_cm AND rsl.sl_len_cm <= rsh.slmaxlen_cm;
The CREATE VIEW command for the shoelace view (which is the simplest one we have) will create a relation shoelace and an entry in pg_rewrite that tells that there is a rewrite rule that must be applied whenever the relation shoelace is referenced in a query's range table. The rule has no rule qualification (discussed later, with the non-SELECT rules, since SELECT rules currently cannot have them) and it is INSTEAD. Note that rule qualifications are not the same as query qualifications. The action of our rule has a query qualification. The action of the rule is one query tree that is a copy of the SELECT statement in the view creation command. Nota: The two extra range table entries for NEW and OLD (named *NEW* and *OLD* for historical reasons in the printed query tree) you can see in the pg_rewrite entry aren't of interest for SELECT rules.
Now we populate unit, shoe_data and shoelace_data and run a simple query on a view: INSERT INTO unit VALUES ('cm', 1.0); INSERT INTO unit VALUES ('m', 100.0); INSERT INTO unit VALUES ('inch', 2.54); INSERT INSERT INSERT INSERT
INTO INTO INTO INTO
shoe_data shoe_data shoe_data shoe_data
VALUES VALUES VALUES VALUES
INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT
INTO INTO INTO INTO INTO INTO INTO INTO
shoelace_data shoelace_data shoelace_data shoelace_data shoelace_data shoelace_data shoelace_data shoelace_data
('sh1', ('sh2', ('sh3', ('sh4',
VALUES VALUES VALUES VALUES VALUES VALUES VALUES VALUES
2, 0, 4, 3,
'black', 'black', 'brown', 'brown',
('sl1', ('sl2', ('sl3', ('sl4', ('sl5', ('sl6', ('sl7', ('sl8',
5, 6, 0, 8, 4, 0, 7, 1,
70.0, 30.0, 50.0, 40.0,
'black', 'black', 'black', 'black', 'brown', 'brown', 'brown', 'brown',
90.0, 40.0, 65.0, 50.0,
'cm'); 'inch'); 'cm'); 'inch');
80.0, 'cm'); 100.0, 'cm'); 35.0 , 'inch'); 40.0 , 'inch'); 1.0 , 'm'); 0.9 , 'm'); 60 , 'cm'); 40 , 'inch');
SELECT * FROM shoelace;
558
sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm -----------+----------+----------+--------+---------+----------sl1 | 5 | black | 80 | cm | 80 sl2 | 6 | black | 100 | cm | 100 sl7 | 7 | brown | 60 | cm | 60 sl3 | 0 | black | 35 | inch | 88.9 sl4 | 8 | black | 40 | inch | 101.6 sl8 | 1 | brown | 40 | inch | 101.6 sl5 | 4 | brown | 1 | m | 100 sl6 | 0 | brown | 0.9 | m | 90 (8 linhas)
This is the simplest SELECT you can do on our views, so we take this opportunity to explain the basics of view rules. The SELECT * FROM shoelace was interpreted by the parser and produced the query tree SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace shoelace;
and this is given to the rule system. The rule system walks through the range table and checks if there are rules for any relation. When processing the range table entry for shoelace (the only one up to now) it finds the _RETURN rule with the query tree SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit, s.sl_len * u.un_fact AS sl_len_cm FROM shoelace *OLD*, shoelace *NEW*, shoelace_data s, unit u WHERE s.sl_unit = u.un_name;
To expand the view, the rewriter simply creates a subquery range-table entry containing the rule's action query tree, and substitutes this range table entry for the original one that referenced the view. The resulting rewritten query tree is almost the same as if you had typed SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM (SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit, s.sl_len * u.un_fact AS sl_len_cm FROM shoelace_data s, unit u WHERE s.sl_unit = u.un_name) shoelace;
There is one difference however: the subquery's range table has two extra entries shoelace *OLD* and shoelace *NEW*. These entries don't participate directly in the query, since they aren't referenced by the subquery's join tree or target list. The rewriter uses them to store the access privilege check information that was originally present in the range-table entry that referenced the view. In this way, the executor will still check that the user has proper privileges to access the view, even though there's no direct use of the view in the rewritten query. That was the first rule applied. The rule system will continue checking the remaining range-table entries in the top query (in this example there are no more), and it will recursively check the range-table entries in the added subquery to see if any of them reference views. (But it won't expand *OLD* or *NEW* --- otherwise we'd have infinite recursion!) In this example, there are no rewrite rules for shoelace_data or unit, so rewriting is complete and the above is the final result given to the planner.
559
No we want to write a query that finds out for which shoes currently in the store we have the matching shoelaces (color and length) and where the total number of exactly matching pairs is greater or equal to two. SELECT * FROM shoe_ready WHERE total_avail >= 2; shoename | sh_avail | sl_name | sl_avail | total_avail ----------+----------+---------+----------+------------sh1 | 2 | sl1 | 5 | 2 sh3 | 4 | sl7 | 7 | 4 (2 linhas)
The output of the parser this time is the query tree SELECT shoe_ready.shoename, shoe_ready.sh_avail, shoe_ready.sl_name, shoe_ready.sl_avail, shoe_ready.total_avail FROM shoe_ready shoe_ready WHERE shoe_ready.total_avail >= 2;
The first rule applied will be the one for the shoe_ready view and it results in the query tree SELECT shoe_ready.shoename, shoe_ready.sh_avail, shoe_ready.sl_name, shoe_ready.sl_avail, shoe_ready.total_avail FROM (SELECT rsh.shoename, rsh.sh_avail, rsl.sl_name, rsl.sl_avail, min(rsh.sh_avail, rsl.sl_avail) AS total_avail FROM shoe rsh, shoelace rsl WHERE rsl.sl_color = rsh.slcolor AND rsl.sl_len_cm >= rsh.slminlen_cm AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready WHERE shoe_ready.total_avail >= 2;
Similarly, the rules for shoe and shoelace are substituted into the range table of the subquery, leading to a three-level final query tree: SELECT shoe_ready.shoename, shoe_ready.sh_avail, shoe_ready.sl_name, shoe_ready.sl_avail, shoe_ready.total_avail FROM (SELECT rsh.shoename, rsh.sh_avail, rsl.sl_name, rsl.sl_avail, min(rsh.sh_avail, rsl.sl_avail) AS total_avail FROM (SELECT sh.shoename, sh.sh_avail, sh.slcolor, sh.slminlen, sh.slminlen * un.un_fact AS slminlen_cm, sh.slmaxlen, sh.slmaxlen * un.un_fact AS slmaxlen_cm, sh.slunit FROM shoe_data sh, unit un WHERE sh.slunit = un.un_name) rsh, (SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit, s.sl_len * u.un_fact AS sl_len_cm
560
FROM shoelace_data s, unit u WHERE s.sl_unit = u.un_name) rsl WHERE rsl.sl_color = rsh.slcolor AND rsl.sl_len_cm >= rsh.slminlen_cm AND rsl.sl_len_cm <= rsh.slmaxlen_cm) shoe_ready WHERE shoe_ready.total_avail > 2;
It turns out that the planner will collapse this tree into a two-level query tree: the bottommost SELECT commands will be “pulled up” into the middle SELECT since there's no need to process them separately. But the middle SELECT will remain separate from the top, because it contains aggregate functions. If we pulled those up it would change the behavior of the topmost SELECT, which we don't want. However, collapsing the query tree is an optimization that the rewrite system doesn't have to concern itself with. Nota: There is currently no recursion stopping mechanism for view rules in the rule system (only for the other kinds of rules). This doesn't hurt much, because the only way to push this into an endless loop (bloating up the server process until it reaches the memory limit) is to create tables and then setup the view rules by hand with CREATE RULE in such a way, that one selects from the other that selects from the one. This could never happen if CREATE VIEW is used because for the first CREATE VIEW, the second relation does not exist and thus the first view cannot select from the second.
34.2.2. View Rules in Non-SELECT Statements Two details of the query tree aren't touched in the description of view rules above. These are the command type and the result relation. In fact, view rules don't need this information. There are only a few differences between a query tree for a SELECT and one for any other command. Obviously, they have a different command type and for a command other than a SELECT, the result relation points to the range-table entry where the result should go. Everything else is absolutely the same. So having two tables t1 and t2 with columns a and b, the query trees for the two statements SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a; UPDATE t1 SET b = t2.b WHERE t1.a = t2.a;
are nearly identical. In particular: •
The range tables contain entries for the tables t1 and t2.
•
The target lists contain one variable that points to column b of the range table entry for table t2.
•
The qualification expressions compare the columns a of both range-table entries for equality.
•
The join trees show a simple join between t1 and t2.
The consequence is, that both query trees result in similar execution plans: They are both joins over the two tables. For the UPDATE the missing columns from t1 are added to the target list by the planner and the final query tree will read as UPDATE t1 SET a = t1.a, b = t2.b WHERE t1.a = t2.a;
and thus the executor run over the join will produce exactly the same result set as a SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
will do. But there is a little problem in UPDATE: The executor does not care what the results from the join it is doing are meant for. It just produces a result set of rows. The difference that one is a SELECT command and the other is an UPDATE is handled in the caller of the executor. The caller still knows (looking at the query tree) that this is an UPDATE, and it knows that this result should go into table t1. But which of the rows that are there has to be replaced by the new row?
561
To resolve this problem, another entry is added to the target list in UPDATE (and also in DELETE) statements: the current tuple ID (CTID). This is a system column containing the file block number and position in the block for the row. Knowing the table, the CTID can be used to retrieve the original row of t1 to be updated. After adding the CTID to the target list, the query actually looks like SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
Now another detail of PostgreSQL enters the stage. Old table rows aren't overwritten, and this is why ROLLBACK is fast. In an UPDATE, the new result row is inserted into the table (after stripping the CTID) and in the row header of the old row, which the CTID pointed to, the cmax and xmax entries are set to the current
command counter and current transaction ID. Thus the old row is hidden, and after the transaction committed the vacuum cleaner can really move it out. Knowing all that, we can simply apply view rules in absolutely the same way to any command. There is no difference.
34.2.3. The Power of Views in PostgreSQL The above demonstrates how the rule system incorporates view definitions into the original query tree. In the second example, a simple SELECT from one view created a final query tree that is a join of 4 tables (unit was used twice with different names). The benefit of implementing views with the rule system is, that the planner has all the information about which tables have to be scanned plus the relationships between these tables plus the restrictive qualifications from the views plus the qualifications from the original query in one single query tree. And this is still the situation when the original query is already a join over views. The planner has to decide which is the best path to execute the query, and the more information the planner has, the better this decision can be. And the rule system as implemented in PostgreSQL ensures, that this is all information available about the query up to that point.
34.2.4. Updating a View What happens if a view is named as the target relation for an INSERT, UPDATE, or DELETE? After doing the substitutions described above, we will have a query tree in which the result relation points at a subquery rangetable entry. This will not work, so the rewriter throws an error if it sees it has produced such a thing. To change this, we can define rules that modify the behavior of these kinds of commands. This is the topic of the next section.
34.3. Rules on INSERT, UPDATE, and DELETE Rules that are defined on INSERT, UPDATE, and DELETE are significantly different from the view rules described in the previous section. First, their CREATE RULE command allows more: •
They are allowed to have no action.
•
They can have multiple actions.
•
They can be INSTEAD or not.
•
The pseudorelations NEW and OLD become useful.
•
They can have rule qualifications.
Second, they don't modify the query tree in place. Instead they create zero or more new query trees and can throw away the original one.
34.3.1. How Update Rules Work Keep the syntax CREATE RULE rule_name AS ON event TO object [WHERE rule_qualification] DO [INSTEAD] [action | (actions) | NOTHING];
562
in mind. In the following, update rules means rules that are defined on INSERT, UPDATE, or DELETE. Update rules get applied by the rule system when the result relation and the command type of a query tree are equal to the object and event given in the CREATE RULE command. For update rules, the rule system creates a list of query trees. Initially the query-tree list is empty. There can be zero (NOTHING key word), one, or multiple actions. To simplify, we will look at a rule with one action. This rule can have a qualification or not and it can be INSTEAD or not. What is a rule qualification? It is a restriction that tells when the actions of the rule should be done and when not. This qualification can only reference the pseudorelations NEW and/or OLD, which basically represent the relation that was given as object (but with a special meaning). So we have four cases that produce the following query trees for a one-action rule. No qualification and not INSTEAD the query tree from the rule action with the original query tree's qualification added No qualification but INSTEAD the query tree from the rule action with the original query tree's qualification added Qualification given and not INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification added Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added Finally, if the rule is not INSTEAD, the unchanged original query tree is added to the list. Since only qualified INSTEAD rules already add the original query tree, we end up with either one or two output query trees for a rule with one action. For ON INSERT rules, the original query (if not suppressed by INSTEAD) is done before any actions added by rules. This allows the actions to see the inserted row(s). But for ON UPDATE and ON DELETE rules, the original query is done after the actions added by rules. This ensures that the actions can see the to-be-updated or to-bedeleted rows; otherwise, the actions might do nothing because they find no rows matching their qualifications. The query trees generated from rule actions are thrown into the rewrite system again, and maybe more rules get applied resulting in more or less query trees. So the query trees in the rule actions must have either a different command type or a different result relation, otherwise, this recursive process will end up in a loop. There is a fixed recursion limit of currently 100 iterations. If after 100 iterations there are still update rules to apply, the rule system assumes a loop over multiple rule definitions and reports an error. The query trees found in the actions of the pg_rewrite system catalog are only templates. Since they can reference the range-table entries for NEW and OLD, some substitutions have to be made before they can be used. For any reference to NEW, the target list of the original query is searched for a corresponding entry. If found, that entry's expression replaces the reference. Otherwise, NEW means the same as OLD (for an UPDATE) or is replaced by a null value (for an INSERT). Any reference to OLD is replaced by a reference to the range-table entry that is the result relation. After the system is done applying update rules, it applies view rules to the produced query tree(s). Views cannot insert new update actions so there is no need to apply update rules to the output of view rewriting. 34.3.1.1. A First Rule Step by Step Say we want to trace changes to the sl_avail column in the shoelace_data relation. So we set up a log table and a rule that conditionally writes a log entry when an UPDATE is performed on shoelace_data.
563
CREATE TABLE shoelace_log ( sl_name text, sl_avail integer, log_who text, log_when timestamp );
-----
shoelace changed new available value who did it when
CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data WHERE NEW.sl_avail <> OLD.sl_avail DO INSERT INTO shoelace_log VALUES ( NEW.sl_name, NEW.sl_avail, current_user, current_timestamp );
Now someone does: UPDATE shoelace_data SET sl_avail = 6 WHERE sl_name = 'sl7';
and we look at the log table: SELECT * FROM shoelace_log; sl_name | sl_avail | log_who | log_when ---------+----------+---------+---------------------------------sl7 | 6 | Al | Tue Oct 20 16:14:45 1998 MET DST (1 linha)
That's what we expected. What happened in the background is the following. The parser created the query tree UPDATE shoelace_data SET sl_avail = 6 FROM shoelace_data shoelace_data WHERE shoelace_data.sl_name = 'sl7';
There is a rule log_shoelace that is ON UPDATE with the rule qualification expression NEW.sl_avail <> OLD.sl_avail
and the action INSERT INTO shoelace_log VALUES ( *NEW*.sl_name, *NEW*.sl_avail, current_user, current_timestamp ) FROM shoelace_data *NEW*, shoelace_data *OLD*;
(This looks a little strange since you can't normally write INSERT ... VALUES ... FROM. The FROM clause here is just to indicate that there are range-table entries in the query tree for *NEW* and *OLD*. These are needed so that they can be referenced by variables in the INSERT command's query tree.) The rule is a qualified non-INSTEAD rule, so the rule system has to return two query trees: the modified rule action and the original query tree. In step 1, the range table of the original query is incorporated into the rule's action query tree. This results in: INSERT INTO shoelace_log VALUES ( *NEW*.sl_name, *NEW*.sl_avail, current_user, current_timestamp ) FROM shoelace_data *NEW*, shoelace_data *OLD*, shoelace_data shoelace_data;
In step 2, the rule qualification is added to it, so the result set is restricted to rows where sl_avail changes:
564
INSERT INTO shoelace_log VALUES ( *NEW*.sl_name, *NEW*.sl_avail, current_user, current_timestamp ) FROM shoelace_data *NEW*, shoelace_data *OLD*, shoelace_data shoelace_data WHERE *NEW*.sl_avail <> *OLD*.sl_avail;
(This looks even stranger, since INSERT ... VALUES doesn't have a WHERE clause either, but the planner and executor will have no difficulty with it. They need to support this same functionality anyway for INSERT ... SELECT.) In step 3, the original query tree's qualification is added, restricting the result set further to only the rows that would have been touched by the original query: INSERT INTO shoelace_log VALUES ( *NEW*.sl_name, *NEW*.sl_avail, current_user, current_timestamp ) FROM shoelace_data *NEW*, shoelace_data *OLD*, shoelace_data shoelace_data WHERE *NEW*.sl_avail <> *OLD*.sl_avail AND shoelace_data.sl_name = 'sl7';
Step 4 replaces references to NEW by the target list entries from the original query tree or by the matching variable references from the result relation: INSERT INTO shoelace_log VALUES ( shoelace_data.sl_name, 6, current_user, current_timestamp ) FROM shoelace_data *NEW*, shoelace_data *OLD*, shoelace_data shoelace_data WHERE 6 <> *OLD*.sl_avail AND shoelace_data.sl_name = 'sl7';
Step 5 changes OLD references into result relation references: INSERT INTO shoelace_log VALUES ( shoelace_data.sl_name, 6, current_user, current_timestamp ) FROM shoelace_data *NEW*, shoelace_data *OLD*, shoelace_data shoelace_data WHERE 6 <> shoelace_data.sl_avail AND shoelace_data.sl_name = 'sl7';
That's it. Since the rule is not INSTEAD, we also output the original query tree. In short, the output from the rule system is a list of two query trees that correspond to these statements: INSERT INTO shoelace_log VALUES ( shoelace_data.sl_name, 6, current_user, current_timestamp ) FROM shoelace_data WHERE 6 <> shoelace_data.sl_avail AND shoelace_data.sl_name = 'sl7'; UPDATE shoelace_data SET sl_avail = 6 WHERE sl_name = 'sl7';
These are executed in this order, and that is exactly what the rule was meant to do. The substitutions and the added qualifications ensure that, if the original query would be, say, UPDATE shoelace_data SET sl_color = 'green' WHERE sl_name = 'sl7';
565
no log entry would get written. In that case, the original query tree does not contain a target list entry for sl_avail, so NEW.sl_avail will get replaced by shoelace_data.sl_avail. Thus, the extra command generated by the rule is INSERT INTO shoelace_log VALUES ( shoelace_data.sl_name, shoelace_data.sl_avail, current_user, current_timestamp ) FROM shoelace_data WHERE shoelace_data.sl_avail <> shoelace_data.sl_avail AND shoelace_data.sl_name = 'sl7';
and that qualification will never be true. It will also work if the original query modifies multiple rows. So if someone issued the command UPDATE shoelace_data SET sl_avail = 0 WHERE sl_color = 'black';
four rows in fact get updated (sl1, sl2, sl3, and sl4). But sl3 already has sl_avail = 0. In this case, the original query trees qualification is different and that results in the extra query tree INSERT INTO shoelace_log SELECT shoelace_data.sl_name, 0, current_user, current_timestamp FROM shoelace_data WHERE 0 <> shoelace_data.sl_avail AND shoelace_data.sl_color = 'black';
being generated by the rule. This query tree will surely insert three new log entries. And that's absolutely correct. Here we can see why it is important that the original query tree is executed last. If the UPDATE had been executed first, all the rows would have already been set to zero, so the logging INSERT would not find any row where 0 <> shoelace_data.sl_avail.
34.3.2. Cooperation with Views A simple way to protect view relations from the mentioned possibility that someone can try to run INSERT, UPDATE, or DELETE on them is to let those query trees get thrown away. So we create the rules CREATE DO CREATE DO CREATE DO
RULE shoe_ins_protect AS ON INSERT TO shoe INSTEAD NOTHING; RULE shoe_upd_protect AS ON UPDATE TO shoe INSTEAD NOTHING; RULE shoe_del_protect AS ON DELETE TO shoe INSTEAD NOTHING;
If someone now tries to do any of these operations on the view relation shoe, the rule system will apply these rules. Since the rules have no actions and are INSTEAD, the resulting list of query trees will be empty and the whole query will become nothing because there is nothing left to be optimized or executed after the rule system is done with it. A more sophisticated way to use the rule system is to create rules that rewrite the query tree into one that does the right operation on the real tables. To do that on the shoelace view, we create the following rules: CREATE RULE shoelace_ins AS ON INSERT TO shoelace DO INSTEAD INSERT INTO shoelace_data VALUES ( NEW.sl_name, NEW.sl_avail, NEW.sl_color, NEW.sl_len, NEW.sl_unit
566
); CREATE RULE shoelace_upd AS ON UPDATE TO shoelace DO INSTEAD UPDATE shoelace_data SET sl_name = NEW.sl_name, sl_avail = NEW.sl_avail, sl_color = NEW.sl_color, sl_len = NEW.sl_len, sl_unit = NEW.sl_unit WHERE sl_name = OLD.sl_name; CREATE RULE shoelace_del AS ON DELETE TO shoelace DO INSTEAD DELETE FROM shoelace_data WHERE sl_name = OLD.sl_name;
Now assume that once in a while, a pack of shoelaces arrives at the shop and a big parts list along with it. But you don't want to manually update the shoelace view every time. Instead we setup two little tables: one where you can insert the items from the part list, and one with a special trick. The creation commands for these are: CREATE TABLE shoelace_arrive ( arr_name text, arr_quant integer ); CREATE TABLE shoelace_ok ( ok_name text, ok_quant integer ); CREATE RULE shoelace_ok_ins AS ON INSERT TO shoelace_ok DO INSTEAD UPDATE shoelace SET sl_avail = sl_avail + NEW.ok_quant WHERE sl_name = NEW.ok_name;
Now you can fill the table shoelace_arrive with the data from the parts list: SELECT * FROM shoelace_arrive; arr_name | arr_quant ----------+----------sl3 | 10 sl6 | 20 sl8 | 20 (3 linhas)
Take a quick look at the current data: SELECT * FROM shoelace; sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm ----------+----------+----------+--------+---------+----------sl1 | 5 | black | 80 | cm | 80 sl2 | 6 | black | 100 | cm | 100 sl7 | 6 | brown | 60 | cm | 60 sl3 | 0 | black | 35 | inch | 88.9 sl4 | 8 | black | 40 | inch | 101.6 sl8 | 1 | brown | 40 | inch | 101.6 sl5 | 4 | brown | 1 | m | 100 sl6 | 0 | brown | 0.9 | m | 90 (8 linhas)
567
Now move the arrived shoelaces in: INSERT INTO shoelace_ok SELECT * FROM shoelace_arrive;
and check the results: SELECT * FROM shoelace ORDER BY sl_name; sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm ----------+----------+----------+--------+---------+----------sl1 | 5 | black | 80 | cm | 80 sl2 | 6 | black | 100 | cm | 100 sl7 | 6 | brown | 60 | cm | 60 sl4 | 8 | black | 40 | inch | 101.6 sl3 | 10 | black | 35 | inch | 88.9 sl8 | 21 | brown | 40 | inch | 101.6 sl5 | 4 | brown | 1 | m | 100 sl6 | 20 | brown | 0.9 | m | 90 (8 linhas) SELECT * FROM shoelace_log; sl_name | sl_avail | log_who| log_when ---------+----------+--------+---------------------------------sl7 | 6 | Al | Tue Oct 20 19:14:45 1998 MET DST sl3 | 10 | Al | Tue Oct 20 19:25:16 1998 MET DST sl6 | 20 | Al | Tue Oct 20 19:25:16 1998 MET DST sl8 | 21 | Al | Tue Oct 20 19:25:16 1998 MET DST (4 linhas)
It's a long way from the one INSERT ... SELECT to these results. And the description of the query-tree transformation will be the last in this chapter. First, there is the parser's output INSERT INTO shoelace_ok SELECT shoelace_arrive.arr_name, shoelace_arrive.arr_quant FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok;
Now the first rule shoelace_ok_ins is applied and turns this into UPDATE shoelace SET sl_avail = shoelace.sl_avail + shoelace_arrive.arr_quant FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok, shoelace_ok *OLD*, shoelace_ok *NEW*, shoelace shoelace WHERE shoelace.sl_name = shoelace_arrive.arr_name;
and throws away the original INSERT on shoelace_ok. This rewritten query is passed to the rule system again, and the second applied rule shoelace_upd produces UPDATE shoelace_data SET sl_name = shoelace.sl_name, sl_avail = shoelace.sl_avail + shoelace_arrive.arr_quant, sl_color = shoelace.sl_color, sl_len = shoelace.sl_len, sl_unit = shoelace.sl_unit FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok, shoelace_ok *OLD*, shoelace_ok *NEW*, shoelace shoelace, shoelace *OLD*, shoelace *NEW*, shoelace_data shoelace_data WHERE shoelace.sl_name = shoelace_arrive.arr_name AND shoelace_data.sl_name = shoelace.sl_name;
568
Again it's an INSTEAD rule and the previous query tree is trashed. Note that this query still uses the view shoelace. But the rule system isn't finished with this step, so it continues and applies the _RETURN rule on it, and we get UPDATE shoelace_data SET sl_name = s.sl_name, sl_avail = s.sl_avail + shoelace_arrive.arr_quant, sl_color = s.sl_color, sl_len = s.sl_len, sl_unit = s.sl_unit FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok, shoelace_ok *OLD*, shoelace_ok *NEW*, shoelace shoelace, shoelace *OLD*, shoelace *NEW*, shoelace_data shoelace_data, shoelace *OLD*, shoelace *NEW*, shoelace_data s, unit u WHERE s.sl_name = shoelace_arrive.arr_name AND shoelace_data.sl_name = s.sl_name;
Finally, the rule log_shoelace gets applied, producing the extra query tree INSERT INTO shoelace_log SELECT s.sl_name, s.sl_avail + shoelace_arrive.arr_quant, current_user, current_timestamp FROM shoelace_arrive shoelace_arrive, shoelace_ok shoelace_ok, shoelace_ok *OLD*, shoelace_ok *NEW*, shoelace shoelace, shoelace *OLD*, shoelace *NEW*, shoelace_data shoelace_data, shoelace *OLD*, shoelace *NEW*, shoelace_data s, unit u, shoelace_data *OLD*, shoelace_data *NEW* shoelace_log shoelace_log WHERE s.sl_name = shoelace_arrive.arr_name AND shoelace_data.sl_name = s.sl_name AND (s.sl_avail + shoelace_arrive.arr_quant) <> s.sl_avail;
After that the rule system runs out of rules and returns the generated query trees. So we end up with two final query trees that are equivalent to the SQL statements INSERT INTO shoelace_log SELECT s.sl_name, s.sl_avail + shoelace_arrive.arr_quant, current_user, current_timestamp FROM shoelace_arrive shoelace_arrive, shoelace_data shoelace_data, shoelace_data s WHERE s.sl_name = shoelace_arrive.arr_name AND shoelace_data.sl_name = s.sl_name AND s.sl_avail + shoelace_arrive.arr_quant <> s.sl_avail; UPDATE shoelace_data SET sl_avail = shoelace_data.sl_avail + shoelace_arrive.arr_quant FROM shoelace_arrive shoelace_arrive, shoelace_data shoelace_data, shoelace_data s WHERE s.sl_name = shoelace_arrive.sl_name AND shoelace_data.sl_name = s.sl_name;
569
The result is that data coming from one relation inserted into another, changed into updates on a third, changed into updating a fourth plus logging that final update in a fifth gets reduced into two queries. There is a little detail that's a bit ugly. Looking at the two queries, it turns out that the shoelace_data relation appears twice in the range table where it could definitely be reduced to one. The planner does not handle it and so the execution plan for the rule systems output of the INSERT will be Nested Loop -> Merge Join -> Seq Scan -> Sort -> Seq Scan on s -> Seq Scan -> Sort -> Seq Scan on shoelace_arrive -> Seq Scan on shoelace_data
while omitting the extra range table entry would result in a Merge Join -> Seq Scan -> Sort -> -> Seq Scan -> Sort ->
Seq Scan on s
Seq Scan on shoelace_arrive
which produces exactly the same entries in the log table. Thus, the rule system caused one extra scan on the table shoelace_data that is absolutely not necessary. And the same redundant scan is done once more in the UPDATE. But it was a really hard job to make that all possible at all. Now we make a final demonstration of the PostgreSQL rule system and its power. Say you add some shoelaces with extraordinary colors to your database: INSERT INTO shoelace VALUES ('sl9', 0, 'pink', 35.0, 'inch', 0.0); INSERT INTO shoelace VALUES ('sl10', 1000, 'magenta', 40.0, 'inch', 0.0);
We would like to make a view to check which shoelace entries do not fit any shoe in color. The view for this is CREATE VIEW shoelace_mismatch AS SELECT * FROM shoelace WHERE NOT EXISTS (SELECT shoename FROM shoe WHERE slcolor = sl_color);
Its output is SELECT * FROM shoelace_mismatch; sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm ---------+----------+----------+--------+---------+----------sl9 | 0 | pink | 35 | inch | 88.9 sl10 | 1000 | magenta | 40 | inch | 101.6
Now we want to set it up so that mismatching shoelaces that are not in stock are deleted from the database. To make it a little harder for PostgreSQL, we don't delete it directly. Instead we create one more view CREATE VIEW shoelace_can_delete AS SELECT * FROM shoelace_mismatch WHERE sl_avail = 0;
and do it this way:
570
DELETE FROM shoelace WHERE EXISTS (SELECT * FROM shoelace_can_delete WHERE sl_name = shoelace.sl_name);
Voilà: SELECT * FROM shoelace; sl_name | sl_avail | sl_color | sl_len | sl_unit | sl_len_cm ---------+----------+----------+--------+---------+----------sl1 | 5 | black | 80 | cm | 80 sl2 | 6 | black | 100 | cm | 100 sl7 | 6 | brown | 60 | cm | 60 sl4 | 8 | black | 40 | inch | 101.6 sl3 | 10 | black | 35 | inch | 88.9 sl8 | 21 | brown | 40 | inch | 101.6 sl10 | 1000 | magenta | 40 | inch | 101.6 sl5 | 4 | brown | 1 | m | 100 sl6 | 20 | brown | 0.9 | m | 90 (9 linhas)
A DELETE on a view, with a subquery qualification that in total uses 4 nesting/joined views, where one of them itself has a subquery qualification containing a view and where calculated view columns are used, gets rewritten into one single query tree that deletes the requested data from a real table. There are probably only a few situations out in the real world where such a construct is necessary. But it makes you feel comfortable that it works.
34.4. Rules and Privileges Due to rewriting of queries by the PostgreSQL rule system, other tables/views than those used in the original query get accessed. When update rules are used, this can include write access to tables. Rewrite rules don't have a separate owner. The owner of a relation (table or view) is automatically the owner of the rewrite rules that are defined for it. The PostgreSQL rule system changes the behavior of the default access control system. Relations that are used due to rules get checked against the privileges of the rule owner, not the user invoking the rule. This means that a user only needs the required privileges for the tables/views that he names explicitly in his queries. For example: A user has a list of phone numbers where some of them are private, the others are of interest for the secretary of the office. He can construct the following: CREATE TABLE phone_data (person text, phone text, private boolean); CREATE VIEW phone_number AS SELECT person, phone FROM phone_data WHERE NOT private; GRANT SELECT ON phone_number TO secretary;
Nobody except him (and the database superusers) can access the phone_data table. But because of the GRANT, the secretary can run a SELECT on the phone_number view. The rule system will rewrite the SELECT from phone_number into a SELECT from phone_data and add the qualification that only entries where private is false are wanted. Since the user is the owner of phone_number and therefore the owner of the rule, the read access to phone_data is now checked against his privileges and the query is permitted. The check for accessing phone_number is also performed, but this is done against the invoking user, so nobody but the user and the secretary can use it. The privileges are checked rule by rule. So the secretary is for now the only one who can see the public phone numbers. But the secretary can setup another view and grant access to that to the public. Then, anyone can see the phone_number data through the secretary's view. What the secretary cannot do is to create a view that directly accesses phone_data. (Actually he can, but it will not work since every access will be denied during the permission checks.) And as soon as the user will notice, that the secretary opened his phone_number view, he can revoke his access. Immediately, any access to the secretary's view would fail.
571
One might think that this rule-by-rule checking is a security hole, but in fact it isn't. But if it did not work this way, the secretary could set up a table with the same columns as phone_number and copy the data to there once per day. Then it's his own data and he can grant access to everyone he wants. A GRANT command means, “I trust you”. If someone you trust does the thing above, it's time to think it over and then use REVOKE. This mechanism also works for update rules. In the examples of the previous section, the owner of the tables in the example database could grant the privileges SELECT, INSERT, UPDATE, and DELETE on the shoelace view to someone else, but only SELECT on shoelace_log. The rule action to write log entries will still be executed successfully, and that other user could see the log entries. But he cannot create fake entries, nor could he manipulate or remove existing ones.
34.5. Rules and Command Status The PostgreSQL server returns a command status string, such as INSERT 149592 1, for each command it receives. This is simple enough when there are no rules involved, but what happens when the query is rewritten by rules? Rules affect the command status as follows: •
If there is no unconditional INSTEAD rule for the query, then the originally given query will be executed, and its command status will be returned as usual. (But note that if there were any conditional INSTEAD rules, the negation of their qualifications will have been added to the original query. This may reduce the number of rows it processes, and if so the reported status will be affected.)
•
If there is any unconditional INSTEAD rule for the query, then the original query will not be executed at all. In this case, the server will return the command status for the last query that was inserted by an INSTEAD rule (conditional or unconditional) and is of the same command type (INSERT, UPDATE, or DELETE) as the original query. If no query meeting those requirements is added by any rule, then the returned command status shows the original query type and zeroes for the row-count and OID fields.
(This system was established in PostgreSQL 7.3. In versions before that, the command status might show different results when rules exist.) The programmer can ensure that any desired INSTEAD rule is the one that sets the command status in the second case, by giving it the alphabetically last rule name among the active rules, so that it gets applied last.
34.6. Rules versus Triggers Many things that can be done using triggers can also be implemented using the PostgreSQL rule system. One of the things that cannot be implemented by rules are some kinds of constraints, especially foreign keys. It is possible to place a qualified rule that rewrites a command to NOTHING if the value of a column does not appear in another table. But then the data is silently thrown away and that's not a good idea. If checks for valid values are required, and in the case of an invalid value an error message should be generated, it must be done by a trigger. On the other hand, a trigger that is fired on INSERT on a view can do the same as a rule: put the data somewhere else and suppress the insert in the view. But it cannot do the same thing on UPDATE or DELETE, because there is no real data in the view relation that could be scanned, and thus the trigger would never get called. Only a rule will help. For the things that can be implemented by both, it depends on the usage of the database, which is the best. A trigger is fired for any affected row once. A rule manipulates the query tree or generates an additional one. So if many rows are affected in one statement, a rule issuing one extra command would usually do a better job than a trigger that is called for every single row and must execute its operations many times. Here we show an example of how the choice of rules versus triggers plays out in one situation. There are two tables: CREATE TABLE computer ( hostname text, manufacturer text );
-- indexed -- indexed
572
CREATE TABLE software ( software text, hostname text );
-- indexed -- indexed
Both tables have many thousands of rows and the indexes on hostname are unique. The rule or trigger should implement a constraint that deletes rows from software that reference a deleted computer. The trigger would use this command: DELETE FROM software WHERE hostname = $1;
Since the trigger is called for each individual row deleted from computer, it can prepare and save the plan for this command and pass the hostname value in the parameter. The rule would be written as CREATE RULE computer_del AS ON DELETE TO computer DO DELETE FROM software WHERE hostname = OLD.hostname;
Now we look at different types of deletes. In the case of a DELETE FROM computer WHERE hostname = 'mypc.local.net';
the table computer is scanned by index (fast), and the command issued by the trigger would also use an index scan (also fast). The extra command from the rule would be DELETE FROM software WHERE computer.hostname = 'mypc.local.net' AND software.hostname = computer.hostname;
Since there are appropriate indexes setup, the planner will create a plan of Nestloop -> Index Scan using comp_hostidx on computer -> Index Scan using soft_hostidx on software
So there would be not that much difference in speed between the trigger and the rule implementation. With the next delete we want to get rid of all the 2000 computers where the hostname starts with old. There are two possible commands to do that. One is DELETE FROM computer WHERE hostname >= 'old' AND hostname < 'ole'
The command added by the rule will be DELETE FROM software WHERE computer.hostname >= 'old' AND computer.hostname < 'ole' AND software.hostname = computer.hostname;
with the plan Hash Join -> Seq Scan on software -> Hash -> Index Scan using comp_hostidx on computer
The other possible command is DELETE FROM computer WHERE hostname ~ '^old';
which results in the following executing plan for the command added by the rule: Nestloop -> Index Scan using comp_hostidx on computer -> Index Scan using soft_hostidx on software
573
This shows, that the planner does not realize that the qualification for hostname in computer could also be used for an index scan on software when there are multiple qualification expressions combined with AND, which is what it does in the regular-expression version of the command. The trigger will get invoked once for each of the 2000 old computers that have to be deleted, and that will result in one index scan over computer and 2000 index scans over software. The rule implementation will do it with two commands that use indexes. And it depends on the overall size of the table software whether the rule will still be faster in the sequential scan situation. 2000 command executions from the trigger over the SPI manager take some time, even if all the index blocks will soon be in the cache. The last command we look at is DELETE FROM computer WHERE manufacurer = 'bim';
Again this could result in many rows to be deleted from computer. So the trigger will again run many commands through the executor. The command generated by the rule will be DELETE FROM software WHERE computer.manufacurer = 'bim' AND software.hostname = computer.hostname;
The plan for that command will again be the nested loop over two index scans, only using a different index on computer: Nestloop -> Index Scan using comp_manufidx on computer -> Index Scan using soft_hostidx on software
In any of these cases, the extra commands from the rule system will be more or less independent from the number of affected rows in a command. The summary is, rules will only be significantly slower than triggers if their actions result in large and badly qualified joins, a situation where the planner fails.
574
Capítulo 35. Gatilhos Este capítulo descreve como são escritas as funções de gatilho. As funções de gatilho podem ser escritas em C, ou em alguma das linguagens procedurais disponíveis. Atualmente não é possível escrever funções de gatilho na linguagem SQL.
35.1. Visão geral do comportamento do gatilho O gatilho pode ser definido para executar antes ou após uma operação de INSERT, UPDATE ou DELETE, podendo ser executado uma vez por linha modificada ou por declaração SQL. Se um evento de gatilho ocorrer, a função de gatilho é chamada no momento apropriado para tratar o evento. A função de gatilho deve ser definida antes da criação do gatilho. A função de gatilho deve ser declarada como uma função que não recebe nenhum argumento, e que retorna o tipo trigger (A função de gatilho recebe sua entrada através da estrutura TriggerData passada especialmente, e não na forma de argumentos usuais de função). Uma vez que a função de gatilho apropriada tenha sido criada, o gatilho é estabelecido através de CREATE TRIGGER. A mesma função de gatilho pode ser utilizada por vários gatilhos. As funções de gatilho retornam uma linha de tabela (um valor do tipo HeapTuple) para o executor que fez a chamada. Um gatilho disparado antes de uma operação possui as seguintes escolhas: •
Pode retornar um ponteiro NULL para saltar a operação para a linha corrente (e, portanto, não haverá inserção/atualização/exclusão).
•
Para os gatilhos de INSERT e UPDATE apenas, a linha retornada se torna a linha a ser inserida ou a que vai substituir a linha sendo atualizada. Isto permite que a função de gatilho modifique a linha sendo inserida ou atualizada.
Um gatilho para disparar antes que não tenha intenção de causar nenhum destes comportamentos, deve ter o cuidado de retornar como seu resultado a mesma linha que foi passada (ou seja, a linha NEW para os gatilhos INSERT e UPDATE, e a linha OLD para os gatilhos de exclusão). O valor retornado é ignorado nos gatilhos disparados após uma operação e, portanto, podem simplesmente retornar NULL. Se mais de um gatilho for definido para o mesmo evento na mesma relação, os gatilhos serão disparados na ordem alfabética dos nomes dos gatilhos. No caso dos gatilhos para antes, a linha possivelmente modificada retornada por cada gatilho se torna a entrada do próximo gatilho. Se qualquer gatilho para antes retornar um ponteiro NULL, a operação é abandonada e os gatilhos seguintes não são disparados. Se a função de gatilho executar comandos SQL, então estes comandos podem disparar gatilhos novamente. Isto é conhecido como gatilhos em cascata. Não existe nenhuma limitação direta do número de níveis da cascata. É possível as cascatas causarem chamadas recursivas ao mesmo gatilho; por exemplo, um gatilho INSERT pode executar um comando que insere uma linha adicional na mesma tabela, fazendo com que o gatilho INSERT seja disparado novamente. É responsabilidade do programador do gatilho evitar uma recursão infinita neste cenário. Quando o gatilho está sendo definido, podem ser especificados argumentos para o mesmo. A finalidade de incluir argumentos na definição do gatilho é permitir gatilhos diferentes, com requisitos semelhantes, chamarem a mesma função. Como exemplo, pode haver uma função de gatilho generalizada que recebe como argumento dois nomes de coluna, coloca o usuário corrente em um e a data e hora corrente no outro. Escrita de forma apropriada, esta função de gatilho pode ser independente da tabela específica de onde é disparada. Portanto, a mesma função pode ser utilizada para eventos de INSERT em qualquer tabela com colunas apropriadas, para acompanhar automaticamente a criação de linhas na tabela de transação, por exemplo. Também pode ser utilizada para acompanhar os eventos de última atualização, se for definida em um gatilho de UPDATE.
575
35.2. Visibilidade das mudança nos dados Se forem executados comandos SQL na função de gatilho, e estes comandos acessarem a tabela para a qual o gatilho se destina, então se deve ter conhecimento das regras de visibilidade dos dados, porque estas determinam se estes comandos SQL enxergam a mudança nos dados para a qual o gatilho foi disparado. Em resumo: •
A mudança nos dados (inserção, atualização ou exclusão) que causou o disparo do gatilho naturalmente não pode ser enxergada pelos comandos SQL executados no gatilho para antes, porque ainda não aconteceram.
•
Entretanto, os comandos SQL executados em um gatilho para antes enxergam os efeitos das mudanças nos dados das linhas processadas anteriormente no mesmo comando externo. Isto requer cautela, uma vez que a ordem destes eventos de mudança geralmente não é previsível; um comando SQL que afeta várias linhas pode atuar sobre as linhas em qualquer ordem.
•
Quando um gatilho para depois é disparado, todas as mudanças nos dados feitas pelo comando externo estão completas, sendo enxergadas pelos comandos SQL.
Mais informações sobre as regras de visibilidade dos dados podem ser encontradas na Seção 41.4. O exemplo na Seção 35.4 contém uma demonstração destas regras.
35.3. Como escrever funções de gatilho em C Esta seção descreve os detalhes de baixo nível da interface da função de gatilho. Esta informação somente é necessária para se escrever uma função de gatilho em C. Se estiver sendo utilizada uma linguagem de nível mais alto, então estes detalhes são tratados para você. A documentação de cada linguagem procedural explica como escrever gatilhos nesta linguagem. A função de gatilho deve utilizar a interface de gerência de função “versão 1”. Quando uma função é chamada pelo gerenciador de gatilho não é passado nenhum argumento normal, mas é passado um ponteiro de “contexto” apontando para a estrutura TriggerData. As funções em C podem verificar se foram chamadas pelo gerenciador de gatilhos executando a macro CALLED_AS_TRIGGER(fcinfo)
que expande para ((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
Se retornar verdade, então é seguro converter fcinfo->context no tipo TriggerData * e fazer uso da estrutura TriggerData apontada. A função não deve alterar a estrutura TriggerData ou algum dos dados para o qual esta aponta. A estrutura TriggerData está definida em commands/trigger.h: typedef struct TriggerData { NodeTag type; TriggerEvent tg_event; Relation tg_relation; HeapTuple tg_trigtuple; HeapTuple tg_newtuple; Trigger *tg_trigger; } TriggerData;
onde os membros estão definidos conforme mostrado abaixo: type
Sempre T_TriggerData.
576
tg_event
Descreve o evento para o qual a função foi chamada. Podem ser utilizadas as seguintes macros para examinar tg_event: TRIGGER_FIRED_BEFORE(tg_event)
Retorna verdade se o gatilho disparou antes da operação. TRIGGER_FIRED_AFTER(tg_event)
Retorna verdade se o gatilho disparou após a operação. TRIGGER_FIRED_FOR_ROW(tg_event)
Retorna verdade se o gatilho disparou para um evento no nível de linha. TRIGGER_FIRED_FOR_STATEMENT(tg_event)
Retorna verdade se o gatilho disparou para um evento no nível de declaração. TRIGGER_FIRED_BY_INSERT(tg_event)
Retorna verdade se o gatilho foi disparado por um comando INSERT. TRIGGER_FIRED_BY_UPDATE(tg_event)
Retorna verdade se o gatilho foi disparado por um comando UPDATE. TRIGGER_FIRED_BY_DELETE(tg_event)
Retorna verdade se o gatilho foi disparado por um comando DELETE. tg_relation
Um ponteiro para a estrutura que descreve a relação para a qual o gatilho foi disparado. Procure em utils/rel.h os detalhes sobre esta estrutura. As coisas mais interessantes são tg_relation->rd_att (descritor das tuplas da relação) e tg_relation->rd_rel->relname (nome da relação; o tipo não é char*, e sim NameData; deve ser utilizado SPI_getrelname(tg_relation) para obter char* se for
necessário copiar o nome). tg_trigtuple
Um ponteiro para a linha para a qual o gatilho foi disparado. Esta é a linha sendo inserida, atualizada ou excluída. Se este gatilho foi disparado para um INSERT ou para um DELETE, então é o que deve ser retornado pela função se não for desejado substituir a linha por outra diferente (no caso do INSERT), ou se for desejado saltar a operação. tg_newtuple
Um ponteiro para a nova versão da linha, se o gatilho foi disparado por um UPDATE, ou NULL se foi disparado por um INSERT ou DELETE. É o que deve ser retornado pela função se o evento for um UPDATE e não for desejado substituir a linha por outra diferente, ou se for desejado saltar a operação. tg_trigger
Um ponteiro para a estrutura do tipo Trigger, definida em utils/rel.h: typedef struct Trigger { Oid tgoid; char *tgname; Oid tgfoid; int16 tgtype; bool tgenabled; bool tgisconstraint; Oid tgconstrrelid; bool tgdeferrable; bool tginitdeferred; int16 tgnargs; int16 tgattr[FUNC_MAX_ARGS]; char **tgargs; } Trigger;
577
onde tgname é o nome do gatilho, tgnargs é o número de argumentos em tgargs, e tgargs é uma matriz de ponteiros para os argumentos especificados na declaração CREATE TRIGGER. Os outros membros são para uso interno apenas. Uma função de gatilho deve retornar NULL ou um ponteiro para HeapTuple. Tome o cuidado de retornar tg_trigtuple ou tg_newtuple, conforme for apropriado, se não for desejado modificar a linha onde está sendo realizada a operação.
35.4. Um exemplo completo Abaixo está mostrado um exemplo muito simples de uma função de gatilho escrita em C (Exemplos de gatilhos escritos nas linguagens procedurais podem ser encontrados na documentação das linguagens procedurais). A função trigf informa o número de linhas na tabela ttest, e salta a operação se o comando tentar inserir um valor nulo na coluna x (Portanto, o gatilho age como uma restrição de não nulo, mas não interrompe a transação). Primeiro, a definição da tabela: CREATE TABLE ttest ( x integer );
A seguir está o código fonte da função de gatilho: #include "postgres.h" #include "executor/spi.h" #include "commands/trigger.h"
/* necessário para trabalhar com SPI */ /* ... e gatilhos */
extern Datum trigf(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(trigf); Datum trigf(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; TupleDesc tupdesc; HeapTuple rettuple; char *when; bool checknull = false; bool isnull; int ret, i; /* certificar-se que foi chamado por um gatilho */ if (!CALLED_AS_TRIGGER(fcinfo)) elog(ERROR, "trigf: não foi chamada por um gerenciador de gatilho"); /* tupla a ser retornada para o executor */ if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) rettuple = trigdata->tg_newtuple; else rettuple = trigdata->tg_trigtuple; /* verificar valores nulos */ if (!TRIGGER_FIRED_BY_DELETE(trigdata->tg_event) && TRIGGER_FIRED_BEFORE(trigdata->tg_event)) checknull = true; if (TRIGGER_FIRED_BEFORE(trigdata->tg_event)) when = "before"; else
578
when = "after "; tupdesc = trigdata->tg_relation->rd_att; /* conectar ao gerenciador de SPI */ if ((ret = SPI_connect()) < 0) elog(INFO, "trigf (disparado %s): SPI_connect retornou %d", when, ret); /* get number of rows in table */ ret = SPI_exec("SELECT count(*) FROM ttest", 0); if (ret < 0) elog(NOTICE, "trigf (disparado %s): SPI_exec retornou %d", when, ret); /* count(*) returns int8, so be careful to convert */ i = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); elog (INFO, "trigf (disparado %s): existem %d linhas em ttest", when, i); SPI_finish(); if (checknull) { SPI_getbinval(rettuple, tupdesc, 1, &isnull); if (isnull) rettuple = NULL; } return PointerGetDatum(rettuple); }
Após compilar o código fonte, a função e o gatilho são declarados: CREATE FUNCTION trigf() RETURNS trigger AS 'nome_do_arquivo' LANGUAGE C; CREATE TRIGGER tbefore BEFORE INSERT OR UPDATE OR DELETE ON ttest FOR EACH ROW EXECUTE PROCEDURE trigf(); CREATE TRIGGER tafter AFTER INSERT OR UPDATE OR DELETE ON ttest FOR EACH ROW EXECUTE PROCEDURE trigf();
Agora pode ser testada a operação do gatilho: => INSERT INTO ttest VALUES (NULL); INFO: trigf (disparado before): existem 0 linhas em ttest INSERT 0 0 -- Inserção saltada e gatilho AFTER não é disparado => SELECT * FROM ttest; x --(0 linhas) => INSERT INTO ttest VALUES (1); INFO: trigf (disparado before): existem 0 linhas em ttest
579
INFO:
trigf (disparado after ): existem 1 linhas em ttest ^^^^^^^^ lembre-se do que foi dito sobre visibilidade. INSERT 167793 1 vac=> SELECT * FROM ttest; x --1 (1 linha) => INSERT INTO ttest SELECT x * 2 FROM ttest; INFO: trigf (disparado before): existem 1 linhas em ttest INFO: trigf (disparado after ): existem 2 linhas em ttest ^^^^^^^^ lembre-se do que foi dito sobre visibilidade. INSERT 167794 1 => SELECT * FROM ttest; x --1 2 (2 linhas) => UPDATE ttest SET x = NULL WHERE x = 2; INFO: trigf (disparado before): existem 2 linhas em ttest UPDATE 0 => UPDATE ttest SET x = 4 WHERE x = 2; INFO: trigf (disparado before): existem 2 linhas em ttest INFO: trigf (disparado after ): existem 2 linhas em ttest UPDATE 1 vac=> SELECT * FROM ttest; x --1 4 (2 linhas) => DELETE FROM ttest; INFO: trigf (disparado before): existem 2 linhas em ttest INFO: trigf (disparado after ): existem 1 linhas em ttest INFO: trigf (disparado before): existem 1 linhas em ttest INFO: trigf (disparado after ): existem 0 linhas em ttest ^^^^^^^^ lembre-se do que foi dito sobre visibilidade. DELETE 2 => SELECT * FROM ttest; x --(0 linhas)
Existem exemplos mais complexos em src/test/regress/regress.c e em contrib/spi.
580
Capítulo 36. Linguagens procedurais O PostgreSQL permite os usuários adicionarem novas linguagens de programação e torná-las disponíveis para escrever funções e procedimentos. São chamadas de linguagens procedurais (PL). No caso de uma função ou gatilho escrito em uma linguagem procedural, o servidor de banco de dados não possui nenhum conhecimento incorporado sobre como interpretar o texto fonte da função. Em vez disso, a tarefa é passada para um tratador especial que conhece os detalhes da linguagem. O tratador pode fazer todo o trabalho de análise, análise sintática, execução, etc. por si próprio, ou pode servir de “ponte” entre o PostgreSQL e a implementação existente da linguagem de programação. O próprio tratador é uma função especial escrita em C, compilada em um objeto compartilhado, e carregada conforme houver necessidade. Como escrever um tratador para uma nova linguagem procedural está descrito no Capítulo 47. Várias linguagens procedurais estão disponíveis na distribuição padrão do PostgreSQL, podendo servir de exemplo.
36.1. Instalação da linguagem procedural A linguagem procedural deve ser “instalada” em cada banco de dados onde vai ser utilizada. Porém, as linguagens procedurais instaladas no banco de dados template1 ficam disponíveis em todos os bancos de dados criados após sua instalação. Portanto, o administrador de banco de dados pode decidir quais linguagens ficarão disponíveis em quais bancos de dados, e pode tornar algumas linguagens disponíveis por padrão se assim o decidir. Para as linguagens fornecidas na distribuição padrão, o programa createlang pode ser utilizado para instalar a linguagem em vez de executar os detalhes manualmente. Por exemplo, para instalar a linguagem PL/pgSQL no banco de dados template1 é utilizado: createlang plpgsql template1
O procedimento manual descrito abaixo somente é recomendado para a instalação de linguagens personalizadas que o programa createlang desconhece. Instalação manual de linguagem procedural A linguagem procedural é instalada no banco de dados em três passos, que devem ser efetuados por um superusuário do banco de dados. O programa createlang automatiza o passo 2 e o passo 3. 1.
O objeto compartilhado contendo o tratador da linguagem deve ser compilado e instalado no diretório de biblioteca apropriado. Funciona da mesma maneira que na construção e instalação dos módulos das funções C definidas pelo usuário; veja a Seção 33.7.6.
2.
O tratador deve ser declarado pelo comando: CREATE FUNCTION nome_da_função_tratadora() RETURNS language_handler AS 'caminho_para_o_objeto_compartilhado' LANGUAGE C;
O tipo especial retornado language_handler informa ao sistema de banco de dados que a função não retorna um dos tipos de dado definidos no SQL, e que não pode ser utilizada diretamente nas declarações SQL. 3.
A linguagem procedural deve ser declarada através do comando: CREATE [TRUSTED] [PROCEDURAL] LANGUAGE nome_da_linguagem HANDLER nome_da_função_tratadora;
A palavra opcional TRUSTED (confiável) especifica que deve ser permitido aos usuários comuns do banco de dados, que não possuem privilégio de superusuário, utilizarem esta linguagem para criar funções e procedimentos de gatilhos. Uma vez que as funções na linguagem procedural são executadas dentro do servidor de banco de dados, o sinalizador TRUSTED somente deve ser especificado para as linguagens que não permitem acesso às funcionalidades internas do servidor de banco de dados, nem ao sistema de
581
arquivos. As linguagens PL/pgSQL, PL/Tcl e PL/Perl são consideradas confiáveis; as linguagens PL/TclU, PL/PerlU e PL/PythonU foram projetadas para fornecer funcionalidades sem limitações, não devendo ser marcadas como confiáveis. O Exemplo 36-1 mostra como o procedimento de instalação manual funciona com a linguagem PL/pgSQL. Exemplo 36-1. Instalação manual do PL/pgSQL O comando abaixo informa ao servidor de banco de dados onde encontrar o objeto compartilhado da função tratadora de chamadas da linguagem PL/pgSQL: CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS '$libdir/plpgsql' LANGUAGE C;
O comando CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql HANDLER plpgsql_call_handler;
então define que a função tratadora de chamadas declarada anteriormente deve ser chamada para as funções e procedimentos de gatilho onde o atributo de linguagem for plpgsql. Na instalação padrão do PostgreSQL, o tratador para a linguagem PL/pgSQL é construído e instalado no diretório “library”. Se o suporte para Tcl/Tk estiver configurado, os tratadores para PL/Tcl e PL/TclU também serão construídos e instalados no mesmo local. Da mesma maneira, os tratadores para PL/Perl e PL/PerlU serão construídos e instalados se o suporte ao Perl estiver configurado, e PL/PythonU será instalado se o suporte ao Python estiver configurado.
582
Capítulo 37. PL/pgSQL - Linguagem procedural SQL PL/pgSQL é uma linguagem procedural carregável desenvolvida para o sistema de banco de dados PostgreSQL. Os objetivos de projeto da linguagem PL/pgSQL foram no sentido de criar uma linguagem procedural carregável que pudesse: •
ser utilizada para criar procedimentos de funções e de gatilhos;
•
adicionar estruturas de controle à linguagem SQL;
•
realizar processamentos complexos;
•
herdar todos os tipos, funções e operadores definidos pelo usuário;
•
ser definida como confiável pelo servidor;
•
ser fácil de utilizar.
37.1. Visão geral O tratador de chamadas da linguagem PL/pgSQL analisa o texto do código fonte, e produz uma árvore binária interna de instruções na primeira vez em que a função é chamada (em cada sessão). A árvore de instruções traduz inteiramente a estrutura das declarações do PL/pgSQL, mas as expressões SQL individuais e os comandos SQL utilizados na função não são traduzidos imediatamente. Assim que cada expressão ou comando SQL é utilizado pela primeira vez na função, o interpretador do PL/pgSQL cria um plano de execução preparado (utilizando as funções SPI_prepare e SPI_saveplan da Interface de Programação do Servidor - SPI). As execuções posteriores da expressão ou do comando reutilizam o plano preparado. Por isso, uma função com código condicional contendo muitas declarações que requerem um plano de execução, somente prepara e salva os planos realmente utilizados durante o espaço de tempo da conexão com o banco de dados. Isto pode reduzir muito a quantidade total de tempo necessário para analisar e gerar os planos de execução para as declarações na função PL/pgSQL. A desvantagem é que erros em uma determinada expressão ou comando podem não ser detectados até que a parte da função onde se encontram seja executada. Uma vez que o PL/pgSQL tenha construído um plano de execução para um determinado comando da função, este plano será reutilizado enquanto durar a conexão com o banco de dados. Normalmente há um ganho de desempenho, mas pode causar problema se o esquema do banco de dados for modificado dinamicamente. Por exemplo: CREATE FUNCTION populate() RETURNS integer AS ' DECLARE -- declarações BEGIN PERFORM minha_funcao(); END; ' LANGUAGE plpgsql;
Se a função acima for executada, fará referência ao OID da minha_funcao() no plano de execução gerado para a declaração PERFORM. Mais tarde, se a função minha_funcao() for removida e recriada, então populate() não vai mais conseguir encontrar minha_funcao(). Por isso é necessário recriar populate(), ou pelo menos começar uma nova sessão de banco de dados, para que esta seja compilada novamente. Outra forma de evitar este problema é utilizar CREATE OR REPLACE FUNCTION ao atualizar a definição de minha_funcao (quando a função é “substituída”, o OID não muda). Uma vez que o PL/pgSQL salva os planos de execução desta maneira, os comandos SQL que aparecem diretamente na função PL/pgSQL devem fazer referência às mesmas tabelas e colunas em todas as execuções; ou seja, não pode ser utilizado um parâmetro como nome de tabela ou de coluna no comando SQL. Para contornar esta restrição, podem ser construídos comandos dinâmicos utilizando a declaração EXECUTE do PL/pgSQL; ao custo de construir um novo plano de execução a cada execução.
583
Nota: A declaração EXECUTE do PL/pgSQL não tem relação com a declaração EXECUTE suportada pelo servidor PostgreSQL. A declaração EXECUTE do servidor não pode ser utilizada dentro das funções PL/pgSQL (e não é necessário).
Exceto por conversão de entrada/saída e funções de cálculo para tipos definidos pelo usuário, tudo que pode ser definido nas funções escritas na linguagem C também pode ser feito com a linguagem PL/pgSQL. Por exemplo, é possível criar funções de processamento condicional complexas e mais tarde utilizá-las para definir operadores ou nas expressões de índices.
37.1.1. Vantagens da utilização do PL/pgSQL SQL é a linguagem que o PostgreSQL (e a maioria dos bancos de dados relacionais) utiliza como linguagem de comandos. É portável e fácil de ser aprendida. Entretanto, todas as declarações SQL devem ser executadas individualmente pelo servidor de banco de dados. Isto significa que a aplicação cliente deve enviar o comando para o servidor de banco de dados, aguardar que seja processado, receber os resultados, realizar algum processamento e enviar o próximo comando para o servidor. Tudo isto envolve comunicação entre processos e pode, também, envolver tráfego na rede se o cliente não estiver na mesma máquina onde se encontra o servidor de banco de dados. Com a linguagem PL/pgSQL um bloco de processamento contendo uma série de comandos pode ser agrupado dentro do servidor de banco de dados, juntando o poder da linguagem procedural com a facilidade de uso da linguagem SQL, economizando muito tempo, porque não há necessidade da sobrecarga de comunicação entre o cliente e o servidor. Isto pode aumentar o desempenho consideravelmente. Também, na linguagem PL/pgSQL podem ser utilizados todos os tipos de dados, operadores e funções da linguagem SQL.
37.1.2. Argumentos suportados e tipos de dado do resultado As funções escritas em PL/pgSQL aceitam como argumento qualquer tipo de dado escalar ou matriz suportado pelo servidor, e podem retornar como resultado qualquer um destes tipos. As funções também aceitam e retornam qualquer tipo composto (tipo linha) especificado por nome. Também é possível declarar uma função PL/pgSQL como retornando record, significando que o resultado é um tipo-linha cujas colunas são determinadas pela especificação no comando que faz a chamada, conforme mostrado na Seção 7.2.1.4. As funções PL/pgSQL também podem ser declaradas como aceitando ou retornando os tipos polimórficos anyelement e anyarray. Os tipos de dado verdadeiros tratados pelas funções polimórficas podem variar
entre chamadas, conforme mostrado na Seção 33.2.5. Um exemplo é mostrado na Seção 37.4.1. As funções PL/pgSQL também podem ser declaradas como retornando “set” (conjunto), ou tabela, de qualquer tipo de dado que pode ser retornada uma única instância. Este tipo de função gera sua saída executando RETURN NEXT para cada elemento desejado do conjunto resultado. Por fim, uma função PL/pgSQL pode ser declarada como retornando void se não produzir nenhum valor de retorno útil.
37.2. Dicas para desenvolvimento em PL/pgSQL Uma boa maneira de desenvolver em PL/pgSQL é utilizar o editor de texto de sua preferência para criar as funções e, em outra janela, utilizar o psql para carregar e testar as funções desenvolvidas. Se estiver sendo feito desta maneira, é uma boa idéia escrever a função utilizando CREATE OR REPLACE FUNCTION. Desta forma basta recarregar o arquivo para atualizar a definição da função. Por exemplo: CREATE OR REPLACE FUNCTION funcao_teste(integer) RETURNS integer AS ' .... end; ' LANGUAGE plpgsql;
Na linha de comando do psql a definição da função pode ser carregada ou recarregada utilizando \i nome_do_arquivo.sql
584
e logo em seguida podem ser executados os comandos SQL que testam a função. Outra boa maneira de desenvolver em PL/pgSQL é utilizar uma ferramenta com interface gráfica e acesso ao banco de dados, que facilite o desenvolvimento em uma linguagem procedural. Um exemplo deste tipo de ferramenta é o PgAccess, mas existem outras. Estas ferramentas geralmente incorporam funcionalidades convenientes, como o tratamento de apóstrofos, e tornam mais fácil recriar e depurar as funções.
37.2.1. Tratamento dos apóstrofos Uma vez que o código da função PL/pgSQL é especificado como um literal cadeia de caracteres no comando CREATE FUNCTION, deve ser feita uma seqüência de escape para os apóstrofos dentro do corpo da função
duplicando estes caracteres. Em certas circunstâncias isto pode levar a um código complicado, especialmente quando são escritas funções que geram outras funções, como no exemplo da Seção 37.6.4. O quadro abaixo pode ser útil como um resumo do número de apóstrofos necessários em diversas situações. 1 apóstrofo para começar e terminar o corpo da função como, por exemplo: CREATE FUNCTION foo() RETURNS integer AS '...' LANGUAGE plpgsql;
Em todas as ocorrências dentro do corpo da função os apóstrofos devem aparecer em pares. 2 apóstrofos Para literais cadeias de caracteres dentro do corpo da função como, por exemplo: a_output := ''Blah''; SELECT * FROM usuarios WHERE f_nome=''foobar'';
A segunda linha é vista pelo PL/pgSQL como: SELECT * FROM usuarios WHERE f_nome='foobar';
4 apóstrofos Quando há necessidade de um apóstrofo dentro de uma constante cadeia de caracteres dentro do corpo da função como, por exemplo: a_output := a_output || '' AND nome LIKE ''''foobar'''' AND xyz''
O valor realmente anexado a a_output seria: AND nome LIKE 'foobar' AND xyz. 6 apóstrofos Quando o apóstrofo na cadeia de caracteres dentro do corpo da função está no final da constante cadeia de caracteres como, por exemplo: a_output := a_output || '' AND nome LIKE ''''foobar''''''
O valor anexado à a_output seria: AND nome LIKE 'foobar'. 10 apóstrofos Quando há necessidade de dois apóstrofos em uma constante cadeia de caracteres (que necessita de 8 apóstrofos), e estes dois apóstrofos estão no final da constante cadeia de caracteres (mais 2 apóstrofos). Normalmente isto só é necessário quando são escritas funções que geram outras funções como, por exemplo: a_output := a_output || '' if v_'' || referrer_keys.kind || '' like '''''''''' || referrer_keys.key_string || '''''''''' then return '''''' || referrer_keys.referrer_type || ''''''; end if;'';
O valor anexado a a_output seria: if v_... like ''...'' then return ''...''; end if;
585
Uma outra abordagem é utilizar a contrabarra para gerar as seqüências de escape para apóstrofos no corpo da função, em vez de duplicá-los. Desta forma é escrito \'\' no lugar de ''''. Alguns acham esta forma mais fácil, porém outros não concordam.
37.3. Estrutura da linguagem PL/pgSQL A linguagem PL/pgSQL é estruturada em blocos. O texto completo da definição da função deve ser um bloco. Um bloco é definido como: [ <> ] [ DECLARE declarações ] BEGIN instruções END;
Todas as declarações e instruções dentro do bloco são terminadas por ponto-e-vírgula. Todas as palavras chave e identificadores podem ser escritos misturando letras maiúsculas e minúsculas. As letras dos identificadores são convertidas implicitamente em minúsculas a menos que estejam entre aspas. Existem dois tipos de comentários no PL/pgSQL. O hífen duplo (--) começa um comentário que se estende até o final da linha. O /* começa um bloco de comentário que se estende até a próxima ocorrência de */. Os blocos de comentários não podem ser aninhados, mas comentários de hífen duplo podem estar contidos em blocos de comentários, e os hífens duplos escondem os delimitadores de bloco de comentário /* e */. Qualquer instrução na seção de instruções do bloco pode ser um sub-bloco. Os sub-blocos podem ser utilizados para agrupamento lógico, ou para limitar o escopo de variáveis a um pequeno grupo de instruções. As variáveis declaradas na seção de declaração que precede um bloco são inicializadas com seu valor padrão toda vez que o bloco é executado, e não somente uma vez a cada chamada da função. Por exemplo: CREATE FUNCTION func_escopo() RETURNS integer AS ' DECLARE quantidade integer := 30; BEGIN -- A quantidade aqui é 30 RAISE NOTICE ''Aqui a quantidade é %'', quantidade; quantidade := 50; --- Criar um sub-bloco -DECLARE quantidade integer := 80; BEGIN -- A quantidade aqui é 80 RAISE NOTICE ''Aqui a quantidade é %'', quantidade; END; -- A quantidade aqui é 50 RAISE NOTICE ''Aqui a quantidade é %'', quantidade; RETURN quantidade; END; ' LANGUAGE plpgsql;
Resultado da execução: select func_escopo(); NOTICE: NOTICE: NOTICE:
Aqui a quantidade é 30 Aqui a quantidade é 80 Aqui a quantidade é 50
586
func_escopo ------------50 (1 linha)
É importante não confundir a utilização de BEGIN/END para o agrupamento de instruções na linguagem PL/pgSQL com os comandos de banco de dados para controle de transação. O BEGIN/END da linguagem PL/pgSQL é apenas para agrupamento; não começam nem terminam transações. Os procedimentos de funções e de gatilhos são sempre executados dentro da transação estabelecida pelo comando externo; não podem começar ou efetivar transações, porque o PostgreSQL não possui transações aninhadas.
37.4. Declarações Todas as variáveis utilizadas em um bloco devem ser declaradas na seção de declarações do bloco (A única exceção é a variável de laço do FOR interagindo sobre um intervalo de valores inteiros, que é automaticamente declarada como do tipo inteiro). As variáveis da linguagem PL/pgSQL podem possuir qualquer tipo de dado da linguagem SQL, tais como integer, varchar e char.
Abaixo seguem alguns exemplos de declaração de variáveis: id_usuario quantidade url minha_linha meu_campo uma_linha
integer; numeric(5); varchar; nome_da_tabela%ROWTYPE; nome_da_tabela.nome_da_coluna%TYPE; RECORD;
A sintaxe geral para declaração de variáveis é: nome [ CONSTANT ] tipo [ NOT NULL ] [ { DEFAULT | := } expressão ];
A cláusula DEFAULT, se for fornecida, especifica o valor inicial atribuído à variável quando o processamento entra no bloco. Se a cláusula DEFAULT não for fornecida, então a variável é inicializada com o valor nulo do SQL. A opção CONSTANT impede que seja atribuído valor a variável e, portanto, seu valor permanece constante pela duração do bloco. Se for especificado NOT NULL, uma atribuição de valor nulo resulta em um erro em tempo de execução. Todas as variáveis declaradas como NOT NULL devem ter um valor padrão não nulo especificado. O valor padrão é avaliado toda vez que a execução entra no bloco. Portanto, por exemplo, atribuir 'now' a uma variável do tipo timestamp faz com que a variável possua a data e hora da chamada corrente à função, e não de quando a função foi pré-compilada. Exemplos: quantidade url id_usuario
integer DEFAULT 32; varchar := ''http://meu-site.com''; CONSTANT integer := 10;
37.4.1. Aliases para parâmetros de função nome ALIAS FOR $n;
Os parâmetros passados para as funções recebem como nome os identificadores $1, $2, etc. Opcionalmente, podem ser declarados aliases para os nomes dos parâmetros $n para melhorar a legibilidade do código. Tanto o aliás quanto o identificador numérico podem ser utilizados para fazer referência ao valor do parâmetro. Alguns exemplos:
587
CREATE FUNCTION taxa_de_venda(real) RETURNS real AS ' DECLARE subtotal ALIAS FOR $1; BEGIN RETURN subtotal * 0.06; END; ' LANGUAGE plpgsql;
CREATE FUNCTION instr(varchar, integer) RETURNS integer AS ' DECLARE v_string ALIAS FOR $1; index ALIAS FOR $2; BEGIN -- algum processamento aqui END; ' LANGUAGE plpgsql;
CREATE FUNCTION concatenar_campos(tablename) RETURNS text AS ' DECLARE in_t ALIAS FOR $1; BEGIN RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7; END; ' LANGUAGE plpgsql;
Quando o tipo retornado por uma função PL/pgSQL é declarado como polimórfico (anyelement ou anyarray), é criado o parâmetro especial $0. Seu tipo de dado é o tipo de dado a ser retornado pela função, conforme deduzido a partir dos tipos da entrada corrente (veja a Seção 33.2.5). Isto permite que a função acesse o tipo retornado para a entrada corrente conforme mostrado na Seção 37.4.2. O parâmetro $0 é inicializado como nulo podendo ser modificado pela função e, portanto, pode ser utilizado para armazenar o valor a ser retornado. Também pode ser criado um aliás para o parâmetro $0. Por exemplo, esta função funciona com qualquer tipo de dado que possua um operador +: CREATE FUNCTION somar_tres_valores(anyelement, anyelement, anyelement) RETURNS anyelement AS ' DECLARE resultado ALIAS FOR $0; primeiro ALIAS FOR $1; segundo ALIAS FOR $2; terceiro ALIAS FOR $3; BEGIN resultado := primeiro + segundo + terceiro; RETURN resultado; END; ' LANGUAGE plpgsql;
Exemplo de utilização: select somar_tres_valores(1,2,3); somar_tres_valores -------------------6 (1 linha)
select somar_tres_valores(1.01,2.02,3.03);
588
somar_tres_valores -------------------6.06 (1 linha)
37.4.2. Cópia de tipos variável%TYPE %TYPE fornece o tipo de dado da variável ou da coluna da tabela. Pode ser utilizado para declarar variáveis que armazenam valores do banco de dados. Por exemplo, digamos que exista uma coluna chamada id_usuario na tabela usuarios. Para declarar uma variável com o mesmo tipo de dado de usuarios.id_usuario deve ser
escrito: id_usuario usuarios.id_usuario%TYPE;
Utilizando %TYPE não há necessidade de conhecer o tipo de dado da estrutura sendo referenciada e, ainda mais importante, se o tipo de dado do item referenciado mudar futuramente (por exemplo: o tipo de dado de id_usuario for mudado de integer para real), não haverá necessidade de mudar a definição na função. %TYPE é particularmente útil em funções polimórficas, uma vez que os tipos de dado das variáveis internas podem mudar de uma chamada para outra. Variáveis apropriadas podem ser criadas aplicando %TYPE aos argumentos da função ou ao resultado.
37.4.3. Tipos linha nome nome_da_tabela%ROWTYPE; nome nome_do_tipo_composto;
Uma variável de tipo composto é chamada de variável linha (ou variável tipo-linha). Este tipo de variável pode armazenar toda uma linha de resultado de um comando SELECT ou FOR, desde que o conjunto de colunas do comando corresponda ao tipo declarado para a variável. Os campos individuais do valor linha são acessados utilizando a notação usual de ponto como, por exemplo, variavel_linha.campo. Uma variável-linha pode ser declarada como tendo o mesmo tipo das linhas de uma tabela ou de uma visão existente, utilizando a notação nome_da_tabela%ROWTYPE; ou pode ser declarada especificando o nome de um tipo composto (Uma vez que todas as tabelas possuem um tipo composto associado com o mesmo nome da tabela, na verdade não faz diferença para o PostgreSQL se %ROWTYPE é escrito ou não, mas a forma incluindo %ROWTYPE é mais portável). Os parâmetros das funções podem ser de tipo composto (linhas completas da tabela). Neste caso o identificador correspondente $n será uma variável linha, e os campos poderão ser selecionados a partir deste identificador como, por exemplo $1.id_usuario. Somente os campos da linha da tabela definidos pelo usuário podem ser acessados na variável tipo-linha, o OID e as outras colunas do sistema não podem ser acessados desta forma (porque a linha pode ser de uma visão). Os campos do tipo-linha herdam o tamanho do campo da tabela, ou a precisão, no caso de tipos de dado como char(n). Abaixo está mostrado um exemplo de utilização de tipos compostos: CREATE FUNCTION use_two_tables(tablename) RETURNS text AS ' DECLARE in_t ALIAS FOR $1; use_t table2name%ROWTYPE; BEGIN SELECT * INTO use_t FROM table2name WHERE ... ; RETURN in_t.f1 || use_t.f3 || in_t.f5 || use_t.f7; END; ' LANGUAGE plpgsql;
589
37.4.4. Tipos registro nome RECORD;
As variáveis tipo-registro são semelhantes as variáveis tipo-linha, mas não possuem uma estrutura prédefinida. Assumem a estrutura da linha para a qual são atribuídas pelo comando SELECT ou FOR. A subestrutura da variável tipo-registro pode mudar toda vez que é usada em uma atribuição. Como conseqüência, antes de ser utilizada em uma atribuição a variável-registro não possui subestrutura, e qualquer tentativa de acessar um de seus campos produz um erro em tempo de execução. Observe que RECORD não é um tipo de dado verdadeiro, mas somente uma reserva de tipo. Se deve ter em mente que, quando uma função do PL/pgSQL é declarada como retornando o tipo record não é exatamente o mesmo conceito da variável-registro, embora a função possa utilizar um tipo-registro para armazenar seus resultados. Nos dois casos a estrutura verdadeira da linha é desconhecida quando a função é escrita, mas na função que retorna o tipo record a estrutura verdadeira é determinada quando a consulta que faz a chamada é analisada, enquanto uma variável do tipo-registro pode mudar a sua estrutura de linha dinamicamente.
37.4.5. RENAME RENAME nome_antigo TO nome_novo;
Através da declaração RENAME pode ser mudado o nome de uma variável, registro ou linha. A utilidade principal é quando NEW ou OLD devem ser referenciados por outro nome dentro da função de gatilho. Veja também ALIAS. Exemplos: RENAME id TO id_usuario; RENAME esta_variavel TO aquela_variavel; Nota: RENAME parece estar com problemas desde o PostgreSQL 7.3. A correção possui baixa prioridade, porque o ALIAS cobre a maior parte dos usos práticos do RENAME.
37.5. Expressões Todas as expressões utilizadas nas instruções do PL/pgSQL são processadas utilizando e executor de SQL normal do servidor. Expressões que parecem conter constantes podem, na realidade, requerer uma avaliação em tempo de execução (por exemplo, 'now' para o tipo timestamp), portanto não é possível o analisador do PL/pgSQL identificar verdadeiros valores constantes além da palavra chave NULL. Todas as expressões são avaliadas internamente utilizando o comando SELECT expressão
através da Interface de Programação do Servidor (SPI). Para fazer a avaliação, as ocorrências dos identificadores de variável do PL/pgSQL são substituídas por parâmetros, e os reais valores das variáveis são passados para o executor numa matriz de parâmetros. Isto permite o plano de consulta para o SELECT ser preparado somente uma vez e, depois, ser reutilizado nas próximas avaliações. A avaliação feita pelo analisador principal do PostgreSQL causa alguns efeitos colaterais na interpretação dos valores constantes. Visto em detalhes existe diferença entre o que estas duas funções fazem: CREATE FUNCTION logfunc1(text) RETURNS timestamp AS ' DECLARE logtxt ALIAS FOR $1; BEGIN INSERT INTO logtable VALUES (logtxt, ''now''); RETURN ''now''; END; ' LANGUAGE plpgsql;
e
590
CREATE FUNCTION logfunc2(text) RETURNS timestamp AS ' DECLARE logtxt ALIAS FOR $1; curtime timestamp; BEGIN curtime := ''now''; INSERT INTO logtable VALUES (logtxt, curtime); RETURN curtime; END; ' LANGUAGE plpgsql;
No caso da função logfunc1 o analisador principal do PostgreSQL sabe, ao preparar o plano para o comando INSERT, que a cadeia de caracteres 'now' deve ser interpretada como timestamp, porque a coluna de destino na tabela logtable é deste tipo, e por isso cria uma constante a partir de 'now' contendo a data e hora da análise. Depois esta constante é utilizada em todas as chamadas à função logfunc1, durante toda a sessão. É desnecessário dizer que isto não é o que o programador deseja. No caso da função logfunc2 o analisador principal do PostgreSQL não sabe que tipo 'now' deve se tornar e, portanto, retorna um valor de dado do tipo text contendo a cadeia de caracteres now. Durante as atribuições seguintes à variável local curtime, o interpretador do PL/pgSQL irá converter a cadeia de caracteres para o tipo timestamp, chamando as funções text_out e timestamp_in para fazer a conversão. Portanto, a data e hora computada é atualizada a cada execução, como esperado pelo programador. A natureza mutante das variáveis tipo-registro também apresenta um problema semelhante. Quando campos de uma variável tipo-registro são utilizados em expressões ou instruções, os tipos de dado dos campos não devem mudar entre chamadas à mesma expressão, uma vez que o planejamento é feito utilizando o tipo de dado presente na expressão quando esta é executada pela primeira vez. Se deve ter isto em mente ao escrever procedimentos de gatilhos que tratam eventos para mais de uma tabela; quando for necessário, pode ser utilizado o EXECUTE para evitar este problema.
37.6. Instruções básicas Esta seção e as seguintes descrevem todos os tipos de instruções explicitamente compreendidas pelo PL/pgSQL. Tudo que não for reconhecido como sendo uma instrução de um destes tipos é assumido como sendo um comando SQL, e enviado para ser executado pela máquina de banco de dados principal (após a substituição das variáveis do PL/pgSQL na instrução). Desta maneira, por exemplo, os comandos SQL INSERT, UPDATE e DELETE podem ser considerados como sendo instruções do PL/pgSQL, mas não são especificamente relacionados aqui.
37.6.1. Atribuições A atribuição de um valor a uma variável, ou a um campo de linha ou de registro, é escrita da seguinte maneira: identificador := expressão;
Como foi explicado anteriormente, a expressão nesta instrução é avaliada através de um comando SELECT do SQL enviado para a máquina de banco de dados principal. A expressão deve produzir um único valor. Se o tipo de dado do resultado da expressão não corresponder ao tipo de dado da variável, ou se a variável possuir um tipo/precisão especificado (como char(20)), o valor do resultado será convertido implicitamente pelo interpretador do PL/pgSQL, utilizando a função de saída do tipo do resultado e a função de entrada do tipo da variável. Observe que este procedimento pode ocasionar erros em tempo de execução gerados pela função de entrada, se a forma cadeia de caracteres do valor do resultado não puder ser aceita pela função de entrada. Exemplos: id_usuario := 20; taxa := subtotal * 0.06;
591
37.6.2. SELECT INTO O resultado de um comando SELECT que retorna várias colunas (mas apenas uma linha) pode ser atribuído a uma variável tipo-registro, a uma variável tipo-linha, ou a uma lista de variáveis escalares. É feito através de SELECT INTO destino expressões_de_seleção FROM ...;
onde destino pode ser uma variável tipo-registro, uma variável tipo-linha, ou uma lista de variáveis simples ou campos de registro/linha. A expressões_de_seleção e o restante do comando são os mesmos do SQL comum. Observe que é bem diferente da interpretação normal de SELECT INTO feita pelo PostgreSQL, onde o destino de INTO é uma nova tabela criada. Se for desejado criar uma tabela dentro de uma função PL/pgSQL a partir do resultado do SELECT, deve ser utilizada a sintaxe CREATE TABLE ... AS SELECT. Se uma linha ou uma lista de variáveis for utilizada como destino, os valores selecionados devem corresponder exatamente à estrutura de destino, senão ocorre um erro em tempo de execução. Quando o destino é uma variável tipo-registro, esta se autoconfigura automaticamente para o tipo-linha das colunas do resultado da consulta. Exceto pela cláusula INTO, a instrução SELECT é idêntica ao comando SELECT normal do SQL, podendo utilizar todos os seus recursos. Se a consulta não retornar nenhuma linha, são atribuídos valores nulos aos destinos. Se a consulta retornar várias linhas, a primeira linha é atribuída aos destinos e as demais são desprezadas; deve ser observado que “a primeira linha” não é bem definida a não ser que seja utilizado ORDER BY. Atualmente a cláusula INTO pode estar praticamente em qualquer posição da instrução SELECT, mas se recomenda que seja colocada logo após a palavra chave SELECT, conforme mostrado acima. As próximas versões do PL/pgSQL podem ser mais rigorosas com relação à posição da cláusula INTO. Pode ser utilizado FOUND imediatamente após SELECT INTO para determinar se a atribuição foi bem-sucedida; ou seja, pelo menos uma linha foi retornada pela consulta. Por exemplo: SELECT INTO meu_registro * FROM emp WHERE nome_emp = meu_nome; IF NOT FOUND THEN RAISE EXCEPTION ''não foi encontrado o empregado %!'', meu_nome; END IF;
Para testar se o resultado do registro/linha é nulo, pode ser utilizada a condição IS NULL. Entretanto, não existe maneira de saber se foram desprezadas linhas adicionais. A seguir está mostrado um exemplo que trata o caso onde o campo é nulo: DECLARE registro_usuario RECORD; nome_completo varchar; BEGIN SELECT INTO registro_usuario * FROM usuarios WHERE id_usuario=3; IF registro_usuario.pagina_web IS NULL THEN -- o usuario não informou a página na web, retornar "http://" RETURN ''http://''; END IF; END;
37.6.3. Execução de expressão ou de consulta sem resultado Algumas vezes se deseja avaliar uma expressão ou comando e desprezar o resultado (normalmente quando está sendo chamada uma função que produz efeitos colaterais, mas não possui nenhum resultado útil). Para isto ser feito deve ser utilizada a instrução PERFORM: PERFORM comando;
592
Executa o comando, que deve ser uma instrução SELECT, e despreza o resultado. As variáveis do PL/pgSQL são substituídas no comando da maneira habitual. Também, a variável especial FOUND é definida como verdade se a consulta produzir pelo menos uma linha, ou como falso se não produzir nenhuma linha. Nota: Poderia se esperar que SELECT sem a cláusula INTO tivesse o mesmo resultado, mas atualmente a única forma aceita para isto ser feito é através do PERFORM.
Exemplo: PERFORM create_mv(''cs_session_page_requests_mv'', my_query);
37.6.4. Execução de comandos dinâmicos As vezes há necessidade de gerar comandos dinamicamente dentro da função PL/pgSQL, ou seja, comandos que envolvem tabelas diferentes ou tipos de dado diferentes cada vez que são executados. A tentativa normal do PL/pgSQL de colocar planos para os comandos no cache não funciona neste cenário. A instrução EXECUTE é fornecida para tratar este tipo de problema: EXECUTE cadeia_de_caracteres_do_comando;
onde cadeia_de_caracteres_do_comando é uma expressão que produz uma cadeia de caracteres (do tipo text) contendo o comando a ser executado. A cadeia de caracteres é enviada literalmente para o máquina SQL. Em particular, deve ser notado que não é feita substituição das variáveis do PL/pgSQL na cadeia de caracteres do comando. Os valores das variáveis devem ser inseridos na cadeia de caracteres do comando quando esta é construída. Quando se trabalha com comandos dinâmicos devem ser feitas seqüências de escape para os apóstrofos no PL/pgSQL. Por favor consulte a visão geral na Seção 37.2.1, o que pode evitar trabalho. Diferentemente de todos os outros comandos do PL/pgSQL, um comando executado pela instrução EXECUTE não é preparado e salvo uma única vez por toda a duração da sessão. Em vez disso, o comando é preparado toda vez que a instrução é executada. A cadeia de caracteres do comando pode ser criada dinamicamente dentro da função para realizar ações em tabelas e colunas que variam. Os resultados dos comandos SELECT são desprezados pelo EXECUTE e, atualmente, o SELECT INTO não é suportado pelo EXECUTE. Existem duas maneiras de extrair resultados de comandos SELECT criados dinamicamente: uma é utilizar a forma FOR-IN-EXECUTE descrita na Seção 37.7.4, e a outra é utilizar um cursor com OPEN-FOR-EXECUTE, conforme descrito na Seção 37.8.2. Exemplo: EXECUTE ''UPDATE tbl SET '' || quote_ident(nome_da_coluna) || '' = '' || quote_literal(novo_valor) || '' WHERE ...'';
Este exemplo mostra o uso das funções quote_ident(text) e quote_literal(text). Por motivo de segurança, as variáveis contendo identificadores de coluna e de tabela devem ser passadas para a função quote_ident. As variáveis contendo valores que devem ser literais cadeias de caracteres no comando construído devem ser passadas para função quote_literal. As duas executam os passos apropriados para retornar o texto de entrada envolto por aspas ou apóstrofos, respectivamente, com todos os caracteres especiais devidamente colocados em seqüências de escape. A seguir está mostrado um exemplo maior de comandos dinâmicos e do EXECUTE:
593
CREATE FUNCTION cs_update_referrer_type_proc() RETURNS integer AS ' DECLARE -- declarar um registro genérico para ser utilizado no FOR referrer_keys RECORD; a_output varchar(4000); BEGIN a_output := ''CREATE FUNCTION cs_find_referrer_type(varchar, varchar, varchar) RETURNS varchar AS '''' DECLARE v_host ALIAS FOR $1; v_domain ALIAS FOR $2; v_url ALIAS FOR $3; BEGIN ''; -- Observe como é feita a varredura dos resultados da consulta -- no laço FOR utilizando a construção FOR. FOR referrer_keys IN SELECT * FROM cs_referrer_keys ORDER BY try_order LOOP a_output := a_output || '' IF v_'' || referrer_keys.kind || '' LIKE '''''''''' || referrer_keys.key_string || '''''''''' THEN RETURN '''''' || referrer_keys.referrer_type || ''''''; END IF;''; END LOOP; a_output := a_output || '' RETURN NULL; END; '''' LANGUAGE plpgsql;''; EXECUTE a_output; END; ' LANGUAGE plpgsql;
37.6.5. Obtenção do status do resultado Existem diversas maneiras de determinar o efeito de um comando. O primeiro método é utilizar o comando GET DIAGNOSTICS, que possui a forma: GET DIAGNOSTICS variável = item [ , ... ] ;
Este comando permite recuperar os indicadores de status do sistema. Cada item é uma palavra chave que identifica o valor de estado a ser atribuído a variável especificada (que deve ser do tipo de dado correto para poder receber). Os itens de status disponíveis atualmente são ROW_COUNT, o número de linhas processadas pelo último comando SQL enviado para a máquina SQL, e RESULT_OID, o OID da última linha inserida pelo comando SQL mais recente. Deve ser observado que RESULT_OID só tem utilidade após um comando INSERT. Exemplo: GET DIAGNOSTICS variavel_inteira = ROW_COUNT;
O segundo método para determinar os efeitos de um comando é verificar a variável especial FOUND, que é do tipo boolean. A variável FOUND é iniciada como falso dentro de cada chamada de função PL/pgSQL. É definida por cada um dos seguintes tipos de instrução: •
A instrução SELECT INTO define FOUND como verdade se retornar uma linha, e como falso se nenhuma linha for retornada.
•
A instrução PERFORM define FOUND como verdade se produzir (e desprezar) uma linha, e como falso se nenhuma linha for produzida.
•
As instruções UPDATE, INSERT e DELETE definem FOUND como verdade se pelo menos uma linha for afetada, e como falso se nenhuma linha for afetada.
594
•
A instrução FETCH define FOUND como verdade se retornar uma linha, e como falso se nenhuma linha for retornada.
•
A instrução FOR define FOUND como verdade se interagir uma ou mais vezes, senão define como falso. Isto se aplica a todas três variantes da instrução FOR (laços FOR inteiros, laços FOR em conjuntos de registros, e laços FOR em conjuntos de registros dinâmicos). A variável FOUND somente é definida quando o laço FOR termina: dentro da execução do laço a variável FOUND não é modificada pela instrução FOR, embora possa ser modificada pela execução de outras instruções dentro do corpo do laço.
FOUND é uma variável local; qualquer mudança feita sobre a mesma afeta somente a função PL/pgSQL corrente.
37.7. Estruturas de controle As estruturas de controle provavelmente são a parte mais útil (e mais importante) do PL/pgSQL. Com as estruturas de controle do PL/pgSQL os dados do PostgreSQL podem ser manipulados de uma forma muita flexível e muito poderosa.
37.7.1. Retorno de uma função Estão disponíveis dois comandos que permitem retornar dados de uma função: RETURN e RETURN NEXT. 37.7.1.1. RETURN RETURN expressão; RETURN com uma expressão termina a função e retorna o valor da expressão para quem chama. Esta forma é utilizada pelas funções do PL/pgSQL que não retornam um conjunto.
Qualquer expressão pode ser utilizada para retornar um tipo escalar. O resultado da expressão é automaticamente convertido no tipo de retorno da função conforme descrito nas atribuições. Deve ser escrita uma variável tipo-registro ou tipo-linha como expressão para retornar um valor composto (linha). O valor retornado pela função não pode ser deixado indefinido. Se o controle atingir o final do bloco de nível mais alto da função sem atingir uma instrução RETURN, ocorrerá um erro em tempo de execução. Se a função for declarada como retornando void, ainda assim uma instrução RETURN deve ser especificada; mas neste caso a expressão após o RETURN é opcional, sendo ignorada caso esteja presente. 37.7.1.2. RETURN NEXT RETURN NEXT expressão;
Quando uma função PL/pgSQL é declarada como retornando SETOF algum_tipo, o procedimento a ser seguido é um pouco diferente. Neste caso, os itens individuais a serem retornados são especificados em comandos RETURN NEXT, e um comando RETURN final sem nenhum argumento é utilizado para indicar que a função chegou ao fim de sua execução. O comando RETURN NEXT pode ser utilizado tanto com tipos de dado escalares quanto compostos; no último caso uma “tabela” inteira de resultados é retornada. As funções que utilizam RETURN NEXT devem ser chamadas da seguinte maneira: SELECT * FROM alguma_funcao();
Ou seja, a função é utilizada como uma fonte de tabela na cláusula FROM. Na verdade o comando RETURN NEXT não retorna da função; simplesmente salva o valor da expressão (ou da variável tipo-registro ou tipo-linha, conforme seja apropriado para o tipo de dado sendo retornado). Depois, a execução continua na próxima instrução da função PL/pgSQL. Ao se executar comandos RETURN NEXT sucessivos, o conjunto de resultados é construído. O RETURN final, que não deve possuir argumentos, faz o controle sair da função. Nota: A implementação atual de RETURN NEXT para o PL/pgSQL armazena todo o conjunto de resultados antes de retornar da função, conforme foi mostrado acima. Isto significa que, se a função PL/pgSQL
595
produzir um conjunto de resultados muito grande, o desempenho será ruim: os dados serão escritos em disco para evitar exaurir a memória, mas a função não retornará antes que todo o conjunto de resultados tenha sido gerado. Uma versão futura do PL/pgSQL poderá permitir os usuários definirem funções que retornam conjuntos que não tenham esta limitação. Atualmente, o ponto onde os dados começam a ser escritos em disco é controlado pela variável de configuração sort_mem. Os administradores que possuem memória suficiente para armazenar conjuntos de resultados maiores, devem considerar o aumento deste parâmetro.
37.7.2. Condicionais As instruções IF permitem executar os comandos com base em certas condições. O PL/pgSQL possui quatro formas de IF: •
IF ... THEN
•
IF ... THEN ... ELSE
•
IF ... THEN ... ELSE IF
•
IF ... THEN ... ELSIF ... THEN ... ELSE
37.7.2.1. IF-THEN IF expressão_booleana THEN instruções END IF;
As instruções IF-THEN são a forma mais simples de IF. As instruções entre o THEN e o END IF são executadas se a condição for verdade. Senão, são saltadas. Exemplo: IF v_id_usuario <> 0 THEN UPDATE usuarios SET email = v_email WHERE id_usuario = v_id_usuario; END IF;
37.7.2.2. IF-THEN-ELSE IF expressão_booleana THEN instruções ELSE instruções END IF;
As instruções IF-THEN-ELSE ampliam o IF-THEN permitindo especificar um conjunto alternativo de instruções a ser executado se a condição for avaliada como falso. Exemplos: IF id_pais IS NULL OR id_pais = '''' THEN RETURN nome_completo; ELSE RETURN hp_true_filename(id_pais) || ''/'' || nome_completo; END IF; IF v_contador > 0 THEN INSERT INTO contador_usuarios (contador) VALUES (v_contador); RETURN ''t''; ELSE RETURN ''f''; END IF;
37.7.2.3. IF-THEN-ELSE IF As instruções IF podem ser aninhadas, como no seguinte exemplo:
596
IF linha_demo.sexo = ''m'' THEN sexo_extenso := ''masculino''; ELSE IF linha_demo.sexo = ''f'' THEN sexo_extenso := ''feminino''; END IF; END IF;
Na verdade, quando esta forma é utilizada uma instrução IF está sendo aninhada dentro da parte ELSE da instrução IF externa. Portanto, é necessária uma instrução END IF para cada IF aninhado, mais um para o IFELSE pai. Embora funcione, se torna entediante quando existem muitas alternativas a serem verificadas. Por isso existe a próxima forma. 37.7.2.4. IF-THEN-ELSIF-ELSE IF expressão_booleana THEN instruções [ ELSIF expressão_booleana THEN instruções [ ELSIF expressão_booleana THEN instruções ...]] [ ELSE instruções ] END IF;
A instrução IF-THEN-ELSIF-ELSE fornece um método mais conveniente para verificar muitas alternativas em uma instrução. Formalmente equivale aos comandos IF-THEN-ELSE-IF-THEN aninhados, mas somente necessita de um END IF. Abaixo está um exemplo: IF number = 0 THEN result := ''zero''; ELSIF number > 0 THEN result := ''positivo''; ELSIF number < 0 THEN result := ''negativo''; ELSE -- hmm, a única outra possibilidade é que o número seja nulo result := ''nulo''; END IF;
37.7.3. Laços simples Com as instruções LOOP, EXIT, WHILE e FOR pode-se fazer a função PL/pgSQL repetir uma série de comandos. 37.7.3.1. LOOP [<>] LOOP instruções END LOOP;
A instrução LOOP define um laço incondicional, repetido indefinidamente até ser terminado por uma instrução EXIT ou RETURN. Nos laços aninhados pode ser utilizado um rótulo opcional na instrução EXIT, para especificar o nível de aninhamento que deve ser terminado.
597
37.7.3.2. EXIT EXIT [ rótulo ] [ WHEN expressão ];
Se nenhum rótulo for especificado o laço mais interno é terminado, e a instrução após o END LOOP é executada a seguir. Se o rótulo for especificado, este deve ser o rótulo do nível corrente ou de algum nível externo do laço ou bloco aninhado. Então o laço ou bloco é terminado, e o controle continua na instrução após o END do laço ou do bloco. Se WHEN estiver presente, a saída do laço ocorre somente se a condição especificada for verdadeira, senão o controle passa para a instrução após o EXIT. Exemplos: LOOP -- algum processamento IF contador > 0 THEN EXIT; -- sair do laço END IF; END LOOP; LOOP -- algum processamento EXIT WHEN contador > 0; END LOOP;
-- o mesmo do exemplo acima
BEGIN -- algum processamento IF estoque > 100000 THEN EXIT; -- inválido; EXIT não pode ser utilizado fora do LOOP END IF; END;
37.7.3.3. WHILE [<>] WHILE expressão LOOP instruções END LOOP;
A instrução WHILE repete a seqüência de instruções enquanto a expressão for avaliada como verdade. A condição é verificada logo antes de cada entrada no corpo do laço. Por exemplo: WHILE quantia_devida > 0 AND saldo_do_certificado_de_bonus > 0 LOOP -- algum processamento END LOOP; WHILE NOT expressão_booleana LOOP -- algum processamento END LOOP;
37.7.3.4. FOR (variação inteira) [<>] FOR nome IN [ REVERSE ] expressão .. expressão LOOP instruções END LOOP;
Esta forma do FOR cria um laço que interage num intervalo de valores inteiros. A variável nome é definida automaticamente como do tipo integer, e somente existe dentro do laço. As expressões que fornecem os
598
limites inferior e superior do intervalo são avaliadas somente uma vez, ao entrar no laço. Normalmente o passo da interação é 1, mas quando REVERSE é especificado se torna -1. Alguns exemplos de laços FOR inteiros: FOR i IN 1..10 LOOP -- algum processamento RAISE NOTICE ''i is %'', i; END LOOP; FOR i IN REVERSE 10..1 LOOP -- algum processamento END LOOP;
Se o limite inferior for maior do que o limite superior (ou menor do que, no caso do REVERSE), o corpo do laço não é executado nenhuma vez. Nenhum erro é gerado.
37.7.4. Laços através dos resultados da consulta Utilizando um tipo diferente de laço FOR, é possível interagir através dos resultados de uma consulta e manipular os dados. A sintaxe é: [<>] FOR registro_ou_linha IN comando LOOP instruções END LOOP;
Cada linha do resultado da consulta (um comando SELECT) é atribuída, sucessivamente, a variável tiporegistro ou tipo-linha, e o corpo do laço é executado para cada linha. Abaixo segue um exemplo: CREATE FUNCTION cs_refresh_mviews() RETURNS integer AS ' DECLARE mviews RECORD; BEGIN PERFORM cs_log(''Refreshing materialized views...''); FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP -- Now "mviews" has one record from cs_materialized_views PERFORM cs_log(''Refreshing materialized view '' || quote_ident(mviews.mv_name) || ''...''); EXECUTE ''TRUNCATE TABLE '' || quote_ident(mviews.mv_name); EXECUTE ''INSERT INTO '' || quote_ident(mviews.mv_name) || '' '' || mviews.mv_query; END LOOP; PERFORM cs_log(''Done refreshing materialized views.''); RETURN 1; END; ' LANGUAGE plpgsql;
Se o laço for terminado por uma instrução EXIT, o último valor de linha atribuído ainda é acessível após o laço. A instrução FOR-IN-EXECUTE é outra forma de interagir sobre os registros: [<>] FOR registro_ou_linha IN EXECUTE texto_da_expressão LOOP instruções END LOOP;
599
Esta forma é semelhante a anterior, exceto que o código fonte da instrução SELECT é especificado como uma expressão cadeia de caracteres, que é avaliada e replanejada a cada entrada no laço FOR. Isto permite ao programador escolher entre a velocidade da consulta pré-planejada e a flexibilidade da consulta dinâmica, da mesma maneira que na instrução EXECUTE pura. Nota: Atualmente o analisador do PL/pgSQL faz a distinção entre os dois tipos de laços FOR (inteiro e resultado de consulta), verificando se a variável de destino mencionada logo após o FOR foi declarada como uma variável tipo-registro ou tipo-linha. Se não foi, então é assumido como sendo um laço FOR inteiro. Isto pode ocasionar mensagens de erro bastante contra-intuitivas quando o problema é, digamos, que o nome da variável foi escrito errado após o FOR. Tipicamente a mensagem será algo como faltando ".." no final da expressão SQL.
37.8. Cursores Em vez de executar toda a consulta de uma vez, é possível definir um cursor encapsulando a consulta e, depois, ler poucas linhas do resultado da consulta de cada vez. Um dos motivos de fazer desta maneira, é para evitar a saturação da memória quando o resultado contém muitas linhas (Entretanto, os usuários da linguagem PL/pgSQL normalmente não precisam se preocupar com isto, uma vez que os laços FOR utilizam, automaticamente, um cursor internamente para evitar problemas de memória). Uma utilização mais interessante é retornar a referência a um cursor criado pela função, permitindo quem chama ler as linhas. Esta forma proporciona uma maneira eficiente para a função retornar conjuntos de linhas muito grandes.
37.8.1. Declaração de variáveis cursor Todos os acessos aos cursores na linguagem PL/pgSQL são feitos através de variáveis cursor, que sempre são do tipo de dado especial refcursor. Uma forma de criar uma variável cursor é simplesmente declará-la como do tipo refcursor. Outra forma é utilizar a sintaxe de declaração de cursor, cuja forma geral é: nome CURSOR [ ( argumentos ) ] FOR comando ;
(FOR pode ser substituído por IS para ficar compatível com o Oracle). Os argumentos, se forem especificados, ficam numa lista separada por vírgulas de pares nome tipo_de_dado que define os nomes a serem substituídos pelos valores dos parâmetros em uma determinada consulta. Os valores verdadeiros que substituirão estes nomes serão especificados posteriormente, quando o cursor for aberto. Alguns exemplos: DECLARE curs1 refcursor; curs2 CURSOR FOR SELECT * FROM tenk1; curs3 CURSOR (chave integer) IS SELECT * FROM tenk1 WHERE unico1 = chave;
Todas estas três variáveis possuem o tipo de dado refcursor, mas a primeira pode ser utilizada em qualquer consulta, enquanto a segunda possui uma consulta presa (bound) à mesma, e a terceira possui uma consulta parametrizada presa à mesma (A chave será substituída por um valor de parâmetro inteiro quando o cursor for aberto). A variável curs1 é dita como livre (unbound), uma vez quer não está presa a uma determinada consulta.
37.8.2. Abertura de cursores Antes do cursor poder ser utilizado para trazer linhas, este deve ser aberto (É a ação equivalente ao comando SQL DECLARE CURSOR). A linguagem PL/pgSQL possui três formas de instrução OPEN, duas das quais utilizam variáveis cursor livres, enquanto a terceira utiliza uma variável cursor presa. 37.8.2.1. OPEN FOR SELECT OPEN cursor_livre FOR SELECT ...;
A variável cursor é aberta e recebe a consulta especificada para executar. O cursor não pode estar aberto, e deve ter sido declarado como um cursor livre, ou seja, simplesmente como uma variável do tipo refcursor. O comando SELECT é tratado da mesma maneira feita nas outras instruções SELECT da linguagem PL/pgSQL: Os
600
nomes das variáveis da linguagem PL/pgSQL são substituídos, e o plano de execução é colocado no cache para uma possível reutilização. Exemplo: OPEN curs1 FOR SELECT * FROM foo WHERE chave = minha_chave;
37.8.2.2. OPEN FOR EXECUTE OPEN cursor_livre FOR EXECUTE cadeia_de_caracteres_da_consulta;
A variável cursor é aberta e recebe a consulta especificada para executar. O cursor não pode estar aberto, e deve ter sido declarado como um cursor livre, ou seja, simplesmente como uma variável do tipo refcursor. A consulta é especificada como uma expressão cadeia de caracteres da mesma maneira que no comando EXECUTE. Como habitual, esta forma provê flexibilidade e, portanto, a consulta pode variar entre execuções. Exemplo: OPEN curs1 FOR EXECUTE ''SELECT * FROM '' || quote_ident($1);
37.8.2.3. Abertura de cursor preso OPEN cursor_preso [ ( valores_dos_argumentos ) ];
Esta forma do OPEN é utilizada para abrir uma variável cursor com uma consulta presa a mesma quando é declarada. O cursor não pode estar aberto. Uma lista de expressões contendo os valores verdadeiros dos argumentos deve estar presente se, e somente se, o cursor for declarado como recebendo argumentos. Estes valores são substituídos na consulta. O plano de comando do cursor preso é sempre considerado como passível de ser colocado no cache; neste caso não há forma EXECUTE equivalente. Exemplos: OPEN curs2; OPEN curs3(42);
37.8.3. Utilização dos cursores Uma vez que o cursor tenha sido aberto, este pode ser manipulado pelas instruções descritas a seguir. Para começar, não há necessidade destas manipulações ocorrerem na mesma função que abriu o cursor. Pode ser retornado um valor refcursor pela função, e deixar por conta de quem chamou operar o cursor (Internamente, o valor de refcursor é simplesmente uma cadeia de caracteres com o nome do tão falado portal contendo o cursor para a consulta ativa. Este nome pode ser passado, atribuído a outras variáveis refcursor, e por aí em diante, sem perturbar o portal). Todos os portais são fechados implicitamente ao término da transação. Portanto, até o fim da transação o valor de refcursor pode ser utilizado para fazer referência a um cursor aberto . 37.8.3.1. FETCH FETCH cursor INTO destino;
A instrução FETCH coloca a próxima linha do cursor no destino, que deve ser uma variável tipo-linha, uma variável tipo-registro, ou uma lista separada por vírgulas de variáveis simples, da mesma maneira que no SELECT INTO. Como no SELECT INTO, a variável especial FOUND pode ser verificada para ver se foi obtida uma linha, ou não. Exemplo: FETCH curs1 INTO variável_linha; FETCH curs2 INTO foo, bar, baz;
601
37.8.3.2. CLOSE CLOSE cursor;
A instrução CLOSE fecha o portal que está por trás do cursor aberto. Pode ser utilizada para liberar recursos antes do fim da transação, ou para liberar a variável cursor para que esta possa ser aberta novamente. Exemplo: CLOSE curs1;
37.8.3.3. Retornar cursores As funções da linguagem PL/pgSQL podem retornar cursores para quem chamou. É útil para retornar várias linhas ou colunas, especialmente em conjuntos de resultados muito grandes. Para ser feito, a função abre o cursor e retorna o nome do cursor para quem chama (ou simplesmente abre o cursor utilizando o nome do portal especificado por, ou de outra forma conhecido por, quem chama). Quem chama pode então buscar as linhas do cursor. O cursor pode ser fechado por quem chama, ou será fechado automaticamente ao término da transação. O nome do portal utilizado para o cursor pode ser especificado pelo programador ou gerado automaticamente. Para especificar o nome do portal, simplesmente deve ser atribuída uma cadeia de caracteres à variável refcursor antes de abri-la. O valor cadeia de caracteres da variável refcursor será utilizado pelo OPEN como o nome do portal que está por trás. Entretanto, quando a variável refcursor é nula, o OPEN gera automaticamente um nome que não conflita com nenhum portal existente, e atribui este nome à variável refcursor. Nota: Uma variável cursor presa é inicializada com o valor cadeia de caracteres que representa o seu nome e, portanto, o portal terá o mesmo nome da variável cursor, a menos que o programador substitua este nome fazendo uma atribuição antes de abrir o cursor. Porém, uma variável cursor livre tem inicialmente o valor nulo por padrão e, portanto, recebe um nome único gerado automaticamente, a menos que este seja substituído.
O exemplo a seguir mostra uma maneira de fornecer o nome do cursor por quem chama: CREATE TABLE teste (col text); INSERT INTO teste VALUES ('123'); CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS ' BEGIN OPEN $1 FOR SELECT col FROM teste; RETURN $1; END; ' LANGUAGE plpgsql; BEGIN; SELECT reffunc('funccursor'); reffunc -----------funccursor (1 linha) FETCH ALL IN funccursor; col ----123 (1 linha) COMMIT;
602
O exemplo a seguir mostra a geração automática do nome do cursor: CREATE FUNCTION reffunc2() RETURNS refcursor AS ' DECLARE ref refcursor; BEGIN OPEN ref FOR SELECT col FROM teste; RETURN ref; END; ' LANGUAGE plpgsql; BEGIN; SELECT reffunc2(); reffunc2 -------------------(1 linha) FETCH ALL IN " "; col ----123 (1 linha) COMMIT;
37.9. Erros e mensagens A instrução RAISE é utilizada para gerar mensagens informativas e causar erros. RAISE nível 'formato' [, variável [, ...]];
Os níveis possíveis são DEBUG, LOG, INFO, NOTICE, WARNING, e EXCEPTION. O nível EXCEPTION causa um erro e interrompe a transação corrente; os outros níveis apenas geram mensagens com diferentes níveis de prioridade. Se mensagens de uma determinada prioridade são informadas ao cliente, escritas no log do servidor, ou as duas coisas, é controlado pelas variáveis de configuração log_min_messages e client_min_messages Veja a Seção 16.4 para obter mais informações. Dentro da cadeia de caracteres de formatação, o caractere % é substituído pela representação na forma de cadeia de caracteres do próximo argumento opcional. Deve ser escrito %% para produzir um % literal. Deve ser observado que atualmente os argumentos opcionais devem ser variáveis simples, e não expressões, e o formato deve ser um literal cadeia de caracteres simples. Neste exemplo o valor de v_job_id substitui o caractere % na cadeia de caracteres: RAISE NOTICE ''Chamando cs_create_job(%)'', v_job_id;
Este exemplo interrompe a transação com a mensagem de erro fornecida: RAISE EXCEPTION ''ID inexistente --> %'', id_usuario;
O PostgreSQL não possui um modelo de tratamento de exceções muito aperfeiçoado. Quando o analisador, planejador/otimizador ou executor decide que a declaração não pode mais ser processada, toda a transação é interrompida e o sistema volta para o laço principal para esperar pelo próximo comando da aplicação cliente. É possível se aprofundar no mecanismo de erro para ver o que acontece. Porém, atualmente é impossível informar o que realmente causou a interrupção (erro do formato do tipo de dado, erro de ponto flutuante, erro de análise, etc.). Também é possível que o servidor de banco de dados esteja em um estado incoerente neste ponto, portanto retornar para o executor superior ou emitir mais comandos pode corromper todo o banco de dados.
603
Portanto, a única coisa que a linguagem PL/pgSQL faz atualmente, quando encontra uma interrupção durante a execução de um procedimento de função ou de gatilho, é adicionar alguns campos à mensagem informando em que função e onde (o número da linha e tipo da instrução) onde o erro ocorreu. O erro sempre termina a execução da função.
37.10. Procedimentos de gatilho A linguagem PL/pgSQL pode ser utilizada para definir procedimentos de gatilho. O procedimento de gatilho é criado através do comando CREATE FUNCTION, sendo declarado como uma função que não recebe argumentos e retorna o tipo trigger. Observe que a função deve ser declarada sem argumentos, mesmo que espere receber argumentos especificados no comando CREATE TRIGGER; os argumentos do gatilho são passados através de TG_ARGV, conforme descrito abaixo. Quando uma função escrita em PL/pgSQL é chamada como um gatilho, diversas variáveis especiais são criadas automaticamente no bloco de nível superior. São estas: NEW
Tipo de dado RECORD; variável armazenando a nova linha do banco de dados para as operações de INSERT/UPDATE nos gatilhos no nível de linha. Esta variável é nula nos gatilhos no nível de declaração. OLD
Tipo de dado RECORD; variável armazenando a linha antiga do banco de dados para as operações de UPDATE/DELETE nos gatilhos no nível de linha. Esta variável é nula nos gatilhos no nível de declaração. TG_NAME
Tipo de dado name; variável contendo o nome do gatilho realmente disparado. TG_WHEN
Tipo de dado text; uma cadeia de caracteres contendo BEFORE ou AFTER dependendo da definição do gatilho. TG_LEVEL
Tipo de dado text; uma cadeia de caracteres contendo ROW ou STATEMENT dependendo da definição do gatilho. TG_OP
Tipo de dado text; uma cadeia de caracteres contendo INSERT, UPDATE, ou DELETE informando para qual operação o gatilho foi disparado. TG_RELID
Tipo de dado oid; o ID de objeto da tabela que causou o disparo do gatilho. TG_RELNAME
Tipo de dado name; o nome da tabela que causou o disparo do gatilho. TG_NARGS
Tipo de dado integer; o número de argumentos fornecidos ao procedimento de gatilho pela declaração CREATE TRIGGER. TG_ARGV[]
Tipo de dado matriz de text; os argumentos da declaração CREATE TRIGGER. O contador do índice começa por 0. Índices inválidos (menor que 0 ou maior ou igual a tg_nargs) resultam em um valor nulo.
Uma função de gatilho deve retornar nulo, ou um valor registro/linha possuindo a mesma estrutura da tabela para a qual o gatilho foi disparado. Os gatilhos no nível de linha disparados BEFORE (antes) podem retornar nulo, para sinalizar ao gerenciador do gatilho para pular o restante da operação para esta linha (ou seja, os gatilhos posteriores não são disparados, e o
604
INSERT/UPDATE/DELETE não ocorre para esta linha. Se for retornado um valor não nulo, então a operação prossegue com este valor de linha. Retornar um valor de linha diferente do valor original de NEW altera a linha que será inserida ou atualizada (mas não tem efeito direto no caso do DELETE). Para alterar a linha a ser armazenada, é possível substituir valores únicos diretamente no NEW e retornar o NEW modificado, ou construir
uma linha/registro novo completo para retornar. O valor retornado por um gatilhoBEFORE ou AFTER no nível de declaração, ou por um gatilho AFTER no nível de linha, é sempre ignorado; pode muito bem ser nulo. Entretanto, qualquer um destes tipos de gatilho pode interromper toda a operação causando um erro. O Exemplo 37-1 mostra um procedimento de gatilho escrito na linguagem PL/pgSQL. Exemplo 37-1. Um procedimento de gatilho escrito em PL/pgSQL Este exemplo de gatilho garante que sempre que uma linha da tabela é inserida ou atualizada, o nome do usuário e a hora são registrados na linha. Além disso verifica se o nome do empregado é fornecido e o salário é um valor positivo. CREATE TABLE emp ( nome_emp salario ultima_data ultimo_usuario );
text, integer, timestamp, text
CREATE FUNCTION emp_carimbo() RETURNS trigger AS ' BEGIN -- Verificar se o nome do empregado foi fornecido IF NEW.nome_emp IS NULL THEN RAISE EXCEPTION ''O nome do empregado não pode ser nulo''; END IF; IF NEW.salario IS NULL THEN RAISE EXCEPTION ''% não pode ter um salário nulo'', NEW.nome_emp; END IF; -- Quem é que paga para trabalhar? IF NEW.salario < 0 THEN RAISE EXCEPTION ''% não pode ter um salário negativo'', NEW.nome_emp; END IF; -- Registrar que alterou o pagamento e quando NEW.ultima_data := ''now''; NEW.ultimo_usuario := current_user; RETURN NEW; END; ' LANGUAGE plpgsql; CREATE TRIGGER emp_carimbo BEFORE INSERT OR UPDATE ON emp FOR EACH ROW EXECUTE PROCEDURE emp_carimbo();
37.11. Migração do PL/SQL do Oracle Esta seção explica as diferenças entre a linguagem PL/pgSQL do PostgreSQL e a linguagem PL/SQL do Oracle, para ajudar os desenvolvedores a migrarem do Oracle para o PostgreSQL. A linguagem PL/pgSQL é semelhante à linguagem PL/SQL em muitos aspectos. É uma linguagem estruturada em blocos, imperativa, e todas as variáveis devem ser declaradas. As atribuições, laços e condicionais são semelhantes. As principais diferenças que se deve ter em mente, ao migrar de PL/SQL para PL/pgSQL, são: •
No PostgreSQL não existe valor padrão para parâmetros.
605
•
Os nomes das funções do PostgreSQL podem ser sobrecarregados. Geralmente é utilizado para resolver o problema da falta de valor padrão para parâmetros.
•
Não há necessidade de cursores na linguagem PL/pgSQL, basta por a consulta na instrução FOR (Veja o Exemplo 37-3.)
•
No PostgreSQL há necessidade de criar seqüências de escape para apóstrofos presentes no corpo da função. Veja a Seção 37.2.1.
•
Em vez de pacotes, são utilizados esquemas para organizar as funções em grupos.
37.11.1. Exemplos de migração O Exemplo 37-2 mostra como migrar uma função simples de PL/SQL para PL/pgSQL. Exemplo 37-2. Migração de uma função simples de PL/SQL para PL/pgSQL Abaixo segue um exemplo de uma função PL/SQL do Oracle: CREATE OR REPLACE FUNCTION cs_fmt_browser_version (v_nome IN varchar, v_versao IN varchar) RETURN varchar IS BEGIN IF v_versao IS NULL THEN RETURN v_nome; END IF; RETURN v_nome || '/' || v_versao; END; / show errors;
Vamos examinar esta função, e ver as diferenças com relação à linguagem PL/pgSQL: •
O PostgreSQL não possui parâmetros com nome. Deve ser criado um aliás explícito dentro da função.
•
O Oracle permite que sejam passados parâmetros IN, OUT e INOUT para as funções. Por exemplo, INOUT significa que o parâmetro recebe um valor e retorna outro. O PostgreSQL somente possui parâmetros IN.
•
A palavra chave RETURN no protótipo da função (não no corpo da função), no PostgreSQL se torna RETURNS.
•
No PostgreSQL as funções são criadas utilizando apóstrofos como delimitadores do corpo da função e, portanto, há necessidade de criar seqüências de escape para os apóstrofos dentro do corpo da função.
•
Não existe o comando /show errors no PostgreSQL.
Abaixo está mostrado como esta função deve ficar parecida após ser migrada para o PostgreSQL 1 CREATE OR REPLACE FUNCTION cs_fmt_browser_version(varchar, varchar) RETURNS varchar AS ' DECLARE v_nome ALIAS FOR $1; v_versao ALIAS FOR $2; BEGIN IF v_versao IS NULL THEN return v_nome; END IF; RETURN v_nome || ''/'' || v_versao; END; ' LANGUAGE plpgsql;
O Exemplo 37-3 mostra como migrar uma função que cria outra função, e como tratar o problema dos apóstrofos.
606
Exemplo 37-3. Migrar uma função que cria outra função de PL/SQL para PL/pgSQL O procedimento abaixo obtém linhas a partir de uma instrução SELECT, e constrói uma função grande com os resultados em instruções IF, por motivo de eficiência. Em particular, deve ser observada a diferença entre o cursor e o laço FOR. Esta é a versão Oracle: CREATE OR REPLACE PROCEDURE cs_update_referrer_type_proc IS CURSOR referrer_keys IS SELECT * FROM cs_referrer_keys ORDER BY try_order; a_output VARCHAR(4000); BEGIN a_output := 'CREATE OR REPLACE FUNCTION cs_find_referrer_type (v_host IN VARCHAR, v_domain IN VARCHAR, v_url IN VARCHAR) RETURN VARCHAR IS BEGIN'; FOR referrer_key IN referrer_keys LOOP a_output := a_output || ' IF v_' || referrer_key.kind || ' LIKE ''' || referrer_key.key_string || ''' THEN RETURN ''' || referrer_key.referrer_type || '''; END IF;'; END LOOP; a_output := a_output || ' RETURN NULL; END;'; EXECUTE IMMEDIATE a_output; END; / show errors;
Abaixo está mostrado como esta função ficaria no PostgreSQL: CREATE FUNCTION cs_update_referrer_type_proc() RETURNS integer AS ' DECLARE referrer_keys RECORD; -- Registro genérico para ser utilizado no FOR a_output varchar(4000); BEGIN a_output := ''CREATE FUNCTION cs_find_referrer_type(varchar, varchar, varchar) RETURNS varchar AS '''' DECLARE v_host ALIAS FOR $1; v_domain ALIAS FOR $2; v_url ALIAS FOR $3; BEGIN ''; -- Observe como os resultados da consulta podem ser varridos no laço FOR -- utilizando a construção FOR. FOR referrer_keys IN SELECT * FROM cs_referrer_keys ORDER BY try_order LOOP a_output := a_output || '' IF v_'' || referrer_keys.kind || '' LIKE '''''''''' || referrer_keys.key_string || '''''''''' THEN RETURN '''''' || referrer_keys.referrer_type || ''''''; END IF;''; END LOOP; a_output := a_output || '' RETURN NULL; END; '''' LANGUAGE plpgsql;''; -- EXECUTE funciona porque não há substituição de variáveis,
607
-- senão iria falhar. Veja em PERFORM outra maneira de executar funções. EXECUTE a_output; END; ' LANGUAGE plpgsql;
O Exemplo 37-4 mostra como migrar uma função com parâmetros OUT e manipulação de cadeia de caracteres. O PostgreSQL não possui a função instr, mas isto pode ser resolvido utilizando uma combinação de outras funções. Na Seção 37.11.3 existe uma implementação em PL/pgSQL da função instr que pode ser utilizada para facilitar a migração. Exemplo 37-4. Migração de PL/SQL para PL/pgSQL de um procedimento com manipulação de cadeia de caracteres e parâmetros OUT O procedimento mostrado abaixo, escrito na linguagem PL/SQL do Oracle, é utilizado para analisar uma URL e retornar vários elementos (hospedeiro, caminho e consulta). As funções escritas em PL/pgSQL podem retornar apenas um valor. No PostgreSQL uma forma de resolver este problema é dividir o procedimento em três funções diferentes: uma para retornar o hospedeiro, outra o caminho e mais uma para a consulta. Esta é a versão Oracle: CREATE OR REPLACE PROCEDURE cs_parse_url( v_url IN VARCHAR, -- Parâmetro de v_host OUT VARCHAR, -- Parâmetro de v_path OUT VARCHAR, -- Parâmetro de v_query OUT VARCHAR) -- Parâmetro de IS a_pos1 INTEGER; a_pos2 INTEGER; BEGIN v_host := NULL; v_path := NULL; v_query := NULL; a_pos1 := instr(v_url, '//');
entrada saída saída saída
IF a_pos1 = 0 THEN RETURN; END IF; a_pos2 := instr(v_url, '/', a_pos1 + 2); IF a_pos2 = 0 THEN v_host := substr(v_url, a_pos1 + 2); v_path := '/'; RETURN; END IF; v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2); a_pos1 := instr(v_url, '?', a_pos2 + 1); IF a_pos1 = 0 THEN v_path := substr(v_url, a_pos2); RETURN; END IF; v_path := substr(v_url, a_pos2, a_pos1 - a_pos2); v_query := substr(v_url, a_pos1 + 1); END; / show errors;
Abaixo está mostrado como uma função em PL/pgSQL para retornar a parte do hospedeiro poderia se parecer:
608
CREATE OR REPLACE FUNCTION cs_parse_url_host(varchar) RETURNS varchar AS ' DECLARE v_url ALIAS FOR $1; v_host varchar; v_path varchar; a_pos1 integer; a_pos2 integer; a_pos3 integer; BEGIN v_host := NULL; a_pos1 := instr(v_url, ''//''); IF a_pos1 = 0 THEN RETURN ''''; -- Retornar uma cadeia de caracteres vazia END IF; a_pos2 := instr(v_url,''/'',a_pos1 + 2); IF a_pos2 = 0 THEN v_host := substr(v_url, a_pos1 + 2); v_path := ''/''; RETURN v_host; END IF; v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2 ); RETURN v_host; END; ' LANGUAGE plpgsql;
O Exemplo 37-5 mostra como migrar um procedimento que utiliza diversas funcionalidades específicas do Oracle. Exemplo 37-5. Migrar um procedimento de PL/SQL para PL/pgSQL A versão Oracle: CREATE OR REPLACE PROCEDURE cs_create_job(v_job_id IN INTEGER) IS a_running_job_count INTEGER; PRAGMA AUTONOMOUS_TRANSACTION;n BEGIN LOCK TABLE cs_jobs IN EXCLUSIVE MODE;o SELECT INTO FROM WHERE
count(*) a_running_job_count cs_jobs end_stamp IS NULL;
IF a_running_job_count > 0 THEN COMMIT; -- liberar bloqueiop raise_application_error(-20000, 'Impossível criar uma nova tarefa: já há uma em execução.'); END IF; DELETE FROM cs_active_job; INSERT INTO cs_active_job(job_id) VALUES (v_job_id); BEGIN INSERT INTO cs_jobs (job_id, start_stamp) VALUES (v_job_id, sysdate); -- não se preocupar se já existeq EXCEPTION WHEN dup_val_on_index THEN NULL; END; COMMIT; END; /
609
show errors
Procedimentos como este podem ser convertidos em funções PostgreSQL que retornam um número inteiro. Em particular este procedimento é interessante, porque ensina algumas coisas: n
Não existe a declaração PRAGMA no PostgreSQL.
o
Após executar LOCK TABLE, na linguagem PL/pgSQL o bloqueio não é liberado antes da transação que fez a chamada terminar.
p
Também não pode haver transações nas funções PL/pgSQL. Todas as funções (e as demais funções chamadas a partir destas) são executadas em uma transação, e o PostgreSQL desfaz a transação se algo de errado acontecer.
q
A exceção teria que ser substituída por uma instrução IF.
Abaixo está mostrada uma maneira de como esta função poderia ser migrada para PL/pgSQL: CREATE OR REPLACE FUNCTION cs_create_job(integer) RETURNS integer AS ' DECLARE v_job_id ALIAS FOR $1; a_running_job_count integer; a_num integer; BEGIN LOCK TABLE cs_jobs IN EXCLUSIVE MODE; SELECT count(*) INTO a_running_job_count FROM cs_jobs WHERE end_stamp IS NULL; IF a_running_job_count > 0 THEN RAISE EXCEPTION ''Impossível criar uma nova tarefa: já há uma em execução.''; END IF; DELETE FROM cs_active_job; INSERT INTO cs_active_job(job_id) VALUES (v_job_id); SELECT count(*) INTO a_num FROM cs_jobs WHERE job_id=v_job_id; IF NOT FOUND THEN -- Se não foi retornado nada pela última consulta -- Esta tarefa não está na tabela então será inserida. INSERT INTO cs_jobs(job_id, start_stamp) VALUES (v_job_id, current_timestamp); RETURN 1; ELSE RAISE NOTICE ''Tarefa já em execução.'';n END IF; RETURN 0; END; ' LANGUAGE plpgsql;
n
Observe como podem ser geradas mensagens (ou erros) em PL/pgSQL.
37.11.2. Outros detalhes a serem observados Esta seção explica algumas poucas outras coisas a serem observadas ao migrar funções da linguagem PL/SQL do Oracle para o PostgreSQL. 37.11.2.1. EXECUTE A versão PL/pgSQL do EXECUTE trabalha de forma semelhante à versão PL/SQL, mas é necessário lembrar de utilizar quote_literal(text) e quote_string(text) conforme descrito na Seção 37.6.4. Construções do tipo EXECUTE ''SELECT * FROM $1''; não funcionam, a menos que estas funções sejam utilizadas.
610
37.11.2.2. Otimização das funções PL/pgSQL O PostgreSQL disponibiliza dois modificadores de criação de função para otimizar a execução: se é imutável (se a função sempre retorna o mesmo resultado quando são passados os mesmos argumentos), se é “estrita” (se a função retorna nulo se algum dos argumentos for nulo). Veja a página de referência do comando CREATE FUNCTION para obter mais detalhes. Para fazer uso dos atributos de otimização, o comando CREATE FUNCTION deve ficar parecido com: CREATE FUNCTION foo(...) RETURNS integer AS ' ... ' LANGUAGE plpgsql STRICT IMMUTABLE;
37.11.3. Apêndice Esta seção contém o código de uma função instr compatível com a do Oracle, que pode ser utilizado para reduzir o esforço de migração. -----------
Funções instr equivalentes a do Oracle. Syntaxe: instr(string1, string2, [n], [m]) onde [] indica que os parâmetros são opcionais. Procura em string1, a partir no n-ésimo caractere, a m-ésima ocorrência de string2. Se n for negativo, procura para trás. Se n ou m não forem fornecidos, são assumidos igual a 1 (procura a partir do primeiro caractere a primeira ocorrência).
CREATE OR REPLACE FUNCTION instr(varchar, varchar) RETURNS integer AS ' DECLARE pos integer; BEGIN pos:= instr($1, $2, 1); RETURN pos; END; ' LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION instr(varchar, varchar, integer) RETURNS integer AS ' DECLARE string ALIAS FOR $1; string_to_search ALIAS FOR $2; beg_index ALIAS FOR $3; pos integer NOT NULL DEFAULT 0; temp_str varchar; beg integer; length integer; ss_length integer; BEGIN IF beg_index > 0 THEN temp_str := substring(string FROM beg_index); pos := position(string_to_search IN temp_str); IF pos = 0 THEN RETURN 0; ELSE RETURN pos + beg_index - 1; END IF; ELSE ss_length := char_length(string_to_search); length := char_length(string); beg := length + beg_index - ss_length + 2;
611
WHILE beg > 0 LOOP temp_str := substring(string FROM beg FOR ss_length); pos := position(string_to_search IN temp_str); IF pos > 0 THEN RETURN beg; END IF; beg := beg - 1; END LOOP; RETURN 0; END IF; END; ' LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION instr(varchar, varchar, integer, integer) RETURNS integer AS ' DECLARE string ALIAS FOR $1; string_to_search ALIAS FOR $2; beg_index ALIAS FOR $3; occur_index ALIAS FOR $4; pos integer NOT NULL DEFAULT 0; occur_number integer NOT NULL DEFAULT 0; temp_str varchar; beg integer; i integer; length integer; ss_length integer; BEGIN IF beg_index > 0 THEN beg := beg_index; temp_str := substring(string FROM beg_index); FOR i IN 1..occur_index LOOP pos := position(string_to_search IN temp_str); IF i = 1 THEN beg := beg + pos - 1; ELSE beg := beg + pos; END IF; temp_str := substring(string FROM beg + 1); END LOOP; IF pos = 0 THEN RETURN 0; ELSE RETURN beg; END IF; ELSE ss_length := char_length(string_to_search); length := char_length(string); beg := length + beg_index - ss_length + 2; WHILE beg > 0 LOOP temp_str := substring(string FROM beg FOR ss_length); pos := position(string_to_search IN temp_str); IF pos > 0 THEN occur_number := occur_number + 1; IF occur_number = occur_index THEN RETURN beg; END IF; END IF; beg := beg - 1; END LOOP; RETURN 0; END IF;
612
END; ' LANGUAGE plpgsql;
Exemplos de utilização: SELECT INSTR('CORPORATE FLOOR','OR') AS "Instring"; Instring ---------2 (1 linha) SELECT INSTR('CORPORATE FLOOR','OR',3) AS "Instring"; Instring ---------5 (1 linha) SELECT INSTR('CORPORATE FLOOR','OR',3,1) AS "Instring"; Instring ---------5 (1 linha) SELECT INSTR('CORPORATE FLOOR','OR',3,2) AS "Instring"; Instring ---------14 (1 linha)
Notas 1. Oracle — o Oracle utiliza as convenções: verbo_substantivo para procedimentos, funções e gatilhos (por exemplo, admitir_empregado, obter_salario e auditar_empregado, respectivamente); a convenção v_substantivo para as variáveis (por exemplo, v_nome); a convenção cursor_substantivo para os cursores (por exemplo, cursor_empregado, entre outras. Fonte: Develop Applications Using Database Procedures 7.2, PO1 Student Guide, Oracle. (N. do T.)
613
Capítulo 38. PL/Tcl - Tcl Procedural Language PL/Tcl is a loadable procedural language for the PostgreSQL database system that enables the Tcl language to be used to write functions and trigger procedures.
38.1. Visão geral PL/Tcl offers most of the capabilities a function writer has in the C language, except for some restrictions. The good restriction is that everything is executed in a safe Tcl interpreter. In addition to the limited command set of safe Tcl, only a few commands are available to access the database via SPI and to raise messages via elog(). There is no way to access internals of the database server or to gain OS-level access under the permissions of the PostgreSQL server process, as a C function can do. Thus, any unprivileged database user may be permitted to use this language. The other, implementation restriction is that Tcl functions cannot be used to create input/output functions for new data types. Sometimes it is desirable to write Tcl functions that are not restricted to safe Tcl. For example, one might want a Tcl function that sends email. To handle these cases, there is a variant of PL/Tcl called PL/TclU (for untrusted Tcl). This is the exact same language except that a full Tcl interpreter is used. If PL/TclU is used, it must be installed as an untrusted procedural language so that only database superusers can create functions in it. The writer of a PL/TclU function must take care that the function cannot be used to do anything unwanted, since it will be able to do anything that could be done by a user logged in as the database administrator. The shared object for the PL/Tcl and PL/TclU call handlers is automatically built and installed in the PostgreSQL library directory if Tcl/Tk support is specified in the configuration step of the installation procedure. To install PL/Tcl and/or PL/TclU in a particular database, use the createlang program, for example createlang pltcl dbname or createlang pltclu dbname.
38.2. PL/Tcl Functions and Arguments To create a function in the PL/Tcl language, use the standard syntax: CREATE FUNCTION funcname (argument-types) RETURNS return-type AS ' # PL/Tcl function body ' LANGUAGE pltcl;
PL/TclU is the same, except that the language has to be specified as pltclu. The body of the function is simply a piece of Tcl script. When the function is called, the argument values are passed as variables $1 ... $n to the Tcl script. The result is returned from the Tcl code in the usual way, with a return statement. For example, a function returning the greater of two integer values could be defined as: CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS ' if {$1 > $2} {return $1} return $2 ' LANGUAGE pltcl STRICT;
Note the clause STRICT, which saves us from having to think about null input values: if a null value is passed, the function will not be called at all, but will just return a null result automatically. In a nonstrict function, if the actual value of an argument is null, the corresponding $n variable will be set to an empty string. To detect whether a particular argument is null, use the function argisnull. For example, suppose that we wanted tcl_max with one null and one nonnull argument to return the nonnull argument, rather than null:
614
CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS ' if {[argisnull 1]} { if {[argisnull 2]} { return_null } return $2 } if {[argisnull 2]} { return $1 } if {$1 > $2} {return $1} return $2 ' LANGUAGE pltcl;
As shown above, to return a null value from a PL/Tcl function, execute return_null. This can be done whether the function is strict or not. Composite-type arguments are passed to the function as Tcl arrays. The element names of the array are the attribute names of the composite type. If an attribute in the passed row has the null value, it will not appear in the array. Here is an example: CREATE TABLE employee ( name text, salary integer, age integer ); CREATE FUNCTION overpaid(employee) RETURNS boolean AS ' if {200000.0 < $1(salary)} { return "t" } if {$1(age) < 30 && 100000.0 < $1(salary)} { return "t" } return "f" ' LANGUAGE pltcl;
There is currently no support for returning a composite-type result value.
38.3. Data Values in PL/Tcl The argument values supplied to a PL/Tcl function's code are simply the input arguments converted to text form (just as if they had been displayed by a SELECT statement). Conversely, the return command will accept any string that is acceptable input format for the function's declared return type. So, the PL/Tcl programmer can manipulate data values as if they were just text.
38.4. Global Data in PL/Tcl Sometimes it is useful to have some global data that is held between two calls to a function or is shared between different functions. This is easily done since all PL/Tcl functions executed in one session share the same safe Tcl interpreter. So, any global Tcl variable is accessible to all PL/Tcl function calls and will persist for the duration of the SQL session. (Note that PL/TclU functions likewise share global data, but they are in a different Tcl interpreter and cannot communicate with PL/Tcl functions.) To help protect PL/Tcl functions from unintentionally interfering with each other, a global array is made available to each function via the upvar command. The global name of this variable is the function's internal name, and the local name is GD. It is recommended that GD be used for private data of a function. Use regular Tcl global variables only for values that you specifically intend to be shared among multiple functions. An example of using GD appears in the spi_execp example below.
38.5. Database Access from PL/Tcl The following commands are available to access the database from the body of a PL/Tcl function:
615
spi_exec ?-count n? ?-array name? command ?loop-body?
Executes an SQL command given as a string. An error in the command causes an error to be raised. Otherwise, the return value of spi_exec is the number of rows processed (selected, inserted, updated, or deleted) by the command, or zero if the command is a utility statement. In addition, if the command is a SELECT statement, the values of the selected columns are placed in Tcl variables as described below. The optional -count value tells spi_exec the maximum number of rows to process in the command. The effect of this is comparable to setting up a query as a cursor and then saying FETCH n. If the command is a SELECT statement, the values of the result columns are placed into Tcl variables named after the columns. If the -array option is given, the column values are instead stored into the named associative array, with the column names used as array indexes. If the command is a SELECT statement and no loop-body script is given, then only the first row of results are stored into Tcl variables; remaining rows, if any, are ignored. No storing occurs if the query returns no rows. (This case can be detected by checking the result of spi_exec.) For example, spi_exec "SELECT count(*) AS cnt FROM pg_proc"
will set the Tcl variable $cnt to the number of rows in the pg_proc system catalog. If the optional loop-body argument is given, it is a piece of Tcl script that is executed once for each row in the query result. (loop-body is ignored if the given command is not a SELECT.) The values of the current row's columns are stored into Tcl variables before each iteration. For example, spi_exec -array C "SELECT * FROM pg_class" { elog DEBUG "have table $C(relname)" }
will print a log message for every row of pg_class. This feature works similarly to other Tcl looping constructs; in particular continue and break work in the usual way inside the loop body. If a column of a query result is null, the target variable for it is “unset” rather than being set. spi_prepare query typelist
Prepares and saves a query plan for later execution. The saved plan will be retained for the life of the current session. The query may use parameters, that is, placeholders for values to be supplied whenever the plan is actually executed. In the query string, refer to parameters by the symbols $1 ... $n. If the query uses parameters, the names of the parameter types must be given as a Tcl list. (Write an empty list for typelist if no parameters are used.) Presently, the parameter types must be identified by the internal type names shown in the system table pg_type; for example int4 not integer. The return value from spi_prepare is a query ID to be used in subsequent calls to spi_execp. See spi_execp for an example. spi_execp ?-count n? ?-array name? ?-nulls string? queryid ?value-list? ?loop-body?
Executes a query previously prepared with spi_prepare. queryid is the ID returned by spi_prepare. If the query references parameters, a value-list must be supplied. This is a Tcl list of actual values for the parameters. The list must be the same length as the parameter type list previously given to spi_prepare. Omit value-list if the query has no parameters. The optional value for -nulls is a string of spaces and 'n' characters telling spi_execp which of the parameters are null values. If given, it must have exactly the same length as the value-list. If it is not given, all the parameter values are nonnull. Except for the way in which the query and its parameters are specified, spi_execp works just like spi_exec. The -count, -array, and loop-body options are the same, and so is the result value. Here's an example of a PL/Tcl function using a prepared plan:
616
CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS ' if {![ info exists GD(plan) ]} { # prepare the saved plan on the first call set GD(plan) [ spi_prepare \\ "SELECT count(*) AS cnt FROM t1 WHERE num >= \\$1 AND num\ <= \\$2" \\ [ list int4 int4 ] ] } spi_execp -count 1 $GD(plan) [ list $1 $2 ] return $cnt ' LANGUAGE pltcl;
Note that each backslash that Tcl should see must be doubled when we type in the function, since the main parser processes backslashes, too, in CREATE FUNCTION. We need backslashes inside the query string given to spi_prepare to ensure that the $n markers will be passed through to spi_prepare as-is, and not replaced by Tcl variable substitution. spi_lastoid
Returns the OID of the row inserted by the last spi_exec or spi_execp, if the command was a singlerow INSERT. (If not, you get zero.) quote string
Duplicates all occurrences of single quote and backslash characters in the given string. This may be used to safely quote strings that are to be inserted into SQL commands given to spi_exec or spi_prepare. For example, think about an SQL command string like "SELECT '$val' AS ret"
where the Tcl variable val actually contains doesn't. This would result in the final command string SELECT 'doesn't' AS ret
which would cause a parse error during spi_exec or spi_prepare. The submitted command should contain SELECT 'doesn''t' AS ret
which can be formed in PL/Tcl using "SELECT '[ quote $val ]' AS ret"
One advantage of spi_execp is that you don't have to quote parameter values like this, since the parameters are never parsed as part of an SQL command string. elog level msg
Emits a log or error message. Possible levels are DEBUG, LOG, INFO, NOTICE, WARNING, ERROR, and FATAL. Most simply emit the given message just like the elog C function. ERROR raises an error condition: further execution of the function is abandoned, and the current transaction is aborted. FATAL aborts the transaction and causes the current session to shut down. (There is probably no good reason to use this error level in PL/Tcl functions, but it's provided for completeness.)
38.6. Trigger Procedures in PL/Tcl Trigger procedures can be written in PL/Tcl. PostgreSQL requires that a procedure that is to be called as a trigger must be declared as a function with no arguments and a return type of trigger. The information from the trigger manager is passed to the procedure body in the following variables: $TG_name
The name of the trigger from the CREATE TRIGGER statement. $TG_relid
The object ID of the table that caused the trigger procedure to be invoked.
617
$TG_relatts
A Tcl list of the table column names, prefixed with an empty list element. So looking up a column name in the list with Tcl's lsearch command returns the element's number starting with 1 for the first column, the same way the columns are customarily numbered in PostgreSQL. $TG_when
The string BEFORE or AFTER depending on the type of trigger call. $TG_level
The string ROW or STATEMENT depending on the type of trigger call. $TG_op
The string INSERT, UPDATE, or DELETE depending on the type of trigger call. $NEW
An associative array containing the values of the new table row for INSERT or UPDATE actions, or empty for DELETE. The array is indexed by column name. Columns that are null will not appear in the array. $OLD
An associative array containing the values of the old table row for UPDATE or DELETE actions, or empty for INSERT. The array is indexed by column name. Columns that are null will not appear in the array. $args
A Tcl list of the arguments to the procedure as given in the CREATE TRIGGER statement. These arguments are also accessible as $1 ... $n in the procedure body. The return value from a trigger procedure can be one of the strings OK or SKIP, or a list as returned by the array get Tcl command. If the return value is OK, the operation (INSERT/UPDATE/DELETE) that fired the trigger will proceed normally. SKIP tells the trigger manager to silently suppress the operation for this row. If a list is returned, it tells PL/Tcl to return a modified row to the trigger manager that will be inserted instead of the one given in $NEW. (This works for INSERT and UPDATE only.) Needless to say that all this is only meaningful when the trigger is BEFORE and FOR EACH ROW; otherwise the return value is ignored. Here's a little example trigger procedure that forces an integer value in a table to keep track of the number of updates that are performed on the row. For new rows inserted, the value is initialized to 0 and then incremented on every update operation. CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS ' switch $TG_op { INSERT { set NEW($1) 0 } UPDATE { set NEW($1) $OLD($1) incr NEW($1) } default { return OK } } return [array get NEW] ' LANGUAGE pltcl; CREATE TABLE mytab (num integer, description text, modcnt integer); CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
Notice that the trigger procedure itself does not know the column name; that's supplied from the trigger arguments. This lets the trigger procedure be reused with different tables.
618
38.7. Modules and the unknown command PL/Tcl has support for autoloading Tcl code when used. It recognizes a special table, pltcl_modules, which is presumed to contain modules of Tcl code. If this table exists, the module unknown is fetched from the table and loaded into the Tcl interpreter immediately after creating the interpreter. While the unknown module could actually contain any initialization script you need, it normally defines a Tcl unknown procedure that is invoked whenever Tcl does not recognize an invoked procedure name. PL/Tcl's standard version of this procedure tries to find a module in pltcl_modules that will define the required procedure. If one is found, it is loaded into the interpreter, and then execution is allowed to proceed with the originally attempted procedure call. A secondary table pltcl_modfuncs provides an index of which functions are defined by which modules, so that the lookup is reasonably quick. The PostgreSQL distribution includes support scripts to maintain these tables: pltcl_loadmod, pltcl_listmod, pltcl_delmod, as well as source for the standard unknown module in share/unknown.pltcl. This module must be loaded into each database initially to support the autoloading mechanism. The tables pltcl_modules and pltcl_modfuncs must be readable by all, but it is wise to make them owned and writable only by the database administrator.
38.8. Tcl Procedure Names In PostgreSQL, one and the same function name can be used for different functions as long as the number of arguments or their types differ. Tcl, however, requires all procedure names to be distinct. PL/Tcl deals with this by making the internal Tcl procedure names contain the object ID of the function from the system table pg_proc as part of their name. Thus, PostgreSQL functions with the same name and different argument types will be different Tcl procedures, too. This is not normally a concern for a PL/Tcl programmer, but it might be visible when debugging.
619
Capítulo 39. PL/Perl - Perl Procedural Language PL/Perl is a loadable procedural language that enables you to write PostgreSQL functions in the Perl (http://www.perl.com) programming language. To install PL/Perl in a particular database, use createlang plperl dbname. Dica: If a language is installed into template1, all subsequently created databases will have the language installed automatically. Nota: Users of source packages must specially enable the build of PL/Perl during the installation process. (Refer to the installation instructions for more information.) Users of binary packages might find PL/Perl in a separate subpackage.
39.1. PL/Perl Functions and Arguments To create a function in the PL/Perl language, use the standard syntax: CREATE FUNCTION funcname (argument-types) RETURNS return-type AS ' # PL/Perl function body ' LANGUAGE plperl;
The body of the function is ordinary Perl code. Arguments and results are handled as in any other Perl subroutine: Arguments are passed in @_, and a result value is returned with return or as the last expression evaluated in the function. For example, a function returning the greater of two integer values could be defined as: CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS ' if ($_[0] > $_[1]) { return $_[0]; } return $_[1]; ' LANGUAGE plperl;
If an SQL null value is passed to a function, the argument value will appear as “undefined” in Perl. The above function definition will not behave very nicely with null inputs (in fact, it will act as though they are zeroes). We could add STRICT to the function definition to make PostgreSQL do something more reasonable: if a null value is passed, the function will not be called at all, but will just return a null result automatically. Alternatively, we could check for undefined inputs in the function body. For example, suppose that we wanted perl_max with one null and one non-null argument to return the non-null argument, rather than a null value: CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS ' my ($a,$b) = @_; if (! defined $a) { if (! defined $b) { return undef; } return $b; } if (! defined $b) { return $a; } if ($a > $b) { return $a; } return $b; ' LANGUAGE plperl;
As shown above, to return an SQL null value from a PL/Perl function, return an undefined value. This can be done whether the function is strict or not. Composite-type arguments are passed to the function as references to hashes. The keys of the hash are the attribute names of the composite type. Here is an example:
620
CREATE TABLE employee ( name text, basesalary integer, bonus integer ); CREATE FUNCTION empcomp(employee) RETURNS integer AS ' my ($emp) = @_; return $emp->{''basesalary''} + $emp->{''bonus''}; ' LANGUAGE plperl; SELECT name, empcomp(employee) FROM employee;
There is currently no support for returning a composite-type result value. Dica: Because the function body is passed as an SQL string literal to CREATE FUNCTION, you have to escape single quotes and backslashes within your Perl source, typically by doubling them as shown in the above example. Another possible approach is to avoid writing single quotes by using Perl's extended quoting operators (q[], qq[], qw[]).
39.2. Data Values in PL/Perl The argument values supplied to a PL/Perl function's code are simply the input arguments converted to text form (just as if they had been displayed by a SELECT statement). Conversely, the return command will accept any string that is acceptable input format for the function's declared return type. So, the PL/Perl programmer can manipulate data values as if they were just text.
39.3. Database Access from PL/Perl Access to the database itself from your Perl function can be done via an experimental module DBD::PgSPI (http://www.cpan.org/modules/by-module/DBD/APILOS/) (also available at CPAN mirror sites (http://www.cpan.org/SITES.html)). This module makes available a DBI-compliant database-handle named $pg_dbh that can be used to perform queries with normal DBI syntax. PL/Perl itself presently provides only one additional Perl command: elog level, msg
Emit a log or error message. Possible levels are DEBUG, LOG, INFO, NOTICE, WARNING, and ERROR. ERROR raises an error condition: further execution of the function is abandoned, and the current transaction is aborted.
39.4. Trusted and Untrusted PL/Perl Normally, PL/Perl is installed as a “trusted” programming language named plperl. In this setup, certain Perl operations are disabled to preserve security. In general, the operations that are restricted are those that interact with the environment. This includes file handle operations, require, and use (for external modules). There is no way to access internals of the database server process or to gain OS-level access with the permissions of the server process, as a C function can do. Thus, any unprivileged database user may be permitted to use this language. Here is an example of a function that will not work because file system operations are not allowed for security reasons: CREATE FUNCTION badfunc() RETURNS integer AS ' open(TEMP, ">/tmp/badfile"); print TEMP "Gotcha!\n"; return 1; ' LANGUAGE plperl;
The creation of the function will succeed, but executing it will not.
621
Sometimes it is desirable to write Perl functions that are not restricted. For example, one might want a Perl function that sends mail. To handle these cases, PL/Perl can also be installed as an “untrusted” language (usually called PL/PerlU). In this case the full Perl language is available. If the createlang program is used to install the language, the language name plperlu will select the untrusted PL/Perl variant. The writer of a PL/PerlU function must take care that the function cannot be used to do anything unwanted, since it will be able to do anything that could be done by a user logged in as the database administrator. Note that the database system allows only database superusers to create functions in untrusted languages. If the above function was created by a superuser using the language plperlu, execution would succeed.
39.5. Missing Features The following features are currently missing from PL/Perl, but they would make welcome contributions. •
PL/Perl functions cannot call each other directly (because they are anonymous subroutines inside Perl). There's presently no way for them to share global variables, either.
•
PL/Perl cannot be used to write trigger functions.
•
DBD::PgSPI or similar capability should be integrated into the standard PostgreSQL distribution.
622
Capítulo 40. PL/Python - Python Procedural Language The PL/Python procedural language allows PostgreSQL functions to be written in the Python (http://www.python.org) language. To install PL/Python in a particular database, use createlang plpythonu dbname. Dica: If a language is installed into template1, all subsequently created databases will have the language installed automatically.
As of PostgreSQL 7.4, PL/Python is only available as an “untrusted” language (meaning it does not offer any way of restricting what users can do in it). It has therefore been renamed to plpythonu. The trusted variant plpython may become available again in future, if a new secure execution mechanism is developed in Python. Nota: Users of source packages must specially enable the build of PL/Python during the installation process. (Refer to the installation instructions for more information.) Users of binary packages might find PL/Python in a separate subpackage.
40.1. PL/Python Functions The Python code you write gets transformed into a Python function. E.g., CREATE FUNCTION myfunc(text) RETURNS text AS 'return args[0]' LANGUAGE plpythonu;
gets transformed into def __plpython_procedure_myfunc_23456(): return args[0]
assuming that 23456 is the OID of the function. If you do not provide a return value, Python returns the default None. The language module translates Python's None into the SQL null value.
The PostgreSQL function parameters are available in the global args list. In the myfunc example, args[0] contains whatever was passed in as the text argument. For myfunc2(text, integer), args[0] would contain the text argument and args[1] the integer argument. The global dictionary SD is available to store data between function calls. This variable is private static data. The global dictionary GD is public data, available to all Python functions within a session. Use with care. Each function gets its own execution environment in the Python interpreter, so that global data and function arguments from myfunc are not available to myfunc2. The exception is the data in the GD dictionary, as mentioned above.
40.2. Trigger Functions When a function is used in a trigger, the dictionary TD contains trigger-related values. The trigger rows are in TD["new"] and/or TD["old"] depending on the trigger event. TD["event"] contains the event as a string (INSERT, UPDATE, DELETE, or UNKNOWN). TD["when"] contains one of BEFORE, AFTER, and UNKNOWN. TD["level"] contains one of ROW, STATEMENT, and UNKNOWN. TD["name"] contains the trigger name, and TD["relid"] contains the OID of the table on which the trigger occurred. If the trigger was called with arguments they are available in TD["args"][0] to TD["args"][(n-1)]. If TD["when"] is BEFORE, you may return None or "OK" from the Python function to indicate the row is unmodified, "SKIP" to abort the event, or "MODIFY" to indicate you've modified the row.
623
40.3. Database Access The PL/Python language module automatically imports a Python module called plpy. The functions and constants in this module are available to you in the Python code as plpy.foo. At present plpy implements the functions plpy.debug("msg"), plpy.log("msg"), plpy.info("msg"), plpy.notice("msg"), plpy.warning("msg"), plpy.error("msg"), and plpy.fatal("msg"). They are mostly equivalent to calling elog(LEVEL, "msg") from C code. plpy.error and plpy.fatal actually raise a Python exception which, if uncaught, causes the PL/Python module to call elog(ERROR, msg) when the function handler returns from the Python interpreter. Long-jumping out of the Python interpreter is probably not good. raise plpy.ERROR("msg") and raise plpy.FATAL("msg") are equivalent to calling plpy.error and plpy.fatal, respectively. Additionally, the plpy module provides two functions called execute and prepare. Calling plpy.execute with a query string and an optional limit argument causes that query to be run and the result to be returned in a result object. The result object emulates a list or dictionary object. The result object can be accessed by row number and column name. It has these additional methods: nrows which returns the number of rows returned by the query, and status which is the SPI_exec() return value. The result object can be modified. For example, rv = plpy.execute("SELECT * FROM my_table", 5)
returns up to 5 rows from my_table. If my_table has a column my_column, it would be accessed as foo = rv[i]["my_column"]
The second function, plpy.prepare, prepares the execution plan for a query. It is called with a query string and a list of parameter types, if you have parameter references in the query. For example: plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", [ "text" ]) text is the type of the variable you will be passing for $1. After preparing a statement, you use the function plpy.execute to run it: rv = plpy.execute(plan, [ "name" ], 5)
The third argument is the limit and is optional. In the current version, any database error encountered while running a PL/Python function will result in the immediate termination of that function by the server; it is not possible to trap error conditions using Python try ... catch constructs. For example, a syntax error in an SQL statement passed to the plpy.execute call will terminate the function. This behavior may be changed in a future release. When you prepare a plan using the PL/Python module it is automatically saved. Read the SPI documentation (Capítulo 41) for a description of what this means. In order to make effective use of this across function calls one needs to use one of the persistent storage dictionaries SD or GD (see Seção 40.1). For example: CREATE FUNCTION usesavedplan() RETURNS trigger AS ' if SD.has_key("plan"): plan = SD["plan"] else: plan = plpy.prepare("SELECT 1") SD["plan"] = plan # rest of function ' LANGUAGE plpythonu;
624
Capítulo 41. Server Programming Interface The Server Programming Interface (SPI) gives writers of user-defined C functions the ability to run SQL commands inside their functions. SPI is a set of interface functions to simplify access to the parser, planner, optimizer, and executor. SPI also does some memory management. Nota: The available procedural languages provide various means to execute SQL commands from procedures. Some of these are based on or modelled after SPI, so this documentation might be of use for users of those languages as well.
To avoid misunderstanding we'll use the term “function” when we speak of SPI interface functions and “procedure” for a user-defined C-function that is using SPI. Note that if during the execution of a procedure the transaction is aborted because of an error in a command, then control will not be returned to your procedure. Rather, all work will be rolled back and the server will wait for the next command from the client. A related restriction is the inability to execute BEGIN, COMMIT, and ROLLBACK (transaction control statements) inside a procedure. Both of these restrictions will probably be changed in the future. SPI functions return a nonnegative result on success (either via a returned integer value or in the global variable SPI_result, as described below). On error, a negative result or NULL will be returned. Source code files that use SPI must include the header file executor/spi.h.
41.1. Interface Functions
625
SPI_connect Nome SPI_connect — connect a procedure to the SPI manager
Sinopse int SPI_connect(void)
Descrição SPI_connect opens a connection from a procedure invocation to the SPI manager. You must call this
function if you want to execute commands through SPI. Some utility SPI functions may be called from unconnected procedures. If your procedure is already connected, SPI_connect will return the error code SPI_ERROR_CONNECT. This could happen if a procedure that has called SPI_connect directly calls another procedure that calls SPI_connect. While recursive calls to the SPI manager are permitted when an SQL command called through SPI invokes another function that uses SPI, directly nested calls to SPI_connect and SPI_finish are forbidden.
Valor retornado SPI_OK_CONNECT
on success SPI_ERROR_CONNECT
on error
626
SPI_finish Nome SPI_finish — disconnect a procedure from the SPI manager
Sinopse int SPI_finish(void)
Descrição SPI_finish closes an existing connection to the SPI manager. You must call this function after completing
the SPI operations needed during your procedure's current invocation. You do not need to worry about making this happen, however, if you abort the transaction via elog(ERROR). In that case SPI will clean itself up automatically. If SPI_finish is called without having a valid connection, it will return SPI_ERROR_UNCONNECTED. There is no fundamental problem with this; it means that the SPI manager has nothing to do.
Valor retornado SPI_OK_FINISH
if properly disconnected SPI_ERROR_UNCONNECTED
if called from an unconnected procedure
627
SPI_exec Nome SPI_exec — execute a command
Sinopse int SPI_exec(const char * command, int count)
Descrição SPI_exec executes the specified SQL command for count rows.
This function should only be called from a connected procedure. If count is zero then it executes the command for all rows that it applies to. If count is greater than 0, then the number of rows for which the command will be executed is restricted (much like a LIMIT clause). For example, SPI_exec("INSERT INTO tab SELECT * FROM tab", 5);
will allow at most 5 rows to be inserted into the table. You may pass multiple commands in one string, and the command may be rewritten by rules. SPI_exec returns the result for the command executed last. The actual number of rows for which the (last) command was executed is returned in the global variable SPI_processed (unless the return value of the function is SPI_OK_UTILITY). If the return value of the function is SPI_OK_SELECT then you may the use global pointer SPITupleTable *SPI_tuptable to access
the result rows. The structure SPITupleTable is defined thus: typedef struct { MemoryContext tuptabcxt; uint32 alloced; uint32 free; TupleDesc tupdesc; HeapTuple *vals; } SPITupleTable;
/* /* /* /* /*
memory context of result table */ number of alloced vals */ number of free vals */ row descriptor */ rows */
vals is an array of pointers to rows. (The number of valid entries is given by SPI_processed). tupdesc is a row descriptor which you may pass to SPI functions dealing with rows. tuptabcxt, alloced, and free are internal fields not intended for use by SPI callers. SPI_finish frees all SPITupleTables allocated during the current procedure. You can free a particular result table earlier, if you are done with it, by calling SPI_freetuptable.
Argumentos const char * command
string containing command to execute int count
maximum number of rows to process or return
Valor retornado If the execution of the command was successful then one of the following (nonnegative) values will be returned:
628
SPI_OK_SELECT
if a SELECT (but not SELECT ... INTO) was executed SPI_OK_SELINTO
if a SELECT ... INTO was executed SPI_OK_DELETE
if a DELETE was executed SPI_OK_INSERT
if an INSERT was executed SPI_OK_UPDATE
if an UPDATE was executed SPI_OK_UTILITY
if a utility command (e.g., CREATE TABLE) was executed On error, one of the following negative values is returned: SPI_ERROR_ARGUMENT
if command is NULL or count is less than 0 SPI_ERROR_COPY
if COPY TO stdout or COPY FROM stdin was attempted SPI_ERROR_CURSOR
if DECLARE, CLOSE, or FETCH was attempted SPI_ERROR_TRANSACTION
if BEGIN, COMMIT, or ROLLBACK was attempted SPI_ERROR_OPUNKNOWN
if the command type is unknown (shouldn't happen) SPI_ERROR_UNCONNECTED
if called from an unconnected procedure
Observações The functions SPI_exec, SPI_execp, and SPI_prepare change both SPI_processed and SPI_tuptable (just the pointer, not the contents of the structure). Save these two global variables into local procedure variables if you need to access the result of SPI_exec or SPI_execp across later calls.
629
SPI_prepare Nome SPI_prepare — prepare a plan for a command, without executing it yet
Sinopse void * SPI_prepare(const char * command, int nargs, Oid * argtypes)
Descrição SPI_prepare creates and returns an execution plan for the specified command but doesn't execute the
command. This function should only be called from a connected procedure. When the same or a similar command is to be executed repeatedly, it may be advantageous to perform the planning only once. SPI_prepare converts a command string into an execution plan that can be executed repeatedly using SPI_execp. A prepared command can be generalized by writing parameters ($1, $2, etc.) in place of what would be constants in a normal command. The actual values of the parameters are then specified when SPI_execp is called. This allows the prepared command to be used over a wider range of situations than would be possible without parameters. The plan returned by SPI_prepare can be used only in the current invocation of the procedure since SPI_finish frees memory allocated for a plan. But a plan can be saved for longer using the function SPI_saveplan.
Argumentos const char * command
command string int nargs
number of input parameters ($1, $2, etc.) Oid * argtypes
pointer to an array containing the OIDs of the data types of the parameters
Valor retornado SPI_prepare returns non-null pointer to an execution plan. On error, NULL will be returned. In both cases, SPI_result will be set analogous to the value returned by SPI_exec, except that it is set to SPI_ERROR_ARGUMENT if command is NULL, or if nargs is less than 0, or if nargs is greater than 0 and argtypes is NULL.
Observações There is a disadvantage to using parameters: since the planner does not know the values that will be supplied for the parameters, it may make worse planning choices than it would make for a normal command with all constants visible.
630
SPI_execp Nome SPI_execp — executes a plan prepared by SPI_prepare
Sinopse int SPI_execp(void * plan, Datum * values, const char * nulls, int count)
Descrição SPI_execp executes a plan prepared by SPI_prepare. tcount has the same interpretation as in SPI_exec.
Argumentos void * plan
execution plan (returned by SPI_prepare) Datum *values
actual parameter values const char * nulls
An array describing which parameters are null. n indicates a null value (entry in values will be ignored); a space indicates a nonnull value (entry in values is valid). If nulls is NULL then SPI_execp assumes that no parameters are null. int count
number of row for which plan is to be executed
Valor retornado The return value is the same as for SPI_exec or one of the following: SPI_ERROR_ARGUMENT
if plan is NULL or count is less than 0 SPI_ERROR_PARAM
if values is NULL and plan was prepared with some parameters
SPI_processed and SPI_tuptable are set as in SPI_exec if successful.
Observações If one of the objects (a table, function, etc.) referenced by the prepared plan is dropped during the session then the result of SPI_execp for this plan will be unpredictable.
631
SPI_cursor_open Nome SPI_cursor_open — set up a cursor using a plan created with SPI_prepare
Sinopse Portal SPI_cursor_open(const char * name, void * plan, Datum * values, const char * nulls)
Descrição SPI_cursor_open sets up a cursor (internally, a portal) that will execute a plan prepared by SPI_prepare.
Using a cursor instead of executing the plan directly has two benefits. First, the result rows can be retrieved a few at a time, avoiding memory overrun for queries that return many rows. Second, a portal can outlive the current procedure (it can, in fact, live to the end of the current transaction). Returning the portal name to the procedure's caller provides a way of returning a row set as result.
Argumentos const char * name
name for portal, or NULL to let the system select a name void * plan
execution plan (returned by SPI_prepare) Datum * values
actual parameter values const char *nulls
An array describing which parameters are null values. n indicates a null value (entry in values will be ignored); a space indicates a nonnull value (entry in values is valid). If nulls is NULL then SPI_cursor_open assumes that no parameters are null.
Valor retornado pointer to portal containing the cursor, or NULL on error
632
SPI_cursor_find Nome SPI_cursor_find — find an existing cursor by name
Sinopse Portal SPI_cursor_find(const char * name)
Descrição SPI_cursor_find finds an existing portal by name. This is primarily useful to resolve a cursor name
returned as text by some other function.
Argumentos const char * name
name of the portal
Valor retornado pointer to the portal with the specified name, or NULL if none was found
633
SPI_cursor_fetch Nome SPI_cursor_fetch — fetch some rows from a cursor
Sinopse void SPI_cursor_fetch(Portal portal, bool forward, int count)
Descrição SPI_cursor_fetch fetches some rows from a cursor. This is equivalent to the SQL command FETCH.
Argumentos Portal portal
portal containing the cursor bool forward
true for fetch forward, false for fetch backward int count
maximum number of rows to fetch
Valor retornado SPI_processed and SPI_tuptable are set as in SPI_exec if successful.
634
SPI_cursor_move Nome SPI_cursor_move — move a cursor
Sinopse void SPI_cursor_move(Portal portal, bool forward, int count)
Descrição SPI_cursor_move skips over some number of rows in a cursor. This is equivalent to the SQL command MOVE.
Argumentos Portal portal
portal containing the cursor bool forward
true for move forward, false for move backward int count
maximum number of rows to move
635
SPI_cursor_close Nome SPI_cursor_close — close a cursor
Sinopse void SPI_cursor_close(Portal portal)
Descrição SPI_cursor_close closes a previously created cursor and releases its portal storage.
All open cursors are closed automatically at the end of a transaction. SPI_cursor_close need only be invoked if it is desirable to release resources sooner.
Argumentos Portal portal
portal containing the cursor
636
SPI_saveplan Nome SPI_saveplan — save a plan
Sinopse void * SPI_saveplan(void * plan)
Descrição SPI_saveplan saves a passed plan (prepared by SPI_prepare) in memory protected from freeing by SPI_finish and by the transaction manager and returns a pointer to the saved plan. This gives you the ability
to reuse prepared plans in the subsequent invocations of your procedure in the current session. You may save the pointer returned in a local variable. Always check if this pointer is NULL or not either when preparing a plan or using an already prepared plan in SPI_execp.
Argumentos void * plan
the plan to be saved
Valor retornado Pointer to the saved plan; NULL if unsuccessful. On error, SPI_result is set thus: SPI_ERROR_ARGUMENT
if plan is NULL SPI_ERROR_UNCONNECTED
if called from an unconnected procedure
Observações If one of the objects (a table, function, etc.) referenced by the prepared plan is dropped during the session then the results of SPI_execp for this plan will be unpredictable.
41.2. Interface Support Functions The functions described here provide an interface for extracting information from result sets returned by SPI_exec and other SPI functions.
All functions described in this section may be used by both connected and unconnected procedures.
637
SPI_fame Nome SPI_fname — determine the column name for the specified column number
Sinopse char * SPI_fname(TupleDesc rowdesc, int colnumber)
Descrição SPI_fname returns the column name of the specified column. (You can use pfree to release the copy of the
name when you don't need it anymore.)
Argumentos TupleDesc rowdesc
input row description int colnumber
column number (count starts at 1)
Valor retornado The column name; NULL if colnumber is out of range. SPI_result set to SPI_ERROR_NOATTRIBUTE on error.
638
SPI_fnumber Nome SPI_fnumber — determine the column number for the specified column name
Sinopse int SPI_fnumber(TupleDesc rowdesc, const char * colname)
Descrição SPI_fnumber returns the column number for the column with the specified name.
If colname refers to a system column (e.g., oid) then the appropriate negative column number will be returned. The caller should be careful to test the return value for exact equality to SPI_ERROR_NOATTRIBUTE to detect an error; testing the result for less than or equal to 0 is not correct unless system columns should be rejected.
Argumentos TupleDesc rowdesc
input row description const char * colname
column name
Valor retornado Column number (count starts at 1), or SPI_ERROR_NOATTRIBUTE if the named column was not found.
639
SPI_getvalue Nome SPI_getvalue — return the string value of the specified column
Sinopse char * SPI_getvalue(HeapTuple row, TupleDesc rowdesc, int colnumber)
Descrição SPI_getvalue returns the string representation of the value of the specified column.
The result is returned in memory allocated using palloc. (You can use pfree to release the memory when you don't need it anymore.)
Argumentos HeapTuple row
input row to be examined TupleDesc rowdesc
input row description int colnumber
column number (count starts at 1)
Valor retornado Column value, or NULL if the column is null, colnumber is out of range (SPI_result is set to SPI_ERROR_NOATTRIBUTE), or no no output function available (SPI_result is set to SPI_ERROR_NOOUTFUNC).
640
SPI_getbinval Nome SPI_getbinval — return the binary value of the specified column
Sinopse Datum SPI_getbinval(HeapTuple row, TupleDesc rowdesc, int colnumber, bool * isnull)
Descrição SPI_getbinval returns the value of the specified column in the internal form (as type Datum).
This function does not allocate new space for the datum. In the case of a pass-by-reference data type, the return value will be a pointer into the passed row.
Argumentos HeapTuple row
input row to be examined TupleDesc rowdesc
input row description int rownumber
column number (count starts at 1) bool * isnull
flag for a null value in the column
Valor retornado The binary value of the column is returned. The variable pointed to by isnull is set to true if the column is null, else to false. SPI_result is set to SPI_ERROR_NOATTRIBUTE on error.
641
SPI_gettype Nome SPI_gettype — return the data type name of the specified column
Sinopse char * SPI_gettype(TupleDesc rowdesc, int colnumber)
Descrição SPI_gettype returns the data type name of the specified column. (You can use pfree to release the copy of
the name when you don't need it anymore.)
Argumentos TupleDesc rowdesc
input row description int colnumber
column number (count starts at 1)
Valor retornado The data type name of the specified column, or NULL on error. SPI_result is set to SPI_ERROR_NOATTRIBUTE on error.
642
SPI_gettypeid Nome SPI_gettypeid — return the data type OID of the specified column
Sinopse Oid SPI_gettypeid(TupleDesc rowdesc, int colnumber)
Descrição SPI_gettypeid returns the OID of the data type of the specified column.
Argumentos TupleDesc rowdesc
input row description int colnumber
column number (count starts at 1)
Valor retornado The OID of the data type of the specified column or InvalidOid on error. On error, SPI_result is set to SPI_ERROR_NOATTRIBUTE.
643
SPI_getrelname Nome SPI_getrelname — return the name of the specified relation
Sinopse char * SPI_getrelname(Relation rel)
Descrição SPI_getrelname returns the name of the specified relation. (You can use pfree to release the copy of the
name when you don't need it anymore.)
Argumentos Relation rel
input relation
Valor retornado The name of the specified relation.
41.3. Memory Management PostgreSQL allocates memory within memory contexts, which provide a convenient method of managing allocations made in many different places that need to live for differing amounts of time. Destroying a context releases all the memory that was allocated in it. Thus, it is not necessary to keep track of individual objects to avoid memory leaks; instead only a relatively small number of contexts have to be managed. palloc and related functions allocate memory from the “current” context. SPI_connect creates a new memory context and makes it current. SPI_finish restores the previous current memory context and destroys the context created by SPI_connect. These actions ensure that transient
memory allocations made inside your procedure are reclaimed at procedure exit, avoiding memory leakage. However, if your procedure needs to return an object in allocated memory (such as a value of a pass-byreference data type), you cannot allocate that memory using palloc, at least not while you are connected to SPI. If you try, the object will be deallocated by SPI_finish, and your procedure will not work reliably. To solve this problem, use SPI_palloc to allocate memory for your return object. SPI_palloc allocates memory in the “upper executor context”, that is, the memory context that was current when SPI_connect was called, which is precisely the right context for return a value from your procedure. If SPI_palloc is called while the procedure is not connected to SPI, then it acts the same as a normal palloc. Before a procedure connects to the SPI manager, the current memory context is the upper executor context, so all allocations made by the procedure via palloc or by SPI utility functions are made in this context. When SPI_connect is called, the private context of the procedure, which is created by SPI_connect, is made the current context. All allocations made by palloc, repalloc, or SPI utility functions (except for SPI_copytuple, SPI_copytupledesc, SPI_copytupleintoslot, SPI_modifytuple, and SPI_palloc) are made in this context. When a procedure disconnects from the SPI manager (via SPI_finish) the current context is restored to the upper executor context, and all allocations made in the procedure memory context are freed and cannot be used any more. All functions described in this section may be used by both connected and unconnected procedures. In an unconnected procedure, they act the same as the underlying ordinary server functions (palloc, etc.).
644
SPI_plloc Nome SPI_palloc — allocate memory in the upper executor context
Sinopse void * SPI_palloc(Size size)
Descrição SPI_palloc allocates memory in the upper executor context.
Argumentos Size size
size in bytes of storage to allocate
Valor retornado pointer to new storage space of the specified size
645
SPI_repalloc Nome SPI_repalloc — reallocate memory in the upper executor context
Sinopse void * SPI_repalloc(void * pointer, Size size)
Descrição SPI_repalloc changes the size of a memory segment previously allocated using SPI_palloc.
This function is no longer different from plain repalloc. It's kept just for backward compatibility of existing code.
Argumentos void * pointer
pointer to existing storage to change Size size
size in bytes of storage to allocate
Valor retornado pointer to new storage space of specified size with the contents copied from the existing area
646
SPI_pfree Nome SPI_pfree — free memory in the upper executor context
Sinopse void SPI_pfree(void * pointer)
Descrição SPI_pfree frees memory previously allocated using SPI_palloc or SPI_repalloc.
This function is no longer different from plain pfree. It's kept just for backward compatibility of existing code.
Argumentos void * pointer
pointer to existing storage to free
647
SPI_copytuple Nome SPI_copytuple — make a copy of a row in the upper executor context
Sinopse HeapTuple SPI_copytuple(HeapTuple row)
Descrição SPI_copytuple makes a copy of a row in the upper executor context.
Argumentos HeapTuple row
row to be copied
Valor retornado the copied row; NULL only if tuple is NULL
648
SPI_copytupledesc Nome SPI_copytupledesc — make a copy of a row descriptor in the upper executor context
Sinopse TupleDesc SPI_copytupledesc(TupleDesc tupdesc)
Descrição SPI_copytupledesc makes a copy of a row descriptor in the upper executor context.
Argumentos TupleDesc tupdesc
row descriptor to be copied
Valor retornado the copied row descriptor; NULL only if tupdesc is NULL
649
SPI_copytupleintoslot Nome SPI_copytupleintoslot — make a copy of a row and descriptor in the upper executor context
Sinopse TupleTableSlot * SPI_copytupleintoslot(HeapTuple row, TupleDesc rowdesc)
Descrição SPI_copytupleintoslot makes a copy of a row in the upper executor context, returning it in the form of a filled-in TupleTableSlot structure.
Argumentos HeapTuple row
row to be copied TupleDesc rowdesc
row descriptor to be copied
Valor retornado TupleTableSlot containing the copied row and descriptor; NULL only if row or rowdesc are NULL
650
SPI_modifytuple Nome SPI_modifytuple — create a row by replacing selected fields of a given row
Sinopse HeapTuple SPI_modifytuple(Relation rel, HeapTuple row, ncols, colnum, Datum * values, const char * nulls)
Descrição SPI_modifytuple creates a new row by substituting new values for selected columns, copying the original
row's columns at other positions. The input row is not modified.
Argumentos Relation rel
Used only as the source of the row descriptor for the row. (Passing a relation rather than a row descriptor is a misfeature.) HeapTuple row
row to be modified int ncols
number of column numbers in the array colnum int * colnum
array of the numbers of the columns that are to be changed (count starts at 1) Datum * values
new values for the specified columns const char * Nulls
which new values are null, if any (see SPI_execp for the format)
Valor retornado new row with modifications, allocated in the upper executor context; NULL only if row is NULL On error, SPI_result is set as follows: SPI_ERROR_ARGUMENT
if rel is NULL, or if row is NULL, or if ncols is less than or equal to 0, or if colnum is NULL, or if values is NULL. SPI_ERROR_NOATTRIBUTE
if colnum contains an invalid column number (less than or equal to 0 or greater than the number of column in row)
651
SPI_freetuple Nome SPI_freetuple — frees a row allocated in the upper executor context
Sinopse void SPI_freetuple(HeapTuple row)
Descrição SPI_freetuple frees a row previously allocated in the upper executor context.
This function is no longer different from plain heap_freetuple. It's kept just for backward compatibility of existing code.
Argumentos HeapTuple row
row to free
652
SPI_freetuptable Nome SPI_freetuptable — free a row set created by SPI_exec or a similar function
Sinopse void SPI_freetuptable(SPITupleTable * tuptable)
Descrição SPI_freetuptable frees a row set created by a prior SPI command execution function, such as SPI_exec. Therefore, this function is usually called with the global variable SPI_tupletable as argument.
This function is useful if a SPI procedure needs to execute multiple commands and does not want to keep the results of earlier commands around until it ends. Note that any unfreed row sets will be freed anyway at SPI_finish.
Argumentos SPITupleTable * tuptable
pointer to row set to free
653
SPI_freeplan Nome SPI_freeplan — free a previously saved plan
Sinopse int SPI_freeplan(void *plan)
Descrição SPI_freeplan releases a command execution plan previously returned by SPI_prepare or saved by SPI_saveplan.
Argumentos void * plan
pointer to plan to free
Valor retornado SPI_ERROR_ARGUMENT if plan is NULL.
41.4. Visibility of Data Changes The following two rules govern the visibility of data changes in functions that use SPI (or any other C function): •
During the execution of an SQL command, any data changes made by the command (or by function called by the command, including trigger functions) are invisible to the command. For example, in command INSERT INTO a SELECT * FROM a;
the inserted rows are invisible to the SELECT part. •
Changes made by a command C are visible to all commands that are started after C, no matter whether they are started inside C (during the execution of C) or after C is done.
The next section contains an example that illustrates the application of these rules.
41.5. Exemplos This section contains a very simple example of SPI usage. The procedure execq takes an SQL command as its first argument and a row count as its second, executes the command using SPI_exec and returns the number of rows that were processed by the command. You can find more complex examples for SPI in the source tree in src/test/regress/regress.c and in contrib/spi. #include "executor/spi.h" int execq(text *sql, int cnt); int execq(text *sql, int cnt) { char *command; int ret; int proc;
654
/* Convert given text object to a C string */ command = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(sql))); SPI_connect(); ret = SPI_exec(command, cnt); proc = SPI_processed; /* * If this is a SELECT and some rows were fetched, * then the rows are printed via elog(INFO). */ if (ret == SPI_OK_SELECT && SPI_processed > 0) { TupleDesc tupdesc = SPI_tuptable->tupdesc; SPITupleTable *tuptable = SPI_tuptable; char buf[8192]; int i, j; for (j = 0; j < proc; j++) { HeapTuple tuple = tuptable->vals[j]; for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++) snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s", SPI_getvalue(tuple, tupdesc, i), (i == tupdesc->natts) ? " " : " |"); elog (INFO, "EXECQ: %s", buf); } } SPI_finish(); pfree(command); return (proc); }
(This function uses call convention version 0, to make the example easier to understand. In real applications you should user the new version 1 interface.) This is how you declare the function after having compiled it into a shared library: CREATE FUNCTION execq(text, integer) RETURNS integer AS 'filename' LANGUAGE C;
Here is a sample session: => SELECT execq('CREATE TABLE a (x integer)', 0); execq ------0 (1 linha) => INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0)); INSERT 167631 1 => SELECT execq('SELECT * FROM a', 0); INFO: EXECQ: 0 -- inserted by execq INFO: EXECQ: 1 -- returned by execq and inserted by upper INSERT
655
execq ------2 (1 linha) => SELECT execq('INSERT INTO a SELECT x + 2 FROM a', 1); execq ------1 (1 linha) => SELECT execq('SELECT * FROM a', 10); INFO: EXECQ: 0 INFO: EXECQ: 1 INFO: EXECQ: 2 -- 0 + 2, only one row inserted - as specified execq ------3 (1 linha)
-- 10 is the max value only, 3 is the real number of rows
=> DELETE FROM a; DELETE 3 => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); INSERT 167712 1 => SELECT * FROM a; x --1 -- no rows in a (0) + 1 (1 linha) => INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); INFO: EXECQ: 0 INSERT 167713 1 => SELECT * FROM a; x --1 2 -- there was one row in a + 1 (2 linhas) -- This demonstrates the data changes visibility rule: => INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; INFO: EXECQ: 1 INFO: EXECQ: 2 INFO: EXECQ: 1 INFO: EXECQ: 2 INFO: EXECQ: 2 INSERT 0 2 => SELECT * FROM a; x --1 2 2 -- 2 rows * 1 (x in first row) 6 -- 3 rows (2 + 1 just inserted) * 2 (x in second row) (4 linhas) ^^^^^^ rows visible to execq() in different invocations
656
VI. Referência As entradas nesta Referência se propõem a fornecer, em um espaço razoável, um sumário confiável, completo e formal dos respectivos assuntos. Mais informações sobre a utilização do PostgreSQL sob forma narrativa, de tutorial, ou de exemplos, podem ser encontradas em outras partes desta documentação. Veja as referências cruzadas presentes em cada página de referência. As entradas de referência também estão disponíveis no formato tradicional “man pages” do Unix.
657
I. Comandos SQL Esta parte contém informação de referência para os comandos SQL suportados pelo PostgreSQL. Como “SQL” a linguagem é referida de forma geral; informações sobre a conformidade e compatibilidade de cada comando com relação ao padrão podem ser encontradas nas respectivas páginas de referência.
658
ABORT Nome ABORT — interrompe a transação corrente
Sinopse ABORT [ WORK | TRANSACTION ]
Descrição O comando ABORT desfaz a transação corrente, fazendo com que todas as modificações realizadas por esta transação sejam desconsideradas. Este comando possui comportamento idêntico ao do comando SQL padrão ROLLBACK, estando presente apenas por motivos históricos.
Parâmetros WORK TRANSACTION
Palavras chave opcionais. Não produzem nenhum efeito.
Observações Use o comando COMMIT para terminar uma transação bem-sucedida. A utilização do ABORT fora de uma transação não causa nenhum problema, mas causa uma mensagem de advertência.
Exemplos Para anular todas as modificações: ABORT;
Compatibilidade Este comando é uma extensão do PostgreSQL presente por motivos históricos. O ROLLBACK é o comando equivalente do padrão SQL.
Veja também BEGIN, COMMIT, ROLLBACK
659
ALTER AGGREGATE Nome ALTER AGGREGATE — altera a definição de uma função de agregação
Sinopse ALTER AGGREGATE nome ( tipo ) RENAME TO novo_nome
Descrição O comando ALTER AGGREGATE altera a definição de uma função de agregação. A única funcionalidade disponível atualmente é mudar o nome da função de agregação.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma função de agregação existente. tipo O tipo de dado do argumento da função de agregação, ou * se a função aceitar qualquer tipo de dado. novo_nome O novo nome da função de agregação.
Exemplo Para mudar o nome da função de agregação minhamedia para o tipo integer para minha_media: ALTER AGGREGATE minhamedia(integer) RENAME TO minha_media;
Compatibilidade Não existe o comando ALTER AGGREGATE no padrão SQL.
Veja também CREATE AGGREGATE, DROP AGGREGATE
660
ALTER CONVERSION Nome ALTER CONVERSION — altera a definição de uma conversão de codificação
Sinopse ALTER CONVERSION nome RENAME TO novo_nome
Descrição O comando ALTER CONVERSION altera a definição de uma conversão de codificação. A única funcionalidade disponível atualmente é mudar o nome de uma conversão.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma conversão existente. novo_nome O novo nome da conversão.
Exemplos Para mudar o nome da conversão de iso_8859_1_to_utf_8 para latin1_to_unicode: ALTER CONVERSION iso_8859_1_to_utf_8 RENAME TO latin1_to_unicode;
Compatibilidade Não existe o comando ALTER CONVERSION no padrão SQL.
Veja também CREATE CONVERSION, DROP CONVERSION
661
ALTER DATABASE Nome ALTER DATABASE — altera um banco de dados
Sinopse ALTER DATABASE nome SET parâmetro { TO | = } { valor | DEFAULT } ALTER DATABASE nome RESET parâmetro ALTER DATABASE nome RENAME TO novo_nome
Descrição O comando ALTER DATABASE modifica os atributos de um banco de dados. As duas primeiras formas mudam o valor padrão para a sessão de uma variável de configuração em tempo de execução, para um banco de dados do PostgreSQL. Depois, sempre que uma nova sessão for iniciada neste banco de dados, o valor especificado se torna o valor padrão para a sessão. O padrão específico para o banco de dados substitui qualquer definição presente no arquivo postgresql.conf, ou que tenha sido recebida a partir da linha de comando do postmaster. Somente o dono do banco de dados ou um superusuário podem mudar os padrões para a sessão de um banco de dados. A terceira forma muda o nome do banco de dados. Somente o dono do banco de dados pode mudar o nome do banco de dados, e somente se possuir o privilégio CREATEDB. O banco de dados corrente não pode ter seu nome mudado (Deve-se conectar a um banco de dados diferente se for necessário realizar esta operação).
Parâmetros nome O nome do banco de dados cujo padrão de sessão está sendo alterado. parâmetro valor Define o padrão de sessão deste banco de dados, para o parâmetro de configuração especificado, como o valor fornecido. Se valor for DEFAULT ou, de forma equivalente, se RESET for utilizado, a definição específica para o banco de dados é removida, e a definição padrão global do sistema passa a ser herdada nas novas sessões. Deve ser utilizado RESET ALL para remover todas as definições específicas do banco de dados. Veja SET e a Seção 16.4 para obter mais informações sobre os nomes e valores permitidos para os parâmetros. novo_nome O novo nome do banco de dados.
Observações Utilizando o comando ALTER USER é possível associar um padrão de sessão a um usuário específico, em vez de associar a um banco de dados. As definições específicas para o usuário substituem as definições específicas para o banco de dados, no caso de haver conflito.
Exemplos Para desabilitar a varredura de índices no banco de dados teste por padrão: ALTER DATABASE teste SET enable_indexscan TO off;
662
Compatibilidade O comando ALTER DATABASE é uma extensão do PostgreSQL.
Veja também ALTER USER, CREATE DATABASE, DROP DATABASE, SET
663
ALTER DOMAIN Nome ALTER DOMAIN — altera a definição de um domínio
Sinopse ALTER DOMAIN nome { SET DEFAULT expressão | DROP DEFAULT } ALTER DOMAIN nome { SET | DROP } NOT NULL ALTER DOMAIN nome ADD restrição_de_domínio ALTER DOMAIN nome DROP CONSTRAINT nome_da_restrição [ RESTRICT | CASCADE ] ALTER DOMAIN nome OWNER TO novo_dono
Descrição O comando ALTER DOMAIN altera a definição de um domínio existente. Existem várias subformas: SET/DROP DEFAULT Estas formas definem ou removem o valor padrão do domínio. Deve ser observado que estes padrões somente se aplicam aos comandos INSERT subseqüentes; não são afetadas as linhas já existentes nas tabelas que utilizam o domínio. SET/DROP NOT NULL Estas formas modificam se o domínio está marcado para permitir valores nulos ou para rejeitar valores nulos. O comando SET NOT NULL pode ser utilizado somente quando as colunas que utilizam o domínio não contêm valores nulos. ADD restrição_de_domínio Esta forma adiciona uma nova restrição ao domínio, utilizando a mesma sintaxe de CREATE DOMAIN. Somente será bem-sucedida se todas as colunas que utilizam o domínio satisfizerem a nova restrição. DROP CONSTRAINT Esta forma remove restrições no domínio. OWNER Esta forma torna o usuário especificado o dono do domínio. É necessário ser o dono do domínio para utilizar ALTER DOMAIN; exceto ALTER DOMAIN OWNER, que só pode ser executado por um superusuário.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) do domínio existente a ser alterado. restrição_de_domínio Nova restrição de domínio para o domínio. nome_da_restrição Nome da restrição existente a ser removida.
664
CASCADE Remove, automaticamente, os objetos que dependem da restrição. RESTRICT Recusa excluir a restrição se houver objetos dependentes. Este é o comportamento padrão. novo_dono O nome de usuário do novo dono do domínio.
Exemplos Para adicionar a restrição NOT NULL ao domínio: ALTER DOMAIN cep SET NOT NULL;
Para remover a restrição NOT NULL do domínio: ALTER DOMAIN cep DROP NOT NULL;
Para adicionar uma restrição de verificação ao domínio: ALTER DOMAIN cep ADD CONSTRAINT chk_cep CHECK (char_length(VALUE) = 8);
Para remover uma restrição de verificação do domínio: ALTER DOMAIN cep DROP CONSTRAINT chk_cep;
Compatibilidade O comando ALTER DOMAIN é compatível com o SQL:1999, exceto pela variante OWNER, que é uma extensão do PostgreSQL.
665
ALTER FUNCTION Nome ALTER FUNCTION — altera a definição de uma função
Sinopse ALTER FUNCTION nome ( [ tipo [, ...] ] ) RENAME TO novo_nome
Descrição O comando ALTER FUNCTION altera a definição de uma função. A única funcionalidade disponível atualmente é mudar o nome da função.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma função existente. tipo O tipo de dado do argumento da função. novo_nome O novo nome da função.
Exemplo Para mudar o nome da função sqrt para o tipo integer para raiz_quadrada: ALTER FUNCTION sqrt(integer) RENAME TO raiz_quadrada;
Compatibilidade Existe o comando ALTER FUNCTION no padrão SQL, mas não possui a opção de mudar o nome da função.
Veja também CREATE FUNCTION, DROP FUNCTION
666
ALTER GROUP Nome ALTER GROUP — altera um grupo de usuários
Sinopse ALTER GROUP nome_do_grupo ADD USER nome_do_usuário [, ... ] ALTER GROUP nome_do_grupo DROP USER nome_do_usuário [, ... ] ALTER GROUP nome_do_grupo RENAME TO novo_nome
Descrição O comando ALTER GROUP é utilizado para alterar um grupo de usuários. As duas primeiras formas adicionam ou removem usuários de um grupo. Somente os superusuários do banco de dados podem utilizar este comando. Adicionar um usuário a um grupo não cria o usuário. Da mesma maneira, remover o usuário de um grupo não remove o usuário do banco de dados. A terceira forma muda o nome do grupo. Somente um superusuário do banco de dados pode mudar o nome de um grupo.
Parâmetros nome_do_grupo O nome do grupo a ser modificado. nome_do_usuário Os usuários a serem adicionados ou removidos do grupo. Os usuários devem existir. novo_nome O novo nome do grupo.
Exemplos Adicionar usuários a um grupo: ALTER GROUP arquitetura ADD USER joana, alberto;
Remover um usuário de um grupo: ALTER GROUP engenharia DROP USER margarida;
Compatibilidade Não existe o comando ALTER GROUP no padrão SQL. O conceito de “roles” é semelhante ao de grupos.
Veja também CREATE GROUP, DROP GROUP
667
ALTER LANGUAGE Nome ALTER LANGUAGE — altera a definição de uma linguagem procedural
Sinopse ALTER LANGUAGE nome RENAME TO novo_nome
Descrição O comando ALTER LANGUAGE altera a definição de uma linguagem. A única funcionalidade é mudar o nome da linguagem. Somente um superusuário pode mudar o nome de uma linguagem.
Parâmetros nome O nome da linguagem novo_nome O novo nome da linguagem
Compatibilidade Não existe o comando ALTER LANGUAGE no padrão SQL.
Veja também CREATE LANGUAGE, DROP LANGUAGE
668
ALTER OPERATOR CLASS Nome ALTER OPERATOR CLASS — altera a definição de uma classe de operadores
Sinopse ALTER OPERATOR CLASS nome USING método_de_índice RENAME TO novo_nome
Descrição O comando ALTER OPERATOR CLASS altera a definição de uma classe de operadores. A única funcionalidade é mudar o nome da classe de operadores.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma classe de operadores existente. método_de_índice O nome do método de índice para o qual esta classe de operadores se destina. novo_nome O novo nome da classe de operadores.
Compatibilidade Não existe o comando ALTER OPERATOR CLASS no padrão SQL.
Veja também CREATE OPERATOR CLASS, DROP OPERATOR CLASS
669
ALTER SCHEMA Nome ALTER SCHEMA — altera a definição de um esquema
Sinopse ALTER SCHEMA nome RENAME TO novo_nome
Descrição O comando ALTER SCHEMA altera a definição de um esquema. A única funcionalidade é mudar o nome do esquema. Para mudar o nome do esquema é necessário ser o dono do esquema e possuir o privilégio CREATE para o banco de dados.
Parâmetros nome O nome do esquema novo_nome O novo nome do esquema
Compatibilidade Não existe o comando ALTER SCHEMA no padrão SQL.
Veja também CREATE SCHEMA, DROP SCHEMA
670
ALTER SEQUENCE Nome ALTER SEQUENCE — altera a definição de um gerador de seqüência
Sinopse ALTER [ [ [
SEQUENCE nome [ INCREMENT [ BY ] incremento ] MINVALUE valor_mínimo | NO MINVALUE ] MAXVALUE valor_máximo | NO MAXVALUE ] RESTART [ WITH ] início ] [ CACHE cache ] [ [ NO ] CYCLE ]
Descrição O comando ALTER SEQUENCE altera os parâmetros de um gerador de seqüência existente. Todos os parâmetros que não são explicitamente definidos no comando ALTER SEQUENCE mantêm suas definições anteriores.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da seqüência a ser alterada. incremento A cláusula INCREMENT BY incremento é opcional. Um valor positivo produz uma seqüência ascendente, enquanto um valor negativo produz uma seqüência descendente. Se não for especificado, o valor anterior do incremento será mantido. valor_mínimo NO MINVALUE
A cláusula opcional MINVALUE valor_mínimo especifica o valor mínimo para a seqüência. Se for especificado NO MINVALUE, serão utilizados os valores padrão 1 e -263-1 para seqüências ascendentes e descendentes, respectivamente. Se nenhuma das duas opções for especificada, o valor mínimo corrente será mantido. valor_máximo NO MAXVALUE
A cláusula opcional MAXVALUE valor_máximo especifica o valor máximo para a seqüência. Se for especificado NO MAXVALUE, serão utilizados valores padrão 263-1 e -1, para seqüências ascendentes e descendentes, respectivamente. Se nenhuma das duas opções for especificada, o valor máximo corrente será mantido. início A cláusula opcional RESTART WITH início muda o valor corrente da seqüência. cache A cláusula CACHE cache permite que números da seqüência sejam pré-alocados e armazenados em memória para obter um acesso mais rápido. O valor mínimo é 1 (somente um valor pode ser gerado de cada vez, ou seja, sem cache). Se não for especificado, o valor anterior de cache será mantido. CYCLE A palavra chave opcional CYCLE pode ser utilizada para permitir uma seqüência ascendente ou descendente reiniciar quando atingir o valor_máximo ou o valor_mínimo, respectivamente. Se o limite for atingido, o próximo número gerado será valor_mínimo ou valor_máximo, respectivamente.
671
NO CYCLE Se a palavra chave opcional NO CYCLE for especificada, todas as chamadas a nextval após a seqüência ter atingido seu valor máximo retornam um erro. Se nem CYCLE nem NO CYCLE for especificado, o comportamento anterior para ciclo será mantido.
Exemplos Reiniciar uma seqüência chamada serial, em 105: ALTER SEQUENCE serial RESTART WITH 105;
Observações Para evitar o bloqueio de transações concorrentes que obtêm números a partir de uma mesma seqüência, o comando ALTER SEQUENCE nunca é desfeito (rollback); as mudanças entram em vigor imediatamente, não sendo reversíveis. O comando ALTER SEQUENCE não afeta imediatamente os resultados de nextval nos processos servidor que pré-alocaram (cached) valores da seqüência, a não ser no processo servidor corrente. Os demais processos servidor utilizarão todos os valores pré-alocados antes de observar a mudança dos parâmetros da seqüência. O processo servidor corrente é afetado imediatamente.
Compatibilidade SQL99 O comando ALTER SEQUENCE é uma extensão do PostgreSQL à linguagem SQL. Não existe o comando ALTER SEQUENCE no SQL99.
672
ALTER TABLE Nome ALTER TABLE — altera a definição de uma tabela
Sinopse ALTER TABLE [ ONLY ] nome [ * ] ADD [ COLUMN ] coluna tipo [ restrição_de_coluna [ ... ALTER TABLE [ ONLY ] nome [ * ] DROP [ COLUMN ] coluna [ RESTRICT | CASCADE ] ALTER TABLE [ ONLY ] nome [ * ] ALTER [ COLUMN ] coluna { SET DEFAULT expressão | DROP ALTER TABLE [ ONLY ] nome [ * ] ALTER [ COLUMN ] coluna { SET | DROP } NOT NULL ALTER TABLE [ ONLY ] nome [ * ] ALTER [ COLUMN ] coluna SET STATISTICS inteiro ALTER TABLE [ ONLY ] nome [ * ] ALTER [ COLUMN ] coluna SET STORAGE { PLAIN | EXTERNAL ALTER TABLE [ ONLY ] nome [ * ] SET WITHOUT OIDS ALTER TABLE [ ONLY ] nome [ * ] RENAME [ COLUMN ] coluna TO novo_nome_da_coluna ALTER TABLE nome RENAME TO novo_nome_da_tabela ALTER TABLE [ ONLY ] nome [ * ] ADD restrição_de_tabela ALTER TABLE [ ONLY ] nome [ * ] DROP CONSTRAINT nome_da_restrição [ RESTRICT | CASCADE ALTER TABLE nome OWNER TO novo_dono ALTER TABLE nome CLUSTER ON nome_do_índice
] ]
DEFAULT }
| EXTENDED | MAIN }
]
Descrição O comando ALTER TABLE altera a definição de uma tabela existente. Existem várias sub-formas: ADD COLUMN
Esta forma adiciona uma nova coluna à tabela utilizando a mesma sintaxe do comando CREATE TABLE. DROP COLUMN
Esta forma remove uma coluna da tabela. Os índices e as restrições da tabela que envolvem a coluna também são automaticamente removidos. É necessário especificar CASCADE se algum objeto fora da tabela depender da coluna como, por exemplo, referências de chaves estrangeiras ou visões. SET/DROP DEFAULT
Estas formas definem ou removem o valor padrão para a coluna. O valor padrão somente é aplicado aos comandos INSERT subseqüentes; não modifica as linhas existentes na tabela. Valores padrão também podem ser criados para visões e, neste caso, são inseridos dentro do comando INSERT na visão, antes da regra ON INSERT da visão ser aplicada. SET/DROP NOT NULL
Estas formas alteram se a coluna está marcada para permitir valores nulos ou para rejeitar valores nulos. A forma SET NOT NULL só pode ser utilizada quando não existem valores nulos na coluna.
673
SET STATISTICS
Esta forma define a quantidade de informações armazenadas na coleta de estatísticas por coluna para as operações subseqüentes de ANALYZE. A quantidade pode ser definida no intervalo de 0 a 1000; como alternativa, pode ser definida como -1 para utilizar a quantidade de estatísticas padrão do sistema. SET STORAGE
Esta forma define o modo de armazenamento da coluna. Controla se a coluna é mantida na mesma tabela ou em uma tabela suplementar, e se os dados devem ser comprimidos ou não. Deve ser utilizado PLAIN para valores de comprimento fixo, como integer, e fica na mesma tabela não comprimido. MAIN é utilizado para dados que ficam na mesma tabela e são compressíveis. EXTERNAL é utilizado para dados externos não comprimidos, e EXTENDED é utilizado para dados externos comprimidos. EXTENDED é o padrão para a maioria dos tipos de dado que suportam armazenamento não-PLAIN. A utilização de EXTERNAL torna as operações de substring em colunas text e bytea mais rápidas, às custas de um aumento no espaço para armazenamento. SET WITHOUT OIDS
Esta forma remove da tabela a coluna de sistema oid. A remoção dos OIDs da tabela não ocorre imediatamente. O espaço ocupado pelo OID é recuperado quando a linha é atualizada. Se a linha não for atualizada, tanto o espaço quanto o valor do OID são mantidos indefinidamente. A semântica é semelhante à do processo DROP COLUMN. RENAME
A forma RENAME muda o nome de uma tabela (de um índice, de uma seqüência ou de uma visão), ou o nome de uma coluna da tabela. Não produz efeito sobre os dados armazenados. ADD restrição_de_tabela
Esta forma adiciona uma nova restrição à tabela utilizando a mesma sintaxe do comando CREATE TABLE. DROP CONSTRAINT
Esta forma remove restrições de tabela. Atualmente, as restrições de tabela não necessitam ter nomes únicos e, portanto, pode haver mais de uma restrição correspondendo ao nome especificado. Todas as restrições correspondentes são removidas. OWNER
Esta forma torna o usuário especificado o dono da tabela, índice, seqüência ou visão. CLUSTER
Esta forma marca a tabela para operações futuras de CLUSTER. É necessário ser o dono da tabela para utilizar o comando ALTER TABLE; exceto ALTER TABLE OWNER, que só pode ser executado por um superusuário.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da tabela existente a ser alterada. Se ONLY for especificado, somente esta tabela será alterada. Se ONLY não for especificado, a tabela e todas as suas tabelas descendentes (se existirem) são alteradas. O * pode ser adicionado ao nome da tabela para indicar que as tabelas descendentes devem ser alteradas, mas na versão atual este é comportamento padrão (Nas versões anteriores a 7.1 ONLY era o comportamento padrão. O padrão pode ser alterado mudando o parâmetro de configuração sql_inheritance). coluna O nome de uma coluna nova ou existente. tipo O tipo de dado da nova coluna.
674
novo_nome_da_coluna Novo nome para uma coluna existente. novo_nome_da_tabela O novo nome da tabela. restrição_de_tabela Nova restrição de tabela (table constraint) para a tabela. nome_da_restrição O nome da restrição existente a ser removida. novo_dono O nome de usuário do novo dono da tabela. nome_do_índice O nome do índice pelo qual a tabela deve ser marcada para agrupamento (clustering). CASCADE
Remove, automaticamente, os objetos que dependem da coluna ou da restrição removida (por exemplo, visões fazendo referência à coluna). RESTRICT
Recusa remover a coluna ou a restrição se existirem objetos dependentes. Este é o comportamento padrão.
Observações A palavra chave COLUMN é apenas informativa, podendo ser omitida. Na atual implementação de ADD COLUMN, as cláusulas valor padrão e NOT NULL não são permitidas para a nova coluna. A nova coluna é sempre criada com todos os valores nulos. Pode ser usada a forma SET DEFAULT do comando ALTER TABLE para definir o valor padrão mais tarde (Os valores atuais das linhas existentes poderão ser atualizados, posteriormente, para o novo valor padrão usando o comando UPDATE). Se for desejado marcar a coluna como não aceitando valores nulos, deve ser utilizada a forma SET NOT NULL após ter entrado com valores não nulos para a coluna em todas as linhas. A forma DROP COLUMN não remove fisicamente a coluna, simplesmente torna a coluna invisível para as operações SQL. As operações subseqüentes de inclusão e de atualização na tabela armazenam o valor nulo na coluna. Portanto, remover uma coluna é rápido mas não reduz imediatamente o espaço em disco da tabela, porque o espaço ocupado pela coluna removida não é recuperado. O espaço é recuperado ao longo do tempo à medida que as linhas existentes são atualizadas. Para recuperar todo o espaço de uma vez deve ser feita uma atualização fictícia de todas as linhas e, depois, executado o comando VACUUM, como em: UPDATE tabela SET coluna = coluna; VACUUM FULL tabela;
Se a tabela possuir tabelas descendentes, não é permitido adicionar ou mudar o nome da coluna na tabela ancestral sem fazer o mesmo nas tabelas descendentes, ou seja, o ALTER TABLE ONLY é rejeitado. Isto garante que as tabelas descendentes sempre possuem colunas correspondendo às da tabela ancestral. A operação DROP COLUMN recursiva remove a coluna de uma tabela descendente somente se a tabela descendente não herdar esta coluna de outros ancestrais, e se nunca teve definição independente para a coluna. A operação DROP COLUMN não recursiva (ou seja, ALTER TABLE ONLY ... DROP COLUMN) nunca remove qualquer coluna descendente e, em vez disto, marca estas colunas como definidas independentemente em vez de herdadas. Mudar qualquer parte de uma tabela do catálogo do sistema não é permitido. Consulte o comando CREATE TABLE para obter uma descrição mais completa dos parâmetros válidos. O Capítulo 5 contém mais informações sobre herança.
675
Exemplos Para adicionar uma coluna do tipo varchar a uma tabela: ALTER TABLE distribuidores ADD COLUMN endereco varchar(30);
Para excluir uma coluna da tabela: ALTER TABLE distribuidores DROP COLUMN endereco RESTRICT;
Para mudar o nome de uma coluna existente: ALTER TABLE distribuidores RENAME COLUMN endereco TO cidade;
Para mudar o nome de uma tabela existente: ALTER TABLE distribuidores RENAME TO fornecedores;
Para adicionar uma restrição de não nulo a uma coluna: ALTER TABLE distribuidores ALTER COLUMN logradouro SET NOT NULL;
Para remover a restrição de não nulo da coluna: ALTER TABLE distribuidores ALTER COLUMN logradouro DROP NOT NULL;
Para adicionar uma restrição de verificação a uma tabela: ALTER TABLE distribuidores ADD CONSTRAINT chk_cep CHECK (char_length(cod_cep) = 8);
Para remover uma restrição de verificação de uma tabela e de todas as suas descendentes: ALTER TABLE distribuidores DROP CONSTRAINT chk_cep;
Para adicionar uma restrição de chave estrangeira a uma tabela: ALTER TABLE distribuidores ADD CONSTRAINT fk_dist FOREIGN KEY (endereco) REFERENCES enderecos (endereco) MATCH FULL;
Para adicionar uma restrição de unicidade (multicoluna) à tabela: ALTER TABLE distribuidores ADD CONSTRAINT unq_id_dist_cod_cep UNIQUE (id_dist, cod_cep);
Para adicionar uma restrição de chave primária a uma tabela com o nome gerado automaticamente, levando em conta que a tabela pode possuir somente uma única chave primária: ALTER TABLE distribuidores ADD PRIMARY KEY (id_dist);
Compatibilidade A forma ADD COLUMN está em conformidade com o padrão SQL, a não ser por não suportar as opções de valor padrão e de não nulo, conforme explicado anteriormente. A forma ALTER COLUMN está em conformidade total. As cláusulas para mudar os nomes das tabelas, colunas, índices, visões e seqüências são extensões do PostgreSQL ao padrão SQL. O comando ALTER TABLE DROP COLUMN pode ser utilizado para remover a única coluna da tabela, produzindo uma tabela com zero coluna. Esta é uma extensão ao SQL, que não permite tabelas sem nenhuma coluna.
676
ALTER TRIGGER Nome ALTER TRIGGER — altera a definição de um gatilho
Sinopse ALTER TRIGGER nome ON tabela RENAME TO novo_nome
Descrição O comando ALTER TRIGGER altera as propriedades de um gatilho existente. A cláusula RENAME muda o nome de um determinado gatilho sem mudar a definição do gatilho. É necessário ser o dono da tabela onde o gatilho atua para poder mudar suas propriedades.
Parâmetros nome O nome do gatilho existente a ser alterado. tabela O nome da tabela onde o gatilho atua. novo_nome O novo nome do gatilho.
Exemplo Para mudar o nome de um gatilho existente: ALTER TRIGGER emp_alt ON tbl_empregados RENAME TO trg_altera_empregado;
Compatibilidade O comando ALTER TRIGGER é uma extensão do PostgreSQL ao padrão SQL.
677
ALTER USER Nome ALTER USER — altera uma conta de usuário do banco de dados
Sinopse ALTER USER nome [ [ WITH ] opção [ ... ] ] onde opção pode ser: [ | | |
ENCRYPTED | UNENCRYPTED ] PASSWORD 'senha' CREATEDB | NOCREATEDB CREATEUSER | NOCREATEUSER VALID UNTIL 'data_hora'
ALTER USER nome RENAME TO novo_nome ALTER USER nome SET parâmetro { TO | = } { valor | DEFAULT } ALTER USER nome RESET parâmetro
Descrição O comando ALTER USER altera os atributos de uma conta de usuário do PostgreSQL. Os atributos não mencionados no comando permanecem com suas definições anteriores. A primeira forma deste comando mostrada na sinopse muda alguns privilégios globais do usuário e definições de autenticação (Veja abaixo para obter detalhes). Somente um superusuário do banco de dados pode alterar os privilégios e a expiração da senha com este comando. Os usuários comuns podem alterar apenas suas próprias senhas. A segunda forma muda o nome do usuário. Somente um superusuário do banco de dados pode mudar nome de conta de usuário. O usuário da sessão não pode ter o nome mudado (Deve-se conectar como um usuário diferente se for necessário fazê-lo). A terceira e a quarta variantes mudam, para uma determinada variável de configuração, o valor padrão da sessão do usuário. Após isto, sempre que o usuário iniciar uma nova sessão o valor especificado se tornará o padrão da sessão, substituindo qualquer configuração presente em postgresql.conf, ou que tenha sido recebida através da linha de comando do postmaster. Os usuários comuns podem mudar seus próprios padrões de sessão. Os superusuários podem mudar os padrões de sessão de qualquer usuário. Certas variáveis não podem ser definidas desta maneira, ou só podem ser definidas por um superusuário.
Parâmetros nome O nome de usuário cujos atributos estão sendo alterados. senha A nova senha a ser utilizada para esta conta. ENCRYPTED UNENCRYPTED
Estas palavras chave controlam se a senha é armazenada criptografada, ou não, em pg_shadow (Consulte o comando CREATE USER para obter mais informações sobre esta opção).
678
CREATEDB NOCREATEDB
Estas cláusulas definem a permissão para o usuário criar banco de dados. Se CREATEDB for especificado, o usuário terá permissão para criar seus próprios bancos de dados. Especificando NOCREATEDB nega-se ao usuário a permissão para criar banco de dados. CREATEUSER NOCREATEUSER
Estas cláusulas determinam se o usuário terá permissão para criar novos usuários. CREATEUSER torna o usuário um superusuário, não Estas cláusulas determinam se o usuário terá permissão para criar novos usuários. CREATEUSER torna o usuário um superusuário, não está sujeito a restrições de acesso. sujeito a restrições de acesso. data_hora A data (e, opcionalmente, a hora) de expiração da senha do usuário. Para fazer com que a senha nunca expire deve ser utilizado 'infinity'. novo_nome O novo nome de usuário. parâmetro valor Define o valor fornecido como sendo o valor padrão para o parâmetro de configuração especificado. Se valor for DEFAULT ou, de forma equivalente, se RESET for utilizado, a definição da variável específica para o usuário é removida, e o valor padrão global do sistema será herdado nas novas sessões do usuário. Use RESET ALL para remover todas as definições específicas do usuário. Consulte o comando SET e o Seção 16.4 para obter mais informações sobre os nomes e valores permitidos para os parâmetros.
Observações Use o comando CREATE USER para criar novos usuários, e o comando DROP USER para remover um usuário. O comando ALTER USER não pode mudar a participação do usuário nos grupos. Use o comando ALTER GROUP para realizar esta operação. Utilizando o comando ALTER DATABASE é possível associar a um banco de dados específico, em vez de associar a um usuário, o valor padrão para a sessão.
Exemplos Mudar a senha do usuário: ALTER USER marcos WITH PASSWORD 'hu8jmn3';
Mudar a data de expiração da senha do usuário: ALTER USER manuel VALID UNTIL 'Jan 31 2030';
Mudar a data de expiração da senha, especificando que a senha expira ao meio dia de 4 de maio de 2005, usando uma zona horária uma hora adiante da UTC: ALTER USER chris VALID UNTIL 'May 4 12:00:00 2005 +1';
Tornar o usuário válido para sempre: ALTER USER fred VALID UNTIL 'infinity';
Dar ao usuário permissão para criar outros usuários e novos bancos de dados: ALTER USER marcela CREATEUSER CREATEDB;
679
Compatibilidade O comando ALTER USER é uma extensão do PostgreSQL. O padrão SQL deixa a definição dos usuários para a implementação.
Veja também CREATE USER, DROP USER, SET
680
ANALYZE Nome ANALYZE — coleta estatísticas sobre o banco de dados
Sinopse ANALYZE [ VERBOSE ] [ tabela [ (coluna [, ...] ) ] ]
Descrição O comando ANALYZE coleta estatísticas sobre o conteúdo das tabelas do banco de dados, e armazena os resultados na tabela do sistema pg_statistic. Posteriormente, o planejador de comandos utiliza estas estatísticas para ajudar a determinar o plano de execução mais eficiente para os comandos. Sem nenhum parâmetro, o comando ANALYZE analisa todas as tabelas do banco de dados corrente. Com um parâmetro, o comando ANALYZE analisa somente esta tabela. É possível, também, fornecer uma lista de nomes de colunas e, neste caso, somente são coletadas estatísticas para estas colunas.
Parâmetros VERBOSE
Habilita a exibição das mensagens de progresso. tabela O nome (possivelmente qualificado pelo esquema) da tabela a ser analisada. O padrão é analisar todas as tabelas do banco de dados corrente. coluna O nome de uma determinada coluna a ser analisada. O padrão é analisar todas as colunas.
Saída Quando VERBOSE é especificado, o comando ANALYZE emite mensagens de progresso indicando qual tabela está sendo processada no momento. Várias estatísticas sobre as tabelas também são mostradas.
Observações Aconselha-se executar o comando ANALYZE periodicamente, ou logo após realizar uma alteração importante no conteúdo de uma tabela. Estatísticas precisas auxiliam o planejador na escolha do plano de comando mais apropriado e, portanto, melhoram o tempo do processamento do comando. Uma estratégia habitual é executar VACUUM e ANALYZE uma vez por dia em hora de pouca utilização. Ao contrário do comando VACUUM FULL, o comando ANALYZE requer somente um bloqueio de leitura na tabela podendo, portanto, ser executado em conjunto com outras atividades na tabela. As estatísticas coletadas pelo comando ANALYZE geralmente incluem a lista dos valores mais comuns de cada coluna, e um histograma mostrando a distribuição aproximada dos dados em cada coluna. Estas informações podem ser omitidas se o comando ANALYZE considerá-las sem importância (por exemplo, em uma coluna de chave única não existem valores repetidos), ou se o tipo de dado da coluna não suportar os operadores apropriados. Existem mais informações sobre estatísticas no Capítulo 21. Para tabelas grandes, o comando ANALYZE pega amostras aleatórias do conteúdo da tabela, em vez de examinar todas as linhas. Esta estratégia permite que mesmo tabelas muito grandes sejam analisadas em curto espaço de tempo. Entretanto, deve ser observado que as estatísticas são apenas aproximadas, e mudam um pouco cada vez que o comando ANALYZE é executado, mesmo que o conteúdo da tabela não se altere, podendo provocar pequenas mudanças no custo estimado pelo planejador mostrado pelo comando EXPLAIN. Em situações raras, este não determinismo faz o otimizador de consultas escolher planos diferentes entre execuções
681
do comando ANALYZE. Para evitar esta situação, a quantidade de estatísticas coletada pelo comando ANALYZE deve ser aumentada, conforme descrito abaixo. A extensão da análise pode ser controlada ajustando o valor da variável de configuração DEFAULT_STATISTICS_TARGET, ou coluna por coluna definindo a quantidade de estatísticas por coluna através do comando ALTER TABLE ALTER COLUMN SET STATISTICS (consulte o comando ALTER
TABLE). O valor especificado define o número máximo de entradas presentes na lista de valores com maior incidência, e o número máximo de barras no histograma. O valor padrão é 10, mas pode ser ajustado para mais, ou para menos, para balancear a precisão das estimativas do planejador contra o tempo gasto para executar o comando ANALYZE e a quantidade de espaço ocupado pela tabela pg_statistic. Em particular, especificar o valor zero desabilita a coleta de estatísticas para a coluna, podendo ser útil em colunas que nunca são usadas como parte das cláusulas WHERE, GROUP BY ou ORDER BY nos comandos, porque as estatísticas para estas colunas nunca são utilizadas pelo planejador. A quantidade máxima de estatísticas entre as colunas sendo analisadas determina o número de linhas amostradas para preparar as estatísticas. Aumentando a quantidade aumenta proporcionalmente o tempo e espaço necessários para executar o comando ANALYZE.
Compatibilidade Não existe o comando ANALYZE no padrão SQL.
682
BEGIN Nome BEGIN — inicia um bloco de transação
Sinopse BEGIN [ WORK | TRANSACTION ]
Descrição O comando BEGIN inicia um bloco de transação, ou seja, todos os comandos após o BEGIN são executados em uma única transação, até ser encontrado um COMMIT ou ROLLBACK explícito. Por padrão (sem o BEGIN), o PostgreSQL executa as transações no modo de auto-efetivação (autocommit), ou seja, cada comando é executado em sua própria transação e uma efetivação (commit) é realizada implicitamente no fim do comando, se a execução for bem-sucedida, senão a transação é desfeita (rollback). Os comandos são executados mais rapidamente em um bloco de transação, porque cada início/efetivação de transação requer uma atividade significativa de CPU e de disco. A execução de vários comandos dentro de uma transação também é útil para garantir a consistência ao se fazer várias modificações relacionadas: as outras sessões não conseguem ver os estados intermediários até que todas as modificações relacionadas tenham sido sido feitas.
Parâmetros WORK TRANSACTION
Palavras chave opcionais. Não produzem nenhum efeito.
Observações START TRANSACTION possui a mesma funcionalidade do BEGIN. Utilize COMMIT ou ROLLBACK para terminar um bloco de transação. Executar o BEGIN dentro de um bloco de transação provoca uma mensagem de advertência. O estado da transação não é afetado.
Exemplos Para iniciar um bloco de transação: BEGIN;
Compatibilidade O comando BEGIN é uma extensão do PostgreSQL à linguagem. Não existe o comando BEGIN explícito no padrão SQL; o início da transação é sempre implícito, terminando por um comando COMMIT ou ROLLBACK. Outros sistemas de banco de dados relacionais podem oferecem a funcionalidade de auto-efetivação (autocommit) como uma conveniência. Por coincidência, a palavra chave BEGIN é utilizada com uma finalidade diferente na linguagem SQL incorporada. Deve ser tomado muito cuidado com relação à semântica da transação ao migrar aplicações de banco de dados.
683
Veja também COMMIT, ROLLBACK
684
CHECKPOINT Nome CHECKPOINT — força um ponto de controle no log de transação
Sinopse CHECKPOINT
Descrição A escrita prévia no log (Write-Ahead Logging/WAL) coloca, periodicamente, um ponto de controle (checkpoint) no log de transação (Para ajustar o intervalo do ponto de controle automático veja as opções de configuração em tempo de execução checkpoint_segments e checkpoint_timeout). Ao ser executado, o comando CHECKPOINT força um ponto de controle imediato, sem aguardar o ponto de controle agendado. Um ponto de controle é um ponto na seqüência do log de transação onde todos os arquivos de dados foram atualizados para refletir a informação no log. Todos os dados são descarregados (flushed) no disco. Consulte o Capítulo 25 para obter mais informações sobre o sistema WAL. Somente os superusuários podem executar o comando CHECKPOINT. Este comando não foi feito para ser utilizado durante a operação normal.
Compatibilidade O comando CHECKPOINT é uma extensão do PostgreSQL à linguagem.
685
CLOSE Nome CLOSE — fecha o cursor
Sinopse CLOSE nome
Descrição O comando CLOSE libera os recursos associados a um cursor aberto. Após o cursor ser fechado, não é permitida nenhuma operação posterior que o utilize. O cursor deve ser fechado quando não for mais necessário. Todo cursor aberto sem a cláusula HOLD é fechado implicitamente quando a transação termina por um COMMIT ou ROLLBACK. O cursor aberto com a cláusula HOLD é fechado implicitamente quando a transação em que foi criado é interrompida através de ROLLBACK. Se a transação que o criou for efetivada com sucesso, o cursor aberto com a cláusula HOLD permanece aberto até o CLOSE explícito ser executado, ou o cliente desconectar.
Parâmetros nome O nome do cursor aberto a ser fechado.
Observações O PostgreSQL não possui um comando OPEN cursor explícito; o cursor é considerado aberto ao ser declarado. Use o comando DECLARE para declarar o cursor.
Exemplos Fechar o cursor cur_emp: CLOSE cur_emp;
Compatibilidade O comando CLOSE está em conformidade total com o padrão SQL.
686
CLUSTER Nome CLUSTER — agrupa a tabela de acordo com um índice
Sinopse CLUSTER nome_do_índice ON nome_da_tabela CLUSTER nome_da_tabela CLUSTER
Descrição O comando CLUSTER instrui o PostgreSQL para agrupar a tabela especificada por nome_da_tabela, com base no índice especificado por nome_do_índice. O índice deve ter sido definido anteriormente na tabela nome_da_tabela. Ao ser agrupada, a tabela é fisicamente reordenada com base na informação do índice. O agrupamento é feito uma única vez: ao ser posteriormente atualizada, as modificações feitas na tabela não são agrupadas, ou seja, nenhuma tentativa é feita para manter as tuplas novas ou atualizadas na ordem do índice. Se for desejado, a tabela pode ser reagrupada periodicamente executando este comando novamente. Quando a tabela é agrupada, o PostgreSQL registra qual foi o índice utilizado para agrupar. A forma CLUSTER nome_da_tabela reagrupa a tabela utilizando o mesmo índice utilizado anteriormente.
O comando CLUSTER sem nenhum parâmetro reagrupa todas as tabelas do banco de dados corrente pertencentes ao usuário que está executando o comando, ou todas as tabelas se for executado por um superusuário (As tabelas que nunca foram agrupadas não são incluídas). Esta forma do comando CLUSTER não pode ser chamada dentro de uma transação ou de uma função. Durante o agrupamento da tabela é obtido o bloqueio ACCESS EXCLUSIVE, que não permite realizar qualquer outra operação de banco de dados na tabela (tanto de leitura quanto de escrita) até o comando CLUSTER terminar.
Parâmetros nome_do_índice O nome do índice. nome_da_tabela O nome da tabela (opcionalmente qualificado pelo esquema).
Observações No caso do acesso aleatório a uma única linha da tabela, a ordem física dos dados da tabela não é importante. Entretanto, havendo tendência para acessar alguns dados mais que outros, e havendo um índice agrupando estes dados, a utilização do comando CLUSTER trará benefícios. Se for acessada uma faixa de valores indexados de uma tabela, ou um único valor indexado possuindo vária linhas correspondendo a este valor, o comando CLUSTER ajuda, porque quando o índice identifica a página da primeira linha, provavelmente todas as outras linhas estarão nesta mesma página, reduzindo o acesso ao disco e acelerando a consulta. Durante a operação de agrupamento, uma cópia temporária da tabela é criada contendo os dados da tabela na ordem do índice. Também são criadas cópias temporárias de cada índice da tabela. Portanto, é necessário um espaço livre em disco pelo menos igual à soma do tamanho da tabela com os tamanhos de seus índices. Como o comando CLUSTER guarda a informação de agrupamento, é possível agrupar as tabelas desejadas manualmente na primeira vez e, depois, configurar um evento periódico, como no VACUUM, para que as tabelas sejam periodicamente reagrupadas.
687
Como o planejador registra estatísticas sobre a ordem das linhas nas tabelas, é aconselhável executar o comando ANALYZE na tabela recém agrupada, senão o otimizador poderá fazer escolhas ruins no planejamento dos comandos. Existe outra forma de agrupar os dados. O comando CLUSTER reordena a tabela original usando a ordem do índice especificado. Este procedimento pode ser lento para tabelas grandes, porque as linhas são lidas no disco na ordem do índice e, se a tabela não estiver ordenada, as linhas estarão em páginas aleatórias, fazendo uma página do disco ser lida para cada linha movida; o PostgreSQL possui um cache, mas a maioria das tabelas grandes não cabem no cache. A outra forma de agrupar a tabela é usar CREATE TABLE nova_tabela AS SELECT lista_de_colunas FROM tabela ORDER BY lista_de_colunas;
que utiliza o código de ordenação da cláusula ORDER BY do PostgreSQL para criar a ordem desejada; geralmente é muito mais rápido que a varredura do índice para dados não ordenados. Em seguida, a tabela original deve ser removida, o comando ALTER TABLE...RENAME deve ser utilizado para mudar o nome da nova_tabela para o nome da tabela original, e recriados os índices da tabela. Entretanto, esta abordagem não preserva os OIDs, restrições, relacionamentos de chaves estrangeiras, privilégios concedidos e outras propriedades da tabela — todos estes itens deverão ser recriados manualmente.
Exemplos Agrupar a tabela empregados baseado no seu índice idx_emp: CLUSTER idx_emp ON empregados;
Agrupar a tabela empregados utilizando o mesmo índice especificado anteriormente: CLUSTER empregados;
Agrupar todas as tabelas de um banco de dados que foram agrupadas anteriormente: CLUSTER;
Compatibilidade Não existe o comando CLUSTER no padrão SQL.
Veja também clusterdb
688
COMMENT Nome COMMENT — define ou muda o comentário sobre um objeto
Sinopse COMMENT ON { TABLE nome_do_objeto | COLUMN nome_da_tabela.nome_da_coluna | AGGREGATE nome_da_agregação (tipo_da_agregação) | CAST (tipo_de_origem AS tipo_de_destino) | CONSTRAINT nome_da_restrição ON nome_da_tabela | CONVERSION nome_do_objeto | DATABASE nome_do_objeto | DOMAIN nome_do_objeto | FUNCTION nome_da_função (tipo_arg1, tipo_arg2, ...) | INDEX nome_do_objeto | LARGE OBJECT oid_objeto_grande | OPERATOR nome_do_operador (tipo_operando_esq, tipo_operando_dir) | OPERATOR CLASS nome_do_objeto USING index_method | [ PROCEDURAL ] LANGUAGE nome_do_objeto | RULE nome_da_regra ON nome_da_tabela | SCHEMA nome_do_objeto | SEQUENCE nome_do_objeto | TRIGGER nome_do_gatilho ON nome_da_tabela | TYPE nome_do_objeto | VIEW nome_do_objeto } IS 'texto'
Descrição O comando COMMENT armazena um comentário sobre um objeto do banco de dados. Os comentários podem ser facilmente acessados através dos comandos \dd, \d+ e \l+ do psql. Outras interfaces de usuário podem acessar os comentários utilizando as mesmas funções nativas usadas pelo psql, ou seja: obj_description() e col_description(). Para modificar um comentário basta executar novamente o comando COMMENT para o mesmo objeto. Somente um único comentário é armazenado para cada objeto. Para remover o comentário deve ser escrito NULL no lugar do texto. O comentário é automaticamente excluído quando o objeto é excluído.
Parâmetros nome_do_objeto nome_da_tabela.nome_da_coluna nome_da_agregação nome_da_restrição nome_da_função nome_do_operador nome_da_regra nome_do_gatilho O nome do objeto ao qual o comentário se refere. Os nomes das tabelas, agregações, domínios, funções, índices, operadores, classes de operador, seqüências, tipos e visões podem ser qualificados pelo esquema. tipo_da_agregação O tipo de dado do argumento da função de agregação, ou * se a função aceitar qualquer tipo de dado.
689
oid_objeto_grande O identificador de objeto (OID) do objeto grande. PROCEDURAL
Meramente informativo. tipo_de_origem O nome do tipo de dado de origem da transformação. tipo_de_destino O nome do tipo de dado de destino da transformação. texto O novo comentário.
Observações Um comentário sobre o banco de dados somente pode ser criado no próprio banco de dados, e somente é visível neste banco de dados, e não nos demais bancos de dados. Não existe atualmente nenhum mecanismo de segurança para os comentários: qualquer usuário conectado ao banco de dados pode ver todos os comentários sobre os objetos neste banco de dados; porém, somente os superusuários podem modificar comentários sobre objetos que não lhe pertencem. Portanto, não devem ser colocadas informações críticas para a segurança nos comentários.
Exemplos Anexar um comentário à tabela minha_tabela: COMMENT ON TABLE minha_tabela IS 'Esta tabela é minha.';
Remover o comentário: COMMENT ON TABLE minha_tabela IS NULL;
Alguns outros exemplos: COMMENT ON AGGREGATE minha_agregacao (double precision) IS 'Calcula a variância da amostra'; COMMENT ON CAST (text AS int4) IS 'Permite transformar texto em int4'; COMMENT ON COLUMN minha_tabela.minha_coluna IS 'Número de identificação do empregado';1 COMMENT ON CONVERSION minha_conversao IS 'Conversão para Unicode'; COMMENT ON DATABASE meu_bd IS 'Banco de dados de desenvolvimento'; COMMENT ON DOMAIN meu_dominio IS 'Domínio de endereço de correio eletrônico'; COMMENT ON FUNCTION minha_funcao (timestamp) IS 'Retorna algarismos romanos'; COMMENT ON INDEX meu_indice IS 'Garante a unicidade do identificador do empregado'; COMMENT ON LANGUAGE plpython IS 'Suporte ao Python nos procedimentos armazenados'; COMMENT ON LARGE OBJECT 346344 IS 'Documento de planejamento'; COMMENT ON OPERATOR ^ (text, text) IS 'Realiza a interseção de dois textos'; COMMENT ON OPERATOR ^ (NONE, text) IS 'Este é um operador de prefixo para texto'; COMMENT ON OPERATOR CLASS int4ops USING btree IS 'Operadores inteiro de 4 bytes para árvores-B'; COMMENT ON RULE minha_regra ON minha_tabela IS 'Registra as atualizações das linhas dos empregados'; COMMENT ON SCHEMA meu_esquema IS 'Dados departamentais'; COMMENT ON SEQUENCE minha_sequencia IS 'Usado para gerar as chaves primárias'; COMMENT ON TABLE meu_esquema.minha_tabela IS 'Informações dos empregados';
690
COMMENT ON 'Usado COMMENT ON COMMENT ON
TRIGGER meu_gatilho ON minha_tabela IS para integridade referencial'; TYPE complex IS 'Tipo de dado de número complexo'; VIEW minha_visão IS 'Visão dos custos departamentais';
Compatibilidade Não existe o comando COMMENT no padrão SQL.
Notas 1. Também pode ser usada a forma COMMENT ON COLUMN minha_visao.minha_coluna IS 'Comentário sobre a coluna da visão'; (N. do T.)
691
COMMIT Nome COMMIT — efetiva a transação corrente
Sinopse COMMIT [ WORK | TRANSACTION ]
Descrição O comando COMMIT efetiva a transação corrente. Todas as modificações efetuadas pela transação se tornam visíveis para os outros, e existe a garantia de permanecerem se uma falha ocorrer.
Parâmetros WORK TRANSACTION
Palavras chave opcionais. Não produzem nenhum efeito.
Observações Use o ROLLBACK para interromper a transação. A utilização do COMMIT fora de uma transação não causa nenhum problema, mas provoca uma mensagem de advertência.
Exemplos Para efetivar a transação corrente e tornar todas as mudanças permanentes: COMMIT;
Compatibilidade O padrão SQL somente especifica as duas formas COMMIT e COMMIT WORK. Fora isso está totalmente em conformidade.
Veja também BEGIN, ROLLBACK
692
COPY Nome COPY — copia dados entre um arquivo e uma tabela
Sinopse COPY nome_da_tabela [ ( coluna [, ...] ) ] FROM { 'nome_do_arquivo' | STDIN } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimitador' ] [ NULL [ AS ] 'cadeia de caracteres nula' ] ] COPY nome_da_tabela [ ( coluna [, ...] ) ] TO { 'nome_do_arquivo' | STDOUT } [ [ WITH ] [ BINARY ] [ OIDS ] [ DELIMITER [ AS ] 'delimitador' ] [ NULL [ AS ] 'cadeia de caracteres nula' ] ]
Descrição O comando COPY copia dados entre tabelas do PostgreSQL e arquivos do sistema operacional. O comando COPY TO copia o conteúdo de uma tabela para um arquivo, enquanto o comando COPY FROM copia dados de um arquivo para uma tabela (adicionando os dados aos já existentes na tabela). Se uma lista de colunas for especificada, o comando COPY somente copia os dados das colunas especificadas de/para o arquivo. Havendo colunas na tabela que não estejam na lista de colunas, o comando COPY FROM insere o valor padrão destas colunas. O comando COPY com um nome de arquivo instrui o servidor PostgreSQL a ler ou escrever diretamente no arquivo. O arquivo deve ser acessível ao servidor, e o nome deve ser especificado sob o ponto de vista do servidor. Quando STDIN ou STDOUT são especificados, os dados são transmitidos através da conexão entre o cliente e o servidor.
Parâmetros nome_da_tabela O nome de uma tabela existente (opcionalmente qualificado pelo esquema). coluna A lista opcional das colunas a serem copiadas. Se nenhuma lista for especificada, todas as colunas são utilizadas. nome_do_arquivo O nome do caminho absoluto do arquivo de entrada ou de saída. STDIN
Especifica que a entrada vem da aplicação cliente. STDOUT
Especifica que a saída vai para a aplicação cliente.
693
BINARY
Faz todos os dados serem armazenados ou lidos no formato binário, em vez de texto. Não é possível especificar as opções DELIMITER ou NULL no modo binário. OIDS
Especifica que deve ser copiado o identificador interno do objeto (OID) de cada linha; é gerado um erro se OIDS for especificado para uma tabela que não possua OIDs. delimitador O caractere único que separa as colunas dentro de cada linha do arquivo. Por padrão o caractere de tabulação. cadeia de caracteres nula A cadeia de caracteres que representa o valor nulo. O padrão é “\N” (contrabarra-N). Pode-se preferir a cadeia de caracteres vazia, por exemplo. Nota: No COPY FROM qualquer item de dado correspondendo a esta cadeia de caracteres é armazenado com o valor nulo e, portanto, deve haver certeza que está sendo utilizada a mesma cadeia de caracteres utilizada para fazer o COPY TO.
Observações O comando COPY só pode ser utilizado em tabelas, não podendo ser utilizado em visões. A palavra chave BINARY faz todos os dados serem armazenados/lidos no formato binário em vez de texto. É um pouco mais rápido que o modo texto normal, mas o arquivo produzido no formato binário é menos portável entre arquiteturas de máquinas e versões do PostgreSQL. É necessário possuir o privilégio SELECT na tabela cujos valores são lidos pelo COPY TO, e o privilégio INSERT na tabela onde os valores são inseridos pelo COPY FROM. Os arquivos declarados no comando COPY são lidos ou escritos diretamente pelo servidor, e não pela aplicação cliente. Portanto, devem residir, ou serem acessíveis, pela máquina servidora de banco de dados, e não pela estação cliente. Os arquivos devem ser acessíveis e poderem ser lidos ou escritos pelo usuário do PostgreSQL (o ID do usuário sob o qual o servidor executa), e não pelo cliente. O COPY com nome de arquivo só é permitido aos superusuários do banco de dados, porque permite ler e escrever em qualquer arquivo que o servidor possua privilégio de acesso. Não confunda o comando COPY com a instrução \copy do psql. O \copy executa COPY FROM STDIN ou COPY TO STDOUT e, portanto, lê/grava os dados em um arquivo acessível ao cliente psql. Por esta razão, a acessibilidade e os direitos de acesso ao arquivo dependem do cliente, e não do servidor, quando o \copy é utilizado. Recomenda-se que o nome do arquivo utilizado no comando COPY seja sempre especificado como um caminho absoluto, o que é exigido pelo servidor no caso do COPY TO, mas para o COPY FROM existe a opção de ler um arquivo especificado pelo caminho relativo. O caminho é interpretado com relação ao diretório de trabalho do processo servidor (algum lugar abaixo do diretório de dados), e não relativo ao diretório de trabalho do cliente. O comando COPY FROM chama os gatilhos e as restrições de verificação da tabela de destino. Entretanto, não chama as regras. O COPY pára de executar no primeiro erro, o que não deve causar problemas no caso do COPY TO, mas a tabela de destino já terá recebido as primeiras linhas no caso do COPY FROM. Estas linhas não são visíveis nem acessíveis, mas ainda assim ocupam espaço em disco, podendo causar o desperdício de uma quantidade considerável de espaço em disco, se o erro ocorrer durante a cópia de uma grande quantidade de dados. Deve ser executado o comando VACUUM para recuperar o espaço desperdiçado.
694
Formatos dos arquivos Formato texto Quando o comando COPY é utilizado sem a opção BINARY, os dados são lidos ou escritos em um arquivo texto com uma linha para cada linha da tabela. As colunas de cada linha são separadas pelo caractere delimitador. Os valores das colunas são cadeias de caracteres geradas pela função de saída, ou aceitas pela função de entrada, do tipo de dado de cada atributo. A cadeia de caracteres nula especificada é utilizada no lugar das colunas nulas. O comando COPY FROM produz um erro se alguma linha do arquivo de entrada possuir mais, ou menos, colunas que o esperado. Se OIDS for especificado, o OID é lido ou escrito como a primeira coluna, antecedendo as colunas de dado do usuário. O fim dos dados pode ser representado por uma única linha contendo apenas contrabarra-ponto (\.). A marca de fim-de-dados não é necessária ao ler de um arquivo, porque o fim-de-arquivo serve perfeitamente bem; é necessária apenas ao copiar dados de/para aplicações cliente quando for utilizado um protocolo cliente anterior ao 3.0. Caracteres contrabarra (\) podem ser utilizados nos dados do comando COPY para evitar que caracteres dos dados sejam interpretados como delimitadores de linha ou de coluna. Em particular, os seguintes caracteres devem ser precedidos por uma contrabarra se fizerem parte do valor de uma coluna: a própria contrabarra, a nova-linha e o caractere delimitador corrente. A cadeia de caracteres nula é enviada pelo COPY TO sem adição de contrabarras; inversamente, o COPY FROM verifica a entrada com relação à cadeia de caracteres nula antes de remover as contrabarras. Portanto, uma cadeia de caracteres nula como o \N não pode ser confundida com o valor de dado \N (que seria representado por \\N). As seguintes seqüências especiais de contrabarra são reconhecidas pelo comando COPY FROM: Seqüência
Representa
\b
Backspace (ASCII 8)
\f
Avanço de formulário (Form feed) (ASCII 12)
\n
Nova-linha (Newline) (ASCII 10)
\r
Retorno do carro (Carriage return) (ASCII 13)
\t
Tabulação (ASCII 9)
\v
Tabulação Vertical (ASCII 11)
\dígitos
A contrabarra seguida por um a três dígitos octais especifica o caractere com este código numérico
No momento o COPY TO nunca produz uma seqüência contrabarra dígitos-octais, mas utiliza as outras seqüências de contrabarra listadas acima para estes caracteres de controle. Qualquer outro caractere precedido por contrabarra que não tenha sido mencionado na tabela acima é interpretado como representando a si próprio. Entretanto, tome cuidado ao adicionar contrabarras desnecessariamente uma vez que isto poderá, acidentalmente, produzir uma cadeia de caracteres correspondendo à marca de fim-de-dados (\.), ou a cadeia de caracteres nula (\N por padrão). Estas cadeias de caracteres são reconhecidas antes de ocorrer qualquer outro processamento da contrabarra. É altamente recomendado que as aplicações que geram dados para o COPY convertam os caracteres de novalinha e de retorno-de-carro presentes nos dados nas seqüências \n e \r, respectivamente. Atualmente é possível representar retorno-de-carro nos dados por contrabarra e retorno-de-carro, e representar nova-linha nos dados por contrabarra e nova-linha. Entretanto, estas representações podem não ser aceitas nas versões futuras. São, também, altamente vulneráveis à corrupção quando o arquivo do COPY é transferido entre máquinas diferentes; por exemplo, do Unix para o Windows e vice-versa. O comando COPY TO termina cada linha pelo caractere de nova-linha (“\n”), no estilo Unix. Os servidores executando no Microsoft Windows em vez disto geram retorno-de-carro/nova-linha (“\r\n”), mas somente no
695
COPY para um arquivo no servidor; para manter a consistência entre as plataformas, COPY TO STDOUT sempre gera “\n”, independentemente da plataforma do servidor. O comando COPY FROM pode tratar linhas
terminando por nova-linha, retorno-de-carro, ou retorno-de-carro/nova-linha. Para reduzir o risco de erro devido a caracteres de nova-linha ou de retorno-de-carro sem contrabarra que fazem parte dos dados, o COPY FROM reclama se o final de todas as linhas de entrada não forem idênticos. Formato Binário O formato do arquivo usado pelo COPY BINARY mudou no PostgreSQL v7.4. O novo formato consiste em um cabeçalho do arquivo, zero ou mais tuplas contendo os dados das linhas, e um rodapé do arquivo. Os cabeçalhos e os dados agora são enviados na ordem de byte da rede. Cabeçalho do Arquivo O cabeçalho do arquivo é formado por 15 bytes para campos fixos, seguidos por uma área de extensão do cabeçalho de comprimento variável. Os campos fixos são: Assinatura A seqüência de 11 bytes PGCOPY\n\377\r\n\0 — observe que o byte zero é uma parte requerida da assinatura (A assinatura foi projetada para permitir a fácil identificação de arquivos corrompidos por uma transferência de dados não apropriada. Esta assinatura é modificada por filtros de tradução de fim de linha, bytes zero suprimidos, bits altos suprimidos, ou mudanças de paridade). Campo de sinalizadores Inteiro de 32 bits máscara de bits, indicando aspectos importantes do formato do arquivo. Os bits são numerados de 0 (LSB) a 31 (MSB). Observe que este campo é armazenado na ordem de bytes da rede (byte mais significativo primeiro), assim como todos os campos inteiro utilizados no formato do arquivo. Os bits 16-31 são reservados para indicar questões críticas do formato do arquivo; a leitura deve ser interrompida se for encontrado um bit definido não esperado neste intervalo. Os bits 0-15 são reservados para sinalizar questões de formato anteriores-compatíveis; a leitura deve simplesmente ignorar qualquer bit definido não esperado neste intervalo. Atualmente somente um bit sinalizador está definido, os demais devem ser zero: Bit 16 Se for 1, os OIDs estão incluídos nos dados; se for 0, não. Comprimento da área de extensão do cabeçalho Inteiro de 32 bits, contendo o comprimento em bytes do restante do cabeçalho, não se incluindo. Atualmente é igual a zero, e a primeira tupla o segue imediatamente. Mudanças futuras no formato poderão permitir dados adicionais estarem presentes no cabeçalho. A leitura deve simplesmente pular qualquer dado na extensão do cabeçalho que não souber o que fazer com o mesmo. A área de extensão do cabeçalho foi concebida para conter uma seqüência de blocos auto-identificadores. O campo de sinalizadores não tem por finalidade informar aos leitores o que existe na área de extensão. O projeto específico do conteúdo da extensão do cabeçalho foi deixado para uma versão futura. Este projeto permite tanto adições de cabeçalhos compatíveis com os anteriores (adicionar blocos de extensão de cabeçalho, ou definir bits sinalizadores de baixa-ordem), quanto mudanças não compatíveis com os anteriores (definir bits sinalizadores de alta-ordem para sinalizar estas mudanças, e adicionar dados de apoio à área de extensão se for necessário). Tuplas Cada tupla começa por um inteiro de 16 bits, que é o contador do número de campos na tupla; atualmente todas as tuplas da tabela possuem o mesmo contador, mas isto pode não ser verdade para sempre. Então, para cada campo da tupla, existe a informação do comprimento com 32 bits, seguida por esta quantidade de bytes de dados do campo (a informação do comprimento não se inclui, podendo ser zero). Como caso especial, -1 informa o valor de um campo nulo, e nenhum byte de valor vem a seguir. Não existe nenhum enchimento de alinhamento ou qualquer outro dado extra entre os campos.
696
Atualmente é assumido que todos os valores dos dados em um arquivo COPY BINARY estão no formato binário (código de formatação um). É previsto que uma extensão futura poderá adicionar um campo de cabeçalho permitindo que os códigos de formatação sejam especificados por coluna. Para determinar o formato binário apropriado para os dados da tupla deve ser consultado o código fonte do PostgreSQL, em particular as funções *send e *recv para o tipo de dado de cada coluna (normalmente estas funções se encontram no diretório src/backend/utils/adt/ da distribuição do código fonte). Se os OIDs forem incluídos no arquivo, o campo OID segue imediatamente a informação contador do número de campos. É um campo normal, exceto que não está incluído no contador do número de campos. Em particular possui uma informação de comprimento — permitindo tratar OIDs de 4-bytes versus 8-bytes sem muita dificuldade e, também, permitindo os OIDs serem mostrados como nulo se por acaso for desejado. Rodapé do Arquivo O rodapé do arquivo consiste numa informação, inteiro de 16 bits, contendo -1, facilmente distinguível da informação contador do número de campos da tupla. A leitura deve relatar um erro se a informação contador do número de campos não for -1 nem for o número esperado de colunas. Isto permite uma verificação extra com relação à perda de sincronização com os dados.
Exemplos O exemplo a seguir copia uma tabela para o cliente utilizando a barra vertical (|) como delimitador de campo: COPY paises TO STDOUT WITH DELIMITER '|';
Para copiar os dados de um arquivo para a tabela paises: COPY paises FROM '/usr1/proj/bray/sql/dados_dos_paises';
Abaixo está mostrado um exemplo contendo dados apropriados para serem copiados a partir da STDIN: AF AL DZ ZM ZW
AFGHANISTAN ALBANIA ALGERIA ZAMBIA ZIMBABWE
Observe que o espaço em branco em cada linha é, na verdade, o caractere de tabulação. Abaixo estão os mesmos dados escritos no formato binário. Os dados mostrados foram filtrados utilizando o utilitário do Unix od -c. A tabela possui três colunas: a primeira é do tipo char(2); a segunda é do tipo text; a terceira é do tipo integer. Todas as linhas possuem o valor nulo na terceira coluna. 0000000 P G C O P 0000020 \0 \0 \0 \0 003 0000040 F G H A N 0000060 \0 \0 \0 002 A 0000100 A 377 377 377 377 0000120 007 A L G E 0000140 \0 002 Z M \0 0000160 377 377 \0 003 \0 0000200 M B A B W
Y \n 377 \r \n \0 \0 \0 \0 \0 \0 \0 \0 \0 002 A F \0 \0 \0 013 A I S T A N 377 377 377 377 \0 003 L \0 \0 \0 007 A L B A N I \0 003 \0 \0 \0 002 D Z \0 \0 \0 R I A 377 377 377 377 \0 003 \0 \0 \0 \0 006 Z A M B I A 377 377 \0 \0 002 Z W \0 \0 \0 \b Z I E 377 377 377 377 377 377
No próximo exemplo 1 é utilizado o comando COPY, chamado a partir do psql, para copiar a primeira, a segunda e a quarta colunas de uma tabela de quatro colunas, a partir da quarta linha do arquivo /tmp/linhas.dat. A tabela foi criada através do comando: CREATE TABLE linhas ( coluna1 TEXT PRIMARY KEY, coluna2 TEXT, coluna3 TEXT, coluna4 TEXT);
697
O conteúdo do arquivo carregado está mostrado abaixo: # cat /tmp/linhas.dat linha1a|linha1b|linha1d linha2a|linha2b|linha2d linha3a|linha3b|linha3d linha4a|linha4b|linha4d linha5a|linha5b|linha5d linha6a|linha6b|linha6d linha7a|linha7b|linha7d linha8a|linha8b|linha8d
E o comando utilizado para copiar os dados do arquivo para a tabela foi: tail +4 /tmp/linhas.dat | psql -U teste teste -c \ "COPY linhas(coluna1,coluna2,coluna4) FROM STDIN WITH DELIMITER '|'"
Como resultado os seguintes dados foram incluídos na tabela: => SELECT * FROM linhas; coluna1 | coluna2 | coluna3 | coluna4 ---------+---------+---------+--------linha4a | linha4b | | linha4d linha5a | linha5b | | linha5d linha6a | linha6b | | linha6d linha7a | linha7b | | linha7d linha8a | linha8b | | linha8d (5 linhas)
Compatibilidade Não existe o comando COPY no padrão SQL. A sintaxe mostrada abaixo era utilizada nas versões anteriores a 7.3, sendo ainda aceita: COPY [ BINARY ] nome_da_tabela [ WITH OIDS ] FROM { 'nome_do_arquivo' | STDIN } [ [USING] DELIMITERS 'delimitador' ] [ WITH NULL AS 'cadeia de caracteres nula' ] COPY [ BINARY ] nome_da_tabela [ WITH OIDS ] TO { 'nome_do_arquivo' | STDOUT } [ [USING] DELIMITERS 'delimitador' ] [ WITH NULL AS 'cadeia de caracteres nula' ]
Notas 1. Este exemplo foi escrito pelo tradutor, não fazendo parte do manual original.
698
CREATE AGGREGATE Nome CREATE AGGREGATE — cria uma função de agregação
Sinopse CREATE AGGREGATE nome ( BASETYPE = tipo_de_dado_da_entrada, SFUNC = função_de_transição_de_estado, STYPE = tipo_de_dado_do_estado [ , FINALFUNC = função_final ] [ , INITCOND = condição_inicial ] )
Descrição O comando CREATE AGGREGATE cria uma função de agregação. Algumas funções de agregação para tipos base, como min(integer) e avg(double precision) são fornecidas na distribuição padrão. Se forem criados tipos novos, ou se houver necessidade de uma função de agregação não fornecida, então o comando CREATE AGGREGATE pode ser utilizado para fornecer as funcionalidades desejadas. Se for fornecido o nome do esquema (por exemplo, CREATE AGGREGATE meu_esquema.minha_agregacao ...) então a função de agregação é criada no esquema especificado, senão é criada no esquema corrente. Uma função de agregação é identificada pelo seu nome e tipo de dado de entrada. Duas funções de agregação no mesmo esquema podem ter o mesmo nome se operarem em tipos de dado de entrada diferentes. O nome e tipo de dado de entrada de uma função de agregação também deve ser diferente do nome e tipo(s) de dado de entrada de todas as funções comuns no mesmo esquema. Uma função de agregação é composta por uma ou duas funções comuns: uma função de transição de estado, função_de_transição_de_estado, e uma função opcional para a realização dos cálculos finais, função_final. Estas funções são utilizadas da seguinte forma: função_de_transição_de_estado( estado-interno, próximo-item-de-dado ) ---> próximo-estado-interno função_final( estado-interno ) ---> valor-da-agregação
O PostgreSQL cria uma variável temporária com o tipo de dado tipo_de_dado_do_estado para armazenar o estado interno corrente da agregação. Para cada item de dado da entrada a função de transição de estado é chamada para calcular o novo valor do estado interno. Após todos os dados terem sido processados, a função final é chamada uma vez para calcular o valor retornado da agregação. Não havendo nenhuma função final, então o valor do estado final é retornado como estiver. A função de agregação pode fornecer uma condição inicial, ou seja, um valor inicial para o valor do estado interno. Este valor é especificado e armazenado no banco de dados em uma coluna do tipo text, mas deve possuir uma representação externa válida para uma constante do tipo de dado do valor do estado. Se não for fornecido, então o valor do estado começa com nulo. Se a função de transição de estado for declarada como “strict”, então não poderá ser chamada com valores da entrada nulos. Para este tipo de função de transição, a execução da agregação se comporta da seguinte forma: Valores da entrada nulos são ignorados (a função não é chamada e o valor do estado anterior permanece); Se o valor do estado inicial for nulo, então o primeiro valor da entrada que não for nulo substitui o valor do estado, e a função de transição é chamada a partir do segundo valor da entrada que não for nulo. Este procedimento é útil para implementar funções de agregação como max. Observe que este comportamento somente está disponível quando o tipo_de_dado_do_estado for o mesmo do tipo_de_dado_da_entrada. Quando estes
699
tipos de dado forem diferentes, deverá ser fornecido um valor não nulo para a condição inicial, ou utilizar uma função de transição que não seja estrita. Se a função de transição de estado não for estrita então será chamada, incondicionalmente, para cada valor da entrada, devendo ser capaz de lidar com entradas nulas e valores de transição nulos por si própria. Esta opção permite ao autor da função de agregação ter pleno controle sobre o tratamento dos valores nulos. Se a função final for declarada como “strict”, então não será chamada quando o valor do estado final for nulo; em vez disso, um resultado nulo será retornado automaticamente (É claro que este é apenas o comportamento normal de funções estritas 1 ). A função final sempre tem a opção de retornar o valor nulo. Por exemplo, a função final para avg retorna nulo quando não há linhas de entrada.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da função de agregação a ser criada. tipo_de_dado_da_entrada O tipo do dado de entrada sobre o qual esta função de agregação opera. Pode ser especificado como "ANY" para uma função de agregação que não examina seus valores de entrada (um exemplo é a função count(*)).
função_de_transição_de_estado O nome da função de transição de estado a ser chamada para cada valor dos dados da entrada. Normalmente esta função possui dois argumentos, o primeiro sendo do tipo tipo_de_dado_do_estado e o segundo do tipo tipo_de_dado_da_entrada. Outra possibilidade, para funções de agregação que não examinam seus valores de entrada, é a função possuir apenas um argumento do tipo tipo_de_dado_do_estado. Em qualquer um dos casos a função deve retornar um valor do tipo tipo_de_dado_do_estado. Esta função recebe o valor do estado corrente e o item de dado da entrada corrente e retorna o próximo valor do estado. tipo_de_dado_do_estado O tipo de dado do valor do estado da agregação. função_final O nome da função final chamada para calcular o resultado da agregação após todos os dados da entrada terem sido examinados. A função deve receber um único argumento do tipo tipo_de_dado_do_estado. O tipo de dado retornado pela agregação é definido pelo tipo retornado por esta função. Se a função_final não for especificada, então o valor do estado final é utilizado como sendo o resultado da agregação, e o tipo retornado fica sendo o tipo_de_dado_do_estado. condição_inicial A definição inicial do valor do estado. Deve ser uma constante cadeia de caracteres na forma aceita pelo tipo de dado tipo_de_dado_do_estado. Se não for especificado, o valor do estado começa com nulo. Os parâmetros para CREATE AGGREGATE podem ser escritos em qualquer ordem, e não apenas na ordem mostrada acima.
Exemplos Veja a Seção 33.9.
Compatibilidade O comando CREATE AGGREGATE é uma extensão do PostgreSQL à linguagem. O padrão SQL não inclui funções de agregação definidas pelo usuário.
700
Veja também ALTER AGGREGATE, DROP AGGREGATE
Notas 1. strict — A função f é estrita em um argumento se “f bottom = bottom”. Em outras palavras, o resultado depende do argumento e, portanto, a avaliação da aplicação da função não pode terminar enquanto a avaliação do argumento não tenha terminado. FOLDOC - Free On-Line Dictionary of Computing (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=strict) (N. do T.)
701
CREATE CAST Nome CREATE CAST — cria uma conversão de tipo de dado
Sinopse CREATE CAST (tipo_de_origem AS tipo_de_destino) WITH FUNCTION nome_da_função (tipo_do_argumento) [ AS ASSIGNMENT | AS IMPLICIT ] CREATE CAST (tipo_de_origem AS tipo_de_destino) WITHOUT FUNCTION [ AS ASSIGNMENT | AS IMPLICIT ]
Descrição O comando CREATE CAST cria uma conversão. A conversão especifica como realizar a conversão entre dois tipos de dado. Por exemplo, SELECT CAST(42 AS text);
converte a constante inteira 42 para o tipo text chamando uma função especificada previamente, neste caso text(int4); se nenhuma conversão adequada tiver sido definida, a conversão falha. Dois tipos podem ser binariamente compatíveis, significando que podem ser convertidos um no outro “livremente”, sem chamar nenhuma função. Requer que os valores correspondentes utilizem a mesma representação interna. Por exemplo, os tipos text e varchar são binariamente compatíveis. Por padrão, a conversão pode ser chamada somente por uma requisição de conversão explícita, ou seja, uma construção explícita CAST(x AS nome_do_tipo), x::nome_do_tipo, ou nome_do_tipo(x). Se a conversão for marcada como AS ASSIGNMENT então pode ser chamada implicitamente quando for atribuído um valor a uma coluna com o tipo de dado de destino. Por exemplo, supondo que foo.f1 seja uma coluna do tipo text, então a atribuição INSERT INTO foo (f1) VALUES (42);
é permitida se a conversão do tipo integer para o tipo text estiver marcada como AS ASSIGNMENT, senão a atribuição não é permitida; geralmente é utilizado o termo conversão de atribuição (assignment cast) para descrever este tipo de conversão. Se a conversão estiver marcada como AS IMPLICIT então poderá ser chamada implicitamente em qualquer contexto, seja em uma atribuição ou internamente em uma expressão. Por exemplo, como || recebe operandos do tipo text, então a expressão SELECT 'Data e hora ' || now();
somente será permitida se a conversão do tipo timestamp para o tipo text estiver marcada como AS IMPLICIT, senão será necessário escrever a conversão explicitamente como, por exemplo, SELECT 'Data e hora ' || CAST(now() AS text);
(Geralmente é utilizado o termo conversão implícita (implicit cast) para descrever este tipo de conversão). É sensato ser conservador com relação a marcar conversões como implícitas. Uma superabundância de possibilidades de conversões implícitas pode fazer o PostgreSQL escolher interpretações surpreendentes para os comandos, ou até não ser capaz de resolver o comando devido à existência de várias interpretações
702
possíveis. Uma boa regra empírica é tornar a conversão chamável implicitamente somente nos casos de transformações que preservam as informações entre tipos da mesma categoria geral. Por exemplo, a conversão de int2 em int4 pode ser implícita, mas a conversão de float8 para int4 provavelmente deve ser somente de atribuição. Conversões entre tipos de categorias diferentes, como text para int4, é melhor serem somente explícitas. É necessário ser o dono do tipo de dado de origem ou de destino para poder criar uma conversão. Para criar uma conversão binariamente compatível é necessário ser um superusuário; esta restrição existe porque uma conversão binariamente compatível pode facilmente derrubar o servidor.
Parâmetros tipo_de_origem O nome do tipo de dado de origem da conversão. tipo_de_destino O nome do tipo de dado de destino da conversão. nome_da_função(tipo_do_argumento) A função utilizada para realizar a conversão. O nome da função pode ser qualificado pelo esquema. Se não for, a função será procurada no caminho de procura de esquema. O tipo do argumento deve ser idêntico ao tipo da origem, e o tipo de dado do resultado da função deve corresponder ao tipo de dado de destino da conversão. WITHOUT FUNCTION
Indica que o tipo de dado de origem e o tipo de dado de destino são binariamente compatíveis e, por isso, não há necessidade de nenhuma função para realizar a conversão. AS ASSIGNMENT
Indica que a conversão pode ser chamada implicitamente em contextos de atribuição. AS IMPLICIT
Indica que a conversão pode ser chamada implicitamente em qualquer contexto.
Observações Use o comando DROP CAST para remover conversões criadas pelo usuário. Lembre-se que para ser possível converter tipos nas duas direções é necessário declarar conversões para as duas direções explicitamente. Antes do PostgreSQL 7.3 toda função que possuía o mesmo nome de um tipo de dado, retornava este tipo de dado, e recebia um argumento de um tipo diferente era, automaticamente, uma função de conversão. Esta convenção foi abandonada devido à introdução dos esquemas e da capacidade de representar conversões binariamente compatíveis nos catálogos do sistema. As funções de conversão internas ainda seguem este esquema de nomes, mas também devem aparecer como conversões no catálogo do sistema pg_cast.
Exemplos Para criar uma conversão do tipo text para o tipo int4 utilizando a função int4(text): CREATE CAST (text AS int4) WITH FUNCTION int4(text);
(Esta conversão já está pré-definida no sistema).
Compatibilidade O comando CREATE CAST está em conformidade com o SQL:1999, exceto que o SQL:1999 não trata de tipos binariamente compatíveis. A cláusula AS IMPLICIT também é uma extensão do PostgreSQL.
703
Veja também CREATE FUNCTION, CREATE TYPE, DROP CAST
704
CREATE CONSTRAINT TRIGGER Nome CREATE CONSTRAINT TRIGGER — cria um gatilho de restrição
Sinopse CREATE CONSTRAINT TRIGGER nome AFTER eventos ON nome_da_tabela restrição atributos FOR EACH ROW EXECUTE PROCEDURE nome_da_função ( argumentos )
Descrição O comando CREATE CONSTRAINT TRIGGER é utilizado dentro do comando CREATE TABLE/ALTER TABLE e pelo pg_dump, para criar gatilhos especiais para integridade referencial. Não se destina a uso geral.
Parâmetros nome O nome do gatilho de restrição. eventos As categorias de evento para as quais este gatilho deve ser disparado. nome_da_tabela O nome (opcionalmente qualificado pelo esquema) da tabela onde ocorrem os eventos que disparam o gatilho. restrição A especificação da restrição. atributos Os atributos da restrição. nome_da_função(argumentos) A função a ser chamada como parte do processamento do gatilho.
705
CREATE CONVERSION Nome CREATE CONVERSION — cria uma conversão de codificação
Sinopse CREATE [DEFAULT] CONVERSION nome FOR codificação_de_origem TO codificação_de_destino FROM nome_da_função
Descrição O comando CREATE CONVERSION cria uma conversão de codificação. Os nomes das conversões podem ser utilizados na função convert para especificar uma determinada conversão de codificação. Além disso, as conversões marcadas como DEFAULT podem ser utilizadas para fazer a conversão automática de codificação entre o cliente e o servidor. Para esta finalidade devem ser criadas duas conversões: da codificação A para B e da codificação B para A. Para poder criar uma conversão é necessário possuir o privilégio EXECUTE na função, e o privilégio CREATE no esquema de destino.
Parâmetros DEFAULT
A cláusula DEFAULT indica que esta é a conversão padrão para o caso particular destas codificações de origem e de destino. Em um esquema deve existir apenas uma codificação padrão para cada par de codificações. nome O nome da conversão. O nome da conversão pode ser qualificado pelo esquema. Caso não seja, a conversão é criada no esquema corrente. O nome da conversão deve ser único no esquema. codificação_de_origem O nome da codificação de origem. codificação_de_destino O nome da codificação de destino. nome_da_função A função utilizada para realizar a conversão. O nome da função pode ser qualificado pelo esquema. Caso não seja, a função é procurada no caminho. A função deve possuir a seguinte assinatura: funcao_de_conversao( integer, -- identificador da codificação de origem integer, -- identificador da codificação de destino cstring, -- cadeia de caracteres de origem -- (cadeia de caracteres C terminada por nulo) cstring, -- cadeia de caracteres de destino -- (cadeia de caracteres C terminada por nulo) integer -- comprimento da cadeia de caracteres de origem ) RETURNS void;
Observações Use o comando DROP CONVERSION para remover conversões definidas pelo usuário. Os privilégios necessários para criar conversão podem ser alterados em uma versão futura.
706
Exemplos Para criar a conversão da codificação UNICODE para LATIN1 utilizando minha_funcao: CREATE CONVERSION minha_conversao FOR 'UNICODE' TO 'LATIN1' FROM minha_funcao;
Compatibilidade O comando CREATE CONVERSION é uma extensão do PostgreSQL. Não existe o comando CREATE CONVERSION no padrão SQL.
Veja também ALTER CONVERSION, CREATE FUNCTION, DROP CONVERSION
707
CREATE DATABASE Nome CREATE DATABASE — cria um banco de dados
Sinopse CREATE DATABASE nome [ [ WITH ] [ OWNER [=] dono_bd ] [ LOCATION [=] 'caminho_bd' ] [ TEMPLATE [=] modelo ] [ ENCODING [=] codificação ] ]
Descrição O comando CREATE DATABASE cria um banco de dados no PostgreSQL. Para poder criar um banco de dados é necessário ser um superusuário ou possuir o privilégio especial CREATEDB. Veja CREATE USER. Normalmente, o criador se torna o dono do novo banco de dados. Os superusuários podem criar bancos de dados cujos donos são outros usuários utilizando a cláusula OWNER e, até mesmo, criar bancos de dados cujos donos são usuários sem nenhum privilégio especial. Usuários comuns com privilégio CREATEDB podem criar apenas bancos de dados cujos donos são eles mesmos. Um local alternativo pode ser especificado com a finalidade de, por exemplo, armazenar o banco de dados em um disco diferente. O caminho deve ter sido preparado anteriormente pelo comando initlocation. Se o nome do caminho não possuir uma barra (/), é interpretado como sendo o nome de uma variável de ambiente, a qual deve ser conhecida pelo processo servidor. Desta forma, o administrador do banco de dados pode controlar os locais onde os bancos de dados podem ser criados (Uma escolha usual é, por exemplo, PGDATA2). Se o servidor for compilado com ALLOW_ABSOLUTE_DBPATHS (o que não é feito por padrão), os nomes de caminhos absolutos, identificados por uma barra inicial (por exemplo, /usr/local/pgsql/data), também são permitidos. Nos dois casos, o nome final do caminho deve ser absoluto e não pode conter nenhum apóstrofo ('). Por padrão, o novo banco de dados é criado clonando o de banco de dados comum do sistema template1. Um modelo diferente pode ser especificado escrevendo TEMPLATE modelo. Em particular, escrevendo TEMPLATE template0 pode ser criado um banco de dados básico contendo apenas os objetos comuns prédefinidos pela versão do PostgreSQL em uso. Esta forma é útil quando se deseja evitar a cópia de qualquer objeto da instalação local que possa ter sido adicionado ao template1. O parâmetro opcional de codificação permite selecionar a codificação do banco de dados. Quando este parâmetro não é especificado, o padrão é utilizar a mesma codificação do banco de dados usado como modelo.
Parâmetros nome O nome do banco de dados a ser criado. dono_bd O nome do usuário do banco de dados que será o dono do novo banco de dados, ou DEFAULT para usar o padrão (ou seja, o usuário que está executando o comando). caminho_bd Um local alternativo no sistema de arquivos onde será armazenado o banco de dados, especificado como uma cadeia de caracteres; ou DEFAULT para utilizar o local padrão.
708
modelo Nome do modelo a partir do qual o novo banco de dados será criado, ou DEFAULT para utilizar o modelo padrão (template1). codificação Codificação do conjunto de caracteres a ser utilizado no novo banco de dados. Deve ser especificada uma constante cadeia de caracteres (por exemplo, 'SQL_ASCII'), ou o número inteiro da codificação, ou DEFAULT para utilizar a codificação padrão. Os parâmetros opcionais podem ser escritos em qualquer ordem, e não apenas na ordem mostrada acima.
Observações O comando CREATE DATABASE não pode ser executado dentro de um bloco de transação. Erros contendo “could not initialize database directory” (impossível inicializar o diretório do banco de dados) estão normalmente relacionados com a falta de permissão no diretório de dados, disco cheio, ou outros problemas no sistema de arquivos. Ao utilizar um local alternativo, o usuário sob o qual o servidor de banco de dados está processando deve ter acesso a este local. Deve ser utilizado DROP DATABASE para remover o banco de dados. A aplicação createdb, fornecida por conveniência, é um programa em torno deste comando. Existem questões de segurança envolvidas, ao se utilizar locais alternativos para bancos de dados especificados por nomes de caminho absoluto; este é o motivo desta funcionalidade não ser habilitada por padrão. Veja a Seção 18.5 para obter mais informações. Embora seja possível copiar outro banco de dados em vez do template1 especificando seu nome como modelo, não se pretende (ainda) que esta seja uma funcionalidade de “COPY DATABASE” de uso geral. Recomenda-se que os bancos de dados utilizados como modelo sejam tratados como se fossem somente para leitura. Veja a Seção 18.3 para obter mais informações.
Exemplos Para criar um banco de dados: CREATE DATABASE lusiadas;
Para criar um banco de dados novo na área alternativa ~/bd_privado, execute a partir da linha de comandos: mkdir bd_privado initlocation ~/bd_privado
Em seguida execute o comando abaixo em uma sessão do psql: CREATE DATABASE outro_lugar WITH LOCATION '/home/olly/bd_privado';
Compatibilidade Não existe o comando CREATE DATABASE no padrão SQL. Os bancos de dados são equivalentes aos catálogos, cuja criação é definida pela implementação.
709
CREATE DOMAIN Nome CREATE DOMAIN — cria um domínio
Sinopse CREATE DOMAIN nome [AS] tipo_de_dado [ DEFAULT expressão ] [ restrição [ ... ] ] onde restrição é: [ CONSTRAINT nome_da_restrição ] { NOT NULL | NULL | CHECK (expressão) }
Descrição O comando CREATE DOMAIN cria um domínio de dados. O usuário que cria o domínio se torna o seu dono. 1 Se o nome do esquema for fornecido (por exemplo, CREATE DOMAIN meu_esquema.meu_dominio ...), então o domínio é criado no esquema especificado, senão é criado no esquema corrente. O nome do domínio deve ser único entre os tipos e domínios existentes no esquema. Domínios são úteis para abstrair campos comuns entre tabelas em um único local para manutenção. Por exemplo, uma coluna de endereço de correio eletrônico pode ser usada em várias tabelas, todas com as mesmas propriedades. Defina o domínio e o utilize em vez de definir as restrições em cada tabela individualmente.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) do domínio a ser criado. tipo_de_dado O tipo de dado subjacente do domínio, podendo incluir especificadores de matrizes (arrays). DEFAULT expressão
A cláusula DEFAULT especifica o valor padrão para as colunas com o tipo de dado do domínio. O valor é qualquer expressão sem variável (variable-free) (mas subconsultas não são permitidas). O tipo de dado da expressão padrão deve corresponder ao tipo de dado do domínio. Se o valor padrão não for especificado, então o valor nulo se torna o valor padrão. A expressão padrão é usada em toda operação de inserção que não especifica valor para a coluna. Se for definido o valor padrão para uma determinada coluna, este substitui o valor padrão associado ao domínio. Por sua vez, o valor padrão para o domínio substitui o valor padrão associado ao tipo de dado subjacente. CONSTRAINT nome_da_restrição
Um nome opcional para a restrição. Se não for especificado, o sistema gera um nome. NOT NULL
Os valores deste domínio não podem ser nulos. NULL
Os valores deste domínio podem ser nulos. Este é o padrão. Esta cláusula tem somente a finalidade de manter a compatibilidade com os bancos de dados SQL fora do padrão. Seu uso é desaconselhado nas novas aplicações.
710
CHECK (expressão)
A cláusula CHECK especifica as restrições de integridade, ou testes, que os valores do domínio devem satisfazer. Cada restrição deve ser uma expressão que produz um resultado booleano. Deve ser utilizado o nome VALUE para fazer referência ao valor sendo testado. Atualmente as expressões CHECK não podem conter subconsultas, nem fazer referências a outras variáveis além de VALUE.
Exemplos Este exemplo cria o tipo de dado cod_nacao (código da nação), em seguida o utiliza na definição da tabela: CREATE DOMAIN cod_nacao char(2) NOT NULL; CREATE TABLE tbl_nacao (id integer, nacao cod_nacao);
Compatibilidade O comando CREATE DOMAIN está em conformidade com o padrão SQL.
Veja também ALTER DOMAIN, DROP DOMAIN
Notas 1. Um domínio é um objeto nomeado definido pelo usuário que pode ser especificado como uma alternativa ao tipo de dado em certos locais onde o tipo de dado pode ser especificado. O domínio consiste do tipo de dado, possivelmente a opção default, e zero ou mais restrições (domínio). A restrição de domínio se aplica a todas as colunas baseadas neste domínio, operando como uma restrição de tabela para cada coluna deste tipo. As restrições de domínio se aplicam apenas às colunas baseadas no domínio associado. A restrição de domínio é aplicada a todo valor resultante de uma operação de conversão (cast) para o domínio. (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
711
CREATE FUNCTION Nome CREATE FUNCTION — cria uma função
Sinopse CREATE [ OR REPLACE ] FUNCTION nome ( [ tipo_do_argumento [, ...] ] ) RETURNS tipo_retornado { LANGUAGE nome_da_linguagem | IMMUTABLE | STABLE | VOLATILE | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT | [EXTERNAL] SECURITY INVOKER | [EXTERNAL] SECURITY DEFINER | AS 'definição' | AS 'arquivo_objeto', 'símbolo_de_vínculação' } ... [ WITH ( atributo [, ...] ) ]
Descrição O comando CREATE FUNCTION cria uma função. O comando CREATE OR REPLACE FUNCTION cria uma função, ou substitui uma função existente. Se o nome do esquema for incluído então a função é criada no esquema especificado, senão é criada no esquema corrente. O nome da nova função não deve ser igual ao de outra função existente com argumentos do mesmo tipo, no mesmo esquema. Entretanto, funções com argumentos de tipos diferentes podem ter o mesmo nome, o que é chamado de sobrecarga (overload). Para atualizar a definição de uma função existente deve ser usado o comando CREATE OR REPLACE FUNCTION. Não é possível mudar o nome ou os tipos dos argumentos da função desta maneira; se for tentado, será criada uma nova função distinta. O comando CREATE OR REPLACE FUNCTION também não permite mudar o tipo de dado retornado por uma função existente; para fazer isto a função deve ser removida e recriada. Se a função for removida e recriada, a nova função não é mais a mesma entidade que era antes; será necessário remover as regras, visões, gatilhos, etc. que fazem referência à função antiga. Use o comando CREATE OR REPLACE FUNCTION para mudar a definição de uma função sem invalidar os objetos que fazem referência à função. O usuário que cria a função se torna o seu dono.
Parâmetros nome O nome da função a ser criada. tipo_do_argumento Os tipos de dado dos argumentos da função (opcionalmente qualificados pelo esquema), caso existam. O tipo de dado do argumento pode ser um tipo base, composto, ou domínio, ou pode fazer referência ao tipo de uma coluna de tabela. O tipo de dado da coluna é referenciado escrevendo nome_da_tabela.nome_da_coluna%TYPE; a utilização desta notação pode, algumas vezes, ajudar a tornar a função independente das mudanças ocorridas na definição da tabela. Dependendo da linguagem de implementação também pode ser permitido especificar “pseudotipos”, como cstring. Pseudotipos indicam que o tipo do argumento não está completamente especificado, ou que está fora do conjunto usual de tipos de dado do SQL.
712
tipo_retornado O tipo de dado retornado (opcionalmente qualificados pelo esquema), que pode ser um tipo base, tipo composto ou domínio, ou pode fazer referência ao tipo de uma coluna de tabela. Veja a descrição acima em tipo_do_argumento sobre como fazer referência ao tipo de uma coluna existente. Dependendo da linguagem de implementação também pode ser permitido especificar “pseudotipos”, como cstring. O modificador SETOF indica que a função retorna um conjunto de itens, em vez de um único item. nome_da_linguagem O nome da linguagem usada para implementar a função. Pode ser SQL, C, internal, ou o nome de uma linguagem procedural definida pelo usuário (Consulte, também, a aplicação createlang). Para manter a compatibilidade com as versões anteriores, o nome pode estar entre apóstrofos ('). IMMUTABLE STABLE VOLATILE
Estes atributos informam ao sistema se é seguro substituir várias chamadas à função por uma única chamada, para otimização em tempo de execução. Pode ser especificado, no máximo, um destes três atributos. Se nenhum deles for especificado, o padrão é assumir VOLATILE. O atributo IMMUTABLE indica que a função sempre retorna o mesmo resultado quando recebe os mesmos valores para os argumentos, ou seja, não faz consultas a bancos de dados, ou de alguma outra forma utiliza informações que não estão diretamente presentes na sua lista de argumentos. Se esta opção for utilizada, qualquer chamada à função com todos os argumentos constantes pode ser imediatamente substituída pelo valor da função. O atributo STABLE indica que dentro de uma única varredura da tabela a função retorna, consistentemente, o mesmo resultado para os mesmos valores dos argumentos, mas que seu resultado pode mudar entre comandos SQL. Esta é a seleção apropriada para as funções cujos resultados dependem de consultas a bancos de dados, valores de parâmetros (como a zona horária corrente), etc. Observe, também, que a família de funções current_timestamp se qualifica como estável, uma vez que seus valores não mudam dentro de uma transação. O atributo VOLATILE indica que o valor da função pode mudar mesmo dentro de uma única varredura da tabela e, portanto, nenhuma otimização pode ser feita. Poucas funções de banco de dados são voláteis neste sentido; alguns exemplos são random(), currval() e timeofday(). Observe que toda função que produz efeito colateral deve ser classificada como volátil, mesmo que seu resultado seja totalmente previsível, para evitar que as chamadas sejam otimizadas; um exemplo é setval(). CALLED ON NULL INPUT RETURNS NULL ON NULL INPUT STRICT CALLED ON NULL INPUT (o padrão) indica que a função é chamada normalmente quando algum de seus argumentos é nulo. Portanto, é responsabilidade do autor da função verificar a presença de valores nulos se for necessário, e responder de forma apropriada. RETURNS NULL ON NULL INPUT ou STRICT indicam que a função sempre retorna nulo quando qualquer um de seus argumentos for nulo. Se este parâmetro for especificado, a função não será executada quando houver argumento nulo; em vez disto será assumido um resultado nulo automaticamente. [EXTERNAL] SECURITY INVOKER [EXTERNAL] SECURITY DEFINER SECURITY INVOKER indica que a função deve ser executada com os privilégios do usuário a chamou. Este é o padrão. SECURITY DEFINER especifica que a função deve ser executada com os privilégios do usuário que a criou.
A palavra chave EXTERNAL está presente para manter a conformidade com o SQL. Entretanto é opcional porque, diferentemente do SQL, esta funcionalidade não se aplica apenas às funções externas.
713
definição A cadeia de caracteres contendo a definição da função; o significado depende da linguagem. Pode ser o nome de uma função interna, o caminho para um arquivo objeto, um comando SQL, ou um texto escrito em uma linguagem procedural. arquivo_objeto, símbolo_de_vínculação
Esta forma da cláusula AS é utilizada para funções escritas na linguagem C carregáveis dinamicamente, quando o nome da função no código fonte na linguagem C não tem o mesmo nome da função SQL. A cadeia de caracteres arquivo_objeto é o nome do arquivo contendo o objeto carregável dinamicamente, e símbolo_de_vínculação é o símbolo de vinculação da função, ou seja, o nome da função no código fonte na linguagem C. Se o símbolo de vinculação for omitido, é assumido como tendo o mesmo nome da função SQL sendo definida. atributo A forma histórica de especificar informações opcionais sobre a função. Os seguintes atributos podem ser utilizados: isStrict
Equivalente a STRICT ou RETURNS NULL ON NULL INPUT isCachable isCachable é um equivalente obsoleto de IMMUTABLE; ainda é aceito por motivo de compatibilidade com versões anteriores.
Não há diferença entre letras minúsculas de maiúsculas nos nomes de atributos.
Observações Consulte a Seção 33.3 para obter mais informações sobre como escrever funções. A sintaxe tipo SQL completa é permitida para os argumentos de entrada e o valor retornado. Entretanto, alguns detalhes da especificação do tipo (por exemplo, o campo precisão para o tipo numeric) são de responsabilidade da implementação da função subjacente, sendo engolidos em silêncio (ou seja, não são reconhecidos nem exigidos) pelo comando CREATE FUNCTION. O PostgreSQL permite a sobrecarga de função, ou seja, o mesmo nome pode ser utilizado por várias funções diferentes, desde que possuam argumentos com tipos distintos. Entretanto, na linguagem C os nomes de todas as funções devem ser diferentes e, portanto, as funções na linguagem C sobrecarregadas devem possuir nomes diferentes (por exemplo, utilizando os tipos dos argumentos como parte do nome na linguagem C). Quando chamadas repetidas ao comando CREATE FUNCTION fazem referência ao mesmo arquivo objeto, o arquivo só é carregado uma vez. Para descarregar e recarregar o arquivo (talvez durante o desenvolvimento), deve ser usado o comando LOAD. Use o comando DROP FUNCTION para remover funções definidas pelo usuário. Todo apóstrofo (') ou contrabarra (\) presente na definição da função deve ser escrito duas vezes. Para poder criar uma função o usuário deve possuir o privilégio USAGE na linguagem.
Exemplos Exemplo 1. Somar dois números inteiros Abaixo está mostrado um exemplo simples para ajudar a começar. Para obter mais informações e exemplos veja a Seção 33.3. CREATE FUNCTION soma(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;
714
Nota: O exemplo abaixo foi escrito pelo tradutor, não fazendo parte do manual original.
Exemplo 2. Somar dias a uma data A seguir está mostrada uma função sobrecarregada para somar dias a uma data. Pode ser utilizada com os tipos de dado date, timestamp e timestamp with time zone. CREATE OR REPLACE FUNCTION soma_dias(date,integer) RETURNS date AS ' DECLARE nova_data date; BEGIN nova_data := $1 + $2; RETURN nova_data; END; ' LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION soma_dias(timestamp,integer) RETURNS timestamp AS ' DECLARE nova_data timestamp; hora interval; BEGIN hora := $1 - CAST($1 AS DATE); nova_data := CAST($1 AS DATE)+ $2; RETURN nova_data + hora; END; ' LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION soma_dias(timestamp with time zone,integer) RETURNS timestamp with time zone AS ' DECLARE nova_data timestamp with time zone; hora interval; BEGIN hora := $1 - CAST($1 AS DATE); nova_data := CAST($1 AS DATE)+ $2; RETURN nova_data + hora; END; ' LANGUAGE plpgsql;
Exemplos de utilização: => SELECT soma_dias(date '2004-07-16', 30); soma_dias -----------2004-08-15 (1 linha)
=> SELECT soma_dias(timestamp '2004-07-16 15:00:00', 30); soma_dias --------------------2004-08-15 15:00:00 (1 linha)
=> SELECT current_timestamp, soma_dias(current_timestamp, 30); timestamptz | soma_dias -------------------------------+------------------------------2005-02-15 21:29:05.403436-02 | 2005-03-17 21:29:05.403436-03 (1 linha)
715
Compatibilidade O comando CREATE FUNCTION está definido no SQL:1999 e posterior. A versão do PostgreSQL é semelhante mas não é totalmente compatível. Os atributos não são portáveis, nem as diferentes linguagens disponíveis o são.
Veja também ALTER FUNCTION, DROP FUNCTION, GRANT, LOAD, REVOKE, createlang
716
CREATE GROUP Nome CREATE GROUP — cria um grupo de usuários
Sinopse CREATE GROUP nome [ [ WITH ] >opção [ ... ] ] onde opção pode ser: SYSID id_grupo | USER nome_do_usuário [, ...]
Descrição O comando CREATE GROUP cria um grupo de usuários no agrupamento de bancos de dados. É necessário ser um superusuário do banco de dados para executar este comando. Deve ser usado o comando ALTER GROUP para incluir ou excluir usuários no grupo, e o comando DROP GROUP para remover um grupo.
Parâmetros nome O nome do grupo. id_grupo A cláusula SYSID pode ser utilizada para escolher o identificador de grupo do PostgreSQL para o novo grupo. Entretanto, sua utilização não é necessária. Se não for especificado, o valor do identificador mais alto atribuído a um grupo, acrescido de um, começando por 1, será utilizado por padrão. nome_do_usuário A lista dos usuários a serem incluídos no grupo. Os usuários devem existir.
Exemplos Criar um grupo vazio: CREATE GROUP colaboradores;
Criar um grupo com membros: CREATE GROUP vendas WITH USER jonas, marcela;
Compatibilidade Não existe o comando CREATE GROUP no padrão SQL. O conceito de “papéis” (roles) é semelhante ao de grupos.
717
CREATE INDEX Nome CREATE INDEX — cria um índice
Sinopse CREATE [ UNIQUE ] INDEX nome_do_índice ON tabela [ USING método ] ( { coluna | ( expressão ) } [ classe_de_operadores ] [, ...] ) [ WHERE predicado ]
Descrição O comando CREATE INDEX constrói o índice nome_do_índice na tabela especificada. Os índices são utilizados, principalmente, para melhorar o desempenho do banco de dados (embora a utilização não apropriada cause uma degradação de desempenho). Os campos chave para o índice são especificados como nomes de coluna ou, também, como expressões escritas entre parênteses. Podem ser especificados vários campos, se o método de índice suportar índices multicolunas. O campo de um índice pode ser uma expressão computada a partir dos valores de uma ou mais colunas da linha da tabela. Esta funcionalidade pode ser utilizada para obter acesso rápido aos dados baseado em alguma transformação dos dados básicos. Por exemplo, um índice computado como upper(col) permite a cláusula WHERE upper(col) = 'JIM' utilizar um índice. O PostgreSQL fornece os métodos de índice B-tree, R-tree, hash e GiST. O método de índice B-tree é uma implementação das B-trees de alta concorrência de Lehman-Yao. O método de índice R-tree implementa R-trees padrão utilizando o algoritmo de divisão quadrática (quadratic split) de Guttman. O método de índice hash é uma implementação do hash linear de Litwin 1 2 . Os usuários também podem definir seus próprios métodos de índice, mas é muito complicado. Quando a cláusula WHERE está presente, um índice parcial é criado. Um índice parcial é um índice contendo entradas apenas para uma parte da tabela, geralmente uma parte mais útil para indexar que o restante da tabela. Por exemplo, havendo uma tabela contendo tanto pedidos faturados quanto não faturados, onde os pedidos não faturados ocupam uma pequena parte da tabela, mas que é a parte mais usada, o desempenho pode ser melhorado criando um índice apenas para esta parte da tabela. Outra aplicação possível é utilizar a cláusula WHERE junto com UNIQUE para garantir a unicidade de um subconjunto dos dados da tabela. A expressão utilizada na cláusula WHERE pode referenciar apenas as colunas da tabela subjacente, mas pode usar todas as colunas, e não apenas as que estão sendo indexadas. Atualmente não são permitidas subconsultas e expressões de agregação na cláusula WHERE. As mesmas restrições se aplicam aos campos do índice que são expressões. Todas as funções e operadores utilizados na definição do índice devem ser “imutáveis” (immutable), ou seja, seus resultados devem depender somente de seus argumentos, e nunca de uma influência externa (como o conteúdo de outra tabela ou a hora atual). Esta restrição garante que o comportamento do índice é bem definido. Para utilizar uma função definida pelo usuário na expressão do índice ou na cláusula WHERE, a função deve ser marcada como IMMUTABLE na sua criação.
Parâmetros UNIQUE
Faz o sistema verificar valores duplicados na tabela quando o índice é criado, se existirem dados, e toda vez que forem adicionados dados. A tentativa de inserir ou de atualizar dados que resultem em uma entrada duplicada gera um erro.
718
nome_do_índice O nome do índice a ser criado. O nome do esquema não pode ser incluído aqui; o índice é sempre criado no mesmo esquema da tabela que este pertence. tabela O nome (opcionalmente qualificado pelo esquema) da tabela a ser indexada. método O nome do método a ser utilizado pelo índice. Pode ser escolhido entre btree, hash, rtree e gist. O método padrão é btree. coluna O nome de uma coluna da tabela. expressão Uma expressão baseada em uma ou mais colunas da tabela. A expressão geralmente deve ser escrita entre parênteses, conforme mostrado na sintaxe. Entretanto, os parênteses podem ser omitidos se a expressão tiver a forma de uma chamada de função. classe_de_operadores O nome de uma classe de operadores. Veja os detalhes abaixo. predicado A expressão de restrição para o índice parcial.
Observações Veja o Capítulo 11 para obter informações sobre quando os índices podem ser utilizados, quando não são utilizados, e em quais situações particulares podem ser úteis. Atualmente somente os métodos de índice B-tree e Gist suportam índices com mais de uma coluna. Por padrão podem ser especificadas até 32 colunas (este limite pode ser alterado na geração do PostgreSQL). Também atualmente somente B-tree suporta índices únicos. Uma classe de operadores pode ser especificada para cada coluna de um índice. A classe de operadores identifica os operadores a serem utilizados pelo índice para esta coluna. Por exemplo, um índice B-tree sobre inteiros de quatro bytes usaria a classe int4_ops; esta classe de operadores inclui funções de comparação para inteiros de quatro bytes. Na prática, a classe de operadores padrão para o tipo de dado da coluna é normalmente suficiente. O ponto principal em haver classes de operadores é que, para alguns tipos de dado, pode haver mais de uma ordenação que faça sentido. Por exemplo, pode-se desejar classificar o tipo de dado do número complexo tanto pelo valor absoluto quanto pela parte real, o que pode ser feito definindo duas classes de operadores para o tipo de dado e, então, selecionando a classe apropriada na construção do índice. Mais informações sobre classes de operadores estão na Seção 11.6 e na Seção 33.13. Deve ser utilizado o comando DROP INDEX para remover um índice.
Exemplos Para criar um índice B-tree para a coluna titulo na tabela filmes: CREATE UNIQUE INDEX unq_titulo ON filmes (titulo);
Compatibilidade O comando CREATE INDEX é uma extensão do PostgreSQL à linguagem. O padrão SQL não trata de índices.
Notas 1. Litwin, W. Linear hashing: A new tool for file and table addressing. In Proceedings of the 6th Conference on Very Large Databases, (New York, 1980}, 212-223. (N. do T.)
719
2. Witold Litwin: Linear Hashing: A new Tool for File and Table Addressing (http://swig.stanford.edu/pub/summaries/database/linhash.html) - Summary by: Steve Gribble and Armando Fox. (N. do T.)
720
CREATE LANGUAGE Nome CREATE LANGUAGE — cria uma linguagem procedural
Sinopse CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE nome HANDLER tratador_de_chamadas [ VALIDATOR função_de_validação ]
Descrição Utilizando o comando CREATE LANGUAGE, um usuário do PostgreSQL pode registrar uma nova linguagem procedural em um banco de dados do PostgreSQL. Depois, podem ser definidas funções e procedimentos de gatilhos nesta nova linguagem. O usuário deve possuir o privilégio de superusuário do PostgreSQL para poder registrar uma nova linguagem. O comando CREATE LANGUAGE associa o nome da linguagem ao tratador de chamadas (call handler) responsável pela execução das funções escritas nesta linguagem. Consulte a Seção 33.3 para obter mais informações sobre tratadores de chamada de linguagens. Observe que as linguagens procedurais são locais a cada banco de dados. Para tornar, por padrão, uma linguagem disponível para todos os bancos de dados, esta deve ser instalada no banco de dados template1.
Parâmetros TRUSTED TRUSTED especifica que o tratador de chamadas para a linguagem é seguro, ou seja, não oferece a um usuário sem privilégios qualquer funcionalidade para transpor as restrições de acesso. Se esta palavra chave for omitida ao registrar a linguagem, somente os usuários do PostgreSQL com privilégio de superusuário vão poder usar esta linguagem para criar novas funções. PROCEDURAL
Apenas informativo. nome O nome da nova linguagem procedural. Não existe distinção entre letras minúsculas e maiúsculas no nome da linguagem. O nome deve ser único entre todas as linguagens do banco de dados. Por compatibilidade com as versões anteriores, o nome pode ser escrito entre apóstrofos ('). HANDLER tratador_de_chamadas
O tratador_de_chamadas é o nome de uma função, previamente registrada, que será chamada para executar as funções escritas nesta linguagem procedural. O tratador de chamadas para a linguagem procedural deve ser escrito em uma linguagem compilada como a linguagem C, com a convenção de chamadas versão 1, registrada no PostgreSQL como uma função que não recebe nenhum argumento e retorna o tipo language_handler, que é um tipo usado apenas para identificar a função como tratadora de chamadas. VALIDATOR função_de_validação
A função_de_validação é nome de uma função, registrada previamente, que será chamada quando for criada uma nova função nesta linguagem para validar esta nova função. Se nenhuma função validadora for especificada, então a nova função não será verificada ao ser criada. A função validadora deve receber um argumento do tipo oid, que é o OID (identificador do objeto) da função a ser criada, e normalmente retorna void.
721
Tipicamente a função validadora inspeciona o corpo da função para verificar se a sintaxe está correta, mas também pode verificar outras propriedades da função como, por exemplo, a linguagem não poder tratar argumentos de determinados tipos. Para sinalizar erro a função validadora deve usar a função ereport(). O valor retornado pela função é ignorado.
Observações Normalmente, este comando não deve ser executado diretamente pelos usuários. Para as linguagens procedurais fornecidas na distribuição do PostgreSQL a aplicação createlang deve ser utilizada, porque esta aplicação também instala o tratador de chamadas correto; a aplicação createlang chama o comando CREATE LANGUAGE internamente. Nas versões do PostgreSQL anteriores a 7.3, era necessário declarar as funções tratadoras como retornando o tipo opaque, em vez de language_handler. Para permitir a carga de cópias de segurança antigas, o comando CREATE LANGUAGE aceita as funções declaradas como retornando opaque, mas mostra uma mensagem e muda para language_handler o tipo retornado declarado pela função. Use o comando CREATE FUNCTION para criar uma função. Use o comando DROP LANGUAGE, ou melhor ainda, a aplicação droplang, para excluir linguagens procedurais. O catálogo do sistema pg_language (veja a Seção 43.18) registra informações sobre as linguagens instaladas correntemente. A aplicação createlang possui uma opção para listar as linguagens instaladas. A definição de uma linguagem procedural não pode ser mudada após ter sido criada, com exceção dos privilégios. Para poder utilizar uma linguagem procedural, deve ser concedido o privilégio USAGE para o usuário. O aplicativo createlang concede, automaticamente, permissão para todos se a linguagem for sabidamente trusted.
Exemplos Os dois comandos mostrados abaixo, executados em seqüência, registram uma nova linguagem procedural e o tratador de chamadas associado: CREATE FUNCTION plsample_call_handler() RETURNS language_handler AS '$libdir/plsample' LANGUAGE C; CREATE LANGUAGE plsample HANDLER plsample_call_handler;
Compatibilidade O comando CREATE LANGUAGE é uma extensão do PostgreSQL.
Veja também ALTER LANGUAGE, CREATE FUNCTION, DROP LANGUAGE, GRANT, REVOKE, createlang, droplang
722
CREATE OPERATOR Nome CREATE OPERATOR — cria um operador
Sinopse CREATE OPERATOR nome ( PROCEDURE = nome_da_função [, LEFTARG = tipo_à_esquerda ] [, RIGHTARG = tipo_à_direita ] [, COMMUTATOR = comutador_do_operador ] [, NEGATOR = negador_do_operador ] [, RESTRICT = função_de_seletividade_da_restrição ] [, JOIN = função_de_seletividade_da_junção ] [, HASHES ] [, MERGES ] [, SORT1 = operador_de_ordenação_à_esquerda ] [, SORT2 = operador_de_ordenação_à_direita ] [, LTCMP = operador_menor_que ] [, GTCMP = operador_maior_que ] )
Descrição O comando CREATE OPERATOR define o novo operador, nome. O usuário que define o operador se torna seu dono. Se for fornecido o nome do esquema, então o operador será criado no esquema especificado, senão será criado no esquema corrente. O nome do operador é uma seqüência com até NAMEDATALEN-1 (63, por padrão) caracteres da seguinte lista: +-*/<>=~!@#%^&|`? Existem algumas restrições na escolha do nome: •
As seqüências -- e /* não podem ocorrer em nenhum lugar no nome do operador, uma vez que são consideradas início de comentário.
•
Um nome de operador multicaractere não pode terminar por + ou por -, a não ser que o nome também contenha pelo menos um destes caracteres: ~!@#%^&|`? Por exemplo, @- é um nome de operador permitido, mas *- não é. Esta restrição permite ao PostgreSQL analisar comandos em conformidade com o SQL sem requerer espaços entre os elementos (tokens).
O operador != é mapeado para <> na entrada e, portanto, estes dois nomes são sempre equivalentes. Com relação a LEFTARG e RIGHTARG, pelo menos um dos dois deve ser definido; para operadores binários os dois devem ser definidos. Para operadores unários direito somente LEFTARG deve ser definido, enquanto que para operadores unários esquerdo somente RIGHTARG deve ser definido. O procedimento nome_da_função deve ser previamente definido utilizando o comando CREATE FUNCTION, e deve estar definido para aceitar o número correto de argumentos (um ou dois) dos tipos indicados. As outras cláusulas são cláusulas de otimização de operador opcionais. Seus significados estão descritos na Seção 33.11.
Parâmetros nome O nome do operador a ser definido. Veja acima os caracteres permitidos. O nome pode ser qualificado pelo esquema como, por exemplo, CREATE OPERATOR meu_esquema.+ (...); caso não seja, o operador será criado no esquema corrente. Dois operadores no mesmo esquema podem possuir o mesmo nome se operarem sobre tipos de dado diferentes. Isto se chama sobrecarga (overload).
723
nome_da_função A função utilizada para implementar este operador. tipo_à_esquerda O tipo de dado do operando à esquerda do operador, se houver. Esta opção deve ser omitida em operadores unário esquerdo. tipo_à_direita O tipo de dado do operando à direita do operador, se houver. Esta opção deve ser omitida em operadores unário direito. comutador_do_operador O comutador deste operador. negador_do_operador O negador deste operador. função_de_seletividade_da_restrição A função que estima a seletividade da restrição para este operador. função_de_seletividade_da_junção A função que estima a seletividade da junção para este operador. HASHES
Indica que este operador pode suportar uma junção por hash. MERGES
Indica que este operador pode suportar uma junção por mesclagem. operador_de_ordenação_à_esquerda Se este operador puder suportar uma junção por mesclagem, o operador menor-que que classifica o tipo de dado à esquerda deste operador. operador_de_ordenação_à_direita Se este operador puder suportar uma junção por mesclagem, o operador menor-que que classifica o tipo de dado à direita deste operador. operador_menor_que Se este operador puder suportar uma junção por mesclagem, o operador menor-que que compara os tipos de dado de entrada deste operador. operador_maior_que Se este operador puder suportar uma junção por mesclagem, o operador maior-que que compara os tipos de dado de entrada deste operador. Para usar um nome de operador qualificado pelo esquema em comutador_do_operador, ou nos demais argumentos opcionais, deve ser utilizada a sintaxe de OPERATOR() como, por exemplo, COMMUTATOR = OPERATOR(meu_esquema.===) ,
Observações Consulte a Seção 33.11 para obter mais informações. Utilize o comando DROP OPERATOR para remover do banco de dados operadores definidos pelo usuário.
Exemplos O comando abaixo define um novo operador, area-equality (igualdade de área), para o tipo de dado box:
724
CREATE OPERATOR === ( LEFTARG = box, RIGHTARG = box, PROCEDURE = area_equal_procedure, COMMUTATOR = ===, NEGATOR = !==, RESTRICT = area_restriction_procedure, JOIN = area_join_procedure, HASHES, SORT1 = <<<, SORT2 = <<< -- Uma vez que os operadores de classificação foram fornecidos, -- MERGES está envolvido. -- LTCMP e GTCMP são assumidos como sendo < e >, respectivamente );
Compatibilidade O comando CREATE OPERATOR é uma extensão do PostgreSQL. O padrão SQL não trata de operadores definidos pelo usuário.
725
CREATE OPERATOR CLASS Nome CREATE OPERATOR CLASS — cria uma classe de operadores
Sinopse CREATE OPERATOR CLASS nome [ DEFAULT ] FOR TYPE tipo_de_dado USING método_de_índice AS { OPERATOR número_da_estratégia nome_do_operador [ ( tipo_do_operador, tipo_do_operador ) ] [ RECHECK ] | FUNCTION número_de_suporte nome_da_função (tipos_dos_argumentos [, ...] ) | STORAGE tipo_armazenado } [, ... ]
Descrição O comando CREATE OPERATOR CLASS cria uma classe de operadores. Uma classe de operadores define como um determinado tipo de dado pode ser usado em um índice. A classe de operadores especifica que certos operadores vão preencher determinados papéis, ou “estratégias”, para este tipo de dado e este método de índice. A classe de operadores também especifica os procedimentos de suporte a serem usados pelo método do índice quando a classe de operadores é selecionada para uma coluna do índice. Todos os operadores e funções usados por uma classe de operadores devem ser definidos antes da classe de operadores ser criada. Se o nome do esquema for fornecido, então a classe de operadores é criada no esquema especificado, senão é criada no esquema corrente. Duas classes de operadores no mesmo esquema podem ter o mesmo nome somente se forem para métodos de índice diferentes. O usuário que cria a classe de operadores se torna seu dono. Atualmente o usuário criador deve ser um superusuário; esta restrição é feita porque uma definição de classe de operadores errada pode confundir, ou mesmo derrubar, o servidor. Atualmente o comando CREATE OPERATOR CLASS não verifica se a definição da classe de operadores inclui todos os operadores e funções requeridos pelo método de índice. É responsabilidade do usuário definir uma classe de operadores válida. Veja a Seção 33.13 para obter mais informações.
Parâmetros nome O nome da classe de operadores a ser criada. O nome pode ser qualificado pelo esquema. DEFAULT
Se estiver presente, a classe de operadores se tornará a classe de operadores padrão para seu tipo de dado. No máximo uma classe de operadores pode ser a classe padrão para um determinado tipo de dado e método de índice. tipo_de_dado O tipo de dado de coluna que esta classe de operadores se destina. método_de_índice O nome do método de índice que esta classe de operadores se destina. número_da_estratégia O número da estratégia do método de índice para um operador associado com a classe de operadores.
726
nome_do_operador O nome (opcionalmente qualificado pelo esquema) de um operador associado com a classe de operadores. tipo_do_operador Os tipos de dado dos operandos de um operador, ou NONE indicando um operador unário-esquerdo ou unário-direito. Os tipos de dado dos operandos podem ser omitidos no caso usual, onde são iguais ao tipo de dado da classe de operadores. RECHECK
Se estiver presente, o índice para este operador é “lossy” 1 e, portanto, as linhas trazidas usando o índice devem ser verificadas outra vez para ver se realmente satisfazem a cláusula de qualificação envolvendo este operador. número_de_suporte O número do procedimento de suporte do método de índice para a função associada com a classe de operadores. nome_da_função O nome (opcionalmente qualificado pelo esquema) da função que é o procedimento de suporte do método de índice para a classe de operadores. tipos_dos_argumentos Os tipos de dado dos parâmetros da função. tipo_armazenado O tipo de dado realmente armazenado no índice. Geralmente é o mesmo tipo de dado da coluna, mas alguns métodos de índice (somente GIST no momento) permitem que seja diferente. A cláusula STORAGE deve ser omitida, a menos que o método de índice permita o uso de um tipo diferente. As cláusulas OPERATOR, FUNCTION e STORAGE podem ser escritas em qualquer ordem.
Exemplos O exemplo mostrado abaixo define uma classe de operadores de índice GiST para o tipo de dado _int4 (matriz de int4). Consulte contrib/intarray/ para ver o exemplo completo. CREATE OPERATOR CLASS gist__int_ops DEFAULT FOR TYPE _int4 USING gist AS OPERATOR 3 &&, OPERATOR 6 = RECHECK, OPERATOR 7 @, OPERATOR 8 ~, OPERATOR 20 @@ (_int4, query_int), FUNCTION 1 g_int_consistent (internal, _int4, int4), FUNCTION 2 g_int_union (bytea, internal), FUNCTION 3 g_int_compress (internal), FUNCTION 4 g_int_decompress (internal), FUNCTION 5 g_int_penalty (internal, internal, internal), FUNCTION 6 g_int_picksplit (internal, internal), FUNCTION 7 g_int_same (_int4, _int4, internal);
Compatibilidade O comando CREATE OPERATOR CLASS é uma extensão do PostgreSQL. Não existe o comando CREATE OPERATOR CLASS no padrão SQL.
Veja também ALTER OPERATOR CLASS, DROP OPERATOR CLASS
727
Notas 1. lossy — Termo que descreve um algoritmo de compressão que na verdade reduz a quantidade de informações nos dados, em vez de reduzir apenas o número de bits usados para representar esta informação. A informação perdida normalmente é removida porque é subjetivamente menos importante à qualidade dos dados (geralmente uma imagem ou som), ou porque pode ser recuperada razoavelmente por interpolação dos dados remanescentes. MPEG e JPEG são exemplos de técnicas de compressão com perdas. FOLDOC - Free On-Line Dictionary of Computing (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=lossy) (N. do T.)
728
CREATE RULE Nome CREATE RULE — cria uma regra de reescrita
Sinopse CREATE [ OR REPLACE ] RULE nome AS ON evento TO tabela [ WHERE condição ] DO [ INSTEAD ] { NOTHING | comando | ( comando ; comando ... ) }
Descrição O comando CREATE RULE cria uma regra aplicada à tabela ou visão especificada. O comando CREATE OR REPLACE RULE cria uma regra, ou substitui uma regra existente com mesmo nome, na tabela. O sistema de regras do PostgreSQL permite definir uma ação alternativa a ser realizada nas inclusões, atualizações ou exclusões em tabelas do banco de dados. Sem entrar em detalhes, uma regra faz com que comandos adicionais sejam executados quando um determinado comando é executado em uma determinada tabela. Diferentemente, a regra INSTEAD pode substituir um determinado comando por outro, ou mesmo fazer com que o comando não seja executado. As regras também são utilizadas para implementar as visões das tabelas. É importante perceber que a regra é, na realidade, um mecanismo de transformação de comando, ou uma macro de comando. A transformação acontece antes do início da execução do comando. Se, na verdade, for desejada uma operação que dispare de forma independente para cada linha física, provavelmente o que se deseja é um gatilho, e não uma regra. Mais informações sobre o sistema de regras podem ser obtidas no Capítulo 34. Atualmente, as regras ON SELECT devem ser regras INSTEAD incondicionais, e devem possuir ações consistindo de um único comando SELECT. Portanto, uma regra ON SELECT tem por efeito transformar a tabela em uma visão, cujo conteúdo visível são as linhas retornadas pelo comando SELECT da regra, em vez do que está armazenado na tabela (se houver alguma coisa). É considerado um estilo melhor usar o comando CREATE VIEW do que criar uma tabela real e definir uma regra ON SELECT para a mesma. É possível criar a ilusão de uma visão atualizável definindo regras ON INSERT, ON UPDATE e ON DELETE, ou qualquer subconjunto destas que seja suficiente para as finalidades desejadas, para substituir as ações de atualização na visão por atualizações apropriadas em outras tabelas. Existe algo a ser lembrado quando se tenta utilizar regras condicionais para atualização de visões: é obrigatório haver uma regra incondicional INSTEAD para cada ação que se deseja permitir na visão. Se a regra for condicional, ou não for INSTEAD, então o sistema continuará a rejeitar as tentativas de realizar a ação de atualização, porque acha que poderá acabar tentando realizar a ação sobre a tabela fictícia da visão em alguns casos. Se for desejado tratar todos os casos úteis por meio de regras condicionais, deve ser adicionada uma regra incondicional DO INSTEAD NOTHING para garantir que o sistema sabe que nunca será chamado para atualizar a tabela fictícia. Em seguida devem ser criadas as regras condicionais não-INSTEAD; nos casos onde se aplicam, se adicionam à ação padrão INSTEAD NOTHING.
Parâmetros nome O nome da regra a ser criada, devendo ser distinto do nome de qualquer outra regra para a mesma tabela. Havendo várias regras para a mesma tabela e mesmo tipo de evento, estas regras são aplicadas na ordem alfabética dos nomes. evento Evento é um entre SELECT, INSERT, UPDATE e DELETE.
729
tabela O nome (opcionalmente qualificado pelo esquema) da tabela ou da visão à qual a regra se aplica. condição Qualquer expressão condicional SQL (retornando boolean). A expressão condicional não pode fazer referência a nenhuma tabela, exceto NEW e OLD, e não pode conter funções de agregação. comando O comando ou comandos que compõem a ação da regra. Os comandos válidos são SELECT, INSERT, UPDATE, DELETE e NOTIFY.
Dentro da condição e do comando, os nomes especiais de tabela NEW e OLD podem ser usados para fazer referência aos valores na tabela referenciada. O NEW é válido nas regras ON INSERT e ON UPDATE, para fazer referência à nova linha sendo inserida ou atualizada. O OLD é válido nas regras ON UPDATE e ON DELETE, para fazer referência à linha existente sendo atualizada ou excluída.
Observações É necessário possuir o privilégio RULE na tabela para poder definir uma regra para a mesma. É muito importante tomar cuidado para evitar regras circulares. Por exemplo, embora as duas definições de regra abaixo sejam aceitas pelo PostgreSQL, o comando SELECT faz com que o PostgreSQL relate um erro, porque a consulta vai circular muitas vezes: CREATE RULE "_RETURN" AS ON SELECT TO t1 DO INSTEAD SELECT * FROM t2; CREATE RULE "_RETURN" AS ON SELECT TO t2 DO INSTEAD SELECT * FROM t1; SELECT * FROM t1;
Atualmente, se a ação da regra contiver um comando NOTIFY, este comando NOTIFY será executado incondicionalmente, ou seja, o NOTIFY será emitido mesmo não havendo nenhuma linha onde a regra se aplique. Por exemplo, em CREATE RULE me_notifique AS ON UPDATE TO minha_tabela DO NOTIFY minha_tabela; UPDATE minha_tabela SET nome = 'foo' WHERE id = 42;
um evento NOTIFY será enviado durante o UPDATE, haja ou não alguma linha que corresponda à condição id = 42. Esta é uma restrição da implementação que deverá estar corrigida em versões futuras.
Compatibilidade O comando CREATE RULE é uma extensão do PostgreSQL à linguagem, assim como todo o sistema de reescrita de comandos.
730
CREATE SCHEMA Nome CREATE SCHEMA — cria um esquema
Sinopse CREATE SCHEMA nome_do_esquema [ AUTHORIZATION nome_do_usuário ] [ elemento_do_esquema [ ... ] ] CREATE SCHEMA AUTHORIZATION nome_do_usuário [ elemento_do_esquema [ ... ] ]
Descrição O comando CREATE SCHEMA cria um esquema no banco de dados corrente. O nome do esquema deve ser distinto do nome de todos os outros esquemas existentes no banco de dados corrente. Um esquema é essencialmente um espaço de nomes: contém objetos nomeados (tabelas, tipos de dado, funções e operadores) cujos nomes podem ser iguais aos de outros objetos existentes em outros esquemas. Os objetos nomeados são acessados “qualificando” seus nomes usando o nome do esquema como prefixo, ou definindo um caminho de procura que inclua os esquemas desejados. Os objetos não qualificados são criados no esquema corrente (o primeiro do caminho de procura, que pode ser determinado pela função current_schema 1 ). Opcionalmente, o comando CREATE SCHEMA pode incluir subcomandos para criar objetos no novo esquema. Estes subcomandos são tratados, essencialmente, da mesma maneira como são tratados os comandos isolados executados após a criação do esquema, exceto que, se a cláusula AUTHORIZATION for usada, todos os objetos criados pertencerão a este usuário.
Parâmetros nome_do_esquema O nome do esquema a ser criado. Se for omitido, o nome do usuário será usado como o nome do esquema. nome_do_usuário O nome do usuário que será o dono do esquema. Se for omitido, será usado por padrão o usuário executando o comando. Somente os superusuários podem criar esquemas pertencentes a outros usuários. elemento_do_esquema Um comando SQL definindo um objeto a ser criado no esquema. Atualmente, somente as cláusulas CREATE TABLE, CREATE VIEW e GRANT são aceitas no comando CREATE SCHEMA. Os outros tipos de
objeto podem ser criados por comandos separados, após o esquema ter sido criado.
Observações Para criar um esquema, o usuário deve possuir o privilégio CREATE no banco de dados corrente (É claro que os superusuários não são afetados por esta exigência).
Exemplos Criar um esquema: CREATE SCHEMA meu_esquema;
Criar um esquema para o usuário antonio; o esquema também se chamará antonio: CREATE SCHEMA AUTHORIZATION antonio;
Criar um esquema e criar uma tabela e uma visão nele:
731
CREATE SCHEMA hollywood CREATE TABLE filmes (titulo text, lancamento date, premios text[]) CREATE VIEW premiados AS SELECT titulo, lancamento FROM filmes WHERE premios IS NOT NULL;
Observe que os subcomandos individuais não terminam por ponto-e-vírgula. Abaixo está mostrada uma forma equivalente para se obter o mesmo resultado: CREATE SCHEMA hollywood; CREATE TABLE hollywood.filmes (titulo text, lancamento date, premios text[]) CREATE VIEW hollywood.premiados AS SELECT titulo, lancamento FROM hollywood.filmes WHERE premios IS NOT NULL;
Compatibilidade O padrão SQL permite a cláusula DEFAULT CHARACTER SET no comando CREATE SCHEMA, bem como mais tipos de subcomandos que os aceitos atualmente pelo PostgreSQL. O padrão SQL especifica que os subcomandos presentes em CREATE SCHEMA podem estar em qualquer ordem. A implementação atual do PostgreSQL não trata todos os casos de referência à frente nos subcomandos; alguma vezes pode ser necessário reordenar os subcomandos para evitar referências à frente. De acordo com o padrão SQL, o dono do esquema sempre possui todos os objetos que este contém. O PostgreSQL permite que os esquemas contenham objetos pertencentes a outros usuários. Isto só acontece quando o dono do esquema concede o privilégio CREATE em seu esquema para algum outro usuário.
Veja também ALTER SCHEMA, DROP SCHEMA
Notas 1. Use o comando SELECT current_schema(); (N. do T.)
732
CREATE SEQUENCE Nome CREATE SEQUENCE — cria um gerador de seqüência
Sinopse CREATE [ TEMPORARY | TEMP ] [ MINVALUE valor_mínimo [ MAXVALUE valor_máximo [ START [ WITH ] início
SEQUENCE nome [ INCREMENT [ BY ] incremento ] | NO MINVALUE ] | NO MAXVALUE ] ] [ CACHE cache ] [ [ NO ] CYCLE ]
Descrição O comando CREATE SEQUENCE cria um gerador de números seqüenciais, que envolve a criação e a inicialização de uma nova tabela especial com uma única linha chamada nome. O usuário que executa o comando se torna o dono do gerador. Se um nome de esquema for fornecido, então a seqüência é criada no esquema especificado, senão é criada no esquema corrente. As seqüências temporárias são criadas em um esquema especial e, portanto, o nome do esquema não pode ser fornecido ao se criar uma seqüência temporária. O nome da seqüência deve ser distinto do nome de qualquer outra seqüência, tabela, índice ou visão no mesmo esquema. Após a seqüência ser criada, podem ser utilizadas as funções nextval, currval e setval para operar na seqüência. Estas funções estão documentadas na Seção 9.11. Embora não seja possível atualizar uma seqüência diretamente, pode ser feita uma consulta como SELECT * FROM nome;
para examinar os parâmetros e o estado atual da seqüência. Em particular, o campo last_value da seqüência mostra o último valor atribuído para qualquer sessão (É claro que este valor pode estar obsoleto no instante em que for exibido, se outras sessões estiverem chamando a função nextval).
Parâmetros TEMPORARY ou TEMP
Se for especificado, o objeto de seqüência é criado somente para esta sessão, sendo automaticamente removido ao término da sessão. Seqüências permanentes existentes não serão visíveis (na sessão) enquanto existirem seqüências temporárias com o mesmo nome, a não ser que sejam referenciadas por um nome qualificado pelo esquema. nome O nome (opcionalmente qualificado pelo esquema) da seqüência a ser criada. incremento A cláusula opcional INCREMENT BY incremento especifica o valor a ser adicionado ao valor corrente da seqüência para gerar o novo valor. Um valor positivo cria uma seqüência ascendente, enquanto um valor negativo cria uma seqüência descendente. O valor padrão é 1. valor_mínimo NO MINVALUE
A cláusula opcional MINVALUE valor_mínimo determina o valor mínimo que a seqüência pode gerar. Se esta cláusula não for fornecida, e se NO MINVALUE não for especificado, então são utilizados os valores padrão. Os valores padrão são 1 e -263-1 para seqüências ascendentes e descendentes, respectivamente.
733
valor_máximo NO MAXVALUE
A cláusula opcional MAXVALUE valor_máximo determina o valor máximo que a seqüência pode gerar. Se esta cláusula não for fornecida, e se NO MAXVALUE não for especificado, então são utilizados os valores padrão. Os valores padrão são 263-1 e -1 para seqüências ascendentes e descendentes, respectivamente. início A cláusula opcional START WITH início permite a seqüência iniciar com qualquer valor. O valor inicial padrão é o valor_mínimo para seqüências ascendentes, e o valor_máximo para seqüências descendentes. cache A cláusula opcional CACHE cache especifica quantos números da seqüência são previamente reservados e armazenados em memória para acesso mais rápido. O valor mínimo é 1 (somente um valor é gerado de cada vez, ou seja, sem cache), e este também é o valor padrão. CYCLE NO CYCLE
A opção CYCLE permite uma seqüência reiniciar quando atingir o valor_máximo ou o valor_mínimo, respectivamente. Se o limite for atingido, o próximo número gerado será o valor_mínimo ou o valor_máximo, respectivamente. Se NO CYCLE for especificado, toda chamada a nextval após a seqüência ter atingido seu valor máximo retorna um erro. Se nem CYCLE nem NO CYCLE for especificado, NO CYCLE é o padrão.
Observações Use o comando DROP SEQUENCE para remover uma seqüência. As seqüências são baseadas na aritmética do tipo bigint e, portanto, a faixa de valores não pode exceder a faixa de um número inteiro de 8 bytes (-9223372036854775808 a 9223372036854775807). Em algumas plataformas mais antigas, pode não haver suporte do compilador para números inteiros de 8 bytes e, neste caso, as seqüências utilizam a aritmética do tipo integer regular (faixa de valores de -2147483648 a +2147483647). Se for utilizada uma definição de cache maior que um, para um objeto de seqüência que será usado concorrentemente por várias sessões, podem ser obtidos resultados não esperados. Cada sessão reserva e armazena valores sucessivos da seqüência durante um acesso ao objeto de seqüência, e aumenta o valor de last_value do objeto de seqüência da forma apropriada. Então, as próximas cache-1 utilizações de nextval nesta sessão simplesmente retornam os valores reservados sem acessar o objeto de seqüência. Portanto, todos os números alocados, mas não utilizados pela sessão, são perdidos quando a sessão termina, produzindo “buracos” na seqüência. Além disso, embora se garanta que as várias sessões reservam valores distintos da seqüência, os valores podem ser gerados fora de seqüência quando são levadas em consideração todas as sessões. Por exemplo, definindo-se cache igual a 10, a sessão A pode reservar os valores 1..10 e retornar nextval=1, enquanto a sessão B pode reservar os valores 11..20 e retornar nextval=11 antes da sessão A ter gerado nextval=2. Portanto, com uma definição de cache igual a um é seguro assumir que os valores de nextval são gerados seqüencialmente; com uma definição de cache maior do que um apenas pode-se assumir que os valores de nextval são todos distintos, mas não que sejam gerados de forma inteiramente seqüencial. Também, o valor last_value reflete o último valor reservado por qualquer sessão, tenha ou não sido retornado por nextval. Outra consideração a ser feita é que a execução de setval neste tipo de seqüência não será percebida pelas outras sessões enquanto estas não utilizarem todos os valores reservados guardados no cache.
Exemplos Criar uma seqüência ascendente chamada serial, começando por 101: CREATE SEQUENCE serial START 101;
734
Selecionar o próximo valor desta seqüência: SELECT nextval('serial'); nextval --------114
Utilizar esta seqüência no comando INSERT: 1 INSERT INTO distribuidores VALUES (nextval('serial'), 'nada');
Atualizar o valor da seqüência após executar o comando COPY FROM: BEGIN; COPY distribuidores FROM 'arquivo_de_entrada'; SELECT setval('serial', max(id)) FROM distribuidores; END;
Compatibilidade O comando CREATE SEQUENCE é uma extensão do PostgreSQL à linguagem. Não existe o comando CREATE SEQUENCE no padrão SQL.
Notas 1. Oracle — No Oracle 9i nextval e currval são pseudocolunas e não funções, portanto é usado no comando INSERT, por exemplo, INSERT INTO orders VALUES (orders_seq.nextval, ... e INSERT INTO order_items VALUES (orders_seq.currval, ... Oracle9i SQL Reference Release 2 (9.2) - Part Number A96540-02 (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96540/sql_elements6a.htm) (N. do T.)
735
CREATE TABLE Nome CREATE TABLE — cria uma tabela
Sinopse CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE nome_da_tabela ( { nome_da_coluna tipo_de_dado [ DEFAULT expressão_padrão ] [ restrição_de_coluna [ ... ] ] | restrição_de_tabela | LIKE tabela_ancestral [ { INCLUDING | EXCLUDING } DEFAULTS ] } [, ... ] ) [ INHERITS ( tabela_ancestral [, ... ] ) ] [ WITH OIDS | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] onde restrição_de_coluna é: [ CONSTRAINT nome_da_restrição ] { NOT NULL | NULL | UNIQUE | PRIMARY KEY | CHECK (expressão) | REFERENCES tabela_referenciada [ ( coluna_referenciada ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE ação ] [ ON UPDATE ação ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] e restrição_de_tabela é: [ CONSTRAINT nome_da_restrição ] { UNIQUE ( nome_da_coluna [, ... ] ) | PRIMARY KEY ( nome_da_coluna [, ... ] ) | CHECK ( expressão ) | FOREIGN KEY ( nome_da_coluna [, ... ] ) REFERENCES tabela_referenciada [ ( coluna_referenciada [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE ação ] [ ON UPDATE ação ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
Descrição O comando CREATE TABLE cria uma tabela, inicialmente vazia, no banco de dados atual. O usuário que executa o comando se torna o dono da tabela. 1 Se o nome do esquema for fornecido (por exemplo, CREATE TABLE meu_esquema.minha_tabela ...) então a tabela é criada no esquema especificado, senão é criada no esquema corrente. As tabelas temporárias são criadas em um esquema especial e, portanto, o nome do esquema não pode ser especificado ao se criar tabelas temporárias. O nome da tabela deve ser distinto do nome de qualquer outra tabela, seqüência, índice ou visão no mesmo esquema. O comando CREATE TABLE também cria, automaticamente, o tipo de dado que representa o tipo composto correspondente a uma linha da tabela. Portanto, as tabelas não podem ter o mesmo nome de um tipo de dado existente no mesmo esquema. Uma tabela não pode ter mais de 1600 colunas (Na prática o limite efetivo é menor, por causa da restrição do comprimento das tuplas).
736
As cláusulas de restrição opcionais especificam as restrições (ou testes) que as linhas novas ou modificadas devem satisfazer para a operação de inserção ou de modificação ser aceita. Uma restrição é um objeto SQL que ajuda a definir o conjunto de valores válidos para a tabela de várias maneiras. Existem duas formas para definir restrições: restrições de tabela e restrições de coluna. A restrição de coluna é definida como parte da definição da coluna. A definição da restrição de tabela não é limitada a uma única coluna, podendo incluir mais de uma coluna. Toda restrição de coluna também pode ser escrita como restrição de tabela; a restrição de coluna é somente uma notação conveniente para ser usada quando a restrição afeta apenas uma coluna. 2
Parâmetros TEMPORARY ou TEMP
Se for especificado, a tabela é criada como sendo temporária. As tabelas temporárias são automaticamente removidas no final da sessão ou, opcionalmente, no fim da transação corrente (veja ON COMMIT abaixo). Tabelas permanentes existentes não serão visíveis na sessão corrente enquanto existirem tabelas temporárias com o mesmo nome, a não ser que sejam referenciadas por um nome qualificado pelo esquema. Todo índice criado em tabela temporária também é temporário. Opcionalmente, GLOBAL ou LOCAL podem ser escritos antes de TEMPORARY e de TEMP. Isto não faz qualquer diferença no PostgreSQL, mas veja Compatibilidade. nome_da_tabela O nome (opcionalmente qualificado pelo esquema) da tabela a ser criada. nome_da_coluna O nome da coluna a ser criada na nova tabela. tipo_de_dado O tipo de dado da coluna. Pode incluir especificadores de matriz (array). DEFAULT expressão_padrão
A cláusula DEFAULT atribui um valor de dado padrão para a coluna em cuja definição está presente. O valor pode ser qualquer expressão sem variável (variable-free) (subconsultas e referências cruzadas para outras colunas da mesma tabela não são permitidas). O tipo de dado da expressão padrão deve corresponder ao tipo de dado da coluna. A expressão padrão é utilizada em todas as operações de inserção que não especificam valor para a coluna. Se não houver valor padrão para a coluna, então o valor padrão é o valor nulo. LIKE tabela_ancestral [ { INCLUDING | EXCLUDING } DEFAULTS ]
A cláusula LIKE especifica a tabela da qual a nova tabela copia, automaticamente, todos os nomes de coluna, seus tipos de dado, e restrições de não-nulo. Ao contrário do INHERITS, a nova tabela e a tabela original ficam completamente separadas após o término da criação. Os dados inseridos na nova tabela não são refletidos na tabela ancestral. As expressões padrão existentes nas definições das colunas herdadas somente são incluídas se INCLUDING DEFAULTS for especificado. O padrão é não incluir as expressões padrão. INHERITS ( tabela_ancestral [, ... ] )
A cláusula opcional INHERITS (herda) especifica uma lista de tabelas das quais a nova tabela herda, automaticamente, todas as colunas. Se o mesmo nome de coluna existir em mais de uma tabela ancestral um erro é relatado, a menos que os tipo de dado das colunas seja o mesmo em todas as tabelas ancestrais. Não havendo conflito, então as colunas duplicadas são unidas para formar uma única coluna da nova tabela. Se a lista de nomes de colunas da nova tabela contiver um nome de coluna que também é herdado, da mesma forma o tipo de dado deve ser o mesmo das colunas herdadas, e a definição das colunas será unida em uma única coluna. Entretanto, declarações de colunas novas e herdadas com o mesmo nome não precisam especificar restrições idênticas: todas as restrições fornecidas em qualquer uma das declarações são unidas, sendo todas aplicadas à nova tabela. Se a nova tabela especificar, explicitamente, um valor
737
padrão para a coluna, este valor padrão substitui o valor padrão das declarações herdadas. Não sendo assim, toda tabela ancestral que especificar um valor padrão para a coluna deve especificar o mesmo valor, ou um erro será relatado. WITH OIDS WITHOUT OIDS
Esta cláusula opcional especifica se as linhas da nova tabela devem possuir OIDs (identificadores de objeto) atribuídos. O padrão é possuir OIDs (Se a nova tabela herdar de alguma tabela que possua OIDs, então a cláusula WITH OIDS é forçada mesmo que no comando esteja especificado WITHOUT OIDS). A especificação de WITHOUT OIDS permite ao usuário suprimir a geração dos OIDs para as linhas da tabela. Este procedimento pode valer a pena em tabelas grandes, porque reduz o consumo de OIDs e, portanto, retarda o reinício do contador OID de 32 bits. Quando o contador reinicia, não é mais possível supor sua unicidade, reduzindo muito sua utilidade. A especificação de WITHOUT OIDS também reduz o espaço necessário para armazenar a tabela em disco em 4 bytes para cada linha da tabela e, portanto, melhora o desempenho. CONSTRAINT nome_da_restrição
Um nome opcional para a restrição de coluna ou de tabela. Se não for especificado, o nome será gerado pelo sistema. NOT NULL
A coluna não pode conter valores nulos. NULL
A coluna pode conter valores nulos. Este é o padrão. Esta cláusula só está disponível para manter a compatibilidade com bancos de dados SQL fora do padrão. Sua utilização nas novas aplicações é desencorajada. UNIQUE (restrição de coluna) UNIQUE ( nome_da_coluna [, ... ] ) (restrição de tabela)
A restrição UNIQUE especifica que um grupo de uma ou mais colunas da tabela pode conter apenas valores únicos. O comportamento da restrição de unicidade de tabela é o mesmo da restrição de unicidade de coluna, mas com a capacidade adicional de envolver várias colunas. Para a finalidade de restrição de unicidade, valores nulos não são considerados iguais. Cada restrição de unicidade de tabela deve especificar um conjunto de colunas diferente do conjunto de colunas especificado por qualquer outra restrição de unicidade e, também, da chave primária definida para a tabela (Senão, seria apenas a mesma restrição declarada duas vezes). PRIMARY KEY (restrição de coluna) PRIMARY KEY ( nome_da_coluna [, ... ] ) (restrição de tabela)
A restrição de chave primária especifica que a coluna, ou colunas, da tabela podem conter apenas valores únicos (não duplicados) e não nulos. Tecnicamente a chave primária (PRIMARY KEY) é simplesmente uma combinação de unicidade (UNIQUE) com não nulo (NOT NULL), mas identificar um conjunto de colunas como chave primária também fornece metadados sobre o projeto do esquema, porque chaves primárias têm como conseqüência permitir que outras tabelas possam depender deste conjunto de colunas como identificador único para linhas. Somente pode ser especificada uma chave primária para cada tabela, seja como restrição de coluna ou como restrição de tabela. A restrição de chave primária deve especificar um conjunto de colunas diferente de outro conjunto de colunas especificado por uma restrição de unicidade definido para a mesma tabela. CHECK (expressão)
A cláusula CHECK especifica uma expressão, que produz um resultado booleano, que as linhas novas ou atualizadas devem satisfazer para a operação de inserção ou de atualização ser bem-sucedida. Uma restrição de verificação especificada como uma restrição de coluna deve fazer referência somente ao valor
738
desta coluna, enquanto uma expressão que aparece como uma restrição de tabela pode fazer referência a várias colunas. Atualmente as expressões CHECK não podem conter subconsultas, nem fazer referência a variáveis que não sejam colunas da linha corrente. REFERENCES tabela_referenciada [ ( coluna_referenciada ) ] [ MATCH tipo_de_correspondência ] [ ON DELETE ação ] [ ON UPDATE ação ] (restrição de coluna) FOREIGN KEY ( nome_da_coluna [, ... ] ) REFERENCES tabela_referenciada [ ( coluna_referenciada [, ... ] ) ] [ MATCH tipo_de_correspondência ] [ ON DELETE ação ] [ ON UPDATE ação ] (restrição de tabela)
Estas cláusulas especificam uma restrição de chave estrangeira, que requer que um grupo de uma ou mais colunas da nova tabela deva conter apenas valores correspondendo a valores nas colunas referenciadas de alguma linha da tabela referenciada. Se a coluna_referenciada for omitida, a chave primária da tabela_referenciada será utilizada. As colunas referenciadas devem ser colunas de uma restrição de unicidade ou de chave primária na tabela referenciada. Os valores inseridos nas colunas que fazem referência são comparados com os valores das colunas referenciadas da tabela referenciada utilizando o tipo de comparação especificado. Existem três tipos de comparação: MATCH FULL, MATCH PARTIAL e MATCH SIMPLE, que também é o padrão. MATCH FULL não permite uma coluna de uma chave estrangeira com várias colunas ser nula, a menos que todas as colunas da chave estrangeira sejam nulas. MATCH SIMPLE permite que algumas colunas da chave estrangeira sejam nulas, enquanto outras colunas da chave estrangeira não são nulas. MATCH PARTIAL ainda não está implementado. Além disso, quando os dados das colunas referenciadas são modificados, certas ações são realizadas nos dados das colunas desta tabela. A cláusula ON DELETE especifica a ação a ser realizada quando uma linha referenciada da tabela referenciada é excluída. Da mesma forma, a cláusula ON UPDATE especifica a ação a ser realizada quando uma coluna referenciada da tabela referenciada é atualizada para um novo valor. Se a linha for atualizada, mas a coluna referenciada não mudar de valor, nenhuma ação é executada. São possíveis as seguintes ações para cada cláusula: NO ACTION
Produz um erro indicando que a exclusão ou a atualização cria uma violação da restrição de chave estrangeira. Esta é a ação padrão. RESTRICT
O mesmo que NO ACTION, exceto que esta ação não será postergada mesmo que o restante da restrição for postergável e postergada. CASCADE
Exclui qualquer linha que faça referência à linha excluída, ou atualiza o valor da coluna que faz referência para o novo valor da coluna referenciada, respectivamente. SET NULL
Atribui o valor nulo às colunas que fazem referência. SET DEFAULT
Atribui o valor padrão às colunas que fazem referência. Se a coluna da chave primária for atualizada freqüentemente pode ser sensato adicionar um índice à coluna da chave estrangeira, para que as ações NO ACTION e CASCADE associadas com a coluna da chave estrangeira sejam realizadas de forma mais eficiente. DEFERRABLE NOT DEFERRABLE
Estas cláusulas controlam se a restrição pode ser postergada. Uma restrição que não pode ser postergada é verificada imediatamente após cada comando. A verificação das restrições postergáveis pode ser adiada para o final da transação (usando o comando SET CONSTRAINTS). NOT DEFERRABLE é o padrão.
739
Atualmente somente as restrições de chave estrangeira aceitam esta cláusula. Todos os outros tipos de restrição não são postergáveis. INITIALLY IMMEDIATE INITIALLY DEFERRED
Se uma restrição for postergável, esta cláusula especifica o instante padrão para verificar a restrição. Se a restrição for INITIALLY IMMEDIATE, então será verificada após cada instrução. Este é o padrão. Se a restrição for INITIALLY DEFERRED, então será verificada apenas no final da transação. O instante de verificação da restrição pode ser alterado pelo comando SET CONSTRAINTS. ON COMMIT
O comportamento das tabelas temporárias ao término do bloco de transação pode ser controlado utilizando ON COMMIT. As três opções são: PRESERVE ROWS
Nenhuma ação especial é realizada ao término da transação. Este é o comportamento padrão. DELETE ROWS
Todas as linhas da tabela temporária são excluídas ao término de cada bloco de transação. Essencialmente, um TRUNCATE é feito após cada efetivação. DROP
A tabela temporária é removida ao término do bloco de transação corrente.
Observações •
Sempre que a aplicação faz uso de OIDs para identificar linhas específicas de uma tabela, é recomendado criar uma restrição de unicidade para a coluna oid da tabela, para garantir que os OIDs na tabela realmente identificam unicamente uma linha, mesmo após o contador reiniciar. Evite supor que os OIDs são únicos entre tabelas; se for necessário um identificador único para todo o banco de dados, use a combinação de tableoid (OID de tabela) com o OID de linha para esta finalidade (é provável que as versões futuras do PostgreSQL utilizem contadores OID separados para cada tabela e, então, será necessário, e não opcional, incluir o tableoid para se ter um identificador único para todo o banco de dados). Dica: Não se recomenda utilizar WITHOUT OIDS para tabelas sem chave primária, porque sem OID e sem chave de dados única fica difícil identificar uma linha específica.
•
O PostgreSQL cria, automaticamente, um índice para cada restrição de unicidade e de chave primária para garantir a unicidade. Portanto, não é necessário criar explicitamente um índice para as colunas da chave primária (Consulte o comando CREATE INDEX para obter mais informações).
•
As restrições de unicidade e de chave primária não são herdadas na implementação corrente, tornando o comportamento da combinação de herança com restrição de unicidade um tanto disfuncional. 3
Exemplos Criar a tabela filmes e a tabela distribuidores: CREATE TABLE filmes ( cod_filme char(5) CONSTRAINT pk_filmes PRIMARY KEY, titulo varchar(40) NOT NULL, did integer NOT NULL, data_prod date, tipo varchar(10), duracao interval hour to minute ); CREATE TABLE distribuidores ( did integer PRIMARY KEY DEFAULT nextval('serial'), nome varchar(40) NOT NULL CHECK (nome <> '') );
740
Criar uma tabela com uma matriz de 2 dimensões: CREATE TABLE matriz2d_int ( matriz int[][] );
Definir uma restrição de unicidade para a tabela filmes. Restrições de unicidade usando a sintaxe de restrição de tabela podem ser definidas envolvendo uma ou mais colunas da tabela. CREATE TABLE filmes ( cod_filme char(5), titulo varchar(40), did integer, data_prod date, tipo varchar(10), duracao interval hour to minute, CONSTRAINT unq_data_prod UNIQUE(data_prod) );
Definir uma restrição de verificação, usando a sintaxe de restrição de coluna: CREATE TABLE distribuidores ( did integer CHECK (did > 100), nome varchar(40) );
Definir uma restrição de verificação, usando a sintaxe de restrição de tabela: CREATE TABLE distribuidores ( did integer, nome varchar(40) CONSTRAINT chk_dist CHECK (did > 100 AND nome <> '') );
Definir uma restrição de chave primária, usando a sintaxe de restrição de tabela, para a tabela filmes. As restrições de chave primária com sintaxe de restrição de tabela podem ser definidas usando uma ou mais colunas da tabela. CREATE TABLE filmes ( cod_filme char(5), titulo varchar(40), did integer, data_prod date, tipo varchar(10), duracao interval hour to minute, CONSTRAINT pk_filmes PRIMARY KEY(cod_filme,titulo) );
Definir a restrição de chave primária para a tabela distribuidores. Os dois exemplos abaixo são equivalentes, o primeiro utiliza a sintaxe de restrição de tabela, e o segundo utiliza a sintaxe de restrição de coluna. CREATE TABLE distribuidores ( did integer, nome varchar(40), PRIMARY KEY(did) ); CREATE TABLE distribuidores ( did integer PRIMARY KEY, nome varchar(40) );
741
O comando abaixo atribui uma constante literal como valor padrão para a coluna nome, faz o valor padrão da coluna did ser gerado pela seleção do próximo valor de um objeto de seqüência, e faz o valor padrão da coluna data_mod ser o momento em que a linha foi inserida. CREATE TABLE distribuidores ( nome varchar(40) DEFAULT 'Luso Filmes', did integer DEFAULT nextval('seq_distribuidores'), data_mod timestamp DEFAULT current_timestamp );
Definir duas restrições de coluna NOT NULL na tabela distribuidores, sendo que uma delas recebe um nome fornecido: CREATE TABLE distribuidores ( did integer CONSTRAINT nao_nulo NOT NULL, nome varchar(40) NOT NULL );
Definir uma restrição de unicidade para a coluna nome: CREATE TABLE distribuidores ( did integer, nome varchar(40) UNIQUE );
O comando acima é equivalente ao mostrado abaixo, especificado como uma restrição de tabela: CREATE TABLE distribuidores ( did integer, nome varchar(40), UNIQUE(nome) );
Compatibilidade O comando CREATE TABLE está em conformidade com o SQL-92 e com um subconjunto do SQL:1999, com as exceções listadas abaixo. Tabelas temporárias Embora a sintaxe de CREATE TEMPORARY TABLE se pareça com a do padrão SQL, o efeito não é o mesmo. No padrão as tabelas temporárias são definidas apenas uma vez, passando a existir automaticamente (começando com um conteúdo vazio) para todas as sessões que necessitarem destas. Em vez disso, o PostgreSQL requer que cada sessão execute seu próprio comando CREATE TEMPORARY TABLE para cada tabela temporária a ser utilizada, permitindo que sessões diferentes usem o mesmo nome de tabela temporária para finalidades diferentes, enquanto que a abordagem do padrão restringe todas as instâncias de um determinado nome de tabela temporária terem a mesma estrutura de tabela. A definição do padrão para o comportamento de tabelas temporárias é amplamente ignorado. O comportamento do PostgreSQL neste ponto é semelhante ao de vários outros bancos de dado SQL. A distinção feita pelo padrão entre tabelas temporárias globais e locais não está presente no PostgreSQL, uma vez que esta distinção depende do conceito de módulos, que o PostgreSQL não possui. Por motivo de compatibilidade, o PostgreSQL aceita as palavras chave GLOBAL e LOCAL na declaração da tabela temporária, mas estas não produzem efeito. A cláusula ON COMMIT para as tabelas temporárias também lembra o padrão SQL, mas possui algumas diferenças. Se a cláusula ON COMMIT for omitida, o padrão SQL especifica que o comportamento padrão deve ser ON COMMIT DELETE ROWS. Entretanto, o comportamento padrão no PostgreSQL é ON COMMIT PRESERVE ROWS. A opção ON COMMIT DROP não existe no padrão SQL.
742
Restrições de verificação de coluna O padrão SQL estabelece que as restrições de coluna CHECK só podem fazer referência à coluna onde estão aplicadas; somente a restrição CHECK de tabela pode fazer referência a várias colunas. O PostgreSQL não obriga o cumprimento desta restrição; as restrições de coluna e de tabela são tratadas da mesma maneira. “Restrição” NULL A “restrição” NULL (na verdade uma não restrição) é uma extensão do PostgreSQL ao padrão SQL incluída para manter a compatibilidade com alguns outros sistemas de banco de dados (e por simetria com a restrição NOT NULL). Uma vez que este é o padrão para qualquer coluna, sua presença é desnecessária. Herança Heranças múltiplas por meio da cláusula INHERITS é uma extensão do PostgreSQL à linguagem. O SQL:1999 (mas não o SQL-92) define herança única utilizando uma sintaxe diferente e semânticas diferentes. O estilo de herança do SQL:1999 ainda não é suportado pelo PostgreSQL. Identificadores de Objeto (Object IDs) O conceito de OIDs (identificadores de objeto) do PostgreSQL não é padrão. Tabelas sem coluna O PostgreSQL permite a criação de tabelas sem colunas (por exemplo, CREATE TABLE foo();). Isto é uma extensão ao padrão SQL, que não permite tabelas com zero coluna. As tabelas sem coluna não são muito úteis, mas se não forem permitidas criam um caso especial para o comando ALTER TABLE DROP COLUMN e, por isso, parece mais simples ignorar esta restrição contida na especificação.
Veja também ALTER TABLE, DROP TABLE
Notas 1. A tabela é uma coleção ordenada de uma ou mais colunas e uma coleção não ordenada de zero ou mais linhas. Cada linha possui, para cada coluna, exatamente um valor do tipo de dado desta coluna. (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.) 2. A restrição de tabela é uma restrição de integridade associada a uma única tabela base. A restrição de tabela é uma entre restrição de unicidade, restrição de chave primária, restrição referencial ou restrição de verificação. A restrição de unicidade especifica uma ou mais colunas da tabela como colunas únicas. A restrição de unicidade é satisfeita se, e somente se, não houverem duas linhas da tabela com os mesmos valores não-nulos nas colunas únicas. A restrição de chave primária é a restrição de unicidade que especifica PRIMARY KEY. A restrição de chave primária é satisfeita se, e somente se, não houverem duas linhas da tabela com os mesmos valores não-nulos nas colunas únicas, e nenhum dos valores da coluna ou colunas especificadas for o valor nulo. A restrição referencial especifica uma ou mais colunas como colunas que fazem referência, e as colunas referenciadas correspondentes em alguma (não necessariamente distinta) tabela base, referida como tabela referenciada. Estas colunas referenciadas são colunas únicas de alguma restrição de unicidade da tabela referenciada. A restrição referencial está sempre satisfeita se, para toda linha da tabela que faz referência, os valores das colunas que fazem referência são iguais àqueles das colunas referenciadas correspondentes de alguma linha da tabela referenciada. Entretanto, se estiverem presentes valores nulos a satisfação da integridade referencial depende do tratamento especificado para os nulos (conhecido como o tipo de correspondência). Podem ser especificadas ações referenciais para determinar que alterações devem ser feitas na tabela que faz referência se, de outra forma, uma alteração na tabela referenciada causasse a violação da restrição referencial. Uma restrição de verificação de tabela especifica uma condição de procura. A restrição é violada se o resultado da condição de procura for falso para qualquer linha da tabela (mas não se for desconhecido). (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
743
2. disfunção — dificuldade ou problema de funcionamento. PRIBERAM - Língua Portuguesa On-Line (http://www.priberam.pt/dlpo/dlpo.aspx) (N. do T.)
744
CREATE TABLE AS Nome CREATE TABLE AS — cria uma tabela a partir dos resultados de uma consulta
Sinopse CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE nome_da_tabela [ (nome_da_coluna [, ...] ) ] AS consulta
Descrição O comando CREATE TABLE AS cria uma tabela e a carrega com dados computados pelo comando SELECT, ou por um comando EXECUTE que executa um comando SELECT preparado. As colunas da tabela possuem os nomes e tipos de dado associados às colunas da saída do comando SELECT (exceto que é possível mudar os nomes das colunas fornecendo uma lista explícita de novos nomes de colunas). O comando CREATE TABLE AS possui alguma semelhança com a criação de uma visão, mas na realidade é bastante diferente: este comando cria a nova tabela e executa a consulta apenas uma vez para fazer a carga inicial da nova tabela. A nova tabela não terá conhecimento das mudanças posteriores ocorridas nas tabelas de origem da consulta. Contrastando com este comportamento, a visão executa novamente o comando SELECT que a define sempre que uma consulta é realizada.
Parâmetros TEMPORARY ou TEMP
Se for especificado, a tabela é criada como uma tabela temporária. Consulte o comando CREATE TABLE para obter mais detalhes. nome_da_tabela O nome (opcionalmente qualificado pelo esquema) da tabela a ser criada. nome_da_coluna O nome da coluna na nova tabela. Se os nomes das colunas não forem fornecidos, são obtidos a partir dos nomes das colunas produzidas pela consulta. Se a tabela for criada a partir de um comando EXECUTE, a lista de nomes de colunas não pode ser especificada. consulta Um comando de consulta (ou seja, um comando SELECT ou um comando EXECUTE que executa um comando SELECT preparado). Consulte SELECT ou EXECUTE, respectivamente, para obter a descrição da sintaxe permitida.
Observações Este comando é funcionalmente equivalente ao SELECT INTO mas é preferível, porque é menos propenso a ser confundido com outros usos da sintaxe do comando SELECT ... INTO.
Compatibilidade Este comando tem por base uma funcionalidade do Oracle. Não existe nenhum comando com funcionalidade equivalente no padrão SQL. Entretanto, uma combinação de CREATE TABLE com INSERT ... SELECT pode ser utilizada para produzir o mesmo resultado com um pouco mais de esforço.
Veja também CREATE TABLE, CREATE VIEW, EXECUTE, SELECT, SELECT INTO
745
CREATE TRIGGER Nome CREATE TRIGGER — cria um gatilho
Sinopse CREATE TRIGGER nome { BEFORE | AFTER } { evento [ OR ... ] } ON tabela [ FOR [ EACH ] { ROW | STATEMENT } ] EXECUTE PROCEDURE nome_da_função ( argumentos )
Descrição O comando CREATE TRIGGER cria um gatilho. O gatilho fica associado à tabela especificada e executa a função especificada nome_da_função quando determinados eventos ocorrem. 1 2 O gatilho pode ser especificado para disparar antes de tentar realizar a operação na linha (antes das restrições serem verificadas e o comando INSERT, UPDATE ou DELETE ser tentado), ou após a operação estar completa (após as restrições serem verificadas e o INSERT, UPDATE ou DELETE ter completado). Se o gatilho for disparado antes do evento, o gatilho pode evitar a operação para a linha corrente, ou modificar a linha sendo inserida (para as operações de INSERT e UPDATE somente). Se o gatilho for disparado após o evento, todas as mudanças, incluindo a última inserção, atualização ou exclusão, são “visíveis” para o gatilho. Se o gatilho estiver marcado como FOR EACH ROW então é chamado uma vez para cada linha modificada pela operação. Por exemplo, um comando DELETE afetando 10 linhas faz com que todos os gatilhos ON DELETE da relação de destino sejam chamados 10 vezes, uma vez para cada linha excluída. Por outro lado, um gatilho marcado como FOR EACH STATEMENT somente executa uma vez para uma determinada operação, a despeito de quantas linhas sejam modificadas; em particular, uma operação que não modifica nenhuma linha ainda assim resulta na execução de todos os gatilhos FOR EACH STATEMENT aplicáveis. Se vários gatilhos do mesmo tipo estão definidos para o mesmo evento, estes são disparados na ordem alfabética de seus nomes 3 . O SELECT não modifica nenhuma linha e, portanto, não é possível criar gatilhos para SELECT. Regras e visões são mais apropriadas neste caso. Consulte o Capítulo 35 para obter mais informações sobre gatilhos.
Parâmetros nome O nome a ser dado ao novo gatilho, devendo ser distinto do nome de qualquer outro gatilho para a mesma tabela. BEFORE AFTER
Determina se a função é chamada antes ou depois do evento. evento Um entre INSERT, UPDATE ou DELETE; especifica o evento que dispara o gatilho. Vários eventos podem ser especificados utilizando OR. tabela O nome (opcionalmente qualificado pelo esquema) da tabela que o gatilho se destina.
746
FOR EACH ROW FOR EACH STATEMENT
Especifica se o procedimento do gatilho deve ser disparado uma vez para cada linha afetada pelo evento do gatilho, ou apenas uma vez para a declaração SQL. Se nenhum dos dois for especificado, FOR EACH STATEMENT é usado por padrão. nome_da_função Uma função fornecida pelo usuário, declarada como não recebendo nenhum argumento e retornando o tipo trigger, que é executada quando o gatilho dispara. argumentos Uma lista opcional de argumentos, separados por vírgula, passada para a função quando o gatilho é executado. Os argumentos são constantes cadeia de caracteres literais. Também podem ser escritos nomes simples e constantes numéricas, mas estes são convertidos em cadeias de caracteres. Por favor, verifique como os argumentos do gatilho são acessados dentro da função, na descrição da linguagem de implementação da função de gatilho; pode ser diferente dos argumentos das função normais.
Observações Para poder criar um gatilho em uma tabela, o usuário deve possuir o privilégio TRIGGER na tabela. Nas versões do PostgreSQL anteriores a 7.3, era necessário declarar as funções dos gatilhos como retornando o tipo opaque em vez de trigger. Para permitir a carga das cópias de segurança antigas, o comando CREATE TRIGGER aceita funções declaradas como retornando opaque, mas mostra uma mensagem e muda para trigger o tipo retornado declarado pela função. Deve ser utilizado o comando DROP TRIGGER para remover um gatilho.
Exemplos A Seção 35.4 contém um exemplo completo.
Compatibilidade A declaração CREATE TRIGGER do PostgreSQL implementa um subconjunto do padrão SQL:1999 (O padrão SQL-92 não trata de gatilhos). As seguintes funcionalidades estão faltando: •
O padrão SQL:1999 permite que os gatilhos sejam disparados pela atualização de colunas específicas (por exemplo, AFTER UPDATE OF col1, col2).
•
O padrão SQL:1999 permite definir outros nomes (aliases) para as linhas e tabelas “velhas” e “novas” a serem utilizados na definição da ação do gatilho (por exemplo, CREATE TRIGGER ... ON nome_da_tabela REFERENCING OLD ROW AS algum_nome NEW ROW AS outro_nome ...). Uma vez que o PostgreSQL permite que os procedimentos dos gatilhos sejam escritos em qualquer linguagem definida pelo usuário, o acesso aos dados é tratado na forma específica da linguagem.
•
O PostgreSQL somente permite a execução de uma função definida pelo usuário para a ação do gatilho. O padrão SQL:1999 permite a execução de vários outros comandos SQL, como o CREATE TABLE, para a ação do gatilho. Esta limitação é fácil de ser superada criando uma função definida pelo usuário para executar os comandos desejados.
O SQL:1999 especifica que os vários gatilhos devem ser disparados na ordem da data de criação. O PostgreSQL usa a ordem dos nomes, que foi considerada mais conveniente para se trabalhar. A capacidade de especificar várias ações para um único gatilho utilizando OR é uma extensão do PostgreSQL ao padrão SQL.
Veja também CREATE FUNCTION, ALTER TRIGGER, DROP TRIGGER
747
Notas 1. O gatilho, embora não seja definido como um componente da tabela base, é um objeto associado a uma única tabela base. O gatilho especifica o evento de gatilho, o momento de ação do gatilho, e uma ou mais ações engatilhadas. O evento de gatilho especifica que ação na tabela base deverá causar as ações engatilhadas. O evento de gatilho é um entre INSERT, DELETE e UPDATE. O momento de ação do gatilho especifica se a ação do gatilho será efetuada BEFORE (antes) ou AFTER (após) o evento do gatilho. A ação engatilhada é um procedimento SQL ou BEGIN ATOMIC, seguido por uma ou mais <declaração de procedimento SQL>, seguido por END. (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
2. Oracle — Os gatilhos de banco de dados permitem definir e obrigar regras de integridade, mas os gatilhos de banco de dados não são a mesma coisa que restrições de integridade. Entre outras coisas, o gatilho de banco de dados não verifica os dados já carregados na tabela. Portanto, é altamente recomendado que o uso de gatilhos de banco de dados seja feito somente quanto as regras de integridade referencial não puderem ser obrigadas através de restrições de integridade. Introduction to the Oracle Server (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96524/c01_02intro.htm#45920) (N. do T.) 3. Oracle — Embora os gatilhos de tipos diferentes sejam disparados em uma ordem específica, não há garantia que os gatilhos do mesmo tipo para o mesmo comando sejam disparados em uma ordem específica. Por exemplo, pode ser que os os gatilhos BEFORE row para o mesmo comando UPDATE nem sempre sejam disparados na mesma ordem. As aplicações devem ser projetadas de forma que não dependam da ordem de disparo de vários gatilhos do mesmo tipo. Triggers (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96524/c18trigs.htm#3585) (N. do T.)
748
CREATE TYPE Nome CREATE TYPE — cria um tipo de dado
Sinopse CREATE TYPE nome AS ( nome_do_atributo tipo_de_dado [, ... ] ) CREATE TYPE nome ( INPUT = função_de_entrada, OUTPUT = função_de_saída [ , RECEIVE = função_de_recepção ] [ , SEND = função_de_envio ] [ , INTERNALLENGTH = { comprimento_interno | VARIABLE } ] [ , PASSEDBYVALUE ] [ , ALIGNMENT = alinhamento ] [ , STORAGE = armazenamento ] [ , DEFAULT = padrão ] [ , ELEMENT = elemento ] [ , DELIMITER = delimitador ] )
Descrição O comando CREATE TYPE registra um novo tipo de dado para uso no banco de dados corrente. O usuário que define o tipo se torna o seu dono. Se o nome do esquema for fornecido, então o tipo será criado no esquema especificado, senão será criado no esquema corrente. O nome do tipo deve ser distinto do nome de qualquer tipo ou domínio existente no mesmo esquema (como as tabelas possuem tipos de dado associados, o nome do tipo também deve ser distinto do nome de qualquer tabela existente no mesmo esquema). Tipos Compostos A primeira forma de CREATE TYPE cria um tipo composto. O tipo composto é especificado por uma lista de nomes de atributo e tipos de dado. É essencialmente a mesma coisa que o tipo de uma linha de tabela, mas o uso de CREATE TYPE evita a necessidade de criar uma tabela real quando tudo o que se deseja é apenas definir um tipo. Um tipo composto autônomo é útil como argumento ou tipo retornado por uma função. Tipos Base A segunda forma do comando CREATE TYPE cria um novo tipo base (tipo escalar). Os parâmetros podem estar em qualquer ordem, e não apenas na ordem mostrada acima, e a maior parte é opcional. Requer o registro de duas ou mais funções (utilizando CREATE FUNCTION) antes de definir o tipo. As funções de suporte função_de_entrada e função_de_saída são requeridas, enquanto as funções função_de_recepção e função_de_envio são opcionais. Geralmente estas funções precisam ser codificadas em C ou em outra linguagem de baixo nível. A função_de_entrada converte a representação textual externa do tipo na representação interna utilizada pelos operadores e funções definidos para o tipo. A função_de_saída realiza a transformação inversa. A função de entrada pode ser declarada como recebendo um argumento do tipo cstring, ou recebendo três argumentos dos tipos cstring, oid e integer. O primeiro argumento é o texto de entrada como uma cadeia de caracteres C, o segundo argumento é o OID do tipo do elemento no caso de ser um tipo matriz, e o terceiro é o typmod da coluna de destino, se for conhecido. A função de entrada deve retornar um valor do próprio tipo de dado. A função de saída pode ser declarada como recebendo um argumento do novo tipo de dado, ou como
749
recebendo dois argumentos dos quais o segundo é do tipo oid. O segundo argumento é novamente o OID do tipo do elemento da matriz para tipos matriz. A função de saída deve ter um retorno do tipo cstring. A função_de_recepção opcional converte a representação binária externa do tipo para a representação interna. Se esta função não for fornecida, o tipo não pode participar de entrada binária. A representação binária deve ser escolhida para ser de baixo custo converter para a forma interna, e ao mesmo tempo razoavelmente portável (Por exemplo, os tipos de dado inteiro padrão utilizam a ordem de byte de rede como sendo a representação binária externa, enquanto a representação interna está na ordem de byte nativa da máquina). A função de recepção deve realizar uma verificação adequada para garantir que o valor seja válido. A função de recepção pode ser declarada como recebendo um argumento do tipo internal, ou dois argumentos dos tipos internal e oid. Deve retornar um valor do próprio tipo de dado (O primeiro argumento é um ponteiro para o buffer StringInfo, que armazena a cadeia de bytes recebida; o segundo argumento opcional é o OID do tipo do elemento no caso de ser um tipo matriz). Da mesma maneira, a função_de_envio opcional converte da representação interna para a representação binária externa. Se esta função não for fornecida, o tipo não pode participar de saída binária. A função de envio pode ser declarada como recebendo um argumento do novo tipo de dado, ou como recebendo dois argumentos dos quais o segundo é do tipo oid. O segundo argumento é novamente o OID do tipo do elemento da matriz para tipos matriz. A função de envio deve possuir um retorno do tipo bytea. Neste ponto podemos estar querendo saber como as funções de entrada e de saída podem ser declaradas possuindo resultados ou argumentos do novo tipo, se devem ser criadas antes que o novo tipo possa ser criado. A resposta é que a função de entrada deve ser criada primeiro, depois a função de saída (e as funções binárias de entrada e de saída, se for desejado) e, finalmente, o tipo de dado. O PostgreSQL vê primeiro o nome do novo tipo de dado como tipo retornado pela função de entrada, e cria um tipo de “abrigo”, que é simplesmente uma entrada no catálogo do sistema, e vincula a definição da função de entrada ao tipo de abrigo. Da mesma maneira, as outras funções são vinculadas ao (agora já existente) tipo de abrigo. Por último, o comando CREATE TYPE substitui a entrada de abrigo com a definição completa do tipo, e o novo tipo poderá ser usado. Enquanto os detalhes da representação interna do novo tipo são conhecidos somente pelas funções de entrada e de saída e por outras funções criadas pelo usuário para trabalhar com o tipo, existem várias propriedades da representação interna que devem ser declaradas para o PostgreSQL. A mais importante destas é o comprimento_interno. Os tipos de dado base podem ser de comprimento fixo e, neste caso, o comprimento_interno é um inteiro positivo, ou de comprimento variável, indicado pela definição do comprimento_interno como VARIABLE (Internamente isto é representado definindo typlen como -1). A representação interna de todos os tipos de comprimento variável devem começar por um inteiro de 4 bytes fornecendo o comprimento total deste valor do tipo. O sinalizador opcional PASSEDBYVALUE indica que os valores deste tipo de dado são passados por valor, e não por referência. Não é possível passar por valor tipos cuja representação interna seja maior do que o tamanho do tipo Datum (4 bytes na maioria das máquinas, e 8 bytes em poucas). O parâmetro alinhamento especifica o alinhamento de armazenamento requerido por este tipo de dado. Os valores permitidos igualam-se ao alinhamento nas fronteiras de 1, 2, 4 ou 8 bytes. Observe que os tipos de comprimento variável devem ter um alinhamento de pelo menos 4, porque contêm, necessariamente, um int4 como seu primeiro componente. O parâmetro armazenamento permite selecionar estratégias de armazenamento para tipos de dado de comprimento variável (somente é permitido plain para os tipos de comprimento fixo). plain especifica que os dados deste tipo são sempre armazenado em-linha e não comprimidos. extended especifica que primeiro o sistema tentará comprimir um valor de dado longo e, depois, movê-lo para fora da linha da tabela principal se ainda permanecerem muito longo. external permite mover os valores para fora da tabela principal, mas o sistema não tentará comprimi-los. main permite a compressão, mas desencoraja mover o valor para fora da tabela principal (os itens de dado com esta estratégia de armazenamento só são movidos para fora da tabela principal se não houver outra maneira de fazer a linha caber, mas têm mais preferência para serem mantidos na tabela principal do que os itens extended e external). Pode ser especificado um valor padrão, quando se deseja que as colunas com este tipo de dado tenham como padrão algo diferente do valor nulo. O valor padrão é especificado pela palavra chave DEFAULT; este padrão pode ser substituído por uma cláusula DEFAULT explícita anexada a uma determinada coluna.
750
Para indicar que o tipo é uma matriz, deve ser especificado o tipo dos elementos da matriz utilizando a palavra chave ELEMENT. Por exemplo, para definir uma matriz de inteiros de 4 bytes (int4), deve ser especificado ELEMENT = int4. Mais detalhes sobre tipos matriz são mostrados abaixo. Para indicar o delimitador a ser usado entre os valores na representação externa das matrizes deste tipo, podese definir delimitador como um caractere específico. O delimitador padrão é a vírgula (,). Observe que o delimitador está associado com o tipo do elemento da matriz, e não com a própria matriz. Tipos matriz Sempre que um tipo de dado base definido pelo usuário é criado, o PostgreSQL cria automaticamente um tipo matriz (array) associado, cujo nome consiste no nome do tipo base prefixado pelo caractere sublinhado. O analisador compreende esta convenção de nome, e traduz as requisições para colunas do tipo foo[] em requisições para o tipo _foo. O tipo matriz criado implicitamente é de comprimento variável e usa as funções de entrada e saída nativas array_in e array_out. Pode ser perguntado, com razão, por que existe a opção ELEMENT se o sistema produz o tipo matriz correto automaticamente. O único caso onde é útil utilizar ELEMENT é quando se constrói um tipo de comprimento fixo que é internamente uma matriz de componentes idênticos, e deseja-se que estes componentes sejam acessados diretamente por índices, além de qualquer outra operação que se planeje fornecer para este tipo como um todo. Por exemplo, o tipo name permite que os elementos char que o constituem sejam acessados desta forma. Um tipo point 2-D pode permitir que os dois números que o compõe sejam acessados como point[0] e point[1]. Observe que esta praticidade somente funciona em tipos de comprimento fixo cuja forma interna seja exatamente uma seqüência de campos idênticos de comprimento fixo. Para permitir o uso de índices, um tipo de comprimento variável deve possuir a representação interna generalizada usada por array_in e array_out. Por razões históricas (ou seja, claramente errado mas muito tarde para mudar) os índices dos tipos matriz de comprimento fixo começam por zero, em vez de começar por um como no caso matrizes de comprimento variável.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) do tipo a ser criado. nome_do_atributo O nome de um atributo (coluna) para o tipo composto. tipo_de_dado O nome de um tipo de dado existente que será uma coluna do tipo composto. função_de_entrada O nome da função que converte os dados da forma textual externa para a forma interna. função_de_saída O nome da função que converte os dados da forma interna do tipo para a forma textual externa. função_de_recepção O nome da função que converte os dados da forma binária externa do tipo para a forma interna. função_de_envio O nome da função que converte os dados da forma interna do tipo para a forma binária externa. comprimento_interno Uma constante numérica que especifica o comprimento em bytes da representação interna do novo tipo. O padrão é assumir como sendo de comprimento variável. alinhamento O alinhamento de armazenamento requerido por este tipo de dado. Se for especificado, deve ser char, int2, int4 ou double; o padrão é int4.
751
armazenamento A estratégia de armazenamento para este tipo de dado. Se for especificado, deve ser plain, external, extended ou main; o padrão é plain.
padrão O valor padrão para este tipo de dado. Se for omitido, o padrão é nulo. elemento O tipo sendo criado é uma matriz (array); especifica o tipo dos elementos da matriz. delimitador O caractere delimitador a ser usado entre os valores nas matrizes (arrays) feitas deste tipo.
Observações Os nomes de tipo definidos pelo usuário não podem começar pelo caractere sublinhado (_), e só podem ter 62 caracteres de comprimento (ou, de modo geral, NAMEDATALEN-2, em vez dos NAMEDATALEN-1 caracteres permitidos para os outros nomes). Os nomes de tipo começados por sublinhado são reservados para os nomes de tipo matriz criados internamente. Nas versões do PostgreSQL anteriores a 7.3, era costume evitar criar um tipo “abrigo” substituindo as referências à frente da função para o nome do tipo usando o pseudotipo opaque. Os argumentos e resultados cstring também tinham que ser declarados como opaque antes da versão 7.3. Para permitir a carga de cópias de segurança antigas, o comando CREATE TYPE aceita funções declaradas como retornando opaque, mas mostra uma mensagem e muda a declaração da função para usar o tipo correto.
Exemplos Este exemplo cria um tipo composto e o utiliza na definição de uma função: CREATE TYPE compfoo AS (f1 int, f2 text); CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, fooname FROM foo' LANGUAGE SQL;
Este exemplo cria o tipo de dado base box e, em seguida, o utiliza na definição da tabela: CREATE TYPE box ( INTERNALLENGTH = 16, INPUT = my_box_in_function, OUTPUT = my_box_out_function ); CREATE TABLE myboxes ( id integer, description box );
Se a estrutura interna de box fosse uma matriz de quatro elementos float4, poderia ter sido usado CREATE TYPE box ( INTERNALLENGTH = 16, INPUT = my_box_in_function, OUTPUT = my_box_out_function, ELEMENT = float4 );
o que permitiria acessar o valor de um componente de box através de índice. Fora isso, o tipo se comporta do mesmo modo que o anterior. Este exemplo cria um tipo objeto grande e o utiliza na definição de uma tabela: CREATE TYPE bigobj ( INPUT = lo_filein, OUTPUT = lo_fileout,
752
INTERNALLENGTH = VARIABLE ); CREATE TABLE big_objs ( id integer, obj bigobj );
Outros exemplos, incluindo funções de entrada e de saída, podem ser encontrados no Capítulo 33.
Compatibilidade Este comando CREATE TYPE é uma extensão do PostgreSQL. Existe um comando CREATE TYPE no SQL:1999 e posterior que é bastante diferente nos detalhes.
Veja também CREATE FUNCTION, DROP TYPE
753
CREATE USER Nome CREATE USER — cria uma conta de usuário do banco de dados
Sinopse CREATE USER nome [ [ WITH ] opção [ ... ] ] onde opção pode ser:
| | | | |
SYSID uid [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'senha' CREATEDB | NOCREATEDB CREATEUSER | NOCREATEUSER IN GROUP nome_do_grupo [, ...] VALID UNTIL 'data_hora'
Descrição O comando CREATE USER adiciona um novo usuário ao agrupamento de bancos de dados do PostgreSQL. Consulte o Capítulo 17 e o Capítulo 19 para obter mais informações sobre o gerenciamento de usuários e autenticação. Apenas os superusuários do banco de dados podem usar este comando.
Parâmetros nome O nome do usuário. uid A cláusula SYSID pode ser utilizada para escolher o identificador de usuário do PostgreSQL do novo usuário. Normalmente não é necessário, mas pode ser útil se for necessário recriar o dono de um objeto que ficou órfão. Se não for especificado, será utilizado por padrão o maior identificador de usuário atribuído acrescido de um (com mínimo de 100). senha Define a senha do usuário. Se não se pretende utilizar autenticação por senha esta opção pode ser omitida, mas o usuário não poderá mais se conectar se for decidido mudar para autenticação por senha. A senha poderá ser definida ou mudada posteriormente através do comando ALTER USER. ENCRYPTED UNENCRYPTED
Estas palavras chave controlam se a senha é armazenada criptografada, ou não, nos catálogos do sistema (se nenhuma das duas for especificada, o comportamento padrão é determinado pelo parâmetro de configuração PASSWORD_ENCRYPTION). Se a cadeia de caracteres da senha já estiver criptografada no formato MD5, então a cadeia de caracteres é armazenada como está, independentemente de ENCRYPTED ou UNENCRYPTED ser especificado(porque o sistema não pode descriptografar a cadeia de caracteres criptografada contendo a senha). Esta funcionalidade permite a restauração de senhas criptografadas efetuadas por uma operação de dump/restore. Observe que clientes antigos podem não possuir suporte para o mecanismo de autenticação MD5, necessário para trabalhar com senhas armazenadas criptografadas.
754
CREATEDB NOCREATEDB
Estas cláusulas definem a permissão para o usuário criar banco de dados. Se CREATEDB for especificado, o usuário sendo definido terá permissão para criar seus próprios bancos de dados. Se NOCREATEDB for especificado, nega-se ao usuário a permissão para criar banco de dados. Se esta cláusula for omitida, NOCREATEDB será utilizado por padrão. CREATEUSER NOCREATEUSER
Estas cláusulas determinam se o usuário pode ou não criar novos usuários. CREATEUSER também torna o usuário um superusuário, o qual pode substituir todas as restrições de acesso. Se não for especificada, NOCREATEUSER é o padrão. nome_do_grupo O nome de um grupo existente onde o usuário será incluído como um novo membro. Podem ser especificados nomes de vários grupos. data_hora A cláusula VALID UNTIL define uma data e hora após a qual a senha do usuário não é mais válida. Se esta cláusula for omitida, a conta será válida para sempre.
Observações Deve ser usado o comando ALTER USER para mudar os atributos de um usuário, e DROP USER para remover um usuário. Deve se usado ALTER GROUP para adicionar ou remover usuários de grupos. O PostgreSQL inclui o programa createuser que possui a mesma funcionalidade do CREATE USER (na verdade, chama este comando), mas pode ser executado a partir da linha de comando.
Exemplos Criar um usuário sem senha: CREATE USER jonas;
Criar um usuário com senha: CREATE USER manuel WITH PASSWORD 'jw8s0F4';
Criar um usuário com uma senha válida até o fim de 2004. Após o primeiro segundo de 2005 a senha não será mais válida. CREATE USER miriam WITH PASSWORD 'jw8s0F4' VALID UNTIL '2005-01-01';
Criar uma conta onde o usuário pode criar bancos de dados: CREATE USER manuel WITH PASSWORD 'jw8s0F4' CREATEDB;
Compatibilidade O comando CREATE USER é uma extensão do PostgreSQL. O padrão SQL deixa a definição de usuários para a implementação.
Veja também ALTER USER, DROP USER, createuser
755
CREATE VIEW Nome CREATE VIEW — cria uma visão
Sinopse CREATE [ OR REPLACE ] VIEW nome [ ( nome_da_coluna [, ...] ) ] AS consulta
Descrição O comando CREATE VIEW cria uma visão. A visão não é materializada fisicamente. Em vez disso, a consulta é executada toda vez que a visão é referenciada em uma consulta. 1 O comando CREATE OR REPLACE VIEW é semelhante, mas se já existir uma visão com o mesmo nome então esta é substituída. Uma visão somente pode ser substituída por uma nova consulta que produza um conjunto idêntico de colunas (ou seja, colunas com mesmos nomes e tipos de dado). Se for fornecido o nome do esquema (por exemplo, CREATE VIEW meu_esquema.minha_visao ...) então a visão será criada no esquema especificado, senão será criada no esquema corrente. O nome da visão deve ser distinto do nome de qualquer outra visão, tabela, seqüência ou índice no mesmo esquema.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da visão a ser criada. nome_da_coluna Uma lista opcional de nomes a serem usados para as colunas da visão. Se não for fornecida, os nomes das colunas são determinados a partir da consulta. consulta Uma consulta (ou seja, um comando SELECT) que gera as colunas e linhas da visão. Consulte o comando SELECT para obter mais informações sobre as consultas válidas.
Observações Atualmente, as visões são somente para leitura: o sistema não permite inserção, atualização ou exclusão em uma visão. É possível obter o efeito de uma visão atualizável criando regras que reescrevem as inserções, etc. na visão como ações apropriadas em outras tabelas. Para obter mais informações consulte o comando CREATE RULE. Deve ser utilizado o comando DROP VIEW para remover uma visão. Tome cuidado para que os nomes e os tipos das colunas da visão sejam atribuídos da maneira desejada. Por exemplo, CREATE VIEW vista AS SELECT 'Hello World';
é ruim por dois motivos: o nome padrão da coluna é ?column?, e o tipo de dado padrão da coluna é unknown. Se for desejado um literal cadeia de caracteres no resultado da visão deve ser utilizado algo como CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
O acesso às tabelas referenciadas pela visão é determinado pelas permissões do dono da visão. Entretanto, as funções chamadas pela visão são tratadas da mesma maneira como se tivessem sido chamadas diretamente pela consulta que utiliza a visão. Portanto, o usuário da visão deve possuir permissão para chamar todas as funções utilizadas pela visão.
756
Exemplos Criar uma visão mostrando todos os filmes de comédia: CREATE VIEW comedias AS SELECT * FROM filmes WHERE tipo = 'Comédia';
Compatibilidade O padrão SQL especifica algumas funcionalidades adicionais para o comando CREATE VIEW: CREATE VIEW nome [ ( coluna [, ...] ) ] AS consulta [ WITH [ CASCADE | LOCAL ] CHECK OPTION ]
As cláusulas opcionais para o comando SQL completo são: CHECK OPTION
Esta opção está associada às visões atualizáveis. Todos os comandos INSERT e UPDATE na visão são verificados para garantir que os dados satisfazem às condições que definem a visão (ou seja, os novos dados devem ser visíveis através da visão). Se as condições não forem satisfeitas, a atualização será rejeitada. LOCAL
Verifica a integridade nesta visão. CASCADE
Verifica a integridade nesta visão e em todas as visões dependentes. CASCADE é assumido se nem CASCADE nem LOCAL forem especificados.
O comando CREATE OR REPLACE VIEW é uma extensão do PostgreSQL à linguagem.
Notas 1. A visão (estritamente, a definição da visão) é uma consulta nomeada, que pode para muitas finalidades ser utilizada da mesma maneira que uma tabela base. Seu valor é o resultado da avaliação da consulta. (ISOANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
757
DEALLOCATE Nome DEALLOCATE — remove um comando preparado
Sinopse DEALLOCATE [ PREPARE ] nome
Descrição O comando DEALLOCATE é utilizado para remover um comando SQL previamente preparado. Se o comando preparado não for removido explicitamente, então será removido quando a sessão terminar. Para obter mais informações sobre comandos preparados consulte o comando PREPARE.
Parâmetros PREPARE
Esta palavra chave é ignorada. nome O nome do comando preparado a ser removido.
Compatibilidade O padrão SQL inclui o comando DEALLOCATE, mas apenas para uso na linguagem SQL incorporada (embedded).
758
DECLARE Nome DECLARE — define um cursor
Sinopse DECLARE nome [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FOR consulta [ FOR { READ ONLY | UPDATE [ OF coluna [, ...] ] } ]
Descrição O comando DECLARE permite o usuário criar cursores, que podem ser utilizados para trazer, de cada vez, um pequeno número de linhas de uma consulta grande. Os cursores podem retornar dados tanto no formato texto quanto binário usando o comando FETCH. Cursores normais retornam dados no formato texto, o mesmo produzido pelo comando SELECT. Como os dados são armazenados nativamente no formato binário, o sistema necessita realizar uma conversão para gerar o formato texto. Como a informação chega no formato texto, a aplicação cliente pode precisar convertê-la para o formato binário para manipulá-la. Além disso, dados no formato texto geralmente possuem um tamanho maior que no formato binário. Os cursores binários retornam os dados na representação binária, que pode ser manipulada mais facilmente. Entretanto, se a intenção for exibir os dados na forma de texto, trazê-los na forma de texto reduz um pouco o esforço no lado cliente. Como exemplo, se uma consulta retornar o valor “um” de uma coluna com tipo de dado inteiro, será recebida a cadeia de caracteres 1 com o cursor padrão, enquanto que com um cursor binário será retornado um campo de 4 bytes contendo a representação interna do valor (na ordem de byte “big-endian” 1 ). Os cursores binários devem ser usados com cuidado. Muitas aplicações, incluindo o psql, não estão preparadas para tratar cursores binários e esperam que os dados cheguem no formato texto. Nota: Quando a aplicação cliente utiliza o protocolo “consulta estendida” (extended query) para executar o comando FETCH, a mensagem Bind do protocolo especifica se os dados devem retornar no formato texto ou binário. Esta escolha substitui a forma como o cursor foi definido. Por isso o conceito de cursor binário fica obsoleto ao se utilizar o protocolo “consulta estendida” — todo cursor pode ser tratado tanto como texto ou binário.
Parâmetros nome O nome do cursor a ser criado. BINARY
Faz o cursor retornar os dados no formato binário em vez do formato texto. INSENSITIVE
Indica que os dados trazidos pelo cursor não devem ser afetados pelas atualizações feitas nas tabelas subjacentes ao cursor, enquanto o cursor existir. No PostgreSQL, todos os cursores são insensíveis; atualmente esta palavra chave não produz efeito, estando presente por motivo de compatibilidade com o padrão SQL. SCROLL NO SCROLL SCROLL (rolar) especifica que o cursor pode ser utilizado para trazer linhas de uma maneira não seqüencial (por exemplo, para trás). Dependendo da complexidade do plano de execução da consulta,
759
especificar SCROLL pode impor uma penalidade de desempenho no tempo de execução da consulta. NO SCROLL especifica que o cursor não pode ser utilizado para trazer linhas de uma maneira não seqüencial. WITH HOLD WITHOUT HOLD WITH HOLD especifica que o cursor pode continuar sendo utilizado após a transação que o criou ter sido efetivada com sucesso. WITHOUT HOLD especifica que o cursor não pode ser utilizado fora da transação que o criou. Se nem WITHOUT HOLD nem WITH HOLD for especificado, WITHOUT HOLD é o padrão.
consulta O comando SELECT que produz as linhas a serem retornadas pelo cursor. Consulte o comando SELECT para obter mais informações sobre consultas válidas. FOR READ ONLY FOR UPDATE FOR READ ONLY indica que o cursor será utilizado no modo somente-leitura. FOR UPDATE indica que o cursor será utilizado para atualizar tabelas. Uma vez que atualizações por cursor não são suportadas pelo PostgreSQL no momento, especificar FOR UPDATE causa uma mensagem de erro, e especificar FOR READ ONLY não produz efeito.
coluna Colunas a serem atualizadas pelo cursor. Uma vez que atualizações por cursor não são suportadas pelo PostgreSQL no momento, a cláusula FOR UPDATE provoca uma mensagem de erro. As palavras chave BINARY, INSENSITIVE e SCROLL podem estar em qualquer ordem.
Observações A menos que WITH HOLD seja especificado, o cursor criado por este comando poderá ser utilizado apenas dentro da transação corrente. Portanto, DECLARE sem WITH HOLD não possui utilidade fora do bloco de transação: o cursor existe apenas até o término da instrução. Por esse motivo, o PostgreSQL relata um erro se este comando for utilizado fora de um bloco de transação. Devem ser utilizados os comandos BEGIN, COMMIT e ROLLBACK para definir um bloco de transação. Se WITH HOLD for especificado, e a transação que criou o cursor for efetivada com sucesso, o cursor pode continuar sendo acessado pelas transações seguintes na mesma sessão (Mas se a transação que o criou for interrompida, o cursor é removido). O cursor criado com WITH HOLD é fechado quando um comando CLOSE explícito é executado para o cursor, ou quando a sessão termina. Na implementação atual, as linhas representadas por um cursor mantido são copiadas para um arquivo temporário, ou para uma área de memória, para permanecerem disponíveis para as transações seguintes. A opção SCROLL deve ser especificada ao se definir um cursor utilizado para trazer para trás. Isto é requerido pelo padrão SQL. Entretanto, para compatibilidade com as versões anteriores, o PostgreSQL permite trazer para trás sem a opção SCROLL, se o plano da consulta do cursor for simples o suficiente para que nenhum trabalho extra seja necessário para isto. Entretanto, aconselha-se aos desenvolvedores de aplicação a não confiar na utilização de trazer para trás a partir de um cursor que não tenha sido criado com a opção de SCROLL. Se NO SCROLL for especificado, então trazer para trás não é permitido em qualquer caso. O padrão SQL somente trata de cursores na linguagem SQL incorporada. O servidor PostgreSQL não implementa o comando OPEN para cursores; o cursor é considerado aberto ao ser declarado. Entretanto o ECPG, o pré-processador do PostgreSQL para a linguagem SQL incorporada, suporta as convenções de cursor do padrão SQL, incluindo as que envolvem as instruções DECLARE e OPEN.
Exemplos Para declarar um cursor: DECLARE liahona CURSOR FOR SELECT * FROM filmes;
Veja no comando FETCH mais exemplos de utilização de cursor.
760
Compatibilidade O padrão SQL permite cursores somente na linguagem SQL incorporada e nos módulos. O PostgreSQL permite que o cursor seja utilizado interativamente. O padrão SQL permite que os cursores atualizem os dados das tabelas. Todos os cursores do PostgreSQL são somente para leitura. Os cursores binários são uma extensão do PostgreSQL.
Notas 1. big-endian — uma arquitetura de computadores na qual, em uma representação numérica com vários bytes, o byte mais significativo possui o menor endereço (a palavra é armazenada com o “maior-fimprimeiro”). FOLDOC - Free On-Line Dictionary of Computing (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=big-endian) (N. do T.)
761
DELETE Nome DELETE — exclui linhas de uma tabela
Sinopse DELETE FROM [ ONLY ] tabela [ WHERE condição ]
Descrição O comando DELETE exclui da tabela especificada as linhas que satisfazem a cláusula WHERE. Se a cláusula WHERE estiver ausente, o efeito produzido é a exclusão de todas as linhas da tabela. O resultado é uma tabela válida, porém vazia. Dica: O comando TRUNCATE é uma extensão do PostgreSQL que fornece um mecanismo mais rápido para excluir todas as linha da tabela.
Por padrão, o comando DELETE exclui linhas da tabela especificada e de todas as suas descendentes. Se for desejado excluir linhas apenas da tabela especificada, deve ser utilizada a cláusula ONLY. É necessário possuir o privilégio DELETE na tabela para excluir linhas da mesma, assim como o privilégio SELECT para todas as tabelas cujos valores são lidos pela condição.
Parâmetros tabela O nome (opcionalmente qualificado pelo esquema) de uma tabela existente. condição Uma expressão de valor, que retorna um valor do tipo boolean, que determina as linhas a serem excluídas.
Saídas Ao terminar bem-sucedido, o comando DELETE retorna uma linha de fim de comando na forma DELETE contador
O contador é o número de linhas excluídas. Se contador for igual a 0, então não há linhas correspondendo à condição (isto não é considerado um erro).
Exemplos Excluir todos os filmes, exceto os musicais: DELETE FROM filmes WHERE tipo <> 'Musical';
Esvaziar a tabela filmes: DELETE FROM filmes;
Compatibilidade Este comando está em conformidade com o padrão SQL.
762
DROP AGGREGATE Nome DROP AGGREGATE — remove uma função de agregação
Sinopse DROP AGGREGATE nome ( tipo ) [ CASCADE | RESTRICT ]
Descrição O comando DROP AGGREGATE remove uma função de agregação existente. Para executar este comando o usuário corrente deve ser o dono da função de agregação.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma função de agregação existente. tipo O tipo de dado do argumento da função de agregação, ou * se a função aceitar qualquer tipo de dado. CASCADE
Exclui automaticamente os objetos que dependem da função de agregação. RESTRICT
Recusa excluir a função de agregação caso existam objetos dependentes da mesma. Este é o padrão.
Exemplos Para remover a função de agregação minha_media para o tipo de dado integer: DROP AGGREGATE minha_media(integer);
Compatibilidade Não existe o comando DROP AGGREGATE no padrão SQL.
Veja também ALTER AGGREGATE, CREATE AGGREGATE
763
DROP CAST Nome DROP CAST — remove uma conversão de tipo de dado
Sinopse DROP CAST (tipo_de_origem AS tipo_de_destino) [ CASCADE | RESTRICT ]
Descrição O comando DROP CAST remove uma conversão de tipo de dado previamente definida. Para poder remover uma conversão de tipo de dado é necessário ser o dono do tipo de dado de origem ou de destino. São os mesmos privilégios necessários para criar uma conversão de tipo de dado.
Parâmetros tipo_de_origem O nome do tipo de dado de origem da conversão. tipo_de_destino O nome do tipo de dado de destino da conversão. CASCADE RESTRICT
Estas palavras chave não produzem nenhum efeito, porque não existem dependências para conversões de tipo de dado.
Exemplos Para remover a conversão do tipo text para o tipo int: DROP CAST (text AS int);
Compatibilidade O comando DROP CAST está em conformidade com o padrão SQL.
Veja também CREATE CAST
764
DROP CONVERSION Nome DROP CONVERSION — remove uma conversão de codificação
Sinopse DROP CONVERSION nome [ CASCADE | RESTRICT ]
Descrição O comando DROP CONVERSION remove uma conversão de codificação definida anteriormente. É necessário ser o dono da conversão para poder removê-la.
Parâmetros nome O nome da conversão de codificação. O nome da conversão pode ser qualificado pelo esquema. CASCADE RESTRICT
Estas palavras chave não produzem nenhum efeito, porque não há dependências em conversões de codificação.
Exemplos Para remover a conversão de codificação chamada minha_conversao: DROP CONVERSION minha_conversao;
Compatibilidade Não existe o comando DROP CONVERSION no padrão SQL.
Veja também ALTER CONVERSION, CREATE CONVERSION
765
DROP DATABASE Nome DROP DATABASE — remove um banco de dados
Sinopse DROP DATABASE nome
Descrição O comando DROP DATABASE remove um banco de dados. Remove as entradas no catálogo para o banco de dados e remove o diretório contendo os dados. Pode ser executado apenas pelo dono do banco de dados. Também, não pode ser executado se você ou alguma outra pessoa estiver conectado ao banco de dados a ser removido; se conecte ao template1 ou a qualquer outro banco de dados para executar este comando. O comando DROP DATABASE não pode ser desfeito. Utilize com cuidado!
Parâmetros nome O nome do banco de dados a ser removido.
Observações O comando DROP DATABASE não pode ser executado dentro de um bloco de transação. Este comando não pode ser executado enquanto conectado ao banco de dados de destino. Portanto, é mais conveniente utilizar a aplicação dropdb, que é um script englobando este comando.
Compatibilidade Não existe o comando DROP DATABASE no padrão SQL.
Veja também CREATE DATABASE
766
DROP DOMAIN Nome DROP DOMAIN — remove um domínio
Sinopse DROP DOMAIN nome [, ...]
[ CASCADE | RESTRICT ]
Descrição O comando DROP DOMAIN remove um domínio. Somente o dono do domínio pode removê-lo.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de um domínio existente. CASCADE
Remove automaticamente os objetos que dependem do domínio (como colunas de tabelas). RESTRICT
Recusa excluir o domínio se existirem objetos dependentes. Este é o padrão.
Exemplos Para remover o domínio box: DROP DOMAIN box;
Compatibilidade Este comando está em conformidade com o padrão SQL.
Veja também CREATE DOMAIN
767
DROP FUNCTION Nome DROP FUNCTION — remove uma função
Sinopse DROP FUNCTION nome ( [ tipo [, ...] ] ) [ CASCADE | RESTRICT ]
Descrição O comando DROP FUNCTION remove a definição de uma função existente. Para executar este comando o usuário deve ser o dono da função. Os tipos de dado dos argumentos da função devem ser especificados, porque várias funções diferentes podem existir com o mesmo nome e listas de argumentos diferentes.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma função existente. tipo O tipo de dado de um argumento da função. CASCADE
Remove automaticamente os objetos que dependem da função (como operadores e gatilhos). RESTRICT
Recusa remover a função se algum objeto depender da mesma. Este é o padrão.
Exemplos Este comando remove a função que calcula a raiz quadrada: DROP FUNCTION sqrt(integer);
Compatibilidade Existe um comando DROP FUNCTION definido no padrão SQL, mas não é compatível com este comando.
Veja também CREATE FUNCTION, ALTER FUNCTION
768
DROP GROUP Nome DROP GROUP — remove um grupo de usuários
Sinopse DROP GROUP nome
Descrição O comando DROP GROUP remove o grupo especificado. Os usuários no grupo não são removidos.
Parâmetros nome O nome de um grupo existente.
Exemplos Para remover um grupo: DROP GROUP engenharia;
Compatibilidade Não existe o comando DROP GROUP no padrão SQL.
Veja também ALTER GROUP, CREATE GROUP
769
DROP INDEX Nome DROP INDEX — remove um índice
Sinopse DROP INDEX nome [, ...] [ CASCADE | RESTRICT ]
Descrição O comando DROP INDEX remove do sistema de banco de dados um índice existente. Para executar este comando é necessário ser o dono do índice.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) do índice a ser removido. CASCADE
Remove automaticamente os objetos que dependem do índice. RESTRICT
Recusa remover o índice se existirem objetos dependentes. Este é o padrão.
Exemplos O comando a seguir remove o índice idx_titulo: DROP INDEX idx_titulo;
Compatibilidade O comando DROP INDEX é uma extensão do PostgreSQL à linguagem. O padrão SQL não trata de índices.
Veja também CREATE INDEX
770
DROP LANGUAGE Nome DROP LANGUAGE — remove uma linguagem procedural
Sinopse DROP [ PROCEDURAL ] LANGUAGE nome [ CASCADE | RESTRICT ]
Descrição O comando DROP LANGUAGE remove a definição da linguagem procedural previamente registrada chamada nome.
Parâmetros nome O nome de uma linguagem procedural existente. Para manter a compatibilidade com as versões anteriores, o nome pode estar entre apóstrofos ('). CASCADE
Remove automaticamente os objetos que dependem da linguagem (como as funções escritas nesta linguagem). RESTRICT
Recusa remover a linguagem se existirem objetos que dependam da mesma. Este é o padrão.
Exemplos O comando mostrado abaixo remove a linguagem procedural plsample: DROP LANGUAGE plsample;
Compatibilidade Não existe o comando DROP LANGUAGE no padrão SQL.
Veja também ALTER LANGUAGE, CREATE LANGUAGE, droplang
771
DROP OPERATOR Nome DROP OPERATOR — remove um operador
Sinopse DROP OPERATOR nome ( tipo_esquerda | NONE , tipo_direita | NONE ) [ CASCADE | RESTRICT ]
Descrição O comando DROP OPERATOR remove do sistema de banco de dados um operador existente. Para executar este comando é necessário ser o dono do operador.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de um operador existente. tipo_esquerda O tipo de dado do operando à esquerda do operador; deve ser escrito NONE se o operador não possuir operando à esquerda. tipo_direita O tipo de dado do operando à direita do operador; deve ser escrito NONE se o operador não possuir operando à direita. CASCADE
Remove automaticamente os objetos que dependem do operador. RESTRICT
Recusa remover o operador se existirem objetos que dependam do mesmo. Este é o padrão.
Exemplos Remover o operador de potência a^b para o tipo integer: DROP OPERATOR ^ (integer, integer);
Remover o operador de complemento bit-a-bit unário esquerdo ~b para o tipo bit: DROP OPERATOR ~ (none, bit);
Remover o operador de fatorial unário direito x! para o tipo integer: DROP OPERATOR ! (integer, none);
Compatibilidade Não existe o comando DROP OPERATOR no padrão SQL.
Veja também CREATE OPERATOR
772
DROP OPERATOR CLASS Nome DROP OPERATOR CLASS — remove uma classe de operadores
Sinopse DROP OPERATOR CLASS nome USING método_de_índice [ CASCADE | RESTRICT ]
Descrição O comando DROP OPERATOR CLASS remove uma classe de operadores existente. É necessário ser o dono da classe de operadores para executar este comando.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) de uma classe de operadores existente. método_de_índice O nome do método de acesso de índice para o qual a classe de operadores se destina. CASCADE
Remove automaticamente os objetos que dependem da classe de operadores. RESTRICT
Recusa excluir a classe de operadores se existirem objetos que dependam da mesma. Este é o comportamento padrão.
Exemplos Remover a classe de operadores B-tree widget_ops: DROP OPERATOR CLASS widget_ops USING btree;
Este comando não é bem-sucedido quando existe algum índice utilizando a classe de operadores. Deve ser especificado CASCADE para remover estes índices junto com a classe de operadores.
Compatibilidade Não existe o comando DROP OPERATOR CLASS no padrão SQL.
Veja também ALTER OPERATOR CLASS, CREATE OPERATOR CLASS
773
DROP RULE Nome DROP RULE — remove uma regra de reescrita
Sinopse DROP RULE nome ON relação [ CASCADE | RESTRICT ]
Descrição O comando DROP RULE remove uma regra de reescrita.
Parâmetros nome O nome da regra a ser removida. relação O nome (opcionalmente qualificado pelo esquema) da tabela ou da visão à qual a regra se aplica. CASCADE
Remove automaticamente os objetos que dependem da regra. RESTRICT
Recusa remover a regra se existirem objetos que dependam da mesma. Este é o padrão.
Exemplos Para remover a regra de reescrita nova_regra: DROP RULE nova_regra ON minha_tabela;
Compatibilidade Não existe o comando DROP RULE no padrão SQL.
Veja também CREATE RULE
774
DROP SCHEMA Nome DROP SCHEMA — remove um esquema
Sinopse DROP SCHEMA nome [, ...] [ CASCADE | RESTRICT ]
Descrição O comando DROP SCHEMA remove esquemas do banco de dados. O esquema somente pode ser removido pelo seu dono ou por um superusuário. Observe que o dono pode remover o esquema (e, portanto, todos os objetos que este contém), mesmo que não seja o dono de alguns objetos contidos no esquema.
Parâmetros nome O nome do esquema. CASCADE
Remove automaticamente os objetos (tabelas, funções, etc.) contidos no esquema. RESTRICT
Recusa remover o esquema se este contiver algum objeto. Este é o padrão.
Exemplos Para remover do banco de dados o esquema meu_esquema junto com todos os objetos que este contém: DROP SCHEMA meu_esquema CASCADE;
Compatibilidade O comando DROP SCHEMA está em conformidade total com o padrão SQL, exceto que o padrão permite apenas remover um esquema por comando.
Veja também ALTER SCHEMA, CREATE SCHEMA
775
DROP SEQUENCE Nome DROP SEQUENCE — remove uma seqüência
Sinopse DROP SEQUENCE nome [, ...] [ CASCADE | RESTRICT ]
Descrição O comando DROP SEQUENCE remove geradores de números seqüenciais.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da seqüência. CASCADE
Remove automaticamente os objetos que dependem da seqüência. RESTRICT
Recusa remover a seqüência se existirem objetos que dependam da mesma. Este é o padrão.
Exemplos Para remover a seqüência serial: DROP SEQUENCE serial;
Compatibilidade Não existe o comando DROP SEQUENCE no padrão SQL.
Veja também CREATE SEQUENCE
776
DROP TABLE Nome DROP TABLE — remove uma tabela
Sinopse DROP TABLE nome [, ...] [ CASCADE | RESTRICT ]
Descrição O comando DROP TABLE remove tabelas do banco de dados. Somente o criador pode destruir a tabela. Para deixar uma tabela sem linhas, sem destrui-la, deve ser usado o comando DELETE. O comando DROP TABLE remove todos os índices, regras, gatilhos e restrições existentes na tabela. Entretanto, para remover uma tabela referenciada por uma restrição de chave estrangeira de outra tabela, deve ser especificado CASCADE (CASCADE remove a restrição de chave estrangeira, e não toda a tabela).
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da tabela a ser removida. CASCADE
Remove automaticamente os objetos que dependem da tabela (como as visões). RESTRICT
Recusa remover a tabela se existirem objetos que dependam da mesma. Este é o padrão.
Exemplos Remover duas tabelas, filmes e distribuidores: DROP TABLE filmes, distribuidores;
Compatibilidade Este comando está em conformidade com o padrão SQL.
Veja também ALTER TABLE, CREATE TABLE
777
DROP TRIGGER Nome DROP TRIGGER — remove um gatilho
Sinopse DROP TRIGGER nome ON tabela [ CASCADE | RESTRICT ]
Descrição O comando DROP TRIGGER remove uma definição de gatilho existente. Para executar este comando, o usuário corrente deve ser o dono da tabela para a qual o gatilho está definido.
Parâmetros nome O nome do gatilho a ser removido. tabela O nome (opcionalmente qualificado pelo esquema) da tabela para a qual o gatilho está definido. CASCADE
Remove automaticamente os objetos que dependem do gatilho. RESTRICT
Recusa remover o gatilho se existirem objetos que dependam do mesmo. Este é o padrão.
Exemplos Remover o gatilho se_dist_existe da tabela filmes: DROP TRIGGER se_dist_existe ON filmes;
Compatibilidade O comando DROP TRIGGER do PostgreSQL não é compatível com o padrão SQL. Pelo padrão SQL, os nomes dos gatilhos não são presos às tabelas e, portanto, o comando é simplesmente DROP TRIGGER nome.
Veja também CREATE TRIGGER
778
DROP TYPE Nome DROP TYPE — remove um tipo de dado
Sinopse DROP TYPE nome [, ...] [ CASCADE | RESTRICT ]
Descrição O comando DROP TYPE remove um tipo de dado definido pelo usuário. Somente o dono do tipo de dado pode removê-lo.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) do tipo de dado a ser removido. CASCADE
Remove automaticamente os objetos que dependem do tipo de dado (como colunas de tabelas, funções, operadores, etc.). RESTRICT
Recusa remover o tipo de dado se existirem objetos que dependam do mesmo. Este é o padrão.
Exemplos Para remover o tipo de dado box: DROP TYPE box;
Compatibilidade Este comando é semelhante ao comando correspondente do padrão SQL, mas deve ser observado que o comando CREATE TYPE e os mecanismos de extensão de tipo de dado do PostgreSQL são diferentes do padrão SQL.
Veja também CREATE TYPE
779
DROP USER Nome DROP USER — remove uma conta de usuário do banco de dados
Sinopse DROP USER nome
Descrição O comando DROP USER remove o usuário especificado. Não remove as tabelas, visões ou outros objetos pertencentes ao usuário. Se o usuário possuir algum banco de dados uma mensagem de erro é gerada.
Parâmetros nome O nome do usuário a ser removido.
Observações O PostgreSQL inclui a aplicação dropuser que possui a mesma funcionalidade deste comando (na verdade, chama este comando), mas que pode ser executada a partir da linha de comandos. Para remover um usuário que possui um banco de dados, primeiro o banco de dados deve ser removido ou mudado de dono.
Exemplos Para remover uma conta de usuário: DROP USER josias;
Compatibilidade O comando DROP USER é uma extensão do PostgreSQL. O padrão SQL deixa a definição de usuários para a implementação
Veja também ALTER USER, CREATE USER
780
DROP VIEW Nome DROP VIEW — remove uma visão
Sinopse DROP VIEW nome [, ...] [ CASCADE | RESTRICT ]
Descrição O comando DROP VIEW remove uma visão existente. Para executar este comando é necessário ser o dono da visão.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da visão a ser removida. CASCADE
Remove automaticamente os objetos que dependem da visão (como outras visões). RESTRICT
Recusa remover a visão se existirem objetos que dependam da mesma. Este é o padrão.
Exemplos Este comando remove a visão chamada tipos: DROP VIEW tipos;
Compatibilidade Este comando está em conformidade com o padrão SQL.
Veja também CREATE VIEW
781
END Nome END — efetiva a transação corrente
Sinopse END [ WORK | TRANSACTION ]
Descrição O comando END efetiva a transação corrente. Todas as modificações efetuadas pela transação se tornam visíveis para os outros, e existe a garantia de permanecerem se uma falha ocorrer. Este comando é uma extensão do PostgreSQL equivalente ao COMMIT.
Parâmetros WORK TRANSACTION
Palavras chave opcionais. Não produzem nenhum efeito.
Observações Use o ROLLBACK para interromper a transação. A utilização do END fora de uma transação não causa nenhum problema, mas provoca uma mensagem de advertência.
Exemplos Para efetivar a transação corrente e tornar todas as modificações permanentes: END;
Compatibilidade O comando END é uma extensão do PostgreSQL que fornece uma funcionalidade equivalente ao COMMIT, que é especificado no padrão SQL.
Veja também BEGIN, COMMIT, ROLLBACK
782
EXECUTE Nome EXECUTE — executa um comando preparado
Sinopse EXECUTE nome_do_plano [ (parâmetro [, ...] ) ]
Descrição O comando EXECUTE é utilizado para executar um comando previamente preparado. Como os comandos preparados existem somente durante o período da sessão, o comando preparado deve ter sido criado por um comando PREPARE executado anteriormente na sessão corrente. Se o comando PREPARE que criou o comando especificar alguns parâmetros, um conjunto compatível de parâmetros deve ser passado para o comando EXECUTE, senão um erro será gerado. Observe que (diferentemente das funções) os comandos preparados não são sobrecarregados baseado no tipo ou número de seus parâmetros: o nome de um comando preparado deve ser único para a sessão. Para obter mais informações sobre a criação e utilização de comandos preparados consulte o comando PREPARE.
Parâmetros nome_do_plano O nome do comando preparado a ser executado. parâmetro O valor para o parâmetro do comando preparado. Deve ser uma expressão que produz um valor com tipo de dado compatível com o tipo de dado especificado para a posição deste parâmetro, no comando PREPARE que criou o comando preparado.
Compatibilidade O padrão SQL inclui o comando EXECUTE, mas somente para ser utilizado na linguagem SQL incorporada (embedded). Esta versão do comando EXECUTE também utiliza uma sintaxe um pouco diferente.
783
EXPLAIN Nome EXPLAIN — mostra o plano de execução de um comando
Sinopse EXPLAIN [ ANALYZE ] [ VERBOSE ] comando
Descrição Este comando mostra o plano de execução que o planejador do PostgreSQL gera para o comando fornecido. O plano de execução mostra como as tabelas referenciadas pelo comando são varridas — por uma varredura seqüencial simples, varredura pelo índice, etc. — e, se várias tabelas forem referenciadas, quais algoritmos de junção são utilizados para unir as linhas das tabelas de entrada. Do que é mostrado, a parte mais importante é o custo estimado de execução do comando, que é a estimativa feita pelo planejador de quanto tempo demora para executar o comando (medido em unidades de acesso às páginas do disco). Na verdade, são mostrados dois números: o tempo inicial antes que a primeira linha possa ser retornada, e o tempo total para retornar todas as linhas. Para a maior parte dos comandos o tempo total é o que importa, mas em contextos como uma subseleção no EXISTS, o planejador escolhe o menor tempo inicial em vez do menor tempo total (porque o executor pára após ter obtido uma linha). Além disso, se for limitado o número de linhas retornadas usando a cláusula LIMIT, o planejador efetua uma interpolação apropriada entre estes custos para saber qual é realmente o plano de menor custo. A opção ANALYZE faz o comando ser realmente executado, e não apenas planejado. O tempo total decorrido gasto em cada nó do plano (em milissegundos) e o número total de linhas realmente retornadas são adicionados ao que é mostrado. Esta opção é útil para ver se as estimativas do planejador estão próximas da realidade. Importante: Tenha em mente que o comando é realmente executado quando a opção ANALYZE é utilizada. Embora o comando EXPLAIN despreze qualquer saída produzida pelo SELECT, os outros efeitos colaterais do comando ocorrem da forma usual. Se for desejado utilizar EXPLAIN ANALYZE em um comando INSERT, UPDATE, DELETE ou EXECUTE sem afetar os dados, utilize o seguinte procedimento: BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
Parâmetros ANALYZE
Executar o comando e mostrar os tempos reais de execução. VERBOSE
Mostrar a representação interna completa da árvore do plano, em vez de apenas um resumo. Geralmente esta opção é útil apenas para finalidades especiais de depuração. A saída produzida pela opção VERBOSE é formatada para ser facilmente lida (pretty-print) ou não, dependendo de como estiver definido o parâmetro de configuração explain_pretty_print. comando Qualquer comando SELECT, INSERT, UPDATE, DELETE, EXECUTE ou DECLARE, cujo plano de execução se deseja ver.
Observações Existe apenas documentação esparsa sobre o uso da informação do custo do otimizador no PostgreSQL. Veja a Seção 13.1 para obter mais informações.
784
Para que o planejador de comandos do PostgreSQL esteja razoavelmente informado para tomar decisões ao otimizar os comandos, o comando ANALYZE deve ser executado para registrar as estatísticas sobre a distribuição dos dados dentro da tabela. Se isto não tiver sido feito (ou se a distribuição estatística dos dados da tabela mudou de forma significativa desde a última vez que o comando ANALYZE foi executado), os custos estimados têm pouca chance de estarem em conformidade com as verdadeiras propriedades do comando e, conseqüentemente, pode ser escolhido um plano de comando inferior. Antes do PostgreSQL 7.3, o plano era mostrado na forma de uma mensagem NOTICE. Agora aparece na forma do resultado de uma consulta (formatado como uma tabela de uma única coluna do tipo texto).
Exemplos Mostrar o plano para uma consulta simples em uma tabela com uma única coluna integer e 10.000 linhas: => EXPLAIN SELECT * FROM foo; QUERY PLAN --------------------------------------------------------Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4) (1 linha)
Havendo um índice, e sendo feita uma consulta com uma condição WHERE indexável, o comando EXPLAIN pode mostrar um plano diferente: => EXPLAIN SELECT * FROM foo WHERE i = 4; QUERY PLAN -------------------------------------------------------------Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4) Index Cond: (i = 4) (2 linhas)
O exemplo abaixo mostra o plano para uma consulta contendo uma função de agregação: => EXPLAIN SELECT sum(i) FROM foo WHERE i < 10; QUERY PLAN --------------------------------------------------------------------Aggregate (cost=23.93..23.93 rows=1 width=4) -> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4) Index Cond: (i < 10) (3 linhas)
Abaixo está um exemplo da utilização do comando EXPLAIN EXECUTE para mostrar o plano para uma consulta preparada: => PREPARE query(int, int) AS SELECT sum(bar) FROM test -> WHERE id > $1 AND id < $2 -> GROUP BY foo; => EXPLAIN ANALYZE EXECUTE query(100, 200); QUERY PLAN ---------------------------------------------------------------------------------HashAggregate (cost=39.53..39.53 rows=1 width=8)\ (actual time=0.661..0.672 rows=7 loops=1) -> Index Scan using test_pkey on test\ (cost=0.00..32.97 rows=1311 width=8)\ (actual time=0.050..0.395 rows=99 loops=1) Index Cond: ((id > $1) AND (id < $2)) Total runtime: 0.851 ms (4 linhas)
785
Obviamente, os números específicos mostrados aqui dependem do conteúdo real das tabelas envolvidas. Observe, também, que os números, e mesmo a estratégia selecionada para o comando, podem variar entre versões diferentes do PostgreSQL devido a melhorias no planejador. Além disso, o comando ANALYZE utiliza amostragem aleatória para estimar as estatísticas dos dados; portanto, é possível que as estimativas de custo mudem após a execução do comando ANALYZE, mesmo que a distribuição real dos dados da tabela não tenha mudado.
Compatibilidade Não existe o comando EXPLAIN no padrão SQL.
786
FETCH Nome FETCH — traz linhas de uma consulta usando um cursor
Sinopse FETCH [ direção { FROM | IN } ] nome_do_cursor onde direção pode ser omitida ou pode ser um dentre: NEXT PRIOR FIRST LAST ABSOLUTE contador RELATIVE contador contador ALL FORWARD FORWARD contador FORWARD ALL BACKWARD BACKWARD contador BACKWARD ALL
Descrição O comando FETCH traz linhas utilizando um cursor previamente criado. O cursor possui uma posição associada, a qual é utilizada pelo comando FETCH. A posição do cursor pode ser: antes da primeira linha, em uma determinada linha, ou após a última linha do resultado da consulta. Ao ser criado, o cursor fica posicionado antes da primeira linha. Após trazer algumas linhas, o cursor fica posicionado na linha trazida mais recentemente. Se o comando FETCH ultrapassar o final das linhas disponíveis, então o cursor fica posicionado após a última linha, ou antes da primeira linha se estiver trazendo para trás. Os comandos FETCH ALL e FETCH BACKWARD ALL sempre deixam o cursor posicionado após a última linha ou antes da primeira linha, respectivamente. As formas NEXT, PRIOR, FIRST, LAST, ABSOLUTE e RELATIVE trazem uma única linha após mover o cursor de forma apropriada. Se a linha não existir, um resultado vazio é retornado, e o cursor é deixado posicionado antes da primeira linha ou após a última linha, conforme seja apropriado. As formas que utilizam FORWARD e BACKWARD trazem o número indicado de linhas movendo o cursor para frente ou para trás, deixando o cursor posicionado na última linha retornada; ou após/antes de todas as linhas se o contador exceder o número de linhas disponíveis. RELATIVE 0, FORWARD 0 e BACKWARD 0 requerem que seja trazida a linha corrente sem mover o cursor, ou
seja, traz novamente a linha trazida mais recentemente. Sempre é bem-sucedido, a menos que o cursor esteja posicionado antes da primeira linha ou após a última linha; nestes casos, nenhuma linha é retornada.
Parâmetros direção Define a direção para trazer e o número de linhas a serem trazidas. Pode ser um entre os seguintes: NEXT
Traz a próxima linha. Este é o padrão se a direção for omitida.
787
PRIOR
Traz a linha anterior. FIRST
Traz a primeira linha da consulta (o mesmo que ABSOLUTE 1). LAST
Traz a última linha da consulta (o mesmo que ABSOLUTE -1). ABSOLUTE contador
Traz a contador-ésima linha da consulta, ou a abs(contador)-ésima linha a partir do fim se contador for negativo. Posiciona antes da primeira linha ou após a última linha se o contador estiver fora do intervalo; em particular, ABSOLUTE 0 posiciona antes da primeira linha. RELATIVE contador
Traz a contador-ésima linha à frente, ou a abs(contador)-ésima linha atrás se o contador for negativo. RELATIVE 0 traz novamente a linha corrente, se houver. contador Traz as próximas contador linhas (o mesmo que FORWARD contador). ALL
Traz todas as linhas restantes (o mesmo que FORWARD ALL). FORWARD
Traz a próxima linha (o mesmo que NEXT). FORWARD contador
Traz as próximas contador linhas. FORWARD 0 traz novamente a linha corrente. FORWARD ALL
Traz todas as linhas restantes. BACKWARD
Traz a linha anterior (o mesmo que PRIOR). BACKWARD contador
Traz as contador linhas anteriores (varrendo para trás). BACKWARD 0 traz novamente a linha corrente. BACKWARD ALL
Traz todas as linhas anteriores (varrendo para trás). contador O contador é uma constante inteira, possivelmente com sinal, que determina a localização ou o número de linhas a serem trazidas. Para os casos FORWARD e BACKWARD, especificar um contador negativo é equivalente a mudar o sentido de FORWARD e BACKWARD. nome_do_cursor O nome de um cursor aberto.
Saídas Ao terminar bem-sucedido, o comando FETCH retorna uma linha de fim de comando na forma FETCH contador
O contador é o número de linhas trazidas (possivelmente zero). Observe que no psql a linha de fim de comando não é exibida, uma vez que o psql mostra as linhas trazidas em seu lugar.
788
Observações O cursor deve ser declarado com a opção SCROLL se houver intenção de utilizar qualquer variante do comando FETCH que não seja FETCH NEXT ou FETCH FORWARD com um contador positivo. Para consultas simples o PostgreSQL permite trazer para trás usando cursores não declarados com SCROLL, mas é bom não confiar neste comportamento. Se o cursor for declarado com NO SCROLL, então trazer para trás não é permitido. Trazer com ABSOLUTE não é nem um pouco mais rápida do que navegar para a linha desejada usando um movimento relativo: a implementação subjacente precisa percorrer todas as linhas intermediárias de qualquer maneira. Buscas absolutas negativas são piores ainda: a consulta precisa ser lida até o fim para encontrar a última linha, e depois percorrida para trás a partir deste ponto. Entretanto, voltar para o início da consulta (como com FETCH ABSOLUTE 0) é rápido. A atualização dos dados através de cursores não é permitida atualmente pelo PostgreSQL. O comando DECLARE é utilizado para definir o cursor. Deve ser utilizado o comando MOVE para mudar a posição do cursor sem trazer dados.
Exemplos O exemplo a seguir percorre uma tabela usando um cursor. => BEGIN WORK; => -- Definir o cursor: => DECLARE liahona SCROLL CURSOR FOR SELECT * FROM filmes; => -- Trazer as 5 primeiras linhas do cursor liahona: => FETCH FORWARD 5 FROM liahona; cod | titulo | did | data_prod | tipo | duracao -------+-------------------------+-----+------------+----------+--------BL101 | The Third Man | 101 | 1949-12-23 | Drama | 01:44 BL102 | The African Queen | 101 | 1951-08-11 | Romance | 01:43 JL201 | Une Femme est une Femme | 102 | 1961-03-12 | Romance | 01:25 P_301 | Vertigo | 103 | 1958-11-14 | Ação | 02:08 P_302 | Becket | 103 | 1964-02-03 | Drama | 02:28 => -- Trazer a linha anterior: => FETCH PRIOR FROM liahona; cod | titulo | did | data_prod | tipo | duracao -------+---------+-----+------------+--------+--------P_301 | Vertigo | 103 | 1958-11-14 | Ação | 02:08 => -- Fechar o cursor e terminar a transação: => CLOSE liahona; => COMMIT WORK;
Compatibilidade O padrão SQL define o comando FETCH apenas para uso na linguagem SQL incorporada (embedded). Esta variante do FETCH descrita aqui retorna os dados como se fossem o resultado de um comando SELECT, em vez de colocar nas variáveis do hospedeiro. Fora este ponto, o comando FETCH possui total compatibilidade ascendente 1 com o padrão SQL. As formas do comando FETCH envolvendo FORWARD e BACKWARD, assim bem como todas as formas de FETCH contador e FETCH ALL, na qual o FORWARD está implícito, são extensões do PostgreSQL. O padrão SQL permite apenas o FROM precedendo o nome do cursor; a opção para utilizar IN é uma extensão.
789
Notas 1. upward compatibility — (compatibilidade ascendente) característica de um software que funciona sem modificações em versões mais recentes ou mais avançadas de determinado sistema de computador. Webster's New World Dicionário de Informática, Bryan Pfaffenberger, Editora Campus, 1999. (N. do T.)
790
GRANT Nome GRANT — define privilégios de acesso
Sinopse GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] } ON [ TABLE ] nome_da_tabela [, ...] TO { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] } ON DATABASE nome_bd [, ...] TO { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { EXECUTE | ALL [ PRIVILEGES ] } ON FUNCTION funcname ([tipo, ...]) [, ...] TO { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE nome_da_linguagem [, ...] TO { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] } ON SCHEMA nome_do_esquema [, ...] TO { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ WITH GRANT OPTION ]
Descrição O comando GRANT concede privilégios específicos para um objeto (tabela, visão, seqüência, banco de dados, função, linguagem procedural ou esquema) para um ou mais usuários ou grupos de usuários. Estes privilégios são adicionados aos já concedidos, caso existam. A palavra chave PUBLIC indica que o privilégio deve ser concedido para todos os usuários, inclusive aos que vierem a ser criados posteriormente. PUBLIC pode ser considerado como um grupo definido implicitamente que sempre inclui todos os usuários. Um determinado usuário possui a soma dos privilégios concedidos diretamente para o mesmo, mais os privilégios concedidos para todos os grupos que este seja membro, mais os privilégios concedidos para PUBLIC. Se for especificado WITH GRANT OPTION quem recebe o privilégio pode, por sua vez, conceder o privilégio a outros. Por padrão, isto não é permitido. Opções de concessão podem ser concedidas apenas a usuários específicos, e não a grupos ou PUBLIC. Não existe necessidade de conceder privilégios para o dono do objeto (geralmente o usuário que o criou), porque o dono possui todos os privilégios por padrão (Entretanto, o dono pode decidir revogar alguns de seus próprios privilégios por motivo de segurança). O direito de remover um objeto, ou de alterar a sua definição de alguma forma, não é descrito por um privilégio que possa ser concedido; é inerente ao dono e não pode ser concedido ou revogado. Também não é possível revogar as opções de conceder do dono. Dependendo do tipo do objeto, os privilégios iniciais padrão podem incluir a concessão de alguns privilégios para PUBLIC. O padrão é: não permitir o acesso público para tabelas e esquemas; privilégio de criação de tabela TEMP para bancos de dados; privilégio EXECUTE para funções; e privilégio USAGE para linguagens. O
791
dono do objeto pode, é claro, revogar estes privilégios (para a máxima segurança deve ser executado o comando REVOKE na mesma transação que criar o objeto; dessa forma não haverá tempo para que outro usuário possa usar o objeto). Os privilégios possíveis são: SELECT Permite consultar (SELECT) qualquer coluna da tabela, visão ou seqüência especificada. Também permite utilizar o comando COPY TO. Para as seqüências, este privilégio também permite o uso da função currval. INSERT Permite inserir (INSERT) novas linhas na tabela especificada. Também permite utilizar o comando COPY FROM. UPDATE Permite modificar (UPDATE) os dados de qualquer coluna da tabela especificada. O comando SELECT ... FOR UPDATE também requer este privilégio (além do privilégio SELECT). Para as seqüências, este privilégio permite o uso das funções nextval e setval. DELETE Permite excluir (DELETE) linhas da tabela especificada. RULE Permite criar regras para a tabela ou para a visão (Consulte o comando CREATE RULE). REFERENCES Para criar uma restrição de chave estrangeira é necessário possuir este privilégio, tanto na tabela que faz referência quanto na tabela que é referenciada. TRIGGER Permite criar gatilhos na tabela especificada (Consulte o comando CREATE TRIGGER). CREATE Para bancos de dados, permite a criação de novos esquemas no banco de dados. Para esquemas, permite a criação de novos objetos no esquema. Para mudar o nome de um objeto existente é necessário ser o dono do objeto e possuir este privilégio no esquema que o contém. TEMPORARY TEMP Permite a criação de tabelas temporárias ao usar o banco de dados. EXECUTE Permite utilizar a função especificada e qualquer operador implementado por cima da função. Este é o único tipo de privilégio aplicável às funções (Esta sintaxe funciona para as funções de agregação, da mesma forma). USAGE Para as linguagens procedurais, permite o uso da linguagem especificada para criar funções nesta linguagem. Este é o único tipo de privilégio aplicável às linguagens procedurais. Para os esquemas, permite acessar os objetos contidos no esquema especificado (assumindo que os privilégios requeridos para os próprios objetos estejam atendidos). Essencialmente, permite a quem recebe a concessão “procurar” por objetos dentro do esquema. ALL PRIVILEGES Concede todos os privilégios disponíveis de uma só vez. A palavra chave PRIVILEGES é opcional no PostgreSQL, embora seja requerida pelo SQL estrito.
792
Os privilégios requeridos por outros comandos estão listados nas páginas de referência dos respectivos comandos.
Observações O comando REVOKE é utilizado para revogar privilégios de acesso. Deve ser observado que os superusuários do banco de dados podem acessar todos os objetos, sem considerar os privilégios definidos para o objeto. Isto é comparável aos direitos do usuário root no sistema operacional Unix. Assim como no caso do root, não é aconselhável operar como um superusuário a não ser quando for absolutamente necessário. Se um superusuário decidir executar o comando GRANT ou o comando REVOKE, o comando é executado como se tivesse sido executado pelo dono do objeto afetado. Em particular, os privilégio concedidos através deste comando aparecem como se tivessem sido concedidos pelo dono do objeto. Atualmente o PostgreSQL não suporta conceder ou revogar privilégios para colunas individuais da tabela. Uma forma possível de transpor esta limitação é criar uma visão possuindo apenas as colunas desejadas e, então, conceder os privilégios para a visão. Pode ser usado o comando \z da aplicação psql para obter informações sobre os privilégios concedidos como, por exemplo: => \z minha_tabela Access privileges for database "lusitania" Schema | Table | Access privileges --------+--------------+--------------------------------------public | minha_tabela | {=r/postgres,miriam=arwdRxt/postgres,\ "group todos=arw/postgres"} (1 linha)
As entradas mostradas pelo comando \z são interpretadas da seguinte forma: =xxxx -- privilégios concedidos para PUBLIC uname=xxxx -- privilégios concedidos para o usuário group gname=xxxx -- privilégios concedidos para o grupo r w a d R x t X U C T arwdRxt *
--------------
SELECT ("read") UPDATE ("write") INSERT ("append") DELETE RULE REFERENCES TRIGGER EXECUTE USAGE CREATE TEMPORARY ALL PRIVILEGES (para tabelas) opção de concessão para o privilégio precedente
/yyyy -- usuário que concedeu este privilégio
O exemplo mostrado acima seria visto pela usuária miriam após esta ter criado a tabela minha_tabela e executado: GRANT SELECT ON minha_tabela TO PUBLIC; GRANT SELECT, UPDATE, INSERT ON minha_tabela TO GROUP todos;
Se a coluna “Access privileges” estiver vazia para um determinado objeto, isto significa que o objeto possui os privilégios padrão (ou seja, suas colunas de privilégio são nulas). Os privilégios padrão sempre incluem todos os privilégios para o dono, e podem incluir alguns privilégios para PUBLIC dependendo do tipo do objeto,
793
como foi explicado acima. O primeiro comando GRANT ou REVOKE em um objeto cria uma instância dos privilégios padrão (produzindo, por exemplo, {=,miriam=arwdRxt}) e, em seguida, modifica esta instância de acordo com a requisição especificada.
Exemplos Conceder, para todos os usuários, o privilégio de inserção na tabela filmes: GRANT INSERT ON filmes TO PUBLIC;
Conceder para o usuário manuel todos os privilégios disponíveis na visão tipos: GRANT ALL PRIVILEGES ON tipos TO manuel;
Compatibilidade De acordo com o padrão SQL, a palavra chave PRIVILEGES em ALL PRIVILEGES é requerida. O padrão SQL não suporta definir privilégios para mais de um objeto por comando. O padrão SQL permite definir privilégios para as colunas individuais da tabela: GRANT privilégios ON tabela [ ( coluna [, ...] ) ] [, ...] TO { PUBLIC | nome_do_usuário [, ...] } [ WITH GRANT OPTION ]
O padrão SQL permite conceder o privilégio USAGE em outros tipos de objeto: conjuntos de caracteres, classificações (collations 1 ), traduções e domínios. O privilégio RULE, e os privilégios para bancos de dados, esquemas, linguagens e seqüências são extensões do PostgreSQL.
Veja também REVOKE
Notas 1. collation; collating sequence — Um método para comparar duas cadeias de caracteres comparáveis. Todo conjunto de caracteres possui seu collation padrão. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992. (N. do T.)
794
INSERT Nome INSERT — cria novas linhas na tabela
Sinopse INSERT INTO tabela [ ( coluna [, ...] ) ] { DEFAULT VALUES | VALUES ( { expressão | DEFAULT } [, ...] ) | consulta }
Descrição O comando INSERT permite inserir novas linhas na tabela. Pode ser inserida uma linha de cada vez, ou várias linhas resultantes de uma consulta. Os nomes das colunas de destino podem ser listados em qualquer ordem. As colunas que não constam da lista de inserção são inseridas utilizando o valor padrão, seja seu valor padrão declarado ou nulo. Se a expressão para alguma coluna não for do tipo de dado correto, será tentada uma conversão automática de tipo. É necessário possuir o privilégio INSERT na tabela para poder inserir linhas. Se for utilizada a cláusula consulta para inserir linhas a partir de uma consulta, também é necessário possuir o privilégio SELECT em todas as tabelas usadas pela consulta.
Parâmetros tabela O nome (opcionalmente qualificado pelo esquema) de uma tabela existente. coluna O nome de uma coluna da tabela. DEFAULT VALUES
Todas as colunas são preenchidas com seu valor padrão. expressão Uma expressão ou valor a ser atribuído à coluna correspondente. DEFAULT
Esta coluna será preenchida com o seu valor padrão. consulta Uma consulta (comando SELECT) que fornece as linhas a serem inseridas. Consulte o comando SELECT para obter a descrição da sintaxe.
Saídas Ao terminar bem-sucedido, o comando INSERT retorna uma linha de fim de comando na forma INSERT oid contador
O contador é o número de linhas inseridas. Se contador for igual a um, e a tabela de destino possuir OIDs, então oid é o OID atribuído à linha inserida, senão oid é zero.
Exemplos Inserir uma única linha na tabela filmes:
795
INSERT INTO filmes VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comédia', '82 minutes');
No exemplo abaixo, a coluna duracao é omitida e, portanto, receberá o valor padrão: INSERT INTO filmes (cod, titulo, did, data_prod, tipo) VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');
O exemplo abaixo utiliza a cláusula DEFAULT para as colunas de data em vez de especificar um valor. INSERT INTO filmes VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comédia', '82 minutes'); INSERT INTO filmes (cod, titulo, did, data_prod, tipo) VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');
O exemplo abaixo insere algumas linhas na tabela filmes a partir da tabela temp: INSERT INTO filmes SELECT * FROM temp;
O exemplo mostrado abaixo insere em colunas de matriz: -- Criar um tabuleiro vazio de 3x3 posições para o Jogo da Velha -- (estes comandos criam o mesmo tabuleiro) INSERT INTO tictactoe (game, board[1:3][1:3]) VALUES (1,'{{"","",""},{},{"",""}}'); INSERT INTO tictactoe (game, board[3][3]) VALUES (2,'{}'); INSERT INTO tictactoe (game, board) VALUES (3,'{{,,},{,,},{,,}}');
Compatibilidade O comando INSERT está em conformidade com o padrão SQL. As possíveis limitações da cláusula consulta estão documentadas no comando SELECT.
796
LISTEN Nome LISTEN — ouve uma notificação
Sinopse LISTEN nome
Descrição O comando LISTEN registra a sessão corrente como ouvinte da condição de notificação nome. Se a sessão corrente já estiver registrada como ouvinte desta condição de notificação, nada é feito. Sempre que o comando NOTIFY nome é executado, tanto por esta sessão quanto por outra conectada ao mesmo banco de dados, todas as sessões ouvindo esta condição de notificação no momento são notificadas, e cada uma por sua vez notifica sua aplicação cliente conectada. Veja a explicação do comando NOTIFY para obter mais informações. A sessão pode cancelar o registro para uma determinada condição de notificação utilizando o comando UNLISTEN. Os registros da sessão como ouvinte são automaticamente removidos quando a sessão termina.
O método que a aplicação cliente deve usar para detectar eventos de notificação depende da interface de programação de aplicações (API) do PostgreSQL que a aplicação usa. Quando usa a biblioteca libpq a aplicação executa o comando LISTEN como um comando SQL comum, e depois deve chamar periodicamente a função PQnotifies para descobrir se algum evento de notificação foi recebido. Outras interfaces, como a libpgtcl, fornecem métodos de mais alto nível para tratar os eventos de notificação; na verdade, usando a libpgtcl o programador da aplicação não deve nem mesmo executar o comando LISTEN ou UNLISTEN diretamente. Consulte a documentação da interface sendo usada para obter mais detalhes. O comando NOTIFY contém uma explicação mais extensa sobre a utilização do comando LISTEN e do comando NOTIFY.
Parâmetros nome O nome da condição de notificação (qualquer identificador).
Exemplos Configurar e executar a seqüência ouvir/notificar a partir do psql: => LISTEN virtual; => NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448.
Compatibilidade Não existe o comando LISTEN no padrão SQL.
Veja também NOTIFY, UNLISTEN
797
LOAD Nome LOAD — carrega ou recarrega um arquivo de biblioteca compartilhada
Sinopse LOAD 'nome_do_arquivo'
Descrição Este comando carrega um arquivo de biblioteca compartilhada no espaço de endereçamento do servidor PostgreSQL. Se o arquivo tiver sido carregado anteriormente, primeiro é descarregado. Este comando é útil, principalmente, para descarregar e recarregar um arquivo de biblioteca compartilhada modificado após ter sido carregado pelo servidor. Para usar a biblioteca compartilhada, as funções na mesma devem ser declaradas usando o comando CREATE FUNCTION. O nome do arquivo é especificado da mesma forma que os nomes de bibliotecas compartilhadas no comando CREATE FUNCTION; em particular, pode-se confiar no caminho de procura e na adição automática da extensão de nome de arquivo de biblioteca compartilhada padrão do sistema. Consulte a Seção 33.3 para obter mais informações sobre e estes assunto.
Compatibilidade O comando LOAD é uma extensão do PostgreSQL.
Veja também CREATE FUNCTION
798
LOCK Nome LOCK — bloqueia uma tabela
Sinopse LOCK [ TABLE ] nome [, ...] [ IN modo_de_bloqueio MODE ] onde modo_de_bloqueio é um entre: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
Descrição O comando LOCK TABLE obtém um bloqueio no nível de tabela aguardando, quando necessário, pela liberação de qualquer bloqueio conflitante. Uma vez obtido, o bloqueio é mantido pelo restante da transação corrente (Não existe o comando UNLOCK TABLE; os bloqueios são sempre liberados no final da transação). Ao obter automaticamente o bloqueio para os comandos que fazem referência a tabelas, o PostgreSQL sempre utiliza o modo de bloqueio menos restritivo possível. O comando LOCK TABLE serve para os casos onde é necessário um modo de bloqueio mais restritivo. Por exemplo, suponha que uma aplicação executa uma transação no nível de isolamento READ COMMITTED, e precisa garantir que os dados da tabela permaneçam estáveis durante a transação. Para conseguir esta situação pode ser obtido o modo de bloqueio SHARE na tabela antes de realizar a consulta. Isto impede a alteração concorrente dos dados, garantindo que as próximas operações de leitura na tabela vão enxergar uma visão estável de dados efetivados, porque o modo de bloqueio SHARE conflita com o modo de bloqueio ROW EXCLUSIVE obtido por quem está escrevendo, fazendo com que o comando LOCK TABLE nome IN SHARE MODE aguarde todas as transações que obtiveram bloqueio no modo ROW EXCLUSIVE efetivarem ou desfazerem suas modificações. Portanto, quando este bloqueio é obtido não existem escritas não efetivadas pendentes; além disso, nenhuma transação pode começar enquanto o bloqueio não for liberado. Para obter um efeito semelhante ao executar uma transação no nível de isolamento serializável, é necessário executar o comando LOCK TABLE antes de executar qualquer comando SELECT ou de modificação de dado. A visão dos dados de uma transação serializável é congelada no momento em que seu primeiro comando SELECT ou de modificação de dados começa. Um comando LOCK TABLE posterior na transação ainda vai impedir escritas concorrentes — mas não vai garantir que o que é lido pela transação corresponde aos últimos valores efetivados. Se uma transação deste tipo altera os dados da tabela, então deve ser utilizado o modo de bloqueio SHARE ROW EXCLUSIVE em vez do modo SHARE, para garantir que somente uma transação deste tipo executa de cada vez. Sem isto, é possível ocorrer um impasse (deadlock): duas transações podem obter o modo de bloqueio SHARE, e depois ficarem impossibilitadas de obter o bloqueio no modo ROW EXCLUSIVE para realizar suas modificações (Observe que os bloqueios da própria transação nunca entram em conflito e, portanto, a transação pode obter o modo ROW EXCLUSIVE enquanto mantém o modo de bloqueio SHARE — mas não se outra transação estiver com o modo de bloqueio SHARE). Para evitar os impasses, deve ser garantido que as transações obtêm o bloqueio dos mesmos objetos na mesma ordem e, se vários modos de bloqueio estão envolvidos para um único objeto, as transações devem sempre obter o modo mais restritivo primeiro. Mais informações sobre os modos de bloqueio e estratégias de bloqueio podem ser encontradas na Seção 12.3.
799
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da tabela existente a ser bloqueada. O comando LOCK TABLE a, b; é equivalente a LOCK TABLE a; LOCK TABLE b;. As tabelas são bloqueadas uma a uma na ordem especificada no comando LOCK. modo_de_bloqueio O modo de bloqueio especifica os bloqueios com os quais este modo conflita. Os modos de bloqueio estão descritos na Seção 12.3. Se não for especificado nenhum modo de bloqueio, então ACCESS EXCLUSIVE, o modo mais restritivo, é usado.
Observações O comando LOCK ... IN ACCESS SHARE MODE requer o privilégio SELECT na tabela especificada. Todas as outras formas de LOCK requerem os privilégios UPDATE e/ou DELETE. O comando LOCK é útil apenas dentro de um bloco de transação (BEGIN...COMMIT), porque o bloqueio é liberado tão logo a transação termina. Um comando LOCK aparecendo fora de um bloco de transação forma uma transação autocontida e, portanto, o bloqueio é liberado logo após ser obtido. O comando LOCK TABLE trata somente de bloqueios no nível de tabela e, portanto, os nomes dos modos contendo ROW são todos equivocados. Os nomes destes modos devem ser lidos geralmente como indicando a intenção de obter um bloqueio no nível de linha dentro da tabela bloqueada. Também, o modo ROW EXCLUSIVE é um bloqueio de tabela compartilhável. Deve-se ter em mente que todos os modos de bloqueio possuem semântica idêntica no que diz respeito ao LOCK TABLE, diferindo apenas nas regras sobre quais modos conflitam com quais modos.
Exemplos Obter o bloqueio no modo SHARE da tabela que contém a chave primária, antes de fazer uma inserção na tabela que contém a chave estrangeira: BEGIN WORK; LOCK TABLE filmes IN SHARE MODE; SELECT id FROM filmes WHERE nome = 'Guerra Nas Estrelas - Episódio I - A Ameaça Fantasma'; -- Executar ROLLBACK se a linha não for encontrada INSERT INTO filmes_comentarios_usuario VALUES (_id_, 'Maravilhoso! Eu estava aguardando por isto há muito tempo!'); COMMIT WORK;
Obter o bloqueio no modo SHARE ROW EXCLUSIVE da tabela que contém a chave primária antes de realizar a operação de exclusão: BEGIN WORK; LOCK TABLE filmes IN SHARE ROW EXCLUSIVE MODE; DELETE FROM filmes_comentarios_usuario WHERE id IN (SELECT id FROM filmes WHERE avaliacao < 5); DELETE FROM filmes WHERE avaliacao < 5; COMMIT WORK;
Compatibilidade Não existe o comando LOCK TABLE no padrão SQL, que em seu lugar usa o comando SET TRANSACTION para especificar os níveis de concorrência das transações. O PostgreSQL também suporta esta funcionalidade; consulte o comando SET TRANSACTION para obter detalhes.
800
Exceto pelos modos de bloqueio ACCESS SHARE, ACCESS EXCLUSIVE e SHARE UPDATE EXCLUSIVE, os modos de bloqueio do PostgreSQL e a sintaxe do comando LOCK TABLE são compatíveis com as presentes no Oracle.
801
MOVE Nome MOVE — posiciona o cursor
Sinopse MOVE [ direção { FROM | IN } ] nome_do_cursor
Descrição O comando MOVE reposiciona o cursor sem trazer dados. O comando MOVE funciona exatamente como o comando FETCH, exceto que apenas posiciona o cursor sem retornar linhas. Consulte o comando FETCH para obter detalhes sobre a sintaxe e utilização.
Saídas Ao terminar bem-sucedido, o comando MOVE retorna uma linha de fim de comando na forma MOVE contador
O contador é o número de linhas de deslocamento (possivelmente zero).
Exemplos => BEGIN WORK; => DECLARE liahona CURSOR FOR SELECT * FROM filmes; => -- Pular as primeiras 5 linhas: => MOVE FORWARD 5 IN liahona; MOVE 5 => -- Trazer a sexta linha no cursor liahona: => FETCH 1 FROM liahona; cod | titulo | did | data_prod | tipo | duracao -------+--------+-----+------------+--------+--------P_303 | 48 Hrs | 103 | 1982-10-22 | Ação | 01:37 (1 linha) => -- Fechar o cursor liahona e terminar a transação: => CLOSE liahona; => COMMIT WORK;
Compatibilidade Não existe o comando MOVE no padrão SQL.
802
NOTIFY Nome NOTIFY — gera uma notificação
Sinopse NOTIFY nome
Descrição O comando NOTIFY envia um evento de notificação para todas as aplicações cliente, que tenham executado anteriormente o comando LISTEN nome para o nome de notificação especificado, no banco de dados corrente,. A informação passada para o cliente por um evento de notificação inclui o nome da notificação e o PID do processo servidor da sessão notificadora. É função do projetista do banco de dados definir os nomes das notificações a serem utilizadas em um determinado banco de dados, e o significado de cada uma delas. Usualmente, o nome da notificação é o mesmo de alguma tabela do banco de dados, e o evento de notificação essencialmente diz “Eu modifiquei esta tabela, dê uma olhada nela e veja o que há de novo”. Porém, este tipo de associação não é exigida pelos comandos NOTIFY e LISTEN. Por exemplo, um projetista de banco de dados pode usar vários nomes diferentes de notificação para sinalizar diferentes tipos de mudança em uma única tabela. O comando NOTIFY fornece uma forma de sinal simples, ou mecanismo de comunicação entre processos, para um conjunto de processos que acessam o mesmo banco de dados do PostgreSQL. Podem ser construídos mecanismos de mais alto nível usando tabelas do banco de dados para passar dados adicionais do notificador para os ouvintes (além do mero nome da notificação). Quando o comando NOTIFY é utilizado para sinalizar a ocorrência de mudanças em uma determinada tabela, uma técnica de programação útil é colocar o comando NOTIFY na regra disparada pela atualização da tabela. Assim, a notificação acontece automaticamente quando a tabela é modificada, e o programador da aplicação não pode acidentalmente esquecer de enviá-la. O comando NOTIFY interage com as transações SQL de maneiras importantes. Em primeiro lugar, se o comando NOTIFY for executado dentro de uma transação o evento de notificação não será enviado até que, e a menos que, a transação seja efetivada. Este comportamento é apropriado, porque se a transação for interrompida todos os comandos dentro desta serão sem efeito, incluindo o NOTIFY. Mas, por outro lado, pode ser desconcertante quando se espera que os eventos de notificação sejam enviados imediatamente. Em segundo lugar, se a sessão ouvinte receber um sinal de notificação durante o tempo em que está executando uma transação, o evento de notificação não será entregue ao seu cliente conectado antes que a transação esteja completa (seja efetivada ou interrompida). Novamente o raciocínio é: se a notificação for enviada dentro de uma transação interrompida posteriormente, se deseja que a notificação seja desfeita de alguma maneira — mas o servidor não pode “pegar de volta” uma notificação após tê-la enviado para o cliente. Portanto, os eventos de notificação somente são entregues entre transações. O resultado final desta situação é que, as aplicações que utilizam o comando NOTIFY para sinalização em tempo real devem tentar manter suas transações curtas. O comando NOTIFY se comporta como os sinais do Unix sob um aspecto importante: se o mesmo nome de notificação for sinalizado diversas vezes em uma sucessão rápida, os receptores podem receber somente um evento de notificação para várias execuções do comando NOTIFY. Portanto, é uma má idéia depender do número de notificações recebidas. Em vez disso, deve ser utilizado o comando NOTIFY para acordar as aplicações que devem prestar atenção em alguma coisa, e usado um objeto de banco de dados (como uma seqüência) para registrar o que aconteceu, ou quantas vezes aconteceu. É comum a situação onde o cliente que executa o comando NOTIFY estar ouvindo este nome de notificação. Neste caso, este cliente recebe o evento de notificação da mesma forma que todas as outras sessões ouvintes. Dependendo da lógica da aplicação, pode resultar em um trabalho sem utilidade; por exemplo, ler a tabela do banco de dados para encontrar as mesmas atualizações que esta sessão acabou de fazer. É possível evitar este
803
trabalho adicional verificando se o PID do processo servidor da sessão notificadora (presente na mensagem do evento de notificação) é o mesmo PID da própria sessão (disponível pela libpq). Quando forem idênticos, o evento de notificação é o seu próprio trabalho retornando, podendo ser ignorado (Apesar do que foi dito no parágrafo anterior, esta técnica é segura. O PostgreSQL mantém as autonotificações separadas das notificações vindas de outras sessões e, portanto, não é possível perder uma notificação externa ignorando as próprias notificações).
Parâmetros nome Nome da notificação a ser sinalizada (qualquer identificador).
Exemplos Configurar e executar a seqüência ouvir/notificar usando a aplicação psql: => LISTEN virtual; => NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448.
Compatibilidade Não existe o comando NOTIFY no padrão SQL.
Veja também LISTEN, UNLISTEN
804
PREPARE Nome PREPARE — prepara um comando para execução
Sinopse PREPARE nome [ (tipo_de_dado [, ...] ) ] AS comando
Descrição O comando PREPARE cria um comando preparado. Um comando preparado é um objeto no lado servidor que pode ser usado para otimizar o desempenho. Quando o comando PREPARE é executado, o comando especificado é analisado, reescrito e planejado. Após isso, quando forem emitidos comandos EXECUTE o comando preparado precisa apenas ser executado. Assim os estágios de análise, reescrita e planejamento são realizados apenas uma vez, e não todas as vezes que o comando é executado. Os comandos preparados podem receber parâmetros: valores que são substituídos no comando quando este é executado. Para incluir parâmetros no comando preparado, deve ser fornecida uma lista de tipos de dado no comando PREPARE e no próprio comando a ser preparado, referenciando os parâmetros pela sua posição utilizando $1, $2, etc. Ao executar o comando devem ser especificados os valores reais destes parâmetros no comando EXECUTE. Consulte o comando EXECUTE para obter mais informações. Os comandos preparados somente continuam existindo enquanto a sessão de banco de dados corrente existir. Quando a sessão termina o comando preparado é esquecido e, portanto, deve ser recriado antes de poder ser usado novamente. Isto significa, também, que o mesmo comando preparado não pode ser usado simultaneamente por vários clientes do banco de dados; entretanto, cada cliente pode criar e usar o seu próprio comando preparado. A maior vantagem de desempenho dos comandos preparados acontece quando uma única sessão é usada para processar um grande número de comandos semelhantes. A diferença no desempenho é particularmente significativa quando os comandos possuem um plano ou reescrita complexos como, por exemplo, um comando envolvendo a junção de muitas tabelas, ou requerendo a aplicação de várias regras. Se o comando for relativamente simples de ser planejado e reescrito, e relativamente dispendioso para ser executado, fica mais difícil perceber a vantagem de desempenho dos comandos preparados.
Parâmetros nome Um nome arbitrário dado a este comando preparado. Deve ser único dentro da mesma sessão, sendo usado em seguida para executar ou remover o comando preparado anteriormente. tipo_de_dado O tipo de dado do parâmetro do comando preparado. Para fazer referência aos parâmetros no comando preparado são usados $1, $2, etc. comando Um entre SELECT, INSERT, UPDATE ou DELETE.
Observações Em algumas situações o plano de comando produzido para o comando preparado será inferior ao plano de comando que seria escolhido se o comando fosse submetido e executado normalmente. Isto se deve ao fato de quando o comando é planejado, e o planejador tenta determinar o plano de comando ótimo, os valores verdadeiros dos parâmetros especificados no comando não estão disponíveis. O PostgreSQL coleta estatísticas sobre a distribuição dos dados na tabela, e pode usar valores constantes no comando para fazer suposições
805
sobre o resultado provável da execução do comando. Como estes dados não estão disponíveis ao planejar comandos preparados com parâmetros, o plano escolhido pode ser inferior ao ótimo. Para examinar o plano de comando escolhido pelo PostgreSQL para o comando preparado, deve ser utilizado o comando EXPLAIN EXECUTE. Para obter mais informações sobre planejamento de comandos e estatísticas coletadas pelo PostgreSQL para esta finalidade, veja a documentação do comando ANALYZE.
Compatibilidade O padrão SQL inclui o comando PREPARE, mas apenas para utilização na linguagem SQL incorporada (embedded). Esta versão do comando PREPARE também utiliza uma sintaxe um pouco diferente.
806
REINDEX Nome REINDEX — reconstrói índices
Sinopse REINDEX { DATABASE | TABLE | INDEX } nome [ FORCE ]
Descrição O comando REINDEX reconstrói um índice baseado nos dados armazenados na tabela do índice, substituindo a cópia antiga do índice. Existem dois motivos principais para utilizar o comando REINDEX: •
O índice está corrompido, e não contém mais dados válidos. Embora na teoria esta situação nunca deva ocorrer, na prática os índices podem ficar corrompidos por causa de erros de programação ou falhas nos equipamentos. O comando REINDEX provê um método de recuperação.
•
O índice em questão contém muitas páginas de índice mortas que não estão sendo reutilizadas. Esta situação pode acontecer com índices B-tree no PostgreSQL sob certos padrões de acesso. O comando REINDEX fornece uma maneira para reduzir o consumo de espaço do índice através da escrita de uma nova versão do índice sem as páginas mortas. Veja a Seção 21.2 para obter mais informações.
Parâmetros DATABASE
Reconstrói todos os índices do sistema do banco de dados especificado. Os índices das tabelas dos usuários não são processados. Também, os índices nos catálogos do sistema compartilhados são pulados, exceto no modo autônomo (veja abaixo). TABLE
Reconstrói todos os índices da tabela especificada. Se a tabela possuir uma tabela secundária “TOAST”, esta também é reindexada. INDEX
Reconstrói o índice especificado. nome O nome do banco de dados, tabela ou índice a ser reindexado. Os nomes das tabelas e dos índices podem ser qualificados pelo esquema. FORCE
Esta é uma opção obsoleta; se for especificada será ignorada.
Observações Havendo suspeita que um índice de uma tabela do usuário está corrompido, é possível simplesmente reconstruir este índice, ou todos os índices da tabela, usando o comando REINDEX INDEX ou o comando REINDEX TABLE. Outra forma de lidar com o problema de índice corrompido em tabela do usuário é simplesmente eliminá-lo e recriá-lo. Pode ser preferida esta forma para manter alguma aparência de uma operação normal em uma tabela. O comando REINDEX obtém um bloqueio exclusivo da tabela, enquanto o comando CREATE INDEX bloqueia a escrita mas não a leitura da tabela. A situação fica mais difícil quando é necessário recuperar um índice corrompido de uma tabela do sistema. Neste caso é importante para o sistema não ter usado nenhum dos índices suspeitos (Sem dúvida, neste tipo de cenário pode acontecer que o processo servidor caia tão logo a inicialização comece por depender de índices
807
corrompidos). Para recuperar com segurança o servidor deve ser inicializado com a opção -P, que impede a utilização de índice para procura em catálogo do sistema. Uma forma de fazer, é parar o postmaster e inicializar o servidor PostgreSQL autônomo com a opção -P incluída na linha de comando. Em seguida pode ser executado REINDEX DATABASE, REINDEX TABLE ou REINDEX INDEX, dependendo de quanto se deseja reconstruir. Em caso de dúvida deve ser usado REINDEX DATABASE para selecionar a reconstrução de todos os índices do sistema no banco de dados. Depois a sessão do servidor autônomo deve ser encerrada, e reiniciado o servidor normal. Veja a página de referência do postgres para obter mais informações sobre como interagir com a interface do servidor autônomo. Como alternativa, pode ser iniciada uma sessão normal do servidor com a opção -P incluída nas opções de linha de comando. O método para se fazer isto varia entre clientes, mas em todos os clientes baseados na biblioteca libpq é possível definir a variável de ambiente PGOPTIONS com o valor -P antes de iniciar o cliente. Observe que embora este método não requeira o bloqueio dos outros clientes, ainda assim é sensato evitar que outros usuários se conectem ao banco de dados danificado até os reparos estarem completos. Havendo suspeita que algum dos índices dos catálogos do sistema compartilhados esteja corrompido (pg_database, pg_group ou pg_shadow), então o servidor autônomo deve ser usado para fazer o reparo. O comando REINDEX não processa os catálogos compartilhados no modo multiusuário. Para todos os índices, exceto os catálogos do sistema compartilhados, o comando REINDEX é seguro quanto à queda e transação (crash-safe e transaction-safe). O comando REINDEX não é seguro quanto à queda para os índices compartilhados, e por esse motivo não é permitido durante a operação normal. Se uma falha ocorrer durante a reindexação de um destes catálogos no modo autônomo, não será possível reiniciar o servidor normal até o problema ser resolvido (O sintoma típico de um índice compartilhado reconstruído parcialmente são erros “index is not a btree”). Antes do PostgreSQL 7.4, o comando REINDEX TABLE não processava automaticamente as tabelas TOAST e, portanto, estas tinham de ser reindexadas através de comandos separados. Isto ainda é possível, porém redundante.
Exemplos Recriar os índices da tabela minha_tabela: REINDEX TABLE minha_tabela;
Reconstruir um único índice: REINDEX INDEX meu_indice;
Reconstruir todos os índices do sistema de um determinado banco de dados, sem confiar que estejam válidos: $ export PGOPTIONS="-P" $ psql bd_danificado ... bd_danificado=> REINDEX DATABASE bd_danificado; bd_danificado=> \q
Compatibilidade Não existe o comando REINDEX no padrão SQL.
808
RESET Nome RESET — redefine o valor de um parâmetro em tempo de execução com seu valor padrão
Sinopse RESET nome RESET ALL
Descrição O comando RESET redefine parâmetros em tempo de execução, colocando em cada um deles o seu respectivo valor padrão. O comando RESET é um forma alternativa de escrever SET parâmetro TO DEFAULT
Veja o comando SET para obter detalhes. O valor padrão é definido como sendo o valor que o parâmetro deveria ter, se nenhum comando SET tivesse sido executado para este parâmetro na sessão corrente. A origem do valor padrão pode ser o valor padrão de compilação, o arquivo de configuração, opções da linha de comando, ou definições por banco de dados ou por usuário. Veja a Seção 16.4 para obter detalhes. Consulte a página de referência do comando SET para obter detalhes sobre o comportamento em transações do comando RESET.
Parâmetros nome O nome de um parâmetro em tempo de execução. Consulte o comando SET para ver a relação. ALL
Redefine todos os parâmetros em tempo de execução, que podem ser definidos, colocando em cada um deles o seu respectivo valor padrão.
Exemplos Definir a variável de configuração datestyle com seu valor padrão: RESET datestyle;
Definir a variável de configuração geqo com seu valor padrão: RESET geqo;
Compatibilidade O comando RESET é uma extensão do PostgreSQL.
809
REVOKE Nome REVOKE — revoga privilégios de acesso
Sinopse REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] } ON [ TABLE ] nome_da_tabela [, ...] FROM { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] } ON DATABASE nome_do_banco_de_dados [, ...] FROM { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { EXECUTE | ALL [ PRIVILEGES ] } ON FUNCTION nome_da_função ([tipo, ...]) [, ...] FROM { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE nome_da_linguagem [, ...] FROM { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] } ON SCHEMA nome_do_esquema [, ...] FROM { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ CASCADE | RESTRICT ]
Descrição O comando REVOKE revoga, de um ou mais usuários ou grupos de usuários, privilégios concedidos anteriormente. A palavra chave PUBLIC se refere ao grupo contendo todos os usuários, definido implicitamente. Veja na descrição do comando GRANT o significado de cada de privilégio. Observe que um determinado usuário possui a soma dos privilégios concedidos diretamente para o próprio usuário mais os privilégios concedidos para os grupos dos quais é membro no momento, mais os privilégios concedidos para PUBLIC. Daí, por exemplo, revogar o privilégio SELECT de PUBLIC não significa, necessariamente, que todos os usuários perdem o privilégio SELECT para o objeto: àqueles que receberam o privilégio diretamente, ou por meio de um grupo, permanecem com o privilégio. Se for especificado GRANT OPTION FOR somente a opção de concessão do privilégio é revogada, e não o próprio privilégio. Se o usuário possui um privilégio com opção de concessão, e concedeu este privilégio para outros usuários, então os privilégios que estes outros usuários possuem são chamados de privilégios dependentes. Se o privilégio ou a opção de concessão que o primeiro usuário possui for revogada, e existirem privilégios dependentes, estes privilégios dependentes também são revogados se for especificado CASCADE, senão a ação
810
de revogar falha. Esta revogação recursiva somente afeta os privilégios que foram concedidos através de uma cadeia de usuários começando pelo usuário objeto deste comando REVOKE. Portanto, os usuários afetados poderão manter o privilégio se este privilégio também foi concedido por outros usuários.
Observações Use o comando \z da aplicação psql para ver os privilégios concedidos para os objetos existentes. Consulte, também, o comando GRANT para obter informações sobre o formato. Um determinado usuário pode revogar somente os privilégios que foram concedidos diretamente por este usuário. Se, por exemplo, o usuário A conceder um privilégio com opção de concessão para o usuário B, e o usuário B por sua vez conceder o privilégio para o usuário C, então o usuário A não poderá revogar diretamente o privilégio de C. Em vez disso, o usuário A poderá revogar a opção de concessão do usuário B e usar a opção CASCADE, para que o privilégio seja por sua vez revogado do usuário C. Se um superusuário decidir executar o comando GRANT ou o comando REVOKE, o comando é executado como se tivesse sido executado pelo dono do objeto afetado. Uma vez que todos os privilégios partem do dono do objeto (possivelmente de forma indireta através de cadeias de opções de concessão), um superusuário pode revogar todos os privilégios, mas pode ser necessário usar CASCADE conforme mostrado acima.
Exemplos Revogar o privilégio de inserção na tabela filmes concedido para todos os usuários: REVOKE INSERT ON filmes FROM PUBLIC;
Revogar todos os privilégios concedidos ao usuário manuel para a visão vis_tipos: REVOKE ALL PRIVILEGES ON vis_tipos FROM manuel;
Compatibilidade As notas sobre compatibilidade presentes no comando GRANT se aplicam de forma análoga ao comando REVOKE. O sumário da sintaxe é: REVOKE [ GRANT OPTION FOR ] privilégios ON objeto [ ( coluna [, ...] ) ] FROM { PUBLIC | nome_do_usuário [, ...] } { RESTRICT | CASCADE }
Um entre RESTRICT ou CASCADE é necessário de acordo com o padrão, mas o PostgreSQL assume RESTRICT por padrão.
Veja também GRANT
811
ROLLBACK Nome ROLLBACK — interrompe a transação corrente
Sinopse ROLLBACK [ WORK | TRANSACTION ]
Descrição O comando ROLLBACK desfaz a transação corrente, desconsiderando todas as modificações realizadas por esta transação.
Parâmetros WORK TRANSACTION
Palavras chave opcionais. Não produzem nenhum efeito.
Observações Use o comando COMMIT para terminar uma transação bem-sucedida. A utilização do ROLLBACK fora de uma transação não causa nenhum problema, mas causa uma mensagem de advertência.
Exemplos Para anular todas as modificações: ROLLBACK;
Compatibilidade O padrão SQL somente especifica as duas formas ROLLBACK e ROLLBACK WORK. Fora isso, este comando está em conformidade total.
Veja também BEGIN, COMMIT
812
SELECT Nome SELECT — retorna linhas de uma tabela ou de uma visão
Sinopse SELECT [ ALL | DISTINCT [ ON ( expressão [, ...] ) ] ] * | expressão [ AS nome_de_saída ] [, ...] [ FROM item_do_from [, ...] ] [ WHERE condição ] [ GROUP BY expressão [, ...] ] [ HAVING condição [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] seleção ] [ ORDER BY expressão [ ASC | DESC | USING operador ] [, ...] ] [ LIMIT { contador | ALL } ] [ OFFSET início ] [ FOR UPDATE [ OF nome_da_tabela [, ...] ] ] onde item_do_from pode ser um entre: [ ONLY ] nome_da_tabela [ * ] [ [ AS ] aliás [ ( aliás_de_coluna [, ...] ) ] ] ( seleção ) [ AS ] aliás [ ( aliás_de_coluna [, ...] ) ] nome_da_função ( [ argumento [, ...] ] ) [ AS ] aliás [ ( aliás_de_coluna [, ...] | definição_de_coluna [, ...] ) ] nome_da_função ( [ argumento [, ...] ] ) AS ( definição_de_coluna [, ...] ) item_do_from [ NATURAL ] tipo_de_junção item_do_from [ ON condição_de_junção | USING ( coluna_de_junção [, ...] ) ]
Descrição O comando SELECT retorna linhas de uma ou mais tabelas. O processamento geral do comando SELECT está descrito abaixo: 1. Todos os elementos da lista FROM são computados; cada elemento na lista FROM é uma tabela real ou virtual. Quando é especificado mais de um elemento na lista FROM, é feita uma junção cruzada entre estes elementos (Veja a Cláusula FROM abaixo). 2. Se for especificada a cláusula WHERE, todas as linhas que não satisfazem a condição são eliminadas da saída (Veja a Cláusula WHERE abaixo). 3. Se for especificada a cláusula GROUP BY, a saída é dividida em grupos de linhas que correspondem a um ou mais valores. Se a cláusula HAVING estiver presente, são eliminados os grupos que não satisfazem à condição especificada (Veja a Cláusula GROUP BY e a Cláusula HAVING abaixo). 4. Usando os operadores UNION, INTERSECT e EXCEPT podem ser combinadas as saídas de vários comandos SELECT para formar um único conjunto de resultados. O operador UNION retorna todas as linhas presentes em um ou nos dois conjuntos de resultados. O operador INTERSECT retorna todas as linhas presentes nos dois conjuntos de resultados. O operador EXCEPT retorna as linhas presentes no primeiro conjunto de resultados mas não no segundo. Em todos estes três casos as linhas duplicadas são eliminadas, a menos que ALL seja especificado (Veja a Cláusula UNION, a Cláusula INTERSECT e Cláusula EXCEPT abaixo). 5. As linhas de saída reais são computadas utilizando as expressões de saída do comando SELECT para cada linha selecionada (Veja a Lista do SELECT abaixo).
813
6. Se for especificada a cláusula ORDER BY, as linhas retornadas são classificadas segundo a ordem especificada. Se a cláusula ORDER BY não for especificada, as linhas são retornadas na ordem em que o sistema considerar mais rápido de produzir (Veja a Cláusula ORDER BY abaixo). 7. A cláusula DISTINCT remove do resultado as linhas duplicadas 1 2 . A cláusula DISTINCT ON remove as linhas que correspondem a todas as expressões especificadas. A cláusula ALL (o padrão) retorna todas as linhas candidatas, incluindo as duplicadas (Veja a Cláusula DISTINCT abaixo). 8. Se for especificada a cláusula LIMIT ou a cláusula OFFSET, o comando SELECT retorna somente um subconjunto das linhas do resultado (Veja a Cláusula LIMIT abaixo) 3 . 9. A cláusula FOR UPDATE faz o comando SELECT bloquear as linhas selecionadas contra atualizações concorrentes (Veja a Cláusula FOR UPDATE abaixo) 4 . É necessário possuir o privilégio SELECT na tabela para poder ler seus valores. A utilização de FOR UPDATE requer também o privilégio UPDATE.
Parâmetros Cláusula FROM A cláusula FROM especifica uma ou mais tabelas fonte para o comando SELECT. Se várias fontes forem especificadas, o resultado será o produto cartesiano (junção cruzada) de todas as fontes, mas normalmente são incluídas condições de qualificação para restringir as linhas retornadas a um pequeno subconjunto do produto cartesiano. A cláusula FROM pode conter os seguintes elementos: nome_da_tabela O nome (opcionalmente qualificado pelo esquema) de uma tabela ou de uma visão existente. Se a cláusula ONLY for especificada, somente esta tabela será varrida. Se a cláusula ONLY não for especificada, esta tabela e todas as suas tabelas descendentes (se existirem) serão varridas. Pode ser anexado um * ao nome da tabela para indicar que as tabelas descendentes devem ser varridas, mas na versão corrente este é o comportamento padrão; nas versões anteriores a 7.1 o comportamento padrão era ONLY. O comportamento padrão pode ser modificado mudando o valor da opção de configuração sql_interitance. aliás Um nome substituto para o item da cláusula FROM contendo o aliás. O aliás é utilizado para abreviar, ou para eliminar ambigüidade em auto-junções (onde a mesma tabela é varrida várias vezes). Quando se fornece um aliás, o nome verdadeiro da tabela ou da função fica totalmente escondido; se, por exemplo, for declarado FROM foo AS f, o restante do comando SELECT deve fazer referência a este item do FROM como f, e não como foo. Se for escrito um aliás, também pode ser escrita uma lista de aliases de coluna para fornecer nomes substitutos para uma ou mais colunas da tabela. seleção Pode haver sub-SELECT na cláusula FROM. Atua como se sua saída fosse criada como uma tabela temporária pela duração deste único comando SELECT. Observe que o sub-SELECT deve estar entre parênteses, e que um aliás deve ser especificado para o mesmo. nome_da_função Podem estar presentes na cláusula FROM chamadas de função (É especialmente útil no caso das funções que retornam um conjunto de resultados, mas pode ser usada qualquer função). Atua como se a sua saída fosse criada como uma tabela temporária pela duração deste único comando SELECT. Também pode ser utilizado um aliás. Se for escrito um aliás, também pode ser escrita uma lista de aliases de coluna para fornecer nomes substitutos para um ou mais atributos do tipo composto retornado pela função. Se a função tiver sido definida como retornando o tipo de dado record então deve estar presente um aliás, ou a palavra chave AS seguida por uma lista de definições de coluna na forma ( nome_de_coluna tipo_de_dado [, ... ] ). A lista de definições de coluna deve corresponder ao número e tipo reais das colunas retornadas pela função.
814
tipo_de_junção Um entre • [ INNER ] JOIN • LEFT [ OUTER ] JOIN • RIGHT [ OUTER ] JOIN • FULL [ OUTER ] JOIN • CROSS JOIN
Para os tipos de junção INNER e OUTER deve ser especificada uma condição de junção designando exatamente um entre NATURAL, ON condição_de_junção ou USING (coluna_de_junção [, ...]). Veja abaixo o significado. Para CROSS JOIN, nenhuma destas cláusulas pode estar presente. A cláusula JOIN combina dois itens da cláusula FROM. Se for necessário devem ser utilizados parênteses para determinar a ordem de aninhamento. Na ausência de parênteses, a cláusula JOIN aninha da esquerda para a direita. Em todos os casos a cláusula JOIN tem nível de precedência superior ao das vírgulas que separam os itens da cláusula FROM. CROSS JOIN e INNER JOIN produzem um produto cartesiano simples, o mesmo resultado obtido listando os dois itens no nível superior da cláusula FROM, mas restrito pela condição de junção (se houver). CROSS JOIN é equivalente a INNER JOIN ON (TRUE), ou seja, nenhuma linha é removida pela qualificação. Estes tipos de junção são apenas uma notação conveniente, uma vez que não fazem nada que não poderia ser feito usando simplesmente FROM e WHERE. LEFT OUTER JOIN retorna todas as linhas presentes no produto cartesiano qualificado (ou seja, todas as linhas combinadas que passam pela sua condição de junção), mais uma cópia de cada linha da tabela à esquerda para a qual não há linha na tabela à direita que passe pela condição de junção. As linhas da tabela à esquerda são estendidas por toda a largura da tabela de junção, inserindo valores nulos para as colunas da tabela à direita. Deve ser observado que somente a condição da própria cláusula JOIN é considerada ao decidir quais linhas possuem correspondência. As condições externas são aplicadas depois.
De forma inversa, RIGHT OUTER JOIN retorna todas as linhas da junção, mais uma linha para cada linha da tabela à direita sem correspondência (estendida com nulos à esquerda). É apenas uma notação conveniente, uma vez que pode ser convertido em LEFT OUTER JOIN trocando as entradas à direita e à esquerda. FULL OUTER JOIN retorna todas as linhas da junção, mais uma linha para cada linha da tabela à esquerda sem correspondência, (estendida com nulos à direita), mais uma linha para cada linha da tabela à direita sem correspondência (estendida com nulos à esquerda). ON condição_de_junção
A condição_de_junção é uma expressão que resulta em um valor do tipo boolean (semelhante à cláusula WHERE) que especifica quais linhas da junção são consideradas correspondentes. USING (coluna_de_junção [, ...])
A cláusula com a forma USING ( a, b, ... ) é uma abreviação de ON tabela_à_esquerda.a = tabela_à_direita.a AND tabela_à_esquerda.b = tabela_à_direita.b .... USING também implica que somente será incluída na saída da junção uma de cada par de colunas equivalentes, e não as duas. NATURAL NATURAL é uma forma abreviada para a lista USING mencionando todas as colunas das duas tabelas que possuem o mesmo nome.
Cláusula WHERE A cláusula opcional WHERE possui a forma geral WHERE condição
815
onde condição é uma expressão que produz um resultado do tipo boolean 5 . Todas as linhas que não satisfazem a esta condição são eliminadas da saída. A linha satisfaz a condição se retorna verdade quando os valores reais da linha são colocados no lugar das variáveis que os referenciam. Cláusula GROUP BY A cláusula opcional GROUP BY possui a forma geral GROUP BY expressão [, ...]
A cláusula GROUP BY condensa em uma única linha todas as linhas selecionadas que compartilham os mesmos valores para as expressões de agrupamento. A expressão pode ser o nome de uma coluna da entrada, ou o nome ou o número ordinal de uma coluna da saída (lista de itens do SELECT), ou uma expressão arbitrária formada por valores das colunas da entrada. Havendo ambigüidade, o nome na cláusula GROUP BY será interpretado como sendo o nome da coluna da entrada, e não o nome da coluna da saída. As funções de agregação, caso sejam usadas, são computadas entre todas as linhas que constituem cada grupo, produzindo um valor separado para cada grupo (enquanto sem GROUP BY, uma agregação produz um único valor computado entre todas as linhas selecionadas). Quando GROUP BY está presente, não é válido a lista de expressões do SELECT fazer referência a colunas não agrupadas, exceto dentro das funções de agregação, uma vez que haveria mais de um valor possível retornado para uma coluna não agrupada. Cláusula HAVING A cláusula opcional HAVING possui a forma geral HAVING condição
onde condição é especificada da mesma forma que na cláusula WHERE. A cláusula HAVING elimina os grupos de linhas que não satisfazem a condição. A cláusula HAVING é diferente da cláusula WHERE: WHERE filtra individualmente as linhas antes do GROUP BY ser aplicado, enquanto HAVING filtra grupos de linhas criados pelo GROUP BY. Cada coluna referenciada na condição deve referenciar sem ambigüidade uma coluna de agrupamento, a menos que a referência apareça dentro de uma função de agregação. A presença da cláusula HAVING torna a consulta uma consulta agrupada, mesmo que não exista a cláusula GROUP BY. É o mesmo que acontece quando a consulta contém funções de agregação mas não possui a cláusula GROUP BY. Todas as linhas selecionadas são consideradas como formando um único grupo, e tanto a lista do SELECT quanto a cláusula HAVING somente podem fazer referência a colunas da tabela dentro de funções de agregação. Este tipo de consulta gera uma única linha se a condição da cláusula HAVING for verdade, ou nenhuma linha se não for verdade. Exemplo 1. Utilização de HAVING sem GROUP BY no SELECT O exemplo abaixo mostra a utilização da cláusula HAVING sem a cláusula GROUP BY no comando SELECT. É criada a tabela produtos e são inseridas cinco linhas. Quando a cláusula HAVING exige a presença de mais de cinco linhas na tabela, a consulta não retorna nenhuma linha. 6 7 => => => => => =>
create insert insert insert insert insert
global temporary table produtos(codigo int, valor float); into produtos values (1, 102); into produtos values (2, 104); into produtos values (3, 202); into produtos values (4, 203); into produtos values (5, 204);
=>
select avg(valor) from produtos;
avg ----163 (1 linha) =>
select avg(valor) from produtos having count(*)>=5;
816
avg ----163 (1 linha) =>
select avg(valor) from produtos having count(*)=5;
avg ----163 (1 linha) =>
select avg(valor) from produtos having count(*)>5;
avg ----(0 linhas)
Cláusula UNION A cláusula UNION possui a forma geral comando_de_seleção UNION [ ALL ] comando_de_seleção
onde comando_de_seleção é qualquer comando SELECT sem as cláusulas ORDER BY, LIMIT e FOR UPDATE (as cláusulas ORDER BY e LIMIT podem ser aplicadas a uma subexpressão se esta estiver entre parênteses. Sem os parênteses, estas cláusulas são consideradas como aplicadas ao resultado da cláusula UNION, e não à sua expressão de entrada à direita). O operador UNION computa o conjunto formado pela união das linhas retornadas pelos comandos SELECT envolvidos. Uma linha está presente no conjunto união dos dois conjuntos de resultados se estiver presente em pelo menos um destes dois conjuntos de resultados. Os dois comandos SELECT que representam os operandos diretos do operador UNION devem produzir o mesmo número de colunas, e as colunas correspondentes devem possuir tipos de dado compatíveis. O resultado do operador UNION não contém nenhuma linha duplicada, a menos que a opção ALL seja especificada. ALL não permite a eliminação das duplicatas. Havendo vários operadores UNION no mesmo comando SELECT, estes são avaliados da esquerda para a direita, a menos que os parênteses indiquem o contrário. Atualmente não pode ser especificado FOR UPDATE nem para o resultado do operador UNION nem para qualquer entrada do operador UNION. Cláusula INTERSECT A cláusula INTERSECT possui a forma geral comando_de_seleção INTERSECT [ ALL ] comando_de_seleção
onde comando_de_seleção é qualquer comando SELECT sem as cláusulas ORDER BY, LIMIT e FOR UPDATE.
O operador INTERSECT computa o conjunto formado pela interseção das linhas retornadas pelos comandos SELECT envolvidos. Uma linha está na interseção dos dois conjuntos de resultados se estiver presente nos dois conjuntos de resultados. O resultado do operador INTERSECT não contém nenhuma linha duplicada, a menos que a opção ALL seja especificada. Usando ALL, uma linha contendo m duplicatas na tabela à esquerda e n duplicatas na tabela à direita, aparece min(m,n) vezes no conjunto de resultados. Havendo vários operadores INTERSECT no mesmo comando SELECT, estes são avaliados da esquerda para a direita, a menos que os parênteses indiquem outra ordem. O operador INTERSECT tem nível de precedência
817
superior ao do operador UNION, ou seja, A UNION B INTERSECT C é lido como A UNION (B INTERSECT C). Cláusula EXCEPT A cláusula EXCEPT possui a forma geral comando_de_seleção EXCEPT [ ALL ] comando_de_seleção
onde comando_de_seleção é qualquer comando SELECT sem as cláusulas ORDER BY, LIMIT e FOR UPDATE.
O operador EXCEPT computa o conjunto de linhas presentes no resultado do comando SELECT à esquerda, mas que não estão presentes no resultado do comando à direita. O resultado do operador EXCEPT não contém nenhuma linha duplicada, a menos que a cláusula ALL seja especificada. Usando ALL, uma linha que possua m duplicatas na tabela à esquerda e n duplicatas na tabela à direita aparece max(m-n,0) vezes no conjunto de resultados. Havendo vários operadores EXCEPT no mesmo comando SELECT, estes são processados da esquerda para a direita, a menos que os parênteses especifiquem outra ordem. O operador EXCEPT possui o mesmo nível de precedência do operador UNION. Lista do SELECT A lista do SELECT (entre as palavras chave SELECT e FROM) especifica expressões que formam as linhas de saída do comando SELECT. As expressões podem (e geralmente fazem) referenciar colunas computadas na cláusula FROM. Usando a cláusula AS nome_de_saída, pode ser especificado outro nome para uma coluna da saída. Este nome é usado, principalmente, como rótulo da coluna mostrada. Também pode ser usado para fazer referência ao valor da coluna nas cláusulas ORDER BY e GROUP BY, mas não nas cláusulas WHERE e HAVING; nestas, a expressão deve ser escrita. Em vez da expressão pode ser escrito * na lista de saída, como abreviação para todas as colunas das linhas selecionadas. Também pode ser escrito nome_da_tabela.* como abreviação das colunas provenientes apenas desta tabela. Cláusula ORDER BY A cláusula opcional ORDER BY possui a forma geral ORDER BY expressão [ ASC | DESC | USING operador ] [, ...]
onde expressão pode ser o nome ou o número ordinal de uma coluna da saída (item da lista do SELECT), ou pode ser uma expressão arbitrária formada por valores das colunas da entrada. A cláusula ORDER BY faz as linhas do resultado serem classificadas de acordo com as expressões especificadas. Se duas linhas são iguais de acordo com a expressão mais à esquerda, estas são comparadas de acordo com a próxima expressão, e assim por diante. Se forem iguais de acordo com todas as expressões especificadas, são retornadas em uma ordem dependente da implementação. O número ordinal se refere à posição ordinal (esquerda para a direita) da coluna do resultado. Esta funcionalidade torna possível definir uma ordenação baseada em uma coluna que não possui um nome único. Isto nunca é absolutamente necessário, porque sempre é possível atribuir um nome à coluna do resultado usando a cláusula AS. Também é possível utilizar expressões arbitrárias na cláusula ORDER BY, incluindo colunas que não aparecem na lista de resultado do SELECT. Portanto, o seguinte comando é válido: SELECT nome FROM distribuidores ORDER BY codigo;
A limitação desta funcionalidade é que a cláusula ORDER BY aplicada ao resultado de UNION, INTERSECT ou EXCEPT pode especificar apenas nomes de coluna ou números, mas não expressões. Se a expressão no ORDER BY for simplesmente um nome correspondendo tanto ao nome de uma coluna do resultado quanto ao nome de uma coluna da entrada, o ORDER BY interpreta como sendo o nome da coluna do
818
resultado. Esta é a escolha oposta à feita pelo GROUP BY na mesma situação. Esta incoerência existe para ficar compatível com o padrão SQL. Pode ser adicionada, opcionalmente, a palavra chave ASC (ascendente) ou DESC (descendente) após cada expressão na cláusula ORDER BY. Se nenhuma das duas for especificada, ASC é assumido por padrão. Como alternativa, pode ser especificado o nome de um operador de ordenação específico na cláusula USING. Geralmente ASC é equivalente a USING < e geralmente DESC é equivalente a USING > (Mas o criador de um tipo de dado definido pelo usuário pode definir exatamente qual é a ordem de classificação padrão, podendo corresponder a operadores com outros nomes). O valor nulo é classificado em uma posição mais alta do que qualquer outro valor. Em outras palavras, na ordem de classificação ascendente os valores nulos ficam no final, e na ordem de classificação descendente os valores nulos ficam no início. 8 Dados na forma de cadeias de caracteres são classificados de acordo com a ordem de classificação (collation 9 ) estabelecida quando o agrupamento de bancos de dados foi inicializado. Cláusula LIMIT A cláusula LIMIT consiste em duas subcláusulas independentes: LIMIT { contador | ALL } OFFSET início
onde contador especifica o número máximo de linhas a serem retornadas, enquanto início especifica o número de linhas a serem puladas antes de começar a retornar as linhas. Quando as duas são especificadas, as início primeiras linhas são puladas antes de começar a contar as contador linhas a serem retornadas. Ao se usar a cláusula LIMIT é uma boa idéia usar também a cláusula ORDER BY para colocar as linhas do resultado dentro de uma ordem única. Caso contrário será retornado um subconjunto imprevisível de linhas da consulta — pode-se estar querendo receber da décima a vigésima linha, mas da décima a vigésima em que ordem? Não é possível saber qual será a ordem, a não ser que ORDER BY seja especificado. O planejador de comandos leva LIMIT em consideração ao gerar o plano da consulta, por isso é muito provável serem obtidos planos diferentes (produzindo linhas em ordens diferentes) dependendo do que for especificado para LIMIT e OFFSET. Portanto, utilizar valores diferentes para LIMIT/OFFSET para selecionar subconjuntos diferentes do resultado da consulta produz resultados inconsistentes, a não ser que se obrigue uma ordem previsível para os resultados utilizando ORDER BY. Isto não está errado; isto é uma conseqüência direta do fato do SQL não prometer retornar os resultados de uma consulta em nenhuma ordem específica, a não ser que ORDER BY seja utilizado para impor esta ordem. Cláusula DISTINCT Se for especificada a cláusula DISTINCT, todas as linhas duplicadas são removidas do conjunto de resultados (é mantida uma linha para cada grupo de duplicatas). A cláusula ALL especifica o oposto: todas as linhas são mantidas; este é o padrão. DISTINCT ON ( expressão [, ...] ) preserva apenas a primeira linha de cada conjunto de linhas onde as expressões fornecidas forem iguais. As expressões em DISTINCT ON são interpretadas usando as mesmas regras da cláusula ORDER BY (veja acima). Deve ser observado que a “primeira linha” de cada conjunto é imprevisível, a menos que seja utilizado ORDER BY para garantir que a linha desejada apareça na frente. Por
exemplo, SELECT DISTINCT ON (local) local, data, condicao FROM tbl_condicao_climatica ORDER BY local, data DESC;
mostra o relatório de condição climática mais recente para cada local, mas se não tivesse sido usado ORDER BY para forçar a ordem descendente dos valores da data para cada local, teria sido obtido um relatório com datas imprevisíveis para cada local.
819
As expressões em DISTINCT ON devem corresponder às expressões mais à esquerda no ORDER BY. A cláusula ORDER BY normalmente contém expressões adicionais para determinar a precedência desejada das linhas dentro de cada grupo DISTINCT ON. Cláusula FOR UPDATE A cláusula FOR UPDATE possui a forma FOR UPDATE [ OF nome_da_tabela [, ...] ]
A cláusula FOR UPDATE faz as linhas selecionadas pelo comando SELECT serem bloqueadas como se fosse para atualização. Isto impede a modificação ou exclusão destas linhas por outras transações até a transação corrente terminar. Ou seja, outras transações tentando usar os comandos UPDATE, DELETE ou SELECT FOR UPDATE nestas linhas ficam bloqueadas até a transação corrente terminar. Também, se um comando UPDATE, DELETE, ou SELECT FOR UPDATE de outra transação já tiver bloqueado uma ou várias destas linhas, o SELECT FOR UPDATE fica aguardando a outra transação completar e, então, bloqueia e retorna a linha atualizada (ou nenhuma linha, se a linha foi excluída). Para obter mais explicações veja o Capítulo 12. Se forem especificados nomes de tabelas na cláusula FOR UPDATE, então somente as linhas oriundas destas tabelas são bloqueadas; todas as outras tabelas usadas no SELECT são simplesmente lidas como de costume. FOR UPDATE não pode ser utilizado nos contextos onde as linhas retornadas não podem ser claramente identificadas com as linhas individuais da tabela; por exemplo, não pode ser utilizado junto com agregações. FOR UPDATE pode estar antes de LIMIT para manter a compatibilidade com as versões do PostgreSQL anteriores a 7.3. Entretanto, será executado após o LIMIT e, portanto, este é o lugar adequado para ser escrito.
Exemplos Para efetuar a junção da tabela filmes com a tabela distribuidores: => SELECT f.titulo, f.did, d.nome, f.data_prod, f.tipo -> FROM distribuidores d, filmes f -> WHERE f.did = d.did titulo | did | nome | data_prod | tipo -------------------+-----+--------------+------------+---------The Third Man | 101 | British Lion | 1949-12-23 | Drama The African Queen | 101 | British Lion | 1951-08-11 | Romance ...
Para somar a coluna duracao de todos os filmes, e agrupar os resultados por tipo: => SELECT tipo, sum(duracao) AS total FROM filmes GROUP BY tipo; tipo | total ----------+------Ação | 07:34 Comédia | 02:58 Drama | 14:28 Musical | 06:42 Romance | 04:38
Para somar a coluna duracao de todos os filmes, agrupar os resultados por tipo, e mostrar apenas os grupos com total inferior a 5 horas: => SELECT tipo, sum(duracao) AS total -> FROM filmes -> GROUP BY tipo -> HAVING sum(duracao) < interval '5 hours';
820
tipo | total ----------+------Comédia | 02:58 Romance | 04:38
Os dois exemplos a seguir são formas idênticas de classificação dos resultados individuais de acordo com o conteúdo da segunda coluna (nome): => SELECT * FROM distribuidores ORDER BY nome; => SELECT * FROM distribuidores ORDER BY 2; did | nome -----+-----------------109 | 20th Century Fox 110 | Bavaria Atelier 101 | British Lion 107 | Columbia 102 | Jean Luc Godard 113 | Luso filmes 104 | Mosfilm 103 | Paramount 106 | Toho 105 | United Artists 111 | Walt Disney 112 | Warner Bros. 108 | Westward
O próximo exemplo mostra como obter a união da tabela distribuidores com a tabela atores, restringindo o resultado aos nomes que iniciam pela letra W em cada uma das tabelas. Somente são desejadas linhas distintas, por isso a palavra chave ALL é omitida: distribuidores did | nome -----+-------------108 | Westward 111 | Walt Disney 112 | Warner Bros. ...
atores: id | nome ----+---------------1 | Woody Allen 2 | Warren Beatty 3 | Walter Matthau ...
=> SELECT distribuidores.nome -> FROM distribuidores -> WHERE distribuidores.nome LIKE 'W%' -> UNION -> SELECT atores.nome -> FROM atores -> WHERE atores.nome LIKE 'W%'; nome ---------------Walt Disney Walter Matthau Warner Bros. Warren Beatty Westward Woody Allen
Este exemplo mostra como usar uma função na cláusula FROM, com e sem uma lista de definição de colunas: => CREATE FUNCTION distribuidores(int) RETURNS SETOF distribuidores AS ' '> SELECT * FROM distribuidores WHERE did = $1; '> ' LANGUAGE SQL; SELECT * FROM distribuidores(111);
821
did | nome -----+------------111 | Walt Disney => CREATE FUNCTION distribuidores_2(int) RETURNS SETOF record AS ' '> SELECT * FROM distribuidores WHERE did = $1; '> ' LANGUAGE SQL; SELECT * FROM distribuidores_2(111) AS (f1 int, f2 text); f1 | f2 -----+------------111 | Walt Disney
Compatibilidade Obviamente, o comando SELECT é compatível com o padrão SQL. Entretanto, existem algumas extensões e algumas funcionalidades faltando. Cláusula FROM omitida O PostgreSQL permite omitir a cláusula FROM. Tem uso direto no cômputo de resultados de expressões simples: => SELECT 2+2; ?column? ---------4
Alguns outros bancos de dados SQL não podem fazer isto, a não ser introduzindo uma tabela fictícia de uma linha para executar o comando SELECT. Uma utilização menos óbvia desta funcionalidade é abreviar comandos SELECT comuns de tabelas: => SELECT distribuidores.* WHERE distribuidores.nome = 'Westward'; did | nome -----+---------108 | Westward
Isso funciona porque é adicionado um item implícito no FROM para cada tabela que é referenciada nas outras partes do comando SELECT, mas que não é mencionada no FROM. Ao mesmo tempo em que é uma forma conveniente de abreviar, é fácil ser usado incorretamente. Por exemplo, o comando SELECT distribuidores.* FROM distribuidores d;
provavelmente deve ser um engano; é mais provável que se deseje SELECT d.* FROM distribuidores d;
do que a junção sem restrições SELECT distribuidores.* FROM distribuidores d, distribuidores distribuidores;
que seria obtida na verdade. Para ajudar a detectar este tipo de engano, o PostgreSQL adverte se uma funcionalidade FROM implícita é utilizada em um comando SELECT que também contenha uma cláusula FROM explícita. Também é possível desabilitar a funcionalidade de FROM-implícito definindo a parâmetro ADD_MISSING_FROM como falso.
822
A palavra chave AS No padrão SQL, a palavra chave opcional AS é apenas ruído podendo ser omitida sem afetar o significado. O analisador do PostgreSQL requer esta palavra chave quando uma coluna da saída é renomeada, porque a funcionalidade de extensividade de tipo conduz o analisador a ambigüidades caso não esteja presente. Entretanto, AS é opcional nos itens do FROM. Espaço de nomes disponível para GROUP BY e ORDER BY No padrão SQL92, a cláusula ORDER BY somente pode utilizar nomes ou números das colunas do resultado, enquanto a cláusula GROUP BY somente pode utilizar expressões baseadas nos nomes das colunas da entrada. O PostgreSQL estende estas duas cláusulas para permitir, também, a outra escolha (mas utiliza a interpretação padrão se houver ambigüidade). O PostgreSQL também permite que as duas cláusulas especifiquem expressões arbitrárias. Observe que os nomes que aparecem na expressão sempre são considerados como nomes das colunas da entrada, e não como nomes das colunas do resultado. O SQL:1999 utiliza uma definição um pouco diferente, que não é inteiramente compatível com o SQL-92. Entretanto, na maioria dos casos o PostgreSQL interpreta uma expressão presente em ORDER BY ou GROUP BY da mesma maneira que o SQL:1999. Cláusulas fora do padrão As cláusulas DISTINCT ON, LIMIT e OFFSET não são definidas no padrão SQL.
Notas 1. Oracle — deve ser especificado DISTINCT ou UNIQUE se for desejado que o Oracle retorne apenas uma cópia de cada conjunto de linhas duplicadas selecionadas (esta duas palavras chave são sinônimos). As linhas duplicadas são aquelas com valores correspondentes para cada expressão na lista de seleção; DISTINCT não pode ser especificado quando a lista de seleção contém colunas LOB. Oracle9i SQL Reference - Release 2 (9.2) - Part Number A96540-02 (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96540/statements_103a.htm#2065826) (N. do T.) 2. SQL Server — DISTINCT especifica que somente linhas únicas podem aparecer no conjunto de resultados. Os valores nulos são considerados iguais para as finalidades da palavra chave DISTINCT. SQL Server Books Online (N. do T.) 3. SQL Server — TOP n [PERCENT] especifica que somente as primeiras n linhas do conjunto de resultados devem ser retornadas. n é um inteiro entre 0 e 4294967295. Se também for especificado PERCENT, somente devem ser retornados os primeiros n porcentos de linhas do conjunto de resultados. Quando especificado com PERCENT, n deve ser um inteiro entre 0 e 100. Se a consulta incluir a cláusula ORDER BY, as primeiras n linhas (ou n porcento das linhas) ordenadas pela cláusula ORDER BY são retornadas. Se a consulta não possuir a cláusula ORDER BY, a ordem das linhas é arbitrária. SQL Server Books Online (N. do T.) 4. Oracle — A cláusula FOR UPDATE permite bloquear as linhas selecionadas, não permitindo assim que outros usuários bloqueiem ou atualizem estas linhas até a transação terminar. Esta cláusula somente pode ser especificada no comando SELECT de nível mais alto (não em subseleções). Esta cláusula não pode ser especificada junto com as seguintes construções: o operador DISTINCT, expressão de CURSOR, operadores de conjunto, cláusula GROUP BY e funções de agregação. Oracle9i SQL Reference - Release 2 (9.2) - Part Number A96540-02 (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96540/statements_103a.htm#2066347) (N. do T.) 5. SQL Server — predicado é uma expressão que é avaliada como TRUE, FALSE ou UNKNOWN. Os predicados são usados nas condições de procura das cláusulas WHERE e HAVING, e nas condições de junção das cláusulas FROM. Veja também BETWEEN, CONTAINS, EXISTS, FREETEXT, IN, IS [NOT] NULL e LIKE. SQL Server Books Online (N. do T.) 6. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 7. Oracle — Este exemplo foi executado no Oracle 10g e produziu os mesmos resultados.
823
8. No PostgreSQL, no Oracle e no DB2 o valor nulo é classificado em uma posição mais alta que os demais valores, mas no SQL Server o valor nulo é classificado em uma posição mais baixa que os demais valores. O Oracle permite especificar NULLS FIRST e NULLS LAST, para cada coluna, na cláusula ORDER BY. (N. do T.) 9. collation; collating sequence — Um método para comparar duas cadeias de caracteres comparáveis. Todo conjunto de caracteres possui seu collation padrão. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992. (N. do T.)
824
SELECT INTO Nome SELECT INTO — cria uma tabela a partir dos resultados de uma consulta
Sinopse SELECT [ ALL | DISTINCT [ ON ( expressão [, ...] ) ] ] * | expressão [ AS nome_de_saída ] [, ...] INTO [ TEMPORARY | TEMP ] [ TABLE ] nova_tabela [ FROM item_do_from [, ...] ] [ WHERE condição ] [ GROUP BY expressão [, ...] ] [ HAVING condição [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] seleção ] [ ORDER BY expressão [ ASC | DESC | USING operator ] [, ...] ] [ LIMIT { contador | ALL } ] [ OFFSET início ] [ FOR UPDATE [ OF nome_da_tabela [, ...] ] ]
Descrição O comando SELECT INTO cria uma tabela e a carrega com dados computados por uma consulta. Os dados não são retornados para o cliente, como acontece normalmente no comando SELECT. As colunas da nova tabela possuem o mesmo nome e tipo de dado das colunas da saída do comando SELECT.
Parâmetros TEMPORARY ou TEMP
Quando especificado, a tabela é criada como uma tabela temporária. Consulte o comando CREATE TABLE para obter detalhes. nova_tabela O nome (opcionalmente qualificado pelo esquema) da tabela a ser criada. Todos os outros parâmetros estão descritos detalhadamente no comando SELECT.
Observações O comando CREATE TABLE AS é funcionalmente semelhante ao comando SELECT INTO. O comando CREATE TABLE AS é a sintaxe recomendada, uma vez que esta forma do comando SELECT INTO não está disponível no ECPG nem no PL/pgSQL, porque estes interpretam a cláusula INTO de forma diferente.
Compatibilidade O padrão SQL utiliza o comando SELECT ... INTO para representar a seleção de valores colocados dentro de variáveis escalares do programa hospedeiro, em vez de criar uma nova tabela. Esta é a mesma utilização encontrada no ECPG (veja o Capítulo 30) e no PL/pgSQL (veja o Capítulo 37). A utilização pelo PostgreSQL do comando SELECT INTO para representar a criação de uma tabela é histórica. É melhor utilizar o comando CREATE TABLE AS para esta finalidade nos programas novos.
825
SET Nome SET — muda um parâmetro de tempo de execução
Sinopse SET [ SESSION | LOCAL ] nome { TO | = } { valor | 'valor' | DEFAULT } SET [ SESSION | LOCAL ] TIME ZONE { zona_horária | LOCAL | DEFAULT }
Descrição O comando SET muda os parâmetros de configuração de tempo de execução. Muitos parâmetros de tempo de execução listados na Seção 16.4 podem ser mudados em tempo de execução pelo comando SET (Mas alguns requerem privilégio de superusuário para serem mudados, e outros não podem ser mudados após o servidor ou a sessão iniciar). O comando SET afeta apenas os valores utilizados na sessão corrente. Se o comando SET, ou SET SESSION, for executado dentro de uma transação interrompida posteriormente, os efeitos produzidos pelo comando SET desaparecem quando a transação é desfeita (Este comportamento representa uma mudança em relação às versões do PostgreSQL anteriores a 7.3, onde os efeitos produzidos pelo comando SET não eram desfeitos após um erro posterior). Se a transação que envolve o comando for efetivada, os efeitos produzidos persistem até o fim da sessão, a não ser que seja mudado por outro comando SET. Os efeitos produzidos pelo comando SET LOCAL duram apenas até o fim da transação corrente, seja esta efetivada ou não. Um caso especial ocorre quando o comando SET é seguido por um comando SET LOCAL dentro da mesma transação: o valor do comando SET LOCAL tem efeito até o final da transação, mas depois (se a transação for efetivada) passa a ter efeito o valor do comando SET.
Parâmetros SESSION
Especifica que o comando tem efeito para a sessão corrente (Este é o padrão se nem SESSION nem LOCAL estiverem presentes). LOCAL
Especifica que o comando tem efeito apenas para a transação corrente. Após o COMMIT ou o ROLLBACK a definição no nível de sessão volta a ter efeito novamente. Observe que o comando SET LOCAL parece não produzir nenhum efeito quando executado fora de um bloco BEGIN, uma vez que a transação termina imediatamente. nome Nome de um parâmetro de tempo de execução cujo valor pode ser definido. Os parâmetros disponíveis estão documentados na Seção 16.4 e abaixo. valor O novo valor do parâmetro. Os valores podem ser especificados como constantes cadeias de caracteres, identificadores, números, ou listas separadas por vírgula dos mesmos. Pode ser utilizado DEFAULT para especificar a redefinição do parâmetro com o seu valor padrão. Além dos parâmetros de configuração documentados na Seção 16.4, existem uns poucos que somente podem ser ajustados usando o comando SET, ou que possuem uma sintaxe especial: NAMES SET NAMES valor é um outro nome para SET client_encoding TO valor.
826
SEED
Define a semente interna para o gerador de números randômicos (a função random). Os valores permitidos são números de ponto flutuante entre 0 e 1, os quais são então multiplicados por 231-1. A semente também pode ser definida chamando a função setseed: SELECT setseed(valor); TIME ZONE SET TIME ZONE valor é um outro nome para SET timezone TO valor. A sintaxe SET TIME ZONE permite uma sintaxe especial para especificar a zona horária. Abaixo estão alguns exemplos de valores válidos (mas deve ser observado que alguns são aceitos apenas em algumas plataformas): 'PST8PDT'
A zona horária de Berkeley, Califórnia. 'Portugal'
A zona horária de Portugal. 'Europe/Rome'
A zona horária da Itália. -7
A zona horária 7 horas a oeste da UTC (equivalente a PDT - Pacific Daylight Time). Os valores positivos estão a leste 1 da UTC. INTERVAL '-08:00' HOUR TO MINUTE
A zona horária 8 horas a oeste da UTC (o mesmo que PST - Pacific Standard Time = UTC - 8 horas). LOCAL DEFAULT
Define a zona horária como a zona horária local (a zona horária padrão do sistema operacional do servidor). Veja a Seção 8.5 para obter mais informações sobre zonas horárias.
Observações A função set_config fornece uma funcionalidade equivalente. Veja a Seção 9.13.
Exemplos Definir o caminho de procura de esquema: SET search_path TO meu_esquema, public;
Definir o estilo da data igual ao estilo tradicional do POSTGRES, com a convenção de entrada “dia antes do mês”: SET datestyle TO postgres, dmy;
Definir a zona horária de Berkeley, Califórnia, usando apóstrofos para preservar as letras maiúsculas do nome da zona horária. => SET TIME ZONE 'PST8PDT'; => SELECT current_timestamp AS agora; agora ------------------------------2003-04-29 15:02:01.218622-07
827
Compatibilidade SET TIME ZONE estende a sintaxe definida no padrão SQL. O padrão permite somente deslocamentos de zona horária numéricos, enquanto o PostgreSQL permite uma especificação de zona horária mais flexível. Todas as outras funcionalidades do SET são extensões do PostgreSQL.
Veja também RESET, SHOW
Notas 1. Leste = oriente, o lado do Sol nascente; Oeste = ocidente, o lado do Sol poente. (N. do T.)
828
SET CONSTRAINTS Nome SET CONSTRAINTS — define os modos de verificação da restrição na transação corrente
Sinopse SET CONSTRAINTS { ALL | nome [, ...] } { DEFERRED | IMMEDIATE }
Descrição O comando SET CONSTRAINTS define o comportamento da verificação da restrição 1 2 dentro da transação corrente. No modo IMMEDIATE (imediato), as restrições são verificadas ao final de cada comando. No modo DEFERRED (postergado), as restrições não são verificadas até a transação ser efetivada (commit). Quando o modo da restrição é mudado para IMMEDIATE, o novo modo da restrição entra em vigor retroativamente: qualquer modificação de dado ativa, que deveria ter sido verificada ao término da transação (quando usado DEFERRED), é verificada durante a execução do comando SET CONSTRAINTS. Ao ser criada, a restrição sempre recebe uma destas três características: INITIALLY DEFERRED (inicialmente postergada), INITIALLY IMMEDIATE DEFERRABLE (inicialmente imediata, postergável), ou INITIALLY IMMEDIATE NOT DEFERRABLE (inicialmente imediata, não postergável). A terceira classe não é afetada pelo comando SET CONSTRAINTS. Atualmente, somente as restrições de chave estrangeira são afetadas por esta definição. As restrições de verificação (check) e de unicidade são sempre, efetivamente, não postergáveis.
Observações Este comando somente altera o comportamento das restrições dentro da transação corrente. Portanto, se este comando for executado fora de um bloco de transação (par BEGIN/COMMIT), parecerá que não produziu nenhum efeito. Se for desejado mudar o comportamento de uma restrição sem haver a necessidade de executar o comando SET CONSTRAINTS em todas as transações, deve ser especificado INITIALLY DEFERRED ou INITIALLY IMMEDIATE quando a restrição for criada.
Compatibilidade Este comando está em conformidade com o comportamento definido no padrão SQL, exceto pela limitação que, no PostgreSQL, somente se aplica às restrições de chave estrangeira.
Notas 1. As restrições de integridade, geralmente chamadas apenas de restrições, definem os estados válidos dos dados SQL restringindo os valores nas tabelas base. Uma restrição pode ser uma restrição de tabela, uma restrição de domínio ou uma asserção. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992 (N. do T.) 2. Oracle — O comando SET CONSTRAINTS é utilizado para especificar, para uma determinada transação, se a restrição postergável será verificada após cada comando da DML, ou quando a transação for efetivada. SET CONSTRAINT[S] (http://www.stanford.edu/dept/itss/docs/oracle/9i/server.920/a96540/statements_104a.htm) (N. do T.)
829
SET SESSION AUTHORIZATION Nome SET SESSION AUTHORIZATION — define o identificador do usuário da sessão e o identificador do usuário corrente, da sessão corrente.
Sinopse SET [ SESSION | LOCAL ] SESSION AUTHORIZATION nome_do_usuário SET [ SESSION | LOCAL ] SESSION AUTHORIZATION DEFAULT RESET SESSION AUTHORIZATION
Descrição Este comando define o identificador do usuário da sessão, e o identificador do usuário corrente, no contexto da sessão SQL corrente, como sendo nome_do_usuário. O nome do usuário pode ser escrito tanto como um identificador quanto como um literal cadeia de caracteres. Usando este comando é possível, por exemplo, se tornar temporariamente um usuário sem privilégios e posteriormente voltar a ser um superusuário. O identificador do usuário da sessão é inicialmente definido como sendo o (possivelmente autenticado) nome do usuário fornecido pelo cliente. O identificador do usuário corrente normalmente é igual ao identificador do usuário da sessão, mas pode mudar temporariamente no contexto das funções “setuid” e de outros mecanismos semelhantes. O identificador do usuário corrente é relevante para verificar as permissões. O identificador do usuário da sessão somente pode ser mudado se o usuário inicial da sessão (o usuário autenticado) possuir o privilégio de superusuário. Senão, o comando é aceito somente se especificar o nome do usuário autenticado. Os modificadores SESSION e LOCAL atuam da mesma forma que atuam no comando SET comum. As formas DEFAULT e RESET redefinem os identificadores de usuário da sessão e corrente como sendo o nome do usuário autenticado originalmente. Estas formas são sempre aceitas.
Exemplos => SELECT SESSION_USER, CURRENT_USER; session_user | current_user --------------+-------------pedro | pedro => SET SESSION AUTHORIZATION 'paulo'; => SELECT SESSION_USER, CURRENT_USER; session_user | current_user --------------+-------------paulo | paulo
Compatibilidade O padrão SQL permite algumas outras expressões aparecerem no lugar do literal nome_do_usuário, as quais não são importantes na prática. O PostgreSQL permite a sintaxe de identificador ("nome_do_usuário"), que o SQL não permite. O padrão SQL não permite este comando durante uma transação; O PostgreSQL não faz esta restrição, porque não há razão para fazê-la. O padrão deixa os privilégios necessários para executar este comando por conta da implementação.
830
SET TRANSACTION Nome SET TRANSACTION — define as características da transação corrente
Sinopse SET TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ] SET SESSION CHARACTERISTICS AS TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ]
Descrição O comando SET TRANSACTION define as características da transação corrente. Não produz nenhum efeito para as transações subseqüentes. O comando SET SESSION CHARACTERISTICS define o padrão das características das transações para as próximas transações na sessão. Estes padrões podem ser mudados pelo comando SET TRANSACTION para uma transação individual. As características de transação disponíveis são o nível de isolamento da transação e o modo de acesso da transação (ler/escrever ou somente para leitura). O nível de isolamento de uma transação determina quais dados a transação pode ver quando outras transações estão processando concorrentemente. READ COMMITTED
A declaração consegue ver apenas as linhas efetivadas (commit) antes do início da sua execução. Este é o padrão. SERIALIZABLE
A transação corrente vê apenas as linhas efetivadas antes da primeira consulta ou comando de modificação de dados ter sido executado nesta transação. Dica: Intuitivamente, serializável significa que duas transações concorrentes deixam o banco de dados no mesmo estado que estas duas transações, executadas uma após a outra em qualquer ordem, deixariam.
O nível de isolamento da transação não pode ser mudado após a primeira consulta ou comando de modificação de dado da transação (SELECT, INSERT, DELETE, UPDATE, FETCH ou COPY) ter sido executado. Veja o Capítulo 12 para obter mais informações sobre o isolamento de transações e controle de concorrência. O modo de acesso da transação determina se a transação lê e escreve, ou se é somente para leitura. Ler e escrever é o padrão. Quando a transação é somente para leitura, os seguintes comandos SQL não são permitidos: INSERT, UPDATE, DELETE e COPY TO se a tabela a ser escrita não for uma tabela temporária; todos os comandos CREATE, ALTER e DROP; COMMENT, GRANT, REVOKE, TRUNCATE; também EXPLAIN ANALYZE e EXECUTE se o comando a ser executado está entre os listados. Esta é uma noção de somente para leitura de alto nível, que não impede escritas no disco.
Observações O nível de isolamento padrão da transação para a sessão também pode ser definido pelo comando SET default_transaction_isolation = 'valor'
no arquivo de configuração. Consulte a Seção 16.4 para obter mais informações.
831
Compatibilidade Os dois comandos estão definidos no padrão SQL. No padrão SQL SERIALIZABLE é o nível de isolamento padrão; no PostgreSQL normalmente o padrão é READ COMMITTED, mas pode ser mudado conforme mencionado acima. O PostgreSQL não possui os níveis de isolamento READ UNCOMMITTED e REPEATABLE READ. Devido à falta de bloqueio de predicado (predicate locking), o nível SERIALIZABLE não é verdadeiramente serializável. Veja o Capítulo 12 para obter detalhes. No padrão SQL existe uma outra característica de transação que pode ser definida por estes comandos: o tamanho da área de diagnósticos. Este conceito só se aplica à linguagem SQL incorporada.
832
SHOW Nome SHOW — mostra o valor de um parâmetro de tempo de execução
Sinopse SHOW nome SHOW ALL
Descrição O comando SHOW mostra a definição corrente de parâmetros de tempo de execução. Estas variáveis podem ser definidas utilizando o comando SET, editando o arquivo de configuração postgresql.conf, pela variável de ambiente PGOPTIONS (ao se usar a libpq ou aplicações baseadas na libpq), ou por meio de sinalizadores de linha de comando ao iniciar o postmaster. Veja a Seção 16.4 para obter mais informações.
Parâmetros nome O nome de um parâmetro de tempo de execução. Os parâmetros disponíveis estão documentados na Seção 16.4 e na página de referência do comando SET. Além disso, existem uns poucos parâmetros que podem ser mostrados mas não podem ser definidos: SERVER_VERSION
Mostra o número da versão do servidor. SERVER_ENCODING
Mostra o conjunto de codificação de caracteres do lado servidor. Atualmente, este parâmetro pode ser mostrado mas não pode ser definido, porque a codificação é definida na hora da criação do banco de dados. LC_COLLATE
Mostra a definição da localização do banco de dados para agrupamento (collation 1 ) (ordenação do texto). Atualmente, este parâmetro pode ser mostrado mas não pode ser definido, porque a definição é determinada pelo comando initdb. LC_CTYPE
Mostra a definição da localização do banco de dados para classificação de caracteres 2 . Atualmente, este parâmetro pode ser mostrado mas não pode ser definido, porque a definição é determinada pelo comando initdb. IS_SUPERUSER
Verdade se o identificador de autorização da sessão corrente tiver privilégios de superusuário. ALL
Mostra os valores de todos os parâmetros de configuração.
Observações A função current_setting produz uma saída equivalente. Veja a Seção 9.13.
Exemplos Mostrar a definição corrente do parâmetro DateStyle (estilo da data): => SHOW DateStyle;
833
DateStyle ----------ISO, MDY (1 linha)
Mostrar a definição corrente do parâmetro geqo: => SHOW geqo; geqo -----on (1 linha)
Mostrar todas as definições: => SHOW ALL; name | setting -------------------------------+--------------------------------------australian_timezones | off authentication_timeout | 60 checkpoint_segments | 3 . . . wal_debug | 0 wal_sync_method | fdatasync (94 linhas)
Compatibilidade O comando SHOW é uma extensão do PostgreSQL.
Veja também SET
Notas 1. collation; collating sequence — Um método para comparar duas cadeias de caracteres comparáveis. Todo conjunto de caracteres possui seu collation padrão. (Second Informal Review Draft) ISO/IEC 9075:1992, Database Language SQL- July 30, 1992. (N. do T.) 3. Define a classificação do caractere, conversão maiúscula/minúscula, e outros atributos do caractere. LC_CTYPE Category for the Locale Definition Source File Format (http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/files/aixfiles/LC_CTYPE.htm) (N. do T.)
834
START TRANSACTION Nome START TRANSACTION — inicia um bloco de transação
Sinopse START TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ]
Descrição Este comando inicia um novo bloco transação. Se for especificado o nível de isolamento, ou modo de ler/escrever, a nova transação terá estas características, como se SET TRANSACTION fosse executado. Em todos os outros aspectos, o comportamento deste comando é idêntico ao do comando BEGIN.
Parâmetros Veja em SET TRANSACTION as informações sobre o significado dos parâmetros deste comando.
Compatibilidade Este comando está em conformidade com o padrão SQL; mas veja também a seção sobre compatibilidade de SET TRANSACTION.
Veja também BEGIN, COMMIT, ROLLBACK, SET TRANSACTION
835
TRUNCATE Nome TRUNCATE — esvazia a tabela
Sinopse TRUNCATE [ TABLE ] nome
Descrição O comando TRUNCATE remove rapidamente todas as linhas da tabela. Produz o mesmo efeito do comando DELETE não qualificado (sem WHERE), mas como na verdade não varre a tabela é mais rápido. É mais útil em tabelas grandes.
Parâmetros nome O nome (opcionalmente qualificado pelo esquema) da tabela a ser truncada.
Observações O comando TRUNCATE não pode ser usado quando existe referência de chave estrangeira de outra tabela para a tabela. Neste caso a verificação da validade tornaria necessária a varredura da tabela, e o ponto central é não fazê-la. O comando TRUNCATE não executa nenhum gatilho ON DELETE definido pelo usuário, porventura existente na tabela.
Exemplo Truncar a tabela tbl_grande: TRUNCATE TABLE tbl_grande;
Compatibilidade Não existe o comando TRUNCATE no padrão SQL.
836
UNLISTEN Nome UNLISTEN — pára de ouvir uma notificação
Sinopse UNLISTEN { nome | * }
Descrição O comando UNLISTEN é utilizado para remover um registro para eventos de NOTIFY existente. O comando UNLISTEN cancela o registro existente da sessão corrente do PostgreSQL como ouvinte da notificação nome. O curinga especial * cancela todos os registros de ouvinte da sessão corrente. O comando NOTIFY contém uma explicação mais extensa sobre a utilização dos comandos LISTEN e NOTIFY.
Parâmetros nome O nome da notificação (qualquer identificador). *
Cancela todos os registros de ouvinte desta sessão.
Observações É possível deixar de ouvir algo que não estava sendo ouvido; nenhum erro ou advertência é mostrado. Ao final de cada sessão, o comando UNLISTEN * é executado automaticamente.
Exemplos Para registrar: => LISTEN virtual; => NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448.
Após o comando UNLISTEN ter sido executado, os comandos NOTIFY posteriores são ignorados: => UNLISTEN virtual; => NOTIFY virtual; -- não é recebido nenhum evento NOTIFY
Compatibilidade Não existe o comando UNLISTEN no padrão SQL.
Veja também LISTEN, NOTIFY
837
UPDATE Nome UPDATE — atualiza linhas de uma tabela
Sinopse UPDATE [ ONLY ] tabela SET coluna = { expressão | DEFAULT } [, ...] [ FROM lista_do_from ] [ WHERE condição ]
Descrição O comando UPDATE muda os valores das colunas especificadas em todas as linhas que satisfazem a condição. Somente as colunas a serem modificadas precisam ser mencionadas na cláusula SET; as colunas que não são modificadas explicitamente mantêm seus valores anteriores. Por padrão, o comando UPDATE atualiza linhas na tabela especificada e nas suas tabelas descendentes. Se for desejado atualizar apenas a tabela especificada, deve ser utilizada a cláusula ONLY. É necessário possuir o privilégio UPDATE na tabela para atualizá-la, assim como o privilégio SELECT em todas as tabelas cujos valores são lidos pela expressão ou pela condição.
Parâmetros tabela O nome (opcionalmente qualificado pelo esquema) da tabela a ser atualizada. coluna O nome de uma coluna da tabela. expressão Uma expressão a ser atribuída à coluna. A expressão pode usar o valor antigo desta e de outras colunas da tabela. DEFAULT
Define o valor da coluna como o seu valor padrão (que é nulo se nenhuma expressão padrão específica tiver sido atribuída à coluna). lista_do_from Uma lista de expressões de tabela, podendo aparecer colunas de outras tabelas na condição WHERE e nas expressões de atualização. condição Uma expressão que retorna um valor do tipo boolean. Somente são atualizadas as linhas para as quais esta expressão retorna true.
Saídas Ao terminar bem-sucedido, o comando UPDATE retorna uma linha de fim de comando na forma UPDATE contador
O contador é o número de linhas atualizadas. Se contador for 0, nenhuma linha corresponde à condição (o que não é considerado um erro).
838
Exemplos Mudar a palavra Drama para Dramático na coluna tipo da tabela filmes: UPDATE filmes SET tipo = 'Dramático' WHERE tipo = 'Drama';
Ajustar as entradas de temperatura e redefinir a precipitação com seu valor padrão em uma linha da tabela clima: UPDATE clima SET temp_min = temp_min+1, temp_max = temp_min+15, precipitacao = DEFAULT WHERE cidade = 'São Francisco' AND data = '2003-07-03';
Compatibilidade Este comando está em conformidade com o padrão SQL, exceto que a cláusula FROM é uma extensão do PostgreSQL.
839
VACUUM Nome VACUUM — limpa e opcionalmente analisa um banco de dados
Sinopse VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ tabela ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ tabela [ (coluna [, ...] ) ] ]
Descrição O comando VACUUM recupera a área de armazenamento ocupada pelas tuplas excluídas. Na operação normal do PostgreSQL as tuplas excluídas, ou tornadas obsoletas por causa de uma atualização, não são fisicamente removidas da tabela; permanecem presentes até o comando VACUUM ser executado. Portanto, é necessário executar o comando VACUUM periodicamente, especialmente em tabelas freqüentemente atualizadas. Sem nenhum parâmetro, o comando VACUUM processa todas as tabelas do banco de dados corrente. Com um parâmetro, o VACUUM processa somente esta tabela. O comando VACUUM ANALYZE executa o comando VACUUM seguido pelo comando ANALYZE para cada tabela selecionada. Esta é uma forma de combinação útil para scripts de rotinas de manutenção. Consulte o comando ANALYZE para obter mais detalhes sobre o seu processamento. O comando VACUUM simples (sem o FULL) apenas recupera o espaço, tornando-o disponível para ser reutilizado. Esta forma do comando pode operar em paralelo com a leitura e escrita normal, porque não requer o bloqueio exclusivo da tabela. O VACUUM FULL executa um processamento mais extenso, incluindo a movimentação das tuplas entre blocos para tentar compactar a tabela no menor número de blocos de disco possível. Esta forma é muito mais lenta, e requer o bloqueio exclusivo da tabela para processá-la. O FREEZE é uma opção com finalidade especial, que faz as tuplas serem marcadas como “congeladas” logo que possível, em vez de aguardar até estarem inteiramente antigas. Se for feito quando não houver nenhuma outra transação aberta no mesmo banco de dados, então é garantido que todas as tuplas do banco de dados sejam “congeladas”, não ficando mais sujeitas aos problemas do recomeço do ID de transação, não importando quanto tempo o banco de dados seja deixado sem o comando VACUUM ser executado. O FREEZE não é recomendado para uso rotineiro. Sua única utilização pretendida é em conjunto com a preparação de bancos de dados modelo definido pelo usuário, ou outros bancos de dados inteiramente somente para leitura, que não receberão operações VACUUM na rotina de manutenção. Veja o Capítulo 21 para obter detalhes.
Parâmetros FULL
Seleciona uma limpeza “completa”, que pode recuperar mais espaço, mas é muito mais demorada e bloqueia a tabela em modo exclusivo. FREEZE
Seleciona um “congelamento” agressivo das tuplas. VERBOSE
Mostra, para cada tabela, um relatório da atividade de limpeza detalhado. ANALYZE
Atualiza as estatísticas utilizadas pelo planejador para determinar o modo mais eficiente de executar um comando.
840
tabela O nome (opcionalmente qualificado pelo esquema) da tabela específica a ser limpa. Por padrão todas as tabelas do banco de dados corrente. coluna O nome da coluna específica a ser analisada. Por padrão todas as colunas.
Saídas Quando é especificado VERBOSE, o comando VACUUM mostra mensagens de progresso indicando qual tabela está sendo processada no momento. Também são mostradas várias estatísticas sobre as tabelas.
Observações Recomenda-se que os bancos de dados de produção ativos sejam limpos com freqüência (pelo menos toda noite), para remover as linhas expiradas. Após adicionar ou remover um grande número de linhas, aconselha-se executar o comando VACUUM ANALYZE para a tabela afetada. Este procedimento atualizará os catálogos do sistema com os resultados de todas as mudanças recentes, permitindo o planejador de comandos do PostgreSQL fazer melhores escolhas ao planejar os comandos. A opção FULL não é recomendada para uso rotineiro, mas pode ser útil em casos especiais. Um exemplo é após ter sido excluída a maioria das linhas da tabela e deseja-se que a tabela seja fisicamente encolhida para ocupar menos espaço em disco. O comando VACUUM FULL geralmente encolhe mais a tabela que o comando VACUUM simples.
Exemplos Abaixo está mostrado um exemplo da execução do comando VACUUM em uma tabela do banco de dados regression: regression=# VACUUM VERBOSE ANALYZE onek; INFO: vacuuming "public.onek" INFO: index "onek_unique1" now contains 1000 tuples in 14 pages DETAIL: 3000 index tuples were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.01s/0.08u sec elapsed 0.18 sec. INFO: index "onek_unique2" now contains 1000 tuples in 16 pages DETAIL: 3000 index tuples were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.00s/0.07u sec elapsed 0.23 sec. INFO: index "onek_hundred" now contains 1000 tuples in 13 pages DETAIL: 3000 index tuples were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.01s/0.08u sec elapsed 0.17 sec. INFO: index "onek_stringu1" now contains 1000 tuples in 48 pages DETAIL: 3000 index tuples were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.01s/0.09u sec elapsed 0.59 sec. INFO: "onek": removed 3000 tuples in 108 pages DETAIL: CPU 0.01s/0.06u sec elapsed 0.07 sec. INFO: "onek": found 3000 removable, 1000 nonremovable tuples in 143 pages DETAIL: 0 dead tuples cannot be removed yet. There were 0 unused item pointers. 0 pages are entirely empty. CPU 0.07s/0.39u sec elapsed 1.56 sec. INFO: analyzing "public.onek" INFO: "onek": 36 pages, 1000 rows sampled, 1000 estimated total rows VACUUM
841
Compatibilidade Não existe o comando VACUUM no padrão SQL.
Veja também vacuumdb
842
II. Aplicações cliente do PostgreSQL Esta parte contém informações de referência para as aplicações e utilitários clientes do PostgreSQL. Nem todos estes comandos são de uso geral, alguns requerem privilégios especiais. A característica comum destas aplicações é poderem ser executadas a partir de qualquer computador, independentemente de onde o servidor de banco de dados está instalado.
843
clusterdb Nome clusterdb — agrupa um banco de dados do PostgreSQL
Sinopse clusterdb [opção_de_conexão...] [--tabela | -t tabela ] [nome_do_banco_de_dados] clusterdb [opção_de_conexão...] [--all | -a]
Descrição O clusterdb é um utilitário para reagrupar tabelas em um banco de dados do PostgreSQL. Encontra as tabelas que foram agrupadas anteriormente, reagrupando-as novamente utilizando o mesmo índice usado da última vez. As tabelas que nunca foram agrupadas não são afetadas. O clusterdb é uma capa em torno do comando CLUSTER do SQL. Não existe diferença efetiva entre agrupar bancos de dado através deste utilitário, ou através de outros métodos para acessar ao servidor.
Opções O clusterdb aceita os seguintes argumentos de linha de comando: -a --all
Agrupa todos os bancos de dados. [-d] nome_do_banco_de_dados [--dbname] nome_do_banco_de_dados
Especifica o nome do banco de dados a ser agrupado. Se não for especificado e não for utilizado -a (ou -all), o nome do banco de dados é lido da variável de ambiente PGDATABASE. Se esta variável não estiver definida, então é utilizado o nome do usuário especificado na conexão. -e --echo
Mostra os comandos que o clusterdb gera e envia para o servidor. -q --quiet
Não exibe resposta. -t tabela --table tabela
Agrupa somente a tabela. O clusterdb também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por barra (/) é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão do arquivo de soquete do domínio Unix local, onde o servidor está ouvindo as conexões.
844
-U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar. -W --password
Força a solicitação da senha.
Ambiente PGDATABASE PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos Encontrando dificuldades veja em CLUSTER e psql a discussão dos problemas possíveis e as mensagens de erro. O servidor de banco de dados deve estar executando no hospedeiro de destino. Também se aplicam todas as definições de conexão padrão e as variáveis de ambiente utilizadas pela biblioteca cliente libpq.
Exemplos Para agrupar o banco de dados teste: $ clusterdb teste
Para agrupar apenas a tabela foo no banco de dados chamado xyzzy: $ clusterdb --table foo xyzzy
Veja também CLUSTER
845
createdb Nome createdb — cria um novo banco de dados do PostgreSQL
Sinopse createdb [opção...] [nome_do_banco_de_dados] [descrição]
Descrição O createdb cria um banco de dados no PostgreSQL. Normalmente, o usuário do banco de dados que executa este comando se torna o dono do novo banco de dados. Entretanto, pode ser especificado um dono diferente por meio da opção -O, se o usuário que está executando este comando tiver os privilégios apropriados. O createdb é uma capa em torno do comando CREATE DATABASE do SQL. Não existe diferença efetiva entre criar bancos de dados através deste utilitário, ou através de outros métodos para acessar o servidor.
Opções O createdb aceita os seguintes argumentos de linha de comando: nome_do_banco_de_dados Especifica o nome do banco de dados a ser criado. O nome deve ser único entre todos os bancos de dados do PostgreSQL deste agrupamento. O padrão é criar o banco de dados com o mesmo nome do usuário atual do sistema operacional. descrição Especifica um comentário a ser associado ao banco de dados recém criado. -D local --location local
Especifica o local alternativo para o banco de dados. Consulte também a aplicação initlocation. -e --echo
Mostra os comandos que o createdb gera e envia para o servidor. -E codificação --encoding codificação
Especifica o esquema de codificação de caracteres a ser usado neste banco de dados. -O dono --owner dono
Especifica o usuário do banco de dados que será o dono do novo banco de dados. -q --quiet
Não exibe resposta. -T modelo --template modelo
Especifica o banco de dados modelo, a partir do qual este banco de dados será construído. As opções -D, -E, -O e -T correspondem às opções do comando CREATE DATABASE subjacente; consulte este comando para obter mais informações sobre estas opções.
846
O createdb também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/), é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. -U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar. -W --password
Força a solicitação da senha.
Ambiente PGDATABASE
Se estiver definido, o nome do banco de dados a ser criado, a menos que o nome esteja definido na linha de comando. PGHOST PGPORT PGUSER
Parâmetros de conexão padrão. PGUSER também determina o nome do banco de dados a ser criado, se este não for especificado na linha de comando ou por PGDATABASE.
Diagnósticos Havendo dificuldade, veja no comando CREATE DATABASE e no psql a discussão dos problemas possíveis e as mensagens de erro. O servidor de banco de dados deve estar executando no hospedeiro de destino. Também se aplicam todas as definições de conexão padrão e as variáveis de ambiente utilizadas pela biblioteca cliente libpq.
Exemplos Para criar o banco de dados demo usando o servidor de banco de dados padrão: $ createdb demo CREATE DATABASE
A resposta é a mesma que teria sido recebida se fosse executado o comando CREATE DATABASE do SQL. Para criar o banco de dados demo usando o servidor no hospedeiro eden, a porta 5000, o esquema de codificação LATIN1 e vendo o comando subjacente: $ createdb -p 5000 -h eden -E LATIN1 -e demo CREATE DATABASE "demo" WITH ENCODING = 'LATIN1' CREATE DATABASE
Veja também dropdb, CREATE DATABASE
847
createlang Nome createlang — cria uma linguagem procedural do PostgreSQL
Sinopse createlang [opções_de_conexão...] nome_da_linguagem [nome_do_banco_de_dados] createlang [opções_de_conexão...] --list | -l nome_do_banco_de_dados
Descrição O createlang é um utilitário para adicionar uma nova linguagem de programação a um banco de dados do PostgreSQL. O createlang pode tratar todas as linguagens fornecidas na distribuição padrão do PostgreSQL, mas não as linguagens fornecidas por terceiros. Embora as linguagens de programação do servidor possam ser adicionadas diretamente usando vários comandos SQL, recomenda-se o uso da aplicação createlang, porque esta realiza várias verificações e é muito mais fácil de usar. Consulte o comando CREATE LANGUAGE para obter informações adicionais.
Opções O createlang aceita os seguintes argumentos de linha de comando: nome_da_linguagem Especifica o nome da linguagem de programação procedural a ser definida. [-d] nome_do_banco_de_dados [--dbname] nome_do_banco_de_dados
Especifica em qual banco de dados a linguagem deve ser adicionada. O padrão é usar o banco de dados com o mesmo nome do usuário corrente do sistema operacional. -e --echo
Mostra os comandos SQL à medida que são executados. -l --list
Mostra a relação de linguagens instaladas no banco de dados de destino. -L diretório
Especifica o diretório onde o interpretador da linguagem deve ser encontrado. Normalmente o diretório é encontrado automaticamente; esta opção é principalmente para fins de depuração. O createlang também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/) é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões.
848
-U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar. -W --password
Força a solicitação da senha.
Ambiente PGDATABASE PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos As mensagens de erro são auto-explicativas, em sua maioria. Caso não seja, execute o createlang com a opção --echo e consulte o respectivo comando SQL para obter detalhes.
Observações Use droplang para remover uma linguagem.
Exemplos Para instalar a linguagem pltcl no banco de dados template1: $ createlang pltcl template1
Veja também droplang, CREATE LANGUAGE
849
createuser Nome createuser — cria uma nova conta de usuário do PostgreSQL
Sinopse createuser [opção...] [nome_do_usuário]
Descrição O utilitário createuser cria um novo usuário do PostgreSQL. Somente os superusuários (usuários com usesuper definido na tabela pg_shadow) podem criar novos usuários do PostgreSQL e, portanto, o createuser deve ser executado por alguém que possa se conectar como superusuário do PostgreSQL. Ser um superusuário também implica na habilidade de transpor as verificações de permissão de acesso do banco de dados e, portanto, o privilégio de superusuário deve ser concedido criteriosamente. O createuser é uma capa em torno do comando CREATE USER do SQL. Não existe diferença efetiva entre criar usuários através deste utilitário, ou através de outros métodos para acessar o servidor.
Opções O createuser aceita os seguintes argumentos de linha de comando: nome_do_usuário Especifica o nome do usuário do PostgreSQL a ser criado. O nome deve ser único entre todos os usuários do PostgreSQL. -a --adduser
Permite o novo usuário criar outros usuários (Nota: na verdade isto torna o novo usuário um superusuário. Esta opção possui um nome equivocado). -A --no-adduser
O novo usuário não pode criar outros usuários (ou seja, o novo usuário é um usuário normal, e não um superusuário). Este é o padrão. -d --createdb
O novo usuário pode criar bancos de dados. -D --no-createdb
O novo usuário não pode criar bancos de dados. Este é o padrão. -e --echo
Mostra os comandos que o createuser gera e envia para o servidor. -E --encrypted
Criptografa a senha do usuário armazenada no banco de dados. Se não for especificado, será utilizado o comportamento padrão para senhas.
850
-i número --sysid número
Permite escolher uma identificação diferente do padrão para o novo usuário. Não é necessário, mas algumas pessoas gostam. -N --unencrypted
Não criptografa a senha do usuário armazenada no banco de dados. Se não for especificado, será utilizado o comportamento padrão para senhas. -P --pwprompt
Se for usado, o createuser solicita a senha do novo usuário. Não é necessário caso não se planeje usar autenticação por senha. -q --quiet
Não exibe resposta. Será solicitado o nome e outras informações que estejam faltando, se não forem especificadas na linha de comando. O createuser também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/), é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. -U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar (e não o nome do usuário a ser criado). -W --password
Força a solicitação da senha (para conectar ao servidor, e não a senha do novo usuário).
Ambiente PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos Havendo dificuldade, veja no comando CREATE USER e no psql a discussão dos problemas possíveis e as mensagens de erro. O servidor de banco de dados deve estar executando no hospedeiro de destino. Também se aplicam todas as definições de conexão padrão e as variáveis de ambiente utilizadas pela biblioteca cliente libpq.
Exemplos Para criar o usuário joel no servidor de banco de dados padrão:
851
$ createuser joel Is the new user allowed to create databases? (y/n) n Shall the new user be allowed to create more new users? (y/n) n CREATE USER
Criar o mesmo usuário joel usando o servidor no hospedeiro eden, porta 5000, evitando solicitação de informação e vendo o comando subjacente: $ createuser -p 5000 -h eden -D -A -e joel CREATE USER "joel" NOCREATEDB NOCREATEUSER CREATE USER
Veja também dropuser, CREATE USER
852
dropdb Nome dropdb — remove um banco de dados do PostgreSQL
Sinopse dropdb [opção...] nome_do_banco_de_dados
Descrição O utilitário dropdb remove um banco de dados do PostgreSQL. Para executar este comando é necessário ser um superusuário, ou o dono do banco de dados. O dropdb é uma capa em torno do comando DROP DATABASE do SQL. Não existe diferença efetiva entre remover bancos de dados através deste utilitário, ou através de outros métodos para acessar o servidor.
Opções O dropdb aceita os seguintes argumentos de linha de comando: nome_do_banco_de_dados Especifica o nome do banco de dados a ser removido. -e --echo
Mostra os comandos que o dropdb gera e envia para o servidor. -i --interactive
Solicita a confirmação antes de fazer qualquer operação destrutiva. -q --quiet
Não exibe resposta. O dropdb também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/), é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. -U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar. -W --password
Força a solicitação da senha.
853
Ambiente PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos Havendo dificuldade, veja no comando DROP DATABASE e no psql a discussão dos problemas possíveis e as mensagens de erro. O servidor de banco de dados deve estar executando no hospedeiro de destino. Também se aplicam todas as definições de conexão padrão e as variáveis de ambiente utilizadas pela biblioteca cliente libpq.
Exemplos Para remover o banco de dados demo no servidor de banco de dados padrão: $ dropdb demo DROP DATABASE
Para remover o banco de dados demo usando o servidor no hospedeiro eden, porta 5000, com confirmação e vendo o comando subjacente: $ dropdb -p 5000 -h eden -i -e demo Database "demo" will be permanently deleted. Are you sure? (y/n) y DROP DATABASE "demo" DROP DATABASE
Veja também createdb, DROP DATABASE
854
droplang Nome droplang — remove uma linguagem procedural do PostgreSQL
Sinopse droplang [opção_de_conexão...] nome_da_linguagem [nome_do_banco_de_dados] droplang [opção_de_conexão...] --list | -l nome_do_banco_de_dados
Descrição O droplang é um utilitário para remover, de um banco de dados do PostgreSQL, uma linguagem de programação existente. O droplang pode remover qualquer linguagem procedural, até mesmo as não fornecidas na distribuição do PostgreSQL. Embora as linguagens de programação do servidor possam ser removidas diretamente usando vários comandos SQL, recomenda-se usar o droplang, porque este realiza várias verificações e é muito mais fácil de usar. Consulte o comando DROP LANGUAGE para obter mais informações.
Opções O droplang aceita os seguintes argumentos de linha de comando: nome_da_linguagem Especifica o nome da linguagem de programação do servidor a ser removida. [-d] nome_do_banco_de_dados [--dbname] nome_do_banco_de_dados
Especifica de qual banco de dados a linguagem deve ser removida. O padrão é usar o banco de dados com o mesmo nome do usuário corrente do sistema operacional. -e --echo
Mostra os comandos SQL à medida que são executados. -l --list
Exibe a lista de linguagens instaladas no banco de dados de destino. O droplang também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/), é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. -U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar.
855
-W --password
Força a solicitação da senha.
Ambiente PGDATABASE PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos As mensagens de erro são, em sua maioria, auto-explicativas. Se alguma não for, execute o droplang com a opção --echo e consulte o respectivo comando SQL para obter detalhes.
Observações Use createlang para adicionar uma linguagem.
Exemplos Para remover a linguagem pltcl: $ droplang pltcl template1
Veja também createlang, DROP LANGUAGE
856
dropuser Nome dropuser — remove uma conta de usuário do PostgreSQL
Sinopse dropuser [opção...] [nome_do_usuário]
Descrição O utilitário dropuser remove um usuário do PostgreSQL, e os bancos de dados que este usuário possui. Somente os superusuários (usuários com usesuper definido na tabela pg_shadow) podem remover usuários do PostgreSQL. O dropuser é uma capa em torno do comando DROP USER do SQL. Não existe diferença efetiva entre remover usuários através deste utilitário, ou através de outros métodos para acessar o servidor.
Opções O dropuser aceita os seguintes argumentos de linha de comando: nome_do_usuário Especifica o nome do usuário do PostgreSQL a ser removido. Será solicitado o nome caso não seja especificado na linha de comando. -e --echo
Mostra os comandos que o dropuser gera e envia para o servidor. -i --interactive
Solicita a confirmação antes de remover o usuário. -q --quiet
Não exibe resposta. O dropuser também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/), é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. -U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar (e não o nome do usuário a ser removido). -W --password
Força a solicitação da senha (para conectar ao servidor, e não a senha do usuário a ser removido).
857
Ambiente PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos Havendo dificuldade, veja no comando DROP USER e no psql a discussão dos problemas possíveis e as mensagens de erro. O servidor de banco de dados deve estar executando no hospedeiro de destino. Também se aplicam todas as definições de conexão padrão e as variáveis de ambiente utilizadas pela biblioteca cliente libpq.
Exemplos Para remover o usuário joel do servidor de banco de dados padrão: $ dropuser joel DROP USER
Para remover o usuário joel usando o servidor no hospedeiro eden, porta 5000, com confirmação e vendo o comando subjacente: $ dropuser -p 5000 -h eden -i -e joel User "joel" and any owned databases will be permanently deleted. Are you sure? (y/n) y DROP USER "joel" DROP USER
Veja também createuser, DROP USER
858
ecpg Nome ecpg — pré-processador da linguagem SQL incorporada para a linguagem C
Sinopse ecpg [opção...] arquivo...
Descrição O utilitário ecpg é o pré-processador da linguagem SQL incorporada (embedded) para programas escritos na linguagem C. Converte programas C com declarações SQL incorporadas em código C normal, substituindo as chamadas ao SQL por chamadas a funções especiais. Os arquivos de saída podem, então, ser processados por qualquer cadeia de ferramentas do compilador C. O ecpg converte cada arquivo de entrada especificado na linha de comando, no arquivo de saída C correspondente. De preferência, os arquivos de entrada devem possuir a extensão .pgc e, neste caso, a extensão é substituída por .c para determinar o nome do arquivo de saída. Se a extensão do arquivo de entrada não for .pgc, então o nome do arquivo de saída será gerado anexando .c ao nome completo do arquivo de entrada. O nome do arquivo de saída pode ser especificado por meio da opção -o. Esta página de referência não descreve a linguagem SQL incorporada. Consulte o Capítulo 30 para obter mais informações sobre este tópico.
Opções O ecpg aceita os seguintes argumentos de linha de comando: -c
Gera, automaticamente, certos códigos C a partir do código SQL. Atualmente funciona para EXEC SQL TYPE. -C modo
Define o modo de compatibilidade. O modo pode ser INFORMIX ou INFORMIX_SE. -D símbolo
Define um símbolo do pré-processador C. -i
Analisa, também, os arquivos de inclusão do sistema. -I diretório
Especifica um caminho de inclusão adicional, utilizado para encontrar arquivos incluídos por meio de EXEC SQL INCLUDE. Por padrão os seguintes: . (o diretório atual), /usr/local/include, o diretório
de
inclusão
do
PostgreSQL definido em tempo /usr/local/pgsql/include) e /usr/include, nesta ordem.
de
compilação
(por
padrão
-o arquivo_de_saída
Especifica que o ecpg deve escrever toda a sua saída no arquivo_de_saída especificado. -r opção
Seleciona um comportamento em tempo de execução. Atualmente opção pode ser apenas no_indicator.
859
-t
Ativa a auto-efetivação (auto-commit) das transações. Neste modo, cada comando SQL é automaticamente efetivado, a não ser que esteja dentro de um bloco de transação explícito. No modo padrão, os comandos são efetivados somente quando é emitido EXEC SQL COMMIT. -v
Mostra informações adicionais, incluindo a versão e o caminho de inclusão. --help
Mostra um breve resumo da utilização e depois termina. --version
Mostra a informação da versão e depois termina.
Observações Ao compilar arquivos com o código C pré-processado, o compilador necessita encontrar os arquivos de cabeçalho do ECPG no diretório de inclusão do PostgreSQL. Portanto, é necessário usar a opção -I ao chamar o compilador (por exemplo, -I/usr/local/pgsql/include). Os programas escritos em C com comandos SQL incorporados necessitam da biblioteca libecpg para a ligação. Pode ser usado, por exemplo, as opções do ligador -L/usr/local/pgsql/lib -lecpg. Os nomes destes diretórios, apropriados para a instalação, podem ser descobertos utilizando a aplicação pg_config.
Exemplos Havendo um arquivo fonte C chamado prog1.pgc, com comandos SQL incorporados, pode ser criado um programa executável utilizando a seguinte seqüência de comandos: ecpg prog1.pgc cc -I/usr/local/pgsql/include -c prog1.c cc -o prog1 prog1.o -L/usr/local/pgsql/lib -lecpg
860
pg_config Nome pg_config — retorna informações sobre a versão do PostgreSQL instalada
Sinopse pg_config {--bindir | --includedir | --includedir-server | --libdir | --pkglibdir | --configure | --version...}
Descrição O utilitário pg_config mostra os parâmetros de configuração da versão do PostgreSQL atualmente instalada. Sua finalidade é, por exemplo, ser usado por pacotes de software que querem interfacear com o PostgreSQL, para ajudar a encontrar os arquivos de cabeçalho e bibliotecas necessários.
Opções Para usar o pg_config deve-se fornecer uma ou mais das seguintes opções: --bindir
Mostra a localização dos executáveis do usuário. Usa-se, por exemplo, para encontrar a aplicação psql. Normalmente, este é também o local onde o pg_config reside. 1 --includedir
Mostra a localização dos arquivos de cabeçalho da linguagem C das interfaces cliente. --includedir-server
Mostra a localização dos arquivos de cabeçalho da linguagem C para programação do servidor. --libdir
Mostra a localização das bibliotecas de código objeto. --pkglibdir
Mostra a localização dos módulos carregáveis dinamicamente, ou onde o servidor deve procurá-los (Também podem estar instalados neste diretório outros arquivos de dados dependentes da arquitetura). --configure
Mostra as opções passadas para o script configure quando o PostgreSQL foi configurado para ser gerado. Pode ser utilizado para reproduzir uma configuração idêntica, ou para descobrir com quais opções o pacote binário foi construído; entretanto, deve ser observado que os pacotes binários geralmente contêm correções específicas da distribuição. --version
Mostra a versão do PostgreSQL e termina. Se for fornecida mais de uma opção (exceto --version), a informação é mostrada nesta ordem, um item por linha.
Observações A opção --includedir-server começou no PostgreSQL 7.2. Nas versões anteriores, os arquivos de inclusão do servidor estavam instalados no mesmo local dos cabeçalhos dos clientes, que podia ser consultado pela opção --includedir. Para tratar os dois casos, deve-se tentar primeiro a opção mais nova, e testar o status da saída para verificar se a execução foi bem-sucedida. Nas versões do PostgreSQL anteriores a 7.1, antes do comando pg_config existir, não existia um método equivalente para encontrar as informações de configuração.
861
Histórico O pg_config apareceu pela primeira vez no PostgreSQL 7.1.
Notas 1. No Fedora Core 3 o utilitário psql pode ser encontrado através do comando which psql, que retorna /usr/bin/psql, mas o utilitário pg_config não é instalado pelos RPMs. (N. do T.)
862
pg_dump Nome pg_dump — salva um banco de dados do PostgreSQL em um arquivo de script ou de outro tipo
Sinopse pg_dump [opção...] [nome_do_banco_de_dados]
Descrição O pg_dump é um utilitário para fazer cópia de segurança de um banco de dados do PostgreSQL. São feitas cópias de segurança consistentes mesmo que o banco de dados esteja sendo utilizado concorrentemente. O pg_dump não bloqueia os outros usuários que estão acessando o banco de dados (leitura ou escrita). As cópias de segurança podem ser feitas no formato de script ou em outros formatos. As cópias de segurança no formato de script são arquivos no formato texto puro, contendo os comandos SQL necessários para reconstruir o banco de dados no estado em que este se encontrava quando foi salvo. Para restaurar a partir destes scripts, deve ser utilizado o psql. Os arquivos de script podem ser utilizados para reconstruir o banco de dados até em outras máquinas com outras arquiteturas; com algumas modificações, até mesmo em outros produtos gerenciadores de banco de dados SQL. Os formatos de arquivo de cópia de segurança alternativos devem ser utilizados com o pg_restore para reconstruir o banco de dados. Estes formatos permitem que o pg_restore selecione o que será restaurado, ou mesmo reordene os itens antes de restaurá-los. As formatos de cópia de segurança alternativos também são projetados para serem portáveis entre arquiteturas diferentes. Quando usado com um dos formatos de cópia de segurança alternativos, e combinado com o pg_restore, o pg_dump fornece um mecanismo flexível para cópias de segurança e transferência. O pg_dump pode ser usado para fazer a cópia de segurança de todo o banco de dados e, posteriormente, o pg_restore pode ser usado para examinar a cópia de segurança e/ou selecionar as partes do banco de dados a serem restauradas. O formato de arquivo de saída mais flexível é o “personalizado” (custom, -Fc); permite a seleção e a reordenação de todos os itens da cópia de segurança, e é comprimido por padrão. O formato tar (-Ft) não é comprimido e não permite reordenar os dados ao a restaurar, mas por outro lado é bastante flexível; além disso, pode ser manipulado pelas ferramentas padrão do Unix, como o tar. Ao executar o pg_dump a saída deve ser examinada à procura de advertências (escritas na saída de erro padrão), com atenção especial às limitações mostradas abaixo.
Opções As seguintes opções de linha de comando controlam o conteúdo e o formato da saída: nome_do_banco_de_dados Especifica o nome do banco de dados a ser salvo. Se não for especificado, é utilizada a variável de ambiente PGDATABASE. Caso esta variável não esteja definida, é utilizado o nome do usuário especificado para a conexão. -a --data-only
Salva somente os dados, não salva o esquema (definições de dado). Esta opção só faz sentido para o formato texto-puro. Para os formatos alternativos esta opção pode ser especificada ao chamar o pg_restore. -b --blobs
Inclui os objetos grandes na cópia de segurança. Deve ser selecionado um formato de saída não-texto.
863
-c --clean
Inclui comandos para remover (drop) os objetos do banco de dados antes dos comandos para criá-los. Esta opção só faz sentido para o formato texto-puro. Para os formatos alternativos esta opção pode ser especificada ao chamar o pg_restore. -C --create
Inicia a saída por um comando para criar o banco de dados e conectar ao banco de dados criado (Com um script assim não importa qual banco de dados se está conectado antes de executar o script). Esta opção só faz sentido para o formato texto-puro. Para os formatos alternativos a opção pode ser especificada ao chamar o pg_restore. -d --inserts
Salva os dados como comandos INSERT, em vez de COPY. Torna a restauração muito lenta, mas os arquivos produzidos são mais portáveis para outros sistemas gerenciadores de banco de dados SQL. -D --column-inserts --attribute-inserts
Salva os dados como comandos INSERT explicitando os nomes das colunas (INSERT INTO tabela (coluna, ...) VALUES ...). Torna a restauração muito lenta, mas é necessário se for desejado mudar a ordem das colunas. -f arquivo --file=arquivo
Envia a saída para o arquivo especificado. Se for omitido é usada a saída padrão. -F formato --format=formato
Seleciona o formato da saída. O formato pode ser um dos seguintes: p
Gera um arquivo de script SQL no formato texto-puro (padrão) t
Gera um arquivo tar adequado para servir de entrada para o pg_restore. A utilização deste formato de arquivo permite reordenar e/ou excluir objetos do banco de dados ao fazer a restauração. Também é possível limitar os dados a serem recarregados ao fazer a restauração. c
Gera um arquivo personalizado adequado para servir de entrada para o pg_restore. Este é o formato mais flexível, porque permite a reordenação da restauração dos dados, assim como das definições dos objetos. Também, este formato é comprimido por padrão. -i --ignore-version
Ignora a diferença de versão entre o pg_dump e o servidor de banco de dados. O pg_dump pode tratar bancos de dados de versões anteriores do PostgreSQL, mas as versões muito antigas não são mais suportadas (atualmente as anteriores a 7.0). Esta opção deve ser utilizada se for necessário desconsiderar a verificação de versão (mas se o pg_dump não for bem-sucedido, não diga que não foi avisado).
864
-n esquema --schema=esquema
Salva apenas o conteúdo do esquema. Se esta opção não for especificada, todos os esquemas no banco de dados especificado (fora os do sistema) são salvos. Nota: Neste modo, o pg_dump não tenta salvar os demais objetos de banco de dados que os objetos no esquema selecionado possam depender. Portanto, não existe nenhuma garantia que o resultado de salvar um único esquema possa, por si próprio, ser bem-sucedido quando restaurado em um banco de dados vazio. -o --oids
Salva os identificadores de objeto (OIDs) de todas as tabelas como parte dos dados. Esta opção deve ser usada quando a coluna OID é referenciada de alguma maneira (por exemplo, em uma restrição de chave estrangeira). Caso contrário, esta opção não deve ser usada. -O --no-owner
Não gera comandos para definir a propriedade dos objetos correspondendo a do banco de dados original. Por padrão, o pg_dump emite comandos SET SESSION AUTHORIZATION para definir o dono dos objetos de bancos de dados criados. Estes comandos não são bem-sucedidos quando o script é executado, a menos que o script seja executado por um superusuário (ou o mesmo usuário que possui todos os objetos presentes no script). Para gerar um script que possa ser restaurado por qualquer usuário, mas que torna este usuário o dono de todos os objetos, deve ser especificada a opção -O. Esta opção só faz sentido para o formato texto-puro. Para os formatos alternativos a opção pode ser especificada ao chamar o pg_restore. -R --no-reconnect
Esta opção está obsoleta, mas ainda é aceita para manter compatibilidade com as versões anteriores. -s --schema-only
Salva somente o esquema (definições dos dados), não os dados. -S nome_do_usuário --superuser=nome_do_usuário
Especifica o nome de usuário do superusuário a ser usado para desabilitar os gatilhos. Somente é relevante quando é usada a opção --disable-triggers (Geralmente é melhor não utilizar esta opção e, em vez disso, executar o script produzido como um superusuário). -t tabela --table=tabela
Salva somente os dados da tabela. É possível existirem várias tabelas com o mesmo nome em esquemas diferentes; se este for o caso, todas as tabelas correspondentes serão salvas. Deve ser especificado tanto --schema quanto --table para selecionar apenas uma tabela. Nota: Neste modo, o pg_dump não tenta salvar os demais objetos de banco de dados que a tabela selecionada possa depender. Portanto, não existe nenhuma garantia que o resultado de salvar uma única tabela possa, por si próprio, ser bem-sucedido quando restaurado em um banco de dados vazio. -v --verbose
Especifica o modo verboso, fazendo o pg_dump enviar as mensagens de progresso para a saída de erro padrão.
865
-x --no-privileges --no-acl
Impede salvar os privilégios de acessos (comandos GRANT/REVOKE). -X use-set-session-authorization --use-set-session-authorization
Esta opção está obsoleta, sendo aceita apenas para manter compatibilidade com as versões anteriores. Atualmente a aplicação pg_dump sempre se comporta da forma anteriormente selecionada por esta opção. -X disable-triggers --disable-triggers
Esta opção somente é relevante ao criar um arquivo de cópia de segurança de dados apenas. Faz o pg_dump incluir comandos para desabilitar, temporariamente, os gatilhos das tabelas de destino enquanto os dados são recarregados. Deve ser utilizado quando existem verificações de integridade referencial, ou outros gatilhos nas tabelas, que não se deseja que sejam chamados durante a recarga dos dados. Atualmente, os comandos emitidos para a opção --disable-triggers devem ser executados por superusuários. Portanto, também deve ser especificado o nome de um superusuário com a opção -S ou, de preferência, executar, com cuidado, o script produzido como um superusuário. Esta opção só faz sentido para o formato texto-puro. Para os formatos alternativos esta opção pode ser especificada ao chamar o pg_restore. -Z 0..9 --compress=0..9
Especifica o nível de compressão a ser usado nas cópias de segurança com formatos que suportam compressão (atualmente somente o formato personalizado suporta compressão). As seguintes opções de linha de comando controlam os parâmetros de conexão com o servidor de banco de dados: -h hospedeiro --host=hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/) é usado como o diretório do soquete do domínio Unix. O padrão é obter o nome a partir da variável de ambiente PGHOST, se esta estiver definida, senão tentar uma conexão pelo soquete do domínio Unix. -p porta --port=porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. O padrão é obter a partir da variável de ambiente PGPORT, se esta estiver definida, senão o padrão compilado. -U nome_do_usuário
Conectar como o usuário especificado. -W
Força a solicitação da senha, o que deve acontecer automaticamente quando o servidor requer autenticação por senha.
Ambiente PGDATABASE PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
866
Diagnósticos O pg_dump executa internamente comandos SELECT. Se acontecerem problemas ao executar o pg_dump, deve-se ter certeza que é possível selecionar informações no banco de dados utilizando, por exemplo, o utilitário psql.
Observações Se o agrupamento de bancos de dados tiver alguma adição local ao banco de dados template1, deve-se ter o cuidado de restaurar a saída do pg_dump em um banco de dados totalmente vazio; senão, podem acontecer erros devido à duplicidade de definição dos objetos adicionados. Para criar um banco de dados vazio, sem nenhuma adição local, deve-se fazê-lo partir de template0, e não de template1 como, por exemplo: CREATE DATABASE foo WITH TEMPLATE template0;
O pg_dump possui algumas poucas limitações: •
Ao salvar uma única tabela, ou no formato texto-puro, o pg_dump não trata os objetos grandes. Os objetos grandes devem ser salvos juntamente com todo o banco de dados usando um dos formatos de cópia de segurança não-texto.
•
Quando é escolhido salvar apenas os dados, e se utiliza a opção --disable-triggers, o pg_dump emite comandos para desabilitar os gatilhos das tabelas do usuário antes de inserir os dados, e comandos para reabilitá-los após os dados terem sido inseridos. Se a restauração for interrompida antes do fim, os catálogos do sistema podem ser deixados em um estado errado.
Os membros de arquivos tar estão limitados a um tamanho inferior a 8 GB (esta limitação é inerente ao formato dos arquivos tar). Portanto, este formato não pode ser utilizado se a representação textual de uma tabela exceder este tamanho. O tamanho total do arquivo tar, e dos outros formatos de saída, não possui limitação exceto, talvez, pelo sistema operacional. Uma vez restaurado, é aconselhável executar o comando ANALYZE em todas as tabelas restauradas para que o otimizador possua estatísticas úteis.
Exemplos Para salvar um banco de dados: $ pg_dump meu_bd > db.out
Para recarregar este banco de dados: $ psql -d banco_de_dados -f db.out
Para salvar o banco de dados chamado meu_bd contendo objetos grandes em um arquivo tar: $ pg_dump -Ft -b meu_bd > db.tar
Para recarregar este banco de dados (com os objetos grandes) em um banco de dados existente chamado novo_bd: $ pg_restore -d novo_bd db.tar
Histórico O pg_dump apareceu pela primeira vez no Postgres95 versão 0.02. Os formatos de saída não-texto-puro foram introduzidos no PostgreSQL versão 7.1.
Veja também pg_dumpall, pg_restore, psql
867
pg_dumpall Nome pg_dumpall — salva os bancos de dados de um agrupamento do PostgreSQL em um arquivo de script
Sinopse pg_dumpall [opção...]
Descrição O pg_dumpall é um utilitário para salvar (dump) todos os bancos de dados de um agrupamento do PostgreSQL em um arquivo de script. O arquivo de script contém comandos SQL que podem ser usados como entrada do psql para restaurar os bancos de dados. Isto é feito chamando o pg_dump para cada banco de dados do agrupamento. O pg_dumpall também salva os objetos globais, comuns a todos os bancos de dados (O pg_dump não salva estes objetos). Atualmente são incluídas informações sobre os usuários do banco de dados e grupos, e permissões de acesso aplicadas aos bancos de dados como um todo. Portanto, o pg_dumpall é uma solução integrada para realizar cópias de segurança dos bancos de dados. Entretanto, deve ser observada a seguinte limitação: não é possível salvar “objetos grandes”, porque o pg_dump não pode salvar estes objetos em arquivos texto. Havendo bancos de dados contendo objetos grandes, estes devem ser salvos usando um dos modos de saída não-texto do pg_dump. Como o pg_dumpall lê tabelas de todos os bancos de dados, muito provavelmente será necessário se conectar como um superusuário para poder gerar uma cópia completa. Também será necessário o privilégio de superusuário para executar o script produzido, para poder criar usuários e grupos, e para poder criar os bancos de dados. O script SQL é escrito na saída padrão. Devem ser usados operadores de linha de comando para redirecionar para um arquivo. O pg_dumpall precisa se conectar várias vezes ao servidor PostgreSQL (uma vez para cada banco de dados), podendo ser necessário solicitar a senha cada uma destas vezes. Neste caso é conveniente existir o arquivo $HOME/.pgpass.
Opções As seguintes opções de linha de comando controlam o conteúdo e o formato da saída: -a --data-only
Salva somente os dados, não salva o esquema (definições de dado). -c --clean
Inclui comandos para remover (drop) os objetos do banco de dados antes dos comandos para criá-los. -d --inserts
Salva os dados como comandos INSERT, em vez de COPY. Torna a restauração muito lenta; sua utilização principal é para fazer cópias de segurança que possam ser carregadas em outros bancos de dados que não o PostgreSQL.
868
-D --column-inserts --attribute-inserts
Salva os dados como comandos INSERT explicitando os nomes das colunas (INSERT INTO tabela (coluna, ...) VALUES ...). Torna a restauração muito lenta, mas é necessário se for desejado mudar a ordem das colunas. -g --globals-only
Salva somente os objetos globais (usuários e grupos), e não os banco de dados. -i --ignore-version
Ignora a diferença de versão entre o pg_dump e o servidor de banco de dados. O pg_dump pode tratar bancos de dados de versões anteriores do PostgreSQL, mas as versões muito antigas não são mais suportadas (atualmente as anteriores a 7.0). Esta opção deve ser utilizada se for necessário desconsiderar a verificação de versão (mas se o pg_dumpall não for bem-sucedido, não diga que não foi avisado). -o --oids
Salva os identificadores de objeto (OIDs) de todas as tabelas como parte dos dados. Esta opção deve ser usada quando a coluna OID é referenciada de alguma maneira (por exemplo, em uma restrição de chave estrangeira). Caso contrário, esta opção não deve ser usada. -s --schema-only
Salva somente o esquema (definições dos dados), não os dados. -v --verbose
Especifica o modo verboso. Faz a aplicação pg_dumpall exibir mensagens de progresso na saída de erro padrão. -x --no-privileges --no-acl
Impede salvar os privilégios de acessos (comandos GRANT/REVOKE). As seguintes opções de linha de comando controlam os parâmetros de conexão com o servidor de banco de dados: -h hospedeiro Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/) é usado como o diretório do soquete do domínio Unix. O padrão é obter o nome a partir da variável de ambiente PGHOST, se esta estiver definida, senão tentar uma conexão pelo soquete do domínio Unix. -p porta Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. O padrão é obter a partir da variável de ambiente PGPORT, se esta estiver definida, senão o padrão compilado. -U nome_do_usuário Conectar como o usuário especificado.
869
-W Força a solicitação da senha, o que deve acontecer automaticamente quando o servidor requer autenticação por senha.
Ambiente PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Observações Como o pg_dumpall chama o pg_dump internamente, algumas mensagens de diagnósticos se referem ao pg_dump. Ao término da restauração, é aconselhável executar o comando ANALYZE em todos os bancos de dados para que o otimizador tenha estatísticas úteis. Também pode ser executado vacuumdb -a -z para analisar todos os bancos de dados.
Exemplos Para salvar todos bancos de dados: $ pg_dumpall > db.out
Para recarregar este banco de dados deve ser utilizado, por exemplo: $ psql -f db.out template1
(Neste caso o banco de dados a se conectar não tem importância, porque o arquivo de script criado pelo pg_dumpall contém os comandos apropriados para criar e conectar aos bancos de dados salvos).
Veja também pg_dump. Veja aí os detalhes sobre as condições de erro possíveis.
870
pg_restore Nome pg_restore — restaura um banco de dados do PostgreSQL a partir de um arquivo criado pelo pg_dump
Sinopse pg_restore [opção...] [nome_da_cópia_de_segurança]
Descrição O pg_restore é um utilitário para restaurar um banco de dados do PostgreSQL, a partir de uma cópia de segurança criada pelo pg_dump em um dos formatos não-texto-puro. São executados os comandos necessários para reconstruir o banco de dados, no estado em que este se encontrava na hora em que foi salvo. Os arquivos de cópia de segurança também permitem ao pg_restore selecionar o que será restaurado, ou mesmo reordenar os itens antes de serem restaurados. Os arquivos de cópia de segurança são projetados para serem portáveis entre arquiteturas diferentes. O pg_restore pode operar de dois modos: Se o nome do banco de dados for especificado, a cópia de segurança é restaurada diretamente no banco de dados (Os objetos grandes só podem ser restaurados utilizando uma conexão direta com o banco de dados como esta). Senão, é criado um script, no formato texto-puro, contendo os comandos SQL necessários para reconstruir o banco de dados (escrito em um arquivo ou na saída padrão), semelhante aos scripts criados pelo pg_dump. Algumas das opções que controlam a criação do script são, portanto, análogas às opções do pg_dump. Obviamente, o pg_restore não pode restaurar informações que não estejam presentes no arquivo de cópia de segurança. Por exemplo, se a cópia de segurança for gerada usando a opção “salvar dados como comandos INSERT”, o pg_restore não poderá restaurar os dados usando comandos COPY.
Opções O pg_restore aceita os seguintes argumentos de linha de comando. nome_da_cópia_de_segurança Especifica a localização do arquivo de cópia de segurança a ser restaurado. Se não for especificado, é usada a entrada padrão. -a --data-only
Salva somente os dados, não salva o esquema (definições de dado). -c --clean
Remove (drop) os objetos do banco de dados antes de criá-los. -C --create
Cria o banco de dados antes de restaurá-lo (Quando esta opção é utilizada, o banco de dados especificado na opção -d é usado apenas para executar o comando CREATE DATABASE inicial. Todos os dados são restaurados no banco de dados cujo nome aparece na cópia de segurança). -d nome_do_banco_de_dados --dbname=nome_do_banco_de_dados
Conecta ao banco de dados nome_do_banco_de_dados e restaura diretamente neste banco de dados.
871
-f arquivo_de_saída --file=arquivo_de_saída
Especifica o arquivo de saída para o script gerado, ou para conter a listagem quando for utilizada a opção -l. Por padrão a saída padrão. -F formato --format=formato
Especifica o formato do arquivo da cópia de segurança. Não é necessário especificar o formato, porque o pg_restore determina o formato automaticamente. Se for especificado, pode ser um dos seguintes: t
A cópia de segurança é um arquivo tar. Este formato de cópia de segurança permite reordenar e/ou excluir elementos do esquema ao restaurar o banco de dados. Também permite limitar quais dados são recarregados ao restaurar. c
A cópia de segurança está no formato personalizado do pg_dump. Este é o formato mais flexível, porque permite reordenar a restauração dos dados e dos elementos do esquema. Também, este formato é comprimido por padrão. -i --ignore-version
Ignora a verificação da versão do banco de dados. -I nome_do_índice --index=nome_do_índice
Restaura apenas a definição do índice especificado. -l --list
Lista o conteúdo da cópia de segurança. A saída desta operação pode ser usada com a opção -L para restringir e reordenar os itens a serem restaurados. -L arquivo_da_listagem --use-list=arquivo_da_listagem
Restaura apenas os elementos presentes no arquivo_da_listagem, e na ordem que aparecem neste arquivo. As linhas podem ser movidas e, também, podem virar comentário colocando um ; no seu início (Veja os exemplos abaixo). -N --orig-order
Restaura os itens na ordem original gerada pela aplicação pg_dump. Esta opção não possui nenhuma utilidade prática conhecida, uma vez que a aplicação pg_dump gera os itens em uma ordem conveniente para a mesma, que provavelmente não é uma ordem segura para restaurá-los (Esta não é a ordem na qual os itens estão listados na tabela de conteúdo da cópia de segurança). Veja também -r. -o --oid-order
Restaura os itens na ordem de OID. Esta opção possui utilidade prática limitada, uma vez que o OID é somente uma indicação aproximada da ordem original de criação. Esta opção prevalece sobre -N se ambas forem especificadas. Veja também -r. -O --no-owner
Não gera comandos para definir os donos dos objetos correspondendo aos donos destes objetos no banco de dados de origem. Por padrão, o pg_restore executa o comando SET SESSION AUTHORIZATION para definir os donos dos elementos criados no esquema. Estes comando não são bem-sucedidos a menos que a
872
conexão inicial com o banco de dados seja feita por um superusuário (ou o mesmo usuário que possui todos os objetos presentes no script). Usando a opção -O, pode ser utilizado qualquer nome de usuário na conexão inicial, e este usuário será o dono de todos objetos criados. -P nome_da_função(tipo_do_argumento [, ...]) --function=nome_da_função(tipo_do_argumento [, ...])
Restaura apenas a função especificada. Tome cuidado para escrever o nome da função e os argumentos exatamente como estes aparecem na tabela de conteúdo da cópia de segurança. -r --rearrange
Rearruma os itens por tipo do objeto (ocorre após a ordenação especificada por -N ou -o, se fornecido). Esta rearrumação tem por finalidade produzir o melhor desempenho possível para a restauração. Quando nem -N, nem -o e nem -r aparecem, o pg_restore restaura os itens na ordem em que aparecem na tabela de conteúdo (índice) da cópia de segurança, ou na ordem em que aparecem no arquivo_da_listagem se -L for especificado. A combinação de -o com -r duplica a ordenação feita pela aplicação pg_dump antes de criar a tabela de conteúdo da cópia de segurança e, portanto, normalmente não é necessário especificar. -R --no-reconnect
Esta opção está obsoleta, mas ainda é aceita para manter a compatibilidade com as versões anteriores. -s --schema-only
Restaura somente o esquema (definições de dados), não os dados. Os valores das seqüências são reiniciados. -S nome_de_usuário --superuser=nome_de_usuário
Especifica o nome de usuário do superusuário a ser usado para desabilitar os gatilhos. Somente é relevante quando é usada a opção --disable-triggers. -t tabela --table=tabela
Restaura apenas a definição e/ou dados da tabela especificada. -T gatilho --trigger=gatilho
Restaura apenas o gatilho especificado. -v --verbose
Especifica o modo verboso. -x --no-privileges --no-acl
Impede restaurar os privilégios de acessos (comandos GRANT/REVOKE). -X use-set-session-authorization --use-set-session-authorization
Esta opção está obsoleta, mas ainda é aceita para manter compatibilidade com as versões anteriores. O pg_restore agora sempre se comporta da maneira anteriormente selecionada por esta opção.
873
-X disable-triggers --disable-triggers
Esta opção é relevante apenas quando se restaura somente os dados. Faz com que o pg_restore execute comandos para desabilitar, temporariamente, os gatilhos das tabelas de destino enquanto os dados são recarregados. Deve ser utilizado quando existem verificações de integridade referencial, ou outros gatilhos nas tabelas, que não se deseja que sejam chamados durante a recarga dos dados. Atualmente, os comandos emitidos para a opção --disable-triggers devem ser executados por superusuários. Portanto, também deve ser especificado o nome de um superusuário com a opção -S ou, de preferência, executar, com cuidado, o script produzido como um superusuário. O pg_restore também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host=hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/) é usado como o diretório do soquete do domínio Unix. O padrão é obter o nome a partir da variável de ambiente PGHOST, se esta estiver definida, senão tentar uma conexão pelo soquete do domínio Unix. -p porta --port=porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. O padrão é obter a partir da variável de ambiente PGPORT, se esta estiver definida, senão o padrão compilado. -U nome_do_usuário
Conectar como o usuário especificado. -W
Força a solicitação da senha, o que deve acontecer automaticamente quando o servidor requer autenticação por senha.
Ambiente PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos Quando a conexão direta com o banco de dados é especificada usando a opção -d, o pg_restore executa internamente comandos SQL. Se acontecerem problemas ao executar o pg_restore, deve-se ter certeza que é possível selecionar informações no banco de dados utilizando, por exemplo, o utilitário psql.
Observações Se o agrupamento de bancos de dados tiver alguma adição local ao banco de dados template1, deve-se ter o cuidado de restaurar a saída do pg_restore em um banco de dados totalmente vazio; senão, podem acontecer erros devido à duplicidade de definição dos objetos adicionados. Para criar um banco de dados vazio, sem nenhuma adição local, deve-se fazê-lo partir de template0, e não de template1 como, por exemplo: CREATE DATABASE foo WITH TEMPLATE template0;
As limitações do pg_restore estão descritas abaixo. •
Ao restaurar os dados em uma tabela pré-existente utilizando a opção --disable-triggers, o pg_restore emite comandos para desabilitar os gatilhos das tabelas do usuário antes de inserir os dados, e comandos para
874
reabilitá-los após os dados terem sido inseridos. Se a restauração for interrompida antes do fim, os catálogos do sistema podem ser deixados em um estado errado. •
O pg_restore não restaura objetos grandes para uma única tabela. Se a cópia de segurança contém objetos grandes, então todos os objetos grandes são restaurados.
Veja também a documentação do pg_dump para obter os detalhes de suas limitações. Uma vez restaurado, é aconselhável executar o comando ANALYZE em todas as tabelas restauradas para que o otimizador possua estatísticas úteis.
Exemplos Para gerar uma cópia de segurança do banco de dados meu_bd, que contém objetos grandes, em um arquivo tar: $ pg_dump -Ft -b meu_bd > db.tar
Para restaurar este banco de dados (com os objetos grandes) no banco de dados chamado novo_bd: $ pg_restore -d novo_bd db.tar
Para reordenar os itens do banco de dados, primeiro é necessário criar um arquivo contendo a tabela de conteúdo (índice) da cópia de segurança: $ pg_restore -l copia_de_seguranca.arquivo > copia_de_seguranca.list
O arquivo de listagem consiste de um cabeçalho e uma linha para cada item como, por exemplo, ; ; Archive created at Fri Jul 28 22:28:36 2000 ; dbname: birds ; TOC Entries: 74 ; Compression: 0 ; Dump Version: 1.4-0 ; Format: CUSTOM ; ; ; Selected TOC Entries: ; 2; 145344 TABLE species postgres 3; 145344 ACL species 4; 145359 TABLE nt_header postgres 5; 145359 ACL nt_header 6; 145402 TABLE species_records postgres 7; 145402 ACL species_records 8; 145416 TABLE ss_old postgres 9; 145416 ACL ss_old 10; 145433 TABLE map_resolutions postgres 11; 145433 ACL map_resolutions 12; 145443 TABLE hs_old postgres 13; 145443 ACL hs_old
Ponto-e-vírgula inicia um comentário, e os números no início das linhas referem-se aos identificadores internos da cópia de segurança atribuídos a cada item. As linhas do arquivo podem ser transformadas em comentário, excluídas e reordenadas. Por exemplo 10; 145433 TABLE map_resolutions postgres ;2; 145344 TABLE species postgres ;4; 145359 TABLE nt_header postgres 6; 145402 TABLE species_records postgres ;8; 145416 TABLE ss_old postgres
875
poderia ser usado como entrada do pg_restore e somente restauraria os itens 10 e 6, nesta ordem. $ pg_restore -L copia_de_seguranca.list copia_de_seguranca.arquivo
Histórico O utilitário pg_restore apareceu pela primeira vez no PostgreSQL 7.1.
Veja também pg_dump, pg_dumpall, psql
876
pgtclsh Nome pgtclsh — shell Tcl cliente do PostgreSQL
Sinopse pgtclsh [nome_do_arquivo [argumento...]]
Descrição O pgtclsh é uma interface shell Tcl estendida com funções de acesso a bancos de dados do PostgreSQL (Essencialmente, é uma tclsh com a libpgtcl carregada). Como no caso da shell Tcl normal, o primeiro argumento da linha de comando é um arquivo de script, e todos os demais argumentos são passados para o script. Se nenhum nome de arquivo de script for fornecido, a shell será interativa. Uma shell Tcl com funções Tk e PostgreSQL está disponível em pgtksh.
Veja também pgtksh, Capítulo 29 (descrição da libpgtcl) , tclsh
877
pgtksh Nome pgtksh — shell Tcl/Tk cliente do PostgreSQL
Sinopse pgtksh [nome_do_arquivo [argumento...]]
Descrição O pgtksh é uma interface shell Tcl/Tk estendida com funções de acesso a bancos de dados do PostgreSQL (Essencialmente, é um wish 1 com a libpgtcl carregada). Como a wish, a Tcl/Tk normal, o primeiro argumento da linha de comando é um arquivo de script, e todos os demais argumentos são passados para o script. As opções especiais podem ser processadas pelas bibliotecas do Sistema X Window em vez desta. Se nenhum arquivo de script for especificado, a shell será interativa. Uma shell Tcl com funções PostgreSQL está disponível em pgtclsh.
Veja também pgtclsh, Capítulo 29 (descrição da libpgtcl) , tclsh , wish
Notas 1. wish — um programa simples que consiste na linguagem de comando Tcl (Tool Command Language), o conjunto de ferramentas Tk, e um programa principal que lê da entrada padrão ou de um arquivo (N. do T.)
878
psql Nome psql — terminal interativo do PostgreSQL
Sinopse psql [opção...] [nome_do_banco_de_dados [nome_do_usuário]]
Descrição O psql é um cliente no modo terminal do PostgreSQL. Permite digitar comandos interativamente, submetê-los para o PostgreSQL e ver os resultados. Como alternativa, a entrada pode vir de um arquivo. Além disso, disponibiliza vários meta-comandos e diversas funcionalidades semelhantes às do interpretador de comandos (shell) para facilitar a criação de scripts e automatizar um grande número de tarefas.
Opções -a --echo-all
Envia todas as linhas de entrada para a saída padrão à medida que são lidas. É mais útil para o processamento de scripts do que no modo interativo. Equivale a definir a variável ECHO como all. -A --no-align
Comuta para o modo de saída não alinhado (De outra forma, o modo de saída padrão é o alinhado). -c comando --command comando
Especifica que o psql deve executar a cadeia de caracteres comando e, em seguida, terminar. Útil em scripts do interpretador comandos. O comando deve ser uma cadeia de caracteres que possa ser integralmente analisada pelo servidor (ou seja, não contém funcionalidades específicas do psql), ou ser um único comando de contrabarra. Portanto, não podem ser misturados comandos SQL com meta-comandos do psql. Para misturar, a cadeia de caracteres pode ser enviada para o psql conforme mostrado a seguir: echo "\x \\ select * from foo;" | psql. Se a cadeia de caracteres do comando contiver vários comandos SQL, estes serão processados em uma única transação, a menos que existam comandos BEGIN/COMMIT explícitos incluídos na cadeia de caracteres para dividi-los em várias transações. Este comportamento é diferente do comportamento que ocorre quando a mesma cadeia de caracteres é introduzida na entrada padrão do psql. -d nome_do_banco_de_dados --dbname nome_do_banco_de_dados
Especifica o nome do banco de dados a se conectar. Equivale a especificar nome_do_banco_de_dados como o primeiro argumento não-opção na linha de comando. -e --echo-queries
Copia todos os comandos SQL enviados para o servidor para a saída padrão também. Equivale a definir a variável ECHO como queries.
879
-E --echo-hidden
Exibe os verdadeiros comandos gerados por \d e por outros comandos de contrabarra. Pode ser usado para estudar as operações internas do psql. Equivale a definir a variável ECHO_HIDDEN dentro do psql. -f nome_do_arquivo --file nome_do_arquivo
Usa o arquivo nome_do_arquivo como origem dos comandos, em vez de ler os comandos interativamente. Após processar o arquivo, o psql termina. Sob muitos aspectos equivale ao comando interno \i. Se o nome_do_arquivo for - (hífen), então a entrada padrão é lida. O uso desta opção é sutilmente diferente de escrever psql < nome_do_arquivo. De uma maneira geral, as duas formas fazem o esperado, mas o uso da opção -f ativa algumas funcionalidades úteis, como mensagens de erro com o número da linha. Ao se usar esta opção existe, também, uma pequena chance de reduzir a sobrecarga de inicialização. Por outro lado, a utilização do redirecionamento da entrada na linha de comando garante, teoricamente, que será produzida exatamente a mesma saída que seria produzida se tudo fosse entrado à mão. -F separador --field-separator separador
Usa o separador como separador de campos. Equivale a \pset fieldsep ou ao comando \f. -h hospedeiro --host hospedeiro
Especifica o nome do hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/) é usado como o diretório do soquete do domínio Unix. -H --html
Ativa a saída tabular HTML. Equivale a \pset format html ou ao comando \H. -l --list
Mostra todos os bancos de dados disponíveis, e depois termina. As outras opções, fora as de conexão, são ignoradas. Semelhante ao comando interno \list. -o nome_do_arquivo --output nome_do_arquivo
Coloca a saída de todos os comandos no arquivo nome_do_arquivo. Equivale ao comando \o. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. O padrão é obter a partir da variável de ambiente PGPORT, se esta estiver definida, senão a porta especificada em tempo de compilação, geralmente 5432. -P atribuição --pset atribuição
Permite especificar opções de exibição no estilo do \pset pela linha de comando. Observe que aqui o nome e o valor devem estar separados pelo sinal de igual, em vez de espaço. Portanto, para definir o formato de saída como LaTeX deve ser escrito -P format=latex.
880
-q --quiet
Especifica que o psql deve trabalhar em silêncio. Por padrão, são exibidas mensagens de boas-vindas e várias outras mensagens informativas. Se esta opção for usada, nada disso acontece. É útil em conjunto com a opção -c. Dentro do psql é possível definir a variável QUIET para obter o mesmo efeito. -R separador --record-separator separador
Usa o separador como separador de registros. Equivale ao comando \pset recordsep. -s --single-step
Executa no modo passo-único, significando que será solicitada uma confirmação antes de cada comando ser enviado para o servidor, com a opção de cancelar a execução. Usado para depurar scripts. -S --single-line
Executa no modo linha-única, onde o caractere de nova-linha termina o comando SQL, como o ponto-evírgula faz. Nota: Este modo é fornecido para aqueles que insistem em usá-lo, mas sua utilização não é incentivada. Em particular, se forem misturados comandos SQL e meta-comandos na mesma linha, a ordem de execução nem sempre será clara para o usuário inexperiente. -t --tuples-only
Desabilita a exibição dos nomes das colunas, rodapés com contadores de linhas do resultado, etc. É equivalente ao comando \t. -T opções_de_tabela --table-attr opções_de_tabela
Permite especificar opções a serem colocadas dentro da marca table do HTML. Veja \pset para obter detalhes. -u
Força o psql solicitar o nome do usuário e a senha antes de conectar ao banco de dados. Esta opção está obsoleta, porque é conceitualmente incorreta (Solicitar um nome de usuário não padrão e solicitar uma senha porque o servidor requer são realmente duas coisas diferentes). Incentiva-se o uso das opções -U e -W em seu lugar. -U nome_do_usuário --username nome_do_usuário
Conecta ao banco de dados como o usuário nome_do_usuário em vez do usuário padrão (É necessário ter permissão para fazê-lo, é claro). -v atribuição --set atribuição --variable atribuição
Realiza atribuição de variável, como o comando interno \set. Observe que é necessário separar o nome e o valor, se houver, por um sinal de igual na linha de comando. Para remover a definição de uma variável deve ser omitido o sinal de igual. Para apenas definir uma variável, sem um valor, o sinal de igual é usado mas o valor é omitido. Estas atribuições são feitas durante um estágio bem no princípio da inicialização e, portanto, as variáveis reservadas para finalidades internas podem ser sobrescritas posteriormente. -V --version
Mostra a versão do psql, e depois termina.
881
-W --password
Força o psql solicitar a senha antes de conectar ao banco de dados. Esta opção continuará definida por toda a sessão, mesmo que a conexão com o banco de dados seja mudada pelo meta-comando \connect. O psql deve solicitar, automaticamente, a senha sempre que o servidor requerer autenticação por senha. Como atualmente a detecção de requisição de senha não é inteiramente confiável, esta opção existe para forçar a solicitação. Se a senha não for solicitada, e o servidor requerer autenticação por senha, a tentativa de conexão não será bem-sucedida. -x --expanded
Ativa o modo formatação de tabela estendido. Equivale ao comando \x. -X, --no-psqlrc
Não lê o arquivo de inicialização ~/.psqlrc. -? --help
Mostra a ajuda sobre os argumentos de linha de comando do psql, e depois termina.
Status de saída O psql retorna para o interpretador de comandos: 0 se terminar normalmente; 1 se ocorrer erro fatal próprio (falta de memória, arquivo não encontrado); 2 se a conexão com o servidor teve problema e a sessão não é interativa; 3 se ocorrer erro no script e a variável ON_ERROR_STOP estiver definida.
Utilização Conexão com o banco de dados O psql é uma aplicação cliente do PostgreSQL comum. Para conectar a um banco de dados é necessário saber o nome do banco de dados, o nome do hospedeiro, o número da porta do servidor e o nome do usuário a ser usado para conectar. O psql pode ser informado sobre estes parâmetros por meio das opções de linha de comando -d, -h, -p e -U, respectivamente. Se for encontrado um argumento que não pertence a nenhuma opção, este será interpretado como o nome do banco de dados (ou o nome do usuário, se o nome do banco de dados já tiver sido fornecido). Nem todas estas opções são requeridas; existem padrões úteis. Se for omitido o nome do hospedeiro, então o psql se conecta através do soquete do domínio Unix ao servidor no hospedeiro local. O número padrão para a porta é determinado na compilação. Uma vez que que o servidor de banco de dados usa o mesmo padrão, não é necessário especificar a porta na maioria dos casos. O nome de usuário padrão é o nome do usuário do Unix, como também é o nome do banco de dados padrão. Observe que não é possível se conectar a qualquer banco de dados com qualquer nome de usuário. O administrador de banco de dados deve informar as permissões de acesso concedidas. Para evitar a digitação, podem ser definidas as variáveis de ambiente PGDATABASE, PGHOST, PGPORT e PGUSER com os valores apropriados. Se a conexão não puder ser estabelecida por algum motivo (por exemplo, privilégios insuficientes, o servidor não está executando no hospedeiro de destino, etc.), o psql retorna uma mensagem de erro e termina. Entrando com comandos SQL No modo normal de operação, o psql exibe um prompt com o nome do banco de dados ao qual está conectado, seguido pela cadeia de caracteres =>. Por exemplo:
882
$ psql testdb Welcome to psql 7.4.1, the PostgreSQL interactive terminal. Type:
\copyright for distribution terms \h for help with SQL commands \? for help on internal slash commands \g or terminate with semicolon to execute query \q to quit
testdb=>
No prompt o usuário pode digitar comandos SQL. Normalmente, as linhas de entrada são enviadas para o servidor quando é encontrado o caractere ponto-e-vírgula, que termina o comando. Um fim de linha não termina o comando. Portanto, os comandos podem ser distribuídos por várias linhas para maior clareza. Se o comando for enviado e executado sem erro, o resultado do comando será mostrado na tela. Sempre que um comando é executado, o psql também procura por eventos de notificação assíncronos gerados pelo LISTEN e NOTIFY. Meta-comandos Qualquer texto digitado no psql começando por uma contrabarra (\) (não entre apóstrofos, ') é um metacomando do psql processado pelo próprio psql. Estes comandos ajudam a tornar o psql mais útil para administração e para scripts. Os meta-comandos são geralmente chamados de comandos de barra ou de contrabarra. O formato de um comando psql é a contrabarra, seguida imediatamente por um verbo comando, e depois pelos argumentos. Os argumentos são separados do verbo comando, e entre si, por qualquer número de caracteres de espaço em branco. Para incluir espaço em branco no argumento deve-se colocá-los entre apóstrofos ('). Para incluir um apóstrofo neste tipo de argumento, deve-se precedê-lo por uma contrabarra. Qualquer texto entre apóstrofos está sujeito às substituições no estilo C para \n (nova-linha), \t (tabulação), \dígitos, \0dígitos e \0xdígitos (o caractere com o código decimal, octal ou hexadecimal especificado). Se um argumento (não entre apóstrofos) começar por dois-pontos (:), será considerado como sendo uma variável do psql, e o valor desta variável será usado como o argumento. Os argumentos entre crases (`) são considerados como sendo linhas de comando a serem passadas para o interpretador de comandos. A saída do comando (com o caractere de nova-linha final removido) é usada como o valor do argumento. As seqüências de escape (\) acima também se aplicam às crases. Alguns comandos recebem um identificador SQL (como o nome de uma tabela) como argumento. Estes argumentos seguem as regras de sintaxe do SQL: letras não entre aspas são transformadas em minúsculas, enquanto as aspas (") protegem as letras de serem convertidas e permitem a incorporação de espaços em branco dentro do identificador. Entre as aspas, um par de aspas é reduzido a uma única aspa no nome resultante. Por exemplo, FOO"BAR"BAZ é interpretado como fooBARbaz, e "Um nome"" estranho" se torna Um nome" estranho. A análise dos argumentos pára quando é encontrada outra contrabarra (não entre apóstrofos). Esta é considerada como sendo o início de um novo meta-comando. A seqüência especial \\ (duas contrabarras) marca o fim dos argumentos e a continuação da análise dos comandos SQL, se existirem. Desta forma, os comandos SQL e psql podem ser livremente misturados na linha. Mas em nenhum caso os argumentos de um meta-comando podem continuar após o fim da linha. Os seguintes meta-comandos estão definidos: \a
Se o formato corrente de saída de tabela for desalinhado, troca para alinhado. Se não for desalinhado, define como desalinhado. Este comando é mantido para compatibilidade com as versões anteriores. Veja em \pset uma solução mais geral.
883
\cd [diretório]
Muda o diretório de trabalho corrente para diretório. Sem argumento, muda para o diretório home do usuário corrente. Dica: Para ver o diretório de trabalho corrente deve ser usado \!pwd. \C [ título ]
Define o título de todas as tabelas mostradas como resultado de uma consulta, ou remove a definição deste título. Este comando equivale a \pset title título (O nome deste comando deriva de “caption” (título), porque anteriormente só era usado para definir título em uma tabela HTML). \connect (ou \c) [ nome_do_banco_de_dados [ nome_do_usuário ] ]
Estabelece a conexão com um banco de dados novo e/ou com um usuário novo. A conexão anterior é fechada. Se o nome_do_banco_de_dados for - (hífen), então é assumido o banco de dados corrente. Se o nome_do_usuário for omitido, então o nome do usuário corrente é utilizado. Como regra especial, o \connect sem nenhum argumento conecta ao banco de dados padrão com o usuário padrão (da mesma forma que aconteceria se o psql fosse iniciado sem argumentos). Se a tentativa de conexão não for bem-sucedida (nome de usuário errado, acesso negado, etc.), a conexão anterior será mantida se, e somente se, o psql estiver no modo interativo. Quando estiver executando um script não interativo, o processamento será interrompido imediatamente com erro. Esta distinção foi escolhida por ser mais conveniente para o usuário, que digita menos, e como um mecanismo de segurança, impedindo os scripts de atuarem acidentalmente no banco de dados errado. \copy tabela [ ( lista_de_colunas ) ] { from | to } nome_do_arquivo | stdin | stdout [ with ] [ oids ] [ delimiter [as] 'caractere' ] [ null [as] 'cadeia_de_caracteres' ]
Executa uma cópia pelo cliente. Esta é uma operação que executa o comando COPY do SQL, mas em vez do servidor ler ou escrever no arquivo especificado, o psql lê ou escreve no arquivo e roteia os dados entre o servidor e o sistema de arquivos local. Isto significa que a acessibilidade ao arquivo e os privilégios são do usuário local, e não do servidor, e que não há necessidade dos privilégios do superusuário. A sintaxe deste comando é semelhante à sintaxe do comando COPY do SQL (Veja sua descrição para obter detalhes). Observe que, por isso, regras especiais de análise se aplicam ao comando \copy. Em particular, as regras de substituição de variável e de escapes de contrabarra (\) não se aplicam. Dica: Este operação não é tão eficiente quanto o comando COPY do SQL, porque todos os dados passam através da conexão cliente/servidor. Para uma grande quantidade de dados, o comando SQL pode ser preferível. Nota: Observe a diferença de interpretação da stdin e da stdout entre as cópias pelo cliente e pelo servidor: na cópia pelo cliente se referem sempre à entrada e saída do psql. Na cópia pelo servidor, stdin vem do lugar onde o próprio comando COPY veio (por exemplo, um script executado com a opção -f), e a stdout se refere à saída do comando (veja o meta-comando \o abaixo). \copyright
Mostra os termos da distribuição e dos direitos autorais do PostgreSQL. \d [ padrão ]
Para cada relação (tabela, visão, índice ou seqüência) correspondendo ao padrão, mostra todas as colunas, seus tipos e os atributos especiais como NOT NULL ou o valor padrão, se houver. Os índices, restrições, regras e gatilhos associados também são mostrados, assim como a definição da visão se a relação for uma visão (A “Correspondência com padrão” é definida abaixo). A forma \d+ do comando é idêntica, mas todos os comentários associados às colunas da tabela também são mostrados. Nota: Se \d for utilizado sem o argumento padrão, torna-se equivalente a \dtvs, mostrando a lista de todas as tabelas, visões e seqüências. Isto é puramente uma medida de conveniência.
884
\da [ padrão ]
Lista todas as funções de agregação disponíveis, junto com o tipo de dado com que operam. Se for especificado o padrão, somente são mostradas as agregações cujos nomes correspondem ao padrão. \dc [ padrão ]
Lista todas as conversões entre codificações de conjunto de caracteres disponíveis. Se for especificado o padrão, somente são mostradas as conversões cujos nomes correspondem ao padrão. \dC
Mostra todas as conversões de tipo (cast) disponíveis. \dd [ padrão ]
Mostra a descrição dos objetos cujos nomes correspondem ao padrão, ou todos os objetos visíveis se nenhum argumento for especificado. Nos dois casos somente são listados os objetos que possuem uma descrição (“Objeto” compreende agregações, funções, operadores, tipos, relações [tabelas, visões, índices, seqüências e objetos grandes], regras e gatilhos). Por exemplo: => \dd version Object descriptions Schema | Name | Object | Description ------------+---------+----------+--------------------------pg_catalog | version | function | PostgreSQL version string (1 linha)
As descrições dos objetos podem ser criadas pelo comando COMMENT do SQL. \dD [ padrão ]
Lista todos os domínios disponíveis. Se for especificado o padrão, somente são mostrados os domínios cujos nomes correspondem ao padrão. \df [ padrão ]
Lista as funções disponíveis, junto com o tipo de dado de seus argumentos e do valor retornado. Se for especificado o padrão, somente são mostradas as funções cujos nomes correspondem ao padrão. Se for usada a forma \df+, são mostradas informações adicionais sobre cada função, incluindo a linguagem e a descrição. Nota: Para reduzir a desordem, o \df não mostra as funções com tipo de dado I/O. Isto é implementado ignorando as funções que recebem ou retornam o tipo cstring. \distvS [ padrão ]
Este não é, na verdade, o nome do comando: As letras i, s, t, v, S correspondem a índice, seqüência, tabela, visão e tabela do sistema, respectivamente. Pode ser especificada qualquer uma ou todas as letras, em qualquer ordem, para obter a listagem de todos os objetos correspondentes. A letra S restringe a listagem aos objetos do sistema; sem o S, somente são mostrados os objetos que não são do sistema. Se for anexado ao nome do comando o caractere +, cada objeto é listado junto com sua descrição associada, se houver. Se for especificado o padrão, somente são mostrados os objetos cujos nomes correspondem ao padrão. \dl
Este é um outro nome para \lo_list, que mostra a lista dos objetos grandes. \dn [ padrão ]
Lista todos os esquemas (espaços de nomes) disponíveis. Se for especificado o padrão (uma expressão regular), somente são mostrados os esquemas cujos nomes correspondem ao padrão. \do [ padrão ]
Lista os operadores disponíveis junto com o tipo de seus operandos e do valor retornado. Se for especificado o padrão, somente são mostrados os operadores cujos nomes correspondem ao padrão.
885
\dp [ padrão ]
Produz uma lista contendo todas as tabelas, visões e seqüências disponíveis, junto com seus privilégios de acesso associados. Se for especificado o padrão, somente são mostradas as tabelas, visões e seqüências cujos nomes correspondem ao padrão. Os comandos GRANT e REVOKE são utilizados para definir os privilégios de acesso. Veja o comando GRANT para obter mais informações. \dT [ padrão ]
Mostra todos os tipos de dado, ou somente aqueles que correspondem ao padrão. A forma do comando \dT+ mostra informações adicionais. \du [ padrão ]
Lista todos os usuários do banco de dados, ou somente aqueles que correspondem ao padrão. \edit (ou \e) [ nome_do_arquivo ]
Se for especificado o nome_do_arquivo, o arquivo é editado; após o fim da edição (fechar o editor), o conteúdo do arquivo é copiado para o buffer de comando. Se não for fornecido nenhum argumento, o buffer de comando corrente é copiado para um arquivo temporário, que é editado de forma idêntica. O novo buffer de comando é então analisado novamente, de acordo com as regras normais do psql, onde todo o buffer é tratado como sendo uma única linha (Portanto, não podem ser gerados scripts dessa forma. Use o comando \i para isso). Significa também que, se o comando terminar por (ou contiver) um ponto-e-vírgula, será executado imediatamente. Se não contiver, apenas permanecerá aguardando no buffer de comando. Dica: O psql procura nas variáveis de ambiente PSQL_EDITOR, EDITOR e VISUAL (nesta ordem) o editor a ser usado. Se nenhuma delas estiver definida, então é usado /bin/vi. \echo texto [ ... ]
Envia os argumentos para a saída padrão, separados por um espaço e seguido por um caractere de novalinha, o que pode ser útil para intercalar informações na saída dos scripts. Por exemplo: => \echo `date` Dom Fev 20 05:10:59 BRT 2005
Se o primeiro argumento for -n (não entre apóstrofos) não é enviado o caractere de nova-linha final. Dica: Se for usado o comando \o para redirecionar a saída do comando, talvez seja preferível utilizar \qecho em vez deste comando. \encoding [ codificação ]
Define a codificação do conjunto de caracteres do cliente. Sem argumento, este comando mostra a codificação corrente. Por exemplo: => \encoding LATIN1 \f [ cadeia_de_caracteres ]
Define o separador de campos para a saída de comando desalinhada. O padrão é a barra vertical (|). Veja também em \pset uma forma genérica para definir as opções de saída. \g [ { nome_do_arquivo | |comando } ]
Envia o buffer de entrada de comando corrente para o servidor e, opcionalmente, armazena a saída do comando em nome_do_arquivo, ou envia a saída para outro interpretador de comandos do Unix executar o comando. Um \g puro e simples é virtualmente equivalente ao ponto-e-vírgula. Um \g com argumento é uma alternativa “de uma única vez” para o comando \o. O exemplo abaixo coloca a saída do comando SELECT na área de edição do editor gvim: 1 => SELECT datname FROM pg_database \g | gvim => Vim: Reading from stdin...
886
\help (ou \h) [ comando ]
Fornece ajuda de sintaxe para o comando SQL especificado. Senão for especificado o comando, então o psql lista todos os comandos para os quais existe ajuda de sintaxe disponível. Se o comando for um asterisco (“*”), então é mostrada a ajuda de sintaxe para todos os comandos SQL. Nota: Para simplificar a digitação, os comandos compostos por várias palavras não necessitam estar entre apóstrofos. Portanto, pode ser digitado \help alter table. \H
Habilita o formato de saída de comando HTML. Se o formato HTML já estiver habilitado, retorna ao formato de texto alinhado padrão. Este comando existe por compatibilidade e conveniência, mas veja em \pset a definição de outras opções de saída. \i nome_do_arquivo
Lê a entrada no arquivo nome_do_arquivo, e executa como se tivesse sido digitada pelo teclado. Nota: Se for desejado ver as linhas na tela à medida que são lidas, deve ser definida a variável ECHO como all. \l (ou \list)
Lista o nome, dono e codificação do conjunto de caracteres de todos os bancos de dados do servidor. Se for adicionado o caractere + ao nome do comando, também são mostradas todas as descrições dos bancos de dados. \lo_export loid nome_do_arquivo
Lê no banco de dados o objeto grande com OID igual a loid, e escreve em nome_do_arquivo. Observe que isto é sutilmente diferente da função do servidor lo_export, que atua com a permissão do usuário como o qual o servidor de banco de dados está executando, e no sistema de arquivos do servidor. Dica: Use \lo_list para descobrir os OIDs dos objetos grandes. \lo_import nome_do_arquivo [ comentário ]
Armazena o arquivo em um objeto grande do PostgreSQL. Opcionalmente, associa o comentário fornecido ao objeto. Exemplo: foo=> \lo_import '/home/peter/pictures/photo.xcf' 'uma fotografia minha' lo_import 152801
A resposta indica que o objeto grande recebeu o identificador de objeto 152801, que deve ser lembrado para acessar o objeto novamente. Por esta razão, recomenda-se associar sempre um comentário inteligível a cada objeto. Estes podem ser vistos utilizando o comando \lo_list. Observe que este comando é sutilmente diferente da função lo_import do servidor, porque atua como o usuário local no sistema de arquivos local, em vez do usuário do servidor no sistema de arquivos do servidor. \lo_list
Mostra a lista de todos os objetos grandes do PostgreSQL armazenados neste instante no banco de dados, junto com os comentários fornecidos para os mesmos. \lo_unlink loid
Remove do banco de dados o objeto grande com o OID igual a loid. Dica: Use \lo_list para descobrir os OIDs dos objetos grandes. \o [ {nome_do_arquivo | |comando} ]
Salva os resultados dos próximos comandos no arquivo nome_do_arquivo, ou envia os próximos resultados para um outro interpretador de comandos do Unix para executar o comando. Se não for especificado nenhum argumento, a saída do comando será redefinida para a saída padrão.
887
O exemplo abaixo coloca a saída dos comandos SELECT e \qecho na área de edição do editor gvim: 2 => => => => => => =>
\o | gvim Vim: Reading from stdin... \qecho Bancos de Dados SELECT datname FROM pg_database; \qecho Linguagens SELECT lanname FROM pg_language; \o
Os “resultados dos comandos” incluem todas as tabelas, respostas dos comandos e notificações recebidas do servidor de banco de dados, assim como a saída de vários comandos de contrabarra que consultam o banco de dados (como o \d), mas não as mensagens de erro. Dica: Para intercalar saída de texto entre os resultados dos comandos deve ser utilizado \qecho. \p
Envia o buffer de comando corrente para a saída padrão. \pset parâmetro [ value ]
Este comando define opções que afetam a saída das tabelas de resultado dos comandos. O parâmetro indica qual opção será definida. A semântica do valor depende do parâmetro. As opções de exibição ajustáveis são: format
Define o formato de saída como unaligned (desalinhado), aligned (alinhado), html ou latex. São permitidas abreviações únicas (O que significa que basta uma letra). O modo “unaligned” escreve todas as colunas de uma linha em uma única linha, separadas pelo separador de campos ativo corrente. Pretende-se com isso criar uma saída que sirva de entrada para outros programas (separada por tabulação, vírgula, etc.). O modo “aligned” é a saída de texto padrão, inteligível e agradavelmente formatada. Os modos “HTML” e “LaTeX” produzem tabelas feitas para serem incluídas em documentos usando a linguagem de marcação correspondente. Não são documentos completos! (Isto não é tão problemático no HTML, mas no LaTeX deve haver um invólucro completo do documento). border
O segundo argumento deve ser um número. Em geral, quanto maior o número mais bordas e linhas a tabela terá, mas isto depende do formato. No modo HTML será traduzido diretamente para o atributo border=..., nos demais modos só fazem sentido os valores: 0 (sem borda); 1 (linhas divisórias internas); e 2 (moldura da tabela). expanded (ou x)
Alterna entre os formatos regular e expandido. Quando o formato expandido está habilitado, todas as saídas possuem duas colunas, com o nome da coluna à esquerda e o dado à direita. Este modo é útil quando os dados não cabem na tela no modo normal “horizontal”. O modo expandido é suportado por todos os quatro formatos de saída. null
O segundo argumento é a cadeia de caracteres a ser mostrada sempre que a coluna for nula. O padrão é não mostrar nada, que pode ser facilmente confundido com, por exemplo, uma cadeia de caracteres vazia. Portanto, pode-se preferir escrever \pset null '(nulo)'. fieldsep
Especifica o separador de campos a ser utilizado no modo de saída desalinhado. Desta forma pode ser criada, por exemplo, uma saída separada por tabulação ou por vírgula, que os outros programas podem preferir. Para definir o caractere de tabulação como separador de campos deve ser usado \pset fieldsep '\t'. O separador de campos padrão é '|' (a barra vertical).
888
footer
Alterna a exibição do rodapé padrão (x linhas). recordsep
Especifica o separador de registro (linha) a ser usado no modo de saída desalinhado. O padrão é o caractere de nova-linha. tuples_only (ou t)
Alterna entre mostrar somente as tuplas e mostrar tudo. O modo mostrar tudo pode mostrar informações adicionais como os cabeçalhos das colunas, títulos e vários rodapés. No modo somentetuplas são mostrados apenas os dados da tabela. title [ texto ]
Define o título das próximas tabelas mostradas. Pode ser usado para colocar textos descritivos na saída. Se não for fornecido nenhum argumento, o título é removido. tableattr (ou T) [ texto ]
Permite especificar qualquer atributo a ser colocado dentro da marca table do HTML. Estes atributos podem ser, por exemplo, cellpadding ou bgcolor. Observe que, provavelmente, não será desejado especificar border aqui, porque isto já é tratado pelo \pset border. pager
Controla o uso do paginador para comandos e para a saída da ajuda do psql. Se a variável de ambiente PAGER estiver definida, a saída será enviada para o programa especificado, senão é utilizado o padrão dependente da plataforma (como o more). Quando o paginador está desabilitado, a paginação não é feita. Quando o paginador está habilitado, a paginação é feita somente quando for apropriado, ou seja, quando a saída é para um terminal e não cabe na tela (O psql não realiza um trabalho perfeito ao avaliar quando o paginador deve ser utilizado). \pset pager habilita e desabilita o paginador. O paginador também pode ser definido como always, o que faz o paginador ser utilizado sempre. Ilustrações mostrando como se parecem estes formatos diferentes podem ser vistas na seção Exemplos. Dica: Existem vários comandos abreviados para o \pset. Veja \a, \C, \H, \t, \T e \x. Nota: É errado chamar o \pset sem argumentos. No futuro, esta chamada deverá mostrar o status corrente de todas as opções de exibição. \q
Sair do programa psql. \qecho texto [ ... ]
Este comando é idêntico a \echo, exceto que toda a saída é escrita no canal de saída de comando, conforme definido por \o. \r
Redefine (limpa) o buffer de comando. \s [ nome_do_arquivo ]
Mostra ou salva o histórico da linha de comando em nome_do_arquivo. Se for omitido o nome_do_arquivo, o histórico é escrito na saída padrão. Esta opção somente estará disponível se o psql estiver configurado para usar a biblioteca Readline do GNU. Nota: Na versão corrente não é mais necessário salvar o histórico de comandos, porque isso é feito automaticamente ao término do programa. O histórico também é carregado, automaticamente, toda vez que o psql inicia.
889
\set [ nome [ value [ ... ]]]
Define a variável interna nome com o valor ou, se for fornecido mais de um valor, com a concatenação de todos os valores. Se não for fornecido o segundo argumento a variável somente é definida, sem nenhum valor. Para remover a definição da variável deve ser usado o comando \unset. Nomes de variáveis válidos podem conter letras, dígitos e sublinhados (_). Veja a seção Variáveis abaixo para obter detalhes. Embora possa ser definida qualquer variável como qualquer coisa desejada, o psql trata várias variáveis como sendo especiais. Elas estão documentadas na seção sobre variáveis. Nota: Este comando é totalmente distinto do comando SET do SQL. \t
Alterna a exibição do cabeçalho contendo o nome das colunas e do rodapé contendo o número de linhas. Este comando equivale a \pset tuples_only, sendo fornecido por conveniência. \T opções_de_tabela
Permite especificar atributos a serem colocados na marca table no modo de saída tabular HTML. Este comando equivale a \pset tableattr opções_de_tabela. \timing
Alterna a exibição de quanto tempo cada comando SQL demora, em milissegundos. \w {nome_do_arquivo | |command}
Escreve o buffer de comando corrente no arquivo nome_do_arquivo, ou envia para o comando Unix comando através de um pipe. O exemplo abaixo utiliza o comando \w para executar dois comandos do sistema operacional: 3 => \w | date Dom Fev 20 07:55:08 BRT 2005 => \w | pwd /root \x
Alterna o modo de formatação de tabela estendido. Como tal equivale a \pset expanded. \z [ padrão ]
Produz uma lista contendo todas as tabelas, visões e seqüências disponíveis, junto com seus privilégios de acesso associados. Se for especificado o padrão, somente são mostradas as tabelas, visões e seqüências cujos nomes correspondem ao padrão. Os comandos GRANT e REVOKE são utilizados para definir os privilégios de acesso. Veja o comando GRANT para obter mais informações. Este comando é um outro nome para o comando \dp (“display privileges”). \! [ comando ]
Abre um outro interpretador de comandos do Unix, ou executa o comando Unix comando. Os argumentos não são mais interpretados, sendo enviados para o interpretador de comandos como estão. O exemplo abaixo utiliza o meta-comando \! para executar dois comandos do sistema operacional Unix: 4
=> \!date Dom Fev 20 08:04:41 BRT 2005 => \!pwd /root \?
Mostra informação de ajuda para os comandos de contrabarra (“\”).
890
Vários comandos \d aceitam como parâmetro um padrão para especificar os nomes dos objetos a serem mostrados. O * significa “qualquer seqüência de caracteres” e ? significa “qualquer um único caractere” (Esta notação é semelhante a do padrão para nomes de arquivos do interpretador de comandos do Unix). Os usuários avançados também podem utilizar a notação das expressões regulares, como as classes de caracteres; por exemplo [0-9] correspondendo a “qualquer dígito”. Para fazer qualquer um desses caracteres de correspondência com padrão ser interpretado literalmente, deve-se colocá-lo entre aspas. Um padrão contendo um ponto (não entre aspas) é interpretado como um padrão de nome de esquema seguido por um padrão de nome de objeto. Por exemplo, \dt foo*.bar* mostra todas as tabelas nos esquemas cujos nomes começam por foo, e cujos nomes de tabela começam por bar. Se não houver nenhum ponto, então o padrão corresponde apenas aos objetos visíveis no caminho de procura de esquemas corrente. Por exemplo: (N. do T.) => \dt info*.*sizing* Lista de relações Esquema | Nome | Tipo | Dono --------------------+---------------------+--------+---------information_schema | sql_sizing | tabela | postgres information_schema | sql_sizing_profiles | tabela | postgres (2 linhas) => \dt 'info*.*sizing*' Lista de relações Esquema | Nome | Tipo | Dono --------------------+---------------------+--------+---------information_schema | sql_sizing | tabela | postgres information_schema | sql_sizing_profiles | tabela | postgres (2 linhas) => \dt "info*.*sizing*" Não foi encontrada nenhuma relação correspondendo.
Sempre que o parâmetro padrão é omitido, o comando \d mostra todos os objetos visíveis no caminho de procura de esquemas corrente. Para mostrar todos os objetos do banco de dados, deve ser usado o padrão *.*. Funcionalidades avançadas Variáveis O psql fornece uma funcionalidade de substituição de variáveis semelhante a dos interpretadores de comando do Unix. As variáveis são simplesmente pares nome/valor, onde o valor pode ser qualquer cadeia de caracteres de qualquer comprimento. Para definir as variáveis é utilizado o meta-comando do psql \set: testdb=> \set foo bar
define a variável foo com o valor bar. Para acessar o conteúdo da variável deve-se preceder seu nome por dois-pontos (:), e usá-lo como argumento de qualquer comando de contrabarra: testdb=> \echo :foo bar Nota: Os argumentos do \set estão sujeitos às mesmas regras de substituição de qualquer outro comando. Portanto, podem ser construídas referências interessantes como \set :foo 'something' e obter “soft links” ou “variable variables” do Perl e do PHP, respectivamente. Desafortunadamente (ou afortunadamente?), não existe nenhuma forma de fazer algo útil com estas construções. Por outro lado, \set bar :foo é uma forma perfeitamente válida de copiar uma variável.
Se \set for chamado sem o segundo argumento, a variável é definida com uma cadeia de caracteres vazia como valor. Para remover a definição (ou excluir) a variável, deve ser utilizado o comando \unset.
891
Os nomes das variáveis internas do psql podem ser formados por letras, números e sublinhados em qualquer ordem e número. Algumas destas variáveis recebem tratamento especial pelo psql. Denotam determinadas configurações de opção que podem ser mudadas em tempo de execução alterando o valor da variável, ou representam algum estado da aplicação. Embora seja possível usar estas variáveis para qualquer outra finalidade isto não é recomendado, porque o comportamento do programa pode ficar muito estranho, muito rapidamente. Por convenção, todas as variáveis com tratamento especial possuem todas as letras maiúsculas (e possivelmente números e sublinhados). Para garantir a máxima compatibilidade futura, evite usar estes nomes de variáveis para as suas próprias finalidades. Abaixo segue a lista de todas as variáveis com tratamento especial. AUTOCOMMIT
Quando está on (o padrão), cada comando SQL é automaticamente efetivado ao terminar bem-sucedido. Neste modo, para adiar a efetivação deve ser entrado um comando SQL BEGIN ou START TRANSACTION. Quando está off, ou não definido, os comandos SQL não são efetivados até ser emitido explicitamente o comando COMMIT ou END. O modo “autocommit-off” opera emitindo um comando BEGIN, implícito, logo antes de qualquer comando que não esteja dentro de um bloco de transação, e não seja o próprio BEGIN ou outro comando de controle de transação, nem um comando que não possa ser executado dentro de uma transação, (como o VACUUM). Nota: No modo “autocommit-off” toda transação que não for bem-sucedida deve ser explicitamente abandonada entrando com ABORT ou ROLLBACK. Também tenha em mente que, se a sessão for terminada sem a transação ser efetivada, o trabalho será perdido. Nota: O modo “autocommit-on” é o comportamento tradicional do PostgreSQL, mas o modo “autocommit-off” é mais próximo da especificação SQL. Se for preferido o modo “autocommit-off”, este pode ser definido no arquivo ~/.psqlrc do usuário.
O exemplo abaixo mostra o valor da variável AUTOCOMMIT: 5 => \echo :AUTOCOMMIT on DBNAME
O nome do banco de dados que se está conectado no momento. Definida toda vez que é feita a conexão com um banco de dados (inclusive na inicialização do programa), mas a definição pode ser removida. O exemplo abaixo mostra o valor da variável DBNAME: 6 => \echo :DBNAME template1 ECHO
Se for definida como “all”, todas as linhas entradas pelo teclado, ou do script, são escritas na saída padrão antes de serem analisadas ou executadas. Para selecionar este comportamento na inicialização do programa, deve ser usada a chave -a. Se for definida como “queries”, o psql simplesmente mostra todos os comandos à medida que são enviados para o servidor. A chave para isto é -e. ECHO_HIDDEN
Quando esta variável está definida, e um comando de contrabarra consulta o banco de dados, primeiro a consulta é mostrada. Por este meio pode-se estudar a parte interna do PostgreSQL e oferecer funcionalidades semelhantes nos próprios programas (Para selecionar este comportamento na inicialização do programa, deve ser usada a chave -E). Se a variável for definida com o valor “noexec” os comandos são apenas mostrados, não são enviados para o servidor para serem executados. O exemplo abaixo define a variável ECHO_HIDDEN e executa o meta-comando \dn: 7
892
=> \set ECHO_HIDDEN => \dn ********* QUERY ********** SELECT n.nspname AS "Nome", u.usename AS "Dono" FROM pg_catalog.pg_namespace n LEFT JOIN pg_catalog.pg_user u ON n.nspowner=u.usesysid ORDER BY 1; ************************** Lista de esquemas Nome | Dono --------------------+---------information_schema | postgres pg_catalog | postgres pg_temp_1 | postgres pg_toast | postgres public | postgres (5 linhas) ENCODING
A codificação corrente do conjunto de caracteres do cliente. O exemplo abaixo mostra o valor da variável ENCODING: 8 => \echo :ENCODING LATIN1 HISTCONTROL
Se esta variável estiver definida como “ignorespace”, as linhas começando por espaço não são guardadas na lista de histórico. Se estiver definida como “ignoredups”, as linhas idênticas à linha anterior do histórico não são guardadas. O valor “ignoreboth” combina estas duas opções. Se não estiver definida, ou se estiver definida com um valor diferente destes acima, todas as linhas lidas no modo interativo são guardadas na lista de histórico. Nota: Esta funcionalidade foi desavergonhadamente plagiada do Bash. HISTSIZE
O número de comandos a serem guardados no histórico de comandos. O valor padrão é 500. Nota: Esta funcionalidade foi desavergonhadamente plagiada do Bash. HOST
O hospedeiro do servidor de banco de dados ao qual se está conectado. Definida toda vez que se conecta com o banco de dados (inclusive na inicialização do programa), mas a definição pode ser removida. IGNOREEOF
Se não estiver definida, o envio do caractere EOF (geralmente Control+D) para uma sessão interativa do psql termina a aplicação. Se estiver definida com um valor numérico, é ignorada esta quantidade de caracteres EOF antes da aplicação terminar. Se a variável estiver definida, mas não tiver um valor numérico, o padrão é 10. Nota: Esta funcionalidade foi desavergonhadamente plagiada do Bash. LASTOID
O valor do último OID afetado, conforme retornado por um comando INSERT ou lo_insert. Somente há garantia desta variável ser válida até ser mostrado o resultado do próximo comando SQL.
893
ON_ERROR_STOP
Por padrão, se um script não-interativo encontrar algum erro, como um comando SQL ou um metacomando interno mal formado, o processamento continua. Este tem sido o comportamento tradicional do psql, mas algumas vezes não é o desejado. Se esta variável estiver definida, o processamento do script terminará imediatamente. Se o script foi chamado por outro script este terminará da mesma maneira. Se o script mais externo não foi chamado por uma sessão interativa do psql, mas usando a opção -f, o psql retorna o código de erro 3, para distinguir este caso das condições de erro fatal (código de erro 1). PORT
A porta do servidor de banco de dados que se está conectado. Definida toda vez que se conecta com o banco de dados (inclusive na inicialização do programa), mas a definição pode ser removida. PROMPT1 PROMPT2 PROMPT3
Especificam como os prompts emitidos pelo psql devem se parecer. Veja Prompt abaixo. QUIET
Esta variável equivale à opção de linha de comando -q. Provavelmente não tem muita utilidade no modo interativo. SINGLELINE
Esta variável equivale à opção de linha de comando -S. SINGLESTEP
Esta variável equivale à opção de linha de comando -s. USER
O usuário do banco de dados como o qual se está conectado. Definida toda vez que é feita a conexão com o banco de dados (inclusive na inicialização do programa), mas a definição pode ser removida. VERBOSITY
Esta variável pode ser definida com os valores default, verbose ou terse (sucinto), para controlar a verbosidade dos relatórios de erro. Interpolação SQL Uma funcionalidade adicional útil das variáveis do psql é poderem ser substituídas (“interpoladas”) dentro de comandos SQL regulares. Novamente a sintaxe é colocar dois-pontos (:) como prefixo do nome da variável. testdb=> \set foo 'minha_tabela' testdb=> SELECT * FROM :foo;
faria então a consulta à tabela minha_tabela. O valor da variável é copiado literalmente podendo, portanto, conter apóstrofos não balanceados ou comandos de contrabarra. Deve-se ter certeza que faz sentido onde é colocada. A interpolação de variáveis não é realizada dentro de entidades SQL entre aspas ou apóstrofos. Por exemplo: (N. do T.) testdb=> \set tabela 'pg_catalog.pg_user' testdb=> \echo :tabela pg_catalog.pg_user testdb=> \echo ':tabela' :tabela testdb=> \echo ":tabela" ":tabela" testdb=> SELECT usename FROM :tabela WHERE usesysid=1; usename ---------postgres (1 linha)
894
testdb=> SELECT usename FROM ':tabela' WHERE usesysid=1; ERRO: erro de sintaxe em ou próximo de "':tabela'" no caractere 21 testdb=> SELECT usename FROM ":tabela" WHERE usesysid=1; ERRO: a relação ":tabela" não existe
Uma aplicação comum desta funcionalidade é para fazer referência nos comandos subseqüentes ao último OID inserido, para construir um cenário de chave estrangeira. Outra utilização possível deste mecanismo é para copiar o conteúdo de um arquivo para uma coluna de uma tabela. Primeiro deve ser carregado o arquivo na variável, e depois proceder conforme mostrado. testdb=> \set conteudo '\'' `cat meu_arquivo.txt` '\'' testdb=> INSERT INTO minha_tabela VALUES (:conteudo);
Um problema possível com esta abordagem é que meu_arquivo.txt pode conter apóstrofos, que devem ser precedidos por contrabarra para não causarem erro de sintaxe quando a segunda linha for processada, o que pode ser feito por meio do programa sed: testdb=> \set conteudo '\'' `sed -e "s/'/\\\\\\'/g" < meu_arquivo.txt` '\''
Observe o número correto de contabarras (6)! Isto funciona da seguinte maneira: Após o psql ter analisado esta linha, enviará sed -e "s/'/\\\'/g" < meu_arquivo.txt para o interpretador de comandos, que fará suas próprias atividades dentro das aspas e executará o sed com os argumentos -e e s/'/\\'/g. Quando o sed fizer a análise substituirá as duas contrabarras por uma única e, então, fará a substituição. Talvez em algum ponto tenha se pensado ser ótimo todos os comandos Unix utilizarem o mesmo caractere de escape (escape character). Isto tudo ainda ignora o fato de ter que colocar contrabarra na frente de contrabarra também, porque as constantes textos do SQL também estão sujeitas a certas interpretações. Neste caso é melhor preparar o arquivo externamente. Uma vez que os dois-pontos podem aparecer legalmente nos comandos SQL, a seguinte regra se aplica: a seqüência de caracteres “:nome” não é modificada a menos que “nome” seja o nome de uma variável atualmente definida. Sempre pode ser feito o escape dos dois-pontos com uma contrabarra para protegê-lo da substituição (A sintaxe dos dois-pontos para as variáveis é padrão SQL para linguagens de comandos incorporados, tal como ECPG. A sintaxe de dois-pontos para “faixa de matriz” e “conversão de tipo” são extensões do PostgreSQL, daí o conflito). Prompt Os prompts emitidos pelo psql podem ser personalizados conforme a preferência. As três variáveis PROMPT1, PROMPT2 e PROMPT3 contêm cadeias de caracteres e seqüências especiais de escape que descrevem a aparência do prompt. O prompt 1 é o prompt normal emitido quando o psql solicita um novo comando. O prompt 2 é emitido durante a entrada do comando quando mais entrada é aguardada, porque o comando não foi terminado por um ponto-e-vírgula, ou um apóstrofo não foi fechado. O prompt 3 é emitido quando se executa o comando COPY do SQL e é esperado que os valores das linhas sejam digitados no terminal. O valor da variável de prompt selecionada é exibido literalmente, exceto quando um sinal de percentagem (%) é encontrado. Dependendo do caractere seguinte, certos outros textos são colocados em seu lugar. As substituições definidas são: %M
O nome completo do hospedeiro do servidor de banco de dados (com o nome do domínio), ou [local] se a conexão for através de um soquete do domínio Unix, ou [local:/dir/nome], se o soquete do domínio Unix não estiver no local padrão da compilação. %m
O nome, truncado no primeiro ponto, do hospedeiro do servidor de banco de dados, ou [local] se a conexão for através de um soquete do domínio Unix. %>
O número da porta na qual o servidor de banco de dados está ouvindo.
895
%n
O nome do usuário da sessão de banco de dados (A expansão deste valor pode mudar durante a sessão de banco de dados como resultado do comando SET SESSION AUTHORIZATION.) %/
O nome do banco de dados corrente. %~
Como %/, mas a saída será “~” (til) se o banco de dados for o banco de dados padrão. %#
Se o usuário da sessão for um superusuário do banco de dados então um #, senão > (A expansão deste valor pode mudar durante a sessão de banco de dados como resultado do comando SET SESSION AUTHORIZATION.) %R
No prompt 1 normalmente “=”, mas “^” se estiver no modo linha-única, e “!” se a sessão estiver desconectada do banco de dados (o que pode acontecer se \connect não for bem-sucedido). No prompt 2 a seqüência é substituída por “-”, “*”, apóstrofo, ou aspas, %x
Status da transação: uma cadeia de caracteres vazia quando não estiver dentro de um bloco de transação, ou * quando estiver dentro de um bloco de transação, ou ! quando estiver em um bloco de transação que falhou, ou ? quando o estado da transação for indeterminado (por exemplo, porque não há conexão). %dígitos
O caractere com o código numérico indicado é substituído. Se dígitos começar por 0x os demais caracteres são interpretados como hexadecimal; senão, se o primeiro dígito for 0, os dígitos são interpretados como octal; senão os dígitos são lidos como um número decimal. %:nome:
O valor da variável do psql nome. Veja a seção Variáveis para obter detalhes. %`comando`
A saída do comando, semelhante à substituição de “crase” normal. Para inserir um sinal de percentagem no prompt deve ser escrito %%. Os prompts padrão são '%/%R%# ' para os prompts 1 e 2, e '>> ' para o prompt 3. Nota: Esta funcionalidade foi desavergonhadamente plagiada do tcsh.
Edição da linha de comando O psql usa a biblioteca Readline para fornecer uma recuperação e edição de linha conveniente. O histórico dos comandos é armazenado no arquivo chamado .psql_history no diretório home do usuário, sendo recarregado quando o psql inicia. Completar com a tecla de tabulação também é suportado, embora a lógica do ato de completar não pretenda ser a de um analisador SQL. Se por algum motivo não se gostar de completar com tabulação, pode-se desativar especificando isto no arquivo chamado .inputrc no diretório home do usuário: $if psql set disable-completion on $endif
(Esta não é uma funcionalidade do psql, mas sim do Readline. Leia sua documentação para obter mais detalhes).
896
Ambiente HOME
Diretório do arquivo de inicialização (.psqlrc) e do arquivo de histórico dos comandos (.psql_history). PAGER
Se o resultado do comando não couber na tela, então é mostrado por meio deste comando. Os valores típicos são more e less. O padrão depende da plataforma. O uso de um paginador pode ser desabilitado por meio do comando \pset. PGDATABASE
Banco de dados padrão para conectar. PGHOST PGPORT PGUSER
Parâmetros padrão para conexão. PSQL_EDITOR EDITOR VISUAL
Editor utilizado pelo comando \e. As variáveis são examinadas na ordem listada; a primeira que estiver definida é utilizada. SHELL
Comando executado pelo meta-comando \!. TMPDIR
Diretório para armazenar os arquivos temporários. O padrão é /tmp.
Arquivos •
Antes de iniciar, o psql tenta ler e executar os comandos do arquivo $HOME/.psqlrc. Pode ser usado para configurar o cliente e o servidor conforme se deseje (usando os comandos \set e SET).
•
O histórico de linha de comando é armazenado no arquivo $HOME/.psql_history.
Observações •
Nas versões iniciais, o psql permitia o primeiro argumento de um comando de contrabarra de uma única letra começar logo após o comando, sem o espaço separador. Por motivo de compatibilidade isto ainda é suportado de alguma forma, que não será explicada em detalhes porque seu uso é desencorajado, mas se forem recebidas mensagens estranhas tenha isso em mente. Por exemplo testdb=> \foo Field separator is "oo".
talvez não seja o esperado. •
O psql somente trabalha adequadamente com servidores da mesma versão. Isto não significa que outras combinações vão falhar imediatamente, mas podem acontecer problemas sutis, e nem tão sutis. Os comandos de contrabarra são os mais propensos a não serem bem-sucedidos se o servidor for de uma versão diferente.
Exemplos O primeiro exemplo mostra como distribuir um comando por várias linhas de entrada. Observe a mudança do prompt:
897
testdb=> CREATE TABLE minha_tabela ( testdb(> first integer not null default 0, testdb(> second text testdb-> ); CREATE TABLE
Agora veja novamente a definição da tabela: testdb=> \d minha_tabela Table "minha_tabela" Attribute | Type | Modifier -----------+---------+-------------------first | integer | not null default 0 second | text |
Agora o prompt será mudado para algo mais interessante: testdb=> \set PROMPT1 '%n@%m %~%R%# ' peter@localhost testdb=>
Vamos assumir que a tabela já esteja com dados e queremos vê-los: peter@localhost testdb=> SELECT * FROM minha_tabela; first | second -------+-------1 | one 2 | two 3 | three 4 | four (4 linhas)
As tabelas podem ser mostradas de forma diferente usando o comando \pset: peter@localhost testdb=> Border style is 2. peter@localhost testdb=> +-------+--------+ | first | second | +-------+--------+ | 1 | one | | 2 | two | | 3 | three | | 4 | four | +-------+--------+ (4 linhas) peter@localhost testdb=> Border style is 0. peter@localhost testdb=>
\pset border 2 SELECT * FROM minha_tabela;
\pset border 0 SELECT * FROM minha_tabela;
first second ----- -----1 one 2 two 3 three 4 four (4 linhas) peter@localhost testdb=> \pset border 1 Border style is 1. peter@localhost testdb=> \pset format unaligned Output format is unaligned. peter@localhost testdb=> \pset fieldsep "," Field separator is ",".
898
peter@localhost testdb=> \pset tuples_only Showing only tuples. peter@localhost testdb=> SELECT second, first FROM minha_tabela; one,1 two,2 three,3 four,4
Como alternativa, podem ser usados os comandos curtos: peter@localhost testdb=> \a \t \x Output format is aligned. Tuples only is off. Expanded display is on. peter@localhost testdb=> SELECT * FROM minha_tabela; -[ RECORD 1 ]first | 1 second | one -[ RECORD 2 ]first | 2 second | two -[ RECORD 3 ]first | 3 second | three -[ RECORD 4 ]first | 4 second | four
Notas 1. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 2. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 3. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 4. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 5. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 6. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 7. Exemplo escrito pelo tradutor, não fazendo parte do manual original. 8. Exemplo escrito pelo tradutor, não fazendo parte do manual original.
899
vacuumdb Nome vacuumdb — limpa e analisa um banco de dados do PostgreSQL
Sinopse vacuumdb [opção_de_conexão...] [--full | -f] [--verbose | -v] [--analyze | -z] [--table | -t tabela [( coluna [,...] )] ] [nome_do_banco_de_dados] vacuumdb [opção_de_conexão...] [--all | -a] [--full | -f] [--verbose | -v] [--analyze | -z]
Descrição O vacuumdb é um utilitário para limpar um banco de dados do PostgreSQL. O vacuumdb também gera as estatísticas internas usadas pelo otimizador de comandos do PostgreSQL. O vacuumdb é uma capa em torno do comando VACUUM do SQL. Não existe diferença efetiva entre limpar o banco de dados através deste utilitário ou através de outros métodos para acessar o servidor.
Opções O vacuumdb aceita os seguintes argumentos de linha de comando: -a --all
Limpa todos bancos de dados. [-d] nome_do_banco_de_dados [--dbname] nome_do_banco_de_dados
Especifica o nome do banco de dados a ser limpo ou analisado. Se não for especificado, e a opção -a (ou --all) não for usada, o nome do banco de dados é obtido a partir da variável de ambiente PGDATABASE. Se esta variável não estiver definida, então é usado o nome do usuário especificado para a conexão. -e --echo
Mostra os comandos que o vacuumdb gera e envia para o servidor. -f --full
Executa a limpeza “completa”. -q --quiet
Não exibe resposta. -t tabela [ (coluna [,...]) ] --table tabela [ (coluna [,...]) ]
Limpa ou analisa somente a tabela. Os nomes das colunas só podem ser especificados juntamente com a opção --analyze. Dica: Se forem especificadas as colunas, provavelmente será necessário fazer o escape (\) dos parênteses para o interpretador de linhas de comando (Veja exemplos abaixo). -v --verbose
Mostra informações detalhadas durante o processamento.
900
-z --analyze
Calcula as estatísticas a serem utilizadas pelo otimizador. O vacuumdb também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão: -h hospedeiro --host hospedeiro
Especifica o nome de hospedeiro da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/) é usado como o diretório do soquete do domínio Unix. -p porta --port porta
Especifica a porta TCP, ou a extensão de arquivo do soquete do domínio Unix local, onde o servidor está ouvindo as conexões. -U nome_do_usuário --username nome_do_usuário
Nome do usuário para conectar. -W --password
Força a solicitação da senha.
Ambiente PGDATABASE PGHOST PGPORT PGUSER
Parâmetros de conexão padrão.
Diagnósticos Havendo dificuldade, veja no comando VACUUM e no psql a explicação dos problemas possíveis e as mensagens de erro. O servidor de banco de dados deve estar executando no hospedeiro de destino. Também se aplicam todas as definições de conexão padrão e as variáveis de ambiente utilizadas pela biblioteca cliente libpq.
Observações O vacuumdb pode precisar se conectar várias vezes ao servidor PostgreSQL, solicitando a senha cada uma destas vezes. Neste caso é conveniente existir o arquivo $HOME/.pgpass. Veja a Seção 27.11 para obter mais informações.
Exemplos Para limpar o banco de dados teste: $ vacuumdb teste
Para limpar e analisar para o otimizador o banco de dados chamado grande_bd: $ vacuumdb --analyze grande_bd
Para limpar uma única tabela chamada foo, no banco de dados chamado xyzzy, e analisar para o otimizador uma única coluna desta tabela chamada bar: $ vacuumdb --analyze --verbose --table 'foo(bar)' xyzzy
Veja também VACUUM
901
III. Aplicações do servidor PostgreSQL Esta parte contém informações de referência para as aplicações e utilitários de suporte do servidor PostgreSQL. Estes comandos só são úteis quando executados no computador onde o servidor de banco de dados está instalado. Outros programas utilitários estão listados em Referência II, Aplicações cliente do PostgreSQL.
902
initdb Nome initdb — cria um agrupamento de bancos de dados do PostgreSQL
Sinopse initdb [opção...] --pgdata | -D diretório
Descrição O utilitário initdb cria um agrupamento de bancos de dados do PostgreSQL. Um agrupamento de bancos de dados é uma coleção de bancos de dados gerenciados por uma única instância do servidor. Criar um agrupamento de banco de dados consiste em criar os diretórios onde os bancos de dados vão residir, gerar as tabelas do catálogo compartilhadas (tabelas que pertencem ao agrupamento como um todo, e não a um determinado banco de dados), e criar o banco de dados template1. Quando, mais tarde, for criado um banco de dado, tudo que existe no banco de dados template1 será copiado. Este banco de dados contém tabelas do catálogo contendo coisas como os tipos de dado nativos. O initdb inicializa a localização e a codificação do conjunto de caracteres padrão do agrupamento de banco de dados. Algumas categorias de localização são estabelecidas para toda a existência do agrupamento e, portanto, é importante fazer a escolha correta ao executar o initdb. Outras categorias de localização podem ser mudadas posteriormente ao inicializar o servidor. O initdb escreve estas definições de localização no arquivo de configuração postgresql.conf tornando-as padrão, mas podem ser mudadas editando este arquivo. Para definir a localização usada pelo initdb, veja a descrição da opção --locale. A codificação do conjunto de caracteres de cada banco de dados pode ser definida individualmente, no momento da criação do banco de dados. O initdb determina a codificação do banco de dados template1, que serve de padrão para todos os outros bancos de dados. Para alterar a codificação padrão deve ser usada a opção --encoding. O initdb deve ser executado pelo mesmo usuário que vai executar processo servidor, porque o servidor necessita ter acesso aos arquivos e diretórios criados pelo initdb. Como o servidor não deve ser executado pelo root, o initdb também não deve ser executado pelo root (Na verdade, se recusará a fazê-lo). Embora o initdb tente criar o diretório de dados especificado, provavelmente não terá permissão para fazêlo, porque geralmente o diretório de dados está sob um diretório que pertence ao root. Para resolver uma situação como esta deve-se: criar um diretório de dados vazio como root; usar o comando chown para tornar o usuário do banco de dados o dono deste diretório; executar su para se tornar o usuário do banco de dados; finalmente, executar o initdb como o usuário do banco de dados.
Opções -D diretório --pgdata=diretório
Esta opção especifica o diretório onde o agrupamento de banco de dados será armazenado. Esta é a única informação requerida pelo initdb, mas pode-se evitar escrevê-la definindo a variável de ambiente PGDATA, o que é conveniente porque, depois, o servidor de banco de dados (postmaster) poderá encontrar o diretório do bancos de dados usando esta mesma variável. -E codificação --encoding=codificação
Seleciona a codificação do banco de dados modelo. Também será a codificação padrão para todos os bancos de dados criados posteriormente, a não ser quando for especificada uma outra. O padrão é SQL_ASCII.
903
--locale=localização
Define a localização padrão para o agrupamento de banco de dados. Se esta opção não for especificada, a localização é herdada do ambiente onde o initdb está executando. --lc-collate=localização --lc-ctype=localização --lc-messages=localização --lc-monetary=localização --lc-numeric=localização --lc-time=localização
Como --locale, mas somente define a localização para a categoria especificada. -U nome_do_usuário --username=nome_do_usuário
Especifica o nome de usuário do superusuário do banco de dados. Por padrão o nome do usuário executando o initdb. Não importa realmente qual seja o nome do superusuário, mas é preferível manter o nome habitual postgres, mesmo que o nome do usuário do sistema operacional seja diferente. -W --pwprompt
Faz o initdb solicitar a senha a ser atribuída ao superusuário do banco de dados. Se não se pretende utilizar autenticação por senha, isto não tem importância. Senão, não será possível utilizar autenticação por senha enquanto não for atribuída uma senha. Também estão disponíveis outros parâmetros, menos utilizados: -d --debug
Mostra a saída de depuração do servidor de bootstrap, e algumas outras mensagens de menor interesse para o público em geral. O servidor de bootstrap é o programa que o initdb utiliza para criar as tabelas do catálogo. Esta opção gera uma quantidade imensa de saída extremamente entediante. -L diretório
Especifica onde o initdb deve encontrar os seus arquivos de entrada para inicializar o agrupamento de banco de dados. Será dito se é necessário especificar a localização explicitamente. -n --noclean
Por padrão, quando o initdb determina que um erro impediu a criação completa do agrupamento de bancos de dados, são removidos todos os arquivos criados antes de ser descoberto que não era possível terminar o trabalho. Esta opção impede a remoção e, portanto, é útil para a depuração.
Ambiente PGDATA
Especifica o diretório onde o agrupamento de bancos de dados deve ser armazenado; pode ser mudado usando a opção -D.
Veja também postgres, postmaster
904
initlocation Nome initlocation — cria uma área secundária de armazenamento de bancos de dados do PostgreSQL
Sinopse initlocation directory
Descrição A aplicação initlocation cria uma nova área secundária de armazenamento de bancos de dados do PostgreSQL. Veja em CREATE DATABASE a explicação sobre como gerenciar e usar áreas de armazenamento secundárias. Se o argumento não tiver uma barra (/), e não for um caminho válido, pressupõe-se ser uma variável de ambiente, a qual é referenciada. Veja os exemplos no final. Para poder usar este comando é necessário estar autenticado no sistema operacional (usando o comando su, por exemplo) como um superusuário do banco de dados.
Exemplos Para criar um banco de dados em um local alternativo, usando uma variável de ambiente: $ export PGDATA2=/opt/postgres/data
O postmaster deve ser parado e reiniciado para que este enxergue a variável de ambiente PGDATA2. O sistema deve ser configurado de forma que o postmaster enxergue PGDATA2 toda vez que iniciar. Por fim: $ initlocation PGDATA2 $ createdb -D PGDATA2 testdb
Como alternativa, se os caminhos absolutos estiverem permitidos pode ser feito: $ initlocation /opt/postgres/data $ createdb -D /opt/postgres/data/testdb testdb
905
ipcclean Nome ipcclean — remove a memória compartilhada e os semáforos de um servidor PostgreSQL que caiu
Sinopse ipcclean
Descrição O utilitário ipcclean remove todos os segmentos de memória compartilhada e os semáforos definidos, pertencentes ao usuário corrente. Sua finalidade é ser usado para fazer a limpeza após a queda do servidor PostgreSQL (postmaster). Observer que reiniciar o servidor imediatamente também limpa a memória compartilhada e os semáforos e, portanto, este utilitário possui pouca utilidade prática. Somente o administrador do banco de dados deve executar este utilitário, porque pode ocasionar um comportamento bizarro (por exemplo, quedas) se for executado durante uma sessão multiusuária. Se este utilitário for executado enquanto o servidor estiver executando, a memória compartilhada e os semáforos alocados pelo servidor são removidos, podendo ocasionar conseqüências graves para o servidor.
Observações Este script é um “hack”, mas nestes vários anos desde que foi escrito ninguém conseguiu desenvolver uma solução igualmente efetiva e portável. Como agora o postmaster pode se autolimpar, não é provável que o ipcclean seja melhorado no futuro. Este script faz suposições em relação ao formato da saída do utilitário ipcs, que podem não ser verdadeiras entre sistemas operacionais diferentes. Portanto, pode ser que não funcione no seu sistema operacional.
906
pg_controldata Nome pg_controldata — mostra informações de controle de um agrupamento de bancos de dados PostgreSQL
Sinopse pg_controldata [diretório_de_dados]
Descrição O utilitário pg_controldata mostra informações inicializadas durante a execução do initdb, tal como a versão do catálogo e a localização do servidor. Mostra, também, informações sobre a escrita prévia do registro no log (WAL) e o processamento dos pontos de controle (checkpoint). Estas informações são globais do agrupamento, e não específicas de um determinado banco de dados. Este utilitário pode ser executado apenas pelo usuário que inicializou o agrupamento, porque necessita de acesso de leitura para o diretório de dados. O diretório de dados pode ser especificado na linha de comando, ou pode ser usada a variável de ambiente PGDATA.
Ambiente PGDATA
Localização padrão do diretório de dados.
907
pg_ctl Nome pg_ctl — inicia, pára ou reinicia o servidor PostgreSQL
Sinopse pg_ctl start [-w] [-s] [-D diretório_de_dados] [-l nome_do_arquivo] [-o opções] [-p caminho] pg_ctl stop [-W] [-s] [-D diretório_de_dados] [-m s[mart] | f[ast] | i[mmediate] ] pg_ctl restart [-w] [-s] [-D diretório_de_dados] [-m s[mart] | f[ast] | i[mmediate] ] [-o opções] pg_ctl reload [-s] [-D diretório_de_dados] pg_ctl status [-D diretório_de_dados]
Descrição O pg_ctl é um utilitário para iniciar, parar ou reiniciar o servidor PostgreSQL (postmaster), ou mostrar o status de um servidor ativo. Embora o servidor possa ser iniciado manualmente, o pg_ctl encapsula tarefas como redirecionar a saída do log, desacoplar do terminal e do grupo de processos de forma adequada, além de fornecer opções convenientes para uma parada controlada. No modo iniciar (start), é lançado um novo servidor. O servidor é iniciado em segundo plano, e a entrada padrão é direcionada para /dev/null. A saída padrão e o erro padrão são ambos anexados ao arquivo de log (se a opção -l for usada), ou redirecionada para a saída padrão do pg_ctl (não o erro padrão). Se não for escolhido nenhum arquivo de log, a saída padrão do pg_ctl deve ser redirecionada para um arquivo, ou ser enviada para outro processo (através de um pipe) como, por exemplo, um programa de rotação de log, como o rotatelogs, senão o postmaster escreverá sua saída no terminal que o controla (do segundo plano), e não vai deixar o grupo de processos da shell. No modo parar (stop), o servidor que está executando no diretório de dados especificado é parado. Podem ser selecionados três métodos de parada diferentes pela opção -m: O modo “Smart” (inteligente) aguarda todos os clientes desconectarem. Este é o padrão. O modo “Fast” (rápido) não aguarda os clientes desconectarem. Todas as transações ativas são desfeitas (rollback), os clientes são desconectados à força e, em seguida, o servidor é parado. O modo “Immediate” (imediato) interrompe todos os processos servidores sem uma parada limpa, provocando um processamento de recuperação ao reiniciar. O modo reiniciar (restart) executa uma parada seguida por um início. Permite mudar as opções de linha de comando do postmaster. O modo recarregar (reload) simplesmente envia o sinal SIGHUP para o processo postmaster, fazendo este ler novamente os arquivos de configuração (postgresql.conf, pg_hba.conf, etc.). Permite mudar as opções do arquivo de configuração que não requerem um reinício completo para produzir efeito. O modo status verifica se o servidor está executando no diretório de dados especificado e, se estiver, mostra o PID e as opções de linha de comando usadas para chamá-lo.
Opções -D diretório_de_dados
Especifica a localização no sistema de arquivos dos arquivos de banco de dados. Se for omitido, é usada a variável de ambiente PGDATA. -l nome_do_arquivo
Anexa a saída do log do servidor ao nome_do_arquivo. Se o arquivo não existir é criado. A umask é definida como 077 e, portanto, o padrão é não permitir o acesso ao arquivo de log pelos outros usuários.
908
-m modo
Especifica o modo de parada (shutdown). O modo pode ser smart, fast ou immediate, ou a primeira letra de um desses três. -o opções
Especifica as opções a serem passadas diretamente para o comando postmaster. As opções são geralmente envoltas por apóstrofos (') ou aspas("), para garantir que sejam passadas como um grupo. -p caminho
Especifica a localização do arquivo executável postmaster. Por padrão o executável postmaster é lido do mesmo diretório do pg_ctl ou, caso não seja bem-sucedido, do diretório de instalação especificado. Não é necessário usar esta opção, a menos que esteja sendo feito algo diferente do usual e recebendo mensagem de erro informando que o executável do postmaster não foi encontrado. -s
Mostra somente os erros, sem mensagens informativas. -w
Aguarda o início ou a parada terminar. Expira em 60 segundos. Este é o padrão para a parada. Uma parada bem-sucedida é indicada pela remoção do arquivo do PID. Para o início, a execução do comando psql -l bem-sucedida indica sucesso. O pg_ctl tenta utilizar a porta apropriada para o psql. Se a variável de ambiente PGPORT existir, esta é usada. Senão, será visto se a porta está definida no arquivo postgresql.conf. Se nenhum destes dois for usado, será utilizada a porta padrão com a qual o PostgreSQL foi compilado (5432 por padrão). -W
Não aguarda o início ou a parada terminar. Este é o padrão para inícios e reinícios.
Ambiente PGDATA
Localização padrão do diretório de dados. PGPORT
Porta padrão para o psql (usada pela opção -w). Para os demais consulte o postmaster.
Arquivos postmaster.pid
A existência deste arquivo no diretório de dados é utilizada para ajudar o pg_ctl a determinar se o servidor está executando ou não. postmaster.opts.default
Se existir este arquivo no diretório de dados, o pg_ctl (no modo start) passa o conteúdo deste arquivo como opções para o comando postmaster, a menos que esteja substituído pela opção -o. postmaster.opts
Se existir este arquivo no diretório de dados, o pg_ctl (no modo restart) passa o conteúdo deste arquivo como opções para o comando postmaster, a menos que esteja substituído pela opção -o. O conteúdo deste arquivo também é mostrado no modo status. postgresql.conf
Este arquivo, localizado no diretório de dados, é analisado para descobrir a porta apropriada a ser utilizada pelo psql quando a opção -w é usada no modo start.
909
Observações Aguardar o término do início não é uma operação bem definida, podendo não ser bem-sucedida se o controle de acesso for configurado de modo que o cliente local não possa se conectar sem intervenção manual (por exemplo, autenticação por senha).
Exemplos Iniciar o servidor Para iniciar o servidor: $ pg_ctl start
Exemplo de iniciar o servidor bloqueando até o servidor estar pronto: $ pg_ctl -w start
Para um servidor usando a porta 5433, e executando sem fsync, deve ser usado: $ pg_ctl -o "-F -p 5433" start
Parar o servidor $ pg_ctl stop
pára o servidor. A chave -m permite controlar como o servidor irá parar. Reiniciar o servidor Reiniciar o servidor praticamente equivale a parar o servidor e iniciá-lo novamente, exceto que o pg_ctl salva e reutiliza as opções de linha de comando passadas para a instância executando anteriormente. Para reiniciar o servidor da forma mais simples possível: $ pg_ctl restart
Para reiniciar o servidor aguardando o término da parada e da inicialização: $ pg_ctl -w restart
Para reiniciar usando a porta 5433 e desabilitando o fsync após o reinício: $ pg_ctl -o "-F -p 5433" restart
Mostrar o status do servidor Abaixo segue um exemplo da saída de status mostrada pelo pg_ctl no Fedora Core 3: $ su - postgres $ pg_ctl status pg_ctl: postmaster is running (PID: 4607) Command line was: /usr/bin/postmaster '-p' '5432' '-D' '/var/lib/pgsql/data'
Esta é a linha de comandos que seria usada no modo de reinício.
Veja também postmaster
910
pg_resetxlog Nome pg_resetxlog — redefine o conteúdo do log de escrita prévia e outras informações de controle de um agrupamento de bancos de dados do PostgreSQL
Sinopse pg_resetxlog [ -f ] [ -n ] [ -o oid ] [ -x xid ] [ -l fileid,seg ] diretório_de_dados
Descrição O utilitário pg_resetxlog limpa o log de escrita prévia (WAL) e, opcionalmente, redefine algumas outras informações de controle (armazenadas no arquivo pg_control). Algumas vezes esta função é necessária quando estes arquivos ficam corrompidos. Deve ser utilizada apenas como último recurso, quando o servidor não iniciar por causa da corrupção destes arquivos. Após executar este comando deve ser possível iniciar o servidor, mas deve-se ter em mente que o banco de dados pode conter dados inconsistentes devido à presença de transações parcialmente efetivadas. Deve ser feita, imediatamente, uma cópia de segurança dos dados, executar o initdb e recarregar os dados. Após a recarga as inconsistências devem ser verificadas e corrigidas conforme necessário. Este utilitário pode ser executado apenas pelo usuário que instalou o servidor, porque requer acesso de leitura/gravação no diretório de dados. Por motivo de segurança, o diretório de dados deve ser especificado na linha de comando. O pg_resetxlog não utiliza a variável de ambiente PGDATA. Se o pg_resetxlog informar que não está conseguindo determinar os dados válidos para pg_control, pode ser forçado a prosseguir assim mesmo especificando a chave -f (forçar). Neste caso, são utilizados valores plausíveis para os dados que estão faltando. Pode-se esperar que a maioria dos campos correspondam, mas pode ser necessário auxílio manual para os campos próximo OID, próximo ID de transação, endereço inicial do WAL e localização do banco de dados. Os três primeiros podem ser definidos usando as chaves discutidas abaixo. O próprio ambiente do pg_resetxlog é a fonte para os campos de localização; deve-se cuidar para que LANG e as demais variáveis de ambiente análogas correspondam ao ambiente em que o initdb foi executado. Se não for possível determinar o valor correto para todos estes campos o -f ainda pode ser usado, mas o banco de dados recuperado deve ser tratado como ainda mais suspeito que o usual: uma imediata cópia de segurança e sua recarga é imperativa. Não deve ser executada nenhuma operação que modifique os dados do banco de dados antes de ser feita a cópia de segurança, porque uma atividade deste tipo pode piorar ainda mais a situação. As chaves -o, -x e -l permitem definir manualmente o próximo OID, o próximo ID de transação e o endereço inicial do WAL. Somente são necessários quando pg_resetxlog não for capaz de determinar os valores apropriados por meio da leitura do arquivo pg_control. Um valor seguro para o identificador da próxima transação pode ser determinado verificando o nome de arquivo com o maior valor numérico no diretório /pg_clog sob o diretório de dados, somando um, e depois multiplicando por 1.048.576. Observe que os nomes dos arquivos estão em hexadecimal. Normalmente é mais fácil especificar o valor da chave em hexadecimal também. Por exemplo, se 0011 for a maior entrada em pg_clog, então -x 0x1200000 servirá (cinco zeros à direita fornecem o multiplicador apropriado). O endereço inicial do WAL deve ser maior do que qualquer nome de arquivo existente no diretório /pg_xlog sob o diretório de dados. Estes nomes também estão em hexadecimal, e possuem duas partes. Por exemplo, se 000000FF0000003A for a maior entrada em pg_xlog, então -l 0xFF,0x3B servirá. Não existe nenhuma forma mais fácil para determinar o próximo OID acima do maior existente no banco de dados, mas por sorte não é crítico definir o próximo OID corretamente. A chave -n (nenhuma operação) faz o pg_resetxlog mostrar os valores reconstruídos a partir de pg_control e terminar em seguida, sem modificar nada. Isto é principalmente uma ferramenta de depuração, mas pode ser útil para fazer uma verificação antes de permitir que a aplicação pg_resetxlog realmente efetue a operação.
911
Observações Este comando não deve ser usado quando o servidor estiver executando. O pg_resetxlog se recusa a iniciar quando encontra o arquivo de bloqueio do servidor no diretório de dados. Se o servidor caiu, então o arquivo de bloqueio pode ter sido deixado no diretório; neste caso, o arquivo de bloqueio deve ser removido para permitir o pg_resetxlog executar, mas antes de remover deve-se ter certeza que nem o postmaster, nem nenhum processo servidor, ainda está executando.
912
postgres Nome postgres — executa o servidor PostgreSQL no modo monousuário
Sinopse postgres [-A 0 | 1 ] [-B número_de_buffers] [-c nome=valor] [-d nível_de_depuração] [--describe-config] [-D diretório_de_dados] [-e] [-E] [-f s | i | t | n | m | h ] [-F] [-N] [-o nome_do_arquivo] [-O] [-P] [-s | -t pa | pl | ex ] [-S memória_de_trabalho] [-W segundos] [--nome=valor] nome_do_banco_de_dados postgres [-A 0 | 1 ] [-B número_de_buffers] [-c nome=valor] [-d nível_de_depuração] [-D diretório_de_dados] [-e] [-f s | i | t | n | m | h ] [-F] [-o nome_do_arquivo] [-O] [-p nome_do_banco_de_dados] [-P] [-s | -t pa | pl | ex ] [-S memória_de_trabalho] [-v protocolo] [-W segundos] [--nome=valor]
Descrição O executável postgres é o verdadeiro processo servidor PostgreSQL que processa os comandos. Normalmente não é chamado diretamente; em vez deste é iniciado o servidor multiusuário postmaster. A segunda forma acima é como o postgres é chamado pelo postmaster (somente conceitualmente, porque o postmaster e o postgres são, na verdade, o mesmo programa); não deve ser chamado diretamente desta maneira. A primeira forma chama o servidor diretamente no modo monousuário interativo. A principal utilização deste modo é durante a inicialização pelo initdb. Algumas vezes é utilizada para depuração ou para recuperação de desastre. Quando chamado no modo interativo a partir da linha de comando, o usuário pode entrar com comandos e os resultados são mostrados na tela, mas de uma forma que é mais útil para os desenvolvedores do que para os usuários finais. Deve-se notar que executar o servidor em modo monousuário não é inteiramente adequado para a depuração do servidor, uma vez que não acontecerá nenhuma comunicação entre processos e bloqueio de fato. Ao executar o servidor autônomo, o usuário da sessão será definido como o usuário com o identificador 1. Não há necessidade deste usuário existir e, portanto, o servidor autônomo pode ser usado para recuperar manualmente certos tipos de dano acidentais dos catálogos do sistema. Poderes implícitos de superusuário são concedidos ao usuário com identificador igual a 1 no modo autônomo.
Opções Quando o postgres é iniciado pelo postmaster, herda todas as opções definidas por este. Além disso, opções específicas do postgres podem ser passadas pelo postmaster usando a chave -o. Pode-se evitar a digitação destas opções definindo um arquivo de configuração. Veja a Seção 16.4 para obter detalhes. Algumas opções (seguras) também podem ser definidas, por um modo dependente da aplicação, pelo cliente se conectando. Por exemplo, se a variável de ambiente PGOPTIONS estiver definida, então os clientes baseados na libpq passam esta cadeia de caracteres para o servidor, que irá interpretá-la como opções de linha de comando do postgres. Finalidade geral As opções -A, -B, -c, -d, -D, -F e --nome possuem o mesmo significado que no postmaster, exceto que -d 0 impede o nível de log do postmaster ser propagado para o postgres.
913
-e
Define, para os campos de entrada de data, o estilo padrão da data como “European”, que é a ordem DMY. Também faz o dia vir antes do mês em certos formatos de saída de data. Veja a Seção 8.5 para obter mais informações. -o nome_do_arquivo
Envia toda saída do log do servidor para nome_do_arquivo. Se o postgres estiver executando sob o postmaster esta opção será ignorada, e a stderr herdada do postmaster será utilizada. -P
Ignora os índices do sistema ao ler as tabelas do sistema (mas continua atualizando os índices ao modificar as tabelas). É útil ao se fazer a recuperação por causa de índices do sistema corrompidos. -s
Mostra a informação de tempo, e outras estatísticas, ao final de cada comando. Útil para avaliações ou para definir o número de buffers. -S memória_de_trabalho
Especifica a quantidade de memória a ser usada pelas ordenações e hashes internos, antes de recorrer a arquivos temporários em disco. O valor é especificado em kilobytes, sendo o padrão 1024. Observe que para uma consulta complexa, diversas ordenações e/ou hashes podem ser executadas em paralelo, podendo cada uma utilizar a quantidade de memória_de_trabalho kilobytes antes de começar a escrever os dados em arquivos temporários. Opções para o modo autônomo nome_do_banco_de_dados Especifica o nome do banco de dados a ser acessado. Se for omitido o padrão é o nome do usuário. -E
Mostra todos os comandos. -N
Desabilita o uso do caractere de nova-linha como delimitador do comando. Opções semi-internas Existem várias outras opções que podem ser especificadas, usadas principalmente para fins de depuração, mostradas apenas para uso pelos desenvolvedores de sistema do PostgreSQL. A utilização de qualquer uma destas opções é altamente desaconselhada. Além disso, qualquer uma destas opções poderá mudar ou desaparecer em uma versão futura sem nenhum aviso. -f { s | i | m | n | h }
Proíbe o uso de um determinado método de varredura ou de junção: s e i desabilitam a varredura seqüencial e de índice, respectivamente, enquanto n, m e h desabilitam as junções de laço-aninhado, mesclagem e hash, respectivamente. Nota: Nem as varreduras seqüenciais nem as junções de laço aninhado podem ser desabilitadas completamente; as opções -fs e -fn simplesmente desencorajam o uso pelo otimizador de planos deste tipo, se houver alguma outra alternativa. -O
Permite modificar a estrutura das tabelas do sistema. Usada pelo initdb. -p nome_do_banco_de_dados
Indica que este processo foi iniciado pelo postmaster e especifica o banco de dados a ser utilizado, etc. -t pa[rser] | pl[anner] | e[xecutor]
Mostra estatísticas de tempo para cada comando, relacionando com cada um dos principais módulos do sistema. Esta opção não pode ser usada junto com a opção -s.
914
-v protocolo
Especifica o número da versão do protocolo cliente/servidor a ser usado por esta sessão. -W segundos
Tão logo esta opção seja encontrada, o processo adormece pela quantidade especificada de segundos, dando ao desenvolvedor tempo para anexar o depurador ao processo servidor. --describe-config
Esta opção mostra as variáveis de configuração internas do servidor, descrições e padrões, em um formato delimitado por tabulação do COPY. Foi projetado para ser utilizado principalmente por ferramentas de administração.
Ambiente PGDATA
Localização padrão do diretório de dados. Para as outras variáveis de ambiente, com pouca influência durante o modo monousuário, veja o postmaster.
Observações Para cancelar a execução de um comando, deve ser enviado o sinal SIGINT para o processo postgres executando este comando. Para fazer o postgres recarregar os arquivos de configuração, deve ser enviado o sinal SIGHUP. Normalmente é melhor enviar o sinal SIGHUP para o postmaster que, por sua vez, enviará o sinal SIGHUP para cada um de seus descendentes. Mas em alguns casos pode ser desejado que apenas um processo postgres recarregue os arquivos de configuração. O postmaster utiliza SIGTERM para comunicar a um processo postgres que termine normalmente, e SIGQUIT para que termine sem a limpeza normal. Estes sinais não devem ser utilizados pelos usuários. Também não é aconselhável enviar um SIGKILL para um processo postgres — o postmaster vai interpretar como sendo uma queda do postgres, e vai forçar todos os processos postgres descendentes terminarem como parte de seu procedimento padrão de recuperação de quedas.
Utilização Inicie o servidor autônomo com um comando do tipo: postgres -D /usr/local/pgsql/data outras_opções meu_banco_de_dados
Forneça o caminho correto para o diretório do banco de dados com -D, ou garanta que a variável de ambiente PGDATA esteja definida. Também especifique o nome do banco de dados em que deseja trabalhar. Normalmente, o servidor autônomo trata o caractere de nova-linha como fim da entrada do comando; não existe inteligência sobre ponto-e-vírgula, como existe no psql. Para continuar o comando por várias linhas, deve ser digitado uma contrabarra (\) logo antes de cada nova-linha, exceto a última. Mas se for usada a chave de linha de comando -N, o caractere de nova-linha não termina a entrada do comando. Neste caso, o servidor lê a entrada padrão até a marca de fim-de-arquivo (EOF) e, então, processa a entrada como sendo a cadeia de caracteres de um único comando. A seqüência contrabarra nova-linha não recebe tratamento especial neste caso. Para sair da sessão tecle EOF (Control+D, geralmente). Se for utilizado -N, serão necessários dois EOF consecutivos para sair. Observe que o servidor autônomo não oferece funcionalidades sofisticadas para edição de linha (não existe o histórico dos comandos, por exemplo).
Veja também initdb, ipcclean, postmaster
915
postmaster Nome postmaster — servidor de banco de dados multiusuário do PostgreSQL
Sinopse postmaster [-A 0 | 1 ] [-B num_buffers] [-c nome=valor] [-d nível_de_depuração] [-D diretório_de_dados] [-F] [-h nome_de_hospedeiro] [-i] [-k diretório] [-l] [-N número_máximo_de_conexões] [-o opções_extras] [-p porta] [-S] [--nome=valor] [-n | -s]
Descrição O postmaster é o servidor de banco de dados multiusuário PostgreSQL. Para uma aplicação cliente acessar um banco de dados deve se conectar (através de uma rede ou localmente) ao postmaster. O postmaster, então, inicia um processo servidor separado (“postgres”) para tratar a conexão. O postmaster também gerencia a comunicação entre os processos servidor. Por padrão, o postmaster inicia em primeiro plano (foreground) e envia as mensagens de log para a saída de erro padrão. Para uso prático o postmaster deve ser iniciado como um processo em segundo plano (background), provavelmente durante a inicialização do sistema operacional. Um postmaster gerencia sempre os dados de, precisamente, um agrupamento de bancos de dados. Um agrupamento de bancos de dados é uma coleção de bancos de dados armazenados em um local comum no sistema de arquivos. Ao iniciar, o postmaster precisa conhecer o local onde estão os arquivos do agrupamento de bancos de dados (“área de dados”), o que é feito por meio da opção de chamada -D, ou por meio da variável de ambiente PGDATA; não existe nenhum valor padrão. Mais de um processo postmaster pode estar executando no sistema operacional ao mesmo tempo, desde que utilizem áreas de dados diferentes e portas de comunicação diferentes (veja abaixo). A área de dados é criada pelo initdb.
Opções O postmaster aceita os argumentos de linha de comando mostrados abaixo. Consulte a Seção 16.4 para obter uma explicação detalhada destas opções. É possível evitar a digitação da maior parte destas opções usando o arquivo de configuração. -A 0|1
Habilita a verificação das asserções 1 em tempo de execução, o que é uma ajuda de depuração para detectar erros de programação. Só está disponível quando habilitada durante a compilação do PostgreSQL. Se for, o padrão é ativa. -B número_de_buffers
Define o número de buffers compartilhados para uso pelos processos servidor. Por padrão 64 buffers, cada um de 8 kB. -c nome=valor
Define o parâmetro em tempo de execução designado. Os parâmetros de configuração suportados pelo PostgreSQL estão descritos na Seção 16.4. A maior parte das outras opções de linha de comando são, na verdade, formas curtas de atribuição destes parâmetros. A opção -c pode aparecer várias vezes para definir vários parâmetros. -d nível_de_depuração
Define o nível de depuração. Quanto mais alto for definido este valor, mais saída de depuração será escrita no log do servidor. Os valores vão de 1 a 5.
916
-D diretório_de_dados
Especifica a localização do diretório de dados e dos arquivos de configuração no sistema de arquivos. Veja a explicação acima. -F
Desabilita as chamadas a fsync para melhorar o desempenho, correndo o risco de corrupção dos dados na ocorrência de uma falha do sistema. Este parâmetro corresponde a definir fsync=false no arquivo postgresql.conf. Leia com atenção a documentação antes de usar esta opção! --fsync=true produz o efeito oposto desta opção. -h nome_de_hospedeiro
Especifica o nome de hospedeiro ou endereço de IP no qual o postmaster ouve as conexões das aplicações cliente. Por padrão ouve em todos os endereços configurados (incluindo localhost). -i
Permite os clientes remotos se conectarem via TCP/IP (Domínio da Internet). Sem esta opção, somente as conexões via soquete do domínio Unix local são aceitas. Esta opção corresponde a definir tcpip_socket=true no arquivo postgresql.conf. --tcpip_socket=false produz o efeito oposto desta opção. -k diretório
Especifica o diretório do soquete do domínio Unix, no qual o postmaster está ouvindo as conexões das aplicações cliente. Normalmente o padrão é /tmp, mas pode ser mudado na compilação. -l
Habilita as conexões seguras usando SSL. A opção -i também é requerida. O PostgreSQL deve ter sido compilado com suporte a SSL para ser possível o uso desta opção. -N número_máximo_de_conexões
Define o número máximo de conexões de clientes aceitas por este postmaster. Por padrão este valor é 32, mas pode ser definido tão alto quanto o sistema operacional suportar (Observe que o valor da opção -B deve ser pelo menos o dobro do valor da opção -N. Veja na Seção 16.5 a explicação sobre os requisitos de recursos do sistema necessários para a conexão de um grande número de clientes). -o opções_extras
As opções no estilo linha de comando especificadas nas opções_extras são passadas para todos os processos servidor iniciados por este postmaster. Consulte o postgres para ver as possibilidades. Se a cadeia de caracteres contendo a opção contiver espaços, toda a cadeia de caracteres deve vir entre apóstrofos ('). -p porta
Especifica a porta TCP/IP, ou a extensão do arquivo de soquete do domínio Unix local, onde o postmaster está ouvindo as conexões das aplicações cliente. Por padrão o valor da variável de ambiente PGPORT ou, se PGPORT não estiver definida, o valor estabelecido durante a compilação (normalmente 5432). Se for especificada uma porta diferente da porta padrão, então todas as aplicações cliente devem especificar a mesma porta usando a opção de linha de comando ou a variável de ambiente PGPORT. -S
Especifica que o processo postmaster deve iniciar no modo silencioso, ou seja, será dissociado do terminal (controlador) do usuário, iniciará seu próprio grupo de processos e redirecionará sua saída padrão e erro padrão para /dev/null. O uso desta chave descarta toda a saída para o log, o que provavelmente não é o desejado, porque torna muito difícil a solução dos problemas. Veja abaixo uma maneira melhor de iniciar o postmaster em segundo plano. --silent_mode=false produz o efeito oposto desta opção.
917
--nome=valor
Define o parâmetro em tempo de execução designado; uma forma mais curta da opção -c. Estão disponíveis duas opções de linha de comando adicionais para a depuração dos problemas que fazem o servidor terminar anormalmente. A estratégia comum nesta situação é notificar todos os outros processos servidor que estes devem terminar e, em seguida, reinicializar a memória compartilhada e os semáforos. Isto é porque o processo servidor com problema pode ter corrompido algum estado compartilhado antes de terminar. Estas opções selecionam comportamentos alternativos do postmaster nesta situação. Nenhuma destas opções foi feita para ser usada durante a operação normal. As opções caso-especial são: -n
O postmaster não reinicializa as estruturas de dado compartilhadas. Um programador de sistemas com conhecimento adequado poderá, então, usar um depurador para examinar a memória compartilhada e o estado do semáforo. -s
O postmaster pára todos os outros processos servidor enviando o sinal SIGSTOP, mas não faz com que terminem, permitindo os programadores de sistema coletar “core dumps” de todos os processos servidor manualmente.
Ambiente PGCLIENTENCODING
A codificação de caracteres padrão utilizada pelos clientes (Os clientes podem substitui-la individualmente). Este valor também pode ser definido no arquivo de configuração. PGDATA
Localização padrão do diretório de dados. PGDATESTYLE
Valor padrão do parâmetro em tempo de execução DATESTYLE (A utilização desta variável de ambiente está obsoleta). PGPORT
Porta padrão (definida de preferência no arquivo de configuração). TZ
Zona horária do servidor. outras Outras variáveis de ambiente podem ser usadas para designar locais alternativos para armazenamento dos dados. Veja a Seção 18.5 para obter mais informações.
Diagnósticos Uma mensagem de erro mencionando semget ou shmget provavelmente indica a necessidade de configurar o núcleo (kernel) para fornecer uma quantidade de memória compartilhada e semáforos adequados. Para obter mais explicações veja a Seção 16.5. Dica: Pode ser possível adiar a reconfiguração do núcleo diminuindo shared_buffers, para reduzir o consumo de memória compartilhada do PostgreSQL, e/ou reduzindo max_connections, para reduzir o consumo de semáforos.
Uma mensagem de erro sugerindo que um outro postmaster está executando deve ser verificada cuidadosamente utilizando, por exemplo, o comando
918
$ ps ax | grep postmaster
ou $ ps -ef | grep postmaster
dependendo do sistema operacional. Havendo certeza de que não há outro postmaster conflitante executando, deve ser removido o arquivo de bloqueio mencionado na mensagem e tentado novamente. Uma mensagem de erro indicando não ser possível vincular a porta, pode indicar que a porta já esteja em uso por um processo não-PostgreSQL. Este erro também pode acontecer se o postmaster for terminado e reiniciado imediatamente usando a mesma porta; neste caso, se deve simplesmente aguardar uns poucos segundos o sistema operacional fechar a porta antes de tentar novamente. Por fim, este erro pode acontecer se for especificado um número de porta que o sistema operacional considere reservado. Por exemplo, muitas versões do Unix consideram os números de porta abaixo de 1024 como “trusted” (confiável) só permitindo o acesso aos superusuários do Unix.
Observações Sempre que for possível não deve ser usado SIGKILL para terminar o postmaster. Este sinal impede que o postmaster libere os recursos do sistema utilizados (por exemplo, memória compartilhada e semáforos) antes de terminar, podendo causar problemas ao iniciar uma nova execução do postmaster. Para terminar o postmaster normalmente, podem ser usados os sinais SIGTERM, SIGINT e SIGQUIT. O primeiro aguarda todos os clientes terminarem antes de fechar, o segundo força a desconexão de todos os clientes e o terceiro fecha imediatamente sem um shutdown adequado, provocando a execução da recuperação ao reiniciar. O sinal SIGHUP recarrega os arquivos de configuração do servidor. O utilitário pg_ctl pode ser usado para iniciar e terminar o postmaster com segurança e conforto. As opções -- não funcionam no FreeBSD nem no OpenBSD. Use o -c em seu lugar. Esta é uma falha destes sistemas operacionais; uma versão futura do PostgreSQL disponibilizará um recurso para contornar este problema, caso não seja corrigido.
Exemplos Para iniciar o postmaster em segundo plano usando os valores padrão: $ nohup postmaster >logfile 2>&1
Para iniciar o postmaster usando uma porta específica: $ postmaster -p 1234
Este comando inicia o postmaster se comunicando através da porta 1234. Para se conectar a este postmaster usando o psql, deve-se executar: $ psql -p 1234
ou definir a variável de ambiente PGPORT: $ export PGPORT=1234 $ psql
Parâmetros em tempo de execução identificados pelo nome podem ser definidos usando um destes estilos: $ postmaster -c sort_mem=1234 $ postmaster --sort-mem=1234
As duas formas substituem o que estiver definido para SORT_MEM no arquivo postgresql.conf. Observe que os sublinhados nos nomes dos parâmetros podem ser escritos com o caractere sublinhado ou hífen na linha de comando. Dica: Exceto para experimentos de curta duração, provavelmente é uma prática melhor editar as definições no arquivo postgresql.conf do que depender das chaves de linha de comando para definir os parâmetros.
919
Veja também initdb, pg_ctl
Notas 1. asserção — do Lat. assertione — proposição que se apresenta como verdadeira. PRIBERAM - Língua Portuguesa On-Line (http://www.priberam.pt/dlpo/dlpo.aspx). (N. do T.)
920
VII. Internals Contém informações variadas que podem ser úteis para os desenvolvedores do PostgreSQL.
921
Capítulo 42. Overview of PostgreSQL Internals Author: This chapter originated as part of Enhancement of the ANSI SQL Implementation of PostgreSQL, Stefan Simkovics' Master's Thesis prepared at Vienna University of Technology under the direction of O.Univ.Prof.Dr. Georg Gottlob and Univ.Ass. Mag. Katrin Seyr.
This chapter gives an overview of the internal structure of the backend of PostgreSQL. After having read the following sections you should have an idea of how a query is processed. This chapter does not aim to provide a detailed description of the internal operation of PostgreSQL, as such a document would be very extensive. Rather, this chapter is intended to help the reader understand the general sequence of operations that occur within the backend from the point at which a query is received, to the point at which the results are returned to the client.
42.1. The Path of a Query Here we give a short overview of the stages a query has to pass in order to obtain a result. 1.
A connection from an application program to the PostgreSQL server has to be established. The application program transmits a query to the server and waits to receive the results sent back by the server.
2.
The parser stage checks the query transmitted by the application program for correct syntax and creates a query tree.
3.
The rewrite system takes the query tree created by the parser stage and looks for any rules (stored in the system catalogs) to apply to the query tree. It performs the transformations given in the rule bodies. One application of the rewrite system is in the realization of views. Whenever a query against a view (i.e. a virtual table) is made, the rewrite system rewrites the user's query to a query that accesses the base tables given in the view definition instead.
4.
The planner/optimizer takes the (rewritten) query tree and creates a query plan that will be the input to the executor. It does so by first creating all possible paths leading to the same result. For example if there is an index on a relation to be scanned, there are two paths for the scan. One possibility is a simple sequential scan and the other possibility is to use the index. Next the cost for the execution of each plan is estimated and the cheapest plan is chosen and handed back.
5.
The executor recursively steps through the plan tree and retrieves rows in the way represented by the plan. The executor makes use of the storage system while scanning relations, performs sorts and joins, evaluates qualifications and finally hands back the rows derived.
In the following sections we will cover each of the above listed items in more detail to give a better understanding of PostgreSQL's internal control and data structures.
42.2. How Connections are Established PostgreSQL is implemented using a simple “process per user” client/server model. In this model there is one client process connected to exactly one server process. As we do not know ahead of time how many connections will be made, we have to use a master process that spawns a new server process every time a connection is requested. This master process is called postmaster and listens at a specified TCP/IP port for incoming connections. Whenever a request for a connection is detected the postmaster process spawns a new server process called postgres. The server tasks (postgres processes) communicate with each other using semaphores and shared memory to ensure data integrity throughout concurrent data access. The client process can be any program that understands the PostgreSQL protocol described in Capítulo 44. Many clients are based on the C-language library libpq, but several independent implementations exist, such as the Java JDBC driver.
922
Once a connection is established the client process can send a query to the backend (server). The query is transmitted using plain text, i.e. there is no parsing done in the frontend (client). The server parses the query, creates an execution plan, executes the plan and returns the retrieved rows to the client by transmitting them over the established connection.
42.3. The Parser Stage The parser stage consists of two parts: •
The parser defined in gram.y and scan.l is built using the Unix tools yacc and lex.
•
The transformation process does modifications and augmentations to the data structures returned by the parser.
42.3.1. Parser The parser has to check the query string (which arrives as plain ASCII text) for valid syntax. If the syntax is correct a parse tree is built up and handed back; otherwise an error is returned. The parser and lexer are implemented using the well-known Unix tools yacc and lex. The lexer is defined in the file scan.l and is responsible for recognizing identifiers, the SQL key words etc. For every key word or identifier that is found, a token is generated and handed to the parser. The parser is defined in the file gram.y and consists of a set of grammar rules and actions that are executed whenever a rule is fired. The code of the actions (which is actually C code) is used to build up the parse tree. The file scan.l is transformed to the C source file scan.c using the program lex and gram.y is transformed to gram.c using yacc. After these transformations have taken place a normal C compiler can be used to create the parser. Never make any changes to the generated C files as they will be overwritten the next time lex or yacc is called. Nota: The mentioned transformations and compilations are normally done automatically using the makefiles shipped with the PostgreSQL source distribution.
A detailed description of yacc or the grammar rules given in gram.y would be beyond the scope of this paper. There are many books and documents dealing with lex and yacc. You should be familiar with yacc before you start to study the grammar given in gram.y otherwise you won't understand what happens there.
42.3.2. Transformation Process The parser stage creates a parse tree using only fixed rules about the syntactic structure of SQL. It does not make any lookups in the system catalogs, so there is no possibility to understand the detailed semantics of the requested operations. After the parser completes, the transformation process takes the tree handed back by the parser as input and does the semantic interpretation needed to understand which tables, functions, and operators are referenced by the query. The data structure that is built to represent this information is called the query tree. The reason for separating raw parsing from semantic analysis is that system catalog lookups can only be done within a transaction, and we do not wish to start a transaction immediately upon receiving a query string. The raw parsing stage is sufficient to identify the transaction control commands (BEGIN, ROLLBACK, etc), and these can then be correctly executed without any further analysis. Once we know that we are dealing with an actual query (such as SELECT or UPDATE), it is okay to start a transaction if we're not already in one. Only then can the transformation process be invoked. The query tree created by the transformation process is structurally similar to the raw parse tree in most places, but it has many differences in detail. For example, a FuncCall node in the parse tree represents something that looks syntactically like a function call. This may be transformed to either a FuncExpr or Aggref node depending on whether the referenced name turns out to be an ordinary function or an aggregate function. Also, information about the actual data types of columns and expression results is added to the query tree.
923
42.4. The PostgreSQL Rule System PostgreSQL supports a powerful rule system for the specification of views and ambiguous view updates. Originally the PostgreSQL rule system consisted of two implementations: •
The first one worked using row level processing and was implemented deep in the executor. The rule system was called whenever an individual row had been accessed. This implementation was removed in 1995 when the last official release of the Berkeley Postgres project was transformed into Postgres95.
•
The second implementation of the rule system is a technique called query rewriting. The rewrite system is a module that exists between the parser stage and the planner/optimizer. This technique is still implemented.
The query rewriter is discussed in some detail in Capítulo 34, so there is no need to cover it here. We will only point out that both the input and the output of the rewriter are query trees, that is, there is no change in the representation or level of semantic detail in the trees. Rewriting can be thought of as a form of macro expansion.
42.5. Planner/Optimizer The task of the planner/optimizer is to create an optimal execution plan. A given SQL query (and hence, a query tree) can be actually executed in a wide variety of different ways, each of which will produce the same set of results. If it is computationally feasible, the query optimizer will examine each of these possible execution plans, ultimately selecting the execution plan that will run the fastest. Nota: In some situations, examining each possible way in which a query may be executed would take an excessive amount of time and memory space. In particular, this occurs when executing queries involving large numbers of join operations. In order to determine a reasonable (not optimal) query plan in a reasonable amount of time, PostgreSQL uses a Genetic Query Optimizer.
After the cheapest path is determined, a plan tree is built to pass to the executor. This represents the desired execution plan in sufficient detail for the executor to run it.
42.5.1. Generating Possible Plans The planner/optimizer decides which plans should be generated based upon the types of indexes defined on the relations appearing in a query. There is always the possibility of performing a sequential scan on a relation, so a plan using only sequential scans is always created. Assume an index is defined on a relation (for example a Btree index) and a query contains the restriction relation.attribute OPR constant. If relation.attribute happens to match the key of the B-tree index and OPR is one of the operators listed in the index's operator class, another plan is created using the B-tree index to scan the relation. If there are further indexes present and the restrictions in the query happen to match a key of an index further plans will be considered. After all feasible plans have been found for scanning single relations, plans for joining relations are created. The planner/optimizer preferentially considers joins between any two relations for which there exist a corresponding join clause in the WHERE qualification (i.e. for which a restriction like where rel1.attr1=rel2.attr2 exists). Join pairs with no join clause are considered only when there is no other choice, that is, a particular relation has no available join clauses to any other relation. All possible plans are generated for every join pair considered by the planner/optimizer. The three possible join strategies are: •
nested loop join: The right relation is scanned once for every row found in the left relation. This strategy is easy to implement but can be very time consuming. (However, if the right relation can be scanned with an index scan, this can be a good strategy. It is possible to use values from the current row of the left relation as keys for the index scan of the right.)
•
merge sort join: Each relation is sorted on the join attributes before the join starts. Then the two relations are merged together taking into account that both relations are ordered on the join attributes. This kind of join is more attractive because each relation has to be scanned only once.
924
•
hash join: the right relation is first scanned and loaded into a hash table, using its join attributes as hash keys. Next the left relation is scanned and the appropriate values of every row found are used as hash keys to locate the matching rows in the table.
The finished plan tree consists of sequential or index scans of the base relations, plus nested-loop, merge, or hash join nodes as needed, plus any auxiliary steps needed, such as sort nodes or aggregate-function calculation nodes. Most of these plan node types have the additional ability to do selection (discarding rows that do not meet a specified boolean condition) and projection (computation of a derived column set based on given column values, that is, evaluation of scalar expressions where needed). One of the responsibilities of the planner is to attach selection conditions from the WHERE clause and computation of required output expressions to the most appropriate nodes of the plan tree.
42.6. Executor The executor takes the plan handed back by the planner/optimizer and recursively processes it to extract the required set of rows. This is essentially a demand-pull pipeline mechanism. Each time a plan node is called, it must deliver one more row, or report that it is done delivering rows. To provide a concrete example, assume that the top node is a MergeJoin node. Before any merge can be done two rows have to be fetched (one from each subplan). So the executor recursively calls itself to process the subplans (it starts with the subplan attached to lefttree). The new top node (the top node of the left subplan) is, let's say, a Sort node and again recursion is needed to obtain an input row. The child node of the Sort might be a SeqScan node, representing actual reading of a table. Execution of this node causes the executor to fetch a row from the table and return it up to the calling node. The Sort node will repeatedly call its child to obtain all the rows to be sorted. When the input is exhausted (as indicated by the child node returning a NULL instead of a row), the Sort code performs the sort, and finally is able to return its first output row, namely the first one in sorted order. It keeps the remaining rows stored so that it can deliver them in sorted order in response to later demands. The MergeJoin node similarly demands the first row from its right subplan. Then it compares the two rows to see if they can be joined; if so, it returns a join row to its caller. On the next call, or immediately if it cannot join the current pair of inputs, it advances to the next row of one table or the other (depending on how the comparison came out), and again checks for a match. Eventually, one subplan or the other is exhausted, and the MergeJoin node returns NULL to indicate that no more join rows can be formed. Complex queries may involve many levels of plan nodes, but the general approach is the same: each node computes and returns its next output row each time it is called. Each node is also responsible for applying any selection or projection expressions that were assigned to it by the planner. The executor mechanism is used to evaluate all four basic SQL query types: SELECT, INSERT, UPDATE, and DELETE. For SELECT, the top-level executor code only needs to send each row returned by the query plan tree off to the client. For INSERT, each returned row is inserted into the target table specified for the INSERT. (A simple INSERT ... VALUES command creates a trivial plan tree consisting of a single Result node, which computes just one result row. But INSERT ... SELECT may demand the full power of the executor mechanism.) For UPDATE, the planner arranges that each computed row includes all the updated column values, plus the TID (tuple ID, or row ID) of the original target row; the executor top level uses this information to create a new updated row and mark the old row deleted. For DELETE, the only column that is actually returned by the plan is the TID, and the executor top level simply uses the TID to visit the target rows and mark them deleted.
925
Capítulo 43. Catálogos do sistema Os catálogos do sistema são os locais onde os sistemas gerenciadores de banco de dados relacionais armazenam os metadados do esquema, tais como informações sobre tabelas e colunas, e informações de controle internas. Os catálogos do sistema do PostgreSQL são tabelas comuns. As tabelas podem ser removidas e recriadas, colunas podem ser adicionadas, podem ser inseridos e atualizados valores, e o sistema pode ser inteiramente arruinado desta forma. Normalmente, os catálogos do sistema não devem ser modificados manualmente, sempre existe um comando SQL para fazê-lo (Por exemplo, CREATE DATABASE insere uma linha no catálogo pg_database; e cria de verdade o banco de dados no disco). Existem exceções para algumas operações obscuras muito particulares, como adicionar método de acesso de índice. 1
43.1. Visão geral A Tabela 43-1 lista os catálogos do sistema. A documentação mais detalhada sobre cada catálogo é mostrada a seguir. Os catálogos do sistema são, em sua maioria, copiados do banco de dados modelo durante a criação de um banco de dados novo e, portanto, estes catálogos são próprios do banco de dados. Alguns poucos catálogos são compartilhados fisicamente entre todos os bancos de dados do agrupamento; isto está indicado na descrição individual do catálogo. Tabela 43-1. Catálogos do sistema Nome do catálogo
Finalidade
pg_aggregate
funções de agregação
pg_am
métodos de acesso de índice
pg_amop
operadores de método de acesso
pg_amproc
procedimentos de suporte de método de acesso
pg_attrdef
valor padrão das colunas
pg_attribute
colunas de tabela (“atributos”)
pg_cast
casts (conversões de tipos de dado)
pg_class
tabelas, índices, seqüências (“relações”)
pg_constraint
restrições de verificação, restrições de unicidade, restrições de chave primária, restrições de chave estrangeira
pg_conversion
informações sobre conversão de codificação
pg_database
bancos de dados que fazem parte deste agrupamento de bancos de dados
pg_depend
dependências entre objetos do banco de dados
pg_description
descrições ou comentários sobre os objetos do banco de dados
pg_group
grupos de usuários do banco de dados
pg_index
informações adicionais sobre índices
pg_inherits
hierarquia de herança de tabela
pg_language
linguagens para escrever funções
pg_largeobject
objetos grandes
926
Nome do catálogo
Finalidade
pg_listener
suporte à notificação assíncrona
pg_namespace
esquemas
pg_opclass
classes de operador de método de acesso de índice
pg_operator
operadores
pg_proc
funções e procedimentos
pg_rewrite
regras de reescrita dos comandos
pg_shadow
usuários do banco de dados
pg_statistic
estatísticas do planejador
pg_trigger
gatilhos
pg_type
tipos de dado
43.2. pg_aggregate O catálogo pg_aggregate armazena informações sobre funções de agregação. Uma função de agregação é uma função que opera sobre um conjunto de valores (tipicamente uma coluna de cada linha que corresponde à condição da consulta), e retorna um único valor calculado a partir destes valores. As funções de agregação típicas são sum, count e max. Cada entrada em pg_aggregate é uma extensão de uma entrada em pg_proc. A entrada em pg_proc mostra o nome da agregação, os tipos de dado de entrada e de saída, além de outras informações semelhantes às das funções comuns. Tabela 43-2. Colunas do catálogo pg_aggregate Nome
Tipo
Referencia
Descrição
aggfnoid
regproc
pg_proc.oid
OID do pg_proc da função de agregação
aggtransfn
regproc
pg_proc.oid
Função de transição
aggfinalfn
regproc
pg_proc.oid
Função final (zero se não houver nenhuma)
aggtranstype
oid
pg_type.oid
Tipo de dado da transição interna (estado) da função de agregação
agginitval
text
O valor inicial do estado da transição. É um campo texto, contendo o valor inicial na sua representação externa na forma de cadeia de caracteres. Se o valor for nulo, o valor do estado da transição começa por nulo.
As novas funções de agregação são registradas através do comando CREATE AGGREGATE. Veja a Seção 33.9 para obter mais informações sobre como escrever funções de agregação e o significado das funções de transição, etc. Exemplo de utilização: SELECT aggfnoid, aggtransfn, aggfinalfn FROM pg_aggregate; aggfnoid | aggtransfn | aggfinalfn ---------------------+---------------------+-----------------pg_catalog.avg | int8_accum | numeric_avg pg_catalog.avg | int4_avg_accum | int8_avg pg_catalog.avg | int2_avg_accum | int8_avg pg_catalog.avg | numeric_accum | numeric_avg
927
pg_catalog.avg pg_catalog.avg pg_catalog.avg pg_catalog.sum pg_catalog.sum pg_catalog.sum pg_catalog.sum pg_catalog.sum pg_catalog.sum pg_catalog.sum pg_catalog.sum pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.max pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min pg_catalog.min count pg_catalog.variance pg_catalog.variance pg_catalog.variance pg_catalog.variance pg_catalog.variance pg_catalog.variance pg_catalog.stddev pg_catalog.stddev pg_catalog.stddev pg_catalog.stddev pg_catalog.stddev pg_catalog.stddev (60 linhas)
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
float4_accum float8_accum interval_accum int8_sum int4_sum int2_sum float4pl float8pl cash_pl interval_pl numeric_add int8larger int4larger int2larger oidlarger float4larger float8larger int4larger date_larger time_larger timetz_larger cashlarger timestamp_larger timestamptz_larger interval_larger text_larger numeric_larger int8smaller int4smaller int2smaller oidsmaller float4smaller float8smaller int4smaller date_smaller time_smaller timetz_smaller cashsmaller timestamp_smaller timestamptz_smaller interval_smaller text_smaller numeric_smaller int8inc int8_accum int4_accum int2_accum float4_accum float8_accum numeric_accum int8_accum int4_accum int2_accum float4_accum float8_accum numeric_accum
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
float8_avg float8_avg interval_avg numeric_variance numeric_variance numeric_variance float8_variance float8_variance numeric_variance numeric_stddev numeric_stddev numeric_stddev float8_stddev float8_stddev numeric_stddev
928
43.3. pg_am O catálogo pg_am armazena informações sobre os métodos de acesso de índice. Existe uma linha para cada método de acesso de índice suportado pelo sistema. Tabela 43-3. Colunas do catálogo pg_am Nome
Tipo
Referencia
Descrição
amname
name
amowner
int4
amstrategies
int2
Número de estratégias do operador para este método de acesso
amsupport
int2
Número de rotinas de suporte para este método de acesso
amorderstrategy
int2
Zero se o índice não oferece ordem de classificação, senão o número da estratégia do operador de estratégia que descreve a ordem de classificação
amcanunique
bool
Verdade se o método de acesso suporta índices únicos
amcanmulticol
bool
Verdade se o método de acesso suporta índices de várias colunas
amindexnulls
bool
Verdade se o método de acesso suporta entradas de índice nulas
amconcurrent
bool
Verdade se o método de acesso suporta atualizações simultâneas
amgettuple
regproc
pg_proc.oid
Função “próxima tupla válida”
aminsert
regproc
pg_proc.oid
Função “insere esta tupla”
ambeginscan
regproc
pg_proc.oid
Função “começa nova varredura”
amrescan
regproc
pg_proc.oid
Função “recomeça esta varredura”
amendscan
regproc
pg_proc.oid
Função “termina esta varredura”
ammarkpos
regproc
pg_proc.oid
Função “marque a posição corrente da varredura”
amrestrpos
regproc
pg_proc.oid
Função “restaure a posição de varredura marcada”
ambuild
regproc
pg_proc.oid
Função “constrói novo índice”
ambulkdelete
regproc
pg_proc.oid
Função “apagar em massa” (bulk-delete)
amvacuumcleanup
regproc
pg_proc.oid
Função limpeza pós-VACUUM
amcostestimate
regproc
pg_proc.oid
Função para estimar o custo de uma varredura de índice
Nome do método de acesso pg_shadow.usesysid
ID de usuário do dono (atualmente não utilizado)
Um método de acesso de índice que suporta várias colunas (possui amcanmulticol verdade) deve suportar a indexação de valores nulos nas colunas após a primeira, porque o planejador assume que o índice pode ser utilizado para consultas apenas na(s) primeira(s) coluna(s). Por exemplo, considere um índice em (a,b) e uma
929
consulta com WHERE a = 4. O sistema assume que o índice pode ser utilizado para ser varrido à procura de linhas com a = 4, o que está errado se o índice omitir as linhas onde b é nulo. Entretanto, está tudo bem se o índice omitir as linhas onde a primeira coluna indexada for nula (atualmente o GiST faz assim). amindexnulls deve ser definida como verdade somente se o método de acesso do índice indexar todas as linhas, incluindo combinações arbitrárias de valores nulos.
43.4. pg_amop O catálogo pg_amop armazena informações sobre operadores associados a classes de operadores de método de acesso de índice. Existe uma linha para cada operador que é membro de uma classe de operadores. Tabela 43-4. Colunas do catálogo pg_amop Nome
Tipo
Referencia
Descrição
amopclaid
oid
pg_opclass.oid
Classe de operador de índice
amopstrategy
int2
Número da estratégia do operador
amopreqcheck
bool
Acerto no índice deve ser verificado novamente
amopopr
oid
OID do operador
pg_operator.oid
43.5. pg_amproc O catálogo pg_amproc armazena informações sobre os procedimentos de suporte associados às classes de operadores de método de acesso de índice. Existe uma linha para cada procedimento de suporte que pertence a uma classe de operadores. Tabela 43-5. Colunas do catálogo pg_amproc Nome
Tipo
Referencia
Descrição
amopclaid
oid
pg_opclass.oid
Classes de operador de índice
amprocnum
int2
amproc
regproc
Número do procedimento de suporte pg_proc.oid
OID do procedimento
43.6. pg_attrdef O catálogo pg_attrdef armazena o valor padrão das colunas. As informações principais sobre as colunas estão armazenadas em pg_attribute (veja a seguir). Somente as colunas que especificam explicitamente o valor padrão (quando a tabela é criada ou a coluna é adicionada) possuem uma entrada nesta tabela. Tabela 43-6. Colunas do catálogo pg_attrdef Nome
Tipo
Referencia
Descrição
adrelid
oid
pg_class.oid
Tabela que esta coluna pertence
adnum
int2
pg_attribute.attnum
Número da coluna
adbin
text
Representação interna do valor padrão da coluna
adsrc
text
Representação humanamente legível do valor padrão
43.7. pg_attribute O catálogo pg_attribute armazena informações sobre as colunas das tabelas. Existe exatamente uma linha em pg_attribute para cada coluna de cada tabela do banco de dados (Também existem entradas de atributo para os índices e outros objetos. Veja pg_class).
930
O termo atributo equivale a coluna, sendo usado por motivos históricos. Tabela 43-7. Colunas do catálogo pg_attribute Nome
Tipo
Referencia
Descrição
attrelid
oid
pg_class.oid
Tabela que esta coluna pertence
attname
name
atttypid
oid
attstattarget
int4
attstattarget controla o nível de detalhe das estatísticas acumuladas para esta coluna pelo comando ANALYZE. O valor zero indica que nenhuma estatística deve ser coletada. Um valor negativo diz para usar o padrão do sistema. O significado exato dos valores positivos é dependente do tipo de dado. Para os tipos de dado escalares, attstattarget é tanto o número de “valores mais comuns” a serem coletados, quanto o número de barras do histograma a serem criadas
attlen
int2
Cópia de pg_type.typlen do tipo desta coluna
attnum
int2
Número da coluna. As colunas comuns são numeradas a partir de um. As colunas do sistema, tal como oid, possuem números negativos (arbitrários)
attndims
int4
Número de dimensões, se a coluna for um tipo matriz; senão zero (Atualmente o número de dimensões de uma matriz não é verificado, portanto qualquer valor diferente de zero significa de fato “isto é uma matriz”)
attcacheoff
int4
Sempre -1 no armazenamento, mas quando carregado na memória em um descritor de linha pode ser atualizado para guardar o deslocamento do atributo na linha
atttypmod
int4
atttypmod registra dados específicos do tipo, fornecidos na hora da criação da tabela (por exemplo, o comprimento máximo de uma coluna varchar). É passado para as funções de entrada específicas dos tipos, e para as funções de imposição de comprimento. Geralmente o valor é -1 para os tipos que não necessitam de atttypmod
attbyval
bool
Cópia de pg_type.typbyval do tipo desta coluna
attstorage
char
Normalmente uma cópia de pg_type.typstorage do tipo desta coluna. Para os tipos de dado TOAST-íveis, pode ser alterado após a criação da coluna para controlar a política de armazenamento
attisset
bool
Se for verdade, este atributo é um conjunto. Neste caso, o que realmente é armazenado no atributo é o OID da linha no catálogo pg_proc. A linha pg_proc contém a cadeia de caracteres da consulta que define este conjunto, ou seja, a consulta a ser executada para obter o conjunto. Portanto, atttypid (veja acima) se refere ao tipo retornado por esta consulta, mas o comprimento real deste atributo é o comprimento (tamanho) de um oid; ao menos esta é a teoria. Provavelmente atualmente existem muitas diferenças
attalign
char
Cópia de pg_type.typalign do tipo desta coluna
Nome da coluna pg_type.oid
Tipo de dado desta coluna
931
Nome
Tipo
Referencia
Descrição
attnotnull
bool
Representa uma restrição de não-nulo. É possível modificar esta coluna para habilitar ou desabilitar a restrição
atthasdef
bool
Indica se esta coluna possui um valor padrão e, neste caso, existe uma entrada correspondente no catálogo pg_attrdef que realmente define o valor
attisdropped
bool
Indica se esta coluna foi removida e, portanto, não é mais válida. Uma coluna removida continua presente na tabela, mas é ignorada pelo analisador e, portanto, não pode ser acessada via SQL
attislocal
bool
Indica se a coluna é definida localmente na relação. Observe que a coluna pode ser definida localmente e herdada simultaneamente
attinhcount
int4
Número de ancestrais diretos que a coluna possui. Uma coluna com um número de ancestrais diferente de zero não pode ser removida nem renomeada
43.8. pg_cast O catálogo pg_cast armazena caminhos de conversão de tipo de dados, tanto os caminhos nativos quanto os definidos através de CREATE CAST. Tabela 43-8. Colunas do catálogo pg_cast Nome
Tipo
Referencia
Descrição
castsource
oid
pg_type.oid
OID do tipo de dado de origem
casttarget
oid
pg_type.oid
OID do tipo de dado de destino
castfunc
oid
pg_proc.oid
OID da função a ser utilizada para realizar esta conversão. Zero se os tipos de dado forem binariamente compatíveis (ou seja, nenhuma operação em tempo de execução é necessária para realizar a conversão).
castcontext
char
Indica em que contextos a conversão pode ser chamada. O valor e significa somente as conversões explícitas (utilizando CAST, ::, ou a sintaxe de chamada de função). O valor a significa implicitamente na atribuição à coluna de destino, bem como explicitamente. O valor i significa implicitamente em expressões, bem como nos demais casos.
43.9. pg_class O catálogo pg_class cataloga as tabelas e tudo mais que possui colunas, ou é de alguma forma semelhante a uma tabela. Isto inclui os índices (mas veja também pg_index), seqüências, visões e alguns tipos de relação especiais; veja relkind. Abaixo, para nos referirmos a todos estes tipos de objetos falamos “relações”. Nem todas as colunas possuem significado em todos os tipos de relação.
932
Tabela 43-9. Colunas do catálogo pg_class Nome
Tipo
Referencia
Descrição
relname
name
relnamespace
oid
pg_namespace.oid
OID do espaço de nomes que contém esta relação.
reltype
oid
pg_type.oid
OID do tipo de dado que corresponde a esta tabela, caso haja algum (zero para índices, os quais não possuem entrada em pg_type).
relowner
int4
pg_shadow.usesysid
Dono da relação
relam
oid
pg_am.oid
Se for um índice, o método de acesso usado (B-tree, hash, etc.)
relfilenode
oid
Nome do arquivo em disco desta relação; 0 se não houver nenhum
relpages
int4
Tamanho da representação em disco desta tabela em páginas (tamanho BLCKSZ). Esta é apenas uma estimativa utilizada pelo planejador. Atualizado pelos comandos VACUUM, ANALYZE e CREATE INDEX.
reltuples
float4
Número de linhas na tabela. Esta é apenas uma estimativa utilizada pelo planejador. Atualizado pelos comandos VACUUM, ANALYZE e CREATE INDEX.
reltoastrelid
oid
pg_class.oid
OID da tabela TOAST associada a esta tabela, 0 se não houver nenhuma. A tabela TOAST armazena atributos grandes “fora de linha”, em uma tabela secundária.
reltoastidxid
oid
pg_class.oid
Para a tabela TOAST, o OID de seu índice. 0 se não for uma tabela TOAST.
relhasindex
bool
Verdade se for uma tabela e possui (ou possuía recentemente) algum índice. É definido por CREATE INDEX, mas não é limpo imediatamente por DROP INDEX. O comando VACUUM limpa relhasindex quando descobre que a tabela não possui índices.
relisshared
bool
Verdade se esta tabela for compartilhada entre todos os bancos de dados do agrupamento. Somente alguns catálogos do sistema, como pg_database, são compartilhados
relkind
char
r = tabela comum, i = índice, S = sequência, v = visão, c = tipo composto, s = especial, t =
Nome da tabela, índice, visão, etc
tabela TOAST relnatts
int2
Número de colunas de usuário na relação (colunas do sistema não são contadas). Deve haver uma quantidade de entradas correspondente em pg_attribute. Veja também pg_attribute.attnum.
933
Nome
Tipo
relchecks
int2
reltriggers
int2
Referencia
Descrição Número de restrições de verificação na tabela; veja o catálogo pg_constraint. Número de gatilhos na tabela; veja o catálogo pg_trigger.
relukeys
int2
Não utilizado (Não é o número de chaves únicas)
relfkeys
int2
Não utilizado (Não é o número de chaves estrangeiras na tabela)
relrefs
int2
Não utilizado
relhasoids
bool
Verdade se for gerado um OID para cada linha da relação.
relhaspkey
bool
Verdade se a tabela possui (ou já possuiu) uma chave primária.
relhasrules
bool
Verdade se a tabela possui regras; veja o catálogo pg_rewrite.
relhassubclass
bool
Verdade se ao menos uma tabela herda desta
relacl
aclitem[]
Privilégios de acesso; veja as descrições dos comandos GRANT e REVOKE para obter detalhes.
43.10. pg_constraint O catálogo pg_constraint armazena restrições de verificação, chave primária, unicidade e chave estrangeira em tabelas (As restrições de coluna não são tratadas de forma especial, porque toda restrição de coluna equivale a alguma restrição de tabela). As restrições de não-nulo são representadas no catálogo pg_attribute. As restrições de verificação em domínios também são tratadas aqui. Tabela 43-10. Colunas do catálogo pg_constraint Nome
Tipo
Referencia
Descrição
conname
name
connamespace
oid
contype
char
c = restrição de verificação; f = restrição de chave estrangeira; p = restrição de chave primária; u = restrição de unicidade.
condeferrable
bool
Verdade se a restrição for postergável
condeferred
bool
Verdade se a restrição for postergada por padrão
conrelid
oid
pg_class.oid
Tabela onde esta restrição se encontra; 0 zero se não for uma restrição de tabela
contypid
oid
pg_type.oid
Domínio onde esta restrição se encontra; 0 se não for uma restrição de domínio
confrelid
oid
pg_class.oid
Se for uma chave estrangeira, a tabela referenciada; senão 0
confupdtype
char
Nome da restrição (não necessariamente única!) pg_namespace.oid
OID do espaço de nomes que contém a restrição.
Código da ação de atualização da chave estrangeira
934
Nome
Tipo
Referencia
Descrição
confdeltype
char
Código da ação de exclusão da chave estrangeira
confmatchtype
char
Tipo de correspondência da chave estrangeira
conkey
int2[]
pg_attribute.attnum
Se for uma restrição de tabela, a lista de colunas que a restrição abrange
confkey
int2[]
pg_attribute.attnum
Se for uma chave estrangeira, a lista de colunas referenciadas
conbin
text
Se for uma restrição de verificação, a representação interna da expressão
consrc
text
Se for uma restrição de verificação, a representação humanamente legível da expressão
Nota: consrc não é atualizada quando os objetos referenciados mudam; por exemplo, não acompanha a mudança dos nomes das colunas. Em vez de confiar neste campo, é melhor utilizar pg_get_constraintdef() para obter a definição da restrição de verificação. Nota: pg_class.relchecks precisa condizer com o número de entradas de restrição de verificação encontradas nesta tabela para uma determinada relação.
43.11. pg_conversion O catálogo pg_conversion armazena informações sobre conversão de codificação. Veja o comando CREATE CONVERSION para obter mais informações. Tabela 43-11. Colunas do catálogo pg_conversion Nome
Tipo
Referencia
Descrição
conname
name
connamespace
oid
pg_namespace.oid
OID do espaço de nomes que contém esta conversão.
conowner
int4
pg_shadow.usesysid
Dono da conversão
conforencoding
int4
ID da codificação de origem
contoencoding
int4
ID da codificação de destino
conproc
regproc
condefault
bool
Nome da conversão (único no espaço de nomes)
pg_proc.oid
Procedimento de conversão Verdade se for a conversão padrão
43.12. pg_database O catálogo pg_database armazena informações sobre os bancos de dados disponíveis. Os bancos de dados são criados pelo comando CREATE DATABASE. Consulte o Capítulo 18 para obter detalhes sobre o significado de alguns parâmetros. Diferentemente da maioria dos catálogos do sistema, pg_database é compartilhado por todos os bancos de dados do agrupamento: só existe uma instância de pg_database por agrupamento, e não uma por banco de dados.
935
Tabela 43-12. Colunas do catálogo pg_database Nome
Tipo
Referencia
Descrição
datname
name
datdba
int4
encoding
int4
Codificação dos caracteres deste banco de dados
datistemplate
bool
Se for verdade, então este banco de dados pode ser utilizado na cláusula TEMPLATE do comando CREATE DATABASE para criar um banco de dados novo que seja um clone deste.
datallowconn
bool
Se for falso, então ninguém pode se conectar a este banco de dados. É utilizado para proteger o banco de dados template0 contra alterações.
datlastsysoid
oid
Último OID de sistema no banco de dados; particularmente útil para pg_dump.
datvacuumxid
xid
Todas as linhas inseridas ou excluídas por IDs de transação anteriores a este, foram marcadas como sabidamente efetivadas ou sabidamente interrompidas, neste banco de dados. É utilizado para determinar quando o espaço de log de efetivação pode ser reciclado.
datfrozenxid
xid
Todas as linhas inseridas por IDs de transação anteriores a este receberam um ID de transação permanente neste banco de dados (“foram congeladas”). Útil para verificar há necessidade de executar em breve o comando VACUUM no banco de dados para evitar o problema de reinício de ID de transação.
datpath
text
Se o banco de dados estiver armazenado em um local alternativo, então esta coluna registra este local. É o nome de uma variável de ambiente ou é um caminho absoluto, dependendo de como foi fornecido.
datconfig
text[]
Padrões de sessão para as variáveis de configuração em tempo de execução
datacl
aclitem[]
Privilégios de acesso
Nome do banco de dados pg_shadow.usesysid
Dono do banco de dados, geralmente o usuário que o criou
43.13. pg_depend O catálogo pg_depend registra os relacionamentos de dependência entre os objetos do banco de dados. Esta informação permite ao comando DROP descobrir quais outros objetos devem ser removidos pelo DROP CASCADE, ou evitar a remoção no caso de DROP RESTRICT.
936
Tabela 43-13. Colunas do catálogo pg_depend Nome
Tipo
Referencia
Descrição
classid
oid
pg_class.oid
OID do catálogo do sistema onde está o objeto dependente
objid
oid
qualquer coluna OID
OID do objeto dependente
objsubid
int4
Para uma coluna de tabela, o número da coluna (o objid e o classid se referem à própria tabela). Para todos os outros tipos de objeto esta coluna é zero.
refclassid
oid
pg_class.oid
OID do catálogo do sistema onde está o objeto referenciado
refobjid
oid
qualquer coluna OID
OID do objeto referenciado
refobjsubid
int4
Para uma coluna de tabela, o número da coluna (o objid e o classid se referem à própria tabela). Para todos os outros tipos de objeto esta coluna é zero.
deptype
char
Código definindo as semânticas específicas deste relacionamento de dependência; veja o texto.
Em todos os casos, um entrada em pg_depend indica que o objeto referenciado não pode ser removido sem também remover o objeto dependente. Entretanto, existem diversas subcategorias identificadas por deptype: DEPENDENCY_NORMAL (n)
Relacionamento normal entre objetos criados separadamente. O objeto dependente pode ser removido sem afetar o objeto referenciado. O objeto referenciado só pode ser removido especificando CASCADE e, neste caso, o objeto dependente também é removido. Exemplo: uma coluna de tabela possui uma dependência normal de seu tipo de dado. DEPENDENCY_AUTO (a)
O objeto dependente pode ser removido separadamente do objeto referenciado, e deve ser removido automaticamente (a despeito do modo RESTRICT ou CASCADE) se o objeto referenciado for removido. Exemplo: uma restrição com nome em uma tabela é autodependente da tabela e, portanto, desaparece quando a tabela é removida. DEPENDENCY_INTERNAL (i)
O objeto dependente foi criado como parte da criação do objeto referenciado sendo, na verdade, apenas uma parte de sua implementação interna. O DROP do objeto dependente será desabilitado imediatamente (será informado ao usuário para executar o DROP do objeto referenciado, em vez deste objeto). O DROP do objeto referenciado é propagado para remover o objeto dependente, estando CASCADE especificado ou não. Exemplo: um gatilho criado para garantir a restrição de chave estrangeira é tornado dependente internamente da entrada em pg_constraint da restrição. DEPENDENCY_PIN (p)
Não existe nenhum objeto dependente; este tipo de entrada é um sinal que o próprio sistema depende do objeto referenciado e, portanto, o objeto não pode ser removido nunca. As entradas deste tipo são criadas apenas pelo initdb. As colunas do objeto dependente contêm zero. Outras modalidades de dependência poderão ser necessárias no futuro.
43.14. pg_description O catálogo pg_description pode armazenar uma descrição opcional, ou comentário, para cada objeto do banco de dados. As descrições podem ser manipuladas pelo comando COMMENT, e vistas pelos comandos \d do psql. A descrição de vários objetos nativos do sistema está presente no conteúdo inicial de pg_description.
937
Tabela 43-14. Colunas do catálogo pg_description Nome
Tipo
Referencia
Descrição
objoid
oid
qualquer coluna OID
OID do objeto que esta descrição pertence
classoid
oid
pg_class.oid
OID do catálogo do sistema onde este objeto se encontra
objsubid
int4
Para um comentário sobre uma coluna de tabela, é o número da coluna (o objoid e o classoid se referem à própria tabela). Para todos os outros tipos de objeto esta coluna é zero.
description
text
Texto arbitrário que serve como descrição do objeto
43.15. pg_group O catálogo pg_group define os grupos e armazena quais usuários pertencem a cada grupo. Os grupos são criados pelo comando CREATE GROUP. Consulte o Capítulo 17 para obter informações sobre o gerenciamento de privilégios de usuário. Como as identidades dos usuários e dos grupos são para todo o agrupamento de bancos de dados, a tabela pg_group é compartilhada por todos os bancos de dados do agrupamento: existe apenas uma instância de pg_group por agrupamento, e não uma por banco de dados.
Tabela 43-15. Colunas do catálogo pg_group Nome
Tipo
Referencia
Descrição
groname
name
Nome do grupo
grosysid
int4
Número arbitrário para identificar o grupo
grolist
int4[]
pg_shadow.usesysid
Matriz contendo os IDs dos usuários neste grupo
43.16. pg_index O catálogo pg_index contém parte das informações sobre índices. O restante se encontra, em sua maioria, em pg_class.
Tabela 43-16. Colunas do catálogo pg_index Nome
Tipo
Referencia
Descrição
indexrelid
oid
pg_class.oid
OID da entrada em pg_class para este índice
indrelid
oid
pg_class.oid
OID da entrada em pg_class da tabela onde este índice está definido
indkey
int2vector
pg_attribute.attnum
Matriz de valores indnatts (contendo até INDEX_MAX_KEYS), indicamdo quais colunas da tabela este índice indexa. Por exemplo, o valor 1 3 significa que a primeira e a terceira coluna da tabela constituem a chave do índice. Um zero nesta matriz indica que o atributo do índice correspondente é uma expressão contendo colunas da tabela, em vez de uma simples referência à coluna.
938
Nome
Tipo
Referencia
Descrição
indclass
oidvector
pg_opclass.oid
Contém o OID da classe de operadores a ser utilizada para cada coluna presente na chave do índice. Veja pg_opclass para obter mais detalhes.
indnatts
int2
Número de colunas no índice (duplica pg_class.relnatts)
indisunique
bool
Se for verdade, então o índice é único
indisprimary
bool
Se for verdade, este índice representa a chave primária da tabela (A coluna indisunique deve ser sempre verdade quando esta coluna for verdade)
indisclustered
bool
Se for verdade, a tabela foi agrupada por este índice na última vez
indexprs
text
Árvores de expressão (na representação nodeToString()) para os atributos do índice que não são simplesmente referências a colunas. É uma lista com um elemento para cada entrada igual a zero em indkey. Nulo se todos os atributos do índice são simplesmente referências a colunas
indpred
text
Árvore de expressão (na representação nodeToString()) para predicados de
índice parciais. Nulo se não for um índice parcial
43.17. pg_inherits O catálogo pg_inherits registra informações sobre hierarquias de herança de tabelas. Tabela 43-17. Colunas do catálogo pg_inherits Nome
Tipo
Referencia
Descrição
inhrelid
oid
pg_class.oid
OID da tabela descendente.
inhparent
oid
pg_class.oid
OID da tabela ancestral.
inhseqno
int4
Se houver mais de um ancestral para a tabela descendente (herança múltipla), este número informa a ordem pela qual as colunas herdadas deve ser dispostas. O contador começa por 1.
43.18. pg_language O catálogo pg_language registra interfaces de chamada ou linguagens em que podem ser escritas funções ou procedimentos armazenados. Veja CREATE LANGUAGE e o Capítulo 36 para obter mais informações sobre tratadores de linguagem.
939
Tabela 43-18. Colunas do catálogo pg_language Nome
Tipo
Referencia
Descrição
lanname
name
Nome da linguagem (a ser especificada ao criar a função)
lanispl
bool
Falso para linguagens internas (tal como SQL), e verdade para as linguagens definidas pelo usuário. Atualmente o pg_dump ainda utiliza esta informação para determinar quais linguagens devem fazer parte da cópia de segurança, mas este mecanismo pode ser substituído por outro diferente alguma hora.
lanpltrusted
bool
Verdade se for uma linguagem confiável (trusted). Veja em CREATE LANGUAGE o que isto significa. Se for uma linguagem interna (lanispl for falso), então esta coluna não faz sentido.
lanplcallfoid
oid
pg_proc.oid
Para as linguagens não internas é a referência ao tratador da linguagem, que é uma função especial responsável pela execução de todas as funções escritas nesta linguagem.
lanvalidator
oid
pg_proc.oid
Faz referência à função validadora da linguagem, responsável pela verificação da sintaxe e validação das novas funções quando estas são criadas. Veja CREATE LANGUAGE para obter mais informações sobre validadores.
lanacl
aclitem[]
Privilégios de acesso
43.19. pg_largeobject O catálogo pg_largeobject armazena os dados que constituem os “objetos grandes”. O objeto grande é identificado por um OID atribuído ao mesmo quando de sua criação. Cada objeto grande é fracionado em segmentos, ou “páginas”, pequenos o suficiente para serem convenientemente armazenados como linhas na tabela pg_largeobject. A quantidade de dados por página é definida como sendo LOBLKSIZE (que atualmente é BLCKSZ/4 ou, tipicamente, 2 kB). Tabela 43-19. Colunas do catálogo pg_largeobject Nome
Tipo
Referencia
Descrição
loid
oid
Identificador do objeto grande que inclui esta página
pageno
int4
Número de página desta página dentro do objeto grande (contado a partir de zero)
data
bytea
Dados realmente armazenados no objeto grande. Nunca mais de LOBLKSIZE bytes, podendo ser menos.
Cada linha de pg_largeobject armazenas dados de uma página do objeto grande, começando pelo deslocamento de (pageno * LOBLKSIZE) bytes dentro do objeto. A implementação permite armazenamento esparso: podem estar faltando páginas, e pode ser menos que LOBLKSIZE bytes, mesmo que não seja a última página do objeto. Regiões faltando dentro do objeto grande são lidas como contendo zeros.
43.20. pg_listener O catálogo pg_listener dá suporte aos comandos LISTEN e NOTIFY. O ouvinte cria uma entrada em pg_listener para cada nome de notificação que está ouvindo. O notificador varre pg_listener e atualiza
940
cada entrada correspondente para indicar que a notificação ocorreu. O notificador também envia um sinal (utilizando oe PID registrado na tabela) para acordar o ouvinte. Tabela 43-20. Colunas do catálogo pg_listener Nome
Tipo
Referencia
Descrição
relname
name
Nome da condição de notificação (O nome não precisa corresponder a nenhuma relação existente no banco de dados; o nome relname é histórico).
listenerpid
int4
PID do processo servidor que criou esta entrada
notification
int4
Zero se não houver nenhum evento pendente para este ouvinte. Havendo um evento pendente, o PID do processo servidor que enviou a notificação.
43.21. pg_namespace O catálogo pg_namespace armazena espaços de nome. O espaço de nomes é a estrutura por baixo dos esquemas SQL: cada espaço de nomes pode ter uma coleção separada de relações, tipos, etc. sem conflito de nomes. Tabela 43-21. Colunas do catálogo pg_namespace Nome
Tipo
nspname
name
nspowner
int4
nspacl
aclitem[]
Referencia
Descrição Nome do espaço de nomes
pg_shadow.usesysid
Dono do espaço de nomes Privilégios de acesso
Exemplo de utilização: SELECT * FROM pg_namespace; nspname | nspowner | nspacl --------------------+----------+--------------------------------------pg_toast | 1 | (nulo) pg_temp_1 | 1 | (nulo) pg_catalog | 1 | {postgres=U*C*/postgres,=U/postgres} public | 1 | {postgres=U*C*/postgres,=UC/postgres} information_schema | 1 | {postgres=U*C*/postgres,=U/postgres} (5 linhas) SELECT catalog_name, schema_name, schema_owner FROM information_schema.schemata; catalog_name | schema_name | schema_owner --------------+--------------------+-------------template1 | pg_toast | postgres template1 | pg_temp_1 | postgres template1 | pg_catalog | postgres template1 | public | postgres template1 | information_schema | postgres (5 linhas)
941
43.22. pg_opclass O catálogo pg_opclass define as classes de operadores de método de acesso de índice. Cada classe de operadores define a semântica para as colunas do índice de um determinado tipo de dado e um determinado método de acesso de índice. Observe que podem existir várias classes de operadores para uma determinada combinação de tipo de dado/método de acesso e, assim, dando suporte a vários comportamentos. As classes de operadores estão descritas por completo na Seção 33.13. Tabela 43-22. Colunas do catálogo pg_opclass Nome
Tipo
Referencia
Descrição
opcamid
oid
pg_am.oid
Classe de método de acesso de índice a que se destina
opcname
name
opcnamespace
oid
pg_namespace.oid
Espaço de nomes desta classe de operadores
opcowner
int4
pg_shadow.usesysid
Dono da classe de operadores
opcintype
oid
pg_type.oid
Tipo de dado de entrada da classe de operadores
opcdefault
bool
opckeytype
oid
Nome desta classe de operadores
Verdade se esta classe de operadores for a classe padrão para opcintype pg_type.oid
Tipo de dado do índice, ou zero se for o mesmo que opcintype
A maior parte das informações que definem a classe de operadores na verdade não está na sua linha em pg_opclass, mas nas linhas associadas em pg_amop e pg_amproc. Estas linhas são consideradas como
sendo parte da definição da classe de operadores; não é diferente da maneira como uma relação é definida por uma única linha em pg_class, mais as linhas associadas em pg_attribute e outras tabelas.
43.23. pg_operator O catálogo pg_operator armazena informações sobre operadores. Veja o comando CREATE OPERATOR e a Seção 33.11 para obter detalhes sobre os parâmetros dos operadores. Tabela 43-23. Colunas do catálogo pg_operator Nome
Tipo
Referencia
Descrição
oprname
name
oprnamespace
oid
pg_namespace.oid
OID do espaço de nomes que contém este operador.
oprowner
int4
pg_shadow.usesysid
Dono do operador
oprkind
char
b = infix (“both”), l = prefix (“esquerda”), r = postfix (“direita”)
oprcanhash
bool
Este operador suporta junções hash
oprleft
oid
pg_type.oid
Tipo do operando esquerdo
oprright
oid
pg_type.oid
Tipo do operando direito
oprresult
oid
pg_type.oid
Tipo do resultado
oprcom
oid
pg_operator.oid
Comutador deste operador, se houver algum
oprnegate
oid
pg_operator.oid
Negador deste operador, se houver algum
Nome do operador
942
Nome
Tipo
Referencia
Descrição
oprlsortop
oid
pg_operator.oid
Se este operador suportar junções por mesclagem (merge), o operador que ordena o tipo do operando à esquerda (L
oprrsortop
oid
pg_operator.oid
Se este operador suportar junções por mesclagem, o operador que ordena o tipo do operando à direita (R
oprltcmpop
oid
pg_operator.oid
Se este operador suportar junções por mesclagem, o operador “menor-que” que compara os tipos de operando à esquerda e à direita (L
oprgtcmpop
oid
pg_operator.oid
Se este operador suportar junções por mesclagem, o operador “maior-que” que compara os tipos de operando à esquerda e à direita (L>R).
oprcode
regproc
pg_proc.oid
Função que implementa este operador
oprrest
regproc
pg_proc.oid
Função estimadora de seletividade da restrição para este operador
oprjoin
regproc
pg_proc.oid
Função estimadora de seletividade da junção para este operador
As colunas não utilizadas contêm zero, por exemplo oprleft é zero para operadores de prefixo.
43.24. pg_proc O catálogo pg_proc armazena informações sobre as funções (ou procedimentos). A descrição do comando CREATE FUNCTION e a Seção 33.3 contêm mais informações sobre o significado de algumas colunas. A tabela contém dados para funções de agregação assim como para funções simples. Se proisagg for verdade, deve existir uma linha correspondente em pg_aggregate. Tabela 43-24. Colunas do catálogo pg_proc Nome
Tipo
Referencia
Descrição
proname
name
pronamespace
oid
pg_namespace.oid
OID do espaço de nomes que contém esta função.
proowner
int4
pg_shadow.usesysid
Dono da função
prolang
oid
pg_language.oid
Linguagem de implementação ou interface de chamada desta função
proisagg
bool
Verdade se a função for uma função de agregação
prosecdef
bool
Verdade se a função for uma função definidora de segurança (ou seja, uma função “setuid”)
proisstrict
bool
Verdade se a função retorna nulo quando algum argumento de chamada é nulo. Neste caso, na verdade, a função nem vai ser chamada. As funções que não são “estritas” devem estar preparadas para tratar entradas nulas.
Nome da função
943
Nome
Tipo
Referencia
Descrição
proretset
bool
Verdade se a função retorna um conjunto (ou seja, vários valores do tipo de dado especificado)
provolatile
char
provolatile informa se o resultado da função depende apenas de seus argumentos de entrada, ou é afetada por fatores externos. Vale i para as funções “imutáveis”, que sempre retornam o mesmo resultado para as mesmas entradas. Vale s para as funções “estáveis”, cujos resultados (para entradas fixas) não mudam dentro de uma mesma varredura. Vale v para as funções “voláteis”, cujos resultados podem mudar a qualquer instante (Também deve ser utilizado v para as funções com efeitos colaterais, para que as chamadas às mesmas não sejam otimizadas).
pronargs
int2
Número de argumentos
prorettype
oid
pg_type.oid
Tipo de dado do valor retornado
proargtypes
oidvector
pg_type.oid
Matriz contendo os tipos de dado dos argumentos da função
prosrc
text
Informa ao tratador da função como chamar a função. Podendo ser o código fonte da função para as linguagens interpretadas, o símbolo de ligação, o nome do arquivo, ou qualquer outra coisa, dependendo da implementação da convenção de chamada da linguagem.
probin
bytea
Informações adicionais sobre como chamar a função. Novamente, a interpretação é específica da linguagem.
proacl
aclitem[]
Privilégios de acesso
prosrc contém o nome da função na linguagem C (símbolo de ligação) para as funções compiladas, tanto nativas quanto carregadas dinamicamente. Para todos os outros tipos de linguagem, prosrc contém o texto do código fonte da função. probin não é utilizado, exceto para as funções C carregadas dinamicamente, para as quais fornece o nome do arquivo de biblioteca compartilhada contendo a função.
43.25. pg_rewrite O catálogo pg_rewrite armazena regras de reescrita para tabelas e visões. Tabela 43-25. Colunas do catálogo pg_rewrite Nome
Tipo
rulename
name
ev_class
oid
ev_attr
int2
ev_type
char
Referencia
Descrição Nome da regra
pg_class.oid
Tabela para a qual esta regra se destina Coluna para a qual esta regra se destina (atualmente sempre zero para indicar toda a tabela) Tipo de evento para o qual esta regra se destina: 1 = SELECT, 2 = UPDATE, 3 = INSERT, 4 = DELETE.
is_instead
bool
Verdade se a regra for uma regra INSTEAD
944
Nome
Tipo
ev_qual
text
ev_action
text
Referencia
Descrição Árvore de expressão (na forma de uma representação nodeToString()) para a condição de qualificação da regra. Árvore de comando (na forma de uma representação nodeToString()) para a ação da regra.
Nota: pg_class.relhasrules deve ser verdade quando a tabela possui alguma regra neste catálogo.
43.26. pg_shadow O catálogo pg_shadow contém informações sobre usuários do banco de dados. Este nome vem do fato desta tabela não poder ser lida pelo público, uma vez que contém senhas. pg_user é uma visão de pg_shadow que pode ser lida pelo público, uma vez que esconde o campo senha. Capítulo 17 contém informações detalhadas sobre a gerência de usuários e de privilégios. Uma vez que as identidades dos usuários valem para todo o agrupamento, pg_shadow é compartilhado por todos os bancos de dados do agrupamento: existe apenas uma instância de pg_shadow por agrupamento, e não uma por banco de dados. Tabela 43-26. Colunas do catálogo pg_shadow Nome
Tipo
Referencia
Descrição
usename
name
Nome do usuário
usesysid
int4
Id do usuário (número arbitrário utilizado para referenciar este usuário)
usecreatedb
bool
Se for verdade o usuário pode criar bancos de dados
usesuper
bool
Se for verdade o usuário é um superusuário
usecatupd
bool
Se for verdade o usuário pode atualizar os catálogos do sistema (Mesmo os superusuários não podem atualizar os catálogos do sistema a não ser que esta coluna seja verdade).
passwd
text
Senha
valuntil
abstime
Tempo de expiração da conta (usado apenas para autenticação da senha)
useconfig
text[]
Padrões da sessão para as variáveis de configuração em tempo de execução
43.27. pg_statistic O catálogo pg_statistic armazena dados estatísticos sobre o conteúdo do banco de dados. As entradas são criadas pelo comando ANALYZE e depois utilizadas pelo planejador de comandos. Existe uma entrada para cada coluna de tabela que foi analisada. Observe que todos os dados estatísticos são inerentemente aproximados, mesmo assumindo que estejam atualizados. Uma vez que tipos de estatística diferentes podem ser apropriados para tipos de dado diferentes, o catálogo pg_statistic foi projetado para não assumir muito sobre que tipo de estatística será armazenado. Somente estatísticas extremamente gerais (como nulidade) recebem colunas dedicadas em pg_statistic. Tudo mais é armazenado em “encaixes” (slots), que são grupos de colunas associadas cujo conteúdo é identificado por um
código
numérico
em
uma
das
colunas
do
encaixe.
Para
obter
mais
informações
veja
src/include/catalog/pg_statistic.h. pg_statistic não deve poder ser vista pelo público, uma vez que mesmo informações estatísticas sobre o conteúdo da tabela podem ser consideradas confidenciais (Exemplo: os valores mínimo e máximo da coluna
945
salário podem ser bastante interessantes). pg_stats é uma visão publicamente legível sobre pg_statistic que mostra apenas informações sobre as tabelas que podem ser lidas pelo usuário corrente. Tabela 43-27. Colunas do catálogo pg_statistic Nome
Tipo
Referencia
Descrição
starelid
oid
pg_class.oid
Tabela que a coluna descrita pertence
staattnum
int2
pg_attribute.attnum
Número da coluna descrita
stanullfrac
float4
Fração das entradas nulas na coluna
stawidth
int4
Largura armazenada média, em bytes, das entradas não-nulas
stadistinct
float4
Número de valores de dado não-nulos distintos na coluna. Um valor maior do que zero é o número real de valores distintos. Um valor menor do que zero é o negativo da fração do número de linhas da tabela (por exemplo, uma coluna em que cada valor aparece duas vezes, em média, pode ser representada por stadistinct = -0.5). O valor zero significa que o número de valores distintos é desconhecido.
stakindN
int2
Código numérico indicando o tipo de estatística armazenada no N-ésimo “encaixe” da linha de pg_statistic.
staopN
oid
stanumbersN
float4[]
Estatísticas numéricas do tipo apropriado para o N-ésimo “encaixe”, ou nulo se o tipo do encaixe não envolve valores numéricos.
stavaluesN
anyarray
Valores dos dados da coluna, do tipo apropriado, para o N-ésimo “encaixe”, ou nulo se o tipo do encaixe não armazena nenhum valor de dado. Cada valor do elemento da matriz é do tipo de dado específico da coluna, portanto não há como definir o tipo de dado desta coluna de forma mais específica que anyarray.
pg_operator.oid
Operador utilizado para derivar as estatísticas armazenadas no N-ésimo “encaixe”. Por exemplo, em um encaixe tipo histograma é mostrado o operador < que define a ordem de classificação dos dados.
43.28. pg_trigger O catálogo pg_trigger armazena os gatilhos das tabelas. Veja o comando CREATE TRIGGER para obter mais informações.
946
Tabela 43-28. Colunas do catálogo pg_trigger Nome
Tipo
Referencia
Descrição
tgrelid
oid
pg_class.oid
Tabela onde o gatilho se encontra
tgname
name
tgfoid
oid
tgtype
int2
Máscara de bits identificando as condições do gatilho
tgenabled
bool
Verdade se o gatilho estiver habilitado (atualmente não é verificado em nenhum lugar onde deveria ser, portanto desabilitar o gatilho definindo esta coluna como falso não funciona de forma confiável)
tgisconstraint
bool
Verdade se o gatilho implementa uma restrição de integridade referencial
tgconstrname
name
Nome da restrição de integridade referencial
tgconstrrelid
oid
tgdeferrable
bool
Verdade se for postergável
tginitdeferred
bool
Verdade se for inicialmente postergado
tgnargs
int2
Número de argumentos do tipo cadeia de caracteres passados para a função de gatilho
tgattr
int2vector
Atualmente não é utilizado
tgargs
bytea
Argumentos do tipo cadeia de caracteres passados para o gatilho, todos terminados por nulo
Nome do gatilho (deve ser único entre os gatilhos da mesma tabela) pg_proc.oid
pg_class.oid
Função a ser chamada
Tabela referenciada pela restrição de integridade referencial
Nota: pg_class.reltriggers precisa corresponder às entradas nesta tabela.
43.29. pg_type O catálogo pg_type armazena informações sobre tipos de dado Os tpos base (tipos escalares) são criados pelo comando CREATE TYPE. Um tipo composto é criado, automaticamente, para cada tabela do banco de dados, para representar a estrutura da linha da tabela. Também é possível criar tipos compostos com o comando CREATE TYPE AS, e domínios com o comando CREATE DOMAIN. Tabela 43-29. Colunas do catálogo pg_type Nome
Tipo
Referencia
typname
name
typnamespace
oid
pg_namespace.oid
typowner
int4
pg_shadow.usesysid
typlen
int2
Descrição Nome do tipo de dado OID do espaço de nomes que contém este tipo. Dono do tipo Para um tipo de tamanho fixo, typlen é o número de bytes na representação interna do tipo. Para um tipo de tamanho variável, typlen é negativo. -1 indica um tipo “varlena” (aquele que tem a palavra comprimento), -2 indica uma cadeia de caracteres C terminada por nulo.
947
Nome
Tipo
typbyval
bool
Referencia
Descrição typbyval determina se as rotinas internas
passam o valor deste tipo por valor ou por referência. É melhor typbyval ser falso se typlen não for igual a 1, 2 ou 4 (ou 8 nas máquinas com Datum igual a 8 bytes). Os tipos de comprimento variável são sempre passados por referência. Observe que typbyval pode ser falso mesmo quando o comprimento permite passar por valor; atualmente isto é verdade para o tipo float4, por exemplo. typtype
char
typtype vale b para um tipo base, c para um tipo composto (ou seja, o tipo de uma linha de tabela), d para um domínio ou p para um pseudotipo. Veja também typrelid e typbasetype.
typisdefined
bool
Verdade se o tipo for definido, falso se for apenas uma entrada para um tipo que ainda não está definido. Quando typisdefined é falso, não se pode confiar em nada além do nome do tipo, espaço de nomes e o OID.
typdelim
char
Caractere que separa dois valores deste tipo ao analisar entrada na forma de matriz. Observe que o delimitador é associado ao tipo de dado do elemento, e não ao tipo de dado da matriz
typrelid
oid
pg_class.oid
Se for um tipo composto (veja typtype), então esta coluna aponta para a entrada em pg_class que define a tabela correspondente (Para um tipo composto independente, a entrada pg_class não representa na verdade uma tabela, mas é necessária de qualquer maneira para fazer vínculo com as entradas do tipo em pg_attribute). Zero para os tipos base.
typelem
oid
pg_type.oid
Se typelem não for 0, então identifica outra linha em pg_type. O tipo corrente pode ser acessado como qualquer matriz produzindo valores do tipo typelem. Um tipo matriz “de verdade” é de comprimento variável (typlen = -1), mas alguns tipos de comprimento fixo (typlen > 0) também possuem typelem diferente de zero como, por exemplo, name e oidvector. Se um tipo de tamanho fixo possui typelem, então sua representação interna deve ser alguma quantidade de valores do tipo de dado typelem com nenhum outro dado. Os tipos matriz de comprimento variável possuem um cabeçalho definido pelas subrotinas da matriz.
typinput
regproc
pg_proc.oid
Função de conversão da entrada (formato texto)
typoutput
regproc
pg_proc.oid
Função de conversão da saída (formato texto)
typreceive
regproc
pg_proc.oid
Função de conversão da entrada (formato binário), ou 0 se nenhuma
948
Nome
Tipo
Referencia
Descrição
typsend
regproc
pg_proc.oid
Função de conversão da saída (formato binário), ou 0 se nenhuma
typalign
char
typalign é o alinhamento requerido para armazenar um valor deste tipo. Se aplica ao armazenamento em disco, assim como a maioria das representações do valor dentro do PostgreSQL. Quando vários valores são armazenados consecutivamente, tal como na representação de uma linha completa no disco, um preenchimento é inserido antes do dado deste tipo para que comece na fronteira especificada. A referência de alinhamento é o início do primeiro dado na seqüência.
Os valores possíveis são: = alinhamento char, ou seja, nenhum alinhamento é necessário.
• c
= alinhamento short (2 bytes na maioria das máquinas).
• s
= alinhamento int (4 bytes na maioria das máquinas).
• i
= alinhamento double (8 bytes na maioria das máquinas, mas de nenhuma forma em todas).
• d
Nota: Para os tipos utilizados nas tabelas do sistema, é crítico que o tamanho e o alinhamento definidos em pg_type estejam de acordo com a forma como o compilador arruma a coluna na estrutura que representa a linha da tabela. typstorage
char
typstorage informa para os tipos varlena (aqueles com typlen = -1) se o tipo está preparado para o fatiamento (toasting), e qual deve ser a estratégia padrão para os atributos deste tipo. Os valores possíveis são: • p:
O valor deve ser sempre armazenado direto.
• e:
O valor pode ser armazenado em uma relação “secundária” (se a relação possuir uma, veja pg_class.reltoastrelid).
• m:
O valor pode ser armazenado em-linha comprimido.
• x:
O valor pode ser armazenado em-linha comprimido, ou posto no armazenamento “secundário”.
Observe que as colunas do tipo m também podem ser movidas para o armazenamento secundário, mas somente como último recurso (Primeiro são movidas as colunas do tipo e e do tipo x).
949
Nome
Tipo
typnotnull
bool
typbasetype
oid
Referencia
Descrição typnotnull representa uma restrição de nãonulo no tipo. Utilizado apenas em domínios.
pg_type.oid
Se for um domínio (veja typtype), então typbasetype identifica o tipo em que é baseado. Zero se não for um domínio.
typtypmod
int4
Os domínios utilizam typtypmod para registrar o typmod a ser aplicado ao seu tipo base (-1 se o tipo base não utilizar um typmod). -1 se este tipo não for um domínio.
typndims
int4
typndims é o número de dimensões da matriz para o domínio que é uma matriz (ou seja, typbasetype é um tipo matriz; o typelem do domínio corresponde ao tipo base de typelem). Zero para os tipos que não forem domínios matriz.
typdefaultbin
text
Se typdefaultbin não for nulo, é a representação nodeToString() da expressão padrão para o tipo. Utilizado apenas para domínios.
typdefault
text
typdefault é nulo se o tipo não tiver valor padrão associado. Se typdefaultbin não for nulo, typdefault deve conter uma versão humanamente legível da expressão padrão representada por typdefaultbin. Se typdefaultbin for nulo e typdefault não for, então typdefault é a representação externa do valor padrão do tipo, o qual pode ser introduzido no conversor de entrada do tipo para produzir uma constante.
43.30. Visões do sistema Além dos catálogos do sistema, o PostgreSQL disponibiliza várias visões nativas. As visões do sistema fornecem um acesso conveniente a algumas consultas aos catálogos do sistema utilizadas com freqüência. Algumas destas visões também fornecem acesso ao estado interno do servidor. A Tabela 43-30 lista as visões do sistema descritas neste capítulo. A documentação mais detalhadas de cada visão vem a seguir. Existem algumas visões adicionais que fornecem acesso aos resultados do coletor de estatísticas; estão descritas na Tabela 23-1. O esquema de informações (Capítulo 32) provê um conjunto alternativo de visões, que se sobrepõem às funcionalidades das visões do sistema. Uma vez que o esquema de informações faz parte do padrão SQL, enquanto as visões aqui descritas são específicas do PostgreSQL, geralmente é melhor utilizar o esquema de informações quando este fornece todas as informações necessárias. Exceto quando indicado, todas as visões descritas aqui são somente para leitura.
950
Tabela 43-30. Visões do sistema Nome da visão
Finalidade
pg_indexes
índices
pg_locks
bloqueios mantidos correntemente
pg_rules
regras
pg_settings
definições dos parâmetros
pg_stats
estatísticas do planejador
pg_tables
tabelas
pg_user
usuários do banco de dados
pg_views
visões
43.31. pg_indexes A visão pg_indexes fornece acesso a informações úteis sobre cada índice do banco de dados. Tabela 43-31. Colunas do catálogo pg_indexes Nome
Tipo
Referencia
Descrição
schemaname
name
pg_namespace.nspname
Nome do esquema que contém a tabela e o índice
tablename
name
pg_class.relname
Nome da tabela para a qual o índice se destina
indexname
name
pg_class.relname
Nome do índice
indexdef
text
Definição do índice (o comando de criação reconstruído)
43.32. pg_locks A visão pg_locks fornece acesso a informações sobre bloqueios dentro do servidor de banco de dados mantidos por transações em aberto. Veja no Capítulo 12 mais explicações sobre bloqueio. pg_locks contém uma linha por objeto bloqueável ativo, modo de bloqueio requisitado e a transação
relevante. Assim, o mesmo objeto bloqueável pode aparecer várias vezes, se várias transações estiverem mantendo ou aguardando por bloqueios no mesmo. Entretanto, um objeto que atualmente não possui nenhum bloqueio atuando sobre o mesmo não é mostrado. Um objeto bloqueável é uma relação (por exemplo, uma tabela), ou um ID de transação. Observe que esta visão inclui apenas bloqueios no nível de tabela, Se a transação estiver aguardando por um bloqueio no nível de linha, é mostrada na visão como aguardando pelo ID da transação que está atualmente mantendo o bloqueio na linha. Tabela 43-32. Colunas do catálogo pg_locks Nome
Tipo
Referencia
Descrição
relation
oid
pg_class.oid
OID da relação bloqueada, ou NULL se o objeto bloqueável for um ID de transação.
database
oid
pg_database.oid
OID do banco de dados em que a relação bloqueada se encontra, ou zero se a relação bloqueada for uma tabela compartilhada globalmente, ou NULL se o objeto bloqueável for um ID de transação.
951
Nome
Tipo
Referencia
Descrição
transaction
xid
ID da transação, ou NULL se o objeto bloqueável for uma relação.
pid
integer
ID de processo do processo servidor mantendo ou aguardando pelo bloqueio
mode
text
Nome do modo de bloqueio mantido ou desejado por este processo (veja a Seção 12.3.1)
granted
boolean
Verdade se o bloqueio está sendo mantido, falso se o bloqueio está sendo aguardado
granted é verdade em uma linha representando um bloqueio mantido pela sessão indicada. Falso indica que esta sessão está atualmente aguardando para obter o bloqueio, o que implica que alguma outra sessão está mantendo um modo de bloqueio conflitante no mesmo objeto bloqueável. A sessão aguardando dorme até que o bloqueio seja liberado( ou até uma situação de impasse seja detectada). Uma única sessão pode estar aguardando para obter no máximo um único bloqueio em um determinado instante.
Cada transação mantém um bloqueio exclusivo em seu ID de transação por toda a sua duração. Se uma transação descobrir que é necessário aguardar especificamente por outra transação, ela fará isto tentando obter um bloqueio compartilhado no ID de transação da outra transação. Somente será bem-sucedido quando a outra transação terminar e liberar seus bloqueios. Quando a visão pg_locks é acessada, as estruturas de dado internas do gerenciador de bloqueios são momentaneamente bloqueadas, e é feita uma cópia para ser mostrada pela visão. Isto garante que a visão produz um conjunto de resultados coerente, enquanto que não bloqueia as operações normais do gerenciador de bloqueios por mais tempo que o necessário. Apesar disso, pode haver algum impacto no desempenho do banco de dados se esta visão for consultada freqüentemente. pg_locks provê uma visão global de todos os bloqueios no agrupamento de bancos de dados, e não apenas aqueles relevantes para o banco de dados corrente. Embora possa ser feita uma junção de sua coluna relation com pg_class.oid para identificar relações bloqueadas, isto só funciona de forma correta para as relações no banco de dados corrente (aqueles em que a coluna database é o OID do banco de dados corrente ou zero).
Se o coletor de estatísticas estiver habilitado, pode ser feita a junção da coluna pid com a coluna procpid da visão pg_stat_activity, para obter mais informações sobre a sessão mantendo ou aguardando para manter o bloqueio.
43.33. pg_rules A visão pg_rules fornece acesso a informações úteis sobre regras de reescrita de comandos. Tabela 43-33. Colunas do catálogo pg_rules Nome
Tipo
Referencia
Descrição
schemaname
name
pg_namespace.nspname
Nome do esquema que contém a tabela
tablename
name
pg_class.relname
Nome da tabela para a qual esta regra está definida
rulename
name
pg_rewrite.rulename
Nome da regra
definition
text
Definição da regra (o comando de criação reconstruído)
A visão pg_rules exclui as regras ON SELECT da visão; estas podem ser vistas em pg_views.
952
43.34. pg_settings A visão pg_settings fornece acesso a parâmetros do servidor em tempo de execução. Essencialmente é uma interface alternativa aos comandos SHOW e SET. Também fornece acesso a alguns fatos sobre cada parâmetro não disponíveis no SHOW, como os valores mínimo e máximo. Tabela 43-34. Colunas do catálogo pg_settings Nome
Tipo
Referencia
Descrição
name
text
Nome do parâmetro de configuração em tempo de execução
setting
text
Valor corrente do parâmetro
context
text
Contexto requerido para definir o valor do parâmetro
vartype
text
Tipo do parâmetro (bool, integer, real ou string).
source
text
Origem do valor corrente do parâmetro
min_val
text
Valor mínimo permitido para o parâmetro (NULL para valores não numéricos)
max_val
text
Valor máximo permitido para o parâmetro (NULL para valores não numéricos)
A visão pg_settings não aceita inserções ou exclusões, mas aceita atualizações. Um UPDATE aplicado a uma linha de pg_settings equivale a executar o comando SET no parâmetro com este nome. A mudança somente afeta o valor utilizado pela sessão corrente. Se um UPDATE for executado dentro de uma transação que seja interrompida posteriormente, o efeito do comando UPDATE desaparece quando a transação é desfeita. Uma vez que a transação envolvente seja efetivada, os efeitos persistem até o fim da sessão, a não ser que seja substituído por outro UPDATE ou SET.
43.35. pg_stats A visão pg_stats fornece acesso a informações armazenadas no catálogo pg_statistic. Esta visão permite acessar somente as linhas de pg_statistic que correspondem às tabelas que o usuário tem permissão para ler e, portanto, é seguro permitir acesso público de leitura a esta visão. A visão pg_stats também foi projetada para mostrar as informações em uma forma mais facilmente lida do que o catálogo subjacente; ao custo de seu esquema ter que ser estendido sempre que novos tipos de encaixe são definidos em pg_statistic. Tabela 43-35. Colunas do catálogo pg_stats Nome
Tipo
Referencia
Descrição
schemaname
name
pg_namespace.nspname
Nome do esquema que contém a tabela
tablename
name
pg_class.relname
Nome da tabela
attname
name
pg_attribute.attname
Nome da coluna descrita por esta linha
null_frac
real
Fração das entradas nulas na coluna
avg_width
integer
Largura média em bytes das entradas da coluna
n_distinct
real
Se for maior que zero, o número estimado de valores distintos na coluna. Se for menor que zero, o negativo do número de valores distintos divididos pelo número de linhas (A forma negativa é utilizada
953
Nome
Tipo
Referencia
Descrição quando o ANALYZE acredita que o número de valores distintos deve aumentar quando a tabela crescer; a forma positiva é utilizada quando a coluna parece ter um número fixo de valores possíveis). Por exemplo, -1 indica uma coluna com restrição de unicidade, onde o número de valores distintos é igual ao número de linhas.
most_common_vals
anyarray
Lista dos valores mais comuns da coluna (NULL se nenhum valor parecer ser mais comum que os outros)
most_common_freqs
real[]
Lista das freqüências dos valores mais comuns, ou seja, o número de ocorrências de cada um deles dividido pelo número total de linhas. (NULL quando most_common_vals também é nulo)
histogram_bounds
anyarray
Lista dos valores que dividem os valores das colunas em grupos com populações aproximadamente iguais. Os valores em most_common_vals, se estiverem presentes, são omitidos no cálculo deste histograma (Esta coluna é NULL se o tipo de dado da coluna não possuir o operador <, ou a lista most_common_vals englobar toda as linhas da tabela)
correlation
real
Correlação estatística entre a ordenação física das linhas e a ordenação lógica dos valores da coluna. Varia de -1 a +1. Quando o valor estiver próximo de -1 ou de +1, uma varredura de índice na coluna será estimada como mais barata do que quando estiver próximo de zero, devido a redução de acesso randômico no disco (Esta coluna é NULL quando o tipo de dado da coluna não possui um operador <)
O número máximo de entradas nas matrizes most_common_vals e histogram_bounds podem ser definidos coluna por coluna utilizando o comando ALTER TABLE SET STATISTICS, ou globalmente definindo o parâmetro em tempo de execução default_statistics_target.
43.36. pg_tables A visão pg_tables fornece acesso a informações úteis sobre todas as tabelas do banco de dados.
954
Tabela 43-36. Colunas do catálogo pg_tables Nome
Tipo
Referencia
Descrição
schemaname
name
pg_namespace.nspname
Nome do esquema que contém a tabela
tablename
name
pg_class.relname
Nome da tabela
tableowner
name
pg_shadow.usename
Nome do dono da tabela
hasindexes
boolean
pg_class.relhasindex
Verdade se a tabela possui (ou possuía recentemente) algum índice
hasrules
boolean
pg_class.relhasrules
Verdade se a tabela possui regras
hastriggers
boolean
pg_class.reltriggers
Verdade se a tabela possui gatilhos
43.37. pg_user A visão pg_user fornece acesso a informações sobre usuários do banco de dados. É simplesmente uma visão de pg_shadow que pode ser lida pelo público por esconder o campo senha. Tabela 43-37. Colunas do catálogo pg_user Nome
Tipo
Referencia
Descrição
usename
name
Nome do usuário
usesysid
int4
Id do usuário (número arbitrário utilizado para fazer referência a este usuário)
usecreatedb
bool
Se for verdade o usuário pode criar bancos de dados
usesuper
bool
Se for verdade o usuário é um superusuário
usecatupd
bool
Se for verdade o usuário pode atualizar os catálogos do sistema (Mesmo os superusuários não podem atualizar os catálogos do sistema a menos que esta coluna seja verdade).
passwd
text
Não é a senha (sempre mostrado como ********)
valuntil
abstime
Tempo de expiração da conta (utilizado apenas para autenticação da senha)
useconfig
text[]
Padrões da sessão para as variáveis de configuração em tempo de execução
43.38. pg_views A visão pg_views fornece acesso a informações úteis sobre todas as visões do banco de dados. Tabela 43-38. Colunas do catálogo pg_views Nome
Tipo
Referencia
Descrição
schemaname
name
pg_namespace.nspname
Nome do esquema que contém a visão
viewname
name
pg_class.relname
Nome da visão
viewowner
name
pg_shadow.usename
Nome do dono da visão
definition
text
Definição da visão (o comando SELECT reconstruído)
955
Notas 1. No diretório do tutorial existe o arquivo syscat.sql (./syscat.sql) contendo várias consultas interessantes aos catálogos do sistema. (N. do T.)
956
Capítulo 44. Frontend/Backend Protocol PostgreSQL uses a message-based protocol for communication between frontends and backends (clients and servers). The protocol is supported over TCP/IP and also over Unix-domain sockets. Port number 5432 has been registered with IANA as the customary TCP port number for servers supporting this protocol, but in practice any non-privileged port number may be used. This document describes version 3.0 of the protocol, implemented in PostgreSQL 7.4 and later. For descriptions of the earlier protocol versions, see previous releases of the PostgreSQL documentation. A single server can support multiple protocol versions. The initial startup-request message tells the server which protocol version the client is attempting to use, and then the server follows that protocol if it is able. Higher level features built on this protocol (for example, how libpq passes certain environment variables when the connection is established) are covered elsewhere. In order to serve multiple clients efficiently, the server launches a new “backend” process for each client. In the current implementation, a new child process is created immediately after an incoming connection is detected. This is transparent to the protocol, however. For purposes of the protocol, the terms “backend” and “server” are interchangeable; likewise “frontend” and “client” are interchangeable.
44.1. Visão geral The protocol has separate phases for startup and normal operation. In the startup phase, the frontend opens a connection to the server and authenticates itself to the satisfaction of the server. (This might involve a single message, or multiple messages depending on the authentication method being used.) If all goes well, the server then sends status information to the frontend, and finally enters normal operation. Except for the initial startuprequest message, this part of the protocol is driven by the server. During normal operation, the frontend sends queries and other commands to the backend, and the backend sends back query results and other responses. There are a few cases (such as NOTIFY) wherein the backend will send unsolicited messages, but for the most part this portion of a session is driven by frontend requests. Termination of the session is normally by frontend choice, but can be forced by the backend in certain cases. In any case, when the backend closes the connection, it will roll back any open (incomplete) transaction before exiting. Within normal operation, SQL commands can be executed through either of two sub-protocols. In the “simple query” protocol, the frontend just sends a textual query string, which is parsed and immediately executed by the backend. In the “extended query” protocol, processing of queries is separated into multiple steps: parsing, binding of parameter values, and execution. This offers flexibility and performance benefits, at the cost of extra complexity. Normal operation has additional sub-protocols for special operations such as COPY.
44.1.1. Messaging Overview All communication is through a stream of messages. The first byte of a message identifies the message type, and the next four bytes specify the length of the rest of the message (this length count includes itself, but not the message-type byte). The remaining contents of the message are determined by the message type. For historical reasons, the very first message sent by the client (the startup message) has no initial message-type byte. To avoid losing synchronization with the message stream, both servers and clients typically read an entire message into a buffer (using the byte count) before attempting to process its contents. This allows easy recovery if an error is detected while processing the contents. In extreme situations (such as not having enough memory to buffer the message), the receiver may use the byte count to determine how much input to skip before it resumes reading messages. Conversely, both servers and clients must take care never to send an incomplete message. This is commonly done by marshaling the entire message in a buffer before beginning to send it. If a communications failure
957
occurs partway through sending or receiving a message, the only sensible response is to abandon the connection, since there is little hope of recovering message-boundary synchronization.
44.1.2. Extended Query Overview In the extended-query protocol, execution of SQL commands is divided into multiple steps. The state retained between steps is represented by two types of objects: prepared statements and portals. A prepared statement represents the result of parsing, semantic analysis, and planning of a textual query string. A prepared statement is not necessarily ready to execute, because it may lack specific values for parameters. A portal represents a ready-to-execute or already-partially-executed statement, with any missing parameter values filled in. (For SELECT statements, a portal is equivalent to an open cursor, but we choose to use a different term since cursors don't handle non-SELECT statements.) The overall execution cycle consists of a parse step, which creates a prepared statement from a textual query string; a bind step, which creates a portal given a prepared statement and values for any needed parameters; and an execute step that runs a portal's query. In the case of a query that returns rows (SELECT, SHOW, etc), the execute step can be told to fetch only a limited number of rows, so that multiple execute steps may be needed to complete the operation. The backend can keep track of multiple prepared statements and portals (but note that these exist only within a session, and are never shared across sessions). Existing prepared statements and portals are referenced by names assigned when they were created. In addition, an “unnamed” prepared statement and portal exist. Although these behave largely the same as named objects, operations on them are optimized for the case of executing a query only once and then discarding it, whereas operations on named objects are optimized on the expectation of multiple uses.
44.1.3. Formats and Format Codes Data of a particular data type might be transmitted in any of several different formats. As of PostgreSQL 7.4 the only supported formats are “text” and “binary”, but the protocol makes provision for future extensions. The desired format for any value is specified by a format code. Clients may specify a format code for each transmitted parameter value and for each column of a query result. Text has format code zero, binary has format code one, and all other format codes are reserved for future definition. The text representation of values is whatever strings are produced and accepted by the input/output conversion functions for the particular data type. In the transmitted representation, there is no trailing null character; the frontend must add one to received values if it wants to process them as C strings. (The text format does not allow embedded nulls, by the way.) Binary representations for integers use network byte order (most significant byte first). For other data types consult the documentation or source code to learn about the binary representation. Keep in mind that binary representations for complex data types may change across server versions; the text format is usually the more portable choice.
44.2. Message Flow This section describes the message flow and the semantics of each message type. (Details of the exact representation of each message appear in Seção 44.4.) There are several different sub-protocols depending on the state of the connection: start-up, query, function call, COPY, and termination. There are also special provisions for asynchronous operations (including notification responses and command cancellation), which can occur at any time after the start-up phase.
44.2.1. Start-Up To begin a session, a frontend opens a connection to the server and sends a startup message. This message includes the names of the user and of the database the user wants to connect to; it also identifies the particular protocol version to be used. (Optionally, the startup message can include additional settings for run-time parameters.) The server then uses this information and the contents of its configuration files (such as pg_hba.conf) to determine whether the connection is provisionally acceptable, and what additional authentication is required (if any).
958
The server then sends an appropriate authentication request message, to which the frontend must reply with an appropriate authentication response message (such as a password). In principle the authentication request/response cycle could require multiple iterations, but none of the present authentication methods use more than one request and response. In some methods, no response at all is needed from the frontend, and so no authentication request occurs. The authentication cycle ends with the server either rejecting the connection attempt (ErrorResponse), or sending AuthenticationOk. The possible messages from the server in this phase are: ErrorResponse The connection attempt has been rejected. The server then immediately closes the connection. AuthenticationOk The authentication exchange is successfully completed. AuthenticationKerberosV4 The frontend must now take part in a Kerberos V4 authentication dialog (not described here, part of the Kerberos specification) with the server. If this is successful, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. AuthenticationKerberosV5 The frontend must now take part in a Kerberos V5 authentication dialog (not described here, part of the Kerberos specification) with the server. If this is successful, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. AuthenticationCleartextPassword The frontend must now send a PasswordMessage containing the password in clear-text form. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. AuthenticationCryptPassword The frontend must now send a PasswordMessage containing the password encrypted via crypt(3), using the 2-character salt specified in the AuthenticationCryptPassword message. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. AuthenticationMD5Password The frontend must now send a PasswordMessage containing the password encrypted via MD5, using the 4-character salt specified in the AuthenticationMD5Password message. If this is the correct password, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. AuthenticationSCMCredential This response is only possible for local Unix-domain connections on platforms that support SCM credential messages. The frontend must issue an SCM credential message and then send a single data byte. (The contents of the data byte are uninteresting; it's only used to ensure that the server waits long enough to receive the credential message.) If the credential is acceptable, the server responds with an AuthenticationOk, otherwise it responds with an ErrorResponse. If the frontend does not support the authentication method requested by the server, then it should immediately close the connection. After having received AuthenticationOk, the frontend must wait for further messages from the server. In this phase a backend process is being started, and the frontend is just an interested bystander. It is still possible for the startup attempt to fail (ErrorResponse), but in the normal case the backend will send some ParameterStatus messages, BackendKeyData, and finally ReadyForQuery. During this phase the backend will attempt to apply any additional run-time parameter settings that were given in the startup message. If successful, these values become session defaults. An error causes ErrorResponse and exit.
959
The possible messages from the backend in this phase are: BackendKeyData This message provides secret-key data that the frontend must save if it wants to be able to issue cancel requests later. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message. ParameterStatus This message informs the frontend about the current (initial) setting of backend parameters, such as client_encoding or DateStyle. The frontend may ignore this message, or record the settings for its
future use; see Seção 44.2.6 for more detail. The frontend should not respond to this message, but should continue listening for a ReadyForQuery message. ReadyForQuery Start-up is completed. The frontend may now issue commands. ErrorResponse Start-up failed. The connection is closed after sending this message. NoticeResponse A warning message has been issued. The frontend should display the message but continue listening for ReadyForQuery or ErrorResponse. The ReadyForQuery message is the same one that the backend will issue after each command cycle. Depending on the coding needs of the frontend, it is reasonable to consider ReadyForQuery as starting a command cycle, or to consider ReadyForQuery as ending the start-up phase and each subsequent command cycle.
44.2.2. Simple Query A simple query cycle is initiated by the frontend sending a Query message to the backend. The message includes an SQL command (or commands) expressed as a text string. The backend then sends one or more response messages depending on the contents of the query command string, and finally a ReadyForQuery response message. ReadyForQuery informs the frontend that it may safely send a new command. (It is not actually necessary for the frontend to wait for ReadyForQuery before issuing another command, but the frontend must then take responsibility for figuring out what happens if the earlier command fails and alreadyissued later commands succeed.) The possible response messages from the backend are: CommandComplete An SQL command completed normally. CopyInResponse The backend is ready to copy data from the frontend to a table; see Seção 44.2.5. CopyOutResponse The backend is ready to copy data from a table to the frontend; see Seção 44.2.5. RowDescription Indicates that rows are about to be returned in response to a SELECT, FETCH, etc query. The contents of this message describe the column layout of the rows. This will be followed by a DataRow message for each row being returned to the frontend. DataRow One of the set of rows returned by a SELECT, FETCH, etc query. EmptyQueryResponse An empty query string was recognized.
960
ErrorResponse An error has occurred. ReadyForQuery Processing of the query string is complete. A separate message is sent to indicate this because the query string may contain multiple SQL commands. (CommandComplete marks the end of processing one SQL command, not the whole string.) ReadyForQuery will always be sent, whether processing terminates successfully or with an error. NoticeResponse A warning message has been issued in relation to the query. Notices are in addition to other responses, i.e., the backend will continue processing the command. The response to a SELECT query (or other queries that return row sets, such as EXPLAIN or SHOW) normally consists of RowDescription, zero or more DataRow messages, and then CommandComplete. COPY to or from the frontend invokes special protocol as described in Seção 44.2.5. All other query types normally produce only a CommandComplete message. Since a query string could contain several queries (separated by semicolons), there might be several such response sequences before the backend finishes processing the query string. ReadyForQuery is issued when the entire string has been processed and the backend is ready to accept a new query string. If a completely empty (no contents other than whitespace) query string is received, the response is EmptyQueryResponse followed by ReadyForQuery. In the event of an error, ErrorResponse is issued followed by ReadyForQuery. All further processing of the query string is aborted by ErrorResponse (even if more queries remained in it). Note that this may occur partway through the sequence of messages generated by an individual query. In simple Query mode, the format of retrieved values is always text, except when the given command is a FETCH from a cursor declared with the BINARY option. In that case, the retrieved values are in binary format. The format codes given in the RowDescription message tell which format is being used. A frontend must be prepared to accept ErrorResponse and NoticeResponse messages whenever it is expecting any other type of message. See also Seção 44.2.6 concerning messages that the backend may generate due to outside events. Recommended practice is to code frontends in a state-machine style that will accept any message type at any time that it could make sense, rather than wiring in assumptions about the exact sequence of messages.
44.2.3. Extended Query The extended query protocol breaks down the above-described simple query protocol into multiple steps. The results of preparatory steps can be re-used multiple times for improved efficiency. Furthermore, additional features are available, such as the possibility of supplying data values as separate parameters instead of having to insert them directly into a query string. In the extended protocol, the frontend first sends a Parse message, which contains a textual query string, optionally some information about data types of parameter placeholders, and the name of a destination prepared-statement object (an empty string selects the unnamed prepared statement). The response is either ParseComplete or ErrorResponse. Parameter data types may be specified by OID; if not given, the parser attempts to infer the data types in the same way as it would do for untyped literal string constants. Nota: The query string contained in a Parse message cannot include more than one SQL statement; else a syntax error is reported. This restriction does not exist in the simple-query protocol, but it does exist in the extended protocol, because allowing prepared statements or portals to contain multiple commands would complicate the protocol unduly.
If successfully created, a named prepared-statement object lasts till the end of the current session, unless explicitly destroyed. An unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued. (Note that a simple Query message also destroys the unnamed statement.) Named prepared statements must be explicitly closed before they can be redefined by a Parse
961
message, but this is not required for the unnamed statement. Named prepared statements can also be created and accessed at the SQL command level, using PREPARE and EXECUTE. Once a prepared statement exists, it can be readied for execution using a Bind message. The Bind message gives the name of the source prepared statement (empty string denotes the unnamed prepared statement), the name of the destination portal (empty string denotes the unnamed portal), and the values to use for any parameter placeholders present in the prepared statement. The supplied parameter set must match those needed by the prepared statement. Bind also specifies the format to use for any data returned by the query; the format can be specified overall, or per-column. The response is either BindComplete or ErrorResponse. Nota: The choice between text and binary output is determined by the format codes given in Bind, regardless of the SQL command involved. The BINARY attribute in cursor declarations is irrelevant when using extended query protocol.
If successfully created, a named portal object lasts till the end of the current transaction, unless explicitly destroyed. An unnamed portal is destroyed at the end of the transaction, or as soon as the next Bind statement specifying the unnamed portal as destination is issued. (Note that a simple Query message also destroys the unnamed portal.) Named portals must be explicitly closed before they can be redefined by a Bind message, but this is not required for the unnamed portal. Named portals can also be created and accessed at the SQL command level, using DECLARE CURSOR and FETCH. Once a portal exists, it can be executed using an Execute message. The Execute message specifies the portal name (empty string denotes the unnamed portal) and a maximum result-row count (zero meaning “fetch all rows”). The result-row count is only meaningful for portals containing commands that return row sets; in other cases the command is always executed to completion, and the row count is ignored. The possible responses to Execute are the same as those described above for queries issued via simple query protocol, except that Execute doesn't cause ReadyForQuery to be issued. If Execute terminates before completing the execution of a portal (due to reaching a nonzero result-row count), it will send a PortalSuspended message; the appearance of this message tells the frontend that another Execute should be issued against the same portal to complete the operation. The CommandComplete message indicating completion of the source SQL command is not sent until the portal's execution is completed. Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended. At completion of each series of extended-query messages, the frontend should issue a Sync message. This parameterless message causes the backend to close the current transaction if it's not inside a BEGIN/COMMIT transaction block (“close” meaning to commit if no error, or roll back if error). Then a ReadyForQuery response is issued. The purpose of Sync is to provide a resynchronization point for error recovery. When an error is detected while processing any extended-query message, the backend issues ErrorResponse, then reads and discards messages until a Sync is reached, then issues ReadyForQuery and returns to normal message processing. (But note that no skipping occurs if an error is detected while processing Sync --- this ensures that there is one and only one ReadyForQuery sent for each Sync.) Nota: Sync does not cause a transaction block opened with BEGIN to be closed. It is possible to detect this situation since the ReadyForQuery message includes transaction status information.
In addition to these fundamental, required operations, there are several optional operations that can be used with extended-query protocol. The Describe message (portal variant) specifies the name of an existing portal (or an empty string for the unnamed portal). The response is a RowDescription message describing the rows that will be returned by executing the portal; or a NoData message if the portal does not contain a query that will return rows; or ErrorResponse if there is no such portal. The Describe message (statement variant) specifies the name of an existing prepared statement (or an empty string for the unnamed prepared statement). The response is a ParameterDescription message describing the parameters needed by the statement, followed by a RowDescription message describing the rows that will be returned when the statement is eventually executed (or a NoData message if the statement will not return rows). ErrorResponse is issued if there is no such prepared statement. Note that since Bind has not yet been issued, the
962
formats to be used for returned columns are not yet known to the backend; the format code fields in the RowDescription message will be zeroes in this case. Dica: In most scenarios the frontend should issue one or the other variant of Describe before issuing Execute, to ensure that it knows how to interpret the results it will get back.
The Close message closes an existing prepared statement or portal and releases resources. It is not an error to issue Close against a nonexistent statement or portal name. The response is normally CloseComplete, but could be ErrorResponse if some difficulty is encountered while releasing resources. Note that closing a prepared statement implicitly closes any open portals that were constructed from that statement. The Flush message does not cause any specific output to be generated, but forces the backend to deliver any data pending in its output buffers. A Flush must be sent after any extended-query command except Sync, if the frontend wishes to examine the results of that command before issuing more commands. Without Flush, messages returned by the backend will be combined into the minimum possible number of packets to minimize network overhead. Nota: The simple Query message is approximately equivalent to the series Parse, Bind, portal Describe, Execute, Close, Sync, using the unnamed prepared statement and portal objects and no parameters. One difference is that it will accept multiple SQL statements in the query string, automatically performing the bind/describe/execute sequence for each one in succession. Another difference is that it will not return ParseComplete, BindComplete, CloseComplete, or NoData messages.
44.2.4. Function Call The Function Call sub-protocol allows the client to request a direct call of any function that exists in the database's pg_proc system catalog. The client must have execute permission for the function. Nota: The Function Call sub-protocol is a legacy feature that is probably best avoided in new code. Similar results can be accomplished by setting up a prepared statement that does SELECT function($1, ...). The Function Call cycle can then be replaced with Bind/Execute.
A Function Call cycle is initiated by the frontend sending a FunctionCall message to the backend. The backend then sends one or more response messages depending on the results of the function call, and finally a ReadyForQuery response message. ReadyForQuery informs the frontend that it may safely send a new query or function call. The possible response messages from the backend are: ErrorResponse An error has occurred. FunctionCallResponse The function call was completed and returned the result given in the message. (Note that the Function Call protocol can only handle a single scalar result, not a rowtype or set of results.) ReadyForQuery Processing of the function call is complete. ReadyForQuery will always be sent, whether processing terminates successfully or with an error. NoticeResponse A warning message has been issued in relation to the function call. Notices are in addition to other responses, i.e., the backend will continue processing the command.
44.2.5. COPY Operations The COPY command allows high-speed bulk data transfer to or from the server. Copy-in and copy-out operations each switch the connection into a distinct sub-protocol, which lasts until the operation is completed. Copy-in mode (data transfer to the server) is initiated when the backend executes a COPY FROM STDIN SQL statement. The backend sends a CopyInResponse message to the frontend. The frontend should then send zero or more CopyData messages, forming a stream of input data. (The message boundaries are not required to have
963
anything to do with row boundaries, although that is often a reasonable choice.) The frontend can terminate the copy-in mode by sending either a CopyDone message (allowing successful termination) or a CopyFail message (which will cause the COPY SQL statement to fail with an error). The backend then reverts to the commandprocessing mode it was in before the COPY started, which will be either simple or extended query protocol. It will next send either CommandComplete (if successful) or ErrorResponse (if not). In the event of a backend-detected error during copy-in mode (including receipt of a CopyFail message), the backend will issue an ErrorResponse message. If the COPY command was issued via an extended-query message, the backend will now discard frontend messages until a Sync message is received, then it will issue ReadyForQuery and return to normal processing. If the COPY command was issued in a simple Query message, the rest of that message is discarded and ReadyForQuery is issued. In either case, any subsequent CopyData, CopyDone, or CopyFail messages issued by the frontend will simply be dropped. The backend will ignore Flush and Sync messages received during copy-in mode. Receipt of any other noncopy message type constitutes an error that will abort the copy-in state as described above. (The exception for Flush and Sync is for the convenience of client libraries that always send Flush or Sync after an Execute message, without checking whether the command to be executed is a COPY FROM STDIN.) Copy-out mode (data transfer from the server) is initiated when the backend executes a COPY TO STDOUT SQL statement. The backend sends a CopyOutResponse message to the frontend, followed by zero or more CopyData messages (always one per row), followed by CopyDone. The backend then reverts to the commandprocessing mode it was in before the COPY started, and sends CommandComplete. The frontend cannot abort the transfer (except by closing the connection or issuing a Cancel request), but it can discard unwanted CopyData and CopyDone messages. In the event of a backend-detected error during copy-out mode, the backend will issue an ErrorResponse message and revert to normal processing. The frontend should treat receipt of ErrorResponse (or indeed any message type other than CopyData or CopyDone) as terminating the copy-out mode. The CopyInResponse and CopyOutResponse messages include fields that inform the frontend of the number of columns per row and the format codes being used for each column. (As of the present implementation, all columns in a given COPY operation will use the same format, but the message design does not assume this.)
44.2.6. Asynchronous Operations There are several cases in which the backend will send messages that are not specifically prompted by the frontend's command stream. Frontends must be prepared to deal with these messages at any time, even when not engaged in a query. At minimum, one should check for these cases before beginning to read a query response. It is possible for NoticeResponse messages to be generated due to outside activity; for example, if the database administrator commands a “fast” database shutdown, the backend will send a NoticeResponse indicating this fact before closing the connection. Accordingly, frontends should always be prepared to accept and display NoticeResponse messages, even when the connection is nominally idle. ParameterStatus messages will be generated whenever the active value changes for any of the parameters the backend believes the frontend should know about. Most commonly this occurs in response to a SET SQL command executed by the frontend, and this case is effectively synchronous --- but it is also possible for parameter status changes to occur because the administrator changed a configuration file and then sent the SIGHUP signal to the postmaster. Also, if a SET command is rolled back, an appropriate ParameterStatus message will be generated to report the current effective value. At present there is a hard-wired set of parameters for which ParameterStatus will be generated: they are server_version (a pseudo-parameter that cannot change after startup); client_encoding, is_superuser, session_authorization, and DateStyle. This set might change in the future, or even become configurable. Accordingly, a frontend should simply ignore ParameterStatus for parameters that it does not understand or care about. If a frontend issues a LISTEN command, then the backend will send a NotificationResponse message (not to be confused with NoticeResponse!) whenever a NOTIFY command is executed for the same notification name.
964
Nota: At present, NotificationResponse can only be sent outside a transaction, and thus it will not occur in the middle of a command-response series, though it may occur just before ReadyForQuery. It is unwise to design frontend logic that assumes that, however. Good practice is to be able to accept NotificationResponse at any point in the protocol.
44.2.7. Cancelling Requests in Progress During the processing of a query, the frontend may request cancellation of the query. The cancel request is not sent directly on the open connection to the backend for reasons of implementation efficiency: we don't want to have the backend constantly checking for new input from the frontend during query processing. Cancel requests should be relatively infrequent, so we make them slightly cumbersome in order to avoid a penalty in the normal case. To issue a cancel request, the frontend opens a new connection to the server and sends a CancelRequest message, rather than the StartupMessage message that would ordinarily be sent across a new connection. The server will process this request and then close the connection. For security reasons, no direct reply is made to the cancel request message. A CancelRequest message will be ignored unless it contains the same key data (PID and secret key) passed to the frontend during connection start-up. If the request matches the PID and secret key for a currently executing backend, the processing of the current query is aborted. (In the existing implementation, this is done by sending a special signal to the backend process that is processing the query.) The cancellation signal may or may not have any effect --- for example, if it arrives after the backend has finished processing the query, then it will have no effect. If the cancellation is effective, it results in the current command being terminated early with an error message. The upshot of all this is that for reasons of both security and efficiency, the frontend has no direct way to tell whether a cancel request has succeeded. It must continue to wait for the backend to respond to the query. Issuing a cancel simply improves the odds that the current query will finish soon, and improves the odds that it will fail with an error message instead of succeeding. Since the cancel request is sent across a new connection to the server and not across the regular frontend/backend communication link, it is possible for the cancel request to be issued by any process, not just the frontend whose query is to be canceled. This may have some benefits of flexibility in building multipleprocess applications. It also introduces a security risk, in that unauthorized persons might try to cancel queries. The security risk is addressed by requiring a dynamically generated secret key to be supplied in cancel requests.
44.2.8. Termination The normal, graceful termination procedure is that the frontend sends a Terminate message and immediately closes the connection. On receipt of this message, the backend closes the connection and terminates. In rare cases (such as an administrator-commanded database shutdown) the backend may disconnect without any frontend request to do so. In such cases the backend will attempt to send an error or notice message giving the reason for the disconnection before it closes the connection. Other termination scenarios arise from various failure cases, such as core dump at one end or the other, loss of the communications link, loss of message-boundary synchronization, etc. If either frontend or backend sees an unexpected closure of the connection, it should clean up and terminate. The frontend has the option of launching a new backend by recontacting the server if it doesn't want to terminate itself. Closing the connection is also advisable if an unrecognizable message type is received, since this probably indicates loss of messageboundary sync. For either normal or abnormal termination, any open transaction is rolled back, not committed. One should note however that if a frontend disconnects while a non-SELECT query is being processed, the backend will probably finish the query before noticing the disconnection. If the query is outside any transaction block (BEGIN ... COMMIT sequence) then its results may be committed before the disconnection is recognized.
965
44.2.9. SSL Session Encryption If PostgreSQL was built with SSL support, frontend/backend communications can be encrypted using SSL. This provides communication security in environments where attackers might be able to capture the session traffic. To initiate an SSL-encrypted connection, the frontend initially sends an SSLRequest message rather than a StartupMessage. The server then responds with a single byte containing S or N, indicating that it is willing or unwilling to perform SSL, respectively. The frontend may close the connection at this point if it is dissatisfied with the response. To continue after S, perform an SSL startup handshake (not described here, part of the SSL specification) with the server. If this is successful, continue with sending the usual StartupMessage. In this case the StartupMessage and all subsequent data will be SSL-encrypted. To continue after N, send the usual StartupMessage and proceed without encryption. The frontend should also be prepared to handle an ErrorMessage response to SSLRequest from the server. This would only occur if the server predates the addition of SSL support to PostgreSQL. In this case the connection must be closed, but the frontend may choose to open a fresh connection and proceed without requesting SSL. An initial SSLRequest may also be used in a connection that is being opened to send a CancelRequest message. While the protocol itself does not provide a way for the server to force SSL encryption, the administrator may configure the server to reject unencrypted sessions as a byproduct of authentication checking.
44.3. Message Data Types This section describes the base data types used in messages. Intn(i) An n-bit integer in network byte order (most significant byte first). If i is specified it is the exact value that will appear, otherwise the value is variable. Eg. Int16, Int32(42). Intn[k] An array of k n-bit integers, each in network byte order. The array length k is always determined by an earlier field in the message. Eg. Int16[M]. String(s) A null-terminated string (C-style string). There is no specific length limitation on strings. If s is specified it is the exact value that will appear, otherwise the value is variable. Eg. String, String("user"). Nota: There is no predefined limit on the length of a string that can be returned by the backend. Good coding strategy for a frontend is to use an expandable buffer so that anything that fits in memory can be accepted. If that's not feasible, read the full string and discard trailing characters that don't fit into your fixed-size buffer.
Byten(c) Exactly n bytes. If the field width n is not a constant, it is always determinable from an earlier field in the message. If c is specified it is the exact value. Eg. Byte2, Byte1('\n').
44.4. Message Formats This section describes the detailed format of each message. Each is marked to indicate that it may be sent by a frontend (F), a backend (B), or both (F & B). Notice that although each message includes a byte count at the beginning, the message format is defined so that the message end can be found without reference to the byte count. This aids validity checking. (The CopyData message is an exception, because it forms part of a data stream; the contents of any individual CopyData message may not be interpretable on their own.) AuthenticationOk (B) Byte1('R') Identifies the message as an authentication request.
966
Int32(8) Length of message contents in bytes, including self. Int32(0) Specifies that the authentication was successful. AuthenticationKerberosV4 (B) Byte1('R') Identifies the message as an authentication request. Int32(8) Length of message contents in bytes, including self. Int32(1) Specifies that Kerberos V4 authentication is required. AuthenticationKerberosV5 (B) Byte1('R') Identifies the message as an authentication request. Int32(8) Length of message contents in bytes, including self. Int32(2) Specifies that Kerberos V5 authentication is required. AuthenticationCleartextPassword (B) Byte1('R') Identifies the message as an authentication request. Int32(8) Length of message contents in bytes, including self. Int32(3) Specifies that a clear-text password is required. AuthenticationCryptPassword (B) Byte1('R') Identifies the message as an authentication request. Int32(10) Length of message contents in bytes, including self. Int32(4) Specifies that a crypt()-encrypted password is required. Byte2 The salt to use when encrypting the password. AuthenticationMD5Password (B) Byte1('R') Identifies the message as an authentication request. Int32(12) Length of message contents in bytes, including self.
967
Int32(5) Specifies that an MD5-encrypted password is required. Byte4 The salt to use when encrypting the password. AuthenticationSCMCredential (B) Byte1('R') Identifies the message as an authentication request. Int32(8) Length of message contents in bytes, including self. Int32(6) Specifies that an SCM credentials message is required. BackendKeyData (B) Byte1('K') Identifies the message as cancellation key data. The frontend must save these values if it wishes to be able to issue CancelRequest messages later. Int32(12) Length of message contents in bytes, including self. Int32 The process ID of this backend. Int32 The secret key of this backend. Bind (F) Byte1('B') Identifies the message as a Bind command. Int32 Length of message contents in bytes, including self. String The name of the destination portal (an empty string selects the unnamed portal). String The name of the source prepared statement (an empty string selects the unnamed prepared statement). Int16 The number of parameter format codes that follow (denoted C below). This can be zero to indicate that there are no parameters or that the parameters all use the default format (text); or one, in which case the specified format code is applied to all parameters; or it can equal the actual number of parameters. Int16[C] The parameter format codes. Each must presently be zero (text) or one (binary). Int16 The number of parameter values that follow (possibly zero). This must match the number of parameters needed by the query. Next, the following pair of fields appear for each parameter:
968
Int32 The length of the parameter value, in bytes (this count does not include itself). Can be zero. As a special case, -1 indicates a NULL parameter value. No value bytes follow in the NULL case. Byten The value of the parameter, in the format indicated by the associated format code. n is the above length. After the last parameter, the following fields appear: Int16 The number of result-column format codes that follow (denoted R below). This can be zero to indicate that there are no result columns or that the result columns should all use the default format (text); or one, in which case the specified format code is applied to all result columns (if any); or it can equal the actual number of result columns of the query. Int16[R] The result-column format codes. Each must presently be zero (text) or one (binary). BindComplete (B) Byte1('2') Identifies the message as a Bind-complete indicator. Int32(4) Length of message contents in bytes, including self. CancelRequest (F) Int32(16) Length of message contents in bytes, including self. Int32(80877102) The cancel request code. The value is chosen to contain 1234 in the most significant 16 bits, and 5678 in the least 16 significant bits. (To avoid confusion, this code must not be the same as any protocol version number.) Int32 The process ID of the target backend. Int32 The secret key for the target backend. Close (F) Byte1('C') Identifies the message as a Close command. Int32 Length of message contents in bytes, including self. Byte1 'S' to close a prepared statement; or 'P' to close a portal. String The name of the prepared statement or portal to close (an empty string selects the unnamed prepared statement or portal).
969
CloseComplete (B) Byte1('3') Identifies the message as a Close-complete indicator. Int32(4) Length of message contents in bytes, including self. CommandComplete (B) Byte1('C') Identifies the message as a command-completed response. Int32 Length of message contents in bytes, including self. String The command tag. This is usually a single word that identifies which SQL command was completed. For an INSERT command, the tag is INSERT oid rows, where rows is the number of rows inserted. oid is the object ID of the inserted row if rows is 1 and the target table has OIDs; otherwise oid is 0. For a DELETE command, the tag is DELETE rows where rows is the number of rows deleted. For an UPDATE command, the tag is UPDATE rows where rows is the number of rows updated. For a MOVE command, the tag is MOVE rows where rows is the number of rows the cursor's position has been changed by. For a FETCH command, the tag is FETCH rows where rows is the number of rows that have been retrieved from the cursor. CopyData (F & B) Byte1('d') Identifies the message as COPY data. Int32 Length of message contents in bytes, including self. Byten Data that forms part of a COPY data stream. Messages sent from the backend will always correspond to single data rows, but messages sent by frontends may divide the data stream arbitrarily. CopyDone (F & B) Byte1('c') Identifies the message as a COPY-complete indicator. Int32(4) Length of message contents in bytes, including self. CopyFail (F) Byte1('f') Identifies the message as a COPY-failure indicator. Int32 Length of message contents in bytes, including self. String An error message to report as the cause of failure.
970
CopyInResponse (B) Byte1('G') Identifies the message as a Start Copy In response. The frontend must now send copy-in data (if not prepared to do so, send a CopyFail message). Int32 Length of message contents in bytes, including self. Int8 0 indicates the overall copy format is textual (rows separated by newlines, columns separated by separator characters, etc). 1 indicates the overall copy format is binary (similar to DataRow format). See COPY for more information. Int16 The number of columns in the data to be copied (denoted N below). Int16[N] The format codes to be used for each column. Each must presently be zero (text) or one (binary). All must be zero if the overall copy format is textual. CopyOutResponse (B) Byte1('H') Identifies the message as a Start Copy Out response. This message will be followed by copy-out data. Int32 Length of message contents in bytes, including self. Int8 0 indicates the overall copy format is textual (rows separated by newlines, columns separated by separator characters, etc). 1 indicates the overall copy format is binary (similar to DataRow format). See COPY for more information. Int16 The number of columns in the data to be copied (denoted N below). Int16[N] The format codes to be used for each column. Each must presently be zero (text) or one (binary). All must be zero if the overall copy format is textual. DataRow (B) Byte1('D') Identifies the message as a data row. Int32 Length of message contents in bytes, including self. Int16 The number of column values that follow (possibly zero). Next, the following pair of fields appear for each column: Int32 The length of the column value, in bytes (this count does not include itself). Can be zero. As a special case, -1 indicates a NULL column value. No value bytes follow in the NULL case.
971
Byten The value of the column, in the format indicated by the associated format code. n is the above length. Describe (F) Byte1('D') Identifies the message as a Describe command. Int32 Length of message contents in bytes, including self. Byte1 'S' to describe a prepared statement; or 'P' to describe a portal. String The name of the prepared statement or portal to describe (an empty string selects the unnamed prepared statement or portal). EmptyQueryResponse (B) Byte1('I') Identifies the message as a response to an empty query string. (This substitutes for CommandComplete.) Int32(4) Length of message contents in bytes, including self. ErrorResponse (B) Byte1('E') Identifies the message as an error. Int32 Length of message contents in bytes, including self. The message body consists of one or more identified fields, followed by a zero byte as a terminator. Fields may appear in any order. For each field there is the following: Byte1 A code identifying the field type; if zero, this is the message terminator and no string follows. The presently defined field types are listed in Seção 44.5. Since more field types may be added in future, frontends should silently ignore fields of unrecognized type. String The field value. Execute (F) Byte1('E') Identifies the message as an Execute command. Int32 Length of message contents in bytes, including self. String The name of the portal to execute (an empty string selects the unnamed portal). Int32 Maximum number of rows to return, if portal contains a query that returns rows (ignored otherwise). Zero denotes “no limit”.
972
Flush (F) Byte1('H') Identifies the message as a Flush command. Int32(4) Length of message contents in bytes, including self. FunctionCall (F) Byte1('F') Identifies the message as a function call. Int32 Length of message contents in bytes, including self. Int32 Specifies the object ID of the function to call. Int16 The number of argument format codes that follow (denoted C below). This can be zero to indicate that there are no arguments or that the arguments all use the default format (text); or one, in which case the specified format code is applied to all arguments; or it can equal the actual number of arguments. Int16[C] The argument format codes. Each must presently be zero (text) or one (binary). Int16 Specifies the number of arguments being supplied to the function. Next, the following pair of fields appear for each argument: Int32 The length of the argument value, in bytes (this count does not include itself). Can be zero. As a special case, -1 indicates a NULL argument value. No value bytes follow in the NULL case. Byten The value of the argument, in the format indicated by the associated format code. n is the above length. After the last argument, the following field appears: Int16 The format code for the function result. Must presently be zero (text) or one (binary). FunctionCallResponse (B) Byte1('V') Identifies the message as a function call result. Int32 Length of message contents in bytes, including self. Int32 The length of the function result value, in bytes (this count does not include itself). Can be zero. As a special case, -1 indicates a NULL function result. No value bytes follow in the NULL case. Byten The value of the function result, in the format indicated by the associated format code. n is the above length.
973
NoData (B) Byte1('n') Identifies the message as a no-data indicator. Int32(4) Length of message contents in bytes, including self. NoticeResponse (B) Byte1('N') Identifies the message as a notice. Int32 Length of message contents in bytes, including self. The message body consists of one or more identified fields, followed by a zero byte as a terminator. Fields may appear in any order. For each field there is the following: Byte1 A code identifying the field type; if zero, this is the message terminator and no string follows. The presently defined field types are listed in Seção 44.5. Since more field types may be added in future, frontends should silently ignore fields of unrecognized type. String The field value. NotificationResponse (B) Byte1('A') Identifies the message as a notification response. Int32 Length of message contents in bytes, including self. Int32 The process ID of the notifying backend process. String The name of the condition that the notify has been raised on. String Additional information passed from the notifying process. (Currently, this feature is unimplemented so the field is always an empty string.) ParameterDescription (B) Byte1('t') Identifies the message as a parameter description. Int32 Length of message contents in bytes, including self. Int16 The number of parameters used by the statement (may be zero). Then, for each parameter, there is the following: Int32 Specifies the object ID of the parameter data type.
974
ParameterStatus (B) Byte1('S') Identifies the message as a run-time parameter status report. Int32 Length of message contents in bytes, including self. String The name of the run-time parameter being reported. String The current value of the parameter. Parse (F) Byte1('P') Identifies the message as a Parse command. Int32 Length of message contents in bytes, including self. String The name of the destination prepared statement (an empty string selects the unnamed prepared statement). String The query string to be parsed. Int16 The number of parameter data types specified (may be zero). Note that this is not an indication of the number of parameters that might appear in the query string, only the number that the frontend wants to prespecify types for. Then, for each parameter, there is the following: Int32 Specifies the object ID of the parameter data type. Placing a zero here is equivalent to leaving the type unspecified. ParseComplete (B) Byte1('1') Identifies the message as a Parse-complete indicator. Int32(4) Length of message contents in bytes, including self. PasswordMessage (F) Byte1('p') Identifies the message as a password response. Int32 Length of message contents in bytes, including self. String The password (encrypted, if requested).
975
PortalSuspended (B) Byte1('s') Identifies the message as a portal-suspended indicator. Note this only appears if an Execute message's row-count limit was reached. Int32(4) Length of message contents in bytes, including self. Query (F) Byte1('Q') Identifies the message as a simple query. Int32 Length of message contents in bytes, including self. String The query string itself. ReadyForQuery (B) Byte1('Z') Identifies the message type. ReadyForQuery is sent whenever the backend is ready for a new query cycle. Int32(5) Length of message contents in bytes, including self. Byte1 Current backend transaction status indicator. Possible values are 'I' if idle (not in a transaction block); 'T' if in a transaction block; or 'E' if in a failed transaction block (queries will be rejected until block is ended). RowDescription (B) Byte1('T') Identifies the message as a row description. Int32 Length of message contents in bytes, including self. Int16 Specifies the number of fields in a row (may be zero). Then, for each field, there is the following: String The field name. Int32 If the field can be identified as a column of a specific table, the object ID of the table; otherwise zero. Int16 If the field can be identified as a column of a specific table, the attribute number of the column; otherwise zero. Int32 The object ID of the field's data type.
976
Int16 The data type size (see pg_type.typlen). Note that negative values denote variable-width types. Int32 The type modifier (see pg_attribute.atttypmod). The meaning of the modifier is type-specific. Int16 The format code being used for the field. Currently will be zero (text) or one (binary). In a RowDescription returned from the statement variant of Describe, the format code is not yet known and will always be zero. SSLRequest (F) Int32(8) Length of message contents in bytes, including self. Int32(80877103) The SSL request code. The value is chosen to contain 1234 in the most significant 16 bits, and 5679 in the least 16 significant bits. (To avoid confusion, this code must not be the same as any protocol version number.) StartupMessage (F) Int32 Length of message contents in bytes, including self. Int32(196608) The protocol version number. The most significant 16 bits are the major version number (3 for the protocol described here). The least significant 16 bits are the minor version number (0 for the protocol described here). The protocol version number is followed by one or more pairs of parameter name and value strings. A zero byte is required as a terminator after the last name/value pair. Parameters can appear in any order. user is required, others are optional. Each parameter is specified as: String The parameter name. Currently recognized names are: user
The database user name to connect as. Required; there is no default. database
The database to connect to. Defaults to the user name. options
Command-line arguments for the backend. (This is deprecated in favor of setting individual run-time parameters.) In addition to the above, any run-time parameter that can be set at backend start time may be listed. Such settings will be applied during backend start (after parsing the command-line options if any). The values will act as session defaults. String The parameter value. Sync (F) Byte1('S') Identifies the message as a Sync command.
977
Int32(4) Length of message contents in bytes, including self. Terminate (F) Byte1('X') Identifies the message as a termination. Int32(4) Length of message contents in bytes, including self.
44.5. Error and Notice Message Fields This section describes the fields that may appear in ErrorResponse and NoticeResponse messages. Each field type has a single-byte identification token. Note that any given field type should appear at most once per message. S
Severity: the field contents are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a localized translation of one of these. Always present. C
Code: the SQLSTATE code for the error (see Apêndice A). Not localizable. Always present. M
Message: the primary human-readable error message. This should be accurate but terse (typically one line). Always present. D
Detail: an optional secondary error message carrying more detail about the problem. May run to multiple lines. H
Hint: an optional suggestion what to do about the problem. This is intended to differ from Detail in that it offers advice (potentially inappropriate) rather than hard facts. May run to multiple lines. P
Position: the field value is a decimal ASCII integer, indicating an error cursor position as an index into the original query string. The first character has index 1, and positions are measured in characters not bytes. W
Where: an indication of the context in which the error occurred. Presently this includes a call stack traceback of active PL functions. The trace is one entry per line, most recent first. F
File: the file name of the source-code location where the error was reported. L
Line: the line number of the source-code location where the error was reported. R
Routine: the name of the source-code routine reporting the error. The client is responsible for formatting displayed information to meet its needs; in particular it should break long lines as needed. Newline characters appearing in the error message fields should be treated as paragraph breaks, not line breaks.
978
44.6. Summary of Changes since Protocol 2.0 This section provides a quick checklist of changes, for the benefit of developers trying to update existing client libraries to protocol 3.0. The initial startup packet uses a flexible list-of-strings format instead of a fixed format. Notice that session default values for run-time parameters can now be specified directly in the startup packet. (Actually, you could do that before using the options field, but given the limited width of options and the lack of any way to quote whitespace in the values, it wasn't a very safe technique.) All messages now have a length count immediately following the message type byte (except for startup packets, which have no type byte). Also note that PasswordMessage now has a type byte. ErrorResponse and NoticeResponse ('E' and 'N') messages now contain multiple fields, from which the client code may assemble an error message of the desired level of verbosity. Note that individual fields will typically not end with a newline, whereas the single string sent in the older protocol always did. The ReadyForQuery ('Z') message includes a transaction status indicator. The distinction between BinaryRow and DataRow message types is gone; the single DataRow message type serves for returning data in all formats. Note that the layout of DataRow has changed to make it easier to parse. Also, the representation of binary values has changed: it is no longer directly tied to the server's internal representation. There is a new “extended query” sub-protocol, which adds the frontend message types Parse, Bind, Execute, Describe, Close, Flush, and Sync, and the backend message types ParseComplete, BindComplete, PortalSuspended, ParameterDescription, NoData, and CloseComplete. Existing clients do not have to concern themselves with this sub-protocol, but making use of it may allow improvements in performance or functionality. COPY data is now encapsulated into CopyData and CopyDone messages. There is a well-defined way to recover from errors during COPY. The special “\.” last line is not needed anymore, and is not sent during COPY OUT. (It is still recognized as a terminator during COPY IN, but its use is deprecated and will eventually be removed.) Binary COPY is supported. The CopyInResponse and CopyOutResponse messages include fields indicating the number of columns and the format of each column. The layout of FunctionCall and FunctionCallResponse messages has changed. FunctionCall can now support passing NULL arguments to functions. It also can handle passing parameters and retrieving results in either text or binary format. There is no longer any reason to consider FunctionCall a potential security hole, since it does not offer direct access to internal server data representations. The backend sends ParameterStatus ('S') messages during connection startup for all parameters it considers interesting to the client library. Subsequently, a ParameterStatus message is sent whenever the active value changes for any of these parameters. The RowDescription ('T') message carries new table OID and column number fields for each column of the described row. It also shows the format code for each column. The CursorResponse ('P') message is no longer generated by the backend. The NotificationResponse ('A') message has an additional string field, which is presently empty but may someday carry additional data passed from the NOTIFY event sender. The EmptyQueryResponse ('I') message used to include an empty string parameter; this has been removed.
979
Capítulo 45. PostgreSQL Coding Conventions 45.1. Formatting Source code formatting uses 4 column tab spacing, with tabs preserved (i.e. tabs are not expanded to spaces). Each logical indentation level is one additional tab stop. Layout rules (brace positioning, etc) follow BSD conventions. While submitted patches do not absolutely have to follow these formatting rules, it's a good idea to do so. Your code will get run through pgindent, so there's no point in making it look nice under some other set of formatting conventions. For Emacs, add the following (or something similar) to your ~/.emacs initialization file: ;; check for files with a path containing "postgres" or "pgsql" (setq auto-mode-alist (cons '("\\(postgres\\|pgsql\\).*\\.[ch]\\'" . pgsql-c-mode) auto-mode-alist)) (setq auto-mode-alist (cons '("\\(postgres\\|pgsql\\).*\\.cc\\'" . pgsql-c-mode) auto-mode-alist)) (defun pgsql-c-mode () ;; sets up formatting for PostgreSQL C code (interactive) (c-mode) (setq-default tab-width 4) (c-set-style "bsd") ; set c-basic-offset to 4, plus other stuff (c-set-offset 'case-label '+) ; tweak case indent to match PG custom (setq indent-tabs-mode t)) ; make sure we keep tabs when indenting
For vi, your ~/.vimrc or equivalent file should contain the following: set tabstop=4
or equivalently from within vi, try :set ts=4
The text browsing tools more and less can be invoked as more -x4 less -x4
to make them show tabs appropriately.
45.2. Reporting Errors Within the Server Error, warning, and log messages generated within the server code should be created using ereport, or its older cousin elog. The use of this function is complex enough to require some explanation. There are two required elements for every message: a severity level (ranging from DEBUG to PANIC) and a primary message text. In addition there are optional elements, the most common of which is an error identifier code that follows the SQL spec's SQLSTATE conventions. ereport itself is just a shell function, that exists mainly for the syntactic convenience of making message generation look like a function call in the C source code. The only parameter accepted directly by ereport is the severity level. The primary message text and any optional message elements are generated by calling auxiliary functions, such as errmsg, within the ereport call. A typical call to ereport might look like this:
980
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO), errmsg("division by zero")));
This specifies error severity level ERROR (a run-of-the-mill error). The errcode call specifies the SQLSTATE error code using a macro defined in src/include/utils/errcodes.h. The errmsg call provides the primary message text. Notice the extra set of parentheses surrounding the auxiliary function calls --- these are annoying but syntactically necessary. Here is a more complex example: ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_FUNCTION), errmsg("function %s is not unique", func_signature_string(funcname, nargs, actual_arg_types)), errhint("Unable to choose a best candidate function. " "You may need to add explicit typecasts.")));
This illustrates the use of format codes to embed run-time values into a message text. Also, an optional “hint” message is provided. The available auxiliary routines for ereport are: • errcode(sqlerrcode)
specifies the SQLSTATE error identifier code for the condition. If this routine is not called, the error identifier defaults to ERRCODE_INTERNAL_ERROR when the error severity level is ERROR or higher, ERRCODE_WARNING when the error level is WARNING, otherwise (for NOTICE and below) ERRCODE_SUCCESSFUL_COMPLETION. While these defaults are often convenient, always think whether they are appropriate before omitting the errcode() call.
• errmsg(const
char *msg, ...) specifies the primary error message text, and possibly run-time values to insert into it. Insertions are specified by sprintf-style format codes. In addition to the standard format codes accepted by sprintf, the format code %m can be used to insert the error message returned by strerror for the current value of errno. 1 %m does not require any corresponding entry in the parameter list for errmsg. Note that the message string will be run through gettext for possible localization before format codes are processed.
• errmsg_internal(const
char *msg, ...) is the same as errmsg, except that the message string will not be included in the internationalization message dictionary. This should be used for “can't happen” cases that are probably not worth expending translation effort on.
• errdetail(const
char *msg, ...) supplies an optional “detail” message; this is to be used when there is additional information that seems inappropriate to put in the primary message. The message string is processed in just the same way as for errmsg.
• errhint(const
char *msg, ...) supplies an optional “hint” message; this is to be used when offering suggestions about how to fix the problem, as opposed to factual details about what went wrong. The message string is processed in just the same way as for errmsg.
• errcontext(const
char *msg, ...) is not normally called directly from an ereport message site; rather it is used in error_context_stack callback functions to provide information about the context in which an error occurred, such as the current location in a PL function. The message string is processed in just the same way as for errmsg. Unlike the other auxiliary functions, this can be called more than once per ereport call; the successive strings thus supplied are concatenated with separating newlines.
• errposition(int
cursorpos) specifies the textual location of an error within a query string. Currently it is only useful for errors detected in the lexical and syntactic analysis phases of query processing.
• errcode_for_file_access()
is a convenience function that selects an appropriate SQLSTATE error identifier for a failure in a file-access-related system call. It uses the saved errno to determine which error code to generate. Usually this should be used in combination with %m in the primary error message text.
• errcode_for_socket_access()
is a convenience function that selects an appropriate SQLSTATE error identifier for a failure in a socket-related system call.
981
There is an older function elog that is still heavily used. An elog call elog(level, "format string", ...);
is exactly equivalent to ereport(level, (errmsg_internal("format string", ...)));
Notice that the SQLSTATE errcode is always defaulted, and the message string is not included in the internationalization message dictionary. Therefore, elog should be used only for internal errors and low-level debug logging. Any message that is likely to be of interest to ordinary users should go through ereport. Nonetheless, there are enough internal “can't happen” error checks in the system that elog is still widely used; it is preferred for those messages for its notational simplicity. Advice about writing good error messages can be found in Seção 45.3.
45.3. Error Message Style Guide This style guide is offered in the hope of maintaining a consistent, user-friendly style throughout all the messages generated by PostgreSQL.
45.3.1. What goes where The primary message should be short, factual, and avoid reference to implementation details such as specific function names. “Short” means “should fit on one line under normal conditions”. Use a detail message if needed to keep the primary message short, or if you feel a need to mention implementation details such as the particular system call that failed. Both primary and detail messages should be factual. Use a hint message for suggestions about what to do to fix the problem, especially if the suggestion might not always be applicable. For example, instead of IpcMemoryCreate: shmget(key=%d, size=%u, 0%o) failed: %m (plus a long addendum that is basically a hint)
write Primary: Detail: Hint:
could not create shared memory segment: %m Failed syscall was shmget(key=%d, size=%u, 0%o). the addendum
Rationale: keeping the primary message short helps keep it to the point, and lets clients lay out screen space on the assumption that one line is enough for error messages. Detail and hint messages may be relegated to a verbose mode, or perhaps a pop-up error-details window. Also, details and hints would normally be suppressed from the server log to save space. Reference to implementation details is best avoided since users don't know the details anyway.
45.3.2. Formatting Don't put any specific assumptions about formatting into the message texts. Expect clients and the server log to wrap lines to fit their own needs. In long messages, newline characters (\n) may be used to indicate suggested paragraph breaks. Don't end a message with a newline. Don't use tabs or other formatting characters. (In error context displays, newlines are automatically added to separate levels of context such as function calls.) Rationale: Messages are not necessarily displayed on terminal-type displays. In GUI displays or browsers these formatting instructions are at best ignored.
45.3.3. Quotation marks English text should use double quotes when quoting is appropriate. Text in other languages should consistently use one kind of quotes that is consistent with publishing customs and computer output of other programs. Rationale: The choice of double quotes over single quotes is somewhat arbitrary, but tends to be the preferred use. Some have suggested choosing the kind of quotes depending on the type of object according to SQL
982
conventions (namely, strings single quoted, identifiers double quoted). But this is a language-internal technical issue that many users aren't even familiar with, it won't scale to other kinds of quoted terms, it doesn't translate to other languages, and it's pretty pointless, too.
45.3.4. Use of quotes Use quotes always to delimit file names, user-supplied identifiers, and other variables that might contain words. Do not use them to mark up variables that will not contain words (for example, operator names). There are functions in the backend that will double-quote their own output at need (for example, format_type_be()). Do not put additional quotes around the output of such functions.
Rationale: Objects can have names that create ambiguity when embedded in a message. Be consistent about denoting where a plugged-in name starts and ends. But don't clutter messages with unnecessary or duplicate quote marks.
45.3.5. Grammar and punctuation The rules are different for primary error messages and for detail/hint messages: Primary error messages: Do not capitalize the first letter. Do not end a message with a period. Do not even think about ending a message with an exclamation point. Detail and hint messages: Use complete sentences, and end each with a period. Capitalize the starts of sentences. Rationale: Avoiding punctuation makes it easier for client applications to embed the message into a variety of grammatical contexts. Often, primary messages are not grammatically complete sentences anyway. (And if they're long enough to be more than one sentence, they should be split into primary and detail parts.) However, detail and hint messages are longer and may need to include multiple sentences. For consistency, they should follow complete-sentence style even when there's only one sentence.
45.3.6. Upper case vs. lower case Use lower case for message wording, including the first letter of a primary error message. Use upper case for SQL commands and key words if they appear in the message. Rationale: It's easier to make everything look more consistent this way, since some messages are complete sentences and some not.
45.3.7. Avoid passive voice Use the active voice. Use complete sentences when there is an acting subject (“A could not do B”). Use telegram style without subject if the subject would be the program itself; do not use “I” for the program. Rationale: The program is not human. Don't pretend otherwise.
45.3.8. Present vs past tense Use past tense if an attempt to do something failed, but could perhaps succeed next time (perhaps after fixing some problem). Use present tense if the failure is certainly permanent. There is a nontrivial semantic difference between sentences of the form could not open file "%s": %m
and cannot open file "%s"
The first one means that the attempt to open the file failed. The message should give a reason, such as “disk full” or “file doesn't exist”. The past tense is appropriate because next time the disk might not be full anymore or the file in question may exist.
983
The second form indicates the the functionality of opening the named file does not exist at all in the program, or that it's conceptually impossible. The present tense is appropriate because the condition will persist indefinitely. Rationale: Granted, the average user will not be able to draw great conclusions merely from the tense of the message, but since the language provides us with a grammar we should use it correctly.
45.3.9. Type of the object When citing the name of an object, state what kind of object it is. Rationale: Else no one will know what “foo.bar.baz” is.
45.3.10. Brackets Square brackets are only to be used (1) in command synopses to denote optional arguments, or (2) to denote an array subscript. Rationale: Anything else does not correspond to widely-known customary usage and will confuse people.
45.3.11. Assembling error messages When a message includes text that is generated elsewhere, embed it in this style: could not open file %s: %m
Rationale: It would be difficult to account for all possible error codes to paste this into a single smooth sentence, so some sort of punctuation is needed. Putting the embedded text in parentheses has also been suggested, but it's unnatural if the embedded text is likely to be the most important part of the message, as is often the case.
45.3.12. Reasons for errors Messages should always state the reason why an error occurred. For example: BAD: could not open file %s BETTER: could not open file %s (I/O failure)
If no reason is known you better fix the code.
45.3.13. Function names Don't include the name of the reporting routine in the error text. We have other mechanisms for finding that out when needed, and for most users it's not helpful information. If the error text doesn't make as much sense without the function name, reword it. BAD: pg_atoi: error in "z": can't parse "z" BETTER: invalid input syntax for integer: "z"
Avoid mentioning called function names, either; instead say what the code was trying to do: BAD: open() failed: %m BETTER: could not open file %s: %m
If it really seems necessary, mention the system call in the detail message. (In some cases, providing the actual values passed to the system call might be appropriate information for the detail message.) Rationale: Users don't know what all those functions do.
45.3.14. Tricky words to avoid Unable. “Unable” is nearly the passive voice. Better use “cannot” or “could not”, as appropriate. Bad. Error messages like “bad result” are really hard to interpret intelligently. It's better to write why the result is “bad”, e.g., “invalid format”.
984
Illegal. “Illegal” stands for a violation of the law, the rest is “invalid”. Better yet, say why it's invalid. Unknown. Try to avoid “unknown”. Consider “error: unknown response”. If you don't know what the response is, how do you know it's erroneous? “Unrecognized” is often a better choice. Also, be sure to include the value being complained of. BAD: unknown node type BETTER: unrecognized node type: 42
Find vs. Exists. If the program uses a nontrivial algorithm to locate a resource (e.g., a path search) and that algorithm fails, it is fair to say that the program couldn't “find” the resource. If, on the other hand, the expected location of the resource is known but the program cannot access it there then say that the resource doesn't “exist”. Using “find” in this case sounds weak and confuses the issue.
45.3.15. Proper spelling Spell out words in full. For instance, avoid: •
spec
•
stats
•
parens
•
auth
•
xact
Rationale: This will improve consistency.
45.3.16. Localization Keep in mind that error message texts need to be translated into other languages. Follow the guidelines in Seção 46.2.2 to avoid making life difficult for translators.
Notas 1. That is, the value that was current when the ereport call was reached; changes of errno within the auxiliary reporting routines will not affect it. That would not be true if you were to write strerror(errno) explicitly in errmsg's parameter list; accordingly, do not do so.
985
Capítulo 46. Native Language Support Peter Eisentraut
46.1. For the Translator PostgreSQL programs (server and client) can issue their messages in your favorite language -- if the messages have been translated. Creating and maintaining translated message sets needs the help of people who speak their own language well and want to contribute to the PostgreSQL effort. You do not have to be a programmer at all to do this. This section explains how to help.
46.1.1. Requirements We won't judge your language skills -- this section is about software tools. Theoretically, you only need a text editor. But this is only in the unlikely event that you do not want to try out your translated messages. When you configure your source tree, be sure to use the --enable-nls option. This will also check for the libintl library and the msgfmt program, which all end users will need anyway. To try out your work, follow the applicable portions of the installation instructions. If you want to start a new translation effort or want to do a message catalog merge (described later), you will need the programs xgettext and msgmerge, respectively, in a GNU-compatible implementation. Later, we will try to arrange it so that if you use a packaged source distribution, you won't need xgettext. (From CVS, you will still need it.) GNU Gettext 0.10.36 or later is currently recommended. Your local gettext implementation should come with its own documentation. Some of that is probably duplicated in what follows, but for additional details you should look there.
46.1.2. Conceitos The pairs of original (English) messages and their (possibly) translated equivalents are kept in message catalogs, one for each program (although related programs can share a message catalog) and for each target language. There are two file formats for message catalogs: The first is the “PO” file (for Portable Object), which is a plain text file with special syntax that translators edit. The second is the “MO” file (for Machine Object), which is a binary file generated from the respective PO file and is used while the internationalized program is run. Translators do not deal with MO files; in fact hardly anyone does. The extension of the message catalog file is to no surprise either .po or .mo. The base name is either the name of the program it accompanies, or the language the file is for, depending on the situation. This is a bit confusing. Examples are psql.po (PO file for psql) or fr.mo (MO file in French). The file format of the PO files is illustrated here: # comment msgid "original string" msgstr "translated string" msgid "more original" msgstr "another translated" "string can be broken up like this" ...
The msgid's are extracted from the program source. (They need not be, but this is the most common way.) The msgstr lines are initially empty and are filled in with useful strings by the translator. The strings can contain Cstyle escape characters and can be continued across lines as illustrated. (The next line must start at the beginning of the line.)
986
The # character introduces a comment. If whitespace immediately follows the # character, then this is a comment maintained by the translator. There may also be automatic comments, which have a non-whitespace character immediately following the #. These are maintained by the various tools that operate on the PO files and are intended to aid the translator. #. automatic comment #: filename.c:1023 #, flags, flags
The #. style comments are extracted from the source file where the message is used. Possibly the programmer has inserted information for the translator, such as about expected alignment. The #: comment indicates the exact location(s) where the message is used in the source. The translator need not look at the program source, but he can if there is doubt about the correct translation. The #, comments contain flags that describe the message in some way. There are currently two flags: fuzzy is set if the message has possibly been outdated because of changes in the program source. The translator can then verify this and possibly remove the fuzzy flag. Note that fuzzy messages are not made available to the end user. The other flag is c-format, which indicates that the message is a printf-style format template. This means that the translation should also be a format string with the same number and type of placeholders. There are tools that can verify this, which key off the c-format flag.
46.1.3. Creating and maintaining message catalogs OK, so how does one create a “blank” message catalog? First, go into the directory that contains the program whose messages you want to translate. If there is a file nls.mk, then this program has been prepared for translation. If there are already some .po files, then someone has already done some translation work. The files are named language.po, where language is the ISO 639-1 (http://lcweb.loc.gov/standards/iso639-2/englangn.html) two-letter language code (in lower case), e.g., fr.po for French. If there is really a need for more than one translation effort per language then the files may also be named language_region.po where region is the ISO 3166-1 (http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1/en_listp1.html) two-letter country code (in upper case), e.g., pt_BR.po for Portuguese in Brazil. If you find the language you wanted you can just start working on that file. If you need to start a new translation effort, then first run the command gmake init-po
This will create a file progname.pot. (.pot to distinguish it from PO files that are “in production”. The T stands for “template”.) Copy this file to language.po and edit it. To make it known that the new language is available, also edit the file nls.mk and add the language (or language and country) code to the line that looks like: AVAIL_LANGUAGES := de fr
(Other languages may appear, of course.) As the underlying program or library changes, messages may be changed or added by the programmers. In this case you do not need to start from scratch. Instead, run the command gmake update-po
which will create a new blank message catalog file (the pot file you started with) and will merge it with the existing PO files. If the merge algorithm is not sure about a particular message it marks it “fuzzy” as explained above. For the case where something went really wrong, the old PO file is saved with a .po.old extension.
46.1.4. Editing the PO files The PO files can be edited with a regular text editor. The translator should only change the area between the quotes after the msgstr directive, may add comments and alter the fuzzy flag. There is (unsurprisingly) a PO mode for Emacs, which I find quite useful.
987
The PO files need not be completely filled in. The software will automatically fall back to the original string if no translation (or an empty translation) is available. It is no problem to submit incomplete translations for inclusions in the source tree; that gives room for other people to pick up your work. However, you are encouraged to give priority to removing fuzzy entries after doing a merge. Remember that fuzzy entries will not be installed; they only serve as reference what might be the right translation. Here are some things to keep in mind while editing the translations: •
Make sure that if the original ends with a newline, the translation does, too. Similarly for tabs, etc.
•
If the original is a printf format string, the translation also needs to be. The translation also needs to have the same format specifiers in the same order. Sometimes the natural rules of the language make this impossible or at least awkward. In that case you can modify the format specifiers like this: msgstr "Die Datei %2$s hat %1$u Zeichen."
Then the first placeholder will actually use the second argument from the list. The digits$ needs to follow the % immediately, before any other format manipulators. (This feature really exists in the printf family of functions. You may not have heard of it before because there is little use for it outside of message internationalization.) •
If the original string contains a linguistic mistake, report that (or fix it yourself in the program source) and translate normally. The corrected string can be merged in when the program sources have been updated. If the original string contains a factual mistake, report that (or fix it yourself) and do not translate it. Instead, you may mark the string with a comment in the PO file.
•
Maintain the style and tone of the original string. Specifically, messages that are not sentences (cannot open file %s) should probably not start with a capital letter (if your language distinguishes letter case) or end with a period (if your language uses punctuation marks). It may help to read Seção 45.3.
•
If you don't know what a message means, or if it is ambiguous, ask on the developers' mailing list. Chances are that English speaking end users might also not understand it or find it ambiguous, so it's best to improve the message.
46.2. For the Programmer 46.2.1. Mechanics This section describes how to implement native language support in a program or library that is part of the PostgreSQL distribution. Currently, it only applies to C programs. Adding NLS support to a program 1.
Insert this code into the start-up sequence of the program: #ifdef ENABLE_NLS #include#endif ... #ifdef ENABLE_NLS setlocale(LC_ALL, ""); bindtextdomain("progname", LOCALEDIR); textdomain("progname"); #endif
(The progname can actually be chosen freely.) 2.
Wherever a message that is a candidate for translation is found, a call to gettext() needs to be inserted. E.g., fprintf(stderr, "panic level %d\n", lvl);
would be changed to fprintf(stderr, gettext("panic level %d\n"), lvl);
988
(gettext is defined as a no-op if no NLS is configured.) This may tend to add a lot of clutter. One common shortcut is to use #define _(x) gettext(x)
Another solution is feasible if the program does much of its communication through one or a few functions, such as ereport() in the backend. Then you make this function call gettext internally on all input strings. 3.
Add a file nls.mk in the directory with the program sources. This file will be read as a makefile. The following variable assignments need to be made here:
CATALOG_NAME
The program name, as provided in the textdomain() call. AVAIL_LANGUAGES
List of provided translations -- empty in the beginning. GETTEXT_FILES
List of files that contain translatable strings, i.e., those marked with gettext or an alternative solution. Eventually, this will include nearly all source files of the program. If this list gets too long you can make the first “file” be a + and the second word be a file that contains one file name per line. GETTEXT_TRIGGERS
The tools that generate message catalogs for the translators to work on need to know what function calls contain translatable strings. By default, only gettext() calls are known. If you used _ or other identifiers you need to list them here. If the translatable string is not the first argument, the item needs to be of the form func:2 (for the second argument). The build system will automatically take care of building and installing the message catalogs.
46.2.2. Message-writing guidelines Here are some guidelines for writing messages that are easily translatable. •
Do not construct sentences at run-time, like printf("Files were %s.\n", flag ? "copied" : "removed");
The word order within the sentence may be different in other languages. Also, even if you remember to call gettext() on each fragment, the fragments may not translate well separately. It's better to duplicate a little code so that each message to be translated is a coherent whole. Only numbers, file names, and such-like runtime variables should be inserted at runtime into a message text. •
For similar reasons, this won't work: printf("copied %d file%s", n, n!=1 ? "s" : "");
because it assumes how the plural is formed. If you figured you could solve it like this if (n==1) printf("copied 1 file"); else printf("copied %d files", n):
then be disappointed. Some languages have more than two forms, with some peculiar rules. We may have a solution for this in the future, but for now the matter is best avoided altogether. You could write: printf("number of copied files: %d", n); •
If you want to communicate something to the translator, such as about how a message is intended to line up with other output, precede the occurrence of the string with a comment that starts with translator, e.g., /* translator: This message is not what it seems to be. */
These comments are copied to the message catalog files so that the translators can see them.
989
Capítulo 47. Writing A Procedural Language Handler All calls to functions that are written in a language other than the current “version 1” interface for compiled languages (this includes functions in user-defined procedural languages, functions written in SQL, and functions using the version 0 compiled language interface), go through a call handler function for the specific language. It is the responsibility of the call handler to execute the function in a meaningful way, such as by interpreting the supplied source text. This chapter outlines how a new procedural language's call handler can be written. The call handler for a procedural language is a “normal” function that must be written in a compiled language such as C, using the version-1 interface, and registered with PostgreSQL as taking no arguments and returning the type language_handler. This special pseudotype identifies the function as a call handler and prevents it from being called directly in SQL commands. The call handler is called in the same way as any other function: It receives a pointer to a FunctionCallInfoData struct containing argument values and information about the called function, and it is expected to return a Datum result (and possibly set the isnull field of the FunctionCallInfoData
structure, if it wishes to return an SQL null result). The difference between a call handler and an ordinary callee function is that the flinfo->fn_oid field of the FunctionCallInfoData structure will contain the OID of the actual function to be called, not of the call handler itself. The call handler must use this field to determine which function to execute. Also, the passed argument list has been set up according to the declaration of the target function, not of the call handler. It's up to the call handler to fetch the entry of the function from the system table pg_proc and to analyze the argument and return types of the called function. The AS clause from the CREATE FUNCTION of the function will be found in the prosrc column of the pg_proc row. This may be the source text in the procedural language itself (like for PL/Tcl), a path name to a file, or anything else that tells the call handler what to do in detail. Often, the same function is called many times per SQL statement. A call handler can avoid repeated lookups of information about the called function by using the flinfo->fn_extra field. This will initially be NULL, but can be set by the call handler to point at information about the called function. On subsequent calls, if flinfo>fn_extra is already non-NULL then it can be used and the information lookup step skipped. The call handler must make sure that flinfo->fn_extra is made to point at memory that will live at least until the end of the current query, since an FmgrInfo data structure could be kept that long. One way to do this is to allocate the extra data in the memory context specified by flinfo->fn_mcxt; such data will normally have the same lifespan as the FmgrInfo itself. But the handler could also choose to use a longer-lived memory context so that it can cache function definition information across queries. When a procedural-language function is invoked as a trigger, no arguments are passed in the usual way, but the FunctionCallInfoData's context field points at a TriggerData structure, rather than being NULL as it is
in a plain function call. A language handler should provide mechanisms for procedural-language functions to get at the trigger information. This is a template for a procedural-language handler written in C: #include #include #include #include #include #include #include #include
"postgres.h" "executor/spi.h" "commands/trigger.h" "fmgr.h" "access/heapam.h" "utils/syscache.h" "catalog/pg_proc.h" "catalog/pg_type.h"
PG_FUNCTION_INFO_V1(plsample_call_handler); Datum plsample_call_handler(PG_FUNCTION_ARGS)
990
{ Datum
retval;
if (CALLED_AS_TRIGGER(fcinfo)) { /* * Called as a trigger procedure */ TriggerData *trigdata = (TriggerData *) fcinfo->context; retval = ... } else { /* * Called as a function */ retval = ... } return retval; }
Only a few thousand lines of code have to be added instead of the dots to complete the call handler. After having compiled the handler function into a loadable module (see Seção 33.7.6), the following commands then register the sample procedural language: CREATE FUNCTION plsample_call_handler() RETURNS language_handler AS 'filename' LANGUAGE C; CREATE LANGUAGE plsample HANDLER plsample_call_handler;
991
Capítulo 48. Genetic Query Optimizer Martin Utesch1997-10-02
Author: Written by Martin Utesch () for the Institute of Automatic Control at the University of Mining and Technology in Freiberg, Germany.
48.1. Query Handling as a Complex Optimization Problem Among all relational operators the most difficult one to process and optimize is the join. The number of alternative plans to answer a query grows exponentially with the number of joins included in it. Further optimization effort is caused by the support of a variety of join methods (e.g., nested loop, hash join, merge join in PostgreSQL) to process individual joins and a diversity of indexes (e.g., R-tree, B-tree, hash in PostgreSQL) as access paths for relations. The current PostgreSQL optimizer implementation performs a near-exhaustive search over the space of alternative strategies. This algorithm, first introduced in the “System R” database, produces a near-optimal join order, but can take an enormous amount of time and memory space when the number of joins in the query grows large. This makes the ordinary PostgreSQL query optimizer inappropriate for database application domains that involve the need for extensive queries, such as artificial intelligence. The Institute of Automatic Control at the University of Mining and Technology, in Freiberg, Germany, encountered the described problems as its folks wanted to take the PostgreSQL DBMS as the backend for a decision support knowledge based system for the maintenance of an electrical power grid. The DBMS needed to handle large join queries for the inference machine of the knowledge based system. Performance difficulties in exploring the space of possible query plans created the demand for a new optimization technique to be developed. In the following we describe the implementation of a Genetic Algorithm to solve the join ordering problem in a manner that is efficient for queries involving large numbers of joins.
48.2. Genetic Algorithms The genetic algorithm (GA) is a heuristic optimization method which operates through determined, randomized search. The set of possible solutions for the optimization problem is considered as a population of individuals. The degree of adaptation of an individual to its environment is specified by its fitness. The coordinates of an individual in the search space are represented by chromosomes, in essence a set of character strings. A gene is a subsection of a chromosome which encodes the value of a single parameter being optimized. Typical encodings for a gene could be binary or integer. Through simulation of the evolutionary operations recombination, mutation, and selection new generations of search points are found that show a higher average fitness than their ancestors. According to the comp.ai.genetic FAQ it cannot be stressed too strongly that a GA is not a pure random search for a solution to a problem. A GA uses stochastic processes, but the result is distinctly non-random (better than random). Figura 48-1. Structured Diagram of a Genetic Algorithm P(t)
generation of ancestors at a time t
P''(t)
generation of descendants at a time t
992
+=========================================+ |>>>>>>>>>>> Algorithm GA <<<<<<<<<<<<<<| +=========================================+ | INITIALIZE t := 0 | +=========================================+ | INITIALIZE P(t) | +=========================================+ | evaluate FITNESS of P(t) | +=========================================+ | while not STOPPING CRITERION do | | +-------------------------------------+ | | P'(t) := RECOMBINATION{P(t)} | | +-------------------------------------+ | | P''(t) := MUTATION{P'(t)} | | +-------------------------------------+ | | P(t+1) := SELECTION{P''(t) + P(t)} | | +-------------------------------------+ | | evaluate FITNESS of P''(t) | | +-------------------------------------+ | | t := t + 1 | +===+=====================================+
48.3. Genetic Query Optimization (GEQO) in PostgreSQL The GEQO module is intended for the solution of the query optimization problem similar to a traveling salesman problem (TSP). Possible query plans are encoded as integer strings. Each string represents the join order from one relation of the query to the next. E. g., the query tree /\ /\ 2 /\ 3 4 1
is encoded by the integer string '4-1-3-2', which means, first join relation '4' and '1', then '3', and then '2', where 1, 2, 3, 4 are relation IDs within the PostgreSQL optimizer. Parts of the GEQO module are adapted from D. Whitley's Genitor algorithm. Specific characteristics of the GEQO implementation in PostgreSQL are: Usage of a steady state GA (replacement of the least fit individuals in a population, not whole-generational replacement) allows fast convergence towards improved query plans. This is essential for query handling with reasonable time; • Usage of edge recombination crossover which is especially suited to keep edge losses low for the solution of the TSP by means of a GA; • Mutation as genetic operator is deprecated so that no repair mechanisms are needed to generate legal TSP tours. •
The GEQO module allows the PostgreSQL query optimizer to support large join queries effectively through non-exhaustive search.
48.3.1. Future Implementation Tasks for PostgreSQL GEQO Work
is
still
needed
to
improve
the
genetic
algorithm
parameter
settings.
In
file
backend/optimizer/geqo/geqo_params.c, routines gimme_pool_size and gimme_number_generations, we have to find a compromise for the parameter settings to satisfy two
competing demands: Optimality of the query plan • Computing time •
993
48.4. Further Readings The following resources contain additional information about genetic algorithms: •
The Hitch-Hiker's Guide to Evolutionary Computation (http://surf.de.uu.net/encore/www/) (FAQ for comp.ai.genetic (news://comp.ai.genetic))
•
Evolutionary Computation and its application to art and design (http://www.red3d.com/cwr/evolve.html) by Craig Reynolds
•
Fundamentals of Database Systems
•
The design and implementation of the POSTGRES query optimizer
994
Capítulo 49. Index Cost Estimation Functions Author: Written by Tom Lane () on 2000-01-24 Nota: This must eventually become part of a much larger chapter about writing new index access methods.
Every index access method must provide a cost estimation function for use by the planner/optimizer. The procedure OID of this function is given in the amcostestimate field of the access method's pg_am entry. Nota: Prior to PostgreSQL 7.0, a different scheme was used for registering index-specific cost estimation functions.
The amcostestimate function is given a list of WHERE clauses that have been determined to be usable with the index. It must return estimates of the cost of accessing the index and the selectivity of the WHERE clauses (that is, the fraction of main-table rows that will be retrieved during the index scan). For simple cases, nearly all the work of the cost estimator can be done by calling standard routines in the optimizer; the point of having an amcostestimate function is to allow index access methods to provide index-type-specific knowledge, in case it is possible to improve on the standard estimates. Each amcostestimate function must have the signature: void amcostestimate (Query *root, RelOptInfo *rel, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation);
The first four parameters are inputs: root The query being processed. rel The relation the index is on. index The index itself. indexQuals List of index qual clauses (implicitly ANDed); a NIL list indicates no qualifiers are available. The last four parameters are pass-by-reference outputs: *indexStartupCost Set to cost of index start-up processing *indexTotalCost Set to total cost of index processing *indexSelectivity Set to index selectivity *indexCorrelation Set to correlation coefficient between index scan order and underlying table's order
995
Note that cost estimate functions must be written in C, not in SQL or any available procedural language, because they must access internal data structures of the planner/optimizer. The
index
access
costs
should
be
computed
in
the
units
used
by
src/backend/optimizer/path/costsize.c: a sequential disk block fetch has cost 1.0, a nonsequential
fetch has cost random_page_cost, and the cost of processing one index row should usually be taken as cpu_index_tuple_cost (which is a user-adjustable optimizer parameter). In addition, an appropriate multiple of cpu_operator_cost should be charged for any comparison operators invoked during index processing (especially evaluation of the indexQuals themselves). The access costs should include all disk and CPU costs associated with scanning the index itself, but NOT the costs of retrieving or processing the main-table rows that are identified by the index. The “start-up cost” is the part of the total scan cost that must be expended before we can begin to fetch the first row. For most indexes this can be taken as zero, but an index type with a high start-up cost might want to set it nonzero. The indexSelectivity should be set to the estimated fraction of the main table rows that will be retrieved during the index scan. In the case of a lossy index, this will typically be higher than the fraction of rows that actually pass the given qual conditions. The indexCorrelation should be set to the correlation (ranging between -1.0 and 1.0) between the index order and the table order. This is used to adjust the estimate for the cost of fetching rows from the main table. Cost Estimation A typical cost estimator will proceed as follows: 1.
Estimate and return the fraction of main-table rows that will be visited based on the given qual conditions. In the absence of any index-type-specific knowledge, use the standard optimizer function clauselist_selectivity(): *indexSelectivity = clauselist_selectivity(root, indexQuals, rel->relid, JOIN_INNER);
2.
Estimate the number of index rows that will be visited during the scan. For many index types this is the same as indexSelectivity times the number of rows in the index, but it might be more. (Note that the index's size in pages and rows is available from the IndexOptInfo struct.)
3.
Estimate the number of index pages that will be retrieved during the scan. This might be just indexSelectivity times the index's size in pages.
4.
Compute the index access cost. A generic estimator might do this: /* * Our generic assumption is that the index pages will be read * sequentially, so they have cost 1.0 each, not random_page_cost. * Also, we charge for evaluation of the indexquals at each index row. * All the costs are assumed to be paid incrementally during the scan. */ cost_qual_eval(&index_qual_cost, indexQuals); *indexStartupCost = index_qual_cost.startup; *indexTotalCost = numIndexPages + (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples;
5.
Estimate the index correlation. For a simple ordered index on a single field, this can be retrieved from pg_statistic. If the correlation is not known, the conservative estimate is zero (no correlation).
Examples of cost estimator functions can be found in src/backend/utils/adt/selfuncs.c. By convention, the pg_proc entry for an amcostestimate function should show eight arguments all declared as internal (since none of them have types that are known to SQL), and the return type is void.
996
Capítulo 50. GiST Indexes 50.1. Introdução GiST stands for Generalized Search Tree. It is a balanced, tree-structured access method, that acts as a base template in which to implement arbitrary indexing schemes. B+-trees, R-trees and many other indexing schemes can be implemented in GiST. One advantage of GiST is that it allows the development of custom data types with the appropriate access methods, by an expert in the domain of the data type, rather than a database expert. Some of the information here is derived from the University of California at Berkeley's GiST Indexing Project web site (http://gist.cs.berkeley.edu/) and Marcel Kornacker's thesis, Access Methods for Next-Generation Database Systems (http://citeseer.nj.nec.com/448594.html). The GiST implementation in PostgreSQL is primarily maintained by Teodor Sigaev and Oleg Bartunov, and there is more information on their website: http://www.sai.msu.su/~megera/postgres/gist/.
50.2. Extensibility Traditionally, implementing a new index access method meant a lot of difficult work. It was necessary to understand the inner workings of the database, such as the lock manager and Write-Ahead Log. The GiST interface has a high level of abstraction, requiring the access method implementor to only implement the semantics of the data type being accessed. The GiST layer itself takes care of concurrency, logging and searching the tree structure. This extensibility should not be confused with the extensibility of the other standard search trees in terms of the data they can handle. For example, PostgreSQL supports extensible B+-trees and R-trees. That means that you can use PostgreSQL to build a B+-tree or R-tree over any data type you want. But B+-trees only support range predicates (<, =, >), and R-trees only support n-D range queries (contains, contained, equals). So if you index, say, an image collection with a PostgreSQL B+-tree, you can only issue queries such as “is imagex equal to imagey”, “is imagex less than imagey” and “is imagex greater than imagey”? Depending on how you define “equals”, “less than” and “greater than” in this context, this could be useful. However, by using a GiST based index, you could create ways to ask domain-specific questions, perhaps “find all images of horses” or “find all over-exposed images”. All it takes to get a GiST access method up and running is to implement seven user-defined methods, which define the behavior of keys in the tree. Of course these methods have to be pretty fancy to support fancy queries, but for all the standard queries (B+-trees, R-trees, etc.) they're relatively straightforward. In short, GiST combines extensibility along with generality, code reuse, and a clean interface.
50.3. Implementation There are seven methods that an index operator class for GiST must provide: consistent Given a predicate p on a tree page, and a user query, q, this method will return false if it is certain that both p and q cannot be true for a given data item. union This method consolidates information in the tree. Given a set of entries, this function generates a new predicate that is true for all the entries. compress Converts the data item into a format suitable for physical storage in an index page.
997
decompress The reverse of the compress method. Converts the index representation of the data item into a format that can be manipulated by the database. penalty Returns a value indicating the “cost” of inserting the new entry into a particular branch of the tree. items will be inserted down the path of least penalty in the tree. picksplit When a page split is necessary, this function decides which entries on the page are to stay on the old page, and which are to move to the new page. same Returns true if two entries are identical, false otherwise.
50.4. Limitations The current implementation of GiST within PostgreSQL has some major limitations: GiST access is not concurrent; the GiST interface doesn't allow the development of certain data types, such as digital trees (see papers by Aoki et al); and there is not yet any support for write-ahead logging of updates in GiST indexes. Solutions to the concurrency problems appear in Marcel Kornacker's thesis; however these ideas have not yet been put into practice in the PostgreSQL implementation. The lack of write-ahead logging is just a small matter of programming, but since it isn't done yet, a crash could render a GiST index inconsistent, forcing a REINDEX.
50.5. Exemplos To see example implementations of index methods implemented using GiST, examine the following contrib modules: btree_gist B-Tree cube Indexing for multi-dimensional cubes intarray RD-Tree for one-dimensional array of int4 values ltree Indexing for tree-like stuctures rtree_gist R-Tree seg Storage and indexed access for “float ranges” tsearch and tsearch2 Full text indexing
998
Capítulo 51. Page Files A description of the database file page format. This section provides an overview of the page format used by PostgreSQL tables and indexes. (Index access methods need not use this page format. At present, all index methods do use this basic format, but the data kept on index metapages usually doesn't follow the item layout rules exactly.) TOAST tables and sequences are formatted just like a regular table. In the following explanation, a byte is assumed to contain 8 bits. In addition, the term item refers to an individual data value that is stored on a page. In a table, an item is a row; in an index, an item is an index entry. Tabela 51-1 shows the basic layout of a page. There are five parts to each page. Tabela 51-1. Sample Page Layout Item
Description
PageHeaderData
20 bytes long. Contains general information about the page, including free space pointers.
ItemPointerData
Array of (offset,length) pairs pointing to the actual items.
Free space
The unallocated space. All new rows are allocated from here, generally from the end.
Items
The actual items themselves.
Special Space
Index access method specific data. Different methods store different data. Empty in ordinary tables.
The first 20 bytes of each page consists of a page header (PageHeaderData). Its format is detailed in Tabela 512. The first two fields deal with WAL related stuff. This is followed by three 2-byte integer fields (pd_lower, pd_upper, and pd_special). These represent byte offsets to the start of unallocated space, to the end of unallocated space, and to the start of the special space. Tabela 51-2. PageHeaderData Layout Field
Type
Length
Description
pd_lsn
XLogRecPtr
8 bytes
LSN: next byte after last byte of xlog
pd_sui
StartUpID
4 bytes
SUI of last changes (currently it's used by heap AM only)
pd_lower
LocationIndex
2 bytes
Offset to start of free space.
pd_upper
LocationIndex
2 bytes
Offset to end of free space.
pd_special
LocationIndex
2 bytes
Offset to start of special space.
pd_pagesize_version
uint16
2 bytes
Page size and layout version number information.
All the details may be found in src/include/storage/bufpage.h. Special space is a region at the end of the page that is allocated at page initialization time and contains information specific to an access method. The last 2 bytes of the page header, pd_pagesize_version, store both the page size and a version indicator. Beginning with PostgreSQL 7.3 the version number is 1; prior releases used version number 0. (The basic page layout and header format has not changed, but the layout of heap row headers has.) The page size is basically only present as a cross-check; there is no support for having more than one page size in an installation.
999
Following the page header are item identifiers (ItemIdData), each requiring four bytes. An item identifier contains a byte-offset to the start of an item, its length in bytes, and a set of attribute bits which affect its interpretation. New item identifiers are allocated as needed from the beginning of the unallocated space. The number of item identifiers present can be determined by looking at pd_lower, which is increased to allocate a new identifier. Because an item identifier is never moved until it is freed, its index may be used on a long-term basis to reference an item, even when the item itself is moved around on the page to compact free space. In fact, every pointer to an item (ItemPointer, also known as CTID) created by PostgreSQL consists of a page number and the index of an item identifier. The items themselves are stored in space allocated backwards from the end of unallocated space. The exact structure varies depending on what the table is to contain. Tables and sequences both use a structure named HeapTupleHeaderData, described below. The final section is the “special section” which may contain anything the access method wishes to store. Ordinary tables do not use this at all (indicated by setting pd_special to equal the pagesize). All table rows are structured the same way. There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field, and the user data. The header is detailed in Tabela 51-3. The actual user data (columns of the row) begins at the offset indicated by t_hoff, which must always be a multiple of the MAXALIGN distance for the platform. The null bitmap is only present if the HEAP_HASNULL bit is set in t_infomask. If it is present it begins just after the fixed header and occupies enough bytes to have one bit per data column (that is, t_natts bits altogether). In this list of bits, a 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not present, all columns are assumed not-null. The object ID is only present if the HEAP_HASOID bit is set in t_infomask. If present, it appears just before the t_hoff boundary. Any padding needed to make t_hoff a MAXALIGN multiple will appear between the null bitmap and the object ID. (This in turn ensures that the object ID is suitably aligned.) Tabela 51-3. HeapTupleHeaderData Layout Field
Type
Length
Description
t_xmin
TransactionId
4 bytes
insert XID stamp
t_cmin
CommandId
4 bytes
insert CID stamp (overlays with t_xmax)
t_xmax
TransactionId
4 bytes
delete XID stamp
t_cmax
CommandId
4 bytes
delete CID stamp (overlays with t_xvac)
t_xvac
TransactionId
4 bytes
XID for VACUUM operation moving row version
t_ctid
ItemPointerData
6 bytes
current TID of this or newer row version
t_natts
int16
2 bytes
number of attributes
t_infomask
uint16
2 bytes
various flags
t_hoff
uint8
1 byte
offset to user data
All the details may be found in src/include/access/htup.h. Interpreting the actual data can only be done with information obtained from other tables, mostly pg_attribute. The particular fields are attlen and attalign. There is no way to directly get a particular attribute, except when there are only fixed width fields and no NULLs. All this trickery is wrapped up in the functions heap_getattr, fastgetattr and heap_getsysattr. To read the data you need to examine each attribute in turn. First check whether the field is NULL according to the null bitmap. If it is, go to the next. Then make sure you have the right alignment. If the field is a fixed width field, then all the bytes are simply placed. If it's a variable length field (attlen == -1) then it's a bit more complicated, using the variable length structure varattrib. Depending on the flags, the data may be either inline, compressed or in another table (TOAST).
1000
Capítulo 52. BKI Backend Interface Backend Interface (BKI) files are scripts in a special language that are input to the PostgreSQL backend running in the special “bootstrap” mode that allows it to perform database functions without a database system already existing. BKI files can therefore be used to create the database system in the first place. (And they are probably not useful for anything else.) initdb uses a BKI file to do part of its job when creating a new database cluster. The input file used by initdb is created as part of building and installing PostgreSQL by a program named genbki.sh from some specially formatted C header files in the source tree. The created BKI file is called postgres.bki and is normally installed in the share subdirectory of the installation tree. Related information may be found in the documentation for initdb.
52.1. BKI File Format This section describes how the PostgreSQL backend interprets BKI files. This description will be easier to understand if the postgres.bki file is at hand as an example. You should also study the source code of initdb to get an idea of how the backend is invoked. BKI input consists of a sequence of commands. Commands are made up of a number of tokens, depending on the syntax of the command. Tokens are usually separated by whitespace, but need not be if there is no ambiguity. There is no special command separator; the next token that syntactically cannot belong to the preceding command starts a new one. (Usually you would put a new command on a new line, for clarity.) Tokens can be certain key words, special characters (parentheses, commas, etc.), numbers, or double-quoted strings. Everything is case sensitive. Lines starting with a # are ignored.
52.2. BKI Commands open tablename Open the table called tablename for further manipulation. close [tablename] Close the open table called tablename. It is an error if tablename is not already opened. If no tablename is given, then the currently open table is closed. create tablename (name1 = type1 [, name2 = type2, ...]) Create a table named tablename with the columns given in parentheses. The type is not necessarily the data type that the column will have in the SQL environment; that is determined by the pg_attribute system catalog. The type here is essentially only used to allocate storage. The following types are allowed: bool, bytea, char (1 byte), name, int2, int2vector, int4, regproc, regclass, regtype, text, oid, tid, xid, cid, oidvector, smgr, _int4 (array), _aclitem (array). Array types can also be indicated by writing [] after the name of the element type. Nota: The table will only be created on disk, it will not automatically be registered in the system catalogs and will therefore not be accessible unless appropriate rows are inserted in pg_class, pg_attribute, etc.
insert [OID = oid_value] (value1 value2 ...) Insert a new row into the open table using value1, value2, etc., for its column values and oid_value for its OID. If oid_value is zero (0) or the clause is omitted, then the next available OID is used. NULL values can be specified using the special key word _null_. Values containing spaces must be double quoted.
1001
declare [unique] index indexname on tablename using amname (opclass1 name1 [, ...]) Create an index named indexname on the table named tablename using the amname access method. The fields to index are called name1, name2 etc., and the operator classes to use are opclass1, opclass2 etc., respectively. build indices Build the indices that have previously been declared.
52.3. Example The following sequence of commands will create the test_table table with the two columns cola and colb of type int4 and text, respectively, and insert two rows into the table. create test_table (cola = int4, colb = text) open test_table insert OID=421 ( 1 "value1" ) insert OID=422 ( 2 _null_ ) close test_table
1002
VIII. Apêndices
1003
Apêndice A. Códigos de erro do PostgreSQL Para todas as mensagens emitidas pelo servidor PostgreSQL, são atribuídos códigos de erro de cinco caracteres conforme as convenções do padrão SQL para os códigos “SQLSTATE”. As aplicações que precisam conhecer qual condição de erro ocorreu geralmente devem testar o código de erro, em vez de analisar o texto da mensagem de erro. Os códigos de error têm menos probabilidade de mudar entre versões do PostgreSQL, e também não estão sujeitos a mudanças devido ao local (pt_BR, etc.) das mensagens de erro. De acordo com o padrão, os dois primeiros caracteres do código de erro indicam a classe do erro, enquanto os três últimos caracteres indicam uma condição específica dentro de uma classe. Portanto, uma aplicação que não reconhece um determinado código de erro, pode ser capaz de inferir o que fazer a partir da classe do erro. A Tabela A-1 relaciona todos os códigos de erro definidos no PostgreSQL 7.4.1 (Na verdade alguns não estão sendo utilizados atualmente, mas são definidos pelo padrão SQL). As classes de erro também estão mostradas. Para cada classe de erro existe um código de erro “padrão” possuindo os três últimos caracteres iguais a 000. Este código é utilizado apenas para as condições de erro que se enquadram na classe mas não possuem nenhum código mais específico atribuído. Tabela A-1. Códigos de erro do PostgreSQL Código de erro
Significado
Class 00
Successful Completion
00000
SUCCESSFUL COMPLETION
Class 01
Warning
01000
WARNING
0100C
WARNING DYNAMIC RESULT SETS RETURNED
01008
WARNING IMPLICIT ZERO BIT PADDING
01003
WARNING NULL VALUE ELIMINATED IN SET FUNCTION
01004
WARNING STRING DATA RIGHT TRUNCATION
Class 02
No Data --- this is also a warning class per SQL99
02000
NO DATA
02001
NO ADDITIONAL DYNAMIC RESULT SETS RETURNED
Class 03
SQL Statement Not Yet Complete
03000
SQL STATEMENT NOT YET COMPLETE
Class 08
Connection Exception
08000
CONNECTION EXCEPTION
08003
CONNECTION DOES NOT EXIST
08006
CONNECTION FAILURE
08001
SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION
08004
SQLSERVER REJECTED ESTABLISHMENT OF SQLCONNECTION
08007
TRANSACTION RESOLUTION UNKNOWN
08P01
PROTOCOL VIOLATION
Class 09
Triggered Action Exception
1004
Código de erro
Significado
09000
TRIGGERED ACTION EXCEPTION
Class 0A
Feature Not Supported
0A000
FEATURE NOT SUPPORTED
Class 0B
Invalid Transaction Initiation
0B000
INVALID TRANSACTION INITIATION
Class 0F
Locator Exception
0F000
LOCATOR EXCEPTION
0F001
INVALID SPECIFICATION
Class 0L
Invalid Grantor
0L000
INVALID GRANTOR
0LP01
INVALID GRANT OPERATION
Class 0P
Invalid Role Specification
0P000
INVALID ROLE SPECIFICATION
Class 21
Cardinality Violation
21000
CARDINALITY VIOLATION
Class 22
Data Exception
22000
DATA EXCEPTION
2202E
ARRAY ELEMENT ERROR
22021
CHARACTER NOT IN REPERTOIRE
22008
DATETIME FIELD OVERFLOW
22012
DIVISION BY ZERO
22005
ERROR IN ASSIGNMENT
2200B
ESCAPE CHARACTER CONFLICT
22022
INDICATOR OVERFLOW
22015
INTERVAL FIELD OVERFLOW
22018
INVALID CHARACTER VALUE FOR CAST
22007
INVALID DATETIME FORMAT
22019
INVALID ESCAPE CHARACTER
2200D
INVALID ESCAPE OCTET
22025
INVALID ESCAPE SEQUENCE
22010
INVALID INDICATOR PARAMETER VALUE
22020
INVALID LIMIT VALUE
22023
INVALID PARAMETER VALUE
2201B
INVALID REGULAR EXPRESSION
22009
INVALID TIME ZONE DISPLACEMENT VALUE
1005
Código de erro
Significado
2200C
INVALID USE OF ESCAPE CHARACTER
2200G
MOST SPECIFIC TYPE MISMATCH
22004
NULL VALUE NOT ALLOWED
22002
NULL VALUE NO INDICATOR PARAMETER
22003
NUMERIC VALUE OUT OF RANGE
22026
STRING DATA LENGTH MISMATCH
22001
STRING DATA RIGHT TRUNCATION
22011
SUBSTRING ERROR
22027
TRIM ERROR
22024
UNTERMINATED C STRING
2200F
ZERO LENGTH CHARACTER STRING
22P01
FLOATING POINT EXCEPTION
22P02
INVALID TEXT REPRESENTATION
22P03
INVALID BINARY REPRESENTATION
22P04
BAD COPY FILE FORMAT
22P05
UNTRANSLATABLE CHARACTER
Class 23
Integrity Constraint Violation
23000
INTEGRITY CONSTRAINT VIOLATION
23001
RESTRICT VIOLATION
23502
NOT NULL VIOLATION
23503
FOREIGN KEY VIOLATION
23505
UNIQUE VIOLATION
23514
CHECK VIOLATION
Class 24
Invalid Cursor State
24000
INVALID CURSOR STATE
Class 25
Invalid Transaction State
25000
INVALID TRANSACTION STATE
25001
ACTIVE SQL TRANSACTION
25002
BRANCH TRANSACTION ALREADY ACTIVE
25008
HELD CURSOR REQUIRES SAME ISOLATION LEVEL
25003
INAPPROPRIATE ACCESS MODE FOR BRANCH TRANSACTION
25004
INAPPROPRIATE ISOLATION LEVEL FOR BRANCH TRANSACTION
25005
NO ACTIVE SQL TRANSACTION FOR BRANCH TRANSACTION
25006
READ ONLY SQL TRANSACTION
25007
SCHEMA AND DATA STATEMENT MIXING NOT SUPPORTED
1006
Código de erro
Significado
25P01
NO ACTIVE SQL TRANSACTION
25P02
IN FAILED SQL TRANSACTION
Class 26
Invalid SQL Statement Name
26000
INVALID SQL STATEMENT NAME
Class 27
Triggered Data Change Violation
27000
TRIGGERED DATA CHANGE VIOLATION
Class 28
Invalid Authorization Specification
28000
INVALID AUTHORIZATION SPECIFICATION
Class 2B
Dependent Privilege Descriptors Still Exist
2B000
DEPENDENT PRIVILEGE DESCRIPTORS STILL EXIST
2BP01
DEPENDENT OBJECTS STILL EXIST
Class 2D
Invalid Transaction Termination
2D000
INVALID TRANSACTION TERMINATION
Class 2F
SQL Routine Exception
2F000
SQL ROUTINE EXCEPTION
2F005
FUNCTION EXECUTED NO RETURN STATEMENT
2F002
MODIFYING SQL DATA NOT PERMITTED
2F003
PROHIBITED SQL STATEMENT ATTEMPTED
2F004
READING SQL DATA NOT PERMITTED
Class 34
Invalid Cursor Name
34000
INVALID CURSOR NAME
Class 38
External Routine Exception
38000
EXTERNAL ROUTINE EXCEPTION
38001
CONTAINING SQL NOT PERMITTED
38002
MODIFYING SQL DATA NOT PERMITTED
38003
PROHIBITED SQL STATEMENT ATTEMPTED
38004
READING SQL DATA NOT PERMITTED
Class 39
External Routine Invocation Exception
39000
EXTERNAL ROUTINE INVOCATION EXCEPTION
39001
INVALID SQLSTATE RETURNED
39004
NULL VALUE NOT ALLOWED
39P01
TRIGGER PROTOCOL VIOLATED
39P02
SRF PROTOCOL VIOLATED
Class 3D
Invalid Catalog Name
3D000
INVALID CATALOG NAME
1007
Código de erro
Significado
Class 3F
Invalid Schema Name
3F000
INVALID SCHEMA NAME
Class 40
Transaction Rollback
40000
TRANSACTION ROLLBACK
40002
INTEGRITY CONSTRAINT VIOLATION
40001
SERIALIZATION FAILURE
40003
STATEMENT COMPLETION UNKNOWN
40P01
DEADLOCK DETECTED
Class 42
Syntax Error or Access Rule Violation
42000
SYNTAX ERROR OR ACCESS RULE VIOLATION
42601
SYNTAX ERROR
42501
INSUFFICIENT PRIVILEGE
42846
CANNOT COERCE
42803
GROUPING ERROR
42830
INVALID FOREIGN KEY
42602
INVALID NAME
42622
NAME TOO LONG
42939
RESERVED NAME
42804
DATATYPE MISMATCH
42P18
INDETERMINATE DATATYPE
42809
WRONG OBJECT TYPE
42703
UNDEFINED COLUMN
42883
UNDEFINED FUNCTION
42P01
UNDEFINED TABLE
42P02
UNDEFINED PARAMETER
42704
UNDEFINED OBJECT
42701
DUPLICATE COLUMN
42P03
DUPLICATE CURSOR
42P04
DUPLICATE DATABASE
42723
DUPLICATE FUNCTION
42P05
DUPLICATE PSTATEMENT
42P06
DUPLICATE SCHEMA
42P07
DUPLICATE TABLE
42712
DUPLICATE ALIAS
42710
DUPLICATE OBJECT
1008
Código de erro
Significado
42702
AMBIGUOUS COLUMN
42725
AMBIGUOUS FUNCTION
42P08
AMBIGUOUS PARAMETER
42P09
AMBIGUOUS ALIAS
42P10
INVALID COLUMN REFERENCE
42611
INVALID COLUMN DEFINITION
42P11
INVALID CURSOR DEFINITION
42P12
INVALID DATABASE DEFINITION
42P13
INVALID FUNCTION DEFINITION
42P14
INVALID PSTATEMENT DEFINITION
42P15
INVALID SCHEMA DEFINITION
42P16
INVALID TABLE DEFINITION
42P17
INVALID OBJECT DEFINITION
Class 44
WITH CHECK OPTION Violation
44000
WITH CHECK OPTION VIOLATION
Class 53
Insufficient Resources
53000
INSUFFICIENT RESOURCES
53100
DISK FULL
53200
OUT OF MEMORY
53300
TOO MANY CONNECTIONS
Class 54
Program Limit Exceeded
54000
PROGRAM LIMIT EXCEEDED
54001
STATEMENT TOO COMPLEX
54011
TOO MANY COLUMNS
54023
TOO MANY ARGUMENTS
Class 55
Object Not In Prerequisite State
55000
OBJECT NOT IN PREREQUISITE STATE
55006
OBJECT IN USE
55P02
CANT CHANGE RUNTIME PARAM
Class 57
Operator Intervention
57000
OPERATOR INTERVENTION
57014
QUERY CANCELED
57P01
ADMIN SHUTDOWN
57P02
CRASH SHUTDOWN
57P03
CANNOT CONNECT NOW
1009
Código de erro
Significado
Class 58
System Error (errors external to PostgreSQL itself)
58030
IO ERROR
58P01
UNDEFINED FILE
58P02
DUPLICATE FILE
Class F0
Configuration File Error
F0000
CONFIG FILE ERROR
F0001
LOCK FILE EXISTS
Class XX
Internal Error
XX000
INTERNAL ERROR
XX001
DATA CORRUPTED
XX002
INDEX CORRUPTED
1010
Apêndice B. Apoio a data e hora O PostgreSQL utiliza um analisador heurístico interno para dar suporte a toda entrada de data e hora. Data e hora são entradas como cadeias de caracteres, e divididas em campos distintos baseado na determinação preliminar do tipo de informação que pode estar contida no campo. Cada campo é interpretado e, em seguida, atribuído um valor numérico, ignorado, ou rejeitado. O analisador contém tabelas internas de procura para todos os campos textuais, incluindo meses, dias da semana e zonas horárias. Este apêndice inclui informações sobre o conteúdo destas tabelas de procura, e descreve os passos utilizados pelo analisador para decodificar data e hora.
B.1. Interpretação de data e hora As entradas dos tipos de data e hora são todas decodificadas utilizando o seguinte procedimento. 1.
2.
Dividir a cadeia de caracteres entrada em elementos (tokens), e categorizar cada elemento como sendo uma cadeia de caracteres, hora, zona horária ou número. a.
Se o elemento numérico contiver dois-pontos (:), então é uma cadeia de caracteres de hora. Incluir todos os dígitos e dois-pontos seguintes.
b.
Se o elemento numérico contiver hífen (-), barra (/), ou dois ou mais pontos (.), então é uma cadeia de caracteres de data que pode conter o mês na forma de texto.
c.
Se o elemento contiver apenas números, então é um campo único ou uma data ISO 8601 concatenada (por exemplo, 19990113 para 13 de janeiro de 1999), ou hora (por exemplo, 141516 para 14:15:16).
d.
Se o elemento começar por um sinal de mais (+) ou de menos (-), então é uma zona horária ou um campo especial.
Se o elemento for uma cadeia de caracteres, estabelecer correspondência com as cadeias de caracteres possíveis. a.
Procurar o elemento em tabela usando pesquisa binária, para ver se é uma cadeia de caracteres especial (por exemplo, today), um dia da semana (por exemplo, Thursday), um mês (por exemplo, January), ou uma palavra ruído (por exemplo, at, on). Definir valores e a máscara de bit para os campos. Por exemplo, colocar ano, mês e dia para today e, adicionalmente, colocar hora, minuto e segundo para now.
3.
b.
Se não for encontrado, fazer uma procura em tabela usando pesquisa binária, semelhante, tentando correspondência com uma zona horária.
c.
Se ainda não for encontrado, gerar erro.
O elemento é um número ou campo numérico. a.
Se contiver 8 ou 6 dígitos, e nenhum outro campo de data foi lido anteriormente, então interpretar como uma “data concatenada” (por exemplo, 19990118 ou 990118). A interpretação é YYYYMMDD ou YYMMDD.
b.
Se o elemento tiver 3 dígitos, e um ano já tiver sido lido, então interpretar como dia do ano.
c.
Se contiver 4 ou 6 dígitos, e o ano já tiver sido lido, então interpretar como hora (HHMM ou HHMMSS).
d.
Se contiver 3 ou mais dígitos, e nenhum campo data foi encontrado anteriormente, interpretar como ano (isto força a ordem yy-mm-dd para os demais campos data).
e.
Senão, a ordem do campo data é assumida como definida por DateStyle: mm-dd-yy, dd-mmyy, ou yy-mm-dd. Gerar erro se o campo mês ou dia estiver fora do intervalo permitido.
1011
4.
Se BC for especificado, tornar o ano negativo e adicionar um para armazenamento interno (Não existe ano zero no Calendário Gregoriano 1 e, portanto, numericamente 1BC se torna o ano zero).
5.
Se BC não for especificado, e o campo do ano tiver comprimento de dois dígitos, então adjustar o ano para quatro dígitos. Se o campo for inferior a 70 adicionar 2000, senão adicionar 1900. Dica: Os anos Gregorianos AD 1-99 2 podem ser entrados utilizando 4 dígitos com zeros à esquerda (por exemplo, 0099 é AD 99). As versões anteriores do PostgreSQL aceitavam anos com três dígitos e com um dígito, mas a partir da versão 7.0 as regras ficaram mais rigorosas para reduzir a possibilidade de ambigüidade.
B.2. Palavras chave para data e hora A Tabela B-1 mostra os elementos reconhecidos como nomes dos meses. Tabela B-1. Abreviaturas dos meses Mês
Abreviatura
Abril
Apr
Agosto
Aug
Dezembro
Dec
Fevereiro
Feb
Janeiro
Jan
Julho
Jul
Junho
Jun
Março
Mar
Novembro
Nov
Outubro
Oct
Setembro
Sep, Sept
Nota: O mês de maio (May) não possui abreviatura explícita, por razões óbvias. 3
A Tabela B-2 mostra os elementos reconhecidos como nomes dos dias da semana. Tabela B-2. Abreviatura dos dias da semana Dia
Abreviatura
Domingo
Sun
Segunda
Mon
Terça
Tue, Tues
Quarta
Wed, Weds
Quinta
Thu, Thur, Thurs
Sexta
Fri
Sábado
Sat
A Tabela B-3 mostra os elementos que servem como modificadores para várias finalidades.
1012
Tabela B-3. Modificadores de campo de data e hora Identificador
Descrição
ABSTIME
Palavra chave ignorada
AM
Hora antes das 12:00
AT
Palavra chave ignorada
JULIAN, JD, J
O próximo campo é dia Juliano
ON
Palavra chave ignorada
PM
Hora após ou às 12:00
T
O próximo campo é hora
A palavra chave ABSTIME é ignorada por razões históricas; nas versões muito antigas do PostgreSQL campos inválidos do tipo abstime eram emitidos como Invalid Abstime. Entretanto, este não é mais o caso, e esta palavra chave provavelmente será retirada em uma versão futura. A Tabela B-4 mostra as abreviaturas de zona horária reconhecidas pelo PostgreSQL nos valores de entrada de data e hora. O PostgreSQL utiliza tabelas internas para decodificar a entrada de zona horária, porque não existe uma interface padrão do sistema operacional para fornecer acesso a informações gerais entre zonas horárias. Entretanto, o sistema operacional é utilizado para fornecer informação de zona horária para a saída. Também tenha em mente que os nomes das zonas horárias reconhecidos por SET TIMEZONE são dependentes do sistema operacional, podendo ter pouco a ver com a Tabela B-4. Por exemplo, alguns sistemas reconhecem valores como 'Europe/Rome' em SET TIMEZONE. A tabela está organizada pelo deslocamento da zona horária relativo à UTC em vez de alfabeticamente, com a finalidade de facilitar a correspondência entre a utilização local e as abreviaturas reconhecidas nos casos em que forem diferentes. Tabela B-4. Abreviaturas das zonas horárias Zona horária
Deslocamento da UTC
Descrição
NZDT
+13:00
New Zealand Daylight-Saving Time
IDLE
+12:00
International Date Line, East
NZST
+12:00
New Zealand Standard Time
NZT
+12:00
New Zealand Time
AESST
+11:00
Australia Eastern Summer Standard Time
ACSST
+10:30
Central Australia Summer Standard Time
CADT
+10:30
Central Australia Daylight-Saving Time
SADT
+10:30
South Australian Daylight-Saving Time
AEST
+10:00
Australia Eastern Standard Time
EAST
+10:00
East Australian Standard Time
GST
+10:00
Guam Standard Time, Russia zone 9
LIGT
+10:00
Melbourne, Australia
SAST
+09:30
South Australia Standard Time
CAST
+09:30
Central Australia Standard Time
AWSST
+09:00
Australia Western Summer Standard Time
1013
Zona horária
Deslocamento da UTC
Descrição
JST
+09:00
Japan Standard Time, Russia zone 8
KST
+09:00
Korea Standard Time
MHT
+09:00
Kwajalein Time
WDT
+09:00
West Australian Daylight-Saving Time
MT
+08:30
Moluccas Time
AWST
+08:00
Australia Western Standard Time
CCT
+08:00
China Coastal Time
WADT
+08:00
West Australian Daylight-Saving Time
WST
+08:00
West Australian Standard Time
JT
+07:30
Java Time
ALMST
+07:00
Almaty Summer Time
WAST
+07:00
West Australian Standard Time
CXT
+07:00
Christmas (Island) Time
MMT
+06:30
Myanmar Time
ALMT
+06:00
Almaty Time
MAWT
+06:00
Mawson (Antarctica) Time
IOT
+05:00
Indian Chagos Time
MVT
+05:00
Maldives Island Time
TFT
+05:00
Kerguelen Time
AFT
+04:30
Afghanistan Time
EAST
+04:00
Antananarivo Summer Time
MUT
+04:00
Mauritius Island Time
RET
+04:00
Reunion Island Time
SCT
+04:00
Mahe Island Time
IRT, IT
+03:30
Iran Time
EAT
+03:00
Antananarivo, Comoro Time
BT
+03:00
Baghdad Time
EETDST
+03:00
Eastern Europe Daylight-Saving Time
HMT
+03:00
Hellas Mediterranean Time (?)
BDST
+02:00
British Double Standard Time
CEST
+02:00
Central European Summer Time
CETDST
+02:00
Central European Daylight-Saving Time
EET
+02:00
Eastern European Time, Russia zone 1
FWT
+02:00
French Winter Time
IST
+02:00
Israel Standard Time
1014
Zona horária
Deslocamento da UTC
Descrição
MEST
+02:00
Middle European Summer Time
METDST
+02:00
Middle Europe Daylight-Saving Time
SST
+02:00
Swedish Summer Time
BST
+01:00
British Summer Time
CET
+01:00
Central European Time
DNT
+01:00
Dansk Normal Tid
FST
+01:00
French Summer Time
MET
+01:00
Middle European Time
MEWT
+01:00
Middle European Winter Time
MEZ
+01:00
Mitteleuropäische Zeit
NOR
+01:00
Norway Standard Time
SET
+01:00
Seychelles Time
SWT
+01:00
Swedish Winter Time
WETDST
+01:00
Western European Daylight-Saving Time
GMT
00:00
Greenwich Mean Time
UT
00:00
Universal Time
UTC
00:00
Universal Coordinated Time
Z
00:00
Same as UTC
ZULU
00:00
Same as UTC
WET
00:00
Western European Time
WAT
-01:00
West Africa Time
FNST
-01:00
Fernando de Noronha Summer Time
FNT
-02:00
Fernando de Noronha Time
BRST
-02:00
Brasilia Summer Time
NDT
-02:30
Newfoundland Daylight-Saving Time
ADT
-03:00
Atlantic Daylight-Saving Time
AWT
-03:00
(unknown)
BRT
-03:00
Brasilia Time
NFT
-03:30
Newfoundland Standard Time
NST
-03:30
Newfoundland Standard Time
AST
-04:00
Atlantic Standard Time (Canada)
ACST
-04:00
Atlantic/Porto Acre Summer Time
EDT
-04:00
Eastern Daylight-Saving Time
ACT
-05:00
Atlantic/Porto Acre Standard Time
CDT
-05:00
Central Daylight-Saving Time
1015
Zona horária
Deslocamento da UTC
Descrição
EST
-05:00
Eastern Standard Time
CST
-06:00
Central Standard Time
MDT
-06:00
Mountain Daylight-Saving Time
MST
-07:00
Mountain Standard Time
PDT
-07:00
Pacific Daylight-Saving Time
AKDT
-08:00
Alaska Daylight-Saving Time
PST
-08:00
Pacific Standard Time
YDT
-08:00
Yukon Daylight-Saving Time
AKST
-09:00
Alaska Standard Time
HDT
-09:00
Hawaii/Alaska Daylight-Saving Time
YST
-09:00
Yukon Standard Time
MART
-09:30
Marquesas Time
AHST
-10:00
Alaska/Hawaii Standard Time
HST
-10:00
Hawaii Standard Time
CAT
-10:00
Central Alaska Time
NT
-11:00
Nome Time
IDLW
-12:00
International Date Line, West
Zona horárias da Austrália. Existem três nomes em conflito entre as zonas horárias da Austrália e as zonas horárias utilizadas normalmente na América do Sul e do Norte: ACST, CST e EST. Se a opção em tempo de execução australian_timezones estiver definida como verdade então ACST, CST, EST e SAT são interpretados como nomes de zonas horárias da Austrália, conforme mostrado na Tabela B-5. Se for falso (que é o padrão), então ACST, CST e EST são tomados como nomes de zonas horárias das Américas, e SAT é interpretado como palavra ruído indicando Sábado. Tabela B-5. Abreviaturas das zonas horárias da Austrália Zona horária
Deslocamento da UTC
Descrição
ACST
+09:30
Central Australia Standard Time
CST
+10:30
Australian Central Standard Time
EST
+10:00
Australian Eastern Standard Time
SAT
+09:30
South Australian Standard Time
Zona horária no Debian (N. do T.). Após instalar o PostgreSQL no Debian, a zona horária era desconhecida: SELECT current_setting('TimeZone'); current_setting ----------------unknown (1 linha)
Ao tentar especificar BRT como zona horária retornava uma mensagem de erro: SELECT set_config('TimeZone','BRT',false); ERROR: unrecognized time zone name: "BRT"
1016
Como o arquivo /etc/timezone da máquina continha America/Sao_Paulo, foi utilizado este valor para especificar a zona horária no lugar de BRT, o que foi aceito pelo PostgreSQL. SELECT set_config('TimeZone','America/Sao_Paulo',false); set_config ------------------America/Sao_Paulo (1 linha) SELECT current_setting('TimeZone'); current_setting ------------------America/Sao_Paulo (1 linha) SELECT TIMESTAMP '2004-02-19 12:00:00' AT TIME ZONE 'GMT'; timezone -----------------------2004-02-19 09:00:00-03 (1 linha)
Mas o valor definido desta forma só se mantinha durante a sessão do usuário. Para fazer com que valesse para todas as sessões de todos os usuários foi necessário editar o arquivo postgresql.conf e especificar timezone = 'America/Sao_Paulo'.
B.3. História das unidades A Data Juliana foi inventada pelo estudioso francês Joseph Justus Scaliger (1540-1609) e, provavelmente, recebeu este nome devido ao pai do Scaliger, o estudioso italiano Julius Caesar Scaliger (1484-1558). Os astrônomos têm utilizado a Data Juliana para atribuir um número único para cada dia a partir de 1 de janeiro de 4713 AC. Esta é a tão falada Data Juliana (DJ). DJ 0 (zero) designa as 24 horas desde o meio-dia UTC de 1 de janeiro de 4713 AC até meio-dia UTC de 2 de janeiro de 4713 AC. A “Data Juliana” é diferente do “Calendário Juliano”. O Calendário Juliano foi introduzido por Julius Caesar em 45 AC. Ficou em uso corrente até 1582, quando os países começaram a mudar para o Calendário Gregoriano. No Calendário Juliano, o ano tropical é aproximado como 365 1/4 dias = 365,25 dias. Isto ocasiona um erro de aproximadamente 1 dia a cada 128 anos. O erro acumulado fez o Papa Gregório XIII reformar o calendário de acordo com as instruções do Concílio de Trento. No Calendário Gregoriano o ano tropical é aproximado como 365 + 97 / 400 dias = 365,2425 dias. Portanto, leva aproximadamente 3.300 anos para o ano tropical se deslocar um dia em relação ao Calendário Gregoriano. A aproximação 365+97/400 é obtida colocando 97 anos bissextos a cada 400 anos, utilizando as seguintes regras: Cada ano divisível por 4 é um ano bissexto. Entretanto, cada ano divisível por 100 não é um ano bissexto. Entretanto, todo ano divisível por 400 é um ano bissexto sempre. Portanto, 1700, 1800, 1900, 2100 e 2200 não são anos bissextos. Porém, 1600, 2000 e 2400 são anos bissextos. Contrapondo, no antigo Calendário Juliano todos os anos divisíveis por 4 eram bissextos. A Bula Papal de fevereiro de 1582 decretou que 10 dias deveriam ser retirados de outubro de 1582, fazendo com que 15 de outubro viesse imediatamente após 4 de outubro. Foi respeitado na Itália, Polônia, Portugal e Espanha. Outros países católicos seguiram logo após, mas os países protestantantes relutaram em mudar, e os países ortodoxos gregos não mudaram até o início do século 20. A reforma foi seguida pela Inglaterra e seus domínios (incluindo o que agora são os EUA) em 1752. Assim, 2 de setembro de 1752 foi seguido por 14 de setembro de 1752. Por isso, nos sistemas Unix, o programa cal produz a seguinte informação:
1017
$ cal 9 1752 setembro 1752 Do Se Te Qu Qu Se 1 2 14 15 17 18 19 20 21 22 24 25 26 27 28 29
Sá 16 23 30
Nota: O padrão SQL declara que “Dentro da definição do ‘literal data/hora’, os ‘valores de data/hora’ são restritos pelas regras naturais para data e hora de acordo com o Calendário Gregoriano”. As datas entre 1752-09-03 e 1752-09-13, embora excluídas em alguns países pela Bula Papal, estão em conformidade com as “regras naturais” sendo, portanto, datas válidas.
Calendários diferentes foram elaborados em várias partes do mundo, diversos anteriores as sistema Gregoriano. Por exemplo, o início do Calendário Chinês remonta ao século 14 AC. Diz a lenda que o Imperador Huangdi inventou o calendário em 2637 AC. A República Popular da China utiliza o Calendário Gregoriano para as finalidades civis. O Calendário Chinês é utilizado para determinar as festividades.
Notas 1. São dois os Calendário Cristãos ainda em uso no mundo: O Calendário Juliano foi proposto por Sosígenes, astrônomo de Alexandria, e introduzido por Julio César em 45 AC. Foi usado pelas igrejas e países cristãos até o século XVI, quando começou a ser trocado pelo Calendário Gregoriano. Alguns países, como a Grécia e a Rússia, o usaram até o século passado. Ainda é usado por algumas Igrejas Ortodoxas, entre elas a Igreja Russa; O Calendário Gregoriano foi proposto por Aloysius Lilius, astrônomo de Nápoles, e adotado pelo Papa Gregório XIII, seguindo as instruções do Concílio de Trento (1545-1563). O decreto instituindo esse calendário foi publicado em 24 de fevereiro de 1582. - Calendários (http://www.observatorio.ufmg.br/pas39.htm) (N. do T.) 2. AD = Anno Domini = DC (N. do T.) 3. Razões óbvias somente em inglês, obviamente! (N. do T.)
1018
Apêndice C. Palavras chave do SQL A Tabela C-1 relaciona todos os termos (tokens) que são palavras chave no padrão SQL e no PostgreSQL 7.4.1. Os conceitos básicos podem ser encontrados na Seção 4.1.1. O padrão SQL faz distinção entre palavras chave reservadas e não reservadas. De acordo com o padrão, as palavras chave reservadas são as únicas palavras chave reais; nunca são permitidas como identificadores. As palavras chave não reservadas somente possuem significado especial em determinados contextos, sendo possível utilizá-las como identificador em outros contextos. Em sua maior parte, as palavras chave não reservadas são, na verdade, nomes de tabelas nativas e funções especificadas pelo padrão SQL. Essencialmente, o conceito de palavra chave não reservada existe apenas para declarar a associação desta palavra com um significado predefinido em alguns contextos. No analisador do PostgreSQL a vida é um pouco mais complicada. Existem várias classes diferentes de termos, indo desde aqueles que nunca podem ser utilizados como identificador, até aqueles que não possuem nenhum status especial no analisador se comparado com um identificador comum (Geralmente, este último é o caso das funções especificadas pelo padrão SQL). Mesmo as palavras chave reservadas não são totalmente reservadas no PostgreSQL, sendo possível utilizá-las como títulos de colunas (por exemplo, SELECT 55 AS CHECK, embora CHECK seja uma palavra chave reservada). Na coluna PostgreSQL da Tabela C-1 são classificadas como “não reservadas” as palavras chave explicitamente reconhecidas pelo analisador mas permitidas na maioria ou em todos os contextos onde um identificador é esperado. Existem algumas palavras chave não reservadas que não podem ser utilizadas como nome de função ou de tipo de dado, estando devidamente indicado (Em sua maioria, estas palavras representam funções nativas ou tipos de dado com sintaxe especial. A função ou o tipo continua disponível, mas não pode ser redefinido pelo usuário). Na coluna “reservadas” estão os termos permitidos apenas como títulos de coluna utilizando “AS” (e, talvez, em muito poucos outros contextos). Algumas palavras chave reservadas são permitidas como nome de função; isto também está indicado na tabela. Como regra geral, acontecendo erros indevidos do analisador em comandos contendo como identificador qualquer uma das palavras chave listadas, deve-se tentar colocar o identificador entre aspas para ver se o problema desaparece. Antes de estudar a Tabela C-1, é importante compreender o fato de uma palavra chave não ser reservada no PostgreSQL não significa que a funcionalidade associada a esta palavra chave não está implementada. Inversamente, a presença de uma palavra chave não indica a existência da funcionalidade. Tabela C-1. Palavras chave do SQL Palavra chave
PostgreSQL
ABORT
não-reservada
ABSOLUTE
não-reservada
ACCESS
não-reservada
ACTION
não-reservada
ADA
não-reservada
reservada
reservada
reservada
reservada
nãoreservada
nãoreservada
reservada
reservada
reservada
ADMIN AFTER
SQL 92
nãoreservada
ABS
ADD
SQL 99
não-reservada
reservada
1019
Palavra chave
PostgreSQL
SQL 99
AGGREGATE
não-reservada
reservada reservada
ALIAS ALL
SQL 92
reservada
ALLOCATE
reservada
reservada
reservada
reservada
reservada
reservada
ALTER
não-reservada
ANALYSE
reservada
ANALYZE
reservada
AND
reservada
reservada
reservada
ANY
reservada
reservada
reservada
reservada
reservada
ARE ARRAY
reservada
reservada
AS
reservada
reservada
reservada
ASC
reservada
reservada
reservada
nãoreservada
ASENSITIVE
ASSERTION
não-reservada
reservada
ASSIGNMENT
não-reservada
nãoreservada nãoreservada
ASYMMETRIC
AT
não-reservada
reservada
reservada
nãoreservada
ATOMIC
AUTHORIZATION
reservada
reservada (pode ser função)
AVG
reservada
reservada
nãoreservada
reservada
BACKWARD
não-reservada
BEFORE
não-reservada
reservada
BEGIN
não-reservada
reservada
reservada
BETWEEN
reservada (pode ser função)
nãoreservada
reservada
BIGINT
não-reservada (não pode ser função ou tipo)
BINARY
reservada (pode ser função)
reservada
BIT
não-reservada (não pode ser função ou tipo)
reservada
BITVAR
reservada
nãoreservada
1020
Palavra chave
PostgreSQL
SQL 99
SQL 92
BIT_LENGTH
nãoreservada
reservada
BLOB
reservada
BOOLEAN
não-reservada (não pode ser função ou tipo)
reservada
BOTH
reservada
reservada reservada
BREADTH BY
não-reservada
C
CACHE
reservada
nãoreservada
nãoreservada
reservada não-reservada
nãoreservada nãoreservada
CARDINALITY
CASCADE
reservada
não-reservada
CALL CALLED
reservada
não-reservada
CASCADED
reservada
reservada
reservada
reservada
CASE
reservada
reservada
reservada
CAST
reservada
reservada
reservada
CATALOG
reservada
reservada
CATALOG_NAME
nãoreservada
nãoreservada
CHAIN
não-reservada
nãoreservada
CHAR
não-reservada (não pode ser função ou tipo)
reservada
reservada
CHARACTER
não-reservada (não pode ser função ou tipo)
reservada
reservada
CHARACTERISTICS
não-reservada
CHARACTER_LENGTH
nãoreservada
reservada
CHARACTER_SET_CATALOG
nãoreservada
nãoreservada
CHARACTER_SET_NAME
nãoreservada
nãoreservada
CHARACTER_SET_SCHEMA
nãoreservada
nãoreservada
CHAR_LENGTH
nãoreservada
reservada
1021
Palavra chave
PostgreSQL
SQL 99
SQL 92
CHECK
reservada
reservada
reservada
nãoreservada
CHECKED
CHECKPOINT
não-reservada
CLASS
não-reservada
reservada
CLASS_ORIGIN
nãoreservada
CLOB
reservada
CLOSE
não-reservada
CLUSTER
não-reservada
COALESCE
não-reservada (não pode ser função ou tipo)
nãoreservada
reservada
reservada
nãoreservada
reservada
nãoreservada
nãoreservada
reservada
reservada
COLLATION
reservada
reservada
COLLATION_CATALOG
nãoreservada
nãoreservada
COLLATION_NAME
nãoreservada
nãoreservada
COLLATION_SCHEMA
nãoreservada
nãoreservada
reservada
reservada
COLUMN_NAME
nãoreservada
nãoreservada
COMMAND_FUNCTION
nãoreservada
nãoreservada
COMMAND_FUNCTION_CODE
nãoreservada
COBOL
COLLATE
COLUMN
reservada
reservada
COMMENT
não-reservada
COMMIT
não-reservada
reservada
reservada
COMMITTED
não-reservada
nãoreservada
nãoreservada
COMPLETION
reservada
CONDITION_NUMBER
nãoreservada
nãoreservada
CONNECT
reservada
reservada
CONNECTION
reservada
reservada
CONNECTION_NAME
não-
não-
1022
Palavra chave
PostgreSQL
SQL 99
SQL 92
reservada
reservada
CONSTRAINT
reservada
reservada
reservada
CONSTRAINTS
não-reservada
reservada
reservada
CONSTRAINT_CATALOG
nãoreservada
nãoreservada
CONSTRAINT_NAME
nãoreservada
nãoreservada
CONSTRAINT_SCHEMA
nãoreservada
nãoreservada
CONSTRUCTOR
reservada
CONTAINS
nãoreservada
CONTINUE
reservada
reservada
nãoreservada
reservada
CORRESPONDING
reservada
reservada
COUNT
nãoreservada
reservada
reservada
reservada
reservada
reservada
CONVERSION
não-reservada
CONVERT
não-reservada (não pode ser função ou tipo)
COPY
não-reservada
CREATE
reservada
CREATEDB
não-reservada
CREATEUSER
não-reservada
CROSS
reservada (pode ser função)
CUBE
reservada
CURRENT
reservada
reservada
reservada
reservada
CURRENT_DATE
reservada
CURRENT_PATH
reservada
CURRENT_ROLE
reservada
CURRENT_TIME
reservada
reservada
reservada
CURRENT_TIMESTAMP
reservada
reservada
reservada
CURRENT_USER
reservada
reservada
reservada
CURSOR
não-reservada
reservada
reservada
nãoreservada
nãoreservada
CURSOR_NAME
CYCLE DATA
não-reservada
reservada reservada
nãoreservada
1023
Palavra chave
PostgreSQL
SQL 99
SQL 92
DATABASE
não-reservada
DATE
reservada
reservada
DATETIME_INTERVAL_CODE
nãoreservada
nãoreservada
DATETIME_INTERVAL_PRECISION
nãoreservada
nãoreservada
DAY
não-reservada
reservada
reservada
DEALLOCATE
não-reservada
reservada
reservada
DEC
não-reservada (não pode ser função ou tipo)
reservada
reservada
DECIMAL
não-reservada (não pode ser função ou tipo)
reservada
reservada
DECLARE
não-reservada
reservada
reservada
DEFAULT
reservada
reservada
reservada
DEFAULTS
não-reservada
DEFERRABLE
reservada
reservada
reservada
DEFERRED
não-reservada
reservada
reservada
nãoreservada
DEFINED
DEFINER
não-reservada
nãoreservada
DELETE
não-reservada
reservada
DELIMITER
não-reservada
DELIMITERS
não-reservada
DEPTH
reservada
DEREF
reservada reservada
reservada
DESCRIBE
reservada
reservada
DESCRIPTOR
reservada
reservada
DESTROY
reservada
DESTRUCTOR
reservada
DETERMINISTIC
reservada
DIAGNOSTICS
reservada
DICTIONARY
reservada
DISCONNECT
reservada
DISPATCH
nãoreservada
DESC
reservada
reservada
reservada
reservada
1024
Palavra chave
PostgreSQL
SQL 99
SQL 92
DISTINCT
reservada
reservada
reservada
DO
reservada
DOMAIN
não-reservada
reservada
reservada
DOUBLE
não-reservada
reservada
reservada
DROP
não-reservada
reservada
reservada
DYNAMIC
reservada
DYNAMIC_FUNCTION
nãoreservada
DYNAMIC_FUNCTION_CODE
nãoreservada
nãoreservada
EACH
não-reservada
reservada
ELSE
reservada
reservada
reservada
ENCODING
não-reservada
ENCRYPTED
não-reservada
END
reservada
reservada
reservada
END-EXEC
reservada
reservada
EQUALS
reservada
ESCAPE
não-reservada
reservada
EXCEPTION EXCLUDING
não-reservada
EXCLUSIVE
não-reservada
EXEC EXECUTE
reservada
reservada
EVERY EXCEPT
reservada
não-reservada
reservada
reservada
reservada
reservada
reservada
reservada
reservada
reservada
nãoreservada
EXISTING
EXISTS
não-reservada (não pode ser função ou tipo)
nãoreservada
reservada
EXPLAIN
não-reservada
EXTERNAL
não-reservada
reservada
reservada
EXTRACT
não-reservada (não pode ser função ou tipo)
nãoreservada
reservada
FALSE
reservada
reservada
reservada
FETCH
não-reservada
reservada
reservada
FINAL
nãoreservada
1025
Palavra chave
PostgreSQL
SQL 99
SQL 92
FIRST
não-reservada
reservada
reservada
FLOAT
não-reservada (não pode ser função ou tipo)
reservada
reservada
FOR
reservada
reservada
reservada
FORCE
não-reservada
FOREIGN
reservada
reservada
reservada
nãoreservada
nãoreservada
FOUND
reservada
reservada
FREE
reservada
FORTRAN
FORWARD
não-reservada
FREEZE
reservada (pode ser função)
FROM
reservada
reservada
reservada
FULL
reservada (pode ser função)
reservada
reservada
FUNCTION
não-reservada
reservada
G
nãoreservada
GENERAL
reservada
GENERATED
nãoreservada
GET
reservada
reservada
reservada
reservada
GO
reservada
reservada
GOTO
reservada
reservada
reservada
reservada
GLOBAL
GRANT
não-reservada
reservada
nãoreservada
GRANTED
GROUP
reservada
HANDLER
não-reservada
HAVING
reservada
reservada
reservada
nãoreservada
HIERARCHY
não-reservada
nãoreservada reservada
HOST HOUR
reservada
reservada
GROUPING
HOLD
reservada
não-reservada
reservada
reservada
1026
Palavra chave
PostgreSQL
SQL 99
SQL 92
IDENTITY
reservada
reservada
IGNORE
reservada
ILIKE
reservada (pode ser função)
IMMEDIATE
não-reservada
IMMUTABLE
não-reservada
reservada
reservada
nãoreservada
IMPLEMENTATION
IMPLICIT
não-reservada
IN
reservada (pode ser função)
INCLUDING
não-reservada
INCREMENT
não-reservada
INDEX
não-reservada
reservada
reservada
INDICATOR
reservada
reservada
INFIX
nãoreservada
INHERITS
não-reservada reservada
INITIALIZE INITIALLY
reservada
reservada
reservada
INNER
reservada (pode ser função)
reservada
reservada
INOUT
não-reservada
reservada
INPUT
não-reservada
reservada
reservada
INSENSITIVE
não-reservada
nãoreservada
reservada
INSERT
não-reservada
reservada
reservada
INSTANCE
nãoreservada
INSTANTIABLE
nãoreservada
INSTEAD
não-reservada
INT
não-reservada (não pode ser função ou tipo)
reservada
reservada
INTEGER
não-reservada (não pode ser função ou tipo)
reservada
reservada
INTERSECT
reservada
reservada
reservada
INTERVAL
não-reservada (não pode ser função ou tipo)
reservada
reservada
INTO
reservada
reservada
reservada
INVOKER
não-reservada
não-
1027
Palavra chave
PostgreSQL
SQL 99
SQL 92
reservada IS
reservada (pode ser função)
ISNULL
reservada (pode ser função)
ISOLATION
não-reservada
reservada (pode ser função)
reservada
reservada
reservada
não-reservada
reservada
KEY_MEMBER
nãoreservada
KEY_TYPE
nãoreservada
LANCOMPILER
não-reservada
LANGUAGE
não-reservada
reservada
reservada
reservada
reservada
LARGE LAST
reservada
nãoreservada
K
KEY
reservada
reservada
ITERATE JOIN
reservada
não-reservada
reservada
reservada
reservada
LATERAL LEADING
reservada
reservada
reservada
LEFT
reservada (pode ser função)
reservada
reservada
LENGTH
nãoreservada
nãoreservada
LESS
reservada
LEVEL
não-reservada
reservada
reservada
LIKE
reservada (pode ser função)
reservada
reservada
LIMIT
reservada
reservada
LISTEN
não-reservada
LOAD
não-reservada
LOCAL
não-reservada
reservada
LOCALTIME
reservada
reservada
LOCALTIMESTAMP
reservada
reservada
LOCATION
não-reservada reservada
LOCATOR LOCK LOWER
reservada
não-reservada nãoreservada
reservada
1028
Palavra chave
PostgreSQL
SQL 99
M
nãoreservada
MAP
reservada reservada
reservada
nãoreservada
reservada
MESSAGE_LENGTH
nãoreservada
nãoreservada
MESSAGE_OCTET_LENGTH
nãoreservada
nãoreservada
MESSAGE_TEXT
nãoreservada
nãoreservada
METHOD
nãoreservada
MIN
nãoreservada
reservada
reservada
reservada
MATCH
não-reservada
SQL 92
MAX
MAXVALUE
não-reservada
MINUTE
não-reservada
MINVALUE
não-reservada nãoreservada
MOD
MODE
não-reservada
MODIFIES
reservada
MODIFY
reservada
MODULE
reservada
reservada
reservada
reservada
nãoreservada
nãoreservada
MUMPS
nãoreservada
nãoreservada
NAME
nãoreservada
nãoreservada
MONTH
não-reservada
MORE
MOVE
não-reservada
NAMES
não-reservada
reservada
reservada
NATIONAL
não-reservada
reservada
reservada
NATURAL
reservada (pode ser função)
reservada
reservada
NCHAR
não-reservada (não pode ser função ou tipo)
reservada
reservada
NCLOB
reservada
1029
Palavra chave
PostgreSQL
SQL 99
NEW
reservada
reservada
NEXT
não-reservada
reservada
reservada
NO
não-reservada
reservada
reservada
NOCREATEDB
não-reservada
NOCREATEUSER
não-reservada
NONE
não-reservada (não pode ser função ou tipo)
reservada
NOT
reservada
reservada
reservada
NOTHING
não-reservada
NOTIFY
não-reservada
NOTNULL
reservada (pode ser função)
NULL
reservada
reservada
reservada
nãoreservada
nãoreservada
nãoreservada
reservada
nãoreservada
nãoreservada
reservada
reservada
NULLABLE
NULLIF
não-reservada (não pode ser função ou tipo)
NUMBER
NUMERIC
não-reservada (não pode ser função ou tipo)
SQL 92
OBJECT
reservada
OCTET_LENGTH
nãoreservada
reservada reservada
OF
não-reservada
reservada
OFF
reservada
reservada
OFFSET
reservada
OIDS
não-reservada
OLD
reservada
reservada
ON
reservada
reservada
reservada
ONLY
reservada
reservada
reservada
OPEN
reservada
reservada
OPERATION
reservada
OPERATOR
não-reservada
OPTION
não-reservada
reservada
nãoreservada
OPTIONS
OR
reservada
reservada
reservada
reservada
1030
Palavra chave
PostgreSQL
SQL 99
SQL 92
ORDER
reservada
reservada
reservada
reservada
ORDINALITY OUT
não-reservada
reservada
OUTER
reservada (pode ser função)
reservada
reservada
reservada
reservada reservada
OUTPUT OVERLAPS
reservada (pode ser função)
nãoreservada
OVERLAY
não-reservada (não pode ser função ou tipo)
nãoreservada nãoreservada
OVERRIDING
OWNER
não-reservada
PAD
reservada
PARAMETER
reservada
PARAMETERS
reservada
PARAMETER_MODE
nãoreservada
PARAMETER_NAME
nãoreservada
PARAMETER_ORDINAL_POSITION
nãoreservada
PARAMETER_SPECIFIC_CATALOG
nãoreservada
PARAMETER_SPECIFIC_NAME
nãoreservada
PARAMETER_SPECIFIC_SCHEMA
nãoreservada
PARTIAL
não-reservada
PASCAL
PASSWORD
não-reservada
PATH
não-reservada
PENDANT
não-reservada
PLACING
reservada
PLI
POSITION
POSTFIX
não-reservada (não pode ser função ou tipo)
reservada
reservada
reservada
nãoreservada
nãoreservada
reservada
nãoreservada
nãoreservada
nãoreservada
reservada
reservada
1031
Palavra chave
PostgreSQL
SQL 99
SQL 92
PRECISION
não-reservada
reservada
reservada
PREFIX
reservada
PREORDER
reservada
PREPARE
não-reservada
reservada
reservada
PRESERVE
não-reservada
reservada
reservada
PRIMARY
reservada
reservada
reservada
PRIOR
não-reservada
reservada
reservada
PRIVILEGES
não-reservada
reservada
reservada
PROCEDURAL
não-reservada
PROCEDURE
não-reservada
reservada
reservada
reservada
reservada
reservada
reservada
PUBLIC READ
não-reservada
reservada
READS REAL
não-reservada (não pode ser função ou tipo)
RECHECK
não-reservada
reservada
RECURSIVE
reservada
REF
reservada
REFERENCES
reservada
reservada
reservada
reservada
reservada
REFERENCING REINDEX
não-reservada
RELATIVE
não-reservada
RENAME
não-reservada
REPEATABLE
REPLACE
não-reservada
RESET
não-reservada
RESTART
não-reservada
RESTRICT
não-reservada
reservada
reservada
nãoreservada
nãoreservada
reservada
reservada
RESULT
reservada
RETURN
reservada
RETURNED_LENGTH
nãoreservada
nãoreservada
RETURNED_OCTET_LENGTH
nãoreservada
nãoreservada
RETURNED_SQLSTATE
nãoreservada
nãoreservada
1032
Palavra chave
PostgreSQL
SQL 99
RETURNS
não-reservada
reservada
REVOKE
não-reservada
reservada
reservada
RIGHT
reservada (pode ser função)
reservada
reservada
reservada
ROLE ROLLBACK
SQL 92
não-reservada
reservada
ROLLUP
reservada
ROUTINE
reservada
ROUTINE_CATALOG
nãoreservada
ROUTINE_NAME
nãoreservada
ROUTINE_SCHEMA
nãoreservada
reservada
ROW
não-reservada (não pode ser função ou tipo)
reservada
ROWS
não-reservada
reservada
reservada
nãoreservada
nãoreservada
ROW_COUNT
RULE
não-reservada
SAVEPOINT
reservada
SCALE
nãoreservada
nãoreservada
reservada
reservada
SCHEMA_NAME
nãoreservada
nãoreservada
SCOPE
reservada
SCHEMA
SCROLL
não-reservada
não-reservada
não-reservada
SECTION
reservada
reservada
reservada
reservada
SECURITY
não-reservada
nãoreservada
SELECT
reservada
reservada
SELF
nãoreservada
SENSITIVE
nãoreservada
SEQUENCE
reservada
reservada
SEARCH SECOND
reservada
não-reservada
reservada
reservada
1033
Palavra chave
PostgreSQL
SQL 99
SQL 92
SERIALIZABLE
não-reservada
nãoreservada
nãoreservada
nãoreservada
nãoreservada
SERVER_NAME
SESSION
não-reservada
reservada
reservada
SESSION_USER
reservada
reservada
reservada
SET
não-reservada
reservada
reservada
SETOF
não-reservada (não pode ser função ou tipo) reservada
SETS SHARE
não-reservada
SHOW
não-reservada
SIMILAR
reservada (pode ser função)
nãoreservada
SIMPLE
não-reservada
nãoreservada
SIZE
reservada
reservada
SMALLINT
não-reservada (não pode ser função ou tipo)
reservada
reservada
SOME
reservada
reservada
reservada
SOURCE
nãoreservada
SPACE
reservada
SPECIFIC
reservada
SPECIFICTYPE
reservada
SPECIFIC_NAME
nãoreservada
SQL
reservada
reservada
reservada
SQLCODE
reservada
SQLERROR
reservada
SQLEXCEPTION
reservada
SQLSTATE
reservada
SQLWARNING
reservada
STABLE
não-reservada
START
não-reservada
STATIC
reservada reservada
STATE STATEMENT
reservada
não-reservada
reservada reservada
1034
Palavra chave
PostgreSQL
STATISTICS
não-reservada
STDIN
não-reservada
STDOUT
não-reservada
STORAGE
não-reservada
STRICT
não-reservada
SQL 99
STRUCTURE
reservada
STYLE
nãoreservada
SUBCLASS_ORIGIN
nãoreservada
SUBLIST
nãoreservada
nãoreservada
nãoreservada
reservada
SUM
nãoreservada
reservada
SYMMETRIC
nãoreservada
SUBSTRING
SYSID
não-reservada (não pode ser função ou tipo)
SQL 92
não-reservada
SYSTEM
nãoreservada
SYSTEM_USER
reservada
reservada
reservada
reservada
nãoreservada
nãoreservada
reservada
reservada
TABLE
reservada
TABLE_NAME
TEMP
não-reservada
TEMPLATE
não-reservada
TEMPORARY
não-reservada
TERMINATE
reservada
THAN
reservada
THEN
reservada
reservada
reservada
TIME
não-reservada (não pode ser função ou tipo)
reservada
reservada
TIMESTAMP
não-reservada (não pode ser função ou tipo)
reservada
reservada
TIMEZONE_HOUR
reservada
reservada
TIMEZONE_MINUTE
reservada
reservada
reservada
reservada
TO
reservada
1035
Palavra chave
PostgreSQL
SQL 99
SQL 92
TOAST
não-reservada
TRAILING
reservada
reservada
reservada
TRANSACTION
não-reservada
reservada
reservada
TRANSACTIONS_COMMITTED
nãoreservada
TRANSACTIONS_ROLLED_BACK
nãoreservada
TRANSACTION_ACTIVE
nãoreservada
TRANSFORM
nãoreservada
TRANSFORMS
nãoreservada
TRANSLATE
nãoreservada
reservada
TRANSLATION
reservada
reservada
TREAT
não-reservada (não pode ser função ou tipo)
reservada
TRIGGER
não-reservada
reservada
TRIGGER_CATALOG
nãoreservada
TRIGGER_NAME
nãoreservada
TRIGGER_SCHEMA
nãoreservada
TRIM
não-reservada (não pode ser função ou tipo)
nãoreservada
reservada
TRUE
reservada
reservada
reservada
TRUNCATE
não-reservada
TRUSTED
não-reservada
TYPE
não-reservada
nãoreservada
nãoreservada
UNCOMMITTED
nãoreservada
nãoreservada
UNDER
reservada
UNENCRYPTED
não-reservada
UNION
reservada
reservada
reservada
UNIQUE
reservada
reservada
reservada
UNKNOWN
não-reservada
reservada
reservada
1036
Palavra chave
PostgreSQL
SQL 99
SQL 92
UNLISTEN
não-reservada
UNNAMED
nãoreservada
nãoreservada
UNNEST
reservada
UNTIL
não-reservada
UPDATE
não-reservada
UPPER
reservada
reservada
nãoreservada
reservada
USAGE
não-reservada
reservada
reservada
USER
reservada
reservada
reservada
USER_DEFINED_TYPE_CATALOG
nãoreservada
USER_DEFINED_TYPE_NAME
nãoreservada
USER_DEFINED_TYPE_SCHEMA
nãoreservada
USING
reservada
VACUUM
não-reservada
VALID
não-reservada
VALIDATOR
não-reservada
VALUE
reservada
reservada
reservada
reservada
VALUES
não-reservada
reservada
reservada
VARCHAR
não-reservada (não pode ser função ou tipo)
reservada
reservada
reservada
VARIABLE VARYING
não-reservada
VERBOSE
reservada (pode ser função)
VERSION
não-reservada
VIEW
não-reservada
VOLATILE
não-reservada
WHEN
reservada
WHENEVER
reservada
reservada
reservada
reservada
reservada
reservada
reservada
reservada
WHERE
reservada
reservada
reservada
WITH
não-reservada
reservada
reservada
WITHOUT
não-reservada
reservada
WORK
não-reservada
reservada
reservada
WRITE
não-reservada
reservada
reservada
1037
Palavra chave
PostgreSQL
SQL 99
SQL 92
YEAR
não-reservada
reservada
reservada
ZONE
não-reservada
reservada
reservada
1038
Apêndice D. Conformidade com o SQL Esta seção tem por objetivo dar uma visão geral sobre até que ponto o PostgreSQL está em conformidade com o padrão SQL. A conformidade total com o padrão, ou uma declaração completa sobre a conformidade com o padrão, é complicada e não é particularmente útil. Portanto, esta seção só pode mostrar uma visão geral. O nome formal do padrão SQL é ISO/IEC 9075 “Database Language SQL”. A versão revisada do padrão é liberada de tempos em tempos; a mais recente surgiu em 1999. Esta versão é referida como ISO/IEC 9075:1999 ou, informalmente, como SQL99. A versão anterior a esta foi a SQL92. O desenvolvimento do PostgreSQL tenta manter a conformidade com a última versão oficial do padrão, quando esta conformidade não contradiz as funcionalidades tradicionais ou o senso comum. Quando este texto foi escrito, uma votação se encontrava em andamento para realizar uma nova revisão do padrão, a qual, se aprovada, se tornará algum dia a referência de conformidade para o desenvolvimento das versões futuras do PostgreSQL. O SQL92 definiu três conjuntos de funcionalidades para conformidade: Entrada, Intermediário e Completo. A maioria dos produtos que clamavam conformidade com este padrão SQL estavam em conformidade apenas com o nível de Entrada, porque o conjunto completo de funcionalidades nos níveis Intermediário e Completo era muito volumoso, ou em conflito com comportamentos legados. O SQL99 define um conjunto maior de funcionalidades individuais em vez dos três níveis amplos não efetivos presentes no SQL92. Um subconjunto grande destas funcionalidades representa as funcionalidades “núcleo”, que toda implementação SQL em conformidade deve atender. As demais funcionalidades são inteiramente opcionais. Algumas funcionalidades opcionais são agrupadas em “pacotes”, com os quais as implementações SQL podem clamar conformidade, portanto clamando conformidade com um determinado grupo de funcionalidades. O padrão SQL99 está dividido em 5 partes: Framework, Foundation, Call Level Interface, Persistent Stored Modules e Host Language Bindings. O PostgreSQL somente cobre as partes 1, 2 e 5. A parte 3 é semelhante à interface ODBC, e a parte 4 é semelhante à linguagem de programação PL/pgSQL, mas a conformidade exata não é pretendida em nenhum destes dois casos. A seguir é fornecida uma lista das funcionalidades suportadas pelo PostgreSQL, seguida por uma lista de funcionalidades definidas no SQL99 ainda não são suportadas pelo PostgreSQL. As duas listas são aproximadas: podem existir pequenos detalhes que não estão em conformidade para uma funcionalidade listada como suportada, enquanto grande parte de uma funcionalidade não suportada pode, na verdade, estar implementada. O corpo principal da documentação sempre contém informações mais precisas sobre o que funciona e que não funciona. Nota: Os códigos de funcionalidade contendo hífen são subfuncionalidades. Portanto, se uma determinada subfuncionalidade não for suportada, a funcionalidade principal é descrita como não suportada, mesmo que outras subfuncionalidades sejam suportadas.
D.1. Funcionalidades suportadas Identificador
Pacote
Descrição
B012
Core
Embedded C
B021
Comentário
Direct SQL
E011
Core
Numeric data types
E011-01
Core
INTEGER and SMALLINT data types
E011-02
Core
REAL, DOUBLE PRECISION, and FLOAT data types
E011-03
Core
DECIMAL and NUMERIC data types
E011-04
Core
Arithmetic operators
1039
Identificador
Pacote
Descrição
E011-05
Core
Numeric comparison
E011-06
Core
Implicit casting among the numeric data types
E021
Core
Character data types
E021-01
Core
CHARACTER data type
E021-02
Core
CHARACTER VARYING data type
E021-03
Core
Character literals
E021-04
Core
CHARACTER_LENGTH function
E021-05
Core
OCTET_LENGTH function
E021-06
Core
SUBSTRING function
E021-07
Core
Character concatenation
E021-08
Core
UPPER and LOWER functions
E021-09
Core
TRIM function
E021-10
Core
Implicit casting among the character data types
E021-11
Core
POSITION function
E021-12
Core
Character comparison
E031
Core
Identifiers
E031-01
Core
Delimited identifiers
E031-02
Core
Lower case identifiers
E031-03
Core
Trailing underscore
E051
Core
Basic query specification
E051-01
Core
SELECT DISTINCT
E051-02
Core
GROUP BY clause
E051-04
Core
GROUP BY can contain columns not in <select list>
E051-05
Core
Select list items can be renamed
E051-06
Core
HAVING clause
E051-07
Core
Qualified * in select list
E051-08
Core
Correlation names in the FROM clause
E051-09
Core
Rename columns in the FROM clause
E061
Core
Basic predicates and search conditions
E061-01
Core
Comparison predicate
E061-02
Core
BETWEEN predicate
E061-03
Core
IN predicate with list of values
E061-04
Core
LIKE predicate
E061-05
Core
LIKE predicate ESCAPE clause
Comentário
AS is required
1040
Identificador
Pacote
Descrição
E061-06
Core
NULL predicate
E061-07
Core
Quantified comparison predicate
E061-08
Core
EXISTS predicate
E061-09
Core
Subqueries in comparison predicate
E061-11
Core
Subqueries in IN predicate
E061-12
Core
Subqueries in quantified comparison predicate
E061-13
Core
Correlated subqueries
E061-14
Core
Search condition
E071
Core
Basic query expressions
E071-01
Core
UNION DISTINCT table operator
E071-02
Core
UNION ALL table operator
E071-03
Core
EXCEPT DISTINCT table operator
E071-05
Core
Columns combined via table operators need not have exactly the same data type
E071-06
Core
Table operators in subqueries
E081-01
Core
SELECT privilege
E081-02
Core
DELETE privilege
E081-03
Core
INSERT privilege at the table level
E081-04
Core
UPDATE privilege at the table level
E081-06
Core
REFERENCES privilege at the table level
E081-08
Core
WITH GRANT OPTION
E091
Core
Set functions
E091-01
Core
AVG
E091-02
Core
COUNT
E091-03
Core
MAX
E091-04
Core
MIN
E091-05
Core
SUM
E091-06
Core
ALL quantifier
E091-07
Core
DISTINCT quantifier
E101
Core
Basic data manipulation
E101-01
Core
INSERT statement
E101-03
Core
Searched UPDATE statement
E101-04
Core
Searched DELETE statement
E111
Core
Single row SELECT statement
E121-01
Core
DECLARE CURSOR
Comentário
1041
Identificador
Pacote
Descrição
E121-02
Core
ORDER BY columns need not be in select list
E121-03
Core
Value expressions in ORDER BY clause
E121-04
Core
OPEN statement
E121-08
Core
CLOSE statement
E121-10
Core
FETCH statement implicit NEXT
E121-17
Core
WITH HOLD cursors
E131
Core
Null value support (nulls in lieu of values)
E141
Core
Basic integrity constraints
E141-01
Core
NOT NULL constraints
E141-02
Core
UNIQUE constraints of NOT NULL columns
E141-03
Core
PRIMARY KEY constraints
E141-04
Core
Basic FOREIGN KEY constraint with the NO ACTION default for both referential delete action and referential update action
E141-06
Core
CHECK constraints
E141-07
Core
Column defaults
E141-08
Core
NOT NULL inferred on PRIMARY KEY
E141-10
Core
Names in a foreign key can be specified in any order
E151
Core
Transaction support
E151-01
Core
COMMIT statement
E151-02
Core
ROLLBACK statement
E152
Core
Basic SET TRANSACTION statement
E152-01
Core
SET TRANSACTION statement: ISOLATION LEVEL SERIALIZABLE clause
E152-02
Core
SET TRANSACTION statement: READ ONLY and READ WRITE clauses
E161
Core
SQL comments using leading double minus
E171
Core
SQLSTATE support
F021
Core
Basic information schema
F021-01
Core
COLUMNS view
F021-02
Core
TABLES view
F021-03
Core
VIEWS view
F021-04
Core
TABLE_CONSTRAINTS view
F021-05
Core
REFERENTIAL_CONSTRAINTS view
F021-06
Core
CHECK_CONSTRAINTS view
F031
Core
Basic schema manipulation
Comentário
1042
Identificador
Pacote
Descrição
F031-01
Core
CREATE TABLE statement to create persistent base tables
F031-02
Core
CREATE VIEW statement
F031-03
Core
GRANT statement
F031-04
Core
ALTER TABLE statement: ADD COLUMN clause
F031-13
Core
DROP TABLE statement: RESTRICT clause
F031-16
Core
DROP VIEW statement: RESTRICT clause
F031-19
Core
REVOKE statement: RESTRICT clause
F032
CASCADE drop behavior
F033
ALTER TABLE statement: DROP COLUMN clause
F034
Extended REVOKE statement
F034-01
REVOKE statement performed by other than the owner of a schema object
F034-02
REVOKE statement: GRANT OPTION FOR clause
F034-03
REVOKE statement to revoke a privilege that the grantee has WITH GRANT OPTION
F041
Core
Basic joined table
F041-01
Core
Inner join (but not necessarily the INNER keyword)
F041-02
Core
INNER keyword
F041-03
Core
LEFT OUTER JOIN
F041-04
Core
RIGHT OUTER JOIN
F041-05
Core
Outer joins can be nested
F041-07
Core
The inner table in a left or right outer join can also be used in an inner join
F041-08
Core
All comparison operators are supported (rather than just =)
F051
Core
Basic date and time
F051-01
Core
DATE data type (including support of DATE literal)
F051-02
Core
TIME data type (including support of TIME literal) with fractional seconds precision of at least 0
F051-03
Core
TIMESTAMP data type (including support of TIMESTAMP literal) with fractional seconds precision of at least 0 and 6
F051-04
Core
Comparison predicate on DATE, TIME, and TIMESTAMP data types
F051-05
Core
Explicit CAST between datetime types and character types
F051-06
Core
CURRENT_DATE
Comentário
1043
Identificador
Pacote
Descrição
F051-07
Core
LOCALTIME
F051-08
Core
LOCALTIMESTAMP
F052
Enhanced datetime facilities
Intervals and datetime arithmetic
F081
Core
UNION and EXCEPT in views
F111-02
Comentário
READ COMMITTED isolation level
F131
Core
Grouped operations
F131-01
Core
WHERE, GROUP BY, and HAVING clauses supported in queries with grouped views
F131-02
Core
Multiple tables supported in queries with grouped views
F131-03
Core
Set functions supported in queries with grouped views
F131-04
Core
Subqueries with GROUP BY and HAVING clauses and grouped views
F131-05
Core
Single row SELECT with GROUP BY and HAVING clauses and grouped views
F171
Multiple schemas per user
F191
Enhanced integrity management
Referential delete actions
F201
Core
CAST function
F221
Core
Explicit defaults
F222
INSERT statement: DEFAULT VALUES clause
F231
Privilege Tables
F231-01
TABLE_PRIVILEGES view
F231-02
COLUMN_PRIVILEGES view
F231-03
USAGE_PRIVILEGES view
F251
Domain support
F261
Core
CASE expression
F261-01
Core
Simple CASE
F261-02
Core
Searched CASE
F261-03
Core
NULLIF
F261-04
Core
COALESCE
F271
Compound character literals
F281
LIKE enhancements
F302
OLAP facilities
INTERSECT table operator
F302-01
OLAP facilities
INTERSECT DISTINCT table operator
1044
Identificador
Pacote
Descrição
F302-02
OLAP facilities
INTERSECT ALL table operator
F304
OLAP facilities
EXCEPT ALL table operator
F311-01
Core
CREATE SCHEMA
F311-02
Core
CREATE TABLE for persistent base tables
F311-03
Core
CREATE VIEW
F311-05
Core
GRANT statement
F321
User authorization
F361
Subprogram support
F381
Extended schema manipulation
F381-01
ALTER TABLE statement: ALTER COLUMN clause
F381-02
ALTER TABLE statement: ADD CONSTRAINT clause
F381-03
ALTER TABLE statement: DROP CONSTRAINT clause
F391
Long identifiers
F401
OLAP facilities
Extended joined table
F401-01
OLAP facilities
NATURAL JOIN
F401-02
OLAP facilities
FULL OUTER JOIN
F401-03
OLAP facilities
UNION JOIN
F401-04
OLAP facilities
CROSS JOIN
F411
Enhanced datetime facilities
Time zone specification
F421
National character
F431
Read-only scrollable cursors
F431-01
FETCH with explicit NEXT
F431-02
FETCH FIRST
F431-03
FETCH LAST
F431-04
FETCH PRIOR
F431-05
FETCH ABSOLUTE
F431-06
FETCH RELATIVE
F441
Extended set function support
F471
Core
Scalar subquery values
F481
Core
Expanded NULL predicate
F491
Enhanced integrity management
Constraint management
F501
Core
Features and conformance views
Comentário
1045
Identificador
Pacote
Descrição
F501-01
Core
SQL_FEATURES view
F501-02
Core
SQL_SIZING view
F501-03
Core
SQL_LANGUAGES view
F502
Enhanced documentation tables
F502-01
SQL_SIZING_PROFILES view
F502-02
SQL_IMPLEMENTATION_INFO view
F502-03
SQL_PACKAGES view
F511
BIT data type
F531
Temporary tables
F555
Enhanced datetime facilities
Enhanced seconds precision
F561
Full value expressions
F571
Truth value tests
F591
OLAP facilities
Derived tables
F611
Indicator data types
F651
Catalog name qualifiers
F701
Enhanced integrity management
Referential update actions
F711
ALTER domain
F761
Session management
F771
Connection management
F781
Self-referencing operations
F791
Insensitive cursors
F801
Full set function
S071
Enhanced object support
SQL paths in function and type name resolution
S111
Enhanced object support
ONLY in query expressions
S211
Enhanced object support, SQL/MM support
User-defined cast functions
T031
BOOLEAN data type
T141
SIMILAR predicate
T151
DISTINCT predicate
T171
LIKE clause in table definition
T191
Enhanced integrity management
Comentário
Referential action RESTRICT
1046
Identificador
Pacote
Descrição
T201
Enhanced integrity management
Comparable data types for referential constraints
T211-01
Enhanced integrity management, Active database
Triggers activated on UPDATE, INSERT, or DELETE of one base table
T211-02
Enhanced integrity management, Active database
BEFORE triggers
T211-03
Enhanced integrity management, Active database
AFTER triggers
T211-04
Enhanced integrity management, Active database
FOR EACH ROW triggers
T211-07
Enhanced integrity management, Active database
TRIGGER privilege
T212
Enhanced integrity management
Enhanced trigger capability
T231
SENSITIVE cursors
T241
START TRANSACTION statement
T312
OVERLAY function
T321-01
Core
User-defined functions with no overloading
T321-03
Core
Function invocation
T321-06
Core
ROUTINES view
T321-07
Core
PARAMETERS view
T322
PSM, SQL/MM support
Overloading of SQL-invoked functions and procedures
T323
Explicit security for external routines
T351
Bracketed SQL comments (/*...*/ comments)
T441
ABS and MOD functions
T501
Enhanced EXISTS predicate
T551
Optional key words for default syntax
T581
Regular expression substring function
T591
UNIQUE constraints of possibly null columns
Comentário
1047
D.2. Funcionalidades não suportadas As seguintes funcionalidades definidas no SQL99 não estão implementadas nesta versão do PostgreSQL. Em alguns poucos casos, uma funcionalidade equivalente está disponível. Identificador
Pacote
Descrição
B011
Core
Embedded Ada
B013
Core
Embedded COBOL
B014
Core
Embedded Fortran
B015
Core
Embedded MUMPS
B016
Core
Embedded Pascal
B017
Core
Embedded PL/I
B031
Basic dynamic SQL
B032
Extended dynamic SQL
B032-01
<describe input> statement
B041
Extensions to embedded SQL exception declarations
B051
Enhanced execution rights
E081
Core
Basic Privileges
E081-05
Core
UPDATE privilege at the column level
E081-07
Core
REFERENCES privilege at the column level
E121
Core
Basic cursor support
E121-06
Core
Positioned UPDATE statement
E121-07
Core
Positioned DELETE statement
E153
Core
Updatable queries with subqueries
E182
Core
Module language
F111
Isolation levels other than SERIALIZABLE
F111-01
READ UNCOMMITTED isolation level
F111-03
REPEATABLE READ isolation level
F121
Basic diagnostics management
F121-01
GET DIAGNOSTICS statement
F121-02
SET TRANSACTION statement: DIAGNOSTICS SIZE clause
F181
Multiple module support
F291
UNIQUE predicate
F301
CORRESPONDING in query expressions
F311
Core
Schema definition statement
F311-04
Core
CREATE VIEW: WITH CHECK OPTION
F341
Comentário
Usage tables
1048
Identificador
Pacote
Descrição
F451
Character set definition
F461
Named character sets
F521
Enhanced integrity management
Assertions
F641
OLAP facilities
Row and table constructors
F661 F671
Simple tables Enhanced integrity management
Subqueries in CHECK
F691
Collation and translation
F721
Deferrable constraints
F731
INSERT column privileges
F741
Referential MATCH types
F751
View CHECK enhancements
F811
Extended flagging
F812
Comentário
Core
intentionally omitted
foreign keys only
no partial match yet
Basic flagging
F813
Extended flagging for "Core SQL Flagging" and "Catalog Lookup" only
F821
Local table references
F831
Full cursor update
F831-01
Updatable scrollable cursors
F831-02
Updatable ordered cursors
S011
Core
Distinct data types
S011-01
Core
USER_DEFINED_TYPES view
S023
Basic object support, SQL/MM support
Basic structured types
S024
Enhanced object support, SQL/MM support
Enhanced structured types
S041
Basic object support
Basic reference types
S043
Enhanced object support
Enhanced reference types
S051
Basic object support
Create table of type
S081
Enhanced object support
Subtables
S091
SQL/MM support
Basic array support
S091-01
SQL/MM support
Arrays of built-in data types
1049
Identificador
Pacote
Descrição
S091-02
SQL/MM support
Arrays of distinct types
S091-03
SQL/MM support
Array expressions
S092
SQL/MM support
Arrays of user-defined types
S094
Arrays of reference types
S151
Basic object support
Type predicate
S161
Enhanced object support
Subtype treatment
S201
SQL routines on arrays
S201-01
Array parameters
S201-02
Array as result type of functions
S231
Enhanced object support
S232 S241
Comentário
Structured type locators Array locators
Enhanced object support
Transform functions
S251
User-defined orderings
S261
Specific type method
T011
Timestamp in Information Schema
T041
Basic object support
Basic LOB data type support
T041-01
Basic object support
BLOB data type
T041-02
Basic object support
CLOB data type
T041-03
Basic object support
POSITION, LENGTH, LOWER, TRIM, UPPER, and SUBSTRING functions for LOB data types
T041-04
Basic object support
Concatenation of LOB data types
T041-05
Basic object support
LOB locator: non-holdable
T042
Extended LOB data type support
T051
Row types
T111
Updatable joins, unions, and columns
T121
WITH (excluding RECURSIVE) in query expression
T131
Recursive query
T211
Enhanced integrity management, Active database
Basic trigger capability
T211-05
Enhanced integrity management, Active database
Ability to specify a search condition that must be true before the trigger is invoked
1050
Identificador
Pacote
Descrição
T211-06
Enhanced integrity management, Active database
Support for run-time rules for the interaction of triggers and constraints
T211-08
Enhanced integrity management, Active database
Multiple triggers for the same event are executed in the order in which they were created
T251
SET TRANSACTION statement: LOCAL option
T261
Chained transactions
T271
Savepoints
T281
SELECT privilege with column granularity
T301
Functional Dependencies
T321
Core
Basic SQL-invoked routines
T321-02
Core
User-defined stored procedures with no overloading
T321-04
Core
CALL statement
T321-05
Core
RETURN statement
T331
Basic roles
T332
Extended roles
T401
INSERT into a cursor
T411
UPDATE statement: SET ROW option
T431
OLAP facilities
Comentário
intentionally omitted
CUBE and ROLLUP operations
T461
Symmetric BETWEEN predicate
T471
Result sets return value
T491
LATERAL derived table
T511
Transaction counts
T541
Updatable table references
T561
Holdable locators
T571
Array-returning external SQL-invoked functions
T601
Local cursor references
1051
Apêndice E. Release Notes E.1. Release 7.4.1 Release date: 2003-12-22
This release contains a variety of fixes from 7.4.
E.1.1. Migration to version 7.4.1 A dump/restore is not required for those running 7.4. If you want to install the fixes in the information schema you need to reload it into the database. This is either accomplished by initializing a new cluster by running initdb, or by running the following sequence of SQL commands in each database (ideally including template1) as a superuser in psql, after installing the new release: DROP SCHEMA information_schema CASCADE; \i /usr/local/pgsql/share/information_schema.sql
Substitute your installation path in the second command.
E.1.2. Changes • Fixed bug in CREATE SCHEMA parsing in ECPG (Michael) • Fix compile error when --enable-thread-safety and --with-perl are used together (Peter) • Fix for subqueries that used hash joins (Tom) Certain subqueries that used hash joins would crash because of improperly shared structures. • Fix free space map compaction bug (Tom) This fixes a bug where compaction of the free space map could lead to a database server shutdown. • Fix for Borland compiler build of libpq (Bruce) • Fix netmask() and hostmask() to return the maximum-length masklen (Tom) Fix these functions to return values consistent with pre-7.4 releases. • Several contrib/pg_autovacuum fixes Fixes include improper variable initialization, missing vacuum after TRUNCATE, and duration computation overflow for long vacuums. • Allow compile of contrib/cube under Cygwin (Jason Tishler) • Fix Solaris use of password file when no passwords are defined (Tom) Fix crash on Solaris caused by use of any type of password authentication when no passwords were defined. • JDBC fix for thread problems, other fixes • Fix for bytea index lookups (Joe) • Fix information schema for bit data types (Peter) • Force zero_damaged_pages to be on during recovery from WAL • Prevent some obscure cases of “variable not in subplan target lists” • Make PQescapeBytea and byteaout consistent with each other (Joe) • Escape bytea output for bytes > 0x7e(Joe) If different client encodings are used for bytea output and input, it is possible for bytea values to be corrupted by the differing encodings. This fix escapes all bytes that might be affected. • Added missing SPI_finish() calls to dblink's get_tuple_of_interest() (Joe)
1052
• New Czech FAQ • Fix information schema view constraint_column_usage for foreign keys (Peter) • ECPG fixes (Michael) • Fix bug with multiple IN subqueries and joins in the subqueries (Tom) • Alllow COUNT('x') to work (Tom) • Install ECPG include files for Informix compatibility into separate directory (Peter) Some names of ECPG include files for Informix compatibility conflicted with operating system include files. By installing them in their own directory, name conflicts have been reduced. • Fix SSL memory leak (Neil) This release fixes a bug in 7.4 where SSL didn't free all memory it allocated. • Prevent pg_service.conf from using service name as default dbname (Bruce) • Fix local ident authentication on FreeBSD (Tom)
E.2. Release 7.4 Release date: 2003-11-17
E.2.1. Overview Major changes in this release: IN / NOT IN subqueries are now much more efficient
In previous releases, IN/NOT IN subqueries were joined to the upper query by sequentially scanning the subquery looking for a match. The 7.4 code uses the same sophisticated techniques used by ordinary joins and so is much faster. An IN will now usually be as fast as or faster than an equivalent EXISTS subquery; this reverses the conventional wisdom that applied to previous releases. Improved GROUP BY processing by using hash buckets In previous releases, rows to be grouped had to be sorted first. The 7.4 code can do GROUP BY without sorting, by accumulating results into a hash table with one entry per group. It will still use the sort technique, however, if the hash table is estimated to be too large to fit in sort_mem. New multikey hash join capability In previous releases, hash joins could only occur on single keys. This release allows multicolumn hash joins. Queries using the explicit JOIN syntax are now better optimized Prior releases evaluated queries using the explicit JOIN syntax only in the order implied by the syntax. 7.4 allows full optimization of these queries, meaning the optimizer considers all possible join orderings and chooses the most efficient. Outer joins, however, must still follow the declared ordering. Faster and more powerful regular expression code The entire regular expression module has been replaced with a new version by Henry Spencer, originally written for Tcl. The code greatly improves performance and supports several flavors of regular expressions. Function-inlining for simple SQL functions Simple SQL functions can now be inlined by including their SQL in the main query. This improves performance by eliminating per-call overhead. That means simple SQL functions now behave like macros. Full support for IPv6 connections and IPv6 address data types Previous releases allowed only IPv4 connections, and the IP data types only supported IPv4 addresses. This release adds full IPv6 support in both of these areas.
1053
Major improvements in SSL performance and reliability Several people very familiar with the SSL API have overhauled our SSL code to improve SSL key negotiation and error recovery. Make free space map efficiently reuse empty index pages, and other free space management improvements In previous releases, B-tree index pages that were left empty because of deleted rows could only be reused by rows with index values similar to the rows originally indexed on that page. In 7.4, VACUUM records empty index pages and allows them to be reused for any future index rows. SQL-standard information schema The information schema provides a standardized and stable way to access information about the schema objects defined in a database. Cursors conform more closely to the SQL standard The commands FETCH and MOVE have been overhauled to conform more closely to the SQL standard. Cursors can exist outside transactions These cursors are also called holdable cursors. New client-to-server protocol The new protocol adds error codes, more status information, faster startup, better support for binary data transmission, parameter values separated from SQL commands, prepared statements available at the protocol level, and cleaner recovery from COPY failures. The older protocol is still supported by both server and clients. libpq and ECPG applications are now fully thread-safe While previous libpq releases already supported threads, this release improves thread safety by fixing some non-thread-safe code that was used during database connection startup. The configure option -enable-thread-safety must be used to enable this feature. New version of full-text indexing A new full-text indexing suite is available in contrib/tsearch2. New autovacuum tool The new autovacuum tool in contrib/autovacuum monitors the database statistics tables for INSERT/UPDATE/DELETE activity and automatically vacuums tables when needed. Array handling has been improved and moved into the server core Many array limitations have been removed, and arrays behave more like fully-supported data types.
E.2.2. Migration to version 7.4 A dump/restore using pg_dump is required for those wishing to migrate data from any previous release. Observe the following incompatibilities: •
The server-side autocommit setting was removed and reimplemented in client applications and languages. Server-side autocommit was causing too many problems with languages and applications that wanted to control their own autocommit behavior, so autocommit was removed from the server and added to individual client APIs as appropriate.
•
Error message wording has changed substantially in this release. Significant effort was invested to make the messages more consistent and user-oriented. If your applications try to detect different error conditions by parsing the error message, you are strongly encouraged to use the new error code facility instead.
•
Inner joins using the explicit JOIN syntax may behave differently because they are now better optimized.
•
A number of server configuration parameters have been renamed for clarity, primarily those related to logging.
1054
or MOVE 0 now does nothing. In prior releases, FETCH 0 would fetch all remaining rows, and MOVE 0 would move to the end of the cursor.
• FETCH 0
and MOVE now return the actual number of rows fetched/moved, or zero if at the beginning/end of the cursor. Prior releases would return the row count passed to the command, not the number of rows actually fetched or moved.
• FETCH
now can process files that use carriage-return or carriage-return/line-feed end-of-line sequences. Literal carriage-returns and line-feeds are no longer accepted in data values; use \r and \n instead.
• COPY
•
Trailing spaces are now trimmed when converting from type char(n) to varchar(n) or text. This is what most people always expected to happen anyway.
•
The data type float(p) now measures p in binary digits, not decimal digits. The new behavior follows the SQL standard.
•
Ambiguous date values now must match the ordering specified by the datestyle setting. In prior releases, a date specification of 10/20/03 was interpreted as a date in October even if datestyle specified that the day should be first. 7.4 will throw an error if a date specification is invalid for the current setting of datestyle.
•
The functions oidrand, oidsrand, and userfntest have been removed. These functions were determined to be no longer useful.
•
String literals specifying time-varying date/time values, such as 'now' or 'today' will no longer work as expected in column default expressions; they now cause the time of the table creation to be the default, not the time of the insertion. Functions such as now(), current_timestamp, or current_date should be used instead. In previous releases, there was special code so that strings such as 'now' were interpreted at INSERT time and not at table creation time, but this work around didn't cover all cases. Release 7.4 now requires that defaults be defined properly using functions such as now() or current_timestamp. These will work in all situations.
•
The dollar sign ($) is no longer allowed in operator names. It can instead be a non-first character in identifiers. This was done to improve compatibility with other database systems, and to avoid syntax problems when parameter placeholders ($n) are written adjacent to operators.
E.2.3. Changes Below you will find a detailed account of the changes between release 7.4 and the previous major release. E.2.3.1. Server Operation Changes •
Allow IPv6 server connections (Nigel Kukard, Johan Jordaan, Bruce, Tom, Kurt Roeckx, Andrew Dunstan)
•
Fix SSL to handle errors cleanly (Nathan Mueller) In prior releases, certain SSL API error reports were not handled correctly. This release fixes those problems.
•
SSL protocol security and performance improvements (Sean Chittenden) SSL key renegotiation was happening too frequently, causing poor SSL performance. Also, initial key handling was improved.
•
Print lock information when a deadlock is detected (Tom) This allows easier debugging of deadlock situations.
•
Update /tmp socket modification times regularly to avoid their removal (Tom) This should help prevent /tmp directory cleaner administration scripts from removing server socket files.
•
Enable PAM for Mac OS X (Aaron Hillegass)
•
Make B-tree indexes fully WAL-safe (Tom)
1055
In prior releases, under certain rare cases, a server crash could cause B-tree indexes to become corrupt. This release removes those last few rare cases. •
Allow B-tree index compaction and empty page reuse (Tom)
•
Fix inconsistent index lookups during split of first root page (Tom) In prior releases, when a single-page index split into two pages, there was a brief period when another database session could miss seeing an index entry. This release fixes that rare failure case.
•
Improve free space map allocation logic (Tom)
•
Preserve free space information between server restarts (Tom) In prior releases, the free space map was not saved when the postmaster was stopped, so newly started servers had no free space information. This release saves the free space map, and reloads it when the server is restarted.
•
Add start time to pg_stat_activity (Neil)
•
New code to detect corrupt disk pages; erase with zero_damaged_pages (Tom)
•
New client/server protocol: faster, no username length limit, allow clean exit from COPY (Tom)
•
Add transaction status, table ID, column ID to client/server protocol (Tom)
•
Add binary I/O to client/server protocol (Tom)
•
Remove autocommit server setting; move to client applications (Tom)
•
New error message wording, error codes, and three levels of error detail (Tom, Joe, Peter)
E.2.3.2. Performance Improvements •
Add hashing for GROUP BY aggregates (Tom)
•
Make nested-loop joins be smarter about multicolumn indexes (Tom)
•
Allow multikey hash joins (Tom)
•
Improve constant folding (Tom)
•
Add ability to inline simple SQL functions (Tom)
•
Reduce memory usage for queries using complex functions (Tom) In prior releases, functions returning allocated memory would not free it until the query completed. This release allows the freeing of function-allocated memory when the function call completes, reducing the total memory used by functions.
•
Improve GEQO optimizer performance (Tom) This release fixes several inefficiencies in the way the GEQO optimizer manages potential query paths.
•
Allow IN/NOT IN to be handled via hash tables (Tom)
•
Improve NOT IN (subquery) performance (Tom)
•
Allow most IN subqueries to be processed as joins (Tom)
•
Pattern matching operations can use indexes regardless of locale (Peter) There is no way for non-ASCII locales to use the standard indexes for LIKE comparisons. This release adds a way to create a special index for LIKE.
•
Allow the postmaster to preload libraries using preload_libraries (Joe) For shared libraries that require a long time to load, this option is available so the library can be preloaded in the postmaster and inherited by all database sessions.
•
Improve optimizer cost computations, particularly for subqueries (Tom)
•
Avoid sort when subquery ORDER BY matches upper query (Tom)
•
Deduce that WHERE a.x = b.y AND b.y = 42 also means a.x = 42 (Tom)
1056
•
Allow hash/merge joins on complex joins (Tom)
•
Allow hash joins for more data types (Tom)
•
Allow join optimization of explicit inner joins, disable with join_collapse_limit (Tom)
•
Add parameter from_collapse_limit to control conversion of subqueries to joins (Tom)
•
Use faster and more powerful regular expression code from Tcl (Henry Spencer, Tom)
•
Use bit-mapped relation sets in the optimizer (Tom)
•
Improve connection startup time (Tom) The new client/server protocol requires fewer network packets to start a database session.
•
Improve trigger/constraint performance (Stephan)
•
Improve speed of col IN (const, const, const, ...) (Tom)
•
Fix hash indexes which were broken in rare cases (Tom)
•
Improve hash index concurrency and speed (Tom) Prior releases suffered from poor hash index performance, particularly for high concurrency situations. This release fixes that, and the development group is interested in reports comparing B-tree and hash index performance.
•
Align shared buffers on 32-byte boundary for copy speed improvement (Manfred Spraul) Certain CPU's perform faster data copies when addresses are 32-byte aligned.
•
Data type numeric reimplemented for better performance (Tom) numeric used to be stored in base 100. The new code uses base 10000, for significantly better performance.
E.2.3.3. Server Configuration Changes •
Rename server parameter server_min_messages to log_min_messages (Bruce) This was done so most parameters that control the server logs begin with log_.
•
Rename show_*_stats to log_*_stats (Bruce)
•
Rename show_source_port to log_source_port (Bruce)
•
Rename hostname_lookup to log_hostname (Bruce)
•
Add checkpoint_warning to warn of excessive checkpointing (Bruce) In prior releases, it was difficult to determine if checkpoint was happening too frequently. This feature adds a warning to the server logs when excessive checkpointing happens.
•
New read-only server parameters for localization (Tom)
•
Change debug server log messages to output as DEBUG rather than LOG (Bruce)
•
Prevent server log variables from being turned off by non-superusers (Bruce) This is a security feature so non-superusers cannot disable logging that was enabled by the administrator.
• log_min_messages/client_min_messages
now controls debug_* output (Bruce)
This centralizes client debug information so all debug output can be sent to either the client or server logs. •
Add Mac OS X Rendezvous server support (Chris Campbell) This allows Mac OS X hosts to query the network for available PostgreSQL servers.
•
Add ability to print only slow statements using log_min_duration_statement (Christopher) This is an often requested debugging feature that allows administrators to see only slow queries in their server logs.
•
Allow pg_hba.conf to accept netmasks in CIDR format (Andrew Dunstan)
1057
This allows administrators to merge the host IP address and netmask fields into a single CIDR field in pg_hba.conf. •
New read-only parameter is_superuser (Tom)
•
New parameter log_error_verbosity to control error detail (Tom) This works with the new error reporting feature to supply additional error information like hints, file names and line numbers.
• postgres --describe-config
now dumps server config variables (Aizaz Ahmed, Peter)
This option is useful for administration tools that need to know the configuration variable names and their minimums, maximums, defaults, and descriptions. •
Add new columns in pg_settings: context, type, source, min_val, max_val (Joe)
•
Make default shared_buffers 1000 and max_connections 100, if possible (Tom) Prior versions defaulted to 64 shared buffers so PostgreSQL would start on even very old systems. This release tests the amount of shared memory allowed by the platform and selects more reasonable default values if possible. Of course, users are still encouraged to evaluate their resource load and size shared_buffers accordingly.
•
New pg_hba.conf record type hostnossl to prevent SSL connections (Jon Jensen) In prior releases, there was no way to prevent SSL connections if both the client and server supported SSL. This option allows that capability.
•
Remove parameter geqo_random_seed (Tom)
•
Add server parameter regex_flavor to control regular expression processing (Tom)
•
Make pg_ctl better handle nonstandard ports (Greg)
E.2.3.4. Query Changes •
New SQL-standard information schema (Peter)
•
Add read-only transactions (Peter)
•
Print key name and value in foreign-key violation messages (Dmitry Tkach)
•
Allow users to see their own queries in pg_stat_activity (Kevin Brown) In prior releases, only the superuser could see query strings using pg_stat_activity. Now ordinary users can see their own query strings.
•
Fix aggregates in subqueries to match SQL standard (Tom) The SQL standard says that an aggregate function appearing within a nested subquery belongs to the outer query if its argument contains only outer-query variables. Prior PostgreSQL releases did not handle this fine point correctly.
•
Add option to prevent auto-addition of tables referenced in query (Nigel J. Andrews) By default, tables mentioned in the query are automatically added to the FROM clause if they are not already there. This is compatible with historic POSTGRES behavior but is contrary to the SQL standard. This option allows selecting standard-compatible behavior.
•
Allow UPDATE ... SET col = DEFAULT (Rod) This allows UPDATE to set a column to its declared default value.
•
Allow expressions to be used in LIMIT/OFFSET (Tom) In prior releases, LIMIT/OFFSET could only use constants, not expressions.
•
Implement CREATE TABLE AS EXECUTE (Neil, Peter)
E.2.3.5. Object Manipulation Changes •
Make CREATE SEQUENCE grammar more conforming to SQL 2003 (Neil)
1058
•
Add statement-level triggers (Neil) While this allows a trigger to fire at the end of a statement, it does not allow the trigger to access all rows modified by the statement. This capability is planned for a future release.
•
Add check constraints for domains (Rod) This greatly increases the usefulness of domains by allowing them to use check constraints.
•
Add ALTER DOMAIN (Rod) This allows manipulation of existing domains.
•
Fix several zero-column table bugs (Tom) PostgreSQL supports zero-column tables. This fixes various bugs that occur when using such tables.
•
Have ALTER TABLE ... ADD PRIMARY KEY add not-null constraint (Rod) In prior releases, ALTER TABLE ... ADD PRIMARY would add a unique index, but not a not-null constraint. That is fixed in this release.
•
Add ALTER TABLE ... WITHOUT OIDS (Rod) This allows control over whether new and updated rows will have an OID column. This is most useful for saving storage space.
•
Add ALTER SEQUENCE to modify minimum, maximum, increment, cache, cycle values (Rod)
•
Add ALTER TABLE ... CLUSTER ON (Alvaro Herrera) This command is used by pg_dump to record the cluster column for each table previously clustered. This information is used by database-wide cluster to cluster all previously clustered tables.
•
Improve automatic type casting for domains (Rod, Tom)
•
Allow dollar signs in identifiers, except as first character (Tom)
•
Disallow dollar signs in operator names, so x=$1 works (Tom)
•
Allow copying table schema using LIKE subtable, also SQL 2003 feature INCLUDING DEFAULTS (Rod)
•
Add WITH GRANT OPTION clause to GRANT (Peter) This enabled GRANT to give other users the ability to grant privileges on a object.
E.2.3.6. Utility Command Changes •
Add ON COMMIT clause to CREATE TABLE for temporary tables (Gavin) This adds the ability for a table to be dropped or all rows deleted on transaction commit.
•
Allow cursors outside transactions using WITH HOLD (Neil) In previous releases, cursors were removed at the end of the transaction that created them. Cursors can now be created with the WITH HOLD option, which allows them to continue to be accessed after the creating transaction has committed.
• FETCH 0
and MOVE 0 now do nothing (Bruce)
In previous releases, FETCH 0 fetched all remaining rows, and MOVE 0 moved to the end of the cursor. •
Cause FETCH and MOVE to return the number of rows fetched/moved, or zero if at the beginning/end of cursor, per SQL standard (Bruce) In prior releases, the row count returned by FETCH and MOVE did not accurately reflect the number of rows processed.
•
Properly handle SCROLL with cursors, or report an error (Neil) Allowing random access (both forward and backward scrolling) to some kinds of queries cannot be done without some additional work. If SCROLL is specified when the cursor is created, this additional work will be performed. Furthermore, if the cursor has been created with NO SCROLL, no random access is allowed.
•
Implement SQL-compatible options FIRST, LAST, ABSOLUTE n, RELATIVE n for FETCH and MOVE (Tom)
1059
•
Allow EXPLAIN on DECLARE CURSOR (Tom)
•
Allow CLUSTER to use index marked as pre-clustered by default (Alvaro Herrera)
•
Allow CLUSTER to cluster all tables (Alvaro Herrera) This allows all previously clustered tables in a database to be reclustered with a single command.
•
Prevent CLUSTER on partial indexes (Tom)
•
Allow DOS and Mac line-endings in COPY files (Bruce)
•
Disallow literal carriage return as a data value, backslash-carriage-return and \r are still allowed (Bruce)
• COPY
changes (binary, \.) (Tom)
•
Recover from COPY failure cleanly (Tom)
•
Prevent possible memory leaks in COPY (Tom)
•
Make TRUNCATE transaction-safe (Rod) TRUNCATE can now be used inside a transaction. If the transaction aborts, the changes made by the TRUNCATE are automatically rolled back.
•
Allow prepare/bind of utility commands like FETCH and EXPLAIN (Tom)
•
Add EXPLAIN EXECUTE (Neil)
•
Improve VACUUM performance on indexes by reducing WAL traffic (Tom)
•
Functional indexes have been generalized into indexes on expressions (Tom) In prior releases, functional indexes only supported a simple function applied to one or more column names. This release allows any type of scalar expression.
•
Have SHOW TRANSACTION ISOLATION match input to SET TRANSACTION ISOLATION (Tom)
•
Have COMMENT ON DATABASE on nonlocal database generate a warning (Rod) Database comments are stored in database-local tables so comments on a database have to be stored in each database.
•
Improve reliability of LISTEN/NOTIFY (Tom)
•
Allow REINDEX to reliably reindex nonshared system catalog indexes (Tom) This allows system tables to be reindexed without the requirement of a standalone session, which was necessary in previous releases. The only tables that now require a standalone session for reindexing are the global system tables pg_database, pg_shadow, and pg_group.
E.2.3.7. Data Type and Function Changes •
New server parameter extra_float_digits to control precision display of floating-point numbers (Pedro Ferreira, Tom) This controls output precision which was causing regression testing problems.
•
Allow +1300 as a numeric time-zone specifier, for FJST (Tom)
•
Remove rarely used functions oidrand, oidsrand, and userfntest functions (Neil)
•
Add md5() function to main server, already in contrib/pgcrypto (Joe) An MD5 function was frequently requested. For more complex encryption capabilities, use contrib/pgcrypto.
•
Increase date range of timestamp (John Cochran)
•
Change EXTRACT(EPOCH FROM timestamp) so timestamp without time zone is assumed to be in local time, not GMT (Tom)
•
Trap division by zero in case the operating system doesn't prevent it (Tom)
•
Change the numeric data type internally to base 10000 (Tom)
1060
•
New hostmask() function (Greg Wickham)
•
Fixes for to_char() and to_timestamp() (Karel)
•
Allow functions that can take any argument data type and return any data type, using anyelement and anyarray (Joe) This allows the creation of functions that can work with any data type.
•
Arrays
may
now
be
specified
as
ARRAY[1,2,3],
ARRAY[['a','b'],['c','d']],
or
ARRAY[ARRAY[ARRAY[2]]] (Joe) •
Allow proper comparisons for arrays, including ORDER BY and DISTINCT support (Joe)
•
Allow indexes on array columns (Joe)
•
Allow array concatenation with || (Joe)
•
Allow WHERE qualification expr op ANY/SOME/ALL (array_expr) (Joe) This allows arrays to behave like a list of values, for purposes like SELECT * FROM tab WHERE col IN (array_val).
•
New array functions array_append, array_cat, array_lower, array_prepend, array_to_string, array_upper, string_to_array (Joe)
•
Allow user defined aggregates to use polymorphic functions (Joe)
•
Allow assignments to empty arrays (Joe)
•
Allow 60 in seconds fields of time, timestamp, and interval input values (Tom) Sixty-second values are needed for leap seconds.
•
Allow cidr data type to be cast to text (Tom)
•
Disallow invalid time zone names in SET TIMEZONE
•
Trim trailing spaces when char is cast to varchar or text (Tom)
•
Make float(p) measure the precision p in binary digits, not decimal digits (Tom)
•
Add IPv6 support to the inet and cidr data types (Michael Graff)
•
Add family() function to report whether address is IPv4 or IPv6 (Michael Graff)
•
Have SHOW datestyle generate output similar to that used by SET datestyle (Tom)
•
Make EXTRACT(TIMEZONE) and SET/SHOW TIME ZONE follow the SQL convention for the sign of time zone offsets, i.e., positive is east from UTC (Tom)
•
Fix date_trunc('quarter', ...) (Böjthe Zoltán) Prior releases returned an incorrect value for this function call.
•
Make initcap() more compatible with Oracle (Mike Nolan) initcap() now uppercases a letter appearing after any non-alphanumeric character, rather than only after
whitespace. •
Allow only datestyle field order for date values not in ISO-8601 format (Greg)
•
Add new datestyle values MDY, DMY, and YMD to set input field order; honor US and European for backward compatibility (Tom)
•
String literals like 'now' or 'today' will no longer work as a column default. Use functions such as now(), current_timestamp instead. (change required for prepared statements) (Tom)
•
Treat NaN as larger than any other value in min()/max() (Tom) NaN was already sorted after ordinary numeric values for most purposes, but min() and max() didn't get this right.
•
Prevent interval from suppressing :00 seconds display
•
New function pg_get_triggerdef(prettyprint) and pg_constraint_is_visible()
1061
•
Allow time to be specified as 040506 or 0405 (Tom)
•
Input date order must now be YYYY-MM-DD (with 4-digit year) or match datestyle
•
Make pg_get_constraintdef to support unique, primary-key, and check constraints (Christopher)
E.2.3.8. Server-Side Language Changes •
Prevent PL/pgSQL crash when RETURN NEXT is used on a zero-row record variable (Tom)
•
Make PL/Python's spi_execute interface handle null values properly (Andrew Bosma)
•
Allow PL/pgSQL to declare variables of composite types without %ROWTYPE (Tom)
•
Fix PL/Python's _quote() function to handle big integers
•
Make PL/Python an untrusted language, now called plpythonu (Kevin Jacobs, Tom) The Python language no longer supports a restricted execution environment, so the trusted version of PL/Python was removed. If this situation changes, a version of PL/python that can be used by non-superusers will be readded.
•
Allow polymorphic PL/pgSQL functions (Joe, Tom)
•
Allow polymorphic SQL functions (Joe)
•
Improved compiled function caching mechanism in PL/pgSQL with full support for polymorphism (Joe)
•
Add new parameter $0 in PL/pgSQL representing the function's actual return type (Joe)
•
Allow PL/Tcl and PL/Python to use the same trigger on multiple tables (Tom)
•
Fixed PL/Tcl's spi_prepare to accept fully qualified type names in the parameter type list (Jan)
E.2.3.9. psql Changes •
Add \pset pager always to always use pager (Greg) This forces the pager to be used even if the number of rows is less than the screen height. This is valuable for rows that wrap across several screen rows.
•
Improve tab completion (Rod, Ross Reedstrom, Ian Barwick)
•
Reorder \? help into groupings (Harald Armin Massa, Bruce)
•
Add backslash commands for listing schemas, casts, and conversions (Christopher)
• \encoding
now changes based on the server parameter client_encoding server (Tom)
In previous versions, \encoding was not aware of encoding changes made using SET client_encoding. •
Save editor buffer into readline history (Ross) When \e is used to edit a query, the result is saved in the readline history for retrieval using the up arrow.
•
Improve \d display (Christopher)
•
Enhance HTML mode to be more standards-conforming (Greg)
•
New \set AUTOCOMMIT off capability (Tom) This takes the place of the removed server parameter autocommit.
•
New \set VERBOSITY to control error detail (Tom) This controls the new error reporting details.
•
New prompt escape sequence %x to show transaction status (Tom)
•
Long options for psql are now available on all platforms
E.2.3.10. pg_dump Changes •
Multiple pg_dump fixes, including tar format and large objects
•
Allow pg_dump to dump specific schemas (Neil)
1062
•
Make pg_dump preserve column storage characteristics (Christopher) This preserves ALTER TABLE ... SET STORAGE information.
•
Make pg_dump preserve CLUSTER characteristics (Christopher)
•
Have pg_dumpall use GRANT/REVOKE to dump database-level privleges (Tom)
•
Allow pg_dumpall to support the options -a, -s, -x of pg_dump (Tom)
•
Prevent pg_dump from lowercasing identifiers specified on the command line (Tom)
•
pg_dump options --use-set-session-authorization and --no-reconnect now do nothing, all dumps use SET SESSION AUTHORIZATION pg_dump no longer reconnects to switch users, but instead always uses SET SESSION AUTHORIZATION. This will reduce password prompting during restores.
•
Long options for pg_dump are now available on all platforms PostgreSQL now includes its own long-option processing routines.
E.2.3.11. libpq Changes •
Add function PQfreemem for freeing memory on Windows, suggested for NOTIFY (Bruce) Windows requires that memory allocated in a library be freed by a function in the same library, hence free() doesn't work for freeing memory allocated by libpq. PQfreemem is the proper way to free libpq
memory, especially on Windows, and is recommended for other platforms as well. •
Document service capability, and add sample file (Bruce) This allows clients to look up connection information in a central file on the client machine.
•
Make PQsetdbLogin have the same defaults as PQconnectdb (Tom)
•
Allow libpq to cleanly fail when result sets are too large (Tom)
•
Improve performance of function PGunescapeBytea (Ben Lamb)
•
Allow thread-safe libpq with configure option --enable-thread-safety (Lee Kindness, Philip Yarra)
•
Allow function pqInternalNotice to accept a format string and arguments instead of just a preformatted message (Tom, Sean Chittenden)
•
Control SSL negotiation with sslmode values disable, allow, prefer, and require (Jon Jensen)
•
Allow new error codes and levels of text (Tom)
•
Allow access to the underlying table and column of a query result (Tom) This is helpful for query-builder applications that want to know the underlying table and column names associated with a specific result set.
•
Allow access to the current transaction status (Tom)
•
Add ability to pass binary data directly to the server (Tom)
•
Add function PQexecPrepared and PQsendQueryPrepared functions which perform bind/execute of previously prepared statements (Tom)
E.2.3.12. JDBC Changes •
Allow setNull on updateable result sets
•
Allow executeBatch on a prepared statement (Barry)
•
Support SSL connections (Barry)
•
Handle schema names in result sets (Paul Sorenson)
•
Add refcursor support (Nic Ferrier)
1063
E.2.3.13. Miscellaneous Interface Changes •
Prevent possible memory leak or core dump during libpgtcl shutdown (Tom)
•
Add Informix compatibility to ECPG (Michael) This allows ECPG to process embedded C programs that were written using certain Informix extensions.
•
Add type decimal to ECPG that is fixed length, for Informix (Michael)
•
Allow thread-safe embedded SQL programs with configure option --enable-thread-safety (Lee Kindness, Bruce) This allows multiple threads to access the database at the same time.
•
Moved Python client PyGreSQL to http://www.pygresql.org (Marc)
E.2.3.14. Source Code Changes •
Prevent need for separate platform geometry regression result files (Tom)
•
Improved PPC locking primitive (Reinhard Max)
•
New function palloc0 to allocate and clear memory (Bruce)
•
Fix locking code for s390x CPU (64-bit) (Tom)
•
Allow OpenBSD to use local ident credentials (William Ahern)
•
Make query plan trees read-only to executor (Tom)
•
Add Darwin startup scripts (David Wheeler)
•
Allow libpq to compile with Borland C++ compiler (Lester Godwin, Karl Waclawek)
•
Use our own version of getopt_long() if needed (Peter)
•
Convert administration scripts to C (Peter)
•
Bison >= 1.85 is now required to build the PostgreSQL grammar, if building from CVS
•
Merge documentation into one book (Peter)
•
Add Windows compatibility functions (Bruce)
•
Allow client interfaces to compile under MinGW (Bruce)
•
New ereport() function for error reporting (Tom)
•
Support Intel compiler on Linux (Peter)
•
Improve Linux startup scripts (Slawomir Sudnik, Darko Prenosil)
•
Add support for AMD Opteron and Itanium (Jeffrey W. Baker, Bruce)
•
Remove --enable-recode option from configure This was no longer needed now that we have CREATE CONVERSION.
•
Generate a compile error if spinlock code is not found (Bruce) Platforms without spinlock code will now fail to compile, rather than silently using semaphores. This failure can be disabled with a new configure option.
E.2.3.15. Contrib Changes •
Change dbmirror license to BSD
•
Improve earthdistance (Bruno Wolff III)
•
Portability improvements to pgcrypto (Marko Kreen)
•
Prevent crash in xml (John Gray, Michael Richards)
•
Update oracle
•
Update mysql
1064
•
Update cube (Bruno Wolff III)
•
Update earthdistance to use cube (Bruno Wolff III)
•
Update btree_gist (Oleg)
•
New tsearch2 full-text search module (Oleg, Teodor)
•
Add hash-based crosstab function to tablefuncs (Joe)
•
Add serial column to order connectby() siblings in tablefuncs (Nabil Sayegh,Joe)
•
Add named persistent connections to dblink (Shridhar Daithanka)
•
New pg_autovacuum allows automatic VACUUM (Matthew T. O'Connor)
•
Make pgbench honor environment variables PGHOST, PGPORT, PGUSER (Tatsuo)
•
Improve intarray (Teodor Sigaev)
•
Improve pgstattuple (Rod)
•
Fix bug in metaphone() in fuzzystrmatch
•
Improve adddepend (Rod)
•
Update spi/timetravel (Böjthe Zoltán)
•
Fix dbase -s option and improve non-ASCII handling (Thomas Behr, Márcio Smiderle)
•
Remove array module because features now included by default (Joe)
E.3. Release 7.3.5 Release date: 2003-12-03
This has a variety of fixes from 7.3.4.
E.3.1. Migration to version 7.3.5 A dump/restore is not required for those running 7.3.*.
E.3.2. Changes •
Force zero_damaged_pages to be on during recovery from WAL
•
Prevent some obscure cases of “variable not in subplan target lists”
•
Force stats processes to detach from shared memory, ensuring cleaner shutdown
•
Make PQescapeBytea and byteaout consistent with each other (Joe)
•
Added missing SPI_finish() calls to dblink's get_tuple_of_interest() (Joe)
•
Fix for possible foreign key violation when rule rewrites INSERT (Jan)
•
Support qualified type names in PL/Tcl's spi_prepare command (Jan)
•
Make pg_dump handle a procedural language handler located in pg_catalog
•
Make pg_dump handle cases where a custom opclass is in another schema
•
Make pg_dump dump binary-compatible casts correctly (Jan)
•
Fix insertion of expressions containing subqueries into rule bodies
•
Fix incorrect argument processing in clusterdb script (Anand Ranganathan)
•
Fix problems with dropped columns in plpython triggers
•
Repair problems with to_char() reading past end of its input string (Karel)
•
Fix GB18030 mapping errors (Tatsuo)
•
Fix several problems with SSL error handling and asynchronous SSL I/O
1065
•
Remove ability to bind a list of values to a single parameter in JDBC (prevents possible SQL-injection attacks)
•
Fix some errors in HAVE_INT64_TIMESTAMP code paths
•
Fix corner case for btree search in parallel with first root page split
E.4. Release 7.3.4 Release date: 2003-07-24
This has a variety of fixes from 7.3.3.
E.4.1. Migration to version 7.3.4 A dump/restore is not required for those running 7.3.*.
E.4.2. Changes •
Repair breakage in timestamp-to-date conversion for dates before 2000
•
Prevent rare possibility of server startup failure (Tom)
•
Fix bugs in interval-to-time conversion (Tom)
•
Add constraint names in a few places in pg_dump (Rod)
•
Improve performance of functions with many parameters (Tom)
•
Fix to_ascii() buffer overruns (Tom)
•
Prevent restore of database comments from throwing an error (Tom)
•
Work around buggy strxfrm() present in some Solaris releases (Tom)
•
Properly escape jdbc setObject() strings to improve security (Barry)
E.5. Release 7.3.3 Release date: 2003-05-22
This release contains of variety of fixes for version 7.3.2.
E.5.1. Migration to version 7.3.3 A dump/restore is not required for those running version 7.3.*.
E.5.2. Changes •
Repair sometimes-incorrect computation of StartUpID after a crash
•
Avoid slowness with lots of deferred triggers in one transaction (Stephan)
•
Don't lock referenced row when UPDATE doesn't change foreign key's value (Jan)
•
Use -fPIC not -fpic on Sparc (Tom Callaway)
•
Repair lack of schema-awareness in contrib/reindexdb
•
Fix contrib/intarray error for zero-element result array (Teodor)
•
Ensure createuser script will exit on control-C (Oliver)
•
Fix errors when the type of a dropped column has itself been dropped
• CHECKPOINT
does not cause database panic on failure in noncritical steps
•
Accept 60 in seconds fields of timestamp, time, interval input values
•
Issue notice, not error, if TIMESTAMP, TIME, or INTERVAL precision too large
1066
•
Fix abstime-to-time cast function (fix is not applied unless you initdb)
•
Fix pg_proc entry for timestampt_izone (fix is not applied unless you initdb)
•
Make EXTRACT(EPOCH FROM timestamp without time zone) treat input as local time
• 'now'::timestamptz
gave wrong answer if timezone changed earlier in transaction
• HAVE_INT64_TIMESTAMP
code for time with timezone overwrote its input
•
Accept GLOBAL TEMP/TEMPORARY as a synonym for TEMPORARY
•
Avoid improper schema-privilege-check failure in foreign-key triggers
•
Fix bugs in foreign-key triggers for SET DEFAULT action
•
Fix incorrect time-qual check in row fetch for UPDATE and DELETE triggers
•
Foreign-key clauses were parsed but ignored in ALTER TABLE ADD COLUMN
•
Fix createlang script breakage for case where handler function already exists
•
Fix misbehavior on zero-column tables in pg_dump, COPY, ANALYZE, other places
•
Fix misbehavior of func_error() on type names containing '%'
•
Fix misbehavior of replace() on strings containing '%'
•
Regular-expression patterns containing certain multibyte characters failed
•
Account correctly for NULLs in more cases in join size estimation
•
Avoid conflict with system definition of isblank() function or macro
•
Fix failure to convert large code point values in EUC_TW conversions (Tatsuo)
•
Fix error recovery for SSL_read/SSL_write calls
•
Don't do early constant-folding of type coercion expressions
•
Validate page header fields immediately after reading in any page
•
Repair incorrect check for ungrouped variables in unnamed joins
•
Fix buffer overrun in to_ascii (Guido Notari)
•
contrib/ltree fixes (Teodor)
•
Fix core dump in deadlock detection on machines where char is unsigned
•
Avoid running out of buffers in many-way indexscan (bug introduced in 7.3)
•
Fix planner's selectivity estimation functions to handle domains properly
•
Fix dbmirror memory-allocation bug (Steven Singer)
•
Prevent infinite loop in ln(numeric) due to roundoff error
• GROUP BY
got confused if there were multiple equal GROUP BY items
•
Fix bad plan when inherited UPDATE/DELETE references another inherited table
•
Prevent clustering on incomplete (partial or non-NULL-storing) indexes
•
Service shutdown request at proper time if it arrives while still starting up
•
Fix left-links in temporary indexes (could make backwards scans miss entries)
•
Fix incorrect handling of client_encoding setting in postgresql.conf (Tatsuo)
•
Fix failure to respond to pg_ctl stop -m fast after Async_NotifyHandler runs
•
Fix SPI for case where rule contains multiple statements of the same type
•
Fix problem with checking for wrong type of access privilege in rule query
•
Fix problem with EXCEPT in CREATE RULE
•
Prevent problem with dropping temp tables having serial columns
1067
•
Fix replace_vars_with_subplan_refs failure in complex views
•
Fix regexp slowness in single-byte encodings (Tatsuo)
•
Allow qualified type names in CREATE CAST and DROP CAST
•
Accept SETOF type[], which formerly had to be written SETOF _type
•
Fix pg_dump core dump in some cases with procedural languages
•
Force ISO datestyle in pg_dump output, for portability (Oliver)
•
pg_dump failed to handle error return from lo_read (Oleg Drokin)
•
pg_dumpall failed with groups having no members (Nick Eskelinen)
•
pg_dumpall failed to recognize --globals-only switch
•
pg_restore failed to restore blobs if -X disable-triggers is specified
•
Repair intrafunction memory leak in plpgsql
•
pltcl's elog command dumped core if given wrong parameters (Ian Harding)
•
plpython used wrong value of atttypmod (Brad McLean)
•
Fix improper quoting of boolean values in Python interface (D'Arcy)
•
Added addDataType() method to PGConnection interface for JDBC
•
Fixed various problems with updateable ResultSets for JDBC (Shawn Green)
•
Fixed various problems with DatabaseMetaData for JDBC (Kris Jurka, Peter Royal)
•
Fixed problem with parsing table ACLs in JDBC
•
Better error message for character set conversion problems in JDBC
E.6. Release 7.3.2 Release date: 2003-02-04
This release contains a variety of fixes for version 7.3.1.
E.6.1. Migration to version 7.3.2 A dump/restore is not required for those running version 7.3.*.
E.6.2. Changes •
Restore creation of OID column in CREATE TABLE AS / SELECT INTO
•
Fix pg_dump core dump when dumping views having comments
•
Dump DEFERRABLE/INITIALLY DEFERRED constraints properly
•
Fix UPDATE when child table's column numbering differs from parent
•
Increase default value of max_fsm_relations
•
Fix problem when fetching backwards in a cursor for a single-row query
•
Make backward fetch work properly with cursor on SELECT DISTINCT query
•
Fix problems with loading pg_dump files containing contrib/lo usage
•
Fix problem with all-numeric user names
•
Fix possible memory leak and core dump during disconnect in libpgtcl
•
Make plpython's spi_execute command handle nulls properly (Andrew Bosma)
•
Adjust plpython error reporting so that its regression test passes again
•
Work with bison 1.875
1068
•
Handle mixed-case names properly in plpgsql's %type (Neil)
•
Fix core dump in pltcl when executing a query rewritten by a rule
•
Repair array subscript overruns (per report from Yichen Xie)
•
Reduce MAX_TIME_PRECISION from 13 to 10 in floating-point case
•
Correctly case-fold variable names in per-database and per-user settings
•
Fix coredump in plpgsql's RETURN NEXT when SELECT into record returns no rows
•
Fix outdated use of pg_type.typprtlen in python client interface
•
Correctly handle fractional seconds in timestamps in JDBC driver
•
Improve performance of getImportedKeys() in JDBC
•
Make shared-library symlinks work standardly on HPUX (Giles)
•
Repair inconsistent rounding behavior for timestamp, time, interval
•
SSL negotiation fixes (Nathan Mueller)
•
Make libpq's ~/.pgpass feature work when connecting with PQconnectDB
•
Update my2pg, ora2pg
•
Translation updates
•
Add casts between types lo and oid in contrib/lo
•
fastpath code now checks for privilege to call function
E.7. Release 7.3.1 Release date: 2002-12-18
This release contains a variety of fixes for version 7.3.
E.7.1. Migration to version 7.3.1 A dump/restore is not required for those running version 7.3. However, it should be noted that the main PostgreSQL interface library, libpq, has a new major version number for this release, which may require recompilation of client code in certain cases.
E.7.2. Changes •
Fix a core dump of COPY TO when client/server encodings don't match (Tom)
•
Allow pg_dump to work with pre-7.2 servers (Philip)
•
contrib/adddepend fixes (Tom)
•
Fix problem with deletion of per-user/per-database config settings (Tom)
•
contrib/vacuumlo fix (Tom)
•
Allow 'password' encryption even when pg_shadow contains MD5 passwords (Bruce)
•
contrib/dbmirror fix (Steven Singer)
•
Optimizer fixes (Tom)
•
contrib/tsearch fixes (Teodor Sigaev, Magnus)
•
Allow locale names to be mixed case (Nicolai Tufar)
•
Increment libpq library's major version number (Bruce)
•
pg_hba.conf error reporting fixes (Bruce, Neil)
•
Add SCO Openserver 5.0.4 as a supported platform (Bruce)
•
Prevent EXPLAIN from crashing server (Tom)
1069
•
SSL fixes (Nathan Mueller)
•
Prevent composite column creation via ALTER TABLE (Tom)
E.8. Release 7.3 Release date: 2002-11-27
E.8.1. Overview Major changes in this release: Schemas Schemas allow users to create objects in separate namespaces, so two people or applications can have tables with the same name. There is also a public schema for shared tables. Table/index creation can be restricted by removing privileges on the public schema. Drop Column PostgreSQL now supports the ALTER TABLE ... DROP COLUMN functionality. Table Functions Functions returning multiple rows and/or multiple columns are now much easier to use than before. You can call such a “table function” in the SELECT FROM clause, treating its output like a table. Also, PL/pgSQL functions can now return sets. Prepared Queries PostgreSQL now supports prepared queries, for improved performance. Dependency Tracking PostgreSQL now records object dependencies, which allows improvements in many areas. DROP statements now take either CASCADE or RESTRICT to control whether dependent objects are also dropped. Privileges Functions and procedural languages now have privileges, and functions can be defined to run with the privileges of their creator. Internationalization Both multibyte and locale support are now always enabled. Logging A variety of logging options have been enhanced. Interfaces A large number of interfaces have been moved to http://gborg.postgresql.org where they can be developed and released independently. Functions/Identifiers By default, functions can now take up to 32 parameters, and identifiers can be up to 63 bytes long. Also, OPAQUE is now deprecated: there are specific “pseudo-datatypes” to represent each of the former meanings of OPAQUE in function argument and result types.
E.8.2. Migration to version 7.3 A dump/restore using pg_dump is required for those wishing to migrate data from any previous release. If your application examines the system catalogs, additional changes will be required due to the introduction of schemas in 7.3; for more information, see: http://developer.postgresql.org/~momjian/upgrade_tips_7.3 (http://developer.postgresql.org/~momjian/upgrade_tips_7.3). Observe the following incompatibilities: •
Pre-6.3 clients are no longer supported.
1070
• pg_hba.conf
now has a column for the user name and additional features. Existing files need to be
adjusted. •
Several postgresql.conf logging parameters have been renamed.
• LIMIT #,#
has been disabled; use LIMIT # OFFSET #.
statements with column lists must specify a value for each specified column. For example, INSERT INTO tab (col1, col2) VALUES ('val1') is now invalid. It's still allowed to supply fewer columns than expected if the INSERT does not have a column list.
• INSERT
• serial •
columns are no longer automatically UNIQUE; thus, an index will not automatically be created.
A SET command inside an aborted transaction is now rolled back. no longer considers missing trailing columns to be null. All columns need to be specified. (However, one may achieve a similar effect by specifying a column list in the COPY command.)
• COPY
•
The data type timestamp is now equivalent to timestamp without time zone, instead of timestamp with time zone.
•
Pre-7.3 databases loaded into 7.3 will not have the new object dependencies for serial columns, unique constraints, and foreign keys. See the directory contrib/adddepend/ for a detailed description and a script that will add such dependencies.
•
An empty string ('') is no longer allowed as the input into an integer field. Formerly, it was silently interpreted as 0.
E.8.3. Changes E.8.3.1. Server Operation •
Add pg_locks view to show locks (Neil)
•
Security fixes for password negotiation memory allocation (Neil)
•
Remove support for version 0 FE/BE protocol (PostgreSQL 6.2 and earlier) (Tom)
•
Reserve the last few backend slots for superusers, add parameter superuser_reserved_connections to control this (Nigel J. Andrews)
E.8.3.2. Performance •
Improve startup by calling localtime() only once (Tom)
•
Cache system catalog information in flat files for faster startup (Tom)
•
Improve caching of index information (Tom)
•
Optimizer improvements (Tom, Fernando Nasser)
•
Catalog caches now store failed lookups (Tom)
•
Hash function improvements (Neil)
•
Improve performance of query tokenization and network handling (Peter)
•
Speed improvement for large object restore (Mario Weilguni)
•
Mark expired index entries on first lookup, saving later heap fetches (Tom)
•
Avoid excessive NULL bitmap padding (Manfred Koizar)
•
Add BSD-licensed qsort() for Solaris, for performance (Bruce)
•
Reduce per-row overhead by four bytes (Manfred Koizar)
•
Fix GEQO optimizer bug (Neil Conway)
•
Make WITHOUT OID actually save four bytes per row (Manfred Koizar)
•
Add default_statistics_target variable to specify ANALYZE buckets (Neil)
•
Use local buffer cache for temporary tables so no WAL overhead (Tom)
1071
•
Improve free space map performance on large tables (Stephen Marshall, Tom)
•
Improved WAL write concurrency (Tom)
E.8.3.3. Privileges •
Add privileges on functions and procedural languages (Peter)
•
Add OWNER to CREATE DATABASE so superusers can create databases on behalf of unprivileged users (Gavin Sherry, Tom)
•
Add new object privilege bits EXECUTE and USAGE (Tom)
•
Add SET SESSION AUTHORIZATION DEFAULT and RESET SESSION AUTHORIZATION (Tom)
•
Allow functions to be executed with the privilege of the function owner (Peter)
E.8.3.4. Server Configuration •
Server log messages now tagged with LOG, not DEBUG (Bruce)
•
Add user column to pg_hba.conf (Bruce)
•
Have log_connections output two lines in log file (Tom)
•
Remove debug_level from postgresql.conf, now server_min_messages (Bruce)
•
New ALTER DATABASE/USER ... SET command for per-user/database initialization (Peter)
•
New parameters server_min_messages and client_min_messages to control which messages are sent to the server logs or client applications (Bruce)
•
Allow pg_hba.conf to specify lists of users/databases separated by commas, group names prepended with +, and file names prepended with @ (Bruce)
•
Remove secondary password file capability and pg_password utility (Bruce)
•
Add variable db_user_namespace for database-local user names (Bruce)
•
SSL improvements (Bear Giles)
•
Make encryption of stored passwords the default (Bruce)
•
Allow pg_statistics to be reset by calling pg_stat_reset() (Christopher)
•
Add log_duration parameter (Bruce)
•
Rename debug_print_query to log_statement (Bruce)
•
Rename show_query_stats to show_statement_stats (Bruce)
•
Add param log_min_error_statement to print commands to logs on error (Gavin)
E.8.3.5. Queries •
Make cursors insensitive, meaning their contents do not change (Tom)
•
Disable LIMIT #,# syntax; now only LIMIT # OFFSET # supported (Bruce)
•
Increase identifier length to 63 (Neil, Bruce)
•
UNION fixes for merging >= 3 columns of different lengths (Tom)
•
Add DEFAULT key word to INSERT, e.g., INSERT ... (..., DEFAULT, ...) (Rod)
•
Allow views to have default values using ALTER COLUMN ... SET DEFAULT (Neil)
•
Fail on INSERTs with column lists that don't supply all column values, e.g., INSERT INTO tab (col1, col2) VALUES ('val1'); (Rod)
•
Fix for join aliases (Tom)
•
Fix for FULL OUTER JOINs (Tom)
•
Improve reporting of invalid identifier and location (Tom, Gavin)
•
Fix OPEN cursor(args) (Tom)
1072
•
Allow 'ctid' to be used in a view and currtid(viewname) (Hiroshi)
•
Fix for CREATE TABLE AS with UNION (Tom)
•
SQL99 syntax improvements (Thomas)
•
Add statement_timeout variable to cancel queries (Bruce)
•
Allow prepared queries with PREPARE/EXECUTE (Neil)
•
Allow FOR UPDATE to appear after LIMIT/OFFSET (Bruce)
•
Add variable autocommit (Tom, David Van Wie)
E.8.3.6. Object Manipulation •
Make equals signs optional in CREATE DATABASE (Gavin Sherry)
•
Make ALTER TABLE OWNER change index ownership too (Neil)
•
New ALTER TABLE tabname ALTER COLUMN colname SET STORAGE controls TOAST storage, compression (John Gray)
•
Add schema support, CREATE/DROP SCHEMA (Tom)
•
Create schema for temporary tables (Tom)
•
Add variable search_path for schema search (Tom)
•
Add ALTER TABLE SET/DROP NOT NULL (Christopher)
•
New CREATE FUNCTION volatility levels (Tom)
•
Make rule names unique only per table (Tom)
•
Add 'ON tablename' clause to DROP RULE and COMMENT ON RULE (Tom)
•
Add ALTER TRIGGER RENAME (Joe)
•
New current_schema() and current_schemas() inquiry functions (Tom)
•
Allow functions to return multiple rows (table functions) (Joe)
•
Make WITH optional in CREATE DATABASE, for consistency (Bruce)
•
Add object dependency tracking (Rod, Tom)
•
Add RESTRICT/CASCADE to DROP commands (Rod)
•
Add ALTER TABLE DROP for non-CHECK CONSTRAINT (Rod)
•
Autodestroy sequence on DROP of table with SERIAL (Rod)
•
Prevent column dropping if column is used by foreign key (Rod)
•
Automatically drop constraints/functions when object is dropped (Rod)
•
Add CREATE/DROP OPERATOR CLASS (Bill Studenmund, Tom)
•
Add ALTER TABLE DROP COLUMN (Christopher, Tom, Hiroshi)
•
Prevent inherited columns from being removed or renamed (Alvaro Herrera)
•
Fix foreign key constraints to not error on intermediate database states (Stephan)
•
Propagate column or table renaming to foreign key constraints
•
Add CREATE OR REPLACE VIEW (Gavin, Neil, Tom)
•
Add CREATE OR REPLACE RULE (Gavin, Neil, Tom)
•
Have rules execute alphabetically, returning more predictable values (Tom)
•
Triggers are now fired in alphabetical order (Tom)
•
Add /contrib/adddepend to handle pre-7.3 object dependencies (Rod)
•
Allow better casting when inserting/updating values (Tom)
1073
E.8.3.7. Utility Commands •
Have COPY TO output embedded carriage returns and newlines as \r and \n (Tom)
•
Allow DELIMITER in COPY FROM to be 8-bit clean (Tatsuo)
•
Make pg_dump use ALTER TABLE ADD PRIMARY KEY, for performance (Neil)
•
Disable brackets in multistatement rules (Bruce)
•
Disable VACUUM from being called inside a function (Bruce)
•
Allow dropdb and other scripts to use identifiers with spaces (Bruce)
•
Restrict database comment changes to the current database
•
Allow comments on operators, independent of the underlying function (Rod)
•
Rollback SET commands in aborted transactions (Tom)
•
EXPLAIN now outputs as a query (Tom)
•
Display condition expressions and sort keys in EXPLAIN (Tom)
•
Add 'SET LOCAL var = value' to set configuration variables for a single transaction (Tom)
•
Allow ANALYZE to run in a transaction (Bruce)
•
Improve COPY syntax using new WITH clauses, keep backward compatibility (Bruce)
•
Fix pg_dump to consistently output tags in non-ASCII dumps (Bruce)
•
Make foreign key constraints clearer in dump file (Rod)
•
Add COMMENT ON CONSTRAINT (Rod)
•
Allow COPY TO/FROM to specify column names (Brent Verner)
•
Dump UNIQUE and PRIMARY KEY constraints as ALTER TABLE (Rod)
•
Have SHOW output a query result (Joe)
•
Generate failure on short COPY lines rather than pad NULLs (Neil)
•
Fix CLUSTER to preserve all table attributes (Alvaro Herrera)
•
New pg_settings table to view/modify GUC settings (Joe)
•
Add smart quoting, portability improvements to pg_dump output (Peter)
•
Dump serial columns out as SERIAL (Tom)
•
Enable large file support, >2G for pg_dump (Peter, Philip Warner, Bruce)
•
Disallow TRUNCATE on tables that are involved in referential constraints (Rod)
•
Have TRUNCATE also auto-truncate the toast table of the relation (Tom)
•
Add clusterdb utility that will auto-cluster an entire database based on previous CLUSTER operations (Alvaro Herrera)
•
Overhaul pg_dumpall (Peter)
•
Allow REINDEX of TOAST tables (Tom)
•
Implemented START TRANSACTION, per SQL99 (Neil)
•
Fix rare index corruption when a page split affects bulk delete (Tom)
•
Fix ALTER TABLE ... ADD COLUMN for inheritance (Alvaro Herrera)
E.8.3.8. Data Types and Functions •
Fix factorial(0) to return 1 (Bruce)
•
Date/time/timezone improvements (Thomas)
•
Fix for array slice extraction (Tom)
1074
•
Fix extract/date_part to report proper microseconds for timestamp (Tatsuo)
•
Allow text_substr() and bytea_substr() to read TOAST values more efficiently (John Gray)
•
Add domain support (Rod)
•
Make WITHOUT TIME ZONE the default for TIMESTAMP and TIME data types (Thomas)
•
Allow alternate storage scheme of 64-bit integers for date/time types using --enable-integer-datetimes in configure (Thomas)
•
Make timezone(timestamptz) return timestamp rather than a string (Thomas)
•
Allow fractional seconds in date/time types for dates prior to 1BC (Thomas)
•
Limit timestamp data types to 6 decimal places of precision (Thomas)
•
Change timezone conversion functions from timetz() to timezone() (Thomas)
•
Add configuration variables datestyle and timezone (Tom)
•
Add OVERLAY(), which allows substitution of a substring in a string (Thomas)
•
Add SIMILAR TO (Thomas, Tom)
•
Add regular expression SUBSTRING(string FROM pat FOR escape) (Thomas)
•
Add LOCALTIME and LOCALTIMESTAMP functions (Thomas)
•
Add named composite types using CREATE TYPE typename AS (column) (Joe)
•
Allow composite type definition in the table alias clause (Joe)
•
Add new API to simplify creation of C language table functions (Joe)
•
Remove ODBC-compatible empty parentheses from calls to SQL99 functions for which these parentheses do not match the standard (Thomas)
•
Allow macaddr data type to accept 12 hex digits with no separators (Mike Wyer)
•
Add CREATE/DROP CAST (Peter)
•
Add IS DISTINCT FROM operator (Thomas)
•
Add SQL99 TREAT() function, synonym for CAST() (Thomas)
•
Add pg_backend_pid() to output backend pid (Bruce)
•
Add IS OF / IS NOT OF type predicate (Thomas)
•
Allow bit string constants without fully-specified length (Thomas)
•
Allow conversion between 8-byte integers and bit strings (Thomas)
•
Implement hex literal conversion to bit string literal (Thomas)
•
Allow table functions to appear in the FROM clause (Joe)
•
Increase maximum number of function parameters to 32 (Bruce)
•
No longer automatically create index for SERIAL column (Tom)
•
Add current_database() (Rod)
•
Fix cash_words() to not overflow buffer (Tom)
•
Add functions replace(), split_part(), to_hex() (Joe)
•
Fix LIKE for bytea as a right-hand argument (Joe)
•
Prevent crashes caused by SELECT cash_out(2) (Tom)
•
Fix to_char(1,'FM999.99') to return a period (Karel)
•
Fix trigger/type/language functions returning OPAQUE to return proper type (Tom)
1075
E.8.3.9. Internationalization •
Add additional encodings: Korean (JOHAB), Thai (WIN874), Vietnamese (TCVN), Arabic (WIN1256), Simplified Chinese (GBK), Korean (UHC) (Eiji Tokuya)
•
Enable locale support by default (Peter)
•
Add locale variables (Peter)
•
Escape byes >= 0x7f for multibyte in PQescapeBytea/PQunescapeBytea (Tatsuo)
•
Add locale awareness to regular expression character classes
•
Enable multibyte support by default (Tatsuo)
•
Add GB18030 multibyte support (Bill Huang)
•
Add CREATE/DROP CONVERSION, allowing loadable encodings (Tatsuo, Kaori)
•
Add pg_conversion table (Tatsuo)
•
Add SQL99 CONVERT() function (Tatsuo)
•
pg_dumpall, pg_controldata, and pg_resetxlog now national-language aware (Peter)
•
New and updated translations
E.8.3.10. Server-side Languages •
Allow recursive SQL function (Peter)
•
Change PL/Tcl build to use configured compiler and Makefile.shlib (Peter)
•
Overhaul the PL/pgSQL FOUND variable to be more Oracle-compatible (Neil, Tom)
•
Allow PL/pgSQL to handle quoted identifiers (Tom)
•
Allow set-returning PL/pgSQL functions (Neil)
•
Make PL/pgSQL schema-aware (Joe)
•
Remove some memory leaks (Nigel J. Andrews, Tom)
E.8.3.11. psql •
Don't lowercase psql \connect database name for 7.2.0 compatibility (Tom)
•
Add psql \timing to time user queries (Greg Sabino Mullane)
•
Have psql \d show index information (Greg Sabino Mullane)
•
New psql \dD shows domains (Jonathan Eisler)
•
Allow psql to show rules on views (Paul ?)
•
Fix for psql variable substitution (Tom)
•
Allow psql \d to show temporary table structure (Tom)
•
Allow psql \d to show foreign keys (Rod)
•
Fix \? to honor \pset pager (Bruce)
•
Have psql reports its version number on startup (Tom)
•
Allow \copy to specify column names (Tom)
E.8.3.12. libpq •
Add $HOME/.pgpass to store host/user password combinations (Alvaro Herrera)
•
Add PQunescapeBytea() function to libpq (Patrick Welche)
•
Fix for sending large queries over non-blocking connections (Bernhard Herzog)
•
Fix for libpq using timers on Win9X (David Ford)
•
Allow libpq notify to handle servers with different-length identifiers (Tom)
1076
•
Add libpq PQescapeString() and PQescapeBytea() to Windows (Bruce)
•
Fix for SSL with non-blocking connections (Jack Bates)
•
Add libpq connection timeout parameter (Denis A Ustimenko)
E.8.3.13. JDBC •
Allow JDBC to compile with JDK 1.4 (Dave)
•
Add JDBC 3 support (Barry)
•
Allows JDBC to set loglevel by adding ?loglevel=X to the connection URL (Barry)
•
Add Driver.info() message that prints out the version number (Barry)
•
Add updateable result sets (Raghu Nidagal, Dave)
•
Add support for callable statements (Paul Bethe)
•
Add query cancel capability
•
Add refresh row (Dave)
•
Fix MD5 encryption handling for multibyte servers (Jun Kawai)
•
Add support for prepared statements (Barry)
E.8.3.14. Miscellaneous Interfaces •
Fixed ECPG bug concerning octal numbers in single quotes (Michael)
•
Move src/interfaces/libpgeasy to http://gborg.postgresql.org (Marc, Bruce)
•
Improve Python interface (Elliot Lee, Andrew Johnson, Greg Copeland)
•
Add libpgtcl connection close event (Gerhard Hintermayer)
•
Move src/interfaces/libpq++ to http://gborg.postgresql.org (Marc, Bruce)
•
Move src/interfaces/odbc to http://gborg.postgresql.org (Marc)
•
Move src/interfaces/libpgeasy to http://gborg.postgresql.org (Marc, Bruce)
•
Move src/interfaces/perl5 to http://gborg.postgresql.org (Marc, Bruce)
•
Remove src/bin/pgaccess from main tree, now at http://www.pgaccess.org (Bruce)
•
Add pg_on_connection_loss command to libpgtcl (Gerhard Hintermayer, Tom)
E.8.3.15. Source Code •
Fix for parallel make (Peter)
•
AIX fixes for linking Tcl (Andreas Zeugswetter)
•
Allow PL/Perl to build under Cygwin (Jason Tishler)
•
Improve MIPS compiles (Peter, Oliver Elphick)
•
Require Autoconf version 2.53 (Peter)
•
Require readline and zlib by default in configure (Peter)
•
Allow Solaris to use Intimate Shared Memory (ISM), for performance (Scott Brunza, P.J. Josh Rovero)
•
Always enable syslog in compile, remove --enable-syslog option (Tatsuo)
•
Always enable multibyte in compile, remove --enable-multibyte option (Tatsuo)
•
Always enable locale in compile, remove --enable-locale option (Peter)
•
Fix for Win9x DLL creation (Magnus Naeslund)
•
Fix for link() usage by WAL code on Windows, BeOS (Jason Tishler)
•
Add sys/types.h to c.h, remove from main files (Peter, Bruce)
1077
•
Fix AIX hang on SMP machines (Tomoyuki Niijima)
•
AIX SMP hang fix (Tomoyuki Niijima)
•
Fix pre-1970 date handling on newer glibc libraries (Tom)
•
Fix PowerPC SMP locking (Tom)
•
Prevent gcc -ffast-math from being used (Peter, Tom)
•
Bison >= 1.50 now required for developer builds
•
Kerberos 5 support now builds with Heimdal (Peter)
•
Add appendix in the User's Guide which lists SQL features (Thomas)
•
Improve loadable module linking to use RTLD_NOW (Tom)
•
New error levels WARNING, INFO, LOG, DEBUG[1-5] (Bruce)
•
New src/port directory holds replaced libc functions (Peter, Bruce)
•
New pg_namespace system catalog for schemas (Tom)
•
Add pg_class.relnamespace for schemas (Tom)
•
Add pg_type.typnamespace for schemas (Tom)
•
Add pg_proc.pronamespace for schemas (Tom)
•
Restructure aggregates to have pg_proc entries (Tom)
•
System relations now have their own namespace, pg_* test not required (Fernando Nasser)
•
Rename TOAST index names to be *_index rather than *_idx (Neil)
•
Add namespaces for operators, opclasses (Tom)
•
Add additional checks to server control file (Thomas)
•
New Polish FAQ (Marcin Mazurek)
•
Add Posix semaphore support (Tom)
•
Document need for reindex (Bruce)
•
Rename some internal identifiers to simplify Windows compile (Jan, Katherine Ward)
•
Add documentation on computing disk space (Bruce)
•
Remove KSQO from GUC (Bruce)
•
Fix memory leak in rtree (Kenneth Been)
•
Modify a few error messages for consistency (Bruce)
•
Remove unused system table columns (Peter)
•
Make system columns NOT NULL where appropriate (Tom)
•
Clean up use of sprintf in favor of snprintf() (Neil, Jukka Holappa)
•
Remove OPAQUE and create specific subtypes (Tom)
•
Cleanups in array internal handling (Joe, Tom)
•
Disallow pg_atoi('') (Bruce)
•
Remove parameter wal_files because WAL files are now recycled (Bruce)
•
Add version numbers to heap pages (Tom)
E.8.3.16. Contrib •
Allow inet arrays in /contrib/array (Neil)
•
GiST fixes (Teodor Sigaev, Neil)
•
Upgrade /contrib/mysql
1078
•
Add /contrib/dbsize which shows table sizes without vacuum (Peter)
•
Add /contrib/intagg, integer aggregator routines (mlw)
•
Improve /contrib/oid2name (Neil, Bruce)
•
Improve /contrib/tsearch (Oleg, Teodor Sigaev)
•
Cleanups of /contrib/rserver (Alexey V. Borzov)
•
Update /contrib/oracle conversion utility (Gilles Darold)
•
Update /contrib/dblink (Joe)
•
Improve options supported by /contrib/vacuumlo (Mario Weilguni)
•
Improvements to /contrib/intarray (Oleg, Teodor Sigaev, Andrey Oktyabrski)
•
Add /contrib/reindexdb utility (Shaun Thomas)
•
Add indexing to /contrib/isbn_issn (Dan Weston)
•
Add /contrib/dbmirror (Steven Singer)
•
Improve /contrib/pgbench (Neil)
•
Add /contrib/tablefunc table function examples (Joe)
•
Add /contrib/ltree data type for tree structures (Teodor Sigaev, Oleg Bartunov)
•
Move /contrib/pg_controldata, pg_resetxlog into main tree (Bruce)
•
Fixes to /contrib/cube (Bruno Wolff)
•
Improve /contrib/fulltextindex (Christopher)
E.9. Release 7.2.4 Release date: 2003-01-30
This release contains a variety of fixes for version 7.2.3, including fixes to prevent possible data loss.
E.9.1. Migration to version 7.2.4 A dump/restore is not required for those running version 7.2.*.
E.9.2. Changes •
Fix some additional cases of VACUUM "No one parent tuple was found" error
•
Prevent VACUUM from being called inside a function (Bruce)
•
Ensure pg_clog updates are sync'd to disk before marking checkpoint complete
•
Avoid integer overflow during large hash joins
•
Make GROUP commands work when pg_group.grolist is large enough to be toasted
•
Fix errors in datetime tables; some timezone names weren't being recognized
•
Fix integer overflows in circle_poly(), path_encode(), path_add() (Neil)
•
Repair long-standing logic errors in lseg_eq(), lseg_ne(), lseg_center()
E.10. Release 7.2.3 Release date: 2002-10-01
This release contains a variety of fixes for version 7.2.2, including fixes to prevent possible data loss.
E.10.1. Migration to version 7.2.3 A dump/restore is not required for those running version 7.2.*.
1079
E.10.2. Changes •
Prevent possible compressed transaction log loss (Tom)
•
Prevent non-superuser from increasing most recent vacuum info (Tom)
•
Handle pre-1970 date values in newer versions of glibc (Tom)
•
Fix possible hang during server shutdown
•
Prevent spinlock hangs on SMP PPC machines (Tomoyuki Niijima)
•
Fix pg_dump to properly dump FULL JOIN USING (Tom)
E.11. Release 7.2.2 Release date: 2002-08-23
This release contains a variety of fixes for version 7.2.1.
E.11.1. Migration to version 7.2.2 A dump/restore is not required for those running version 7.2.*.
E.11.2. Changes •
Allow EXECUTE of "CREATE TABLE AS ... SELECT" in PL/pgSQL (Tom)
•
Fix for compressed transaction log id wraparound (Tom)
•
Fix PQescapeBytea/PQunescapeBytea so that they handle bytes > 0x7f (Tatsuo)
•
Fix for psql and pg_dump crashing when invoked with non-existent long options (Tatsuo)
•
Fix crash when invoking geometric operators (Tom)
•
Allow OPEN cursor(args) (Tom)
•
Fix for rtree_gist index build (Teodor)
•
Fix for dumping user-defined aggregates (Tom)
•
contrib/intarray fixes (Oleg)
•
Fix for complex UNION/EXCEPT/INTERSECT queries using parens (Tom)
•
Fix to pg_convert (Tatsuo)
•
Fix for crash with long DATA strings (Thomas, Neil)
•
Fix for repeat(), lpad(), rpad() and long strings (Neil)
E.12. Release 7.2.1 Release date: 2002-03-21
This release contains a variety of fixes for version 7.2.
E.12.1. Migration to version 7.2.1 A dump/restore is not required for those running version 7.2.
E.12.2. Changes •
Ensure that sequence counters do not go backwards after a crash (Tom)
•
Fix pgaccess kanji-conversion key binding (Tatsuo)
•
Optimizer improvements (Tom)
•
Cash I/O improvements (Tom)
1080
•
New Russian FAQ
•
Compile fix for missing AuthBlockSig (Heiko)
•
Additional time zones and time zone fixes (Thomas)
•
Allow psql \connect to handle mixed case database and user names (Tom)
•
Return proper OID on command completion even with ON INSERT rules (Tom)
•
Allow COPY FROM to use 8-bit DELIMITERS (Tatsuo)
•
Fix bug in extract/date_part for milliseconds/microseconds (Tatsuo)
•
Improve handling of multiple UNIONs with different lengths (Tom)
•
contrib/btree_gist improvements (Teodor Sigaev)
•
contrib/tsearch dictionary improvements, see README.tsearch for an additional installation step (Thomas T. Thai, Teodor Sigaev)
•
Fix for array subscripts handling (Tom)
•
Allow EXECUTE of "CREATE TABLE AS ... SELECT" in PL/pgSQL (Tom)
E.13. Release 7.2 Release date: 2002-02-04
E.13.1. Overview This release improves PostgreSQL for use in high-volume applications. Major changes in this release: VACUUM Vacuuming no longer locks tables, thus allowing normal user access during the vacuum. A new VACUUM FULL command does old-style vacuum by locking the table and shrinking the on-disk copy of the table. Transactions There is no longer a problem with installations that exceed four billion transactions. OIDs OIDs are now optional. Users can now create tables without OIDs for cases where OID usage is excessive. Optimizer The system now computes histogram column statistics during ANALYZE, allowing much better optimizer choices. Security A new MD5 encryption option allows more secure storage and transfer of passwords. A new Unixdomain socket authentication option is available on Linux and BSD systems. Statistics Administrators can use the new table access statistics module to get fine-grained information about table and index usage. Internationalization Program and library messages can now be displayed in several languages.
E.13.2. Migration to version 7.2 A dump/restore using pg_dump is required for those wishing to migrate data from any previous release. Observe the following incompatibilities:
1081
•
The semantics of the VACUUM command have changed in this release. You may wish to update your maintenance procedures accordingly.
•
In this release, comparisons using = NULL will always return false (or NULL, more precisely). Previous releases automatically transformed this syntax to IS NULL. The old behavior can be re-enabled using a postgresql.conf parameter.
•
The pg_hba.conf and pg_ident.conf configuration is now only reloaded after receiving a SIGHUP signal, not with each connection.
•
The function octet_length() now returns the uncompressed data length.
•
The date/time value 'current' is no longer available. You will need to rewrite your applications.
•
The timestamp(), time(), and interval() functions are no longer available. Instead of timestamp(), use timestamp 'string' or CAST.
The SELECT ... LIMIT #,# syntax will be removed in the next release. You should change your queries to use separate LIMIT and OFFSET clauses, e.g. LIMIT 10 OFFSET 20.
E.13.3. Changes E.13.3.1. Server Operation •
Create temporary files in a separate directory (Bruce)
•
Delete orphaned temporary files on postmaster startup (Bruce)
•
Added unique indexes to some system tables (Tom)
•
System table operator reorganization (Oleg Bartunov, Teodor Sigaev, Tom)
•
Renamed pg_log to pg_clog (Tom)
•
Enable SIGTERM, SIGQUIT to kill backends (Jan)
•
Removed compile-time limit on number of backends (Tom)
•
Better cleanup for semaphore resource failure (Tatsuo, Tom)
•
Allow safe transaction ID wraparound (Tom)
•
Removed OIDs from some system tables (Tom)
•
Removed "triggered data change violation" error check (Tom)
•
SPI portal creation of prepared/saved plans (Jan)
•
Allow SPI column functions to work for system columns (Tom)
•
Long value compression improvement (Tom)
•
Statistics collector for table, index access (Jan)
•
Truncate extra-long sequence names to a reasonable value (Tom)
•
Measure transaction times in milliseconds (Thomas)
•
Fix TID sequential scans (Hiroshi)
•
Superuser ID now fixed at 1 (Peter E)
•
New pg_ctl "reload" option (Tom)
E.13.3.2. Performance •
Optimizer improvements (Tom)
•
New histogram column statistics for optimizer (Tom)
•
Reuse write-ahead log files rather than discarding them (Tom)
•
Cache improvements (Tom)
•
IS NULL, IS NOT NULL optimizer improvement (Tom)
1082
•
Improve lock manager to reduce lock contention (Tom)
•
Keep relcache entries for index access support functions (Tom)
•
Allow better selectivity with NaN and infinities in NUMERIC (Tom)
•
R-tree performance improvements (Kenneth Been)
•
B-tree splits more efficient (Tom)
E.13.3.3. Privileges •
Change UPDATE, DELETE privileges to be distinct (Peter E)
•
New REFERENCES, TRIGGER privileges (Peter E)
•
Allow GRANT/REVOKE to/from more than one user at a time (Peter E)
•
New has_table_privilege() function (Joe Conway)
•
Allow non-superuser to vacuum database (Tom)
•
New SET SESSION AUTHORIZATION command (Peter E)
•
Fix bug in privilege modifications on newly created tables (Tom)
•
Disallow access to pg_statistic for non-superuser, add user-accessible views (Tom)
E.13.3.4. Client Authentication •
Fork postmaster before doing authentication to prevent hangs (Peter E)
•
Add ident authentication over Unix domain sockets on Linux, *BSD (Helge Bahmann, Oliver Elphick, Teodor Sigaev, Bruce)
•
Add a password authentication method that uses MD5 encryption (Bruce)
•
Allow encryption of stored passwords using MD5 (Bruce)
•
PAM authentication (Dominic J. Eidson)
•
Load pg_hba.conf and pg_ident.conf only on startup and SIGHUP (Bruce)
E.13.3.5. Server Configuration •
Interpretation of some time zone abbreviations as Australian rather than North American now settable at run time (Bruce)
•
New parameter to set default transaction isolation level (Peter E)
•
New parameter to enable conversion of "expr = NULL" into "expr IS NULL", off by default (Peter E)
•
New parameter to control memory usage by VACUUM (Tom)
•
New parameter to set client authentication timeout (Tom)
•
New parameter to set maximum number of open files (Tom)
E.13.3.6. Queries •
Statements added by INSERT rules now execute after the INSERT (Jan)
•
Prevent unadorned relation names in target list (Bruce)
•
NULLs now sort after all normal values in ORDER BY (Tom)
•
New IS UNKNOWN, IS NOT UNKNOWN Boolean tests (Tom)
•
New SHARE UPDATE EXCLUSIVE lock mode (Tom)
•
New EXPLAIN ANALYZE command that shows run times and row counts (Martijn van Oosterhout)
•
Fix problem with LIMIT and subqueries (Tom)
•
Fix for LIMIT, DISTINCT ON pushed into subqueries (Tom)
•
Fix nested EXCEPT/INTERSECT (Tom)
1083
E.13.3.7. Schema Manipulation •
Fix SERIAL in temporary tables (Bruce)
•
Allow temporary sequences (Bruce)
•
Sequences now use int8 internally (Tom)
•
New SERIAL8 creates int8 columns with sequences, default still SERIAL4 (Tom)
•
Make OIDs optional using WITHOUT OIDS (Tom)
•
Add %TYPE syntax to CREATE TYPE (Ian Lance Taylor)
•
Add ALTER TABLE / DROP CONSTRAINT for CHECK constraints (Christopher Kings-Lynne)
•
New CREATE OR REPLACE FUNCTION to alter existing function (preserving the function OID) (Gavin Sherry)
•
Add ALTER TABLE / ADD [ UNIQUE | PRIMARY ] (Christopher Kings-Lynne)
•
Allow column renaming in views
•
Make ALTER TABLE / RENAME COLUMN update column names of indexes (Brent Verner)
•
Fix for ALTER TABLE / ADD CONSTRAINT ... CHECK with inherited tables (Stephan Szabo)
•
ALTER TABLE RENAME update foreign-key trigger arguments correctly (Brent Verner)
•
DROP AGGREGATE and COMMENT ON AGGREGATE now accept an aggtype (Tom)
•
Add automatic return type data casting for SQL functions (Tom)
•
Allow GiST indexes to handle NULLs and multikey indexes (Oleg Bartunov, Teodor Sigaev, Tom)
•
Enable partial indexes (Martijn van Oosterhout)
E.13.3.8. Utility Commands •
Add RESET ALL, SHOW ALL (Marko Kreen)
•
CREATE/ALTER USER/GROUP now allow options in any order (Vince)
•
Add LOCK A, B, C functionality (Neil Padgett)
•
New ENCRYPTED/UNENCRYPTED option to CREATE/ALTER USER (Bruce)
•
New light-weight VACUUM does not lock table; old semantics are available as VACUUM FULL (Tom)
•
Disable COPY TO/FROM on views (Bruce)
•
COPY DELIMITERS string must be exactly one character (Tom)
•
VACUUM warning about index tuples fewer than heap now only appears when appropriate (Martijn van Oosterhout)
•
Fix privilege checks for CREATE INDEX (Tom)
•
Disallow inappropriate use of CREATE/DROP INDEX/TRIGGER/VIEW (Tom)
E.13.3.9. Data Types and Functions •
SUM(), AVG(), COUNT() now uses int8 internally for speed (Tom)
•
Add convert(), convert2() (Tatsuo)
•
New function bit_length() (Peter E)
•
Make the "n" in CHAR(n)/VARCHAR(n) represents letters, not bytes (Tatsuo)
•
CHAR(), VARCHAR() now reject strings that are too long (Peter E)
•
BIT VARYING now rejects bit strings that are too long (Peter E)
•
BIT now rejects bit strings that do not match declared size (Peter E)
•
INET, CIDR text conversion functions (Alex Pilosov)
1084
•
INET, CIDR operators << and <<= indexable (Alex Pilosov)
•
Bytea \### now requires valid three digit octal number
•
Bytea comparison improvements, now supports =, <>, >, >=, <, and <=
•
Bytea now supports B-tree indexes
•
Bytea now supports LIKE, LIKE...ESCAPE, NOT LIKE, NOT LIKE...ESCAPE
•
Bytea now supports concatenation
•
New bytea functions: position, substring, trim, btrim, and length
•
New encode() function mode, "escaped", converts minimally escaped bytea to/from text
•
Add pg_database_encoding_max_length() (Tatsuo)
•
Add pg_client_encoding() function (Tatsuo)
•
now() returns time with millisecond precision (Thomas)
•
New TIMESTAMP WITHOUT TIMEZONE data type (Thomas)
•
Add ISO date/time specification with "T", yyyy-mm-ddThh:mm:ss (Thomas)
•
New xid/int comparison functions (Hiroshi)
•
Add precision to TIME, TIMESTAMP, and INTERVAL data types (Thomas)
•
Modify type coercion logic to attempt binary-compatible functions first (Tom)
•
New encode() function installed by default (Marko Kreen)
•
Improved to_*() conversion functions (Karel Zak)
•
Optimize LIKE/ILIKE when using single-byte encodings (Tatsuo)
•
New functions in contrib/pgcrypto: crypt(), hmac(), encrypt(), gen_salt() (Marko Kreen)
•
Correct description of translate() function (Bruce)
•
Add INTERVAL argument for SET TIME ZONE (Thomas)
•
Add INTERVAL YEAR TO MONTH (etc.) syntax (Thomas)
•
Optimize length functions when using single-byte encodings (Tatsuo)
•
Fix path_inter, path_distance, path_length, dist_ppath to handle closed paths (Curtis Barrett, Tom)
•
octet_length(text) now returns non-compressed length (Tatsuo, Bruce)
•
Handle "July" full name in date/time literals (Greg Sabino Mullane)
•
Some datatype() function calls now evaluated differently
•
Add support for Julian and ISO time specifications (Thomas)
E.13.3.10. Internationalization •
National language support in psql, pg_dump, libpq, and server (Peter E)
•
Message translations in Chinese (simplified, traditional), Czech, French, German, Hungarian, Russian, Swedish (Peter E, Serguei A. Mokhov, Karel Zak, Weiping He, Zhenbang Wei, Kovacs Zoltan)
•
Make trim, ltrim, rtrim, btrim, lpad, rpad, translate multibyte aware (Tatsuo)
•
Add LATIN5,6,7,8,9,10 support (Tatsuo)
•
Add ISO 8859-5,6,7,8 support (Tatsuo)
•
Correct LATIN5 to mean ISO-8859-9, not ISO-8859-5 (Tatsuo)
•
Make mic2ascii() non-ASCII aware (Tatsuo)
•
Reject invalid multibyte character sequences (Tatsuo)
1085
E.13.3.11. PL/pgSQL •
Now uses portals for SELECT loops, allowing huge result sets (Jan)
•
CURSOR and REFCURSOR support (Jan)
•
Can now return open cursors (Jan)
•
Add ELSEIF (Klaus Reger)
•
Improve PL/pgSQL error reporting, including location of error (Tom)
•
Allow IS or FOR key words in cursor declaration, for compatibility (Bruce)
•
Fix for SELECT ... FOR UPDATE (Tom)
•
Fix for PERFORM returning multiple rows (Tom)
•
Make PL/pgSQL use the server's type coercion code (Tom)
•
Memory leak fix (Jan, Tom)
•
Make trailing semicolon optional (Tom)
E.13.3.12. PL/Perl •
New untrusted PL/Perl (Alex Pilosov)
•
PL/Perl is now built on some platforms even if libperl is not shared (Peter E)
E.13.3.13. PL/Tcl •
Now reports errorInfo (Vsevolod Lobko)
•
Add spi_lastoid function ([email protected])
E.13.3.14. PL/Python •
...is new (Andrew Bosma)
E.13.3.15. psql •
\d displays indexes in unique, primary groupings (Christopher Kings-Lynne)
•
Allow trailing semicolons in backslash commands (Greg Sabino Mullane)
•
Read password from /dev/tty if possible
•
Force new password prompt when changing user and database (Tatsuo, Tom)
•
Format the correct number of columns for Unicode (Patrice)
E.13.3.16. libpq •
New function PQescapeString() to escape quotes in command strings (Florian Weimer)
•
New function PQescapeBytea() escapes binary strings for use as SQL string literals
E.13.3.17. JDBC •
Return OID of INSERT (Ken K)
•
Handle more data types (Ken K)
•
Handle single quotes and newlines in strings (Ken K)
•
Handle NULL variables (Ken K)
•
Fix for time zone handling (Barry Lind)
•
Improved Druid support
•
Allow eight-bit characters with non-multibyte server (Barry Lind)
•
Support BIT, BINARY types (Ned Wolpert)
•
Reduce memory usage (Michael Stephens, Dave Cramer)
1086
•
Update DatabaseMetaData (Peter E)
•
Add DatabaseMetaData.getCatalogs() (Peter E)
•
Encoding fixes (Anders Bengtsson)
•
Get/setCatalog methods (Jason Davies)
•
DatabaseMetaData.getColumns() now returns column defaults (Jason Davies)
•
DatabaseMetaData.getColumns() performance improvement (Jeroen van Vianen)
•
Some JDBC1 and JDBC2 merging (Anders Bengtsson)
•
Transaction performance improvements (Barry Lind)
•
Array fixes (Greg Zoller)
•
Serialize addition
•
Fix batch processing (Rene Pijlman)
•
ExecSQL method reorganization (Anders Bengtsson)
•
GetColumn() fixes (Jeroen van Vianen)
•
Fix isWriteable() function (Rene Pijlman)
•
Improved passage of JDBC2 conformance tests (Rene Pijlman)
•
Add bytea type capability (Barry Lind)
•
Add isNullable() (Rene Pijlman)
•
JDBC date/time test suite fixes (Liam Stewart)
•
Fix for SELECT 'id' AS xxx FROM table (Dave Cramer)
•
Fix DatabaseMetaData to show precision properly (Mark Lillywhite)
•
New getImported/getExported keys (Jason Davies)
•
MD5 password encryption support (Jeremy Wohl)
•
Fix to actually use type cache (Ned Wolpert)
E.13.3.18. ODBC •
Remove query size limit (Hiroshi)
•
Remove text field size limit (Hiroshi)
•
Fix for SQLPrimaryKeys in multibyte mode (Hiroshi)
•
Allow ODBC procedure calls (Hiroshi)
•
Improve boolean handing (Aidan Mountford)
•
Most configuration options now settable via DSN (Hiroshi)
•
Multibyte, performance fixes (Hiroshi)
•
Allow driver to be used with iODBC or unixODBC (Peter E)
•
MD5 password encryption support (Bruce)
•
Add more compatibility functions to odbc.sql (Peter E)
E.13.3.19. ECPG •
EXECUTE ... INTO implemented (Christof Petig)
•
Multiple row descriptor support (e.g. CARDINALITY) (Christof Petig)
•
Fix for GRANT parameters (Lee Kindness)
•
Fix INITIALLY DEFERRED bug
•
Various bug fixes (Michael, Christof Petig)
1087
•
Auto allocation for indicator variable arrays (int *ind_p=NULL)
•
Auto allocation for string arrays (char **foo_pp=NULL)
•
ECPGfree_auto_mem fixed
•
All function names with external linkage are now prefixed by ECPG
•
Fixes for arrays of structures (Michael)
E.13.3.20. Misc. Interfaces •
Python fix fetchone() (Gerhard Haring)
•
Use UTF, Unicode in Tcl where appropriate (Vsevolod Lobko, Reinhard Max)
•
Add Tcl COPY TO/FROM (ljb)
•
Prevent output of default index op class in pg_dump (Tom)
•
Fix libpgeasy memory leak (Bruce)
E.13.3.21. Build and Install •
Configure, dynamic loader, and shared library fixes (Peter E)
•
Fixes in QNX 4 port (Bernd Tegge)
•
Fixes in Cygwin and Windows ports (Jason Tishler, Gerhard Haring, Dmitry Yurtaev, Darko Prenosil, Mikhail Terekhov)
•
Fix for Windows socket communication failures (Magnus, Mikhail Terekhov)
•
Hurd compile fix (Oliver Elphick)
•
BeOS fixes (Cyril Velter)
•
Remove configure --enable-unicode-conversion, now enabled by multibyte (Tatsuo)
•
AIX fixes (Tatsuo, Andreas)
•
Fix parallel make (Peter E)
•
Install SQL language manual pages into OS-specific directories (Peter E)
•
Rename config.h to pg_config.h (Peter E)
•
Reorganize installation layout of header files (Peter E)
E.13.3.22. Source Code •
Remove SEP_CHAR (Bruce)
•
New GUC hooks (Tom)
•
Merge GUC and command line handling (Marko Kreen)
•
Remove EXTEND INDEX (Martijn van Oosterhout, Tom)
•
New pgjindent utility to indent java code (Bruce)
•
Remove define of true/false when compiling under C++ (Leandro Fanzone, Tom)
•
pgindent fixes (Bruce, Tom)
•
Replace strcasecmp() with strcmp() where appropriate (Peter E)
•
Dynahash portability improvements (Tom)
•
Add 'volatile' usage in spinlock structures
•
Improve signal handling logic (Tom)
E.13.3.23. Contrib •
New contrib/rtree_gist (Oleg Bartunov, Teodor Sigaev)
1088
•
New contrib/tsearch full-text indexing (Oleg, Teodor Sigaev)
•
Add contrib/dblink for remote database access (Joe Conway)
•
contrib/ora2pg Oracle conversion utility (Gilles Darold)
•
contrib/xml XML conversion utility (John Gray)
•
contrib/fulltextindex fixes (Christopher Kings-Lynne)
•
New contrib/fuzzystrmatch with levenshtein and metaphone, soundex merged (Joe Conway)
•
Add contrib/intarray boolean queries, binary search, fixes (Oleg Bartunov)
•
New pg_upgrade utility (Bruce)
•
Add new pg_resetxlog options (Bruce, Tom)
E.14. Release 7.1.3 Release date: 2001-08-15
E.14.1. Migration to version 7.1.3 A dump/restore is not required for those running 7.1.X.
E.14.2. Changes Remove unused WAL segements of large transactions (Tom) Multiaction rule fix (Tom) PL/pgSQL memory allocation fix (Jan) VACUUM buffer fix (Tom) Regression test fixes (Tom) pg_dump fixes for GRANT/REVOKE/comments on views, user-defined types (Tom) Fix subselects with DISTINCT ON or LIMIT (Tom) BeOS fix Disable COPY TO/FROM a view (Tom) Cygwin build (Jason Tishler)
E.15. Release 7.1.2 Release date: 2001-05-11
This has one fix from 7.1.1.
E.15.1. Migration to version 7.1.2 A dump/restore is not required for those running 7.1.X.
E.15.2. Changes Fix PL/pgSQL SELECTs when returning no rows Fix for psql backslash core dump Referential integrity privilege fix Optimizer fixes pg_dump cleanups
E.16. Release 7.1.1 Release date: 2001-05-05
This has a variety of fixes from 7.1.
1089
E.16.1. Migration to version 7.1.1 A dump/restore is not required for those running 7.1.
E.16.2. Changes Fix for numeric MODULO operator (Tom) pg_dump fixes (Philip) pg_dump can dump 7.0 databases (Philip) readline 4.2 fixes (Peter E) JOIN fixes (Tom) AIX, MSWIN, VAX, N32K fixes (Tom) Multibytes fixes (Tom) Unicode fixes (Tatsuo) Optimizer improvements (Tom) Fix for whole rows in functions (Tom) Fix for pg_ctl and option strings with spaces (Peter E) ODBC fixes (Hiroshi) EXTRACT can now take string argument (Thomas) Python fixes (Darcy)
E.17. Release 7.1 Release date: 2001-04-13
This release focuses on removing limitations that have existed in the PostgreSQL code for many years. Major changes in this release: Write-ahead Log (WAL) To maintain database consistency in case of an operating system crash, previous releases of PostgreSQL have forced all data modifications to disk before each transaction commit. With WAL, only one log file must be flushed to disk, greatly improving performance. If you have been using -F in previous releases to disable disk flushes, you may want to consider discontinuing its use. TOAST TOAST - Previous releases had a compiled-in row length limit, typically 8k - 32k. This limit made storage of long text fields difficult. With TOAST, long rows of any length can be stored with good performance. Outer Joins We now support outer joins. The UNION/NOT IN workaround for outer joins is no longer required. We use the SQL92 outer join syntax. Function Manager The previous C function manager did not handle null values properly, nor did it support 64-bit CPU's (Alpha). The new function manager does. You can continue using your old custom functions, but you may want to rewrite them in the future to use the new function manager call interface. Complex Queries A large number of complex queries that were unsupported in previous releases now work. Many combinations of views, aggregates, UNION, LIMIT, cursors, subqueries, and inherited tables now work properly. Inherited tables are now accessed by default. Subqueries in FROM are now supported.
E.17.1. Migration to version 7.1 A dump/restore using pg_dump is required for those wishing to migrate data from any previous release.
E.17.2. Changes Bug Fixes
1090
--------Many multibyte/Unicode/locale fixes (Tatsuo and others) More reliable ALTER TABLE RENAME (Tom) Kerberos V fixes (David Wragg) Fix for INSERT INTO...SELECT where targetlist has subqueries (Tom) Prompt username/password on standard error (Bruce) Large objects inv_read/inv_write fixes (Tom) Fixes for to_char(), to_date(), to_ascii(), and to_timestamp() (Karel, Daniel Baldoni) Prevent query expressions from leaking memory (Tom) Allow UPDATE of arrays elements (Tom) Wake up lock waiters during cancel (Hiroshi) Fix rare cursor crash when using hash join (Tom) Fix for DROP TABLE/INDEX in rolled-back transaction (Hiroshi) Fix psql crash from \l+ if MULTIBYTE enabled (Peter E) Fix truncation of rule names during CREATE VIEW (Ross Reedstrom) Fix PL/perl (Alex Kapranoff) Disallow LOCK on views (Mark Hollomon) Disallow INSERT/UPDATE/DELETE on views (Mark Hollomon) Disallow DROP RULE, CREATE INDEX, TRUNCATE on views (Mark Hollomon) Allow PL/pgSQL accept non-ASCII identifiers (Tatsuo) Allow views to proper handle GROUP BY, aggregates, DISTINCT (Tom) Fix rare failure with TRUNCATE command (Tom) Allow UNION/INTERSECT/EXCEPT to be used with ALL, subqueries, views, DISTINCT, ORDER BY, SELECT...INTO (Tom) Fix parser failures during aborted transactions (Tom) Allow temporary relations to properly clean up indexes (Bruce) Fix VACUUM problem with moving rows in same page (Tom) Modify pg_dump to better handle user-defined items in template1 (Philip) Allow LIMIT in VIEW (Tom) Require cursor FETCH to honor LIMIT (Tom) Allow PRIMARY/FOREIGN Key definitions on inherited columns (Stephan) Allow ORDER BY, LIMIT in subqueries (Tom) Allow UNION in CREATE RULE (Tom) Make ALTER/DROP TABLE rollback-able (Vadim, Tom) Store initdb collation in pg_control so collation cannot be changed (Tom) Fix INSERT...SELECT with rules (Tom) Fix FOR UPDATE inside views and subselects (Tom) Fix OVERLAPS operators conform to SQL92 spec regarding NULLs (Tom) Fix lpad() and rpad() to handle length less than input string (Tom) Fix use of NOTIFY in some rules (Tom) Overhaul btree code (Tom) Fix NOT NULL use in Pl/pgSQL variables (Tom) Overhaul GIST code (Oleg) Fix CLUSTER to preserve constraints and column default (Tom) Improved deadlock detection handling (Tom) Allow multiple SERIAL columns in a table (Tom) Prevent occasional index corruption (Vadim) Enhancements -----------Add OUTER JOINs (Tom) Function manager overhaul (Tom) Allow ALTER TABLE RENAME on indexes (Tom) Improve CLUSTER (Tom) Improve ps status display for more platforms (Peter E, Marc) Improve CREATE FUNCTION failure message (Ross) JDBC improvements (Peter, Travis Bauer, Christopher Cain, William Webber, Gunnar) Grand Unified Configuration scheme/GUC. Many options can now be set in data/postgresql.conf, postmaster/postgres flags, or SET commands (Peter E) Improved handling of file descriptor cache (Tom) New warning code about auto-created table alias entries (Bruce)
1091
Overhaul initdb process (Tom, Peter E) Overhaul of inherited tables; inherited tables now accessed by default; new ONLY key word prevents it (Chris Bitmead, Tom) ODBC cleanups/improvements (Nick Gorham, Stephan Szabo, Zoltan Kovacs, Michael Fork) Allow renaming of temp tables (Tom) Overhaul memory manager contexts (Tom) pg_dumpall uses CREATE USER or CREATE GROUP rather using COPY (Peter E) Overhaul pg_dump (Philip Warner) Allow pg_hba.conf secondary password file to specify only username (Peter E) Allow TEMPORARY or TEMP key word when creating temporary tables (Bruce) New memory leak checker (Karel) New SET SESSION CHARACTERISTICS (Thomas) Allow nested block comments (Thomas) Add WITHOUT TIME ZONE type qualifier (Thomas) New ALTER TABLE ADD CONSTRAINT (Stephan) Use NUMERIC accumulators for INTEGER aggregates (Tom) Overhaul aggregate code (Tom) New VARIANCE and STDDEV() aggregates Improve dependency ordering of pg_dump (Philip) New pg_restore command (Philip) New pg_dump tar output option (Philip) New pg_dump of large objects (Philip) New ESCAPE option to LIKE (Thomas) New case-insensitive LIKE - ILIKE (Thomas) Allow functional indexes to use binary-compatible type (Tom) Allow SQL functions to be used in more contexts (Tom) New pg_config utility (Peter E) New PL/pgSQL EXECUTE command which allows dynamic SQL and utility statements (Jan) New PL/pgSQL GET DIAGNOSTICS statement for SPI value access (Jan) New quote_identifiers() and quote_literal() functions (Jan) New ALTER TABLE table OWNER TO user command (Mark Hollomon) Allow subselects in FROM, i.e. FROM (SELECT ...) [AS] alias (Tom) Update PyGreSQL to version 3.1 (D'Arcy) Store tables as files named by OID (Vadim) New SQL function setval(seq,val,bool) for use in pg_dump (Philip) Require DROP VIEW to remove views, no DROP TABLE (Mark) Allow DROP VIEW view1, view2 (Mark) Allow multiple objects in DROP INDEX, DROP RULE, and DROP TYPE (Tom) Allow automatic conversion to/from Unicode (Tatsuo, Eiji) New /contrib/pgcrypto hashing functions (Marko Kreen) New pg_dumpall --globals-only option (Peter E) New CHECKPOINT command for WAL which creates new WAL log file (Vadim) New AT TIME ZONE syntax (Thomas) Allow location of Unix domain socket to be configurable (David J. MacKenzie) Allow postmaster to listen on a specific IP address (David J. MacKenzie) Allow socket path name to be specified in hostname by using leading slash (David J. MacKenzie) Allow CREATE DATABASE to specify template database (Tom) New utility to convert MySQL schema dumps to SQL92 and PostgreSQL (Thomas) New /contrib/rserv replication toolkit (Vadim) New file format for COPY BINARY (Tom) New /contrib/oid2name to map numeric files to table names (B Palmer) New "idle in transaction" ps status message (Marc) Update to pgaccess 0.98.7 (Constantin Teodorescu) pg_ctl now defaults to -w (wait) on shutdown, new -l (log) option Add rudimentary dependency checking to pg_dump (Philip) Types ----Fix INET/CIDR type ordering and add new functions (Tom) Make OID behave as an unsigned type (Tom)
1092
Allow BIGINT as synonym for INT8 (Peter E) New int2 and int8 comparison operators (Tom) New BIT and BIT VARYING types (Adriaan Joubert, Tom, Peter E) CHAR() no longer faster than VARCHAR() because of TOAST (Tom) New GIST seg/cube examples (Gene Selkov) Improved round(numeric) handling (Tom) Fix CIDR output formatting (Tom) New CIDR abbrev() function (Tom) Performance ----------Write-Ahead Log (WAL) to provide crash recovery with less performance overhead (Vadim) ANALYZE stage of VACUUM no longer exclusively locks table (Bruce) Reduced file seeks (Denis Perchine) Improve BTREE code for duplicate keys (Tom) Store all large objects in a single table (Denis Perchine, Tom) Improve memory allocation performance (Karel, Tom) Source Code ----------New function manager call conventions (Tom) SGI portability fixes (David Kaelbling) New configure --enable-syslog option (Peter E) New BSDI README (Bruce) configure script moved to top level, not /src (Peter E) Makefile/configuration/compilation overhaul (Peter E) New configure --with-python option (Peter E) Solaris cleanups (Peter E) Overhaul /contrib Makefiles (Karel) New OpenSSL configuration option (Magnus, Peter E) AIX fixes (Andreas) QNX fixes (Maurizio) New heap_open(), heap_openr() API (Tom) Remove colon and semi-colon operators (Thomas) New pg_class.relkind value for views (Mark Hollomon) Rename ichar() to chr() (Karel) New documentation for btrim(), ascii(), chr(), repeat() (Karel) Fixes for NT/Cygwin (Pete Forman) AIX port fixes (Andreas) New BeOS port (David Reid, Cyril Velter) Add proofreader's changes to docs (Addison-Wesley, Bruce) New Alpha spinlock code (Adriaan Joubert, Compaq) UnixWare port overhaul (Peter E) New Darwin/MacOS X port (Peter Bierman, Bruce Hartzler) New FreeBSD Alpha port (Alfred) Overhaul shared memory segments (Tom) Add IBM S/390 support (Neale Ferguson) Moved macmanuf to /contrib (Larry Rosenman) Syslog improvements (Larry Rosenman) New template0 database that contains no user additions (Tom) New /contrib/cube and /contrib/seg GIST sample code (Gene Selkov) Allow NetBSD's libedit instead of readline (Peter) Improved assembly language source code format (Bruce) New contrib/pg_logger New --template option to createdb New contrib/pg_control utility (Oliver) New FreeBSD tools ipc_check, start-scripts/freebsd
E.18. Release 7.0.3 Release date: 2000-11-11
1093
This has a variety of fixes from 7.0.2.
E.18.1. Migration to version 7.0.3 A dump/restore is not required for those running 7.0.*.
E.18.2. Changes Jdbc fixes (Peter) Large object fix (Tom) Fix lean in COPY WITH OIDS leak (Tom) Fix backwards-index-scan (Tom) Fix SELECT ... FOR UPDATE so it checks for duplicate keys (Hiroshi) Add --enable-syslog to configure (Marc) Fix abort transaction at backend exit in rare cases (Tom) Fix for psql \l+ when multibyte enabled (Tatsuo) Allow PL/pgSQL to accept non ascii identifiers (Tatsuo) Make vacuum always flush buffers (Tom) Fix to allow cancel while waiting for a lock (Hiroshi) Fix for memory aloocation problem in user authentication code (Tom) Remove bogus use of int4out() (Tom) Fixes for multiple subqueries in COALESCE or BETWEEN (Tom) Fix for failure of triggers on heap open in certain cases (Jeroen van Vianen) Fix for erroneous selectivity of not-equals (Tom) Fix for erroneous use of strcmp() (Tom) Fix for bug where storage manager accesses items beyond end of file (Tom) Fix to include kernel errno message in all smgr elog messages (Tom) Fix for '.' not in PATH at build time (SL Baur) Fix for out-of-file-descriptors error (Tom) Fix to make pg_dump dump 'iscachable' flag for functions (Tom) Fix for subselect in targetlist of Append node (Tom) Fix for mergejoin plans (Tom) Fix TRUNCATE failure on relations with indexes (Tom) Avoid database-wide restart on write error (Hiroshi) Fix nodeMaterial to honor chgParam by recomputing its output (Tom) Fix VACUUM problem with moving chain of update row versions when source and destination of a row version lie on the same page (Tom) Fix user.c CommandCounterIncrement (Tom) Fix for AM/PM boundary problem in to_char() (Karel Zak) Fix TIME aggregate handling (Tom) Fix to_char() to avoid coredump on NULL input (Tom) Buffer fix (Tom) Fix for inserting/copying longer multibyte strings into char() data types (Tatsuo) Fix for crash of backend, on abort (Tom)
E.19. Release 7.0.2 Release date: 2000-06-05
This is a repackaging of 7.0.1 with added documentation.
E.19.1. Migration to version 7.0.2 A dump/restore is not required for those running 7.*.
E.19.2. Changes Added documentation to tarball.
1094
E.20. Release 7.0.1 Release date: 2000-06-01
This is a cleanup release for 7.0.
E.20.1. Migration to version 7.0.1 A dump/restore is not required for those running 7.0.
E.20.2. Changes Fix many CLUSTER failures (Tom) Allow ALTER TABLE RENAME works on indexes (Tom) Fix plpgsql to handle datetime->timestamp and timespan->interval (Bruce) New configure --with-setproctitle switch to use setproctitle() (Marc, Bruce) Fix the off by one errors in ResultSet from 6.5.3, and more. jdbc ResultSet fixes (Joseph Shraibman) optimizer tunings (Tom) Fix create user for pgaccess Fix for UNLISTEN failure IRIX fixes (David Kaelbling) QNX fixes (Andreas Kardos) Reduce COPY IN lock level (Tom) Change libpqeasy to use PQconnectdb() style parameters (Bruce) Fix pg_dump to handle OID indexes (Tom) Fix small memory leak (Tom) Solaris fix for createdb/dropdb (Tatsuo) Fix for non-blocking connections (Alfred Perlstein) Fix improper recovery after RENAME TABLE failures (Tom) Copy pg_ident.conf.sample into /lib directory in install (Bruce) Add SJIS UDC (NEC selection IBM kanji) support (Eiji Tokuya) Fix too long syslog message (Tatsuo) Fix problem with quoted indexes that are too long (Tom) JDBC ResultSet.getTimestamp() fix (Gregory Krasnow & Floyd Marinescu) ecpg changes (Michael)
E.21. Release 7.0 Release date: 2000-05-08
This release contains improvements in many areas, demonstrating the continued growth of PostgreSQL. There are more improvements and fixes in 7.0 than in any previous release. The developers have confidence that this is the best release yet; we do our best to put out only solid releases, and this one is no exception. Major changes in this release: Foreign Keys Foreign keys are now implemented, with the exception of PARTIAL MATCH foreign keys. Many users have been asking for this feature, and we are pleased to offer it. Optimizer Overhaul Continuing on work started a year ago, the optimizer has been improved, allowing better query plan selection and faster performance with less memory usage. Updated psql psql, our interactive terminal monitor, has been updated with a variety of new features. See the psql manual page for details.
1095
Join Syntax SQL92 join syntax is now supported, though only as INNER JOIN for this release. JOIN, NATURAL JOIN, JOIN/USING, and JOIN/ON are available, as are column correlation names.
E.21.1. Migration to version 7.0 A dump/restore using pg_dump is required for those wishing to migrate data from any previous release of PostgreSQL. For those upgrading from 6.5.*, you may instead use pg_upgrade to upgrade to this release; however, a full dump/reload installation is always the most robust method for upgrades. Interface and compatibility issues to consider for the new release include: •
The date/time types datetime and timespan have been superseded by the SQL92-defined types timestamp and interval. Although there has been some effort to ease the transition by allowing PostgreSQL to recognize the deprecated type names and translate them to the new type names, this mechanism may not be completely transparent to your existing application.
•
The optimizer has been substantially improved in the area of query cost estimation. In some cases, this will result in decreased query times as the optimizer makes a better choice for the preferred plan. However, in a small number of cases, usually involving pathological distributions of data, your query times may go up. If you are dealing with large amounts of data, you may want to check your queries to verify performance.
•
The JDBC and ODBC interfaces have been upgraded and extended.
•
The string function CHAR_LENGTH is now a native function. Previous versions translated this into a call to LENGTH, which could result in ambiguity with other types implementing LENGTH such as the geometric types.
E.21.2. Changes Bug Fixes --------Prevent function calls exceeding maximum number of arguments (Tom) Improve CASE construct (Tom) Fix SELECT coalesce(f1,0) FROM int4_tbl GROUP BY f1 (Tom) Fix SELECT sentence.words[0] FROM sentence GROUP BY sentence.words[0] (Tom) Fix GROUP BY scan bug (Tom) Improvements in SQL grammar processing (Tom) Fix for views involved in INSERT ... SELECT ... (Tom) Fix for SELECT a/2, a/2 FROM test_missing_target GROUP BY a/2 (Tom) Fix for subselects in INSERT ... SELECT (Tom) Prevent INSERT ... SELECT ... ORDER BY (Tom) Fixes for relations greater than 2GB, including vacuum Improve propagating system table changes to other backends (Tom) Improve propagating user table changes to other backends (Tom) Fix handling of temp tables in complex situations (Bruce, Tom) Allow table locking at table open, improving concurrent reliability (Tom) Properly quote sequence names in pg_dump (Ross J. Reedstrom) Prevent DROP DATABASE while others accessing Prevent any rows from being returned by GROUP BY if no rows processed (Tom) Fix SELECT COUNT(1) FROM table WHERE ...' if no rows matching WHERE (Tom) Fix pg_upgrade so it works for MVCC (Tom) Fix for SELECT ... WHERE x IN (SELECT ... HAVING SUM(x) > 1) (Tom) Fix for "f1 datetime DEFAULT 'now'" (Tom) Fix problems with CURRENT_DATE used in DEFAULT (Tom) Allow comment-only lines, and ;;; lines too. (Tom) Improve recovery after failed disk writes, disk full (Hiroshi) Fix cases where table is mentioned in FROM but not joined (Tom) Allow HAVING clause without aggregate functions (Tom) Fix for "--" comment and no trailing newline, as seen in perl interface Improve pg_dump failure error reports (Bruce) Allow sorts and hashes to exceed 2GB file sizes (Tom)
1096
Fix for pg_dump dumping of inherited rules (Tom) Fix for NULL handling comparisons (Tom) Fix inconsistent state caused by failed CREATE/DROP commands (Hiroshi) Fix for dbname with dash Prevent DROP INDEX from interfering with other backends (Tom) Fix file descriptor leak in verify_password() Fix for "Unable to identify an operator =$" problem Fix ODBC so no segfault if CommLog and Debug enabled (Dirk Niggemann) Fix for recursive exit call (Massimo) Fix for extra-long timezones (Jeroen van Vianen) Make pg_dump preserve primary key information (Peter E) Prevent databases with single quotes (Peter E) Prevent DROP DATABASE inside transaction (Peter E) ecpg memory leak fixes (Stephen Birch) Fix for SELECT null::text, SELECT int4fac(null) and SELECT 2 + (null) (Tom) Y2K timestamp fix (Massimo) Fix for VACUUM 'HEAP_MOVED_IN was not expected' errors (Tom) Fix for views with tables/columns containing spaces (Tom) Prevent privileges on indexes (Peter E) Fix for spinlock stuck problem when error is generated (Hiroshi) Fix ipcclean on Linux Fix handling of NULL constraint conditions (Tom) Fix memory leak in odbc driver (Nick Gorham) Fix for privilege check on UNION tables (Tom) Fix to allow SELECT 'a' LIKE 'a' (Tom) Fix for SELECT 1 + NULL (Tom) Fixes to CHAR Fix log() on numeric type (Tom) Deprecate ':' and ';' operators Allow vacuum of temporary tables Disallow inherited columns with the same name as new columns Recover or force failure when disk space is exhausted (Hiroshi) Fix INSERT INTO ... SELECT with AS columns matching result columns Fix INSERT ... SELECT ... GROUP BY groups by target columns not source columns (Tom)
Fix Fix Fix Fix Fix Fix Fix
CREATE TABLE test (a char(5) DEFAULT text '', b int4) with INSERT (Tom) UNION with LIMIT CREATE TABLE x AS SELECT 1 UNION SELECT 2 CREATE TABLE test(col char(2) DEFAULT user) mismatched types in CREATE TABLE ... DEFAULT SELECT * FROM pg_class where oid in (0,-1) SELECT COUNT('asdf') FROM pg_class WHERE oid=12
Prevent user who can create databases can modifying pg_database table (Peter E)
Fix btree to give a useful elog when key > 1/2 (page - overhead) (Tom) Fix INSERT of 0.0 into DECIMAL(4,4) field (Tom) Enhancements -----------New CLI interface include file sqlcli.h, based on SQL3/SQL98 Remove all limits on query length, row length limit still exists (Tom) Update jdbc protocol to 2.0 (Jens Glaser <[email protected]>) Add TRUNCATE command to quickly truncate relation (Mike Mascari) Fix to give super user and createdb user proper update catalog rights (Peter E)
Allow ecpg bool variables to have NULL values (Christof) Issue ecpg error if NULL value for variable with no NULL indicator (Christof) Allow ^C to cancel COPY command (Massimo) Add SET FSYNC and SHOW PG_OPTIONS commands(Massimo) Function name overloading for dynamically-loaded C functions (Frankpitt) Add CmdTuples() to libpq++(Vince) New CREATE CONSTRAINT TRIGGER and SET CONSTRAINTS commands(Jan) Allow CREATE FUNCTION/WITH clause to be used for all language types configure --enable-debug adds -g (Peter E) configure --disable-debug removes -g (Peter E) Allow more complex default expressions (Tom)
1097
First real FOREIGN KEY constraint trigger functionality (Jan) Add FOREIGN KEY ... MATCH FULL ... ON DELETE CASCADE (Jan) Add FOREIGN KEY ... MATCHreferential actions (Don Baccus) Allow WHERE restriction on ctid (physical heap location) (Hiroshi) Move pginterface from contrib to interface directory, rename to pgeasy (Bruce) Change pgeasy connectdb() parameter ordering (Bruce) Require SELECT DISTINCT target list to have all ORDER BY columns (Tom) Add Oracle's COMMENT ON command (Mike Mascari <[email protected]>) libpq's PQsetNoticeProcessor function now returns previous hook(Peter E) Prevent PQsetNoticeProcessor from being set to NULL (Peter E) Make USING in COPY optional (Bruce) Allow subselects in the target list (Tom) Allow subselects on the left side of comparison operators (Tom) New parallel regression test (Jan) Change backend-side COPY to write files with permissions 644 not 666 (Tom) Force permissions on PGDATA directory to be secure, even if it exists (Tom) Added psql LASTOID variable to return last inserted oid (Peter E) Allow concurrent vacuum and remove pg_vlock vacuum lock file (Tom) Add privilege check for vacuum (Peter E) New libpq functions to allow asynchronous connections: PQconnectStart(), PQconnectPoll(), PQresetStart(), PQresetPoll(), PQsetenvStart(), PQsetenvPoll(), PQsetenvAbort (Ewan Mellor) New libpq PQsetenv() function (Ewan Mellor) create/alter user extension (Peter E) New postmaster.pid and postmaster.opts under $PGDATA (Tatsuo) New scripts for create/drop user/db (Peter E) Major psql overhaul (Peter E) Add const to libpq interface (Peter E) New libpq function PQoidValue (Peter E) Show specific non-aggregate causing problem with GROUP BY (Tom) Make changes to pg_shadow recreate pg_pwd file (Peter E) Add aggregate(DISTINCT ...) (Tom) Allow flag to control COPY input/output of NULLs (Peter E) Make postgres user have a password by default (Peter E) Add CREATE/ALTER/DROP GROUP (Peter E) All administration scripts now support --long options (Peter E, Karel) Vacuumdb script now supports --all option (Peter E) ecpg new portable FETCH syntax Add ecpg EXEC SQL IFDEF, EXEC SQL IFNDEF, EXEC SQL ELSE, EXEC SQL ELIF and EXEC SQL ENDIF directives Add pg_ctl script to control backend start-up (Tatsuo) Add postmaster.opts.default file to store start-up flags (Tatsuo) Allow --with-mb=SQL_ASCII Increase maximum number of index keys to 16 (Bruce) Increase maximum number of function arguments to 16 (Bruce) Allow configuration of maximum number of index keys and arguments (Bruce) Allow unprivileged users to change their passwords (Peter E) Password authentication enabled; required for new users (Peter E) Disallow dropping a user who owns a database (Peter E) Change initdb option --with-mb to --enable-multibyte Add option for initdb to prompts for superuser password (Peter E) Allow complex type casts like col::numeric(9,2) and col::int2::float8 (Tom) Updated user interfaces on initdb, initlocation, pg_dump, ipcclean (Peter E) New pg_char_to_encoding() and pg_encoding_to_char() functions (Tatsuo) libpq non-blocking mode (Alfred Perlstein) Improve conversion of types in casts that don't specify a length New plperl internal programming language (Mark Hollomon) Allow COPY IN to read file that do not end with a newline (Tom) Indicate when long identifiers are truncated (Tom) Allow aggregates to use type equivalency (Peter E) Add Oracle's to_char(), to_date(), to_datetime(), to_timestamp(), to_number() conversion functions (Karel Zak )
1098
Add SELECT DISTINCT ON (expr [, expr ...]) targetlist ... (Tom) Check to be sure ORDER BY is compatible with the DISTINCT operation (Tom) Add NUMERIC and int8 types to ODBC Improve EXPLAIN results for Append, Group, Agg, Unique (Tom) Add ALTER TABLE ... ADD FOREIGN KEY (Stephan Szabo) Allow SELECT .. FOR UPDATE in PL/pgSQL (Hiroshi) Enable backward sequential scan even after reaching EOF (Hiroshi) Add btree indexing of boolean values, >= and <= (Don Baccus) Print current line number when COPY FROM fails (Massimo) Recognize POSIX time zone e.g. "PST+8" and "GMT-8" (Thomas) Add DEC as synonym for DECIMAL (Thomas) Add SESSION_USER as SQL92 key word, same as CURRENT_USER (Thomas) Implement SQL92 column aliases (aka correlation names) (Thomas) Implement SQL92 join syntax (Thomas) Make INTERVAL reserved word allowed as a column identifier (Thomas) Implement REINDEX command (Hiroshi) Accept ALL in aggregate function SUM(ALL col) (Tom) Prevent GROUP BY from using column aliases (Tom) New psql \encoding option (Tatsuo) Allow PQrequestCancel() to terminate when in waiting-for-lock state (Hiroshi) Allow negation of a negative number in all cases Add ecpg descriptors (Christof, Michael) Allow CREATE VIEW v AS SELECT f1::char(8) FROM tbl Allow casts with length, like foo::char(8) New libpq functions PQsetClientEncoding(), PQclientEncoding() (Tatsuo) Add support for SJIS user defined characters (Tatsuo) Larger views/rules supported Make libpq's PQconndefaults() thread-safe (Tom) Disable // as comment to be ANSI conforming, should use -- (Tom) Allow column aliases on views CREATE VIEW name (collist) Fixes for views with subqueries (Tom) Allow UPDATE table SET fld = (SELECT ...) (Tom) SET command options no longer require quotes Update pgaccess to 0.98.6 New SET SEED command New pg_options.sample file New SET FSYNC command (Massimo) Allow pg_descriptions when creating tables Allow pg_descriptions when creating types, columns, and functions Allow psql \copy to allow delimiters (Peter E) Allow psql to print nulls as distinct from "" [null] (Peter E) Types ----Many array fixes (Tom) Allow bare column names to be subscripted as arrays (Tom) Improve type casting of int and float constants (Tom) Cleanups for int8 inputs, range checking, and type conversion (Tom) Fix for SELECT timespan('21:11:26'::time) (Tom) netmask('x.x.x.x/0') is 255.255.255.255 instead of 0.0.0.0 (Oleg Sharoiko) Add btree index on NUMERIC (Jan) Perl fix for large objects containing NUL characters (Douglas Thomson) ODBC fix for for large objects (free) Fix indexing of cidr data type Fix for Ethernet MAC addresses (macaddr type) comparisons Fix for date/time types when overflows happened in computations (Tom) Allow array on int8 (Peter E) Fix for rounding/overflow of NUMERIC type, like NUMERIC(4,4) (Tom) Allow NUMERIC arrays Fix bugs in NUMERIC ceil() and floor() functions (Tom) Make char_length()/octet_length including trailing blanks (Tom) Made abstime/reltime use int4 instead of time_t (Peter E) New lztext data type for compressed text fields
1099
Revise code to handle coercion of int and float constants (Tom) Start at new code to implement a BIT and BIT VARYING type (Adriaan Joubert) NUMERIC now accepts scientific notation (Tom) NUMERIC to int4 rounds (Tom) Convert float4/8 to NUMERIC properly (Tom) Allow type conversion with NUMERIC (Thomas) Make ISO date style (2000-02-16 09:33) the default (Thomas) Add NATIONAL CHAR [ VARYING ] (Thomas) Allow NUMERIC round and trunc to accept negative scales (Tom) New TIME WITH TIME ZONE type (Thomas) Add MAX()/MIN() on time type (Thomas) Add abs(), mod(), fac() for int8 (Thomas) Rename functions to round(), sqrt(), cbrt(), pow() for float8 (Thomas) Add transcendental math functions (e.g. sin(), acos()) for float8 (Thomas) Add exp() and ln() for NUMERIC type Rename NUMERIC power() to pow() (Thomas) Improved TRANSLATE() function (Edwin Ramirez, Tom) Allow X=-Y operators (Tom) Allow SELECT float8(COUNT(*))/(SELECT COUNT(*) FROM t) FROM t GROUP BY f1; (Tom)
Allow LOCALE to use indexes in regular expression searches (Tom) Allow creation of functional indexes to use default types Performance ----------Prevent exponential space consumption with many AND's and OR's (Tom) Collect attribute selectivity values for system columns (Tom) Reduce memory usage of aggregates (Tom) Fix for LIKE optimization to use indexes with multibyte encodings (Tom) Fix r-tree index optimizer selectivity (Thomas) Improve optimizer selectivity computations and functions (Tom) Optimize btree searching for cases where many equal keys exist (Tom) Enable fast LIKE index processing only if index present (Tom) Re-use free space on index pages with duplicates (Tom) Improve hash join processing (Tom) Prevent descending sort if result is already sorted(Hiroshi) Allow commuting of index scan query qualifications (Tom) Prefer index scans in cases where ORDER BY/GROUP BY is required (Tom) Allocate large memory requests in fix-sized chunks for performance (Tom) Fix vacuum's performance by reducing memory allocation requests (Tom) Implement constant-expression simplification (Bernard Frankpitt, Tom) Use secondary columns to be used to determine start of index scan (Hiroshi) Prevent quadruple use of disk space when doing internal sorting (Tom) Faster sorting by calling fewer functions (Tom) Create system indexes to match all system caches (Bruce, Hiroshi) Make system caches use system indexes (Bruce) Make all system indexes unique (Bruce) Improve pg_statistics management for VACUUM speed improvement (Tom) Flush backend cache less frequently (Tom, Hiroshi) COPY now reuses previous memory allocation, improving performance (Tom) Improve optimization cost estimation (Tom) Improve optimizer estimate of range queries x > lowbound AND x < highbound (Tom)
Use DNF instead of CNF where appropriate (Tom, Taral) Further cleanup for OR-of-AND WHERE-clauses (Tom) Make use of index in OR clauses (x = 1 AND y = 2) OR (x = 2 AND y = 4) (Tom) Smarter optimizer computations for random index page access (Tom) New SET variable to control optimizer costs (Tom) Optimizer queries based on LIMIT, OFFSET, and EXISTS qualifications (Tom) Reduce optimizer internal housekeeping of join paths for speedup (Tom) Major subquery speedup (Tom) Fewer fsync writes when fsync is not disabled (Tom) Improved LIKE optimizer estimates (Tom) Prevent fsync in SELECT-only queries (Vadim) Make index creation use psort code, because it is now faster (Tom)
1100
Allow creation of sort temp tables > 1 Gig Source Tree Changes ------------------Fix for linux PPC compile New generic expression-tree-walker subroutine (Tom) Change form() to varargform() to prevent portability problems Improved range checking for large integers on Alphas Clean up #include in /include directory (Bruce) Add scripts for checking includes (Bruce) Remove un-needed #include's from *.c files (Bruce) Change #include's to use <> and "" as appropriate (Bruce) Enable Windows compilation of libpq Alpha spinlock fix from Uncle GeorgeOverhaul of optimizer data structures (Tom) Fix to cygipc library (Yutaka Tanida) Allow pgsql to work on newer Cygwin snapshots (Dan) New catalog version number (Tom) Add Linux ARM Rename heap_replace to heap_update Update for QNX (Dr. Andreas Kardos) New platform-specific regression handling (Tom) Rename oid8 -> oidvector and int28 -> int2vector (Bruce) Included all yacc and lex files into the distribution (Peter E.) Remove lextest, no longer needed (Peter E) Fix for libpq and psql on Windows (Magnus) Internally change datetime and timespan into timestamp and interval (Thomas) Fix for plpgsql on BSD/OS Add SQL_ASCII test case to the regression test (Tatsuo) configure --with-mb now deprecated (Tatsuo) NT fixes NetBSD fixes (Johnny C. Lam ) Fixes for Alpha compiles New multibyte encodings
E.22. Release 6.5.3 Release date: 1999-10-13
This is basically a cleanup release for 6.5.2. We have added a new PgAccess that was missing in 6.5.2, and installed an NT-specific fix.
E.22.1. Migration to version 6.5.3 A dump/restore is not required for those running 6.5.*.
E.22.2. Changes Updated version of pgaccess 0.98 NT-specific patch Fix dumping rules on inherited tables
E.23. Release 6.5.2 Release date: 1999-09-15
This is basically a cleanup release for 6.5.1. We have fixed a variety of problems reported by 6.5.1 users.
E.23.1. Migration to version 6.5.2 A dump/restore is not required for those running 6.5.*.
1101
E.23.2. Changes subselect+CASE fixes(Tom) Add SHLIB_LINK setting for solaris_i386 and solaris_sparc ports(Daren Sefcik) Fixes for CASE in WHERE join clauses(Tom) Fix BTScan abort(Tom) Repair the check for redundant UNIQUE and PRIMARY KEY indexes(Thomas) Improve it so that it checks for multicolumn constraints(Thomas) Fix for Windows making problem with MB enabled(Hiroki Kataoka) Allow BSD yacc and bison to compile pl code(Bruce) Fix SET NAMES working int8 fixes(Thomas) Fix vacuum's memory consumption(Hiroshi,Tatsuo) Reduce the total memory consumption of vacuum(Tom) Fix for timestamp(datetime) Rule deparsing bugfixes(Tom) Fix quoting problems in mkMakefile.tcldefs.sh.in and mkMakefile.tkdefs.sh.in(Tom)
This is to re-use space on index pages freed by vacuum(Vadim) document -x for pg_dump(Bruce) Fix for unary operators in rule deparser(Tom) Comment out FileUnlink of excess segments during mdtruncate()(Tom) IRIX linking fix from Yu Cao >[email protected]< Repair logic error in LIKE: should not return LIKE_ABORT when reach end of pattern before end of text(Tom) Repair incorrect cleanup of heap memory allocation during transaction abort(Tom)
Updated version of pgaccess 0.98
E.24. Release 6.5.1 Release date: 1999-07-15
This is basically a cleanup release for 6.5. We have fixed a variety of problems reported by 6.5 users.
E.24.1. Migration to version 6.5.1 A dump/restore is not required for those running 6.5.
E.24.2. Changes Add NT README file Portability fixes for linux_ppc, IRIX, linux_alpha, OpenBSD, alpha Remove QUERY_LIMIT, use SELECT...LIMIT Fix for EXPLAIN on inheritance(Tom) Patch to allow vacuum on multisegment tables(Hiroshi) R-Tree optimizer selectivity fix(Tom) ACL file descriptor leak fix(Atsushi Ogawa) New expresssion subtree code(Tom) Avoid disk writes for read-only transactions(Vadim) Fix for removal of temp tables if last transaction was aborted(Bruce) Fix to prevent too large row from being created(Bruce) plpgsql fixes Allow port numbers 32k - 64k(Bruce) Add ^ precidence(Bruce) Rename sort files called pg_temp to pg_sorttemp(Bruce) Fix for microseconds in time values(Tom) Tutorial source cleanup New linux_m68k port Fix for sorting of NULL's in some cases(Tom) Shared library dependencies fixed (Tom) Fixed glitches affecting GROUP BY in subselects(Tom) Fix some compiler warnings (Tomoaki Nishiyama)
1102
Add Win1250 (Czech) support (Pavel Behal)
E.25. Release 6.5 Release date: 1999-06-09
This release marks a major step in the development team's mastery of the source code we inherited from Berkeley. You will see we are now easily adding major features, thanks to the increasing size and experience of our world-wide development team. Here is a brief summary of the more notable changes: Multiversion concurrency control(MVCC) This removes our old table-level locking, and replaces it with a locking system that is superior to most commercial database systems. In a traditional system, each row that is modified is locked until committed, preventing reads by other users. MVCC uses the natural multiversion nature of PostgreSQL to allow readers to continue reading consistent data during writer activity. Writers continue to use the compact pg_log transaction system. This is all performed without having to allocate a lock for every row like traditional database systems. So, basically, we no longer are restricted by simple table-level locking; we have something better than row-level locking. Hot backups from pg_dump pg_dump takes advantage of the new MVCC features to give a consistent database dump/backup while the database stays online and available for queries. Numeric data type We now have a true numeric data type, with user-specified precision. Temporary tables Temporary tables are guaranteed to have unique names within a database session, and are destroyed on session exit. New SQL features We now have CASE, INTERSECT, and EXCEPT statement support. We have new LIMIT/OFFSET, SET TRANSACTION ISOLATION LEVEL, SELECT ... FOR UPDATE, and an improved LOCK TABLE command. Speedups We continue to speed up PostgreSQL, thanks to the variety of talents within our team. We have sped up memory allocation, optimization, table joins, and row transfer routines. Ports We continue to expand our port list, this time including Windows NT/ix86 and NetBSD/arm32. Interfaces Most interfaces have new versions, and existing functionality has been improved. Documentation New and updated material is present throughout the documentation. New FAQs have been contributed for SGI and AIX platforms. The Tutorial has introductory information on SQL from Stefan Simkovics. For the User's Guide, there are reference pages covering the postmaster and more utility programs, and a new appendix contains details on date/time behavior. The Administrator's Guide has a new chapter on troubleshooting from Tom Lane. And the Programmer's Guide has a description of query processing, also from Stefan, and details on obtaining the PostgreSQL source tree via anonymous CVS and CVSup.
1103
E.25.1. Migration to version 6.5 A dump/restore using pg_dump is required for those wishing to migrate data from any previous release of PostgreSQL. pg_upgrade can not be used to upgrade to this release because the on-disk structure of the tables has changed compared to previous releases. The new Multiversion Concurrency Control (MVCC) features can give somewhat different behaviors in multiuser environments. Read and understand the following section to ensure that your existing applications will give you the behavior you need. E.25.1.1. Multiversion Concurrency Control Because readers in 6.5 don't lock data, regardless of transaction isolation level, data read by one transaction can be overwritten by another. In other words, if a row is returned by SELECT it doesn't mean that this row really exists at the time it is returned (i.e. sometime after the statement or transaction began) nor that the row is protected from being deleted or updated by concurrent transactions before the current transaction does a commit or rollback. To ensure the actual existence of a row and protect it against concurrent updates one must use SELECT FOR UPDATE or an appropriate LOCK TABLE statement. This should be taken into account when porting applications from previous releases of PostgreSQL and other environments. Keep the above in mind if you are using contrib/refint.* triggers for referential integrity. Additional techniques are required now. One way is to use LOCK parent_table IN SHARE ROW EXCLUSIVE MODE command if a transaction is going to update/delete a primary key and use LOCK parent_table IN SHARE MODE command if a transaction is going to update/insert a foreign key. Nota: Note that if you run a transaction in SERIALIZABLE mode then you must execute the LOCK commands above before execution of any DML statement (SELECT/INSERT/DELETE/UPDATE/FETCH/COPY_TO) in the transaction.
These inconveniences will disappear in the future when the ability to read dirty (uncommitted) data (regardless of isolation level) and true referential integrity will be implemented.
E.25.2. Changes Bug Fixes --------Fix text<->float8 and text<->float4 conversion functions(Thomas) Fix for creating tables with mixed-case constraints(Billy) Change exp()/pow() behavior to generate error on underflow/overflow(Jan) Fix bug in pg_dump -z Memory overrun cleanups(Tatsuo) Fix for lo_import crash(Tatsuo) Adjust handling of data type names to suppress double quotes(Thomas) Use type coercion for matching columns and DEFAULT(Thomas) Fix deadlock so it only checks once after one second of sleep(Bruce) Fixes for aggregates and PL/pgsql(Hiroshi) Fix for subquery crash(Vadim) Fix for libpq function PQfnumber and case-insensitive names(Bahman Rafatjoo) Fix for large object write-in-middle, no extra block, memory consumption(Tatsuo)
Fix for pg_dump -d or -D and quote special characters in INSERT Repair serious problems with dynahash(Tom) Fix INET/CIDR portability problems Fix problem with selectivity error in ALTER TABLE ADD COLUMN(Bruce) Fix executor so mergejoin of different column types works(Tom) Fix for Alpha OR selectivity bug Fix OR index selectivity problem(Bruce) Fix so \d shows proper length for char()/varchar()(Ryan) Fix tutorial code(Clark) Improve destroyuser checking(Oliver) Fix for Kerberos(Rodney McDuff) Fix for dropping database while dirty buffers(Bruce)
1104
Fix so sequence nextval() can be case-sensitive(Bruce) Fix !!= operator Drop buffers before destroying database files(Bruce) Fix case where executor evaluates functions twice(Tatsuo) Allow sequence nextval actions to be case-sensitive(Bruce) Fix optimizer indexing not working for negative numbers(Bruce) Fix for memory leak in executor with fjIsNull Fix for aggregate memory leaks(Erik Riedel) Allow user name containing a dash to grant privileges Cleanup of NULL in inet types Clean up system table bugs(Tom) Fix problems of PAGER and \? command(Masaaki Sakaida) Reduce default multisegment file size limit to 1GB(Peter) Fix for dumping of CREATE OPERATOR(Tom) Fix for backward scanning of cursors(Hiroshi Inoue) Fix for COPY FROM STDIN when using \i(Tom) Fix for subselect is compared inside an expression(Jan) Fix handling of error reporting while returning rows(Tom) Fix problems with reference to array types(Tom,Jan) Prevent UPDATE SET oid(Jan) Fix pg_dump so -t option can handle case-sensitive tablenames Fixes for GROUP BY in special cases(Tom, Jan) Fix for memory leak in failed queries(Tom) DEFAULT now supports mixed-case identifiers(Tom) Fix for multisegment uses of DROP/RENAME table, indexes(Ole Gjerde) Disable use of pg_dump with both -o and -d options(Bruce) Allow pg_dump to properly dump group privileges(Bruce) Fix GROUP BY in INSERT INTO table SELECT * FROM table2(Jan) Fix for computations in views(Jan) Fix for aggregates on array indexes(Tom) Fix for DEFAULT handles single quotes in value requiring too many quotes Fix security problem with non-super users importing/exporting large objects(Tom)
Rollback of transaction that creates table cleaned up properly(Tom) Fix to allow long table and column names to generate proper serial names(Tom) Enhancements -----------Add "vacuumdb" utility Speed up libpq by allocating memory better(Tom) EXPLAIN all indexes used(Tom) Implement CASE, COALESCE, NULLIF expression(Thomas) New pg_dump table output format(Constantin) Add string min()/max() functions(Thomas) Extend new type coercion techniques to aggregates(Thomas) New moddatetime contrib(Terry) Update to pgaccess 0.96(Constantin) Add routines for single-byte "char" type(Thomas) Improved substr() function(Thomas) Improved multibyte handling(Tatsuo) Multiversion concurrency control/MVCC(Vadim) New Serialized mode(Vadim) Fix for tables over 2gigs(Peter) New SET TRANSACTION ISOLATION LEVEL(Vadim) New LOCK TABLE IN ... MODE(Vadim) Update ODBC driver(Byron) New NUMERIC data type(Jan) New SELECT FOR UPDATE(Vadim) Handle "NaN" and "Infinity" for input values(Jan) Improved date/year handling(Thomas) Improved handling of backend connections(Magnus) New options ELOG_TIMESTAMPS and USE_SYSLOG options for log files(Massimo) New TCL_ARRAYS option(Massimo) New INTERSECT and EXCEPT(Stefan)
1105
New pg_index.indisprimary for primary key tracking(D'Arcy) New pg_dump option to allow dropping of tables before creation(Brook) Speedup of row output routines(Tom) New READ COMMITTED isolation level(Vadim) New TEMP tables/indexes(Bruce) Prevent sorting if result is already sorted(Jan) New memory allocation optimization(Jan) Allow psql to do \p\g(Bruce) Allow multiple rule actions(Jan) Added LIMIT/OFFSET functionality(Jan) Improve optimizer when joining a large number of tables(Bruce) New intro to SQL from S. Simkovics' Master's Thesis (Stefan, Thomas) New intro to backend processing from S. Simkovics' Master's Thesis (Stefan) Improved int8 support(Ryan Bradetich, Thomas, Tom) New routines to convert between int8 and text/varchar types(Thomas) New bushy plans, where meta-tables are joined(Bruce) Enable right-hand queries by default(Bruce) Allow reliable maximum number of backends to be set at configure time (--with-maxbackends and postmaster switch (-N backends))(Tom) GEQO default now 10 tables because of optimizer speedups(Tom) Allow NULL=Var for MS-SQL portability(Michael, Bruce) Modify contrib check_primary_key() so either "automatic" or "dependent"(Anand) Allow psql \d on a view show query(Ryan) Speedup for LIKE(Bruce) Ecpg fixes/features, see src/interfaces/ecpg/ChangeLog file(Michael) JDBC fixes/features, see src/interfaces/jdbc/CHANGELOG(Peter) Make % operator have precedence like /(Bruce) Add new postgres -O option to allow system table structure changes(Bruce) Update contrib/pginterface/findoidjoins script(Tom) Major speedup in vacuum of deleted rows with indexes(Vadim) Allow non-SQL functions to run different versions based on arguments(Tom) Add -E option that shows actual queries sent by \dt and friends(Masaaki Sakaida)
Add version number in start-up banners for psql(Masaaki Sakaida) New contrib/vacuumlo removes large objects not referenced(Peter) New initialization for table sizes so non-vacuumed tables perform better(Tom) Improve error messages when a connection is rejected(Tom) Support for arrays of char() and varchar() fields(Massimo) Overhaul of hash code to increase reliability and performance(Tom) Update to PyGreSQL 2.4(D'Arcy) Changed debug options so -d4 and -d5 produce different node displays(Jan) New pg_options: pretty_plan, pretty_parse, pretty_rewritten(Jan) Better optimization statistics for system table access(Tom) Better handling of non-default block sizes(Massimo) Improve GEQO optimizer memory consumption(Tom) UNION now suppports ORDER BY of columns not in target list(Jan) Major libpq++ improvements(Vince Vielhaber) pg_dump now uses -z(ACL's) as default(Bruce) backend cache, memory speedups(Tom) have pg_dump do everything in one snapshot transaction(Vadim) fix for large object memory leakage, fix for pg_dumping(Tom) INET type now respects netmask for comparisons Make VACUUM ANALYZE only use a readlock(Vadim) Allow VIEWs on UNIONS(Jan) pg_dump now can generate consistent snapshots on active databases(Vadim) Source Tree Changes ------------------Improve port matching(Tom) Portability fixes for SunOS Add Windows NT backend port and enable dynamic loading(Magnus and Daniel Horak)
New port to Cobalt Qube(Mips) running Linux(Tatsuo) Port to NetBSD/m68k(Mr. Mutsuki Nakajima) Port to NetBSD/sun3(Mr. Mutsuki Nakajima)
1106
Port to NetBSD/macppc(Toshimi Aoki) Fix for tcl/tk configuration(Vince) Removed CURRENT key word for rule queries(Jan) NT dynamic loading now works(Daniel Horak) Add ARM32 support(Andrew McMurry) Better support for HP-UX 11 and UnixWare Improve file handling to be more uniform, prevent file descriptor leak(Tom) New install commands for plpgsql(Jan)
E.26. Release 6.4.2 Release date: 1998-12-20
The 6.4.1 release was improperly packaged. This also has one additional bug fix.
E.26.1. Migration to version 6.4.2 A dump/restore is not required for those running 6.4.*.
E.26.2. Changes Fix for datetime constant problem on some platforms(Thomas)
E.27. Release 6.4.1 Release date: 1998-12-18
This is basically a cleanup release for 6.4. We have fixed a variety of problems reported by 6.4 users.
E.27.1. Migration to version 6.4.1 A dump/restore is not required for those running 6.4.
E.27.2. Changes Add pg_dump -N flag to force double quotes around identifiers. This is the default(Thomas) Fix for NOT in where clause causing crash(Bruce) EXPLAIN VERBOSE coredump fix(Vadim) Fix shared-library problems on Linux Fix test for table existence to allow mixed-case and whitespace in the table name(Thomas) Fix a couple of pg_dump bugs Configure matches template/.similar entries better(Tom) Change builtin function names from SPI_* to spi_* OR WHERE clause fix(Vadim) Fixes for mixed-case table names(Billy) contrib/linux/postgres.init.csh/sh fix(Thomas) libpq memory overrun fix SunOS fixes(Tom) Change exp() behavior to generate error on underflow(Thomas) pg_dump fixes for memory leak, inheritance constraints, layout change update pgaccess to 0.93 Fix prototype for 64-bit platforms Multibyte fixes(Tatsuo) New ecpg man page Fix memory overruns(Tatsuo) Fix for lo_import() crash(Bruce) Better search for install program(Tom) Timezone fixes(Tom) HP-UX fixes(Tom)
1107
Use implicit type coercion for matching DEFAULT values(Thomas) Add routines to help with single-byte (internal) character type(Thomas) Compilation of libpq for Windows fixes(Magnus) Upgrade to PyGreSQL 2.2(D'Arcy)
E.28. Release 6.4 Release date: 1998-10-30
There are many new features and improvements in this release. Thanks to our developers and maintainers, nearly every aspect of the system has received some attention since the previous release. Here is a brief, incomplete summary: •
Views and rules are now functional thanks to extensive new code in the rewrite rules system from Jan Wieck. He also wrote a chapter on it for the Programmer's Guide.
•
Jan also contributed a second procedural language, PL/pgSQL, to go with the original PL/pgTCL procedural language he contributed last release.
•
We have optional multiple-byte character set support from Tatsuo Ishii to complement our existing locale support.
•
Client/server communications has been cleaned up, with better support for asynchronous messages and interrupts thanks to Tom Lane.
•
The parser will now perform automatic type coercion to match arguments to available operators and functions, and to match columns and expressions with target columns. This uses a generic mechanism which supports the type extensibility features of PostgreSQL. There is a new chapter in the User's Guide which covers this topic.
•
Three new data types have been added. Two types, inet and cidr, support various forms of IP network, subnet, and machine addressing. There is now an 8-byte integer type available on some platforms. See the chapter on data types in the User's Guide for details. A fourth type, serial, is now supported by the parser as an amalgam of the int4 type, a sequence, and a unique index.
•
Several more SQL92-compatible syntax features have been added, including INSERT DEFAULT VALUES
•
The automatic configuration and installation system has received some attention, and should be more robust for more platforms than it has ever been.
E.28.1. Migration to version 6.4 A dump/restore using pg_dump or pg_dumpall is required for those wishing to migrate data from any previous release of PostgreSQL.
E.28.2. Changes Bug Fixes --------Fix for a tiny memory leak in PQsetdb/PQfinish(Bryan) Remove char2-16 data types, use char/varchar(Darren) Pqfn not handles a NOTICE message(Anders) Reduced busywaiting overhead for spinlocks with many backends (dg) Stuck spinlock detection (dg) Fix up "ISO-style" timespan decoding and encoding(Thomas) Fix problem with table drop after rollback of transaction(Vadim) Change error message and remove non-functional update message(Vadim) Fix for COPY array checking Fix for SELECT 1 UNION SELECT NULL Fix for buffer leaks in large object calls(Pascal) Change owner from oid to int4 type(Bruce) Fix a bug in the oracle compatibility functions btrim() ltrim() and rtrim() Fix for shared invalidation cache overflow(Massimo) Prevent file descriptor leaks in failed COPY's(Bruce)
1108
Fix memory leak in libpgtcl's pg_select(Constantin) Fix problems with username/passwords over 8 characters(Tom) Fix problems with handling of asynchronous NOTIFY in backend(Tom) Fix of many bad system table entries(Tom) Enhancements -----------Upgrade ecpg and ecpglib,see src/interfaces/ecpc/ChangeLog(Michael) Show the index used in an EXPLAIN(Zeugswetter) EXPLAIN invokes rule system and shows plan(s) for rewritten queries(Jan) Multibyte awareness of many data types and functions, via configure(Tatsuo) New configure --with-mb option(Tatsuo) New initdb --pgencoding option(Tatsuo) New createdb -E multibyte option(Tatsuo) Select version(); now returns PostgreSQL version(Jeroen) libpq now allows asynchronous clients(Tom) Allow cancel from client of backend query(Tom) psql now cancels query with Control-C(Tom) libpq users need not issue dummy queries to get NOTIFY messages(Tom) NOTIFY now sends sender's PID, so you can tell whether it was your own(Tom) PGresult struct now includes associated error message, if any(Tom) Define "tz_hour" and "tz_minute" arguments to date_part()(Thomas) Add routines to convert between varchar and bpchar(Thomas) Add routines to allow sizing of varchar and bpchar into target columns(Thomas) Add bit flags to support timezonehour and minute in data retrieval(Thomas) Allow more variations on valid floating point numbers (e.g. ".1", "1e6")(Thomas)
Fixes for unary minus parsing with leading spaces(Thomas) Implement TIMEZONE_HOUR, TIMEZONE_MINUTE per SQL92 specs(Thomas) Check for and properly ignore FOREIGN KEY column constraints(Thomas) Define USER as synonym for CURRENT_USER per SQL92 specs(Thomas) Enable HAVING clause but no fixes elsewhere yet. Make "char" type a synonym for "char(1)" (actually implemented as bpchar)(Thomas)
Save string type if specified for DEFAULT clause handling(Thomas) Coerce operations involving different data types(Thomas) Allow some index use for columns of different types(Thomas) Add capabilities for automatic type conversion(Thomas) Cleanups for large objects, so file is truncated on open(Peter) Readline cleanups(Tom) Allow psql \f \ to make spaces as delimiter(Bruce) Pass pg_attribute.atttypmod to the frontend for column field lengths(Tom,Bruce)
Msql compatibility library in /contrib(Aldrin) Remove the requirement that ORDER/GROUP BY clause identifiers be included in the target list(David) Convert columns to match columns in UNION clauses(Thomas) Remove fork()/exec() and only do fork()(Bruce) Jdbc cleanups(Peter) Show backend status on ps command line(only works on some platforms)(Bruce) Pg_hba.conf now has a sameuser option in the database field Make lo_unlink take oid param, not int4 New DISABLE_COMPLEX_MACRO for compilers that can't handle our macros(Bruce) Libpgtcl now handles NOTIFY as a Tcl event, need not send dummy queries(Tom) libpgtcl cleanups(Tom) Add -error option to libpgtcl's pg_result command(Tom) New locale patch, see docs/README/locale(Oleg) Fix for pg_dump so CONSTRAINT and CHECK syntax is correct(ccb) New contrib/lo code for large object orphan removal(Peter) New psql command "SET CLIENT_ENCODING TO 'encoding'" for multibytes feature, see /doc/README.mb(Tatsuo) contrib/noupdate code to revoke update permission on a column libpq can now be compiled on Windows(Magnus) Add PQsetdbLogin() in libpq New 8-byte integer type, checked by configure for OS support(Thomas) Better support for quoted table/column names(Thomas)
1109
Surround table and column names with double-quotes in pg_dump(Thomas) PQreset() now works with passwords(Tom) Handle case of GROUP BY target list column number out of range(David) Allow UNION in subselects Add auto-size to screen to \d? commands(Bruce) Use UNION to show all \d? results in one query(Bruce) Add \d? field search feature(Bruce) Pg_dump issues fewer \connect requests(Tom) Make pg_dump -z flag work better, document it in manual page(Tom) Add HAVING clause with full support for subselects and unions(Stephan) Full text indexing routines in contrib/fulltextindex(Maarten) Transaction ids now stored in shared memory(Vadim) New PGCLIENTENCODING when issuing COPY command(Tatsuo) Support for SQL92 syntax "SET NAMES"(Tatsuo) Support for LATIN2-5(Tatsuo) Add UNICODE regression test case(Tatsuo) Lock manager cleanup, new locking modes for LLL(Vadim) Allow index use with OR clauses(Bruce) Allows "SELECT NULL ORDER BY 1;" Explain VERBOSE prints the plan, and now pretty-prints the plan to the postmaster log file(Bruce) Add indexes display to \d command(Bruce) Allow GROUP BY on functions(David) New pg_class.relkind for large objects(Bruce) New way to send libpq NOTICE messages to a different location(Tom) New \w write command to psql(Bruce) New /contrib/findoidjoins scans oid columns to find join relationships(Bruce) Allow binary-compatible indexes to be considered when checking for valid Indexes for restriction clauses containing a constant(Thomas) New ISBN/ISSN code in /contrib/isbn_issn Allow NOT LIKE, IN, NOT IN, BETWEEN, and NOT BETWEEN constraint(Thomas) New rewrite system fixes many problems with rules and views(Jan) * * * * * * * * * * * * * * * *
Rules on relations work Event qualifications on insert/update/delete work New OLD variable to reference CURRENT, CURRENT will be remove in future Update rules can reference NEW and OLD in rule qualifications/actions Insert/update/delete rules on views work Multiple rule actions are now supported, surrounded by parentheses Regular users can create views/rules on tables they have RULE permits Rules and views inherit the privileges of the creator No rules at the column level No UPDATE NEW/OLD rules New pg_tables, pg_indexes, pg_rules and pg_views system views Only a single action on SELECT rules Total rewrite overhaul, perhaps for 6.5 handle subselects handle aggregates on views handle insert into select from view works
System indexes are now multikey(Bruce) Oidint2, oidint4, and oidname types are removed(Bruce) Use system cache for more system table lookups(Bruce) New backend programming language PL/pgSQL in backend/pl(Jan) New SERIAL data type, auto-creates sequence/index(Thomas) Enable assert checking without a recompile(Massimo) User lock enhancements(Massimo) New setval() command to set sequence value(Massimo) Auto-remove unix socket file on start-up if no postmaster running(Massimo) Conditional trace package(Massimo) New UNLISTEN command(Massimo) psql and libpq now compile under Windows using win32.mak(Magnus) Lo_read no longer stores trailing NULL(Bruce) Identifiers are now truncated to 31 characters internally(Bruce)
1110
Createuser options now availble on the command line Code for 64-bit integer supported added, configure tested, int8 type(Thomas) Prevent file descriptor leaf from failed COPY(Bruce) New pg_upgrade command(Bruce) Updated /contrib directories(Massimo) New CREATE TABLE DEFAULT VALUES statement available(Thomas) New INSERT INTO TABLE DEFAULT VALUES statement available(Thomas) New DECLARE and FETCH feature(Thomas) libpq's internal structures now not exported(Tom) Allow up to 8 key indexes(Bruce) Remove ARCHIVE key word, that is no longer used(Thomas) pg_dump -n flag to supress quotes around indentifiers disable system columns for views(Jan) new INET and CIDR types for network addresses(TomH, Paul) no more double quotes in psql output pg_dump now dumps views(Terry) new SET QUERY_LIMIT(Tatsuo,Jan) Source Tree Changes ------------------/contrib cleanup(Jun) Inline some small functions called for every row(Bruce) Alpha/linux fixes HP-UX cleanups(Tom) Multibyte regression tests(Soonmyung.) Remove --disabled options from configure Define PGDOC to use POSTGRESDIR by default Make regression optional Remove extra braces code to pgindent(Bruce) Add bsdi shared library support(Bruce) New --without-CXX support configure option(Brook) New FAQ_CVS Update backend flowchart in tools/backend(Bruce) Change atttypmod from int16 to int32(Bruce, Tom) Getrusage() fix for platforms that do not have it(Tom) Add PQconnectdb, PGUSER, PGPASSWORD to libpq man page NS32K platform fixes(Phil Nelson, John Buller) SCO 7/UnixWare 2.x fixes(Billy,others) Sparc/Solaris 2.5 fixes(Ryan) Pgbuiltin.3 is obsolete, move to doc files(Thomas) Even more documention(Thomas) Nextstep support(Jacek) Aix support(David) pginterface manual page(Bruce) shared libraries all have version numbers merged all OS-specific shared library defines into one file smarter TCL/TK configuration checking(Billy) smarter perl configuration(Brook) configure uses supplied install-sh if no install script found(Tom) new Makefile.shlib for shared library configuration(Tom)
E.29. Release 6.3.2 Release date: 1998-04-07
This is a bug-fix release for 6.3.x. Refer to the release notes for version 6.3 for a more complete summary of new features. Summary: •
Repairs automatic configuration support for some platforms, including Linux, from breakage inadvertently introduced in version 6.3.1.
•
Correctly handles function calls on the left side of BETWEEN and LIKE clauses.
1111
A dump/restore is NOT required for those running 6.3 or 6.3.1. A make distclean, make, and make install is all that is required. This last step should be performed while the postmaster is not running. You should re-link any custom applications that use PostgreSQL libraries. For upgrades from pre-6.3 installations, refer to the installation and migration instructions for version 6.3.
E.29.1. Changes Configure detection improvements for tcl/tk(Brook Milligan, Alvin) Manual page improvements(Bruce) BETWEEN and LIKE fix(Thomas) fix for psql \connect used by pg_dump(Oliver Elphick) New odbc driver pgaccess, version 0.86 qsort removed, now uses libc version, cleanups(Jeroen) fix for buffer over-runs detected(Maurice Gittens) fix for buffer overrun in libpgtcl(Randy Kunkee) fix for UNION with DISTINCT or ORDER BY(Bruce) gettimeofday configure check(Doug Winterburn) Fix "indexes not used" bug(Vadim) docs additions(Thomas) Fix for backend memory leak(Bruce) libreadline cleanup(Erwan MAS) Remove DISTDIR(Bruce) Makefile dependency cleanup(Jeroen van Vianen) ASSERT fixes(Bruce)
E.30. Release 6.3.1 Release date: 1998-03-23
Summary: •
Additional support for multibyte character sets.
•
Repair byte ordering for mixed-endian clients and servers.
•
Minor updates to allowed SQL syntax.
•
Improvements to the configuration autodetection for installation.
A dump/restore is NOT required for those running 6.3. A make distclean, make, and make install is all that is required. This last step should be performed while the postmaster is not running. You should re-link any custom applications that use PostgreSQL libraries. For upgrades from pre-6.3 installations, refer to the installation and migration instructions for version 6.3.
E.30.1. Changes ecpg cleanup/fixes, now version 1.1(Michael Meskes) pg_user cleanup(Bruce) large object fix for pg_dump and tclsh (alvin) LIKE fix for multiple adjacent underscores fix for redefining builtin functions(Thomas) ultrix4 cleanup upgrade to pg_access 0.83 updated CLUSTER manual page multibyte character set support, see doc/README.mb(Tatsuo) configure --with-pgport fix pg_ident fix big-endian fix for backend communications(Kataoka) SUBSTR() and substring() fix(Jan) several jdbc fixes(Peter) libpgtcl improvements, see libptcl/README(Randy Kunkee)
1112
Fix for "Datasize = 0" error(Vadim) Prevent \do from wrapping(Bruce) Remove duplicate Russian character set entries Sunos4 cleanup Allow optional TABLE key word in LOCK and SELECT INTO(Thomas) CREATE SEQUENCE options to allow a negative integer(Thomas) Add "PASSWORD" as an allowed column identifier(Thomas) Add checks for UNION target fields(Bruce) Fix Alpha port(Dwayne Bailey) Fix for text arrays containing quotes(Doug Gibson) Solaris compile fix(Albert Chin-A-Young) Better identify tcl and tk libs and includes(Bruce)
E.31. Release 6.3 Release date: 1998-03-01
There are many new features and improvements in this release. Here is a brief, incomplete summary: •
Many new SQL features, including full SQL92 subselect capability (everything is here but target-list subselects).
•
Support for client-side environment variables to specify time zone and date style.
•
Socket interface for client/server connection. This is the default now so you may need to start postmaster with the -i flag.
•
Better password authorization mechanisms. Default table privileges have changed.
•
Old-style time travel has been removed. Performance has been improved. Nota: Bruce Momjian wrote the following notes to introduce the new release.
There are some general 6.3 issues that I want to mention. These are only the big items that can not be described in one sentence. A review of the detailed changes list is still needed. First, we now have subselects. Now that we have them, I would like to mention that without subselects, SQL is a very limited language. Subselects are a major feature, and you should review your code for places where subselects provide a better solution for your queries. I think you will find that there are more uses for subselects than you may think. Vadim has put us on the big SQL map with subselects, and fully functional ones too. The only thing you can't do with subselects is to use them in the target list. Second, 6.3 uses Unix domain sockets rather than TCP/IP by default. To enable connections from other machines, you have to use the new postmaster -i option, and of course edit pg_hba.conf. Also, for this reason, the format of pg_hba.conf has changed. Third, char() fields will now allow faster access than varchar() or text. Specifically, the text and varchar() have a penalty for access to any columns after the first column of this type. char() used to also have this access penalty, but it no longer does. This may suggest that you redesign some of your tables, especially if you have short character columns that you have defined as varchar() or text. This and other changes make 6.3 even faster than earlier releases. We now have passwords definable independent of any Unix file. There are new SQL USER commands. See the Administrator's Guide for more information. There is a new table, pg_shadow, which is used to store user information and user passwords, and it by default only SELECT-able by the postgres super-user. pg_user is now a view of pg_shadow, and is SELECT-able by PUBLIC. You should keep using pg_user in your application without changes. User-created tables now no longer have SELECT privilege to PUBLIC by default. This was done because the ANSI standard requires it. You can of course GRANT any privileges you want after the table is created. System tables continue to be SELECT-able by PUBLIC. We also have real deadlock detection code. No more sixty-second timeouts. And the new locking code implements a FIFO better, so there should be less resource starvation during heavy use.
1113
Many complaints have been made about inadequate documentation in previous releases. Thomas has put much effort into many new manuals for this release. Check out the doc/ directory. For performance reasons, time travel is gone, but can be implemented using triggers (see pgsql/contrib/spi/README). Please check out the new \d command for types, operators, etc. Also, views
have their own privileges now, not based on the underlying tables, so privileges on them have to be set separately. Check /pgsql/interfaces for some new ways to talk to PostgreSQL. This is the first release that really required an explanation for existing users. In many ways, this was necessary because the new release removes many limitations, and the work-arounds people were using are no longer needed.
E.31.1. Migration to version 6.3 A dump/restore using pg_dump or pg_dumpall is required for those wishing to migrate data from any previous release of PostgreSQL.
E.31.2. Changes Bug Fixes --------Fix binary cursors broken by MOVE implementation(Vadim) Fix for tcl library crash(Jan) Fix for array handling, from Gerhard Hintermayer Fix acl error, and remove duplicate pqtrace(Bruce) Fix psql \e for empty file(Bruce) Fix for textcat on varchar() fields(Bruce) Fix for DBT Sendproc (Zeugswetter Andres) Fix vacuum analyze syntax problem(Bruce) Fix for international identifiers(Tatsuo) Fix aggregates on inherited tables(Bruce) Fix substr() for out-of-bounds data Fix for select 1=1 or 2=2, select 1=1 and 2=2, and select sum(2+2)(Bruce) Fix notty output to show status result. -q option still turns it off(Bruce) Fix for count(*), aggs with views and multiple tables and sum(3)(Bruce) Fix cluster(Bruce) Fix for PQtrace start/stop several times(Bruce) Fix a variety of locking problems like newer lock waiters getting lock before older waiters, and having readlock people not share locks if a writer is waiting for a lock, and waiting writers not getting priority over waiting readers(Bruce) Fix crashes in psql when executing queries from external files(James) Fix problem with multiple order by columns, with the first one having NULL values(Jeroen) Use correct hash table support functions for float8 and int4(Thomas) Re-enable JOIN= option in CREATE OPERATOR statement (Thomas) Change precedence for boolean operators to match expected behavior(Thomas) Generate elog(ERROR) on over-large integer(Bruce) Allow multiple-argument functions in constraint clauses(Thomas) Check boolean input literals for 'true','false','yes','no','1','0' and throw elog(ERROR) if unrecognized(Thomas) Major large objects fix Fix for GROUP BY showing duplicates(Vadim) Fix for index scans in MergeJion(Vadim) Enhancements -----------Subselects with EXISTS, IN, ALL, ANY key words (Vadim, Bruce, Thomas) New User Manual(Thomas, others) Speedup by inlining some frequently-called functions Real deadlock detection, no more timeouts(Bruce) Add SQL92 "constants" CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER(Thomas)
1114
Modify constraint syntax to be SQL92-compliant(Thomas) Implement SQL92 PRIMARY KEY and UNIQUE clauses using indexes(Thomas) Recognize SQL92 syntax for FOREIGN KEY. Throw elog notice(Thomas) Allow NOT NULL UNIQUE constraint clause (each allowed separately before)(Thomas) Allow PostgreSQL-style casting ("::") of non-constants(Thomas) Add support for SQL3 TRUE and FALSE boolean constants(Thomas) Support SQL92 syntax for IS TRUE/IS FALSE/IS NOT TRUE/IS NOT FALSE(Thomas) Allow shorter strings for boolean literals (e.g. "t", "tr", "tru")(Thomas) Allow SQL92 delimited identifiers(Thomas) Implement SQL92 binary and hexadecimal string decoding (b'10' and x'1F')(Thomas) Support SQL92 syntax for type coercion of literal strings (e.g. "DATETIME 'now'")(Thomas) Add conversions for int2, int4, and OID types to and from text(Thomas) Use shared lock when building indexes(Vadim) Free memory allocated for an user query inside transaction block after this query is done, was turned off in <= 6.2.1(Vadim) New SQL statement CREATE PROCEDURAL LANGUAGE(Jan) New PostgreSQL Procedural Language (PL) backend interface(Jan) Rename pg_dump -H option to -h(Bruce) Add Java support for passwords, European dates(Peter) Use indexes for LIKE and ~, !~ operations(Bruce) Add hash functions for datetime and timespan(Thomas) Time Travel removed(Vadim, Bruce) Add paging for \d and \z, and fix \i(Bruce) Add Unix domain socket support to backend and to frontend library(Goran) Implement CREATE DATABASE/WITH LOCATION and initlocation utility(Thomas) Allow more SQL92 and/or PostgreSQL reserved words as column identifiers(Thomas) Augment support for SQL92 SET TIME ZONE...(Thomas) SET/SHOW/RESET TIME ZONE uses TZ backend environment variable(Thomas) Implement SET keyword = DEFAULT and SET TIME ZONE DEFAULT(Thomas) Enable SET TIME ZONE using TZ environment variable(Thomas) Add PGDATESTYLE environment variable to frontend and backend initialization(Thomas) Add PGTZ, PGCOSTHEAP, PGCOSTINDEX, PGRPLANS, PGGEQO frontend library initialization environment variables(Thomas) Regression tests time zone automatically set with "setenv PGTZ PST8PDT"(Thomas) Add pg_description table for info on tables, columns, operators, types, and aggregates(Bruce) Increase 16 char limit on system table/index names to 32 characters(Bruce) Rename system indexes(Bruce) Add 'GERMAN' option to SET DATESTYLE(Thomas) Define an "ISO-style" timespan output format with "hh:mm:ss" fields(Thomas) Allow fractional values for delta times (e.g. '2.5 days')(Thomas) Validate numeric input more carefully for delta times(Thomas) Implement day of year as possible input to date_part()(Thomas) Define timespan_finite() and text_timespan() functions(Thomas) Remove archive stuff(Bruce) Allow for a pg_password authentication database that is separate from the system password file(Todd) Dump ACLs, GRANT, REVOKE privileges(Matt) Define text, varchar, and bpchar string length functions(Thomas) Fix Query handling for inheritance, and cost computations(Bruce) Implement CREATE TABLE/AS SELECT (alternative to SELECT/INTO)(Thomas) Allow NOT, IS NULL, IS NOT NULL in constraints(Thomas) Implement UNIONs for SELECT(Bruce) Add UNION, GROUP, DISTINCT to INSERT(Bruce) varchar() stores only necessary bytes on disk(Bruce) Fix for BLOBs(Peter) Mega-Patch for JDBC...see README_6.3 for list of changes(Peter) Remove unused "option" from PQconnectdb() New LOCK command and lock manual page describing deadlocks(Bruce) Add new psql \da, \dd, \df, \do, \dS, and \dT commands(Bruce) Enhance psql \z to show sequences(Bruce)
1115
Show NOT NULL and DEFAULT in psql \d table(Bruce) New psql .psqlrc file start-up(Andrew) Modify sample start-up script in contrib/linux to show syslog(Thomas) New types for IP and MAC addresses in contrib/ip_and_mac(TomH) Unix system time conversions with date/time types in contrib/unixdate(Thomas) Update of contrib stuff(Massimo) Add Unix socket support to DBD::Pg(Goran) New python interface (PyGreSQL 2.0)(D'Arcy) New frontend/backend protocol has a version number, network byte order(Phil) Security features in pg_hba.conf enhanced and documented, many cleanups(Phil) CHAR() now faster access than VARCHAR() or TEXT ecpg embedded SQL preprocessor Reduce system column overhead(Vadmin) Remove pg_time table(Vadim) Add pg_type attribute to identify types that need length (bpchar, varchar) Add report of offending line when COPY command fails Allow VIEW privileges to be set separately from the underlying tables. For security, use GRANT/REVOKE on views as appropriate(Jan) Tables now have no default GRANT SELECT TO PUBLIC. You must explicitly grant such privileges. Clean up tutorial examples(Darren) Source Tree Changes ------------------Add new html development tools, and flow chart in /tools/backend Fix for SCO compiles Stratus computer port Robert Gillies Added support for shlib for BSD44_derived & i386_solaris Make configure more automated(Brook) Add script to check regression test results Break parser functions into smaller files, group together(Bruce) Rename heap_create to heap_create_and_catalog, rename heap_creatr to heap_create()(Bruce) Sparc/Linux patch for locking(TomS) Remove PORTNAME and reorganize port-specific stuff(Marc) Add optimizer README file(Bruce) Remove some recursion in optimizer and clean up some code there(Bruce) Fix for NetBSD locking(Henry) Fix for libptcl make(Tatsuo) AIX patch(Darren) Change IS TRUE, IS FALSE, ... to expressions using "=" rather than function calls to istrue() or isfalse() to allow optimization(Thomas) Various fixes NetBSD/Sparc related(TomH) Alpha linux locking(Travis,Ryan) Change elog(WARN) to elog(ERROR)(Bruce) FAQ for FreeBSD(Marc) Bring in the PostODBC source tree as part of our standard distribution(Marc) A minor patch for HP/UX 10 vs 9(Stan) New pg_attribute.atttypmod for type-specific info like varchar length(Bruce) UnixWare patches(Billy) New i386 'lock' for spinlock asm(Billy) Support for multiplexed backends is removed Start an OpenBSD port Start an AUX port Start a Cygnus port Add string functions to regression suite(Thomas) Expand a few function names formerly truncated to 16 characters(Thomas) Remove un-needed malloc() calls and replace with palloc()(Bruce)
E.32. Release 6.2.1 Release date: 1997-10-17
1116
6.2.1 is a bug-fix and usability release on 6.2. Summary: •
Allow strings to span lines, per SQL92.
•
Include example trigger function for inserting user names on table updates.
This is a minor bug-fix release on 6.2. For upgrades from pre-6.2 systems, a full dump/reload is required. Refer to the 6.2 release notes for instructions.
E.32.1. Migration from version 6.2 to version 6.2.1 This is a minor bug-fix release. A dump/reload is not required from version 6.2, but is required from any release prior to 6.2. In upgrading from version 6.2, if you choose to dump/reload you will find that avg(money) is now calculated correctly. All other bug fixes take effect upon updating the executables. Another way to avoid dump/reload is to use the following SQL command from psql to update the existing system table: update pg_aggregate set aggfinalfn = 'cash_div_flt8' where aggname = 'avg' and aggbasetype = 790;
This will need to be done to every existing database, including template1.
E.32.2. Changes Allow TIME and TYPE column names(Thomas) Allow larger range of true/false as boolean values(Thomas) Support output of "now" and "current"(Thomas) Handle DEFAULT with INSERT of NULL properly(Vadim) Fix for relation reference counts problem in buffer manager(Vadim) Allow strings to span lines, like ANSI(Thomas) Fix for backward cursor with ORDER BY(Vadim) Fix avg(cash) computation(Thomas) Fix for specifying a column twice in ORDER/GROUP BY(Vadim) Documented new libpq function to return affected rows, PQcmdTuples(Bruce) Trigger function for inserting user names for INSERT/UPDATE(Brook Milligan)
E.33. Release 6.2 Release date: 1997-10-02
A dump/restore is required for those wishing to migrate data from previous releases of PostgreSQL.
E.33.1. Migration from version 6.1 to version 6.2 This migration requires a complete dump of the 6.1 database and a restore of the database in 6.2. Note that the pg_dump and pg_dumpall utility from 6.2 should be used to dump the 6.1 database.
E.33.2. Migration from version 1.x to version 6.2 Those migrating from earlier 1.* releases should first upgrade to 1.09 because the COPY output format was improved from the 1.02 release.
E.33.3. Changes Bug Fixes --------Fix problems with pg_dump for inheritance, sequences, archive tables(Bruce) Fix compile errors on overflow due to shifts, unsigned, and bad prototypes from Solaris(Diab Jerius)
1117
Fix bugs in geometric line arithmetic (bad intersection calculations)(Thomas) Check for geometric intersections at endpoints to avoid rounding ugliness(Thomas) Catch non-functional delete attempts(Vadim) Change time function names to be more consistent(Michael Reifenberg) Check for zero divides(Michael Reifenberg) Fix very old bug which made rows changed/inserted by a command visible to the command itself (so we had multiple update of updated rows, etc.)(Vadim) Fix for SELECT null, 'fail' FROM pg_am (Patrick) SELECT NULL as EMPTY_FIELD now allowed(Patrick) Remove un-needed signal stuff from contrib/pginterface Fix OR (where x != 1 or x isnull didn't return rows with x NULL) (Vadim) Fix time_cmp function (Vadim) Fix handling of functions with non-attribute first argument in WHERE clauses (Vadim) Fix GROUP BY when order of entries is different from order in target list (Vadim) Fix pg_dump for aggregates without sfunc1 (Vadim) Enhancements -----------Default genetic optimizer GEQO parameter is now 8(Bruce) Allow use parameters in target list having aggregates in functions(Vadim) Added JDBC driver as an interface(Adrian & Peter) pg_password utility Return number of rows inserted/affected by INSERT/UPDATE/DELETE etc.(Vadim) Triggers implemented with CREATE TRIGGER (SQL3)(Vadim) SPI (Server Programming Interface) allows execution of queries inside C-functions (Vadim) NOT NULL implemented (SQL92)(Robson Paniago de Miranda) Include reserved words for string handling, outer joins, and unions(Thomas) Implement extended comments ("/* ... */") using exclusive states(Thomas) Add "//" single-line comments(Bruce) Remove some restrictions on characters in operator names(Thomas) DEFAULT and CONSTRAINT for tables implemented (SQL92)(Vadim & Thomas) Add text concatenation operator and function (SQL92)(Thomas) Support WITH TIME ZONE syntax (SQL92)(Thomas) Support INTERVAL unit TO unit syntax (SQL92)(Thomas) Define types DOUBLE PRECISION, INTERVAL, CHARACTER, and CHARACTER VARYING (SQL92)(Thomas) Define type FLOAT(p) and rudimentary DECIMAL(p,s), NUMERIC(p,s) (SQL92)(Thomas) Define EXTRACT(), POSITION(), SUBSTRING(), and TRIM() (SQL92)(Thomas) Define CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP (SQL92)(Thomas) Add syntax and warnings for UNION, HAVING, INNER and OUTER JOIN (SQL92)(Thomas) Add more reserved words, mostly for SQL92 compliance(Thomas) Allow hh:mm:ss time entry for timespan/reltime types(Thomas) Add center() routines for lseg, path, polygon(Thomas) Add distance() routines for circle-polygon, polygon-polygon(Thomas) Check explicitly for points and polygons contained within polygons using an axis-crossing algorithm(Thomas) Add routine to convert circle-box(Thomas) Merge conflicting operators for different geometric data types(Thomas) Replace distance operator "<===>" with "<->"(Thomas) Replace "above" operator "!^" with ">^" and "below" operator "!|" with "<^"(Thomas) Add routines for text trimming on both ends, substring, and string position(Thomas) Added conversion routines circle(box) and poly(circle)(Thomas) Allow internal sorts to be stored in memory rather than in files(Bruce & Vadim) Allow functions and operators on internally-identical types to succeed(Bruce) Speed up backend start-up after profiling analysis(Bruce) Inline frequently called functions for performance(Bruce) Reduce open() calls(Bruce) psql: Add PAGER for \h and \?,\C fix Fix for psql pager when no tty(Bruce)
1118
New entab utility(Bruce) General trigger functions for referential integrity (Vadim) General trigger functions for time travel (Vadim) General trigger functions for AUTOINCREMENT/IDENTITY feature (Vadim) MOVE implementation (Vadim) Source Tree Changes ------------------HP-UX 10 patches (Vladimir Turin) Added SCO support, (Daniel Harris) MkLinux patches (Tatsuo Ishii) Change geometric box terminology from "length" to "width"(Thomas) Deprecate temporary unstored slope fields in geometric code(Thomas) Remove restart instructions from INSTALL(Bruce) Look in /usr/ucb first for install(Bruce) Fix c++ copy example code(Thomas) Add -o to psql manual page(Bruce) Prevent relname unallocated string length from being copied into database(Bruce) Cleanup for NAMEDATALEN use(Bruce) Fix pg_proc names over 15 chars in output(Bruce) Add strNcpy() function(Bruce) remove some (void) casts that are unnecessary(Bruce) new interfaces directory(Marc) Replace fopen() calls with calls to fd.c functions(Bruce) Make functions static where possible(Bruce) enclose unused functions in #ifdef NOT_USED(Bruce) Remove call to difftime() in timestamp support to fix SunOS(Bruce & Thomas) Changes for Digital Unix Portability fix for pg_dumpall(Bruce) Rename pg_attribute.attnvals to attdispersion(Bruce) "intro/unix" manual page now "pgintro"(Bruce) "built-in" manual page now "pgbuiltin"(Bruce) "drop" manual page now "drop_table"(Bruce) Add "create_trigger", "drop_trigger" manual pages(Thomas) Add constraints regression test(Vadim & Thomas) Add comments syntax regression test(Thomas) Add PGINDENT and support program(Bruce) Massive commit to run PGINDENT on all *.c and *.h files(Bruce) Files moved to /src/tools directory(Bruce) SPI and Trigger programming guides (Vadim & D'Arcy)
E.34. Release 6.1.1 Release date: 1997-07-22
E.34.1. Migration from version 6.1 to version 6.1.1 This is a minor bug-fix release. A dump/reload is not required from version 6.1, but is required from any release prior to 6.1. Refer to the release notes for 6.1 for more details.
E.34.2. Changes fix for SET with options (Thomas) allow pg_dump/pg_dumpall to preserve ownership of all tables/objects(Bruce) new psql \connect option allows changing usernames without changing databases fix for initdb --debug option(Yoshihiko Ichikawa)) lextest cleanup(Bruce) hash fixes(Vadim) fix date/time month boundary arithmetic(Thomas) fix timezone daylight handling for some ports(Thomas, Bruce, Tatsuo) timestamp overhauled to use standard functions(Thomas) other code cleanup in date/time routines(Thomas)
1119
psql's \d now case-insensitive(Bruce) psql's backslash commands can now have trailing semicolon(Bruce) fix memory leak in psql when using \g(Bruce) major fix for endian handling of communication to server(Thomas, Tatsuo) Fix for Solaris assembler and include files(Yoshihiko Ichikawa) allow underscores in usernames(Bruce) pg_dumpall now returns proper status, portability fix(Bruce)
E.35. Release 6.1 Release date: 1997-06-08
The regression tests have been adapted and extensively modified for the 6.1 release of PostgreSQL. Three new data types (datetime, timespan, and circle) have been added to the native set of PostgreSQL types. Points, boxes, paths, and polygons have had their output formats made consistent across the data types. The polygon output in misc.out has only been spot-checked for correctness relative to the original regression output. PostgreSQL 6.1 introduces a new, alternate optimizer which uses genetic algorithms. These algorithms introduce a random behavior in the ordering of query results when the query contains multiple qualifiers or multiple tables (giving the optimizer a choice on order of evaluation). Several regression tests have been modified to explicitly order the results, and hence are insensitive to optimizer choices. A few regression tests are for data types which are inherently unordered (e.g. points and time intervals) and tests involving those types are explicitly bracketed with set geqo to 'off' and reset geqo. The interpretation of array specifiers (the curly braces around atomic values) appears to have changed sometime after the original regression tests were generated. The current ./expected/*.out files reflect this new interpretation, which may not be correct! The float8 regression test fails on at least some platforms. This is due to differences in implementations of pow() and exp() and the signaling mechanisms used for overflow and underflow conditions.
The “random” results in the random test should cause the “random” test to be “failed”, since the regression tests are evaluated using a simple diff. However, “random” does not seem to produce random results on my test machine (Linux/gcc/i686).
E.35.1. Migration to version 6.1 This migration requires a complete dump of the 6.0 database and a restore of the database in 6.1. Those migrating from earlier 1.* releases should first upgrade to 1.09 because the COPY output format was improved from the 1.02 release.
E.35.2. Changes Bug Fixes --------packet length checking in library routines lock manager priority patch check for under/over flow of float8(Bruce) multitable join fix(Vadim) SIGPIPE crash fix(Darren) large object fixes(Sven) allow btree indexes to handle NULLs(Vadim) timezone fixes(D'Arcy) select SUM(x) can return NULL on no rows(Thomas) internal optimizer, executor bug fixes(Vadim) fix problem where inner loop in < or <= has no rows(Vadim) prevent re-commuting join index clauses(Vadim) fix join clauses for multiple tables(Vadim) fix hash, hashjoin for arrays(Vadim) fix btree for abstime type(Vadim)
1120
large object fixes(Raymond) fix buffer leak in hash indexes (Vadim) fix rtree for use in inner scan (Vadim) fix gist for use in inner scan, cleanups (Vadim, Andrea) avoid unnecessary local buffers allocation (Vadim, Massimo) fix local buffers leak in transaction aborts (Vadim) fix file manager memmory leaks, cleanups (Vadim, Massimo) fix storage manager memmory leaks (Vadim) fix btree duplicates handling (Vadim) fix deleted rows reincarnation caused by vacuum (Vadim) fix SELECT varchar()/char() INTO TABLE made zero-length fields(Bruce) many psql, pg_dump, and libpq memory leaks fixed using Purify (Igor) Enhancements -----------attribute optimization statistics(Bruce) much faster new btree bulk load code(Paul) BTREE UNIQUE added to bulk load code(Vadim) new lock debug code(Massimo) massive changes to libpg++(Leo) new GEQO optimizer speeds table multitable optimization(Martin) new WARN message for non-unique insert into unique key(Marc) update x=-3, no spaces, now valid(Bruce) remove case-sensitive identifier handling(Bruce,Thomas,Dan) debug backend now pretty-prints tree(Darren) new Oracle character functions(Edmund) new plaintext password functions(Dan) no such class or insufficient privilege changed to distinct messages(Dan) new ANSI timestamp function(Dan) new ANSI Time and Date types (Thomas) move large chunks of data in backend(Martin) multicolumn btree indexes(Vadim) new SET var TO value command(Martin) update transaction status on reads(Dan) new locale settings for character types(Oleg) new SEQUENCE serial number generator(Vadim) GROUP BY function now possible(Vadim) re-organize regression test(Thomas,Marc) new optimizer operation weights(Vadim) new psql \z grant/permit option(Marc) new MONEY data type(D'Arcy,Thomas) tcp socket communication speed improved(Vadim) new VACUUM option for attribute statistics, and for certain columns (Vadim) many geometric type improvements(Thomas,Keith) additional regression tests(Thomas) new datestyle variable(Thomas,Vadim,Martin) more comparison operators for sorting types(Thomas) new conversion functions(Thomas) new more compact btree format(Vadim) allow pg_dumpall to preserve database ownership(Bruce) new SET GEQO=# and R_PLANS variable(Vadim) old (!GEQO) optimizer can use right-sided plans (Vadim) typechecking improvement in SQL parser(Bruce) new SET, SHOW, RESET commands(Thomas,Vadim) new \connect database USER option new destroydb -i option (Igor) new \dt and \di psql commands (Darren) SELECT "\n" now escapes newline (A. Duursma) new geometry conversion functions from old format (Thomas) Source tree changes ------------------new configuration script(Marc) readline configuration option added(Marc)
1121
OS-specific configuration options removed(Marc) new OS-specific template files(Marc) no more need to edit Makefile.global(Marc) re-arrange include files(Marc) nextstep patches (Gregor Hoffleit) removed Windows-specific code(Bruce) removed postmaster -e option, now only postgres -e option (Bruce) merge duplicate library code in front/backends(Martin) now works with eBones, international Kerberos(Jun) more shared library support c++ include file cleanup(Bruce) warn about buggy flex(Bruce) DG/UX, Ultrix, IRIX, AIX portability fixes
E.36. Release 6.0 Release date: 1997-01-29
A dump/restore is required for those wishing to migrate data from previous releases of PostgreSQL.
E.36.1. Migration from version 1.09 to version 6.0 This migration requires a complete dump of the 1.09 database and a restore of the database in 6.0.
E.36.2. Migration from pre-1.09 to version 6.0 Those migrating from earlier 1.* releases should first upgrade to 1.09 because the COPY output format was improved from the 1.02 release.
E.36.3. Changes Bug Fixes --------ALTER TABLE bug - running postgress process needs to re-read table definition Allow vacuum to be run on one table or entire database(Bruce) Array fixes Fix array over-runs of memory writes(Kurt) Fix elusive btree range/non-range bug(Dan) Fix for hash indexes on some types like time and date Fix for pg_log size explosion Fix permissions on lo_export()(Bruce) Fix unitialized reads of memory(Kurt) Fixed ALTER TABLE ... char(3) bug(Bruce) Fixed a few small memory leaks Fixed EXPLAIN handling of options and changed full_path option name Fixed output of group acl privileges Memory leaks (hunt and destroy with tools like Purify(Kurt) Minor improvements to rules system NOTIFY fixes New asserts for run-checking Overhauled parser/analyze code to properly report errors and increase speed Pg_dump -d now handles NULL's properly(Bruce) Prevent SELECT NULL from crashing server (Bruce) Properly report errors when INSERT ... SELECT columns did not match Properly report errors when insert column names were not correct psql \g filename now works(Bruce) psql fixed problem with multiple statements on one line with multiple outputs Removed duplicate system OIDs SELECT * INTO TABLE . GROUP/ORDER BY gives unlink error if table exists(Bruce) Several fixes for queries that crashed the backend Starting quote in insert string errors(Bruce) Submitting an empty query now returns empty status, not just " " query(Bruce)
1122
Enhancements -----------Add EXPLAIN manual page(Bruce) Add UNIQUE index capability(Dan) Add hostname/user level access control rather than just hostname and user Add synonym of != for <>(Bruce) Allow "select oid,* from table" Allow BY,ORDER BY to specify columns by number, or by non-alias table.column(Bruce) Allow COPY from the frontend(Bryan) Allow GROUP BY to use alias column name(Bruce) Allow actual compression, not just reuse on the same page(Vadim) Allow installation-configuration option to auto-add all local users(Bryan) Allow libpq to distinguish between text value '' and null(Bruce) Allow non-postgres users with createdb privs to destroydb's Allow restriction on who can create C functions(Bryan) Allow restriction on who can do backend COPY(Bryan) Can shrink tables, pg_time and pg_log(Vadim & Erich) Change debug level 2 to print queries only, changed debug heading layout(Bruce) Change default decimal constant representation from float4 to float8(Bruce) European date format now set when postmaster is started Execute lowercase function names if not found with exact case Fixes for aggregate/GROUP processing, allow 'select sum(func(x),sum(x+y) from z' Gist now included in the distrubution(Marc) Idend authentication of local users(Bryan) Implement BETWEEN qualifier(Bruce) Implement IN qualifier(Bruce) libpq has PQgetisnull()(Bruce) libpq++ improvements New options to initdb(Bryan) Pg_dump allow dump of OIDs(Bruce) Pg_dump create indexes after tables are loaded for speed(Bruce) Pg_dumpall dumps all databases, and the user table Pginterface additions for NULL values(Bruce) Prevent postmaster from being run as root psql \h and \? is now readable(Bruce) psql allow backslashed, semicolons anywhere on the line(Bruce) psql changed command prompt for lines in query or in quotes(Bruce) psql char(3) now displays as (bp)char in \d output(Bruce) psql return code now more accurate(Bryan?) psql updated help syntax(Bruce) Re-visit and fix vacuum(Vadim) Reduce size of regression diffs, remove timezone name difference(Bruce) Remove compile-time parameters to enable binary distributions(Bryan) Reverse meaning of HBA masks(Bryan) Secure Authentication of local users(Bryan) Speed up vacuum(Vadim) Vacuum now had VERBOSE option(Bruce) Source tree changes ------------------All functions now have prototypes that are compared against the calls Allow asserts to be disabled easly from Makefile.global(Bruce) Change oid constants used in code to #define names Decoupled sparc and solaris defines(Kurt) Gcc -Wall compiles cleanly with warnings only from unfixable constructs Major include file reorganization/reduction(Marc) Make now stops on compile failure(Bryan) Makefile restructuring(Bryan, Marc) Merge bsdi_2_1 to bsdi(Bruce) Monitor program removed Name change from Postgres95 to PostgreSQL New config.h file(Marc, Bryan) PG_VERSION now set to 6.0 and used by postmaster
1123
Portability additions, including Ultrix, DG/UX, AIX, and Solaris Reduced the number of #define's, centeralized #define's Remove duplicate OIDS in system tables(Dan) Remove duplicate system catalog info or report mismatches(Dan) Removed many os-specific #define's Restructured object file generation/location(Bryan, Marc) Restructured port-specific file locations(Bryan, Marc) Unused/uninialized variables corrected
E.37. Release 1.09 Release date: 1996-11-04
Sorry, we didn't keep track of changes from 1.02 to 1.09. Some of the changes listed in 6.0 were actually included in the 1.02.1 to 1.09 releases.
E.38. Release 1.02 Release date: 1996-08-01
E.38.1. Migration from version 1.02 to version 1.02.1 Here is a new migration file for 1.02.1. It includes the 'copy' change and a script to convert old ASCII files. Nota: The following notes are for the benefit of users who want to migrate databases from Postgres95 1.01 and 1.02 to Postgres95 1.02.1. If you are starting afresh with Postgres95 1.02.1 and do not need to migrate old databases, you do not need to read any further.
In order to upgrade older Postgres95 version 1.01 or 1.02 databases to version 1.02.1, the following steps are required: 1.
Start up a new 1.02.1 postmaster
2.
Add the new built-in functions and operators of 1.02.1 to 1.01 or 1.02 databases. This is done by running the new 1.02.1 server against your own 1.01 or 1.02 database and applying the queries attached at the end of the file. This can be done easily through psql. If your 1.01 or 1.02 database is named testdb and you have cut the commands from the end of this file and saved them in addfunc.sql: % psql testdb -f addfunc.sql
Those upgrading 1.02 databases will get a warning when executing the last two statements in the file because they are already present in 1.02. This is not a cause for concern.
E.38.2. Dump/Reload Procedure If you are trying to reload a pg_dump or text-mode, copy tablename to stdout generated with a previous version, you will need to run the attached sed script on the ASCII file before loading it into the database. The old format used '.' as end-of-data, while '\.' is now the end-of-data marker. Also, empty strings are now loaded in as '' rather than NULL. See the copy manual page for full details. sed 's/^\.$/\\./g'out_file
If you are loading an older binary copy or non-stdout copy, there is no end-of-data character, and hence no conversion necessary. -- following lines added by agc to reflect the case-insensitive -- regexp searching for varchar (in 1.02), and bpchar (in 1.02.1) create operator ~* (leftarg = bpchar, rightarg = text, procedure = texticregexeq); create operator !~* (leftarg = bpchar, rightarg = text, procedure = texticregexne); create operator ~* (leftarg = varchar, rightarg = text, procedure = texticregexeq); create operator !~* (leftarg = varchar, rightarg = text, procedure = texticregexne);
1124
E.38.3. Changes Source code maintenance and development * worldwide team of volunteers * the source tree now in CVS at ftp.ki.net Enhancements * psql (and underlying libpq library) now has many more options for formatting output, including HTML * pg_dump now output the schema and/or the data, with many fixes to enhance completeness. * psql used in place of monitor in administration shell scripts. monitor to be deprecated in next release. * date/time functions enhanced * NULL insert/update/comparison fixed/enhanced * TCL/TK lib and shell fixed to work with both tck7.4/tk4.0 and tcl7.5/tk4.1 Bug Fixes (almost too numerous to mention) * indexes * storage management * check for NULL pointer before dereferencing * Makefile fixes New Ports * added SolarisX86 port * added BSD/OS 2.1 port * added DG/UX port
E.39. Release 1.01 Release date: 1996-02-23
E.39.1. Migration from version 1.0 to version 1.01 The following notes are for the benefit of users who want to migrate databases from Postgres95 1.0 to Postgres95 1.01. If you are starting afresh with Postgres95 1.01 and do not need to migrate old databases, you do not need to read any further. In order to Postgres95 version 1.01 with databases created with Postgres95 version 1.0, the following steps are required: 1.
Set the definition of NAMEDATALEN in src/Makefile.global to 16 and OIDNAMELEN to 20.
2.
Decide whether you want to use Host based authentication. a.
If you do, you must create a file name pg_hba in your top-level data directory (typically the value of your $PGDATA). src/libpq/pg_hba shows an example syntax.
b.
If you do not want host-based authentication, you can comment out the line HBA = 1
in src/Makefile.global Note that host-based authentication is turned on by default, and if you do not take steps A or B above, the out-of-the-box 1.01 will not allow you to connect to 1.0 databases. 3.
Compile and install 1.01, but DO NOT do the initdb step.
4.
Before doing anything else, terminate your 1.0 postmaster, and backup your existing $PGDATA directory.
5.
Set your PGDATA environment variable to your 1.0 databases, but set up path up so that 1.01 binaries are being used.
6.
Modify the file $PGDATA/PG_VERSION from 5.0 to 5.1
7.
Start up a new 1.01 postmaster
1125
8.
Add the new built-in functions and operators of 1.01 to 1.0 databases. This is done by running the new 1.01 server against your own 1.0 database and applying the queries attached and saving in the file 1.0_to_1.01.sql. This can be done easily through psql. If your 1.0 database is name testdb: % psql testdb -f 1.0_to_1.01.sql
and then execute the following commands (cut and paste from here): -- add builtin functions that are new to 1.01 create function int4eqoid (int4, oid) returns bool as 'foo' language 'internal'; create function oideqint4 (oid, int4) returns bool as 'foo' language 'internal'; create function char2icregexeq (char2, text) returns bool as 'foo' language 'internal'; create function char2icregexne (char2, text) returns bool as 'foo' language 'internal'; create function char4icregexeq (char4, text) returns bool as 'foo' language 'internal'; create function char4icregexne (char4, text) returns bool as 'foo' language 'internal'; create function char8icregexeq (char8, text) returns bool as 'foo' language 'internal'; create function char8icregexne (char8, text) returns bool as 'foo' language 'internal'; create function char16icregexeq (char16, text) returns bool as 'foo' language 'internal'; create function char16icregexne (char16, text) returns bool as 'foo' language 'internal'; create function texticregexeq (text, text) returns bool as 'foo' language 'internal'; create function texticregexne (text, text) returns bool as 'foo' language 'internal'; -- add builtin functions that are new to 1.01 create create create create create create create create create create create create
operator operator operator operator operator operator operator operator operator operator operator operator
= (leftarg = int4, rightarg = oid, procedure = int4eqoid); = (leftarg = oid, rightarg = int4, procedure = oideqint4); ~* (leftarg = char2, rightarg = text, procedure = char2icregexeq); !~* (leftarg = char2, rightarg = text, procedure = char2icregexne); ~* (leftarg = char4, rightarg = text, procedure = char4icregexeq); !~* (leftarg = char4, rightarg = text, procedure = char4icregexne); ~* (leftarg = char8, rightarg = text, procedure = char8icregexeq); !~* (leftarg = char8, rightarg = text, procedure = char8icregexne); ~* (leftarg = char16, rightarg = text, procedure = char16icregexeq); !~* (leftarg = char16, rightarg = text, procedure = char16icregexne); ~* (leftarg = text, rightarg = text, procedure = texticregexeq); !~* (leftarg = text, rightarg = text, procedure = texticregexne);
E.39.2. Changes Incompatibilities: * 1.01 is backwards compatible with 1.0 database provided the user follow the steps outlined in the MIGRATION_from_1.0_to_1.01 file. If those steps are not taken, 1.01 is not compatible with 1.0 database. Enhancements: * added PQdisplayTuples() to libpq and changed monitor and psql to use it * added NeXT port (requires SysVIPC implementation) * added CAST .. AS ... syntax * added ASC and DESC key words * added 'internal' as a possible language for CREATE FUNCTION internal functions are C functions which have been statically linked
1126
into the postgres backend. * a new type "name" has been added for system identifiers (table names, attribute names, etc.) This replaces the old char16 type. The of name is set by the NAMEDATALEN #define in src/Makefile.global * a readable reference manual that describes the query language. * added host-based access control. A configuration file ($PGDATA/pg_hba) is used to hold the configuration data. If host-based access control is not desired, comment out HBA=1 in src/Makefile.global. * changed regex handling to be uniform use of Henry Spencer's regex code regardless of platform. The regex code is included in the distribution * added functions and operators for case-insensitive regular expressions. The operators are ~* and !~*. * pg_dump uses COPY instead of SELECT loop for better performance Bug fixes: * fixed an optimizer bug that was causing core dumps when functions calls were used in comparisons in the WHERE clause * changed all uses of getuid to geteuid so that effective uids are used * psql now returns non-zero status on errors when using -c * applied public patches 1-14
E.40. Release 1.0 Release date: 1995-09-05
E.40.1. Changes Copyright change: * The copyright of Postgres 1.0 has been loosened to be freely modifiable and modifiable for any purpose. Please read the COPYRIGHT file. Thanks to Professor Michael Stonebraker for making this possible. Incompatibilities: * date formats have to be MM-DD-YYYY (or DD-MM-YYYY if you're using EUROPEAN STYLE). This follows SQL-92 specs. * "delimiters" is now a key word Enhancements: * sql LIKE syntax has been added * copy command now takes an optional USING DELIMITER specification. delimiters can be any single-character string. * IRIX 5.3 port has been added. Thanks to Paul Walmsley and others. * updated pg_dump to work with new libpq * \d has been added psql Thanks to Keith Parks * regexp performance for architectures that use POSIX regex has been improved due to caching of precompiled patterns. Thanks to Alistair Crooks * a new version of libpq++ Thanks to William Wanders Bug fixes: * arbitrary userids can be specified in the createuser script * \c to connect to other databases in psql now works. * bad pg_proc entry for float4inc() is fixed * users with usecreatedb field set can now create databases without having to be usesuper * remove access control entries when the entry no longer has any privileges * fixed non-portable datetimes implementation * added kerberos flags to the src/backend/Makefile * libpq now works with kerberos * typographic errors in the user manual have been corrected. * btrees with multiple index never worked, now we tell you they don't
1127
work when you try to use them
E.41. Postgres95 Release 0.03 Release date: 1995-07-21
E.41.1. Changes Incompatible changes: * BETA-0.3 IS INCOMPATIBLE WITH DATABASES CREATED WITH PREVIOUS VERSIONS (due to system catalog changes and indexing structure changes). * double-quote (") is deprecated as a quoting character for string literals; you need to convert them to single quotes ('). * name of aggregates (eg. int4sum) are renamed in accordance with the SQL standard (eg. sum). * CHANGE ACL syntax is replaced by GRANT/REVOKE syntax. * float literals (eg. 3.14) are now of type float4 (instead of float8 in previous releases); you might have to do typecasting if you depend on it being of type float8. If you neglect to do the typecasting and you assign a float literal to a field of type float8, you may get incorrect values stored! * LIBPQ has been totally revamped so that frontend applications can connect to multiple backends * the usesysid field in pg_user has been changed from int2 to int4 to allow wider range of Unix user ids. * the netbsd/freebsd/bsd o/s ports have been consolidated into a single BSD44_derived port. (thanks to Alistair Crooks) SQL standard-compliance (the following details changes that makes postgres95 more compliant to the SQL-92 standard): * the following SQL types are now built-in: smallint, int(eger), float, real, char(N), varchar(N), date and time. The following are aliases to existing postgres types: smallint -> int2 integer, int -> int4 float, real -> float4 char(N) and varchar(N) are implemented as truncated text types. In addition, char(N) does blank-padding. * single-quote (') is used for quoting string literals; '' (in addition to \') is supported as means of inserting a single quote in a string * SQL standard aggregate names (MAX, MIN, AVG, SUM, COUNT) are used (Also, aggregates can now be overloaded, i.e. you can define your own MAX aggregate to take in a user-defined type.) * CHANGE ACL removed. GRANT/REVOKE syntax added. - Privileges can be given to a group using the "GROUP" key word. For example: GRANT SELECT ON foobar TO GROUP my_group; The key word 'PUBLIC' is also supported to mean all users. Privileges can only be granted or revoked to one user or group at a time. "WITH GRANT OPTION" is not supported. Only class owners can change access control - The default access control is to to grant users readonly access. You must explicitly grant insert/update access to users. To change this, modify the line in src/backend/utils/acl.h that defines ACL_WORLD_DEFAULT Bug fixes: * the bug where aggregates of empty tables were not run has been fixed. Now, aggregates run on empty tables will return the initial conditions of the
1128
aggregates. Thus, COUNT of an empty table will now properly return 0. MAX/MIN of an empty table will return a row of value NULL. * allow the use of \; inside the monitor * the LISTEN/NOTIFY asynchronous notification mechanism now work * NOTIFY in rule action bodies now work * hash indexes work, and access methods in general should perform better. creation of large btree indexes should be much faster. (thanks to Paul Aoki) Other changes and enhancements: * addition of an EXPLAIN statement used for explaining the query execution plan (eg. "EXPLAIN SELECT * FROM EMP" prints out the execution plan for the query). * WARN and NOTICE messages no longer have timestamps on them. To turn on timestamps of error messages, uncomment the line in src/backend/utils/elog.h: /* define ELOG_TIMESTAMPS */ * On an access control violation, the message "Either no such class or insufficient privilege" will be given. This is the same message that is returned when a class is not found. This dissuades non-privileged users from guessing the existence of privileged classes. * some additional system catalog changes have been made that are not visible to the user. libpgtcl changes: * The -oid option has been added to the "pg_result" tcl command. pg_result -oid returns oid of the last row inserted. If the last command was not an INSERT, then pg_result -oid returns "". * the large object interface is available as pg_lo* tcl commands: pg_lo_open, pg_lo_close, pg_lo_creat, etc. Portability enhancements and New Ports: * flex/lex problems have been cleared up. Now, you should be able to use flex instead of lex on any platforms. We no longer make assumptions of what lexer you use based on the platform you use. * The Linux-ELF port is now supported. Various configuration have been tested: The following configuration is known to work: kernel 1.2.10, gcc 2.6.3, libc 4.7.2, flex 2.5.2, bison 1.24 with everything in ELF format, New utilities: * ipcclean added to the distribution ipcclean usually does not need to be run, but if your backend crashes and leaves shared memory segments hanging around, ipcclean will clean them up for you. New documentation: * the user manual has been revised and libpq documentation added.
E.42. Postgres95 Release 0.02 Release date: 1995-05-25
E.42.1. Changes Incompatible changes: * The SQL statement for creating a database is 'CREATE DATABASE' instead of 'CREATEDB'. Similarly, dropping a database is 'DROP DATABASE' instead of 'DESTROYDB'. However, the names of the executables 'createdb' and 'destroydb' remain the same. New tools: * pgperl - a Perl (4.036) interface to Postgres95 * pg_dump - a utility for dumping out a postgres database into a script file containing query commands. The script files are in a ASCII format and can be used to reconstruct the database, even on other
1129
machines and other architectures. (Also good for converting a Postgres 4.2 database to Postgres95 database.) The following ports have been incorporated into postgres95-beta-0.02: * the NetBSD port by Alistair Crooks * the AIX port by Mike Tung * the Windows NT port by Jon Forrest (more stuff but not done yet) * the Linux ELF port by Brian Gallew The following bugs have been fixed in postgres95-beta-0.02: * new lines not escaped in COPY OUT and problem with COPY OUT when first attribute is a '.' * cannot type return to use the default user id in createuser * SELECT DISTINCT on big tables crashes * Linux installation problems * monitor doesn't allow use of 'localhost' as PGHOST * psql core dumps when doing \c or \l * the "pgtclsh" target missing from src/bin/pgtclsh/Makefile * libpgtcl has a hard-wired default port number * SELECT DISTINCT INTO TABLE hangs * CREATE TYPE doesn't accept 'variable' as the internallength * wrong result using more than 1 aggregate in a SELECT
E.43. Postgres95 Release 0.01 Release date: 1995-05-01
Initial release.
1130
Apêndice F. O repositório CVS Marc Fournier, Tom Lane, e Thomas Lockhart1999-05-20 O código fonte do PostgreSQL é armazenado e gerenciado utilizando o sistema de gerenciamento de código CVS. Pelo menos dois métodos, CVS anônimo e CVSup, podem ser utilizados para trazer a árvore de código no CVS do servidor PostgreSQL para a máquina local.
F.1. Obtenção do código fonte via CVS anônimo Se for desejado ficar em dia regularmente com os fontes correntes, pode-se trazê-los do servidor CVS, e depois realizar atualizações periódicas utilizando o CVS. CVS anônimo 1.
É necessária uma cópia do CVS (Concurrent Version Control System), que pode ser obtida em http://www.cvshome.org/ ou em qualquer local que disponibilize software GNU. Atualmente recomendase a versão 1.10 (a mais recente ao se escrever este documento). Muitos sistemas possuem uma versão recente do cvs instalada por padrão.
2.
Efetuar o login inicial no servidor CVS: cvs -d :pserver:[email protected]:/projects/cvsroot login
Será solicitada uma senha; pode ser qualquer coisa, exceto uma cadeia de caracteres vazia (Portanto, não pressione a tecla Enter antes de digitar alguma coisa - N. do T.). Só é necessário realizar esta operação uma única vez, porque a senha é salva no arquivo .cvspass no seu diretório base (home). 3.
Trazer os fontes do PostgreSQL: cvs -z3 -d :pserver:[email protected]:/projects/cvsroot co -P pgsql
(co é sinônimo de checkout. N. do T.) Este comando coloca os fontes do PostgreSQL no subdiretório pgsql do diretório corrente. Nota: Se for usado um acesso de banda larga à Internet, pode não haver necessidade da opção -z3, que instrui o CVS a usar a compressão gzip na transferência dos dados, mas em um acesso na velocidade de modem há um ganho substancial.
A transferência inicial é um pouco mais lenta do que simplesmente baixar o arquivo tar.gz; espera-se que demore 40 minutos ou mais com um modem de 28.8K. A vantagem do CVS não é sentida até que se deseje atualizar o conjunto de arquivos posteriormente. 4.
Sempre que for desejado atualizar para obter os fontes mais recentes no CVS, muda-se para o subdiretório (cd) pgsql e executa-se $ cvs -z3 update -d -P
Este procedimento traz somente as alterações realizadas desde a última atualização. Normalmente a atualização demora poucos minutos, mesmo em um acesso na velocidade de modem. 5.
É possível reduzir um pouco a digitação criando o arquivo ~/.cvsrc 1 contendo cvs -z3 update -d -P
definindo a opção global -z3 para todos os comandos cvs, e as opções -d e -P para atualizações no cvs. Em seguida, basta digitar $ cvs update
para atualizar os arquivos.
1131
Cuidado Algumas versões mais antigas do CVS possuem um erro que faz com que os arquivos trazidos sejam armazenados no diretório podendo ser escritos por todos. Caso isto aconteça, é possível fazer algo como $ chmod -R go-w pgsql
para definir as permissões de forma apropriada. Este erro foi corrigido no CVS versão 1.9.28.
O CVS pode fazer muitas outras coisas, tal como trazer versões anteriores dos fontes do PostgreSQL em vez de trazer a última versão de desenvolvimento. Para mais informações consulte o manual que acompanha o CVS, ou veja a documentação em http://www.cvshome.org/.
F.2. Organização da árvore do CVS Autor: Escrito por Marc G. Fournier (<[email protected]>) em 1998-11-05
O comando cvs checkout possui um sinalizador, -r, que permite trazer (checkout) uma determinada revisão de um módulo. Este sinalizador torna fácil, por exemplo, trazer os fontes que compõem a versão 6_4 do módulo `tc' a qualquer momento: $ cvs checkout -r REL6_4 tc
Este comando é útil, por exemplo, caso alguém reclame que existe um erro nesta versão, mas o erro não pode ser encontrado na cópia de trabalho corrente. Dica: Também é possível trazer um módulo, como este se encontrava em uma determinada data, utilizando a opção -D.
Quando se marca mais de um arquivo com a mesma marca, pode-se pensar na marca (tag) como sendo “uma curva traçada através de uma matriz de nome de arquivo versus número de revisão” 2 . Digamos que existam 5 arquivos com as seguintes revisões: arq1
arq2
arq3
arq4
arq5
1.1 1.1 1.1 1.1 /--1.1* 1.2*1.2 1.2 -1.2*1.3 \- 1.3*1.3 / 1.3 1.4 \ 1.4 / 1.4 \-1.5*1.5 1.6
<-*-
MARCA
então a marca MARCA faz referência a arq1-1.2, arq2-1.3, etc. (continuação tirada do manual do CVS->) Pode-se imaginar a marca como uma alça presa a curva traçada através das revisões marcadas. Quando se puxa a alça, são trazidas todas as revisões marcadas. Outra forma de enxergar é como uma “visão” através de um conjunto de revisões que é um “plano” ao longo das revisões marcadas, como mostrado abaixo: arq1
arq2
arq3 arq4 arq5 1.1 1.2 1.1 1.3 1.1 1.2 1.4 1.1 1.2*----1.3*----1.5*----1.2*----1.1 1.3 1.6 1.3 1.4 1.4
_ / (--- <--- Veja aqui \_
(<-fim da continuação do manual - N. do T.)
1132
Nota: É a mesma coisa que criar uma ramificação (branch) de versão, sem utilizar a opção -b adicionada ao comando.
Portanto, para criar a versão 6.4 foi feito o seguinte: $ cd pgsql $ cvs tag -b REL6_4
criando a marca e a ramificação para a árvore RELEASE. Para os que possuem acesso ao CVS, é simples criar diretórios para versões diferentes. Primeiro são criados dois subdiretórios, RELEASE e CURRENT, para não confundir os dois. Depois é feito: cd RELEASE cvs checkout -P -r REL6_4 pgsql cd ../CURRENT cvs checkout -P pgsql
que resulta em duas árvores de diretório, RELEASE/pgsql e CURRENT/pgsql. Deste ponto em diante, o CVS mantém controle de qual ramificação do repositório está qual árvore de diretório, permitindo atualizações independentes para cada árvore 3 . Para trabalhar apenas na árvore de fonte CURRENT, basta fazer tudo como estava sendo feito antes de começar a colocar marcas de ramificação de versão. Após a baixa (checkout) inicial de uma ramificação $ cvs checkout -r REL6_4
tudo que é feito dentro desta árvore de diretório está restrito a esta ramificação. Se for aplicada uma correção a esta árvore de diretório e feito um cvs commit
de dentro desta árvore, a correção é aplicada a esta ramificação e somente a esta ramificação 4 .
F.3. Obtenção do código fonte via CVSup Uma alternativa ao uso do CVS anônimo para trazer a árvore dos fontes do PostgreSQL é o CVSup. O CVSup foi desenvolvido por John Polstra (<[email protected]>) para distribuir repositórios CVS e outras árvores de arquivo para o projeto FreeBSD (http://www.freebsd.org). Uma das principais vantagens em utilizar o CVSup é que este pode replicar, confiavelmente, todo o repositório CVS no sistema local, permitindo acesso local rápido às operações do CVS, tais como log e diff. Entre outras vantagens está a sincronização rápida com o servidor PostgreSQL devido a um protocolo de transferência de fluxo eficiente, que envia apenas as modificações realizadas desde a última atualização.
F.3.1. Preparação do sistema cliente do CVSup São necessárias duas áreas de diretório para o CVSup realizar seu trabalho: um repositório CVS local (ou simplesmente uma área de diretório se estiver trazendo um instantâneo em vez do repositório; veja abaixo) e uma área local para registrar as transações do CVSup. Estas duas áreas podem coexistir na mesma árvore de diretório. Decidir onde se deseja manter a cópia local do repositório CVS. Em um dos nossos sistemas foi definido recentemente o repositório em /home/cvs/, mas estava sendo mantido anteriormente sob a árvore de desenvolvimento do PostgreSQL em /opt/postgres/cvs/. Caso se pretenda manter o repositório em /home/cvs/, então deve ser colocado setenv CVSROOT /home/cvs
no arquivo .cshrc do usuário, ou uma linha semelhante no arquivo .bashrc ou .profile, dependendo do interpretador de comandos utilizado.
1133
A área de repositório do cvs deve ser inicializada. Após CVSROOT ser definido, então a inicialização pode ser feita com um único comando: $ cvs init
após o qual deve ser visto pelo menos um diretório chamado CVSROOT ao se listar o diretório CVSROOT: $ ls $CVSROOT CVSROOT/
F.3.2. Execução do cliente do CVSup Vericar se o cvsup está no caminho; na maioria dos sistemas é feito digitando which cvsup
Depois, basta executar cvsup utilizando: $ cvsup -L 2 postgres.cvsup
onde -L 2 ativa algumas mensagens de status permitindo monitorar a evolução da atualização, e postgres.cvsup é o caminho e nome atribuído ao arquivo de configuração do CVSup. Abaixo está mostrado um arquivo de configuração do CVSup modificado para uma instalação específica, e que mantém um repositório local CVS completo: # This file represents the standard CVSup distribution file # for the PostgreSQL ORDBMS project # Modified by [email protected] 1997-08-28 # - Point to my local snapshot source tree # - Pull the full CVS repository, not just the latest snapshot # # Defaults that apply to all the collections *default host=cvsup.postgresql.org *default compress *default release=cvs *default delete use-rel-suffix # enable the following line to get the latest snapshot #*default tag=. # enable the following line to get whatever was specified above or by default # at the date specified below #*default date=97.08.29.00.00.00 # base directory where CVSup will store its 'bookmarks' file(s) # will create subdirectory sup/ #*default base=/opt/postgres # /usr/local/pgsql *default base=/home/cvs # prefix directory where CVSup will store the actual distribution(s) *default prefix=/home/cvs # complete distribution, including all below pgsql # # # #
individual distributions vs 'the whole thing' pgsql-doc pgsql-perl5 pgsql-src
A seguir está mostrado o arquivo de configuração sugerido do CVSup, tirado do site de ftp do PostgreSQL (ftp://ftp.postgresql.org/pub/CVSup/README.cvsup), que traz o instantâneo corrente apenas:
1134
# This file represents the standard CVSup distribution file # for the PostgreSQL ORDBMS project # # Defaults that apply to all the collections *default host=cvsup.postgresql.org *default compress *default release=cvs *default delete use-rel-suffix *default tag=. # base directory where CVSup will store its 'bookmarks' file(s) *default base=/usr/local/pgsql # prefix directory where CVSup will store the actual distribution(s) *default prefix=/usr/local/pgsql # complete distribution, including all below pgsql # # # #
individual distributions vs 'the whole thing' pgsql-doc pgsql-perl5 pgsql-src
F.3.3. Instalação do CVSup O CVSup está disponível sob a forma de fonte, binários pré-construídos, e RPMs do Linux . É muito muito mais fácil usar o binário do que construir a partir do fonte, principalmente porque o muito poderoso, mas muito grande, compilador Modula-3 é necessário para a construção. Instalação do CVSup a partir dos binários Podem ser utilizados binários pré-construídos se for utilizada uma plataforma para a qual os binários estão disponíveis no site de ftp do PostgreSQL (ftp://ftp.postgresql.org/pub), ou se estiver utilizando o FreeBSD, para o qual o CVSup está disponível como um “port” 5 . Nota: O CVSup foi desenvolvido originalmente como uma ferramenta para distribuição da árvore do fonte do FreeBSD. Está disponível como um “port” e, para os usuários do FreeBSD, se não for suficiente dizer como obter e instalar então, por favor, contribua enviando o procedimento.
Quando este material foi escrito, haviam binários disponíveis para Alpha/Tru64, ix86/xBSD, HPPA/HP-UX 10.20, MIPS/IRIX, ix86/linux-libc5, ix86/linux-glibc, Sparc/Solaris e Sparc/SunOS. 1.
2.
Obter o arquivo tar binário do cvsup (cvsupd não é necessário para ser um cliente) apropriado para a plataforma sendo usada. a.
Se estiver usando o FreeBSD, instalar o “port” do CVSup.
b.
Se estiver sendo utilizada uma outra plataforma, verificar e baixar o binário apropriado do site de ftp do PostgreSQL (ftp://ftp.postgresql.org/pub).
Analisar o arquivo tar para verificar o conteúdo e a estrutura de diretório. Pelo menos para o arquivo tar do Linux, o binário estático e as páginas do manual estão incluídas sem nenhum empacotamento de diretório. a.
Se o binário estiver no nível mais alto do arquivo tar então simplesmente extraia o arquivo tar no diretório de destino: $ cd /usr/local/bin $ tar zxvf /usr/local/src/cvsup-16.0-linux-i386.tar.gz $ mv cvsup.1 ../doc/man/man1/
b. 3.
Havendo uma estrutura de diretório no arquivo tar, então extraia o arquivo tar dentro de /usr/local/src e mova os binários para o local apropriado como mostrado acima.
Garanta que os novos binários podem ser encontrados no caminho.
1135
$ rehash $ which cvsup $ set path=(caminho para o cvsup $path) $ which cvsup /usr/local/bin/cvsup
F.3.4. Instalação a partir dos fontes A instalação do CVSup a partir dos arquivos fonte não é totalmente trivial, principalmente porque a maioria dos sistemas necessita da instalação do compilador Modula-3 antes. Este compilador está disponível como um arquivo RPM do Linux, um pacote FreeBSD, ou código fonte. Nota: A instalação do Modula-3 a partir dos fontes ocupa cerca de 200MB de espaço em disco, que fica reduzido para cerca de 50MB de espaço quando os fontes são removidos.
Instalação no Linux 1.
Instalar o Modula-3. a.
Obter a distribuição do Modula-3 em Polytechnique Montréal Modula-3 (PM3) (http://www.elegosoft.com/pm3/), que está mantendo atualmente o código base desenvolvido originalmente pelo DEC Systems Research Center (http://www.research.digital.com/SRC/modula-3/html/home.html). A distribuição do RPM do PM3 comprimida tem aproximadamente 30MB. Quando este documento foi escrito, a versão 1.1.10-1 instalava sem problemas no RH-5.2, enquanto a versão 1.1.11-1 era aparentemente feita para outra versão (RH-6.0?) e não executava no RH-5.2. Dica: Este empacotamento de rpm possui muitos arquivos RPM e, portanto, provavelmente se desejará colocá-los em um diretório separado.
b.
Instalar os rpms do Modula-3: # rpm -Uvh pm3*.rpm
2.
Descompactar a distribuição do cvsup: # cd /usr/local/src # tar zxf cvsup-16.0.tar.gz
3.
Construir a distribuição do cvsup, suprimindo a funcionalidade de interface GUI para evitar a necessidade de bibliotecas do X11: # make M3FLAGS="-DNOGUI"
e, se for desejado construir um binário estático que possa ser movido para sistemas que não possuam o Modula-3 instalado, tente: # make M3FLAGS="-DNOGUI -DSTATIC"
4.
Instalar o binário construído: # make M3FLAGS="-DNOGUI -DSTATIC" install
Notas 1. ~/.cvsrc - o til especifica diretório home e o ponto especifica arquivo oculto no Unix. (N. do T.) 2. Número de revisão — Cada versão do arquivo possui um número de revisão único. Os números de revisão se parecem como “1.1”, “1.2”, “1.3.2.2” ou mesmo “1.3.2.2.4.5”. Por padrão, a revisão “1.1” é a primeira revisão do arquivo. A cada revisão sucessiva é atribuído um novo número acrescentando um ao número mais à direita. Também é possível haver números contendo mais de um ponto como, por exemplo, “1.3.2.2”. Estas revisões representam revisões em ramificações. Manual do CVS (http://www.cvshome.org/docs/manual/cvs-1.11.13/cvs.html) (N. do T.) 3. Se for desejado trazer duas ramificações como, por exemplo, REL6_4 e REL7_4_1, é necessário criar os subdiretórios RELEASE/REL6_4 e RELEASE/REL7_4_1, e executar os comandos “cvs checkout -P -r REL6_4 pgsql” e “cvs checkout -P -r REL7_4_1 pgsql” de dentro destes subdiretórios. (N. do T.)
1136
4. Dentro de cada árvore existe o arquivo pgsql/CVS/Tag contendo o nome da ramificação. (N. do T.) 5. Para o Debian basta executar “apt-get install cvsup”. (N. do T.)
1137
Apêndice G. Documentação O PostgreSQL possui quatro formatos de documentação principais: •
Texto puro, para informações de pré-instalação.
•
HTML, para navegação on-line e referência.
•
PDF ou Postscript, para impressão.
• man pages
1
para referência rápida.
Além desses, vários arquivos texto puro README podem ser encontrados dentro da árvore do código fonte do PostgreSQL, documentando diversas questões de implementação. A documentação em HTML e as man pages fazem parte da distribuição padrão, sendo instaladas por padrão. Os formatos PDF e Postscript da documentação estão disponíveis em separado, podendo ser baixados.
G.1. DocBook Os fontes da documentação estão escritos em DocBook, que é uma linguagem de marcação semelhante, superficialmente, ao HTML. Estas duas linguagens são aplicações da Standard Generalized Markup Language, SGML, que é essencialmente uma linguagem para descrever outras linguagens. No que se segue, os dois termos DocBook e SGML são empregados, mas tecnicamente não podem ser trocados. O DocBook permite ao autor especificar a estrutura e o conteúdo de um documento técnico sem se preocupar com relação aos detalhes da apresentação. O estilo do documento define como o conteúdo é apresentado em uma dentre várias formas finais. O DocBook is é mantido pelo grupo OASIS (http://www.oasis-open.org). O Site oficial do DocBook (http://www.oasis-open.org/docbook) possui uma boa documentação introdutória e de referência e um livro O'Reilly completo que pode ser lido on-line. O FreeBSD Documentation Project (http://www.freebsd.org/docproj/docproj.html) também usa o DocBook e possui boas informações, incluindo vários guias para estilo que valem a pena serem levados em consideração.
G.2. Conjunto de ferramentas As seguintes ferramentas são utilizadas para processar a documentação. Algumas podem ser opcionais, conforme indicado. DTD do DocBook (http://www.oasis-open.org/docbook/sgml/) Esta é a definição do próprio DocBook. Atualmente é utilizada a versão 4.2; não pode ser usada uma versão anterior ou posterior. Observe que também existe uma versão XML do DocBook -- não utilize esta versão. Entidades de caractere ISO 8879 (http://www.oasis-open.org/cover/ISOEnts.zip) Estas entidades são requeridas pelo DocBook, mas são distribuídas em separado porque são mantidas pela ISO. OpenJade (http://openjade.sourceforge.net) Este é o pacote básico para processar o SGML. Contém um analisador SGML, um processador DSSSL (ou seja, um programa para converter SGML em outros formatos utilizando as folhas de estilo DSSSL), assim bem como várias ferramentas relacionadas. O Jade agora é mantido pelo grupo OpenJade, e não mais por James Clark. Folhas de estilo DSSSL do DocBook (http://docbook.sourceforge.net/projects/dsssl/index.html) Contém instruções de processamento para converter os fontes em DocBook para outros formatos, tal como HTML.
1138
Ferramentas DocBook2X (http://docbook2x.sourceforge.net) Este pacote opcional é utilizado para criar as man pages, e contém vários pacotes pré-requisitos próprios. Verifique o sítio na Web. JadeTeX (http://jadetex.sourceforge.net) Se for desejado, podem ser instalados também JadeTeX para utilizar o TeX como formatador para o Jade. O JadeTeX pode criar arquivos Postscript ou PDF (este último com marcas). Entretanto, a saída do JadeTeX é inferior à obtida pelo processador do RTF. Entre as áreas com problemas específicos estão as tabelas e vários artefatos de espaçamento vertical e horizontal. Além disso, não existe oportunidade para melhorar manualmente os resultados. Possuímos experiências documentadas em vários métodos de instalação para as várias ferramentas necessárias para processar a documentação, as quais estão descritas abaixo. Podem haver outros pacotes contendo distribuições destas ferramentas. Por favor informe o status do pacote para a lista de discussão da documentação, e esta informação será incluída aqui.
G.2.1. Instalação de RPM no Linux A maioria dos fornecedores disponibiliza um conjunto completo de pacotes RPM para processar o DocBook em sua distribuição. Procure pela opção “SGML” ao instalar, ou os seguintes pacotes: sgml-common, docbook, stylesheets, openjade (ou jade). É possível que sgml-tools também seja necessário. Se não estiver disponível na sua distribuição, então deve ser possível utilizar pacotes de alguma outra, razoavelmente compatível, distribuição.
G.2.2. Instalação no FreeBSD O próprio Projeto de Documentação do FreeBSD é um grande usuário do DocBook e, portanto, não é surpresa que exista um conjunto completo de “ports” das ferramentas de documentação disponível no FreeBSD. As seguintes ferramentas portadas precisam ser instaladas para gerar a documentação no FreeBSD. • textproc/sp • textproc/openjade • textproc/iso8879 • textproc/dsssl-docbook-modular
Aparentemente, não existe um DocBook V4.2 SGML DTD portado disponível atualmente, sendo necessário efetuar sua instalação manualmente. Várias outras aplicações contidas em /usr/ports/print (tex, jadetex) também podem ser de interesse. É possível que as aplicações portadas não atualizem o arquivo do catálogo principal em /usr/local/share/sgml/catalog. Tenha certeza de que a seguinte linha esteja presente: CATALOG "/usr/local/share/sgml/docbook/4.2/docbook.cat"
Se não for desejado editar o arquivo também pode ser definida a variável de ambiente SGML_CATALOG_FILES como uma lista separada por vírgulas de arquivos de catálogo (tal como o acima). Outras informações sobre as ferramentas de documentação do FreeBSD podem ser encontradas em FreeBSD Documentation Project's instructions (http://www.freebsd.org/doc/en_US.ISO8859-1/books/fdpprimer/tools.html).
G.2.3. Pacotes do Debian Existe um conjunto completo de pacotes para as ferramentas de documentação disponível para o Debian GNU/Linux. Para instalar, deve simplesmente ser utilizado 2 : apt-get install jade apt-get install docbook apt-get install docbook-stylesheets
1139
G.2.4. Instalação manual a partir dos fontes O processo de instalação manual das ferramentas do DocBook é um tanto complexo e, portanto, havendo pacotes pré-construídos disponíveis, estes devem ser utilizados. Aqui é mostrada apenas a instalação padrão, com caminhos de instalação padrão razoáveis, e nenhuma funcionalidade “fantasiosa”. Para obter detalhes, deve ser estudada a documentação do próprio pacote, e ler o material de introdução do SGML. G.2.4.1. Instalação do OpenJade 1.
A instalação do OpenJade oferece um processo de construção ./configure; make; make install ao estilo GNU. Os detalhes podem ser encontrados na distribuição do código fonte do OpenJade. De forma concisa: ./configure --enable-default-catalog=/usr/local/share/sgml/catalog make make install
Não se esqueça de onde foi colocado o “catálogo padrão”; será necessário a seguir. Também pode ser deixado de fora, mas deverá ser definida a variável de ambiente SGML_CATALOG_FILES para apontar para o arquivo sempre que o jade for utilizado posteriormente (Este método também é uma opção se OpenJade já estiver instalado e for desejado instalar o restante do conjunto de ferramentas localmente). 2.
Além disso, devem ser instalados os arquivos dsssl.dtd, fot.dtd, style-sheet.dtd e catalog a partir do diretório dsssl em algum lugar, talvez no diretório /usr/local/share/sgml/dsssl. Provavelmente é mais fácil copiar todo o diretório: cp -R dsssl /usr/local/share/sgml
3.
Para terminar, deve ser criado o arquivo /usr/local/share/sgml/catalog e adicionada a seguinte linha ao mesmo: CATALOG "dsssl/catalog"
(Este é o caminho relativo de referência ao arquivo instalado no passo 2. Assegure de ajustá-lo se for escolhida uma disposição diferente para a instalação). G.2.4.2. Instalação do kit DTD do DocBook 1.
Obtenha a distribuição DocBook V4.2 (http://www.docbook.org/sgml/4.2/docbook-4.2.zip).
2.
Crie o diretório /usr/local/share/sgml/docbook-4.2 e torne-o o diretório corrente (A localização exata é irrelevante, mas esta está razoável dentro da disposição que está sendo seguida). $ mkdir /usr/local/share/sgml/docbook-4.2 $ cd /usr/local/share/sgml/docbook-4.2
3.
Descompactar o arquivo. $ unzip -a ...../docbook-4.2.zip
(Os arquivos serão descompactados no diretório corrente) 4.
Editar o arquivo /usr/local/share/sgml/catalog (ou o que foi informado ao jade durante a instalação) e adicionar uma linha como esta: CATALOG "docbook-4.2/docbook.cat"
5.
Opcionalmente, pode ser editado o arquivo docbook.cat e tornada comentário ou removida a linha contendo DTDDECL. Se não for feito então serão recebidas advertências do jade, mas sem maiores problemas.
6.
Baixe o arquivo Entidades caractere ISO 8879 (http://www.oasis-open.org/cover/ISOEnts.zip), e descompacte-o colocando os arquivos no mesmo diretório em que foram colocados os arquivos do DocBook. $ cd /usr/local/share/sgml/docbook-4.2 $ unzip ...../ISOEnts.zip
1140
7.
Execute o seguinte comando no diretório contendo os arquivos do DocBook e do ISO: perl -pi -e 's/iso-(.*).gml/ISO\1/g' docbook.cat
(Este procedimento corrige uma discrepância entre os nomes utilizados no arquivo de catálogo do DocBook e os nomes verdadeiros dos arquivos das entidades caractere ISO). G.2.4.3. Instalação das folhas de estilo DSSSL do DocBook Para instalar as folhas de estilo descompacte os arquivos e mova-os para um lugar adequado como, por exemplo, /usr/local/share/sgml (O arquivo compactado cria automaticamente um subdiretório ao ser descompactado). $ gunzip docbook-dsssl-1.xx.tar.gz $ tar -C /usr/local/share/sgml -xf docbook-dsssl-1.xx.tar
Também pode ser colocada a entrada usual do catálogo em /usr/local/share/sgml/catalog: CATALOG "docbook-dsssl--1.xx/catalog
Como as folhas de estilo mudam muito freqüentemente, e é alguma vezes benéfico tentar versões alternativas, o PostgreSQL não utiliza esta entrada do catálogo. Em seu lugar, veja a Seção G.2.5 para obter informações sobre como selecionar uma folha de estilo. G.2.4.4. Instação do JadeTeX Para instalar e utilizar o JadeTeX, é necessário haver uma instalação do TeX e do LaTeX2e funcionando, incluindo: ferramentas (tools) e pacotes gráficos (graphics); Babel; fontes AMS (AMS fonts) e AMS-LaTeX; a extensão PSNFSS; o kit de 35 fontes (“the 35 fonts”) que acompanha o programa dvips para gerar PostScript; os pacotes de macros fancyhdr, hyperref, minitoc, url e ot2enc. Todos estes podem ser encontrados em CTAN (http://www.ctan.org). A instalação do sistema básico do TeX está muito acima do escopo desta introdução. Os pacotes binários devem estar disponíveis para qualquer sistema que possa executar o TeX. Antes de ser possível utilizar o JadeTeX com os fontes da documentação do PostgreSQL, é necessário aumentar o tamanho das estruturas internas do TeX. Os detalhes podem ser encontrados nas instruções de instalação do JadeTeX. Após terminar esta parte pode ser instalado o JadeTeX: $ gunzip jadetex-xxx.tar.gz $ tar xf jadetex-xxx.tar $ cd jadetex $ make install $ mktexlsr
Os dois últimos comando devem ser executados como root.
G.2.5. Detecção pelo configure Antes de poder gerar a documentação é necessário executar o script configure como seria feito para gerar os próprios programas do PostgreSQL. Verifique a saída perto do fim da execução, que deve ser parecida com: checking for onsgmls... onsgmls checking for openjade... openjade checking for DocBook V4.2... yes checking for DocBook stylesheets... /usr/lib/sgml/stylesheets/nwalsh-modular checking for sgmlspl... sgmlspl
Se nem onsgmls nem nsgmls forem encontrados então não serão vistas as quatro linhas restantes. O nsgmls é parte do pacote Jade. Se “DocBook V4.2” não for encontrado então não foi instalado o kit DocBook DTD em um lugar onde o jade possa encontrá-lo, ou os arquivos do catálogo não foram definidos corretamente. Veja as
1141
dicas de instalação acima. As folhas de estilo do DocBook são procuradas em vários locais relativamente padrão, mas se estiverem em algum outro lugar deve ser definida a variável de ambiente DOCBOOKSTYLE com o local correto e executar novamente configure após isto.
G.3. Geração da documentação Após estar tudo instalado, torne o diretório doc/src/sgml o diretório corrente, e execute um dos comandos descritos nas subseções abaixo para gerar a documentação (Lembre-se de utilizar o make do GNU).
G.3.1. HTML Para gerar a versão HTML da documentação: doc/src/sgml$ gmake html
Esta também é a versão gerada por padrão. Quando a documentação HTML é gerada, o processamento também gera as informações de vínculo com as entradas do índice. Portanto, se for desejado que a documentação possua um índice no final, é necessário gerar a documentação HTML primeiro, e depois gerar a documentação novamente no formato desejado. 3 Para permitir o tratamento mais fácil da distribuição final, os arquivos que compõem a documentação HTML se encontram empacotados em um arquivo tar que é desempacotado durante a instalação. Para criar o pacote de documentação HTML, devem ser utilizados os comandos cd doc/src gmake postgres.tar.gz
Na distribuição, estes arquivos se encontram no diretório doc, sendo instalados por padrão pelo gmake install.
G.3.2. Páginas do manual Unix É utilizado o utilitário docbook2man para converter as páginas refentry do DocBook em saída *roff adequada para as páginas do manual. As páginas do manual também são distribuídas como um arquivo tar, semelhante à versão HTML. Para gerar o pacote de páginas do manual devem ser utilizados os comandos cd doc/src gmake man.tar.gz
que produz um arquivo tar gerado no diretório doc/src. Para gerar páginas do manual com qualidade, pode ser necessário utilizar uma versão “hackeada” do utilitário de conversão, ou algum pós-processamento manual. Todas as páginas do manual devem ser inspecionadas manualmente antes de serem distribuídas.
G.3.3. Imprimir a saída usando JadeTex Se for desejado utilizar o JadeTex para gerar uma versão da documentação que possa ser impressa, pode ser utilizado um dos seguintes comandos: •
Para gerar a versão DVI: doc/src/sgml$ gmake postgres.dvi
•
Para gerar o Postscript a partir do DVI: doc/src/sgml$ gmake postgres.ps
•
Para gerar PDF: doc/src/sgml$ gmake postgres.pdf
(Obviamente pode ser gerada a versão PDF a partir do Postscript, mas se o PDF for gerado diretamente, terá hiperligações e outras funcionalidades avançadas).
1142
G.3.4. Imprimir a saída através do RTF Também é possível criar uma versão imprimível da documentação do PostgreSQL convertendo-a em RTF, e depois aplicando pequenas correções de formatação utilizando um pacote de automação de escritórios. Dependendo das funcionalidades do pacote de automação de escritórios utilizado, a documentação pode ser convertida para Postscript a partir do PDF. O procedimento abaixo mostra este processo utilizando o Applixware. Nota: Parece que a versão corrente da documentação do PostgreSQL dispara algum erro ou excede o limite do OpenJade. Se o processo de geração da versão RTF demorar muito tempo, e o tamanho do arquivo de saída permanecer igual a 0, então você esbarrou no problema; mas tenha em mente que a geração normal leva de 5 a 10 minutos, portanto não interrompa muito rapidamente.
Limpeza do RTF usando o Applixware O OpenJade omite a especificação do estilo padrão para o corpo do texto. No passado, este problema não diagnosticado levou a um longo processo para geração do sumário. Entretanto, com grande ajuda das pessoas da Applixware o sintoma foi diagnosticado e uma correção está disponível. 1.
Gerar a versão RTF digitando: doc/src/sgml$ gmake postgres.rtf
2.
Reparar o arquivo RTF para especificar corretamente todos os estilos, em particular o estilo padrão. Se o documento contém seções refentry, devem também serem substituídas as dicas de formatação que ligam o parágrafo precedente ao parágrafo corrente e, em vez disso, ligar o parágrafo corrente ao próximo parágrafo. O utilitário fixrtf está disponível em doc/src/sgml para efetuar estes reparos: doc/src/sgml$ ./fixrtf --refentry postgres.rtf
Este script adiciona {\s0 Normal;} como sendo o zero-ésimo estilo no documento. De acordo com a Applixware, o padrão RTF proíbe adicionar um zero-ésimo estilo implícito, embora o Word da Microsoft trate este caso. Para reparar as seções refentry, o script substitui as marcas \keepn por \keep. 3.
Abra um novo documento no Applixware Words e depois importe o arquivo RTF.
4.
Gere o novo Sumário (ToC) utilizando o Applixware. a.
Selecione as linhas existentes no Sumário, do início do primeiro caractere da primeira linha ao último caractere da última linha.
b.
Construa um novo Sumário utilizando Tools→Book Building→Create Table of Contents. Selecione os três primeiros níveis de cabeçalho para serem incluídos no Sumário. Este procedimento substitui as linhas existentes importadas no RTF por um Sumário nativo do Applixware.
c.
Ajuste a formatação do Sumário utilizando Format→Style, selecione cada um dos três estilos de cabeçalho, e ajuste o afastamento para First e Left. Use os seguintes valores: Style
5.
First Indent (inches) Left Indent (inches)
TOC-Heading 1
0.4
0.4
TOC-Heading 2
0.8
0.8
TOC-Heading 3
1.2
1.2
Percorra o documento para: •
Ajustar as quebras de página.
•
Ajustar as larguras das colunas das tabelas.
6.
Substitua os números das páginas alinhados à direita na parte de Exemplos e de Figuras do Sumário pelos valores corretos. Esta atividade só toma alguns minutos.
7.
Apague a seção de índice do documento caso esteja vazia.
8.
Gere novamente e ajuste o Sumário.
1143
9.
a.
Selecione o campo Sumário.
b.
Selecione Tools→Book Building→Create Table of Contents.
c.
Libere o Sumário selecionando Tools→Field Editing→Unprotect.
d.
Apague a primeira linha do Sumário, que é uma entrada para o próprio Sumário.
Salve o documento no formato nativo do Applixware Words para facilitar uma edição posterior caso seja necessário.
10. Imprima (“Print”) o documento para um arquivo no formato Postscript.
G.3.5. Arquivos em texto puro Diversos arquivos são distribuídos como texto puro, para serem lidos durante o processo de instalação. O arquivo INSTALL corresponde ao Capítulo 14, com pequenas alterações para levar em conta a diferença de contexto. Para recriar o arquivo, torne o diretório doc/src/sgml o diretório corrente, e execute gmake INSTALL. Isto cria o arquivo INSTALL.html que pode ser salvo como texto utilizando o Netscape Navigator e colocado no lugar do arquivo existente. O Netscape parece oferecer a melhor qualidade na conversão de HTML em texto (melhor que o lynx e o w3m). O arquivo HISTORY pode ser criado de forma semelhante, utilizando o comando gmake HISTORY. Para o arquivo src/test/regress/README o comando é gmake regress_README.
G.3.6. Verificação da sintaxe A geração da documentação pode ser demorada. Entretanto, existe um método para verificar apenas se a sintaxe dos arquivos de documentação está correta que só leva alguns segundos: doc/src/sgml$ gmake check
G.4. Criação da documentação O SGML e o DocBook não sofrem o mal do número excessivo de ferramentas de código aberto para criação de páginas. O conjunto de ferramentas mais comum é o editor Emacs/XEmacs com o modo apropriado de edição. Em alguns sistemas estas ferramentas fazem parte da instalação típica completa.
G.4.1. Emacs/PSGML O PSGML é o modo de editar documentos SGML mais comum e mais poderoso. Quando configurado de forma apropriada, permite utilizar o Emacs para inserir marcas e verificar a coerência da marcação. Também pode ser utilizado para o HTML. Visite o sítio na Web do PSGML (http://www.lysator.liu.se/projects/about_psgml.html) para baixar os arquivos, obter as instruções de instalação, e ver a documentação detalhada. Existe uma coisa importante a ser observada com relação ao PSGML: o autor assume que o diretório principal da DTD do SGML na sua máquina é /usr/local/lib/sgml. Se, como acontece nos exemplos deste capítulo, for utilizado /usr/local/share/sgml, isto deve ser compensado, seja definindo a variável de ambiente SGML_CATALOG_FILES, ou personalizando a instalação do PSGML (o manual explica como fazer). Adicione o que se segue ao seu arquivo de ambiente ~/.emacs (ajustando os nomes dos caminhos conforme apropriado para o seu sistema): ; ********** for SGML mode (psgml) (setq (setq (setq (setq (setq (setq (setq (setq
sgml-omittag t) sgml-shorttag t) sgml-minimize-attributes nil) sgml-always-quote-attributes t) sgml-indent-step 1) sgml-indent-data t) sgml-parent-document nil) sgml-default-dtd-file "./reference.ced")
1144
(setq sgml-exposed-tags nil) (setq sgml-catalog-files '("/usr/local/share/sgml/catalog")) (setq sgml-ecat-files nil) (autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t )
e no mesmo arquivo adicione uma entrada para SGML na definição (existente) de auto-mode-alist: (setq auto-mode-alist '(("\\.sgml$" . sgml-mode) ))
Atualmente, cada arquivo fonte SGML possui o seguinte bloco no seu final:
Isto define vários parâmetros do modo de edição mesmo que o arquivo ~/.emacs não esteja definido mas, por azar, uma vez que foram seguidas as instruções de instalação acima, então o caminho do catálogo não corresponde ao local na sua máquina. Por isso pode ser necessário desabilitar as variáveis locais: (setq inhibit-local-variables t)
A distribuição do PostgreSQL inclui o arquivo de definições DTD analisado reference.ced. Ao utilizar o PSGML, podemos acabar descobrindo que uma maneira confortável de trabalhar com os arquivos separados das partes do livro é inserir uma declaração DOCTYPE apropriada ao editar. Por exemplo, ao trabalhar com o fonte deste arquivo, que é um capítulo do apêndice, o documento pode ser especificado como uma instância do “appendix” do documento DocBook fazendo a primeira linha parecida com:
Isto permite que qualquer coisa e todas as coisas que leiam SGML o façam direito, e que o documento possa ser verificado com nsgmls -s docguide.sgml; mas esta linha precisa ser removida antes de ser gerado o conjunto completo da documentação.
G.4.2. Outros modos do Emacs O GNU Emacs é disponibilizado com um modo SGML diferente, que não é tão poderoso quanto o PSGML, mas é menos confuso e mais leve. Oferece, também, realce da sintaxe (bloqueio de fonte), que pode ser muito útil. Norm Walsh oferece um modo principal específico para DocBook (http://nwalsh.com/emacs/docbookide/index.html), que também possui bloqueio de fonte além de várias funcionalidades para reduzir a digitação.
1145
G.5. Guia de estilo G.5.1. Páginas de referência As páginas de referência devem seguir a disposição padrão. Isto permite os usuários encontrarem as informações desejadas mais rapidamente e, também, encoraja os escritores a documentar todos os aspectos relevantes do comando. A consistência não é desejada apenas entre as páginas de referência do PostgreSQL, mas também com as páginas de referência disponibilizadas pelo sistema operacional e por outros pacotes. Para esse fim, as diretrizes descritas a seguir foram desenvolvidas. Em sua maior parte estas diretrizes são coerentes com as diretrizes semelhantes estabelecidas por vários sistemas operacionais. As páginas de referência que descrevem comandos executáveis devem conter as seguintes seções, nesta ordem. As seções que não se aplicam podem ser omitidas. Seções adicionais de nível mais alto devem ser utilizadas apenas em circunstâncias especiais; geralmente esta informação pertence à seção “Utilização”. Nome Esta seção é gerada automaticamente. Contém o nome do comando e um resumo de meia-sentença de sua funcionalidade. Sinopse Esta seção contém o diagrama da sintaxe do comando. Normalmente a sinopse não deve relacionar todas as opções de linha de comando; isto é feito abaixo. Em vez disto, devem ser relacionados os componentes principais da linha de comando, tal como a destinação dos arquivos de entrada e de saída. Descrição Vários parágrafos explicando o que o comando faz. Opções Uma lista descrevendo cada opção de linha de comando. Havendo muitas opções, podem ser usadas subseções. Status de saída Se o programa utilizar zero para bem-sucedido e diferente de zero para falha, então isto não precisa ser documentado. Se houver um significado por trás dos códigos de retorno diferentes de zero, estes devem ser descritos aqui. Utilização Descreva todas as sub-linguagens ou interfaces em tempo de execução do programa. Se o programa não for interativo, normalmente esta seção pode ser omitida. Senão, esta seção engloba a descrição de todas as funcionalidades em tempo de execução. Se for apropriado, devem ser utilizadas subseções. Ambiente Relacione todas as variáveis de ambiente que o programa possa utilizar. Tente ser completo; mesmo variáveis que pareçam triviais, como SHELL, podem ser de interesse do usuário. Arquivos Relacione todos os arquivos que o programa possa acessar implicitamente, ou seja, não relacione os arquivos de entrada e de saída especificados na linha de comando, mas relacione os arquivos de configuração, etc. Diagnósticos Explique qualquer saída não usual que o programa possa produzir. Evite relacionar todas as mensagens de erro possíveis; isto dá muito trabalho e possui pouca utilidade prática. Mas se, por exemplo, as mensagens de erro possuem um formato padrão que o usuário pode analisar, este é o lugar para que isto seja explicado. Notas Tudo que não se adequa aos outros lugares, mas em particular erros, problemas na implementação, considerações sobre segurança, e questões de compatibilidade.
1146
Exemplos Exemplos Histórico Havendo marcos relevantes na história do programa, estes devem ser descritos aqui. Normalmente esta seção pode ser omitida. Veja também Referências cruzadas, relacionadas na seguinte ordem: outras páginas de referência de comandos do PostgreSQL, páginas de referência de comandos SQL do PostgreSQL, citação dos manuais do PostgreSQL, outras páginas de referência (por exemplo, sistema operacional, outros pacotes) outra documentação. Os itens do mesmo grupo devem estar em ordem alfabética. As páginas de referência contendo os comandos SQL devem conter as seguintes seções: Nome, Sinopse, Descrição, Parâmetros, Saídas, Notas, Exemplos, Compatibilidade, Histórico, Veja Também. A seção sobre Parâmetros é como a seção Opções, mas há maior liberdade sobre que cláusulas do comando podem ser relacionadas. A seção Saídas somente é necessária quando o comando retorna algo diferente da marca padrão de comando completo. A seção Compatibilidade deve explicar a extensão da conformidade 4 do comando com o padrão SQL, ou informar com que outro sistema de banco de dados é compatível. A seção Veja Também dos comandos SQL deve relacionar os comandos SQL antes da referência cruzada com os programas.
Notas 1. man pages — Unix Manual Page - Uma parte da extensa documentação on-line do Unix. FOLDOC - Free On-Line Dictionary of Computing (http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=man+pages) (N. do T.) 2. Para gerar esta documentação houve necessidade de instalar também: libc6-dev, openjade, jadetex e opensp. (N. do T.) 3. Ou seja, para gerar a documentação HTML com índice no final, a documentação HTML precisa ser gerada duas vezes. (N. do T.) 4. conformidade — atributos do software que o tornam consonante com padrões ou convenções relacionadas à portabilidade. NBR 13596/1996, Tecnologia da Informação - Avaliação de produto de software Características de qualidade e diretrizes para o seu uso, ABNT, Rio de Janeiro. (N. do T.)
1147
Bibliografia Referências e artigos selecionados para o SQL e para o PostgreSQL. Alguns relatórios oficiais e técnicos da equipe original de desenvolvimento do POSTGRES estão disponíveis no sítio na Web do Departamento de Ciência da Computação da Universidade da Califórnia em Berkeley. (http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/papers/)
Livros de Referência sobre o SQL Judith Bowman, Sandra Emerson, e Marcy Darnovsky, The Practical SQL Handbook: Using Structured Query Language, Third Edition, Addison-Wesley, ISBN 0-201-44787-8, 1996. C. J. Date e Hugh Darwen, A Guide to the SQL Standard: A user's guide to the standard database language SQL, Fourth Edition, Addison-Wesley, ISBN 0-201-96426-0, 1997. C. J. Date, An Introduction to Database Systems, Volume 1, Sixth Edition, Addison-Wesley, 1994. Ramez Elmasri e Shamkant Navathe, Fundamentals of Database Systems, 3rd Edition, Addison-Wesley, ISBN 0-805-31755-4, August 1999. Jim Melton e Alan R. Simon, Understanding the New SQL: A complete guide, Morgan Kaufmann, ISBN 155860-245-3, 1993. Jeffrey D. Ullman, Principles of Database and Knowledge: Base Systems, Volume 1, Computer Science Press, 1988.
Documentação específica do PostgreSQL Stefan Simkovics, Enhancement of the ANSI SQL Implementation of PostgreSQL, Department of Information Systems, Vienna University of Technology, November 29, 1998. Discusses SQL history and syntax, and describes the addition of INTERSECT and EXCEPT constructs into PostgreSQL. Prepared as a Master's Thesis with the support of O. Univ. Prof. Dr. Georg Gottlob and Univ. Ass. Mag. Katrin Seyr at Vienna University of Technology. A. Yu e J. Chen, The POSTGRES Group, The Postgres95 User Manual, University of California, Sept. 5, 1995. Zelaine Fong, The design and implementation of the POSTGRES query optimizer (http://s2kftp.CS.Berkeley.EDU:8000/postgres/papers/UCB-MS-zfong.pdf), University of California, Berkeley, Computer Science Department.
Conferências e Artigos Nels Olson, Partial indexing in POSTGRES: research project, University of California, UCB Engin T7.49.1993 O676, 1993. L. Ong e J. Goh, “A Unified Framework for Version Modeling Using Production Rules in a Database System”, ERL Technical Memorandum M90/33, University of California, April, 1990. L. Rowe e M. Stonebraker, “The POSTGRES data model (http://s2kftp.CS.Berkeley.EDU:8000/postgres/papers/ERL-M87-13.pdf)”, Proc. VLDB Conference, Sept. 1987. P. Seshadri e A. Swami, “Generalized Partial Indexes (http://simon.cs.cornell.edu/home/praveen/papers/partindex.de95.ps.Z) ”, Proc. Eleventh International Conference on Data Engineering, 6-10 March 1995, IEEE Computer Society Press, Cat. No.95CH35724, 1995, 420-7. M. Stonebraker e L. Rowe, “The design of POSTGRES (http://s2kftp.CS.Berkeley.EDU:8000/postgres/papers/ERL-M85-95.pdf)”, Proc. ACM-SIGMOD Conference on Management of Data, May 1986.
1148
M. Stonebraker, E. Hanson, e C. H. Hong, “The design of the POSTGRES rules system”, Proc. IEEE Conference on Data Engineering, Feb. 1987. M. Stonebraker, “The design of the POSTGRES storage system (http://s2kftp.CS.Berkeley.EDU:8000/postgres/papers/ERL-M87-06.pdf)”, Proc. VLDB Conference, Sept. 1987. M. Stonebraker, M. Hearst, e S. Potamianos, “A commentary on the POSTGRES rules system (http://s2kftp.CS.Berkeley.EDU:8000/postgres/papers/ERL-M89-82.pdf)”, SIGMOD Record 18(3), Sept. 1989. M. Stonebraker, “The case for partial indexes (http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/papers/ERLM89-17.pdf)”, SIGMOD Record 18(4), Dec. 1989, 4-11. M. Stonebraker, L. A. Rowe, e M. Hirohama, “The implementation of POSTGRES (http://s2kftp.CS.Berkeley.EDU:8000/postgres/papers/ERL-M90-34.pdf)”, Transactions on Knowledge and Data Engineering 2(1), IEEE, March 1990. M. Stonebraker, A. Jhingran, J. Goh, e S. Potamianos, “On Rules, Procedures, Caching and Views in Database Systems (http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/papers/ERL-M90-36.pdf)”, Proc. ACMSIGMOD Conference on Management of Data, June 1990.
1149
autenticação do cliente tempo esgotado durante, 269 auto-incremento (Veja serial) autocommit, 246
Índice Remissivo
3
Simbolos
3
$, 49 *, 91 .pgpass, 368 3
B
3
B-tree (Veja indice) banco de dados, 295 criação, 23 privilégio para criar, 293 banco de dados hierárquico, 27 banco de dados orientado a objeto, 27 banco de dados relacional, 27 BEGIN, 683 BETWEEN, 134 biblioteca compartilhada, 257, 522 bigint, 46, 98 bigserial, 100 BLOB (Veja large object) bloqueio, 234 monitoramento, 330 booleano operadores (Veja operadores, lógicos) tipo de dado, 114 boot inicializar o servidor durante, 265 BSD/OS biblioteca compartilhada, 523 configuração do IPC, 285 bytea, 105 in JDBC, 428 in libpq, 357
3
A
3
ABORT, 659 aggregate function user-defined, 540 agrupamento, 89 bancos de dados (Veja agrupamento de bancos de dados) agrupamento de bancos de dados, 27, 264 aliás na cláusula FROM, 86 na lista de seleção, 91 para nome de tabela em consulta, 31 ALL, 209, 212 ALTER AGGREGATE, 660 ALTER CONVERSION, 661 ALTER DATABASE, 662 ALTER DOMAIN, 664 ALTER FUNCTION, 666 ALTER GROUP, 667 ALTER LANGUAGE, 668 ALTER OPERATOR CLASS, 669 ALTER SCHEMA, 670 ALTER SEQUENCE, 671 ALTER TABLE, 673 ALTER TRIGGER, 677 ALTER USER, 293, 678 ANALYZE, 316, 681 AND (operador), 133 any, 130, 209, 212 anyarray, 130 anyelement, 130 apóstrofo escape, 43 area de dados (Veja agrupamento de bancos de dado) array constante, 120 of user-defined type, 544 resolução do tipo do resultado, 221 aspas e identificadores, 41 atividade do banco de dados monitoramento, 325 atualização, 80, 251, 323 autenticação de cliente, 299
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
C C, 343, 408 cadeia binária comprimento, 155 concatenação, 154 cadeia de bits constante, 45 tipo de dado, 119 cadeia de caracteres comprimento, 140 concatenação, 140 constante, 43 tipos de dado, 101 caixa (tipo de dado), 116 caminho para esquemas, 278 caminho (tipo de dado), 116 3
3
3
3
3
3
3
3
3
3
3
3
3
1150
caminho de classe, 423 caminho de procura, 74 corrente, 198 canceling SQL command, 360 carimbo do tempo, 107, 110 carimbo do tempo com zona horária, 107, 110 carimbo do tempo sem zona horária, 107, 110 carregamento dinâmico, 514 CASCADE ação da chave estrangeira, 64 com DROP, 76 CASE, 196 resolução do tipo do resultado, 221 catálogo do sistema esquema, 75 char, 101 character, 101 character varying, 101 chave estrangeira, 35, 62 chave primária, 62 CHECKPOINT, 685 cid, 128 cidr, 118 classe de operadores, 226 CLASSPATH, 423 CLOSE, 686 CLUSTER, 687 clusterdb, 844 cmax, 58 cmin, 57 COALESCE, 197 coluna, 27, 56 adicionar, 70 coluna do sistema, 57 mudar nome, 71 remover, 71 col_description, 198 comentário sobre os objetos do banco de dados, 198 no SQL, 47 COMMENT, 689 COMMIT, 692 comparação de linhas, 212 operador, 134 compiling libpq applications, 369 comprimento de uma cadeia de caracteres (Veja cadeia de caracteres, comprimento) de cadeias binárias (Veja cadeias binárias, comprimento) de cadeia de caracteres (Veja cadeia de caracteres, comprimento) configuração, 252
do servidor, 267 do servidor funções, 198 conjunto de caracteres, 280, 310 conjunto diferença, 92 conjunto interseção, 92 conjunto união, 92 conjunção, 133 constante, 43 consulta, 29, 82 contar, 32 conversão de tipo, 46, 51 COPY, 29, 693 with libpq, 362 CREATE AGGREGATE, 699 CREATE CAST, 702 CREATE CONSTRAINT, 705 CREATE CONVERSION, 706 CREATE DATABASE, 295, 708 CREATE DOMAIN, 710 CREATE FUNCTION, 712 CREATE GROUP, 717 CREATE INDEX, 718 CREATE LANGUAGE, 721 CREATE OPERATOR, 723 CREATE OPERATOR CLASS, 726 CREATE RULE, 729 CREATE SCHEMA, 731 CREATE SEQUENCE, 733 CREATE TABLE, 27, 736 CREATE TABLE AS, 745 CREATE TRIGGER, 746 CREATE TYPE, 749 CREATE USER, 292, 754 CREATE VIEW, 756 createdb, 23, 296, 846 createlang, 848 crypt, 304 thread safety, 368 cstring, 130 ctid, 58, 562 currval, 195 cursor no PL/pgSQL, 600 círculo, 117 códigos de erro relação, 1004 cópias de segurança, 320
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
D dado binário, 105 funções, 154 data, 107, 109 constantes, 111 corrente, 179 3
3
3
3
3
3
1151
formato da saída, 112 (Veja também formatação) data type user-defined, 541 DataSource, 449 DBI, 621 DEALLOCATE, 758 decimal (Veja numérico) DECLARE, 759 DELETE, 33, 80, 762 desvio padrão, 208 Digital UNIX (Veja Tru64 UNIX) dirty read, 232 disjunção, 133 disk drive, 335 DISTINCT, 29, 91 dono, 293 DROP AGGREGATE, 763 DROP CAST, 764 DROP CONVERSION, 765 DROP DATABASE, 298, 766 DROP DOMAIN, 767 DROP FUNCTION, 768 DROP GROUP, 769 DROP INDEX, 770 DROP LANGUAGE, 771 DROP OPERATOR, 772 DROP OPERATOR CLASS, 773 DROP RULE, 774 DROP SCHEMA, 775 DROP SEQUENCE, 776 DROP TABLE, 28, 777 DROP TRIGGER, 778 DROP TYPE, 779 DROP USER, 292, 780 DROP VIEW, 781 dropdb, 298, 853 droplang, 855 duplicadas, 29, 91 dynamic loading, 280 dígitos significativos, 279
environment variable, 367 ereport, 980 error message, 349 escalar (Veja expressão) escaping strings, 357 escolha de campo, 50 espaço de tempo, 107 espaço em disco, 315 esquema, 72, 295 corrente, 74, 198 criação, 73 público, 74 remover, 73 esquema de informações, 468 estatísticas, 326 do planejador, 243, 316 estendendo o SQL, 505 estilo da data, 279 EXCEPT, 92 exclusão, 80 EXECUTE, 783 EXISTS, 209 EXPLAIN, 240, 784 expressão ordem de avaliação, 53 sintaxe, 49 expressão condicional, 196 expressão de tabela, 82 expressão de valor, 49 expressão regular, 157, 158 (Veja também correspondência com padrão) expressões regulares, 281
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
F
3
3
3
3
3
3
3
3
3
3
3
E
falso, 114 FAQ, 16 fast path, 361 FETCH, 787 float4 (Veja real) float8 (Veja precisão dupla) formatação, 167 FreeBSD biblioteca compartilhada, 523 configuração do IPC, 286 3
3
3
3
3
ECPG, 408, 859 elog, 980 in PL/Perl, 621 in PL/Python, 624 in PL/Tcl, 617 embedded SQL in C, 408 END, 782 endereço MAC (Veja macaddr) 3
3
3
3
3
3
3
3
3
3
FROM faltando, 281 fsync, 272, 333 função, 133 chamada, 51 definida pelo usuário, 506 em C, 507 3
3
3
3
3
3
3
1152
em SQL, 507 interna, 513 na cláusula FROM, 87 polimórfica, 506 resolução do tipo na chamada, 219 função de agregação, 32 chamada, 51 nativa, 208 função de tabela, 87 funções polimórficas, 506
I
3
3
ID de transação reinício, 317 ident, 305 identificador comprimento, 41 sintaxe de, 40 identificador de objeto tipo de dado, 128 impasse, 236 tempo esgotado durante, 281 IN, 209, 212 index for user-defined data type, 548 parcial, 227 indice, 50, 223 B-tree, 224 bloqueios, 238 examinar a utilização, 229 em expressões, 226 hash, 224 multicoluna, 225 R-tree, 224 único, 225 inet (tipo de dado), 117 initdb, 264, 903 initlocation, 298, 905 input function, 541 of a data type, 541 INSERT, 28, 79, 795 inserção, 79 instalação, 249 instr, 608 int2 (Veja smallint) int4 (Veja integer) int8 (Veja bigint) integer, 98 integridade referencial, 35, 62 inteiro, 46 internal, 130 INTERSECT, 92 intervalo, 107, 111 ipcclean, 906 IRIX biblioteca compartilhada, 523 IS NULL, 282 isolamento da transação, 232
3
3
3
3
3
3
3
3
3
3
3
3
3
3
G
3
3
gatilho, 575 argumentos para funções de gatilho, 575 no PL/pgSQL, 604 gatilhos em C, 576 GEQO (Veja otimização genética de comandos) get_bit, 154 get_byte, 154 global data in PL/Python, 623 in PL/Tcl, 615 GRANT, 293, 791 GROUP BY, 32, 89 grupo, 293 3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
H
3
3
hash (Veja indice) has_database_privilege, 198 has_function_privilege, 198 has_language_privilege, 198 has_schema_privilege, 198 has_table_privilege, 198 HAVING, 32, 90 herança, 37, 281 história do PostgreSQL, 15 hora, 107, 110 constantes, 111 corrente, 179 formato da saída, 112 (Veja também formatação) hora com zona horária, 107, 110 hora sem zona horária, 107, 110 host name, 343 HP-UX biblioteca compartilhada, 523 configuração do IPC, 286
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
J Java, 423 JDBC, 423 3
3
1153
JNDI, 452 junção, 30, 83 auto, 31 controle da ordem, 245 cruzada, 83 direita, 84 esquerda, 84 externa, 31, 83 natural, 84 junção cruzada, 83 junção direita, 84 junção esquerda, 84 junção externa, 83 junção natural, 84
lo_tell, 379 lo_unlink, 379 lo_write, 378 lseg, 116
3
3
3
3
3
3
3
3
3
3
M
3
3
3
macaddr (tipo de dado), 119 MacOS X biblioteca compartilhada, 523 configuração do IPC, 287 MANPATH, 258 manutenção, 315 matriz, 120 construtor, 52 MD5, 304 memory context in SPI, 644 memória compartilhada, 284 monitoramento atividade do banco de dados, 325 MOVE, 802 MVCC, 232 máximo, 32 média, 32, 208 mínimo, 32 3
3
3
3
3
3
3
3
3
3
3
3
3
3
K
3
Kerberos, 304 3
3
3
L
3
language_handler, 130 large object, 377 in pgctl, 385 in JDBC, 428 laço no PL/pgSQL, 597 ldconfig, 258 letras maiúsculas e minúsculas nos comandos SQL, 41 libpgtcl, 385 libpq, 343 libpq-fe.h, 343, 348 libpq-int.h, 348, 369 LIKE, 155 LIMIT, 94 linguagem procedural, 581 linha, 27, 56 Linux biblioteca compartilhada, 523 configuração do IPC, 286 LISTEN, 797 LOAD, 798 localização, 265, 308 LOCK, 235, 799 log de transação (Veja WAL) log do servidor, 275 manutenção do arquivo de log, 318 lo_close, 379 lo_creat, 378 lo_export, 378, 379 lo_import, 378, 379 lo_lseek, 379 lo_open, 378 lo_read, 378 3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
N negação, 133 NetBSD biblioteca compartilhada, 524 configuração do IPC, 286 nextval, 195 nome não qualificado, 74 sintaxe de, 40 nome não qualificado, 74 nonblocking connection, 345, 358 nonrepeatable read, 232 NOT (operador), 133 NOT IN, 209, 212 notice processing in libpq, 366 notice processor, 366 notice receiver, 366 NOTIFY, 803 in libpq, 361 in pgtcl, 396 null value in libpq, 356 in PL/Perl, 620 in PL/Python, 623 nullif, 197 numérica, 46 constante, 45 3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
1154
numérico (tipo de dado), 99 níveis de isolamento da transação serializável, 234 nível de isolamento da transação, 232, 279 read committed, 233 3
3
3
3
3
password file, 368 PATH, 258 Perl, 620 permissão (Veja privilégio) PGconn, 343 PGDATA, 264 3
3
3
3
O
3
objetos grandes cópias de segurança, 322 obj_description, 198 OFFSET, 94 oid, 128 coluna, 57 in libpq, 357 ONLY, 83 opaque, 130 OpenBSD biblioteca compartilhada, 524 configuração do IPC, 286 OpenSSL, 255 (Veja também SSL) operador, 133 chamada, 50 lógico, 133 precedência, 47 resolução do tipo na chamada, 216 sintaxe, 46 operator user-defined, 544 operator class, 549 operação de conjunto, 92 OR (operador), 133 Oracle migrar PL/SQL para PL/pgSQL, 605 ordenação, 93 ORDER BY, 29, 93 ordering operator, 553 orrespondência com padrão, 155 otimização genética de comandos, 274 output function, 541 of a data type, 541 overlay, 140 overloading operators, 544 3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
PGresult, 351 pgtcl, 385 pgtclsh, 877 pgtksh, 878 pg_aggregate, 927 pg_am, 929 pg_amop, 930 pg_amproc, 930 pg_attrdef, 930 pg_attribute, 930 pg_cast, 932 pg_class, 932 pg_config, 861 with libpq, 369 pg_conndefaults, 389 pg_connect, 387 pg_constraint, 934 pg_controldata, 907 pg_conversion, 935 pg_conversion_is_visible, 198 pg_ctl, 265, 908 pg_database, 297, 935 pg_depend, 936 pg_description, 937 pg_disconnect, 388 pg_dump, 863 pg_dumpall, 868 uso durante a atualização, 251 pg_exec, 390 pg_execute, 394 pg_function_is_visible, 198 pg_get_constraintdef, 198 pg_get_expr, 198 pg_get_indexdef, 198 pg_get_ruledef, 198 pg_get_triggerdef, 198 pg_get_userbyid, 198 pg_get_viewdef, 198 pg_group, 938 pg_hba.conf, 299 pg_ident.conf, 305 pg_index, 938 pg_indexes, 951 pg_inherits, 939 pg_language, 939 pg_largeobject, 940 pg_listen, 396 pg_listener, 940 3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
P
3
3
palavra chave relação, 1019 sintaxe de, 40 PAM, 255, 306 parâmetro sintaxe, 49 password autenticação, 304 3
3
3
3
3
3
3
3
3
3
4
4
4
4
1155
pg_locks, 951 pg_lo_close, 400 pg_lo_creat, 398 pg_lo_export, 407 pg_lo_import, 406 pg_lo_lseek, 403 pg_lo_open, 399 pg_lo_read, 401 pg_lo_tell, 404 pg_lo_unlink, 405 pg_lo_write, 402 pg_namespace, 941 pg_on_connection_loss, 397 pg_opclass, 942 pg_opclass_is_visible, 198 pg_operator, 942 pg_operator_is_visible, 198 pg_proc, 943 pg_restore, 871 pg_result, 391 pg_rewrite, 944 pg_rules, 952 pg_select, 393 pg_settings, 953 pg_shadow, 945 pg_statistic, 244, 945 pg_stats, 244, 953 pg_tables, 954 pg_table_is_visible, 198 pg_trigger, 946 pg_type, 947 pg_type_is_visible, 198 pg_user, 955 pg_views, 955 phantom read, 232 PIC, 522 PID determining PID of server process in libpq, 349 PL/Perl, 620 PL/PerlU, 622 PL/pgSQL, 583 PL/Python, 623 PL/SQL (Oracle) migrar para PL/pgSQL, 605 PL/Tcl, 614 plano de comando, 240 polígono, 117 ponto, 116 ponto de controle, 334 ponto flutuante, 100 exibição, 279 pool de conexão no JDBC, 449 port, 344 porta, 269 4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
POSTGRES, 15 Postgres95, 15 postgresql.conf, 267 PQbackendPID, 349 PQbinaryTuples, 355 with COPY, 363 PQclear, 353 PQcmdStatus, 356 PQcmdTuples, 356 PQconndefaults, 347 PQconnectdb, 343 PQconnectPoll, 345 PQconnectStart, 345 PQconsumeInput, 359 PQdb, 348 PQendcopy, 365 PQerrorMessage, 349 PQescapeBytea, 357 PQescapeString, 357 PQexec, 350 PQexecParams, 350 PQexecPrepared, 351 PQfformat, 354 with COPY, 363 PQfinish, 347 PQflush, 361 PQfmod, 355 PQfn, 361 PQfname, 354 PQfnumber, 354 PQfreemem, 358 PQfsize, 355 PQftable, 354 PQftablecol, 354 PQftype, 355 PQgetCopyData, 364 PQgetisnull, 356 PQgetlength, 356 PQgetline, 364 PQgetlineAsync, 364 PQgetResult, 359 PQgetssl, 350 PQgetvalue, 355 PQhost, 348 PQisBusy, 360 PQisnonblocking, 360 PQmakeEmptyPGresult, 353 PQnfields, 354 with COPY, 363 PQnotifies, 362 PQntuples, 354 PQoidStatus, 357 PQoidValue, 357 PQoptions, 348 PQparameterStatus, 349 PQpass, 348 4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
1156
PQport, 348 PQprint, 356 PQprotocolVersion, 349 PQputCopyData, 363 PQputCopyEnd, 363 PQputline, 365 PQputnbytes, 365 PQrequestCancel, 360 PQreset, 347 PQresetPoll, 347 PQresetStart, 347 PQresStatus, 352 PQresultErrorField, 352 PQresultErrorMessage, 352 PQresultStatus, 351 PQsendQuery, 358 PQsendQueryParams, 358 PQsendQueryPrepared, 359 PQsetdb, 345 PQsetdbLogin, 344 PQsetErrorVerbosity, 366 PQsetnonblocking, 360 PQsetNoticeProcessor, 366 PQsetNoticeReceiver, 366 PQsocket, 349 PQstatus, 348 PQtrace, 366 PQtransactionStatus, 349 PQtty, 348 PQunescapeBytea, 358 PQuntrace, 366 PQuser, 348 precisão dupla, 100 preload_libraries, 271 preparação do comando no PL/pgSQL, 583 PREPARE, 805 PreparedStatement, 425 preparing a query in PL/Python, 624 in PL/Tcl, 616 privilege with rules, 571 with views, 571 privilégio, 72, 293 consulta, 199 para esquemas, 75 procedural language handler for, 990 programa postgres, 913 ps para monitorar atividade, 325 psql, 24, 879 Python, 623 pão fatiado (Veja TOAST) 4
Q
4
query tree, 555 quote_ident, 142 uso no PL/pgSQL, 593 quote_literal, 142 uso no PL/pgSQL, 593 4
4
4
4
4
4
4
4
4
4
4
4
R
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
R-tree (Veja indice) range table, 555 real, 100 record, 130 rectangle, 116 rede tipos de dado, 117 referência a coluna, 49 regclass, 128 regoper, 128 regoperator, 128 regproc, 128 regprocedure, 128 regtype, 128 REINDEX, 807 reindexação, 318 relação, 27 RESET, 809 RESTRICT ação da chave estrangeira, 64 com DROP, 76 restrição, 59 adicionar, 71 chave estrangeira, 62 chave primária, 62 nome, 59 NOT NULL, 60 remover, 71 unicidade, 61 verificação, 59 restrição de não-nulo, 60 restrição de unicidade, 61 restrição de verificação, 59 ResultSet, 425 REVOKE, 293, 810 ROLLBACK, 812 rule, 555 and views, 556 for DELETE, 562 for INSERT, 562 for SELECT, 557 compared with triggers, 572 for UPDATE, 562 rótulo (Veja aliás) 4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
1157
SPI_exec, 628 SPI_execp, 631 SPI_finish, 627 SPI_fname, 638 SPI_fnumber, 639 SPI_freeplan, 654 SPI_freetuple, 652 SPI_freetuptable, 653 SPI_getbinval, 641 SPI_getrelname, 644 SPI_gettype, 642 SPI_gettypeid, 643 SPI_getvalue, 640 spi_lastoid, 617 SPI_modifytuple, 651 SPI_palloc, 645 SPI_pfree, 647 SPI_prepare, 630 SPI_repalloc, 646 SPI_saveplan, 637 ssh, 290 SSL, 270, 290 with libpq, 344, 350 START TRANSACTION, 835 Statement, 425 string (Veja cadeia de caracteres) subconsulta, 32, 52, 87, 209 substring, 140, 154, 157 superusuário, 24, 293 syslog, 275
S
4
4
savepoint, 333 SCO OpenServer configuração do IPC, 287 search_path, 74, 278 segmento de linha, 116 SELECT, 29, 82, 813 lista de seleção, 91 SELECT INTO, 825 in PL/pgSQL, 592 semáforos, 284 senha, 293 do superusuário, 265 seqüência, 195 e tipo serial, 100 serial, 100 serial4, 100 serial8, 100 SET, 198, 826 SET CONSTRAINTS, 829 SET SESSION AUTHORIZATION, 830 SET TRANSACTION, 831 SETOF, 507 setval, 195 set_bit, 154 set_byte, 154 SHMMAX, 285 SHOW, 198, 833 shutdown, 289 SIGHUP, 268, 302, 306 SIGINT, 289 SIGQUIT, 289 SIGTERM, 289 SIMILAR TO, 157 simultaneidade, 232 sintaxe SQL, 40 smallint, 98 sobrecarga funções, 539 Solaris biblioteca compartilhada, 524 configuração do IPC, 287 soma, 32 SOME, 209, 212 SPI, 625 SPI_connect, 626 SPI_copytuple, 648 SPI_copytupledesc, 649 SPI_copytupleintoslot, 650 SPI_cursor_close, 636 SPI_cursor_fetch, 634 SPI_cursor_find, 633 SPI_cursor_move, 635 SPI_cursor_open, 632 4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
T
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
tabela, 27, 56 criação, 56 modificar, 70 mudar nome, 72 remover, 57 tableoid, 57 target list, 556 Tcl, 385, 614 TCP/IP, 265, 268 template0, 296 template1, 295, 296 tempo esgotado autenticação do cliente, 269 impasse, 281 termo, 40 teste, 337 teste de regressão, 256 testes de regressão, 337 text, 101 threads com JDBC, 448 with libpq, 368 4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
1158
tid, 128 tipo (Veja tipo de dado) polimórfico, 506 tipo base, 505 tipo composto, 505 tipo de dado, 96 base, 505 categoria, 216 composto, 505 conversão, 215 conversão de tipo, 51 numérico, 98 organização interna, 515 tipos de dado constante, 46 tipos polimórficos, 506 TOAST, 377 and user-defined types, 544 to_char, 167 transação, 36 transação somente para leitura, 279 trigger, 130 in PL/Python, 623 in PL/Tcl, 617 compared with rules, 572 Tru64 UNIX biblioteca compartilhada, 524 TRUNCATE, 836 trusted PL/Perl, 621
mudar, 71 varchar, 101 variância, 208 varredura de índice, 273 varredura seqüencial, 273 verdade, 114 versão, 25, 198 compatibilidade, 323 view implementation through rules, 556 updating, 566 visão, 35 void, 130
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
W
4
WAL, 333 WHERE, 88 4
4
4
4
4
4
X
4
xid, 128 xmax, 58 xmin, 57 4
4
4
4
4
4
4
4
4
4
Z zona horária, 113, 279 abreviaturas, 1013 Australiana, 279 conversão, 178 4
4
4
4
4
4
U UNION, 92 resolução do tipo do resultado, 221 Unix domain socket, 343 UnixWare biblioteca compartilhada, 524 configuração do IPC, 287 UNLISTEN, 837 UPDATE, 33, 80, 838 usuário, 292 corrente, 198 usuário postgres, 264 utilização de disco, 331 4
4
4
4
4
4
4
4
4
4
4
4
4
V vacuum, 315, 840 vacuumdb, 900 valor nulo em restrições de verificação, 60 no DISTINCT, 92 valor padrão, 58 valor padrão, 58 4
4
4
4
4
4
4
1159