Diversos Sobre Oracle

12
Utilizando imagens no forms 6i. Manipular imagens no Oracle Forms. Para isso, utilizaremos a procedure READ_IMAGE_FILE, nativa do forms. Sua definição é: Sintaxe PROCEDURE READ_IMAGE_FILE (file_name VARCHAR2,file_type VARCHAR2,item_id ITEM); PROCEDURE READ_IMAGE_FILE (file_name VARCHAR2,file_type VARCHAR2,item_name VARCHAR2); Parametros file_name Nome do arquivo de imagem, se passado apenas o nome irá buscar o caminho default da Path, também é possível passar o caminho completo. file_type Tipo do arquivo: BMP, CALS, GIF, JFIF, JPG, PICT, RAS, TIFF, ou TPIC. item_id Id do item que irá receber um a imagem. item_name Nome do item que irá receber a imagem. Bom, vamos aos passos para a construção do form. 1 - Vamos criar um data block, não base table (aquele que não referencia a estrutura de um objeto do banco de dados) com nome de IMAGEM.

Transcript of Diversos Sobre Oracle

Page 1: Diversos Sobre Oracle

Utilizando imagens no forms 6i.

Manipular imagens no Oracle Forms. Para isso, utilizaremos a procedure READ_IMAGE_FILE, nativa do forms. Sua definição é: Sintaxe PROCEDURE READ_IMAGE_FILE (file_name VARCHAR2,file_type VARCHAR2,item_id ITEM);

PROCEDURE READ_IMAGE_FILE (file_name VARCHAR2,file_type

VARCHAR2,item_name VARCHAR2);

Parametros

file_name Nome do arquivo de imagem, se passado apenas o nome irá buscar o

caminho default da Path, também é possível passar o caminho completo.

file_type Tipo do arquivo: BMP, CALS, GIF, JFIF, JPG, PICT, RAS, TIFF, ou TPIC.

item_id Id do item que irá receber um a imagem.

item_name Nome do item que irá receber a imagem.

Bom, vamos aos passos para a construção do form.

1 - Vamos criar um data block, não base table (aquele que não referencia a estrutura de

um objeto do banco de dados) com nome de IMAGEM.

Page 2: Diversos Sobre Oracle

2 - Entre na propriedade do data block, altere o valor da opção DATABASE DATA

BLOCK para NO. Afinal, este bloco não precisa acessar o banco de dados.

3 - Neste data block, criaremos dois campos.

São eles:

IMAGEM do tipo Image

CAMINHO do tipo TEXT ITEM

Page 3: Diversos Sobre Oracle

4 - Devemos criar um canvas chamado Imagem.

5 - Depois de criado, alterar os campos para que ficam dentro dele.

Para isso entre na propriedade do campo, e na opção canvas escolha IMAGEM.

Faça isso para os dois campos.

6 - Após isso entre no Layout Editor [F2] e posicione os campos da melhor forma

Page 4: Diversos Sobre Oracle

7 - Agora, vamos criar um procedure com o nome de LEIMAGEM.

Com o conteúdo:

PROCEDURE leImagem(p_imagem varchar2) IS

button_pressed number;

alerta Alert;

begin

:SYSTEM.MESSAGE_LEVEL := 25;

IF(:IMAGEM.CAMINHO IS NOT NULL)THEN

READ_IMAGE_FILE(p_imagem,’BMP’,'IMAGEM.IMAGEM’);

END IF;

IF NOT FORM_SUCCESS THEN

alerta := find_alert(’ERRO’);

Page 5: Diversos Sobre Oracle

button_pressed := SHOW_ALERT(alerta);

END IF;

:SYSTEM.MESSAGE_LEVEL := 0;

END;

Esta deverá ser chamada quando houver uma alteração no campo CAMINHO, vamos

colocar no WHEN-VALIDATE-ITEM a chamada para esta procedure. Optei de criar

nesta trigger pois é apenas quando mudar o conteúdo deste campo que a imagem será

recarregada.

8 - Vamos criar a trigger WHEN-VALIDATE-ITEM no campo CAMINHO com

conteúdo:

declare

begin

leImagem(p_imagem => :IMAGEM.CAMINHO);

end;

É legal observar que o Oracle possibilita dois tipos de passagem de parâmetros, são

eles:

• O habitual posicional onde os parâmetros são passados na mesma seqüência que

declarados.

Exemplo: leImagem(:IMAGEM.CAMINHO);.

• E o referenciado onde os parâmetros são passados com a referencia identificada.

Exemplo: leImagem(p_imagem => :IMAGEM.CAMINHO);.

9 - Agora vamos criar um alerta para tratar a exceção, pois é possível que o usuário

digite um caminho que não há uma imagem.

Page 6: Diversos Sobre Oracle

Vamos mudar algumas propriedades:

10 - No alert ERRO:

Title: Erro ao Encontrar a Imagem

Message: Imagem não encontrada!

Deixe a propriedade Button 2 Label em branco, utilizaremos apenas o botão OK no

alert.

11 - Na Window WINDOW1:

Title: Imagem

No campo CAMINHO:

Maximum Length: 120

12 - Compile todo o form [Ctrl + Shift + K].

13 - Execute o forms [Ctrl + R] e se divirta.

Page 7: Diversos Sobre Oracle

Visão inicial do programa ao ser executado.

Visão do programa com a imagem encontrada.

Visão do programa com a imagem não encontrada.

Page 8: Diversos Sobre Oracle

Validando diversos campos no Oracle Forms 6i Existem alguns Forms que pelo seu tempo de vida e diversas correções e implementações de

novas regras de negócio fazem com que um único Forms contenha as funções e complexidades

de um sistema completo (já operei com um Forms que o arquivo fonte .FMB tinha 10 Mb).

Um Forms desse tipo com certeza terá diversos campos, e estes campos por sua vez deverão

conter validações e consistências com o intuito de manter e assegurar que os dados inseridos

pelos usuários são os corretos ou na pior das situações o menos errado possível.

E deixar o código-fonte do seu PL/SQL embutido no Forms completamente abarrotado de IF´s

para realizar essas consistências, realmente não é o melhor caminho, pois torna a manutenção

maçante e lenta, além de deixar o seu código “feio”.

Veja um exemplo, de como consistir campos de forma inteligente e elegante, dando

simplicidade e agilidade tanto no desenvolvimento quanto na manutenção do código-fonte

PL/SQL: /* ************************************************************************************************** * Autor: Petter Rafael * Empresa: Viamais Web Intelligence * Desde: Dezembro/2010 * Versão: 1.0.1 – Oracle Forms 6i / Oracle PL/SQL 8 * * Objetivo: Consistir blocos de dados no Forms de forma automática e funcional, eliminando a * necessidade de construção de procedures e outros artefatos para consistir diversos * campos. Ideal para blocos de dados com grande quantidade de campos. * * Variáveis: p_nome_bloco = Nome do bloco que será consistido. * p_tipo_valida = Tipo de consistência que será realizada. * 1 - para consistência de campos nulos. * 2 - para consistência de campos negativos. * p_campo_tipo = Tipo do campo que será consistido. Obs.: precisar ser idêntico à nomenclatura do Forms (consulte F1 para ajuda). * p_mens_err_pro = Identifica se q mensagem de erro padrão será substituída por uma mensagem de erro definida pelo desenvolvedor. * p_mensagem_erro = Texto da mensagem de erro própria. Somente será preenchido caso a mensagem de erro personalizada esteja ativa. * p_cor_erro = Cor que o fundo do campo deve assumir caso sinalize inconsistência. Caso esteja nulo uma cor padrão é assumida. Padrão de cores Forms (consulte F1 para ajuda). * * Retorno: Retorna mensagem de erro caso os critérios indiquem inconsistência informando o * HINT do campo para sinalizar para o usuário qual campo precisa ser corrigido. * Alterar a cor de fundo (background) do campo caso possível. ************************************************************************************************* */

PROCEDURE C_CONSIS_GERAL(p_nome_bloco IN varchar2

,p_tipo_valida IN NUMBER

,p_campo_tipo IN varchar2

,p_mens_err_pro IN BOOLEAN

,p_mensagem_erro IN varchar2

,p_cor_erro IN varchar2) IS

w_campo_fim varchar2(400);

w_campo_ini varchar2(400);

w_erro varchar2(4000);

w_cor_back varchar2(15) := 'r350g0b0';

BEGIN

-- Controle da mensagem de erro.

IF p_mens_err_pro = TRUE THEN

w_erro := p_mensagem_erro;

ELSE

w_erro := 'Os seguintes campos estão com erros: ';

END IF;

-- Controle para cor de background de campos consistidos

IF p_cor_erro IS NOT NULL THEN

w_cor_back := p_cor_erro;

END IF;

-- Resgatando dados para início da consistência.

w_campo_ini := get_block_property(p_nome_bloco, first_item);

w_campo_fim := get_block_property(p_nome_bloco, last_item);

go_item(p_nome_bloco || '.' || w_campo_ini);

loop

-- Somente atua sobre campos de tipo específico

IF get_item_property(:system.cursor_item, item_type) = p_campo_tipo THEN

IF p_tipo_valida = 1 THEN

Page 9: Diversos Sobre Oracle

IF :system.current_value IS NULL THEN

message(w_erro || get_item_property(:system.cursor_item, hint_text));

set_item_property(:system.cursor_item, background_color, w_cor_back);

END IF;

elsif p_tipo_valida = 2 THEN

IF :system.current_value < 0 THEN

message(w_erro || get_item_property(:system.cursor_item, hint_text));

set_item_property(:system.cursor_item, background_color, w_cor_back);

END IF;

END IF;

END IF;

-- Saída caso alcance o último campo do bloco

IF w_campo_fim = :system.current_item THEN

exit;

END IF;

next_item;

END loop;

END;

Como utilizar? É muito simples, no Forms crie uma procedure (Program units) e cole o código PL/SQL que listei

acima.

Pronto, agora é só chamar a procedure, passando os parâmetros de acordo com a sua necessidade. Pode ser utilizada a

partir de qualquer triggers do Forms ou ainda embutida em outra procedure ou function.

As principais vantagens são:

Código PL/SQL embutido no Forms, mais coeso, simples de ser mantido e/ou alterado;

Maior eficiência, pois trata a consistência orientada por tipo do campo e validação e não caso a caso como

normalmente vemos;

Maior agilidade no desenvolvimento é mais versátil;

Permite customizar a mensagem de erro por campo, de forma transparente para o desenvolvedor, sem a

necessidade de alterar código-fonte PL/SQL;

Testada no Oracle Forms 6i, porém não existem restrições para versões posteriores do Forms.

Page 10: Diversos Sobre Oracle

mar/11

24

Falha de segurança no PL/SQL Developer afeta OracleTodo bom DBA, AD ou mesmo qualquer analista de sistemas e/ou programador sabe que a senha dos usuários com privilégios máster de um determinado banco de dados deve ser muito bem guardada. Porém notei um comportamento muito estranho no PL/SQL Developer, uma das ferramentas mais utilizadas para quem trabalha com Oracle. Supondo que o DBA utilize o PL/SQL Developer para seus trabalhos, como logicamente ou ele terá a senha do SYSDBA ou pelo menos um usuário com mais privilégios ele irá utilizar este usuário no PL/SQL Developer, feito isso, dentro da pasta Preferences irá ser armazena seu perfil de uso, em um arquivo criptografado. Os arquivos de devem ser copiados são: default.ini e user.prefs. Qual o problema? Se o arquivo é criptografado quem tentar abri-lo não vai conseguir decifrar a senha. Porém, eu posso copiar o perfil de uso utilizado pelo DBA e simplesmente copia-lo para dentro da pasta Preferences do meu PL/SQL Developer, assim eu poderei utilizar a senha do usuário do DBA e terei os mesmos privilégios. Simples assim. Creio eu que o pessoal que desenvolve o PL/SQL Developer poderia pelo menos colocar uma validação para ver se o usuário da pasta Preferences é o mesmo do usuário informado dentro do arquivo. Embora a senha de alto privilégio continue indecifrável um usuário mal intencionado poderá conseguir acesso privilegiado ao banco de dados Oracle, efetuar o que ele quiser e a culpa ainda ficará com a pessoa que utiliza o usuário roubado.

Descobrindo a semana com PL/SQL

Talvez você ainda não tenha precisado ou talvez nem saiba, mas em todo calendário

temos uma informação que não é muito utilizado no cenário brasileiro, é o número da

semana. Começando obviamente a contar da primeira semana do ano, esse número

pode auxiliar bastante se a precisão de cálculo de data do seu não pode ser diária ou

mensal e sim semanal (já trabalhei em diversos sistemas de agenciamento de fretes

que utilizam a semana para montagem de cargas, pois em termos de transporte a

precisão diária é demasia e a precisão mensal é obsoleta demais).

Em PL/SQL, realizar esse procedimento é muito simples, veja o exemplo abaixo:

SELECT to_char(to_date('02-feb-2011'), 'WW') FROM dual

E como retorno eu obtive o número 05, que significa que a data informada é da quinta

semana do ano de 2011.

É claro que a formatação da instalação do seu banco de dados Oracle pode influenciar

um pouco no PL/SQL que passei, por exemplo, o formato de data 02-feb-2011 é o

formato norte-americano, mas poderia ser também o mais usual no Brasil que é

02/02/2011.

Page 11: Diversos Sobre Oracle

Goto no PL/SQL

Noto que alguns programadores/desenvolvedores tem certa repulsa pelo comando

GOTO (vá para, em tradução livre) seja de qual for à linguagem, talvez esse sentimento

seja antigo, pois algumas linguagens de outros tempos permitiam uma verdadeira salada

com o comando GOTO o que tornava a manutenção do código ou alguma melhoria um

verdadeiro trabalho Herculano.

Porém se o código-fonte for bem estruturado, é totalmente passível e de bom tom

utilizar o comando GOTO quando a linguagem o possuir (obviamente).

Não sei se é endêmico da região em que trabalho, mas o pessoal do PL/SQL daqui não

utiliza muito o GOTO em seus softwares, quando é preciso fazer algum jump para

outra parte do código-fonte ou é tudo separado em diversas procedures dentro de um

mesmo body (package) o que pode gerar uma confusão maior do que com o uso do

GOTO, ou o que é pior, fica uma parte do código-fonte dentro de um if e a outra parte

dentro do else, nem preciso comentar muito, veja o resultado por você mesmo:

IF varTeste = TRUE THEN

-- Todo o seu código que será executado caso a condição seja

verdadeira

ELSE

-- Todo o seu código que será executado caso a condição não seja

verdadeira

END IF;

Em pequenos fragmentos de código-fonte isso não trás problemas, mas experimente

dividir o seu código em duas partes, cada uma com mais de 2.000 linhas e veja que isso

fica muito boçal. Agora veja a diferença com o uso do GOTO:

IF varTeste != TRUE THEN

GOTO EXEC

END IF;

-- Todo o seu código que será executado caso a condição seja

verdadeira

<<exec>>

-- Todo o seu código que será executado caso a condição não seja

verdadeira

Fica muito mais fácil de manter e mais performático também. Realmente não sei para

que não utilizar. Ainda duvida da aplicação do GOTO no PL/SQL, veja um exemplo

mais conciso:

DECLARE

w_teste varchar2(1000);

w_laco varchar2(10);

cursor u_teste IS

SELECT cod_venda

FROM vendas

WHERE ;

BEGIN

OPEN u_teste;

loop

fetch u_teste INTO w_laco;

Page 12: Diversos Sobre Oracle

exit WHEN u_teste%notfound;

IF w_teste IS NULL THEN

w_teste := w_laco;

ELSE

w_teste := w_teste || ', ' || w_laco;

END IF;

END loop;

IF w_teste IS NULL THEN

GOTO sem_erro;

END IF;

close u_teste;

dbms_output.put_line('Saída de teste:');

dbms_output.put_line('Valor: ' || w_teste);

<<sem_erro>>

dbms_output.put_line('Fim de execução!');

END;