<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog Geo.NET &#187; History Tables</title>
	<atom:link href="http://blog.geoprocessamento.net/tag/history-tables/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.geoprocessamento.net</link>
	<description>Geoprocessamento, SIG e Sensoriamento Remoto</description>
	<lastBuildDate>Wed, 21 Sep 2011 12:00:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>History Tables &#8211; pt 1</title>
		<link>http://blog.geoprocessamento.net/2010/01/history-tables-pt-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=history-tables-pt-1</link>
		<comments>http://blog.geoprocessamento.net/2010/01/history-tables-pt-1/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 00:40:55 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[History Tables]]></category>
		<category><![CDATA[PostGIS]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=123</guid>
		<description><![CDATA[


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/07/postgis-decisoes-municipais-2/' rel='bookmark' title='Permanent Link: Desenvolvendo um SIG para Suporte de Decisões Municipais #2'>Desenvolvendo um SIG para Suporte de Decisões Municipais #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/05/funcoes-postgis-1/' rel='bookmark' title='Permanent Link: Funções PostGIS #1'>Funções PostGIS #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Boa noite pessoal.</p>
<p style="text-align: justify;">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 <em>PostGIS</em>.</p>
<p style="text-align: justify;">Bem, aqui vão algumas questões: O <em>PostgreSQL</em> nos permite lidar com este tipo de situação de duas formas: <em>Rules</em> e/ou <em>Triggers</em>.</p>
<p style="text-align: justify;">No caso do nosso projetinho, foram utilizadas <em>rules</em> para lidar com o que precisamos fazer. Bem, o que deve ter um histórico de feições?</p>
<p style="text-align: justify;">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.</p>
<p style="text-align: justify;">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.</p>
<p style="text-align: justify;">Bem, vou postar aqui a estrutura de uma tabela histórica:</p>
<pre name="code" class="sql">
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)
);
</pre>
<p style="text-align: justify;">É 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:</p>
<pre name="code" class="sql">
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)
);</pre>
<p style="text-align: justify;">*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.</p>
<p style="text-align: justify;">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.</p>
<p style="text-align: justify;">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.</p>
<p style="text-align: justify;">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.</p>
<p style="text-align: justify;">Não é muito complicado, mas também não é muito simples. Daqui uns dias falo deste códigozinho e dou umas dicas sobre ele.</p>
<p style="text-align: justify;">George Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/07/postgis-decisoes-municipais-2/' rel='bookmark' title='Permanent Link: Desenvolvendo um SIG para Suporte de Decisões Municipais #2'>Desenvolvendo um SIG para Suporte de Decisões Municipais #2</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/05/funcoes-postgis-1/' rel='bookmark' title='Permanent Link: Funções PostGIS #1'>Funções PostGIS #1</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/12/arcobjects-e-class-extensions-1/' rel='bookmark' title='Permanent Link: ArcObjects e Class Extensions #1'>ArcObjects e Class Extensions #1</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/01/history-tables-pt-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Contribuindo um pouquinho&#8230;</title>
		<link>http://blog.geoprocessamento.net/2010/01/contribuindo-um-pouquinho/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=contribuindo-um-pouquinho</link>
		<comments>http://blog.geoprocessamento.net/2010/01/contribuindo-um-pouquinho/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 00:31:32 +0000</pubDate>
		<dc:creator>George Rodrigues da Cunha Silva</dc:creator>
				<category><![CDATA[George Silva]]></category>
		<category><![CDATA[Banco de Dados]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[History Tables]]></category>
		<category><![CDATA[PostGIS]]></category>

		<guid isPermaLink="false">http://blog.geoprocessamento.net/?p=119</guid>
		<description><![CDATA[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 [...]


Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/03/monografia/' rel='bookmark' title='Permanent Link: Monografia'>Monografia</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/07/postgis-wkt-raster/' rel='bookmark' title='Permanent Link: PostGIS WKT Raster'>PostGIS WKT Raster</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/08/introducao-ao-geodjango/' rel='bookmark' title='Permanent Link: Introdução ao GeoDjango'>Introdução ao GeoDjango</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Boa noite pessoal,</p>
<p style="text-align: justify;">Alguns dias atrás me cadastrei no <a rel="nofollow" target="_blank" href="http://trac.osgeo.org/postgis/wiki/UsersWikiMain"><em>trac</em></a> da <a rel="nofollow" target="_blank" href="http://www.osgeo.org/"><em>OsGeo</em></a> para ver se conseguia solucionar algum tiquete em aberto.</p>
<p style="text-align: justify;">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.</p>
<p style="text-align: justify;">Aceitei o tíquete <a rel="nofollow" target="_blank" href="http://trac.osgeo.org/postgis/ticket/180">#180</a> 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.</p>
<p style="text-align: justify;">Montei algumas funções em pl/pgsql puro para gerar estes códigos, e as mesma estão disponíveis no link mostrado acima. <span style="text-decoration: line-through;">Ainda existe muita discussão à ser feita para que elas comecem a pertencer ao código "oficial" do <em>PostGIS</em>, mas está caminhando.</span> 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!</p>
<p style="text-align: justify;">
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.</p>
<p style="text-align: justify;">George Silva</p>


<p>Related posts:<ol><li><a href='http://blog.geoprocessamento.net/2010/03/monografia/' rel='bookmark' title='Permanent Link: Monografia'>Monografia</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/07/postgis-wkt-raster/' rel='bookmark' title='Permanent Link: PostGIS WKT Raster'>PostGIS WKT Raster</a></li>
<li><a href='http://blog.geoprocessamento.net/2010/08/introducao-ao-geodjango/' rel='bookmark' title='Permanent Link: Introdução ao GeoDjango'>Introdução ao GeoDjango</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.geoprocessamento.net/2010/01/contribuindo-um-pouquinho/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

