History Tables – pt 1
Boa noite pessoal.
Uns posts atrás falei sobre uma função que permitisse e criasse automaticamente as regras e tabelas para armazenamento de registros históricos no PostGIS.
Bem, aqui vão algumas questões: O PostgreSQL nos permite lidar com este tipo de situação de duas formas: Rules e/ou Triggers.
No caso do nosso projetinho, foram utilizadas rules para lidar com o que precisamos fazer. Bem, o que deve ter um histórico de feições?
Primeiramente ele deve guardar todas as feições inseridas, atualizadas e deletadas, bem como a data, hora, nome do usuário que realizou a alteração, e uma coisa interessante, qual é a versão atual daquela feição. Desta forma podemos rastrear quais foram as alterações históricas de cada versão e caso preciso, achar a versão mais apropriada e restaurá-la para o banco de dados principal.
Além disso, temos um registro histórico de fato. Sabemos todas as alterações de uma feição. É possível entender como um lote mudou, por exemplo, ou como um animal rastreado por GPS está se movimentando. Outra coisa bacana, podemos saber como está evoluindo a cobertura vegetal de uma determinada região. Aumentou? Diminuiu? Não existe ambiguidade ou imperícia. Tudo pode ser restaurado e analisado de acordo com uma dimensão extra, o tempo.
Bem, vou postar aqui a estrutura de uma tabela histórica:
CREATE TABLE foo_history ( history_id SERIAL NOT NULL, date_created timestamp NOT NULL DEFAULT NOW(), date_deleted timestamp DEFAULT NULL, operation VARCHAR(20) NOT NULL, user VARCHAR(80) NOT NULL DEFAULT CURRENT_USER, current_version VARCHAR(80), LIKE foo, CONSTRAINT foo_history_pk PRIMARY KEY(history_id) );
É mais ou menos isso. Deêm uma olhada na linha 8, a expressão LIKE foo. Ela diz ao PostgreSQL que ele deve procurar a estrutura da tabela foo, e copiar ela todinha embaixo. Legal não? Imagine a tabela foo:
CREATE TABLE foo ( fid SERIAL NOT NULL, classe_vegetacao VARCHAR(30) NOT NULL, CONSTRAINT foo_pk PRIMARY KEY(fid) ); -- nossa tabela final gerada pela função é: CREATE TABLE foo_history ( history_id SERIAL NOT NULL, date_created timestamp NOT NULL DEFAULT NOW(), date_deleted timestamp DEFAULT NULL, operation VARCHAR(20) NOT NULL, user VARCHAR(80) NOT NULL DEFAULT CURRENT_USER, current_version VARCHAR(80), fid INTEGER, classe_vegetacao VARCHAR(30), CONSTRAINT foo_history_pk PRIMARY KEY(history_id) );
*Uma particularidade: qualquer campo do tipo SERIAL (como fid, na tabela foo) é realmente do tipo INTEGER. Quando declaramos SERIAL, o PostgreSQL entende que deve criar uma sequência específica para aquele campo e escolhe o valor padrão para aquele campo o próximo valor daquela sequência.
Bem, para começar precisamos de um código SQL que gere automaticamente este código acima. Ele precisa gerar a tabela sem que o usuário digite nada, apenas escolha a tabela que ele quer montar um registro histórico.
Nosso código também precisa montar automaticamente as regras que vão realizar a gestão desta tabelinha acima. Lembre-se que precisamos de uma regra para cada tipo de modificação na tabela, uma para INSERT, uma para UPDATE e uma para DELETE.
Cada uma tem uma particularidade, pois as alterações na tabela histórica não são as mesmas. A regra para delete, por exemplo, não deve criar novo registro na série histórica, apenas indicar que o registro foi deletado.
Não é muito complicado, mas também não é muito simples. Daqui uns dias falo deste códigozinho e dou umas dicas sobre ele.
George Silva
Contribuindo um pouquinho…
Boa noite pessoal,
Alguns dias atrás me cadastrei no trac da OsGeo para ver se conseguia solucionar algum tiquete em aberto.
Para quem não sabe, trac é um sistema que controla as informações sobre bugs, melhoramentos entre outras coisas à fazer, dentro de um projeto de software. Ele permite um usuário aceitar uma tarefa, postar arquivos e mensagens e receber comentários em seu trabalho.
Aceitei o tíquete #180 que pede a criação de algumas funções para criar tabelas "históricas", permitindo o usuário saber quem alterou a tabela, como alterou, quando e todas as alterações feitas. À partir daí ele tem opções de restaurar uma feição que foi deletada ou editada de forma errada, entre outras coisinhas.
Montei algumas funções em pl/pgsql puro para gerar estes códigos, e as mesma estão disponíveis no link mostrado acima. Ainda existe muita discussão à ser feita para que elas comecem a pertencer ao código "oficial" do PostGIS, mas está caminhando. PS do dia 13/01/2010 - o patch foi aceito e já foi comitado em trunk. Provavelmente seu PostGIS já vem com o módulo, com algumas mudanças. Não deixe de conferir!
O bacana, além de aprender e conhecer gente nova, é poder devolver um pouco pra um software excelente. Uma contribuição pequena, com certeza, mas que mais pra frente pode ajudar muita gente.
George Silva