Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Função: DBSetFilter

Permite definir um filtro lógico de visibilidade de registros para a área de trabalho atual - alias corrente. Quando um filtro é setado, os registros que não atendem a condição de filtro não estão logicamente visíveis. Isto significa que os registros filtrados não estão visíveis para as operações e instruções que atuam sob a visibilidade lógica das informações.

DBSetFilter ( < bCondicao>, < cCondicao> ) --> Nil

NomeTipoDescriçãoObrigatórioReferência
bCondicaoBloco de códigoIndica um bloco de código AdvPL avaliado para determinar a visibilidade dos registros do alias enquanto filtrado. Ele expressa efetivamente a condição de filtro, onde o bloco de código deve retornar verdadeiro (.T.), caso o registro atual seja considerado pelo filtro, ou falso (.F.), caso o registro não deve ser considerado. X
cCondicaoCaracterIndica a representação literal da condição de filtro expressada no bloco de código. Trata-se de um parâmetro obrigatório, e deve refletir o conteúdo – fonte (source) do bloco de código usado no primeiro parâmetro, em caso de diferenças entre eles, o comportamento do filtro é imprevisível. Caso seja informada uma string em branco, é assumido automaticamente o código-fonte do bloco de código especificado. X
Nil (Nulo)

A expressão de filtro fornecida para a função deve retornar verdadeiro (.T.) caso o registro atual da tabela atenda à condição de filtro, caso contrário deve retornar falso (.F.). A expressão de filtro deve ser um bloco de código (bCondicao), e a equivalente condição em string (cCondicao), e ambas sendo fornecidas, elas devem expressar a mesma condição.

A função DBSetFilter() é chamada internamente a partir do comando SET FILTER TO <cExp>. A utilização deste comando recebe a expressão AdvPL de filtro, e na pré-compilação do código-fonte AdvPL, realiza a chamada explícita da função DBSetFilter() com o bloco de código montado a partir da condição informada. A utilização do comando SET FILTER TO torna a codificação mais simples e legível, mesmo que internamente o resultado seja o mesmo.

Ao aplicar um filtro em uma tabela aberta, esta passa a se comportar como se contivesse apenas os registros que atendem a condição de filtro especificada. A maior parte das funções que movem o ponteiro de registro atual respeita o filtro atualmente setado, exceto os comandos que trabalham com o número físico do registro (RECNO). Isto inclui a instrução DBGoTo() e comandos onde é especificada a cláusula RECORD <n>.

 

Observações e Comportamento

  • Ao executar a instrução DBSetFilter(), o ponteiro de registro atual não é reposicionado. Isto significa que o filtro não se torna ativo a menos que o ponteiro de registro seja movido em alguma direção. Normalmente utilizamos DBGoTop() para ativar o filtro, onde o ponteiro de registro será posicionado no primeiro registro logicamente válido dentro da expressão de filtro atual na ordem em uso.
  • A expressão de filtro não é obrigatoriamente executada em um momento especifico e/ou em um ou vários registros. Sua execução é dinâmica, quando da determinação de visibilidade lógica de registros nas operações de posicionamento da RDD.
  • O contexto de execução (EVAL) da expressão de filtro está atrelado ao alias filtrado, que será implicitamente setado como alias corrente durante a avaliação da condição de filtro.
  • Caso a expressão de filtro utilize informações externas ao alias atual, como campos de outras tabelas, os efeitos são imprevisíveis.
  • Caso a expressão de filtro realize alguma alteração de status no alias atual, como por exemplo trocar o conteúdo de algum campo, os efeitos são imprevisíveis.

 

Performance e tráfego de registros

O contexto de execução de filtros AdvPL em sua origem é independente de RDD, e por se tratar de um comportamento da linguagem, a expressão de filtro é avaliada pelo servidor de aplicação (Application Server), na execução das instruções de movimentação de ponteiro de registro. Quando utilizada uma arquitetura client/server de banco de dados (como por exemplo ADS Server, c-tree Server , TOPConnect, DBAccess), isto torna necessária a leitura dos registros no banco de dados e o tráfego dos registros para a avaliação da expressão de filtro no Application Server, onde está sendo executado o programa AdvPL que definiu o filtro.

A linguagem AdvPL possui otimizações para atender a determinadas condições de filtro, onde o filtro é aplicado total ou parcialmente diretamente na aplicação servidora de banco de dados, sendo mais eficiente, performático e eliminando o overhead de rede gerado pelo tráfego de registros.  Em linhas gerais, tabelas utilizando uma RDD com componentes client/server (ADS Server, c-tree Server e/ou DBAccess) executam a expressão de filtro na íntegra diretamente na aplicação servidora de banco, desde que o filtro não faça uso de nenhuma função da linguagem AdvPL, mesmo que função básica e/ou nativa da linguagem, e utilize apenas os operadores binários > (maior), >=  (maior ou igual),  < (menor), <= (menor ou igual), <> ou !=  (diferente) e = (igual), e expressões lógicas com os operadores .AND., .OR. e/ou .NOT., e devem preferencialmente utilizar na condição de filtro campos da tabela que façam parte da ordem de índice em uso no momento.

As características e pré-requisitos do comportamento de filtros executados diretamente na aplicação servidora de bancos de dados, e suporte a operadores e funções nativas para execução de filtro diretamente no banco são abortadas dentro dos tópicos de comportamentos específicos de acordo com a RDD e aplicação servidora de banco utilizada.

 

Filtros em tabelas utilizando ADS Server e/ou c-tree Server

Ambos os engines suportam o uso de funções básicas da linguagem AdvPL na montagem da expressão de filtro, e executam de modo nativo o filtro na aplicação servidora. Funções como AllTrim(), DToS(), Left(), Right(), operador $ (contido em), Str(), StrZero() e afins são tratadas diretamente pelo ADS Server e/ou c-tree Server. Englobam os acessos realizados através das seguintes RDDs sob as seguintes condições:

  • RDD DBFCDX - em ambiente configurado com LocalFiles=CTREE, utilizando um c-tree Server para controle dos dicionários.
  • RDD DBFCDXAX - em ambiente configurado para base de dados principal com ADS Server e repositório ADS (RpoDb=ADS).
  • RDD CTREECDX - em ambiente configurado para base de dados principal com c-tree Server e repositorio c-tree (RPODB=CTREE).

 

Filtros em tabelas utilizando DBaccess

Através do DBAccess, criamos e acessamos tabelas em bancos de dados relacionais usando a RDD TOPCONN, em diversos bancos de dados homologados. As funcionalidades extendidas de filtro, como suporte a algumas funções básicas da linguagem AdvPL foram implementadas no DBAccess de forma diferenciada para cada banco de dados, de acordo com os recursos disponíveis nos bancos, capazes de prover ou emular o comportamento original de um filtro AdvPL.

Quando setada uma expressão de filtro em uma tabela acessada pela RDD TOPCONN, através de um programa AdvPL, caso existam comparações suportadas e não suportadas na mesma expressão, o DBAccess faz uma redução do filtro, tentando aproveitar todas as partes da expressão suportadas, para filtrar o que for possível através das queries de busca de dados do DBAccess, e minimizar tráfego de rede e recuperação desnecessária de registros. Qualquer condição não suportada pelo DBAccess e enviada a ele resultará em uma comparação sempre verdadeira considerando o primeiro campo da tabela (no ERP, em geral é o campo _FILIAL).

Observe, a seguir, o suporte para funções AdvPL em filtro implementado no DBAccess:

Funções AdvPL/Banco Microsoft SQL Oracle IBM DB2 Informix Sybase PostgreSQL MySQL
DToS (cpo) SIM SIM SIM SIM SIM SIM SIM
SubStr(s,n,n) SIM SIM SIM SIM SIM SIM SIM
$ (operador) SIM SIM SIM SIM SIM SIM SIM
Empty() SIM SIM SIM SIM NÃO SIM NÃO
AllTrim() SIM SIM SIM SIM NÃO NÃO NÃO
Lower() SIM SIM SIM SIM NÃO SIM NÃO
Upper() SIM SIM SIM SIM NÃO SIM NÃO
Left() SIM SIM SIM NÃO NÃO NÃO NÃO
Right() SIM NÃO SIM NÃO NÃO NÃO NÃO
Space() SIM SIM SIM NÃO NÃO NÃO NÃO
StrTran() SIM SIM SIM SIM NÃO SIM NÃO
Len() NÃO SIM SIM SIM NÃO NÃO NÃO
CHR() SIM SIM NÃO NÃO NÃO NÃO NÃO
ASC() SIM SIM SIM NÃO NÃO NÃO NÃO

As únicas funcionalidades suportadas de modo nativo ao aplicar um filtro AdvPL em todos os bancos de dados são: DToS (campo) -> Onde a expressão é removida, pois o DBAccess grava um campo “D” Data do AdvPL no banco como string, no formato “AAAAMMDD”, SubStr(campo ,nStart ,nLen) , e o operador $ (contido em expressão string). Quaisquer outras funções utilizadas em uma condição de filtro serão avaliadas no servidor de aplicação (TOTVS/ByYou Application Server). 

 

Exemplo

Partindo de uma tabela com a seguinte estrutura :

CPOC C 2 0
CPON N 12 2
CPOD D 8 0

Ao aplicarmos os filtros abaixo e navegar na tabela, é possível verificar através do recurso de trace de conexão do DBAccess que as condições foram traduzidas para condições nas queries montadas pelo DBAccess para busca dos dados. Os exemplos abaixo, foram obtidos com um trace feito em uma conexão do Application Server com um DBAccess 4.2 utilizando um Microsoft SQL Server 2005, onde o programa seta o filtro usando o comando SET FILTER TO (expressão), e após setar o filtro executa um DBGoTop() na tabela.

SET FILTER TO CPOC = ‘  ’SELECT R_E_C_N_O_ FROM dbo.RDDT0010 WHERE D_E_L_E_T_ = ' ' AND (CPOC = '  ') ORDER BY CPOC,R_E_C_N_O______________________________________________________________________________________________________________SET FILTER TO CPON = 0SELECT R_E_C_N_O_ FROM dbo.RDDT0010 WHERE D_E_L_E_T_ = ' ' AND (CPON = 0) ORDER BY CPOC,R_E_C_N_O______________________________________________________________________________________________________________SET FILTER TO CPOC$'01,05'SELECT R_E_C_N_O_ FROM dbo.RDDT0010 WHERE D_E_L_E_T_ = ' ' AND (CHARINDEX(( CPOC ),( '01,05' ))>0 ) ORDER BY CPOC,R_E_C_N_O______________________________________________________________________________________________________________SET FILTER TO VAL(CPOC)>0SELECT R_E_C_N_O_ FROM dbo.RDDT0010 WHERE D_E_L_E_T_ = ' ' AND (CPOC=CPOC) ORDER BY CPOC,R_E_C_N_O_Como a expressão VAL(campo) não é suportada, e é a unica condição do filtro, o DBAccess coloca na expressão de filtro uma condição verdadeira, comparando o primeiro campo da tabela com ele mesmo. Neste caso, durante a navegação do ponteiro de registro da tabela (DBSkip por exemplo) vai fazer quantos Skip’s no DBAccess forem necessários até que seja retornado um registro válido dentro da condição de filtro.  _____________________________________________________________________________________________________________SET FILTER TO CPON = 0 .AND. VAL(CPOC)>0SELECT R_E_C_N_O_ FROM dbo.RDDTEST WHERE R_E_C_N_O_  > 0 AND (CPON = 0 AND CPOC=CPOC) ORDER BY R_E_C_N_O_Uma expressão suportada e outra não suportada, como a operação é um “E” lógico (AND) , a expressão não suportada é trocada pela expressão de comparação verdadeira, de modo que no banco serão filtrados e trafegados os registros onde o campo CPOC tem conteúdo zero. Quando o registro for recebido pelo Microsiga Protheus, será feita a validação da condição de filtro completa, onde será verificado se o valor do campo CPOC é maior que zero. Cada registro trafegado e recebido que não atender à condição de filtro é descartado  e o TOTVS/ByYou Application Server vai solicitar o próximo registro ao DBAccess, até que seja retornado um registro que atenda à condição estabelecida. Na prática, se a tabela em foco possui um total de 1000 registros, onde 500 registros possuem CPON = 0, e destes 500, apenas 10 possuem um conteúdo em CPOC que tornem verdadeira a condição VAL(CPOC) > 0, ao aplicar o filtro e fazer um looping de processamento mostrando o número do registro filtrado encontrado (dbgotop() – While !eof() – conout(recno()) - DbSkip() – Enddo), 500 registros serão filtrados no banco de dados, e estes 500 serão trafegados pela rede e avaliados pelo TOTVS/ByYou Application Server, que vai mostrar apenas 15 números de registro. Esta operação vai fazer mais de 500 IO/s entre Protheus e DBAccess, e entre DBAccess e o banco de dados, para aproveitar apenas 15 registros. _____________________________________________________________________________________________________________SET FILTER TO CPON > 0  .OR. VAL(CPOC)>0SELECT R_E_C_N_O_ FROM dbo.RDDTEST WHERE R_E_C_N_O_  > 0 AND (( CPON > 0 ) OR ( CPOC=CPOC )) ORDER BY R_E_C_N_O_Uma expressão suportada e outra não suportada, como a operação entre as expressões é um “OU” lógico (OR), e a expressão não suportada é trocada pela expressão de comparação verdadeira, na prática nenhum registro será filtrado no Banco de Dados.Considerando o exemplo anterior, onde a tabela possui um total de 1000 registros, onde 500 registros atendem à condição de filtro, todos os 1000 registros serão recuperados e trafegados pela rede, mas apenas 500 registros serão utilizados pelo programa AdvPL.
Advanced Protheus 6.09 , Advanced Protheus 7.10 , Microsiga Protheus 8.11 , Protheus 10 , TOTVS Application Server 10 , ByYou Application Server

  • No labels