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
Related posts: