Tabelas temporárias são usadas para dados não-persistentes. Elas são muito usadas em duas situações:
Como datasource para um formulário ou relatório, onde os dados são muito complexos para serem analisados e por isso, populamos a tabela temporária e a usamos;
Como dados temporários durante processos complicados, para guardar os resultados durante o processo.
Regras para as tabelas temporárias:
No geral, cada instância de uma tabela temporária e os dados à ela associados, existirão apenas no buffer da variável usada no escopo atual.
Você pode apontar várias variáveis para uma mesma instância de tabela temporária usando ou o método .setTmpData() ou apontando diretamente um buffer para o outro, idêntico a tabelas normais. Desta forma, mesmo que seu buffer original vá para fora do escopo, seus dados serão mantidos enquanto uma das outras referencias permaneçam.
Esteja ciente que os métodos estáticos das tabelas (como o find()) não irão trabalhar com tabelas temporárias a menos que você passe através de uma variável no método.
Por exemplo, este método não funcionará em uma tabela temporária, como a variável tempTable que foi usada é nova e desta forma, não conterá registros.
// Isto não funciona public static TempTable find(AccountNum _accountNum, boolean _forUpdate = false) { TempTable tempTable ; ; if (_accountNum) { tempTable.selectForUpdate(_forUpdate) ; select firstonly tempTable where tempTable.AccountNum == _accountNum ; } return tempTable ; } |
Se você quiser ter um método find() em sua tabela temporária, então você precisará modifica-la para passar através de uma referência a nossa tabela temporária populada.
// Use this pattern instead public static TempTable find(AccountNum _accountNum, TempTable _tempTable, boolean _forUpdate = false) { if (_accountNum) { _tempTable.selectForUpdate(_forUpdate) ; select firstonly _tempTable where _tempTable.AccountNum == _accountNum ; } return _tempTable ; } |
Alguns exemplos de como popular e usar tabelas temporárias pode ser encontras no projeto trg_temptablesgeneral.
Criado tabelas temporárias
Na AOT:
Marque a propriedade Temporary para YES para criar uma tabela que sempre será temporária. (saiba que qualquer dado existente será permanentemente removido se você marcar esta opção)
Claro que você não poderá mais usar o Table Browser para verificar os dados, uma vez que os dados são armazenados apenas no escopo da instância da tabela.
Fazendo uma tabela existente ser temporária
Você pode converter uma tabela normal para temporária no código. Por exemplo, se você quiser criar uma cópia temporária da tabela inventTable:
InventTable inventTable; ; inventTable.setTmp(); |
Fazendo isso você removerá todos os dados da tabela temporária. Se você quiser criar uma cópia temporária de uma tabela populada, você poderá fazer o seguinte:
InventTable inventTable; InventTable inventTableTmp; ; inventTableTmp.setTmp(); while select inventTable { inventTableTmp.data(inventTable.data()); inventTableTmp.doInsert(); } |
Agora você pode adicionar, modificar ou remover dados da tabela sem afetar o conteúdo real da tabela.
Tabelas temporárias nos formulários
Usar tabelas temporárias em formulários requer o uso do método .setTmpData().
Por exemplo:
Os dados da tabela temporária são populados em um método static (rodando no lado do servidor), o qual é chamado de um formulário e retorna uma tabela populada. Nós podemos popular um formulário com uma tabela temporária caso seja necessário, ou apenas chamar o método que irá popular diretamente como é mostrado abaixo.
No método init() do datasource, nós usamos .setTmpData() para instruir a query datasource para usar nossa tabela temporária. O nome do nosso datasource neste exemplo é TempTable.
public void init() { super(); TempTable.setTmpData(tmpTableClass::populateTmpData()); } |
Veja o preojeto trg_temptablesform para ter um exemplo de trabalhar com formulários baseados em tabelas temporárias.
Tabelas temporárias nos relatórios
O método correto de se usar tabelas temporárias em relatórios é levemente diferente do que em formulários.
A diferença mais importante é o uso do .setRecord() no lugar de .setTmpData(). Abaixo um simples exemplo:
public boolean fetch() { boolean ret; ; this.queryRun().setRecord(tmpTableClass::populateTmpData()); ret = super(); return ret; } |
Como muitas vezes já existe uma classe RunBaseReport sendo usada no relatórios, é fácil integrar a população da tabela temporária dentro da classe que já existe. Isto é muito útil se você precisa que os dados em uma tabela temporária dependam dos dados inseridos no report dialog inseridos pelo usuário.
Veja o projeto trg_temptablesreports para um exemplo de um relatório usando a classe RunBaseReport em um tabela temporária.
Tabelas temporárias – Performance
Os dados inseridos em uma tabela temporária são inseridos em um arquivo físico no sistema de arquivos. O arquivo é automaticamente criado quando o primeiro registro é inserido na instância da tabela temporária. Sendo assim, em um ambiente 3 tier, o arquivo pode ser mantido no servidor ou no cliente, depende onde o primeiro registro é inserido. Para o ponto de vista de performance esse é um ponto relevante quando se for usar tabelas temporárias.
Tabelas temporárias – Índices
Assim como as tabelas normais, índices podem ser criados também nas tabelas temporárias. Quando uma tabela temporária é copiada de uma tabela normal usando o .setTemp() os indices existentes também são criados na tabela temporária. Para tabelas temporárias criadas (com a propriedade Temporary setada para yes), você deve criar os índices desejados através da AOT normalmente.
Índices tem um efeito substancial na performance das tabelas temporárias. Para tabelas temporárias com muitos registros você poderá notar uma grande limitação na performance quando fizer pesquisas em campos não indexados.
Tabelas temporárias – Segurança
Você pode setar uma SecurityKey em uma tabela temporária, como em outra qualquer. A SecurityKey funcionará bem, limitando o acesso. No entanto, tabelas temporárias nunca serão exibidas na árvore de atribuição de permissões, portanto não é realmente possível ativa-la para os usuários. Por isso é importante não colocar uma SecurityKey em qualquer tabela temporária ou os usuários nunca serão capazes de usá-las.
[]s
Ricardo Pichler
Leave a reply