1 - Linguagem 4GL
O TotvsTec 4GL surgiu com base nas linguagens nativas 4GL do banco de dados Informix e também com base na linguagem 4JS da IBM.
A linguagem 4GL se caracteriza por acessar as bases de dados através de uma linguagem comum chamada SQL (extensão do standard SQL-Structured Query Language) que não será vista neste manual. Esta filosofia permite uma maior facilidade na formação de programadores bem como uma separação efetiva entre o nível físico e lógico da exploração da base de dados tal como é definido na teoria das bases de dados relacionais.
O desenvolvimento e compilação das aplicações desenvolvidas em 4GL são realizadas via ferramenta de desenvolvimento Totvs Developer Studio disponível para download na central de download da página de suporte da TOTVS.
Quando compilados, todos os arquivos de código fonte tornam-se unidades de inteligência básicas, chamadas de RPO´s (Repository Protheus Objects). Esses RPO´s são mantidos em um repositório e carregados dinamicamente pelo servidor de aplicação (Application Server) para a execução. No entanto, não existe link ou união física do código compilado a um determinado ambiente ou aplicação, o que permite executar funções criadas em 4GL em qualquer ponto do ambiente ERP.
2 - Estrutura de um programa
Um programa é constituído por funções e declarações. A primeira função a ser executada é a função "MAIN", e, tem de existir em todos os programas.
Fonte olamundo.4gl MAIN |
As várias funções podem estar distribuídas por vários fontes a que se resolveu chamar de módulos.
2.1 Fluxo de um programa
Tal como nas linguagens de terceira geração, um programa é executado de acordo com instruções de controle de fluxo, em todas as funções exceto nos reports (os reports possuem uma estrutura de definição).
Para controlar o fluxo do programa foram implementadas diversas instruções de controle de fluxo das linguagens tradicionais (while, if, case, etc.), e, algumas com instruções específicas desta linguagem (Menus, prompts, etc.), algumas das quais não são procedurais (ex: MENU, INPUT, etc.).
O 4GL é ao mesmo tempo de definição e procedural. Como exemplo de definição temos os reports e as instruções de entrada/saída formatada, e, como exemplo de procedural a estrutura geral das funções.
2.2 Tipos e conversões de tipos
Como linguagem de gerenciamento de base de dados, o 4GL reconhece as estruturas representáveis na base de dados, e, algumas de maior complexidade. Os tipos de dados complexos, são declarados por composição de tipos elementares. Em 4GL os tipos de dados elementares existentes utilizados no produto LOGIX são:
SMALLINT
Números inteiros pequenos, uma variável deste tipo pode receber números inteiros entre –32767 e 37767.
INTEGER
Números inteiros entre -2,147,483,647 e +2,147,483,647.
DECIMAL[(m,[,n])]
Números decimais com “m” algarismos, sendo que “n” algarismos são para formar o número de casas decimais. Por exemplo, para DECIMAL(14,2), possui 14 dígitos significativos, sendo 2 deles para formar o número de dígitos a direita da vírgula, ou seja, são 12 dígitos inteiros e 2 decimais.
Uma variável do tipo decimal não pode exceder 32 dígitos significativos.
CHAR(n)
Alfanumérico de comprimento “n”. Uma variável do tipo CHAR pode ter o tamanho que varia de 1 a 32767.
DATE
Tipo equivalente a uma data, é configurável através da variável de ambiente DBDATE. Internamente, este tipo é armazenado como inteiro, no formato juliano (nº de dias desde 31 de dezembro de 1899). O formato padrão do DBDATE é “mdy4/” ou seja, “mm/dd/yyyy”, onde mm é o mês (1 a 12), dd (1 a 31) é o dia e yyyy o ano (0001 a 9999). O padrão utilizado na Logocenter é “dmy4/”, ou seja, “dd/mm/yyyy”.
Existem ainda dois tipos, compostos dos acima descritos.
ARRAY tipo
Representa uma variável composta por vários elementos do mesmo “tipo”, denominado como vetor. Uma variável deste tipo pode ser definida com 1, 2 ou 3 dimensões de tamanhos distintos entre si, mas sendo todas do mesmo tipo. O tamanho de um array pode variar de 1 até um tamanho limitado ao volume de memória disponível no servidor de aplicação em uso.
Uma variável do tipo ARRAY é uma variável estática, ou seja, a memória consumida será sempre conforme o tipo e o número de elementos, podendo ser bi-dimensional se houver necessidade.
RECORD
Representa uma variável composta por diferentes variáveis de qualquer tipo, incluindo os tipos simples (DATE, CHAR, SMALLINT, INTEGER, etc) e os tipos compostos (ARRAY e RECORD). Assemelha-se ao conceito de variável do tipo STRUCT da linguagem C.
DATETIME
O tipo de dados DATETIME define uma instância de tempo, expressado como uma data do calendário e uma hora do dia. As unidades do tempo que o valor de DATETIME armazena é você quem determina; a precisão pode variar de um ano até uma fração de um segundo. Internamente, os valores são armazenados no formato DECIMAL que representam uma seqüência contígua de valores de unidades de tempo.
A especificação de escala de precisão é chamada de qualificador do DATETIME. Este qualificador é utilizado no formato do "primeiro ao último" para declarar variáveis e campos de tela. Você deve substituir um ou dois destes qualificadores para o primeiro e o último termo.
Qualificador | Unidade de tempo / faixa de valores |
YEAR | Um ano, variando de 0001 até 9999. |
MONTH | Um mês, variando de 1 a 12. |
DAY | Um dia, variando de 1 a 31. |
HOUR | Uma hora, variando de 0 a 23. |
MINUTE | Um minuto, variando de 0 a 59. |
SECOND | Um segundo, variando de 0 a 59. |
FRACTION(escala) | Um décimo de fração de um segundo, com uma escala de até 5 dígitos, sendo que a escala padrão é de 3 dígitos. |
O qualificador especificado por último não pode representar uma unidade de tempo maior do que o primeiro. Assim, o YEAR TO SECOND ou HOUR TO HOUR são válidos, mas o DAY TO MONTH resulta em um erro do compilador, porque o valor para o último qualificador (aqui MONTH) especifica uma unidade de tempo maior do que o DAT, o primeiro qualificador.
O formato de uma variável do tipo DATETIME é “yyyy-mm-dd hh:mm:ss.fffff”, onde yyyy é o ano, mm é o mês, dd é o dia, hh é a hora, mm é os minutos, ss é os segundos e fffff é a fração de segundos.
2.3 Variáveis
Uma linguagem, deve possuir sempre alguma forma de armazenar em memória uma informação necessária para execução dos programas. Tal como nas linguagens de terceira geração, no 4GL existem variáveis.
Uma variável pode ser de qualquer dos tipos definidos anteriormente.
A declaração de variáveis é sempre efetuada depois da palavra chave "DEFINE". Uma variável declara-se da seguinte forma:
DEFINE nome_da_variavel TIPO |
No segundo caso cria-se uma nova variável cuja estrutura condiz com a estrutura de uma coluna de uma tabela do banco de dados. Sempre que uma variável for declarada usando a instrução LIKE, deve existir no início do módulo (fonte .4gl) uma instrução DATABASE que indica o banco de dados a ser usado para obter informações de definição das colunas utilizadas na declaração de variáveis.
Um caracter ou uma faixa de caracteres (substring) pertencentes a uma variável do tipo CHAR pode ser acessado utilizando o operador “[]” (colchetes), assim:
l_texto[1] |
No primeiro caso está se obtendo o primeiro caracter da variável l_texto. Já no segundo caso, está se obtendo 4 caracteres da variável l_texto, referente a posição inicial 2 até a posição 5.
Se a variável for um DATETIME deve-se declarar da seguinte forma:
nome_do_datetime DATETIME qualificador_inicial TO qualidificador_final |
Para uma variável DATETIME que tem o formato que vai do ano até 5 dígitos de fração de segundo, deve-se definir assim:
l_datahora DATETIME YEAR TO FRACTION(5) |
Se a variável for um RECORD deve-se apenas declarar da seguinte forma:
nome_do_record RECORD OU nome_do_record RECORD LIKE tabela.* |
No segundo caso é criada uma estrutura com elementos idênticos a todas as colunas de uma tabela do banco de dados corrente.
Um elemento de uma variável tipo RECORD pode ser acessado através do operador "." (ponto), assim:
lr_dados.codigo OU lr_dados.* |
Este representa o elemento “codigo” do RECORD “lr_dados”. A notação ".*" pode ser usada em alguns contextos para indicar todos os elementos de um RECORD.
Se a variável elementos das variáveis tipo ARRAY podem ser acessadas através do operador [] (colchetes) e dá indicação do número do elemento a que se quer ter acesso, assim:
la_dados[10] |
Neste caso representa o 10º elemento do ARRAY la_dados.
Se a variável for um array deve ser declarada da seguinte forma:
nome_da_variavel ARRAY[m,n,...] OF tipo |
Os elementos das variáveis tipo ARRAY podem ser acessadas através do operador [] (colchetes) e dá indicação do número do elemento a que se quer ter acesso, assim:
la_dados[10] |
Neste caso representa o 10º elemento do ARRAY la_dados.
Para acessar um elemento de uma variável do tipo ARRAY do tipo RECORD utiliza-se o “.” (ponto) após a determinação da posição desejada do ARRAY, assim:
la_dados[5].codigo |
Neste caso, representa o valor da variável “codigo” pertencente ao 5º elemento do ARRAY la_dados.
Para acessar um conjunto de caracteres de uma variável do tipo CHAR, sendo esta um componente de um ARRAY do tipo RECORD, utiliza-se o ponto após a determinação da posição desejada do ARRAY e o operador “[]” (colchetes) para determinar o conjunto de caracteres desejados da variável tipo CHAR, assim:
la_dados[3].descricao[5,10] |
Neste caso está se obtendo o conjunto de caracteres da posição 5 até a 10 da variável descrição pertencente ao 3º elemento da variável la_dados (ARRAY do tipo RECORD).
As variáveis podem ser locais a uma função, globais a um módulo (modulares) ou programa (globais).
O escopo de referência de uma variável é determinado pelo lugar em que a cláusula DEFINE aparece no fonte .4gl. Os identificadores de variáveis podem ser locais, modulares, ou (em alguns casos) globais em seu escopo:
2.3.1 Variáveis locais
DEFINE nome_da_variável tipo [, ...] |
As variáveis locais precisam ser declaradas no início de cada função e somente são reconhecidas dentro do escopo da função em que foram declaradas.
varlocal.4gl MAIN FUNCTION mostra_local() FUNCTION mostra_local_agora(l_inteiro) RESULTADO: |
Exemplo com variáveis locais
Se declarar duas variáveis com o mesmo nome em duas funções distintas, cada variável somente será reconhecida na função de declaração. Concluindo, as variáveis com o mesmo nome localizadas em funções diferentes são variáveis diferentes.
2.3.2 Variáveis globais
GLOBALS "fonte.4gl" OU GLOBALS |
Definição genérica de uma declaração global
Como se pode ver acima, a instrução GLOBALS tem duas formas possíveis. Na primeira indica-se o nome de um fonte que contém um conjunto de instruções DEFINE e uma instrução DATABASE. A vantagem deste sistema é o conhecimento das variáveis globais em todos os módulos sem necessidade de declará-las em cada um deles.
Da outra forma, a instrução GLOBALS é constituída por uma instrução DEFINE.
varglob1.4gl GLOBALS MAIN
varglob2.4gl GLOBALS FUNCTION mostra_varglob2() RESULTADO: |
Exemplo com variáveis globais
No programa dado como exemplo não havia grande necessidade de declarar as variáveis como globais. Á medida que for programando pode-se sentir a necessidade de utilizar este tipo de variável.
2.3.3 Variáveis modulares
DEFINE nome_da_variável tipo [, ...] |
As variáveis modulares tem que ser declaradas no inicio do fonte, fora do escopo de definição de variáveis globais (GLOBALS..END GLOBALS) e fora do escopo de qualquer função (MAIN, FUNCTION, REPORT). Variáveis modulares somente são reconhecidas dentro do escopo do fonte (módulo) em que foram declaradas.
varmod1.4gl DEFINE m_inteiro INTEGER MAIN varmod2.4gl DEFINE m_inteiro INTEGER END FUNCTION RESULTADO |
Exemplo com variáveis modulares |
Se declarar duas variáveis modulares com o mesmo nome em dois fontes (módulos) distintos, cada variável só vai ser reconhecida no fonte onde foi declarado. Efetivamente as variáveis com o mesmo nome localizadas em fontes diferentes são variáveis diferentes.
2.3.4 Atribuições, comparações e inicializações
Uma das operações básicas a realizar sobre variáveis é a atribuição.
No 4GL para atribuir a uma variável um valor constante, expressão ou conteúdo de outra variável, utiliza-se o seguinte formato:
LET variável = {expressão | variável | constante} |
No 4GL pode-se inicializar uma variável de qualquer tipo básico. As variáveis compostas só podem ser inicializadas através dos seus elementos constituintes.
afecta.4gl DATABASE livros SELECT * RESULTADO: |
Conforme se viu, inicializou-se variáveis de diversos tipos elementares e compostos. Nos tipos compostos, o número e tamanho das variáveis elementares que dele fazem parte tem de ser iguais.
Nesta linguagem, não há diferença entre o operador "=" usado na inicialização e na comparação. Este fato deve-se a identificação destas operações serem efetuadas por intermédio do contexto em que as instruções estão incluídas.
Quando se inicializa uma variável com uma expressão, esta é automaticamente convertida para o tipo da variável, se a conversão resultar em erro, o programa notifica com erro de execução. Por exemplo, na instrução LET i ="10" se a variável i for um inteiro, a expressão "10" é automaticamente convertida em inteiro.
compara.4gl MAIN DEFINE y CHAR(20) IF y < "uma string" THEN IF y = "Uma string" THEN RESULTADO: |
Em qualquer programa, muitas vezes é necessário proceder as inicializações de variáveis.
Uma das formas de o fazer é inicializando a variável com o valor pretendido, na área do programa em que se pretende fazer. Outra forma é utilizando a instrução INITIALIZE.
INITIALIZE lista_de_variáveis TO NULL |
A instrução INITIALIZE inicializa as variáveis com valor NULL.
2.3.5 Operadores
Os operadores de comparação no Informix 4GL são:
Operador | Descrição | Exemplo |
> | maior que | var1 > var2 |
< | menor que | var1 < var2 |
>= | maior ou igual que | var1 >= var2 |
<= | menor ou igual que | var1 <= var2 |
= ou == | igual a | var1 = var2 |
!= ou <> | diferente de | var1 <> var2 |
NOT | negação | NOT <expressão> |
AND | e | <expressão1> AND <expressão2> |
OR | ou | <expressão1> OR <expressão2> |
MATCHES | comparação usando metacarateres (*, ?, []) | var1 MATCHES “*z?” |
LIKE | comparação usando metacaracteres (-, %) | var1 LIKE “%z_%” |
BETWEEN | intervalo de valores | BETWEEN 1 AND 100 |
IN | conjunto de valores | NOT IN (“A”,”B”,”C”) |
IS NULL | teste de valor nulo | var1 IS NULL / var2 IS NOT NULL |
Os operadores para cálculos matemáticos, no 4GL são:
Operador | Descrição | Exemplo |
+ | adição | var1 + var2 |
- | subtração | var1 - var2 |
** | exponenciação | var1 ** var2 |
MOD | módulo (divisão inteira c/ retorno do resto da divisão) | var1 MOD var2 |
* | multiplicação | var1 * var2 |
/ | divisão | var1 / var2 |
Os demais operadores existentes são:
Operador | Descrição | Exemplo |
. | Para referenciar um membro de uma variável do tipo RECORD. | lr_dados.código |
[] | Para referenciar um elemento de uma variável do tipo ARRAY ou um conjunto de caracteres de uma variável do tipo CHAR. | la_dados[10] |
() | Para chamada de funções. | CALL entrada_dados() |
UNITS | Para referenciar a unidade de qualificador. | LET data = data + 5 UNITS DAY |
|| ou , | Concatenação | “abc” || “def” ou “abc”,”def” |
ASCII | Retorna o caracter ASCII correspondente. | LET letra = ASCII(65) |
ORD | Retorna o código ASCII correspondente. | LET cod_ascii = ORD(“A”) |
CLIPPED | Elimina espaços em branco do final de um string. | LET l_texto = l_texto CLIPPED, “x” |
COLUMN | Para posicionar a coluna de impressão de dados. | PRINT COLUMN 10, “Texto”. |
SPACES | Para inserir espaços em branco. | DISPLAY 5 SPACES |
USING | Para formatar um conteúdo atribuído a um string. | LET texto = TODAY USING “dd/mm/yy” |
WORDWRAP | Impressão de um texto com quebra automática de linhas. | PRINT texto WORDWRAP |
2.3.6 Concatenação de variáveis tipo CHAR
No 4GL é muito simples concatenar strings, basta separá-las por uma virgula (o operador de concatenação de strings é a virgula).
concat.4gl MAIN RESULTADO |
2.4 Funções
Uma função é um conjunto de instruções que são executadas conjuntamente e que pode receber um conjunto de parâmetros e devolver valores.
O 4GL apesar de ser uma linguagem de 4ª geração possui esta capacidade das linguagens estruturadas.
FUNCTION nome_da_funcao([arg1,arg2,...,argn]) |
Uma função é identificada por um nome, começa com a palavra chave FUNCTION e termina com as palavras chave END FUNCTION, exceto a função MAIN que não tem nome e é delimitada por MAIN...END MAIN.
olafuncao.4gl MAIN FUNCTION funcao_ola() RESULTADO: |
Numa função, além de poder ter variáveis locais, pode ainda ter variáveis de entrada (parâmetros), e, ter associação valores a serem retornados á função que a invocou (valores de retorno). Tanto os parâmetros como os valores de retorno podem ser de qualquer tipo permitido pelo 4gl. A chamada da função faz-se com a instrução CALL e para definir em que variáveis são atribuídos os valores devolvidos usa-se a cláusula RETURNING com uma lista de variáveis a retornar.
CALL função([argumentos]) [RETURNING lista_de_variáveis] |
Se uma função devolver apenas um valor pode-se chamar com a instrução LET.
LET variavel = função([argumentos]) |
Os parâmetros de uma função são sempre declarados. Esta declaração faz com que a linguagem verifique todas as chamadas ás funções e no caso destas não serem executadas com o mesmo número de parâmetros que a declaração da função resulta em um erro de compilação do programa.
max.4gl MAIN FUNCTION maximo(n1,n2,n3) IF n1 > n2 THEN RETURN n3 END FUNCTION RESULTADO: |
Para retornar determinado valor a partir de uma função usa-se a palavra chave RETURN.
Ao contrário de algumas linguagens de terceira geração (por exemplo o C), uma função de 4GL não necessita ser declarada como um determinado tipo, ou seja, se pretender que a função devolva o número inteiro 10, só terá que retornar um valor de tal tipo:
retfunc1.4gl MAIN FUNCTION FUNC() RESULTADO: |
Se pretender devolver uma string poderá também o fazer:
retfunc2.4gl MAIN FUNCTION FUNC() RESULTADO: |
É preciso ter cuidado para que a variável em que se atribui o retorno da função seja do mesmo tipo do valor (ou variável) retornado dentro da função.
retfunc3.4gl MAIN CALL func() RETURNING x,y DISPLAY x END MAIN FUNCTION func() RESTULTADO: |
Uma função (FUNCTION ou REPORT) não pode ter como parâmetro ou retorno uma variável do tipo ARRAY. O mesmo também se restringe a variáveis do tipo RECORD que possui componente definido como tipo ARRAY.
2.5 Conversões de tipos
Como já foi visto anteriormente, quando se falou de inicializações, as expressões no 4GL são sempre convertidas para o tipo necessário ao contexto onde são incluídas, não existem por isso operadores de conversão de tipo como noutras linguagens, a única exceção é o operador DATE(...) que converte uma expressão para um tipo DATE.
Esta situação pode tornar-se problemática na conversão de tipos, podendo no entanto contornar o problema declarando uma variável do tipo para o qual se quer converter a expressão e inicializando a variável com a expressão.
3 Comandos de controle sequencial
A construção de um programa implica a tomada de decisões, a repetição de instruções parametrizadas, etc. No 4GL encontram-se alguns dos mecanismos de controle e repetição existentes nas linguagens de terceira geração.
3.1 IF..THEN..ELSE..END IF
Esta instrução existe na maioria das linguagens. A decisão é realizada a partir de uma expressão booleana.
Em português esta instrução poderia ser explicada por:
Se esta expressão é verdadeira |
Em que "faz isto" e "faz aquilo" seria um conjunto de instruções a executar em cada um dos casos.
IF expressão_booleana THEN |
Definição geral da instrução IF...THEN...ELSE
Uma expressão booleana pode, por exemplo, ser um conjunto de comparações entre expressões, sendo possível realizar operações booleanas entre expressões, nomeadamente:
AND A expressão é verdadeira se todas as sub-expressões também forem verdadeiras.
IF a = "casado" AND b = "solteiro" THEN |
Utilização de AND numa expressão
OR A expressão é verdadeira se pelo menos uma das sub-expressões for verdadeira.
IF cao = "morde" OR cao = "grande" THEN |
Utilização de OR numa expressão
NOT A expressão é verdadeira se a sub-expressão não o for.
IF NOT ha_cerveja THEN |
Utilização de NOT numa expressão
3.2 WHILE
Esta instrução de repetição pode ser explicada por:
Enquanto esta_expressão_for_verdadeira faz_isto |
WHILE é um conjunto de instruções a serem executadas se a expressão booleana for verdadeira.
WHILE expressao_booleana |
Definição genérica da instrução WHILE
Uma expressão booleana usada no WHILE é idêntica a usada no IF e a qualquer outra que se utilize num programa.
WHILE esta <> "bebado" |
Ciclo WHILE
Existem duas instruções que podem ser usadas dentro de um WHILE:
- EXIT WHILE
- CONTINUE WHILE
EXIT WHILE, serve para abandonar o ciclo independentemente da expressão booleana do WHILE.
CONTINUE WHILE, quando invocada, provoca um reposicionamento no início do ciclo (com o correspondente teste de continuidade do ciclo) sem cumprir as instruções que se encontravam abaixo.
3.3 FOR
As vezes é necessário executar um ciclo por um determinado número de vezes, incrementando uma variável com um valor.
FOR variavel_inteira = expressão1 TO expressao2 |
Definição genérica do ciclo FOR
A instrução acima definida inicializa a variavel_inteira com o resultado da expressão1 e cumpre as instruções até que a expressão2 seja falsa, incrementando a variável_inteira com o resultado de expressão3. Se o programador, por alguma razão desejar sair do ciclo, pode utilizar a instrução EXIT FOR. Se, por outro lado já não pretender executar as instruções abaixo e continuar a partir do próximo ciclo, pode utilizar a instrução CONTINUE FOR. Estas duas ultimas instruções são análogas às instruções existentes no ciclo WHILE, incidindo no entanto somente sobre o comando FOR.
3.4 CASE
As vezes é necessário tomar uma decisão múltipla, isso pode ser feito com uso de várias instruções IF agrupadas. A instrução CASE surge como uma forma mais simples de resolver esta questão.
CASE [(expressão)] |
Definição genérica da instrução CASE
A instrução CASE pode ser utilizada de duas formas diversas:
- Por expressões;
- Por expressões booleanas.
3.4.1 SELEÇÃO REALIZADA POR EXPRESSÕES
CASE (expr) |
Forma geral de CASE com seleção por expressões
A expressão é comparada com os vários valores, sendo executadas as instruções associadas ao primeiro valor igual ao resultado da expressão. Se todos os valores forem diferentes do resultado da expressão, são executadas as instruções associadas á cláusula OTHERWISE, se esta existir.
case1.4gl DATABASE livros MAIN LET ans = "s" WHILE 1 SELECT livros.nome DISPLAY nome CASE (ans) $ fglpc case1.4gl |
Utilização do CASE utilizando expressões para fazer a seleção
Na execução deste programa, quando se perguntou ao usuário se desejava procurar mais livros, ele respondeu a letra <g> quando as opções válidas eram <s> ou <n> e neste caso o programa entrou na cláusula OTHERWISE do CASE.
Neste caso a seleção do CASE pretendido é realizado quando o resultado da expressão existente junto da palavra chave CASE é idêntico ao resultado de uma das expressões junto a uma das palavras chave WHEN. Note que, se existirem duas expressões que tenham resultado de igual valor, é executada a que aparece em 1º lugar.
3.4.2 SELEÇÃO REALIZADA POR EXPRESSÃO BOOLEANA
A instrução CASE com expressões booleanas toma a seguinte forma:
CASE |
Instrução CASE com seleção por expressão booleana
As expressões booleanas são avaliadas na ordem em que aparecem e é executado o grupo de instruções associado á primeira expressão booleana verdadeira. Se todas as expressões forem falsas são executadas as instruções associadas á cláusula OTHERWISE.
Em qualquer das formas da instrução CASE pode-se incluir no bloco de instruções uma instrução EXIT CASE que provoca a interrupção do CASE neste ponto.
case2.4gl MAIN $ fglpc case1.4gl |
Utilização do CASE utilizando expressões para fazer a seleção
4 BIBLIOTECA 4GL
Este capítulo descreve as funções que estão disponíveis na biblioteca do INFORMIX-4GL. Qualquer uma das funções apresentadas em seguida podem ser chamadas num programa, que o compilador automaticamente linka ao programa.
Em seguida estão as descrições das funções da biblioteca:
ARG_VAL(expressão)
Esta função recebe como argumento uma variável tipo INTEGER, devolve o argumento correspondente a esse número que lhe foi passado pela linha de comando.
A função ARG_VAL(n) devolve o n-ésimo argumento da linha de comando, sendo do tipo CHAR. O valor da expressão tem de estar entre 0 e NUM_ARGS() do número de argumentos passados pela linha de comando. ARG_VAL(0) corresponde ao nome do programa em execução.
As funções ARG_VAL e NUM_ARGS permitem passar dados ao programa a partir da linha de comando quando este é executado.
Suponhamos que o nosso programa de 4GL compilado se chame teste.4go. Ao executá-lo a partir da linha de comando fazemos:
fglgo teste Maria Pedro Catarina |
Execução de um programa de 4GL, com argumentos
O programa que se segue é um exemplo, recebe os nomes num ARRAY de variáveis do tipo CHAR
ARR_COUNT()
Esta função devolve o número de linhas introduzidas num ARRAY de um programa durante ou após a instrução INPUT ARRAY.
Quando se executa uma instrução com a cláusula BEFORE, AFTER ou ON KEY, o valor de ARR_CURR, SCR_LINE ou ARR_COUNT, é alterado, e o valor resulta da execução das cláusulas.
FUNCTION inserir_livros() FOR contador = 1 TO arr_count() |
Exemplo de utilização da função ARR_COUNT
ARR_CURR()
Esta função devolve a linha do ARRAY do programa que corresponde à linha do ARRAY corrente da tela durante ou imediatamente após a instrução INPUT ARRAY ou DISPLAY ARRAY.
A linha corrente do ARRAY da tela corresponde à linha onde está localizado o cursor no inicio de uma cláusula BEFORE ROW ou AFTER ROW.
A primeira linha tanto do ARRAY do programa ou da tela é numerada a partir de 1.
INPUT ARRAY ma_livros TO sr_livros.* |
Exemplo da utilização da função ARR_CURR
DOWNSHIFT(frase)
Esta função devolve uma string em que todos os caracteres que lhe tenham sido passados em letras maiúsculas sejam convertidos em minúsculas.
Se o caracteres passados como argumentos à função forem numéricos, estes não serão alterados.
A função DOWNSHIFT pode ser usada numa expressão ou para atribuição a uma variável com o valor devolvido pela função.
LET l_str = DOWNSHIFT(l_str) |
Exemplo de utilização da função DOWNSHIFT
UPSHIFT(frase)
Esta função devolve uma string em que todos os caracteres que lhe tenham sido passados em letras minúsculas sejam convertidos em maiúsculas.
Se os caracteres passados como argumentos à função forem numéricos, este não serão alterados.
A função UPSHIFT pode ser usada numa expressão ou para atribuição a uma variável com o valor devolvido pela função.
LET l_str = UPSHIFT(l_str) |
Exemplo de utilização da função UPSHIFT
ERR_GET(expressão)
Esta função devolve uma variável do tipo CHAR que contém a mensagem de erro, correspondente ao código enviado como argumento.
Geralmente a expressão é a variável global STATUS ou SQLCA.SQLCODE.
A utilização desta função é muito importante durante as operações de debug.
IF status < 0 THEN |
Exemplo de utilização da função ERR_GET
ERR_PRINT(expressão)
Esta função escreve a mensagem de erro do INFORMIX-4GL, correspondente ao seu argumento, na ERROR LINE (linha de erro).
Mais uma vez, em geral a expressão é a variável global STATUS ou SQLCA.SQLCODE.
A utilização desta função é muito importante durante as operações de debug.
IF status < 0 THEN |
Exemplo de utilização da função ERR_PRINT
ERR_QUIT(expressão)
Esta função escreve a mensagem de erro do INFORMIX-4GL, correspondente ao seu argumento, na ERROR LINE (linha de erro) e interrompe a execução do programa.
CALL ERR_QUIT(expressão) |
Formato da função ERR_QUIT
Geralmente a expressão é a variável global STATUS ou SQLCA.SQLCODE.
A utilização desta função é muito importante durante as operações de debug.
IF status < 0 THEN |
Exemplo de utilização da função ERR_QUIT
5 Comandos básicos para entrada/saída de dados
5.1 PROMPTS
Em 4GL, uma das formas do programa se comunicar com o usuário, é por intermédio da instrução PROMPT. Esta instrução envia uma mensagem para o aplicativo e recebe um caracter ou seqüência de caracteres que foram digitados pelo usuário no seu terminal.
A definição genérica de uma instrução PROMPT é a seguinte:
PROMPT mensagem FOR [CHAR] variável |
Definição genérica da instrução PROMPT
As mensagens assinaladas são um conjunto de uma ou mais variáveis, ou string(s) constantes, separados por vírgula.
Se a instrução for invocada com a palavra chave CHAR, o programa não espera pela tecla <NEW LINE>, o que equivale a dizer que aceita o caracter e sai da instrução PROMPT assim que é pressionada uma tecla.
prompt.4gl DATABASE livros MAIN LET ans = "s" WHILE (ans = "s" OR ans = "S") SELECT livros.nome DISPLAY nome END WHILE $ fglpc prompt.4gl |
Utilização da instrução PROMPT
Quando o programa proposto é executado, pede ao usuário que digite o número do livro do qual pretende saber o nome, faz uma busca no banco de dados para descobrir o nome e pergunta se o usuário pretende ou não continuar a executar essa tarefa.
No programa, quando é executada a primeira instrução PROMPT, como não existe a palavra CHAR, é permitido digitar vários caracteres ou dígitos, e terminar pressionando <ENTER>. Na segunda instrução PROMPT, tal tecla já não é necessária, pois assim que foi informada a tecla <n> o programa continuou a sua execução.
5.2 MENUS
Uma forma simples de perguntar ao usuário qual tarefa pretende executar de um conjunto de N opções é a utilização de menus.
No 4GL é bastante fácil construir menus horizontais. Nestes menus, cada opção é identificada por uma pequena palavra e uma linha de explicação. Uma opção de menu encontra-se sempre destacada, sendo selecionada pressionando a tecla <ENTER>. Pode-se mudar a opção selecionada com a barra de espaços, as setas ou a primeira letra da opção desejada. Podem também criar-se opções invisíveis. Se as opções não couberem todas no menu, este é prolongado automaticamente com "..." (3 pontos) significando que se podem ser acessadas as outras opções que não estão visíveis.
Para construir um menu usa-se a instrução MENU cuja definição genérica é:
MENU "nome_do_menu" [BEFORE MENU] instruções |
Definição genérica de uma instrução MENU
As cláusulas CONTINUE MENU (Interrupção das instruções de uma opção de menu selecionada), NEXT OPTION (Reposicionar o cursor para outra opção do menu), e EXIT MENU (sair do menu) podem ser colocadas dentro de outras instruções, desde que estejam dentro de uma instrução MENU. Estas cláusulas permitem uma grande otimização do comportamento do menu para o usuário pois pode haver reposicionamento na opção que logicamente deveria ser escolhida.
Se for utilizada a cláusula de HELP, quando pressiona a tecla de help, o programa chama a função show_help e envia o help com o número pretendido para visualização na tela.
A cláusula KEY é ótima para definir opções escondidas, e/ou atribuir uma nova tecla de atalho a uma opção.
Se houver a necessidade de tornar invisível alguma opção de menu em tempo de execução é possível utilizar a instrução HIDE OPTION “opção”. Já para tornar visível uma opção de menu tida antes como invisível pode-se utilizar a instrução SHOW OPTION “opção”.
Se houver necessidade de executar uma ou mais instruções no início do menu, antes de apresentá-lo ao usuário na execução é possível definir o bloco de comandos BEFORE MENU.
5.3 DISPLAY AT
Se pretender enviar pequenas mensagens ao usuário utiliza-se no 4GL a instrução DISPLAY AT.
DISPLAY lista_de_variaveis |
Definição da instrução DISPLAY AT
lista_de_variaveis
É um conjunto de uma ou mais variáveis do programa ou string(s) constantes separadas por vírgulas.
linha_da_tela e coluna_da_tela
São as coordenadas da tela que definem o local onde vai aparecer a mensagem pretendida
lista de atributos
É um conjunto de atributos possiveis a utilizar quando se envia a mensagem para a tela.
Os atributos possiveis são:
WHITE | REVERSE |
Atributos de tela possíveis
A instrução DISPLAY é complexa e no capítulo sobre gestão de telas será novamente abordada.
Esta instrução envia para a tela uma mensagem constituída por um conjunto de variáveis e strings definidas na instrução. Em alguns dos exemplos anteriores, esta instrução já foi usada na sua forma mais simples.
display.4gl MAIN $ fglpc display.4gl Isto vai aparecer na tela na linha 10 coluna 3 |
Programa utilizando DISPLAY AT com ATTRIBUTES
5.4 Exercício – Instrução PROMPT e MENU
Criar um programa que tenha 2 opções de menu. As 2 opções de menu deverão acionar uma única função, mas passando um argumento diferente para permitir a identificação da opção de menu selecionada por parte da função.
Na função deverá ser apresentada uma pergunta ao usuário, utilizando o comando PROMPT, mas estas perguntas deverão ser diferentes, ou seja, caso seja acionada a primeira opção do menu, deverá apresentar uma pergunta, e ser for acionada a outra opção de menu deverá aparecer uma outra pergunta ao usuário.
Ambas as perguntas deverão aceitar como resposta somente as letras S (Sim) ou N (Não), não importando se for em letra maiúscula ou minúscula. Apresentar mensagem de erro ao usuário caso seja informada uma opção inválida.
Após responder a pergunta, deverá apresentar uma mensagem apresentando a opção selecionada.
6 Gestão de erros
No 4GL, depois de compilar com sucesso um programa, existem vários tipos de erros que ainda podem estar sujeito a ocorrer.
É possível que o programa ainda possua erros de lógica (bugs), ou devido a uma má utilização do programa, surja uma situação de erro.
O usuário do programa, sem conhecimentos de programação nem acesso aos fontes, deve receber uma mensagem de erro que o ajude a corrigir a sua utilização ou solicitar a correção aos programadores.
6.1 Como apanhar um erro
No 4GL existe a instrução WHENEVER que permite alterar a forma como o programa se comporta ao ser confrontado com uma situação de erro ou aviso (warning).
WHENEVER {ERROR | WARNING} |
Definição genérica da instrução WHENEVER
A primeira opção na cláusula (ERROR/WARNING) informa sobre a situação de erro ou aviso para a qual se vai tomar determinada ação, se ocorrer. Numa situação de erro (ERROR), pede-se ao programa que efetue determinada tarefa que ele não pode efetuar dessa forma e nesse contexto, a instrução WHENEVER é utilizada com a cláusula ERROR. Numa situação de aviso (WARNING), a tarefa pode ser cumprida ainda que não seja uma situação usual e então a instrução WHENEVER é invocada com a cláusula WARNING.
A segunda cláusula diz a ação que deve ser tomada quando confrontado com uma situação. As ações possíveis são:
GOTO label
Quando for encontrada esta situação, o programa deve continuar a partir da instrução assinalada por uma label. Um label é assinalado colocando-se um nome de label qualquer seguido do caracter ":" (dois pontos).
FUNCTION exp() RETURN LABEL erro: |
WHENEVER com GOTO
CALL nome_de_função
Quando for encontrada uma situação de erro, é executada a função nome_de_função.
FUNCTION exp() RETURN FUNCTION erro() |
Exemplo de WHENEVER com CALL
STOP
Quando é utilizada a cláusula STOP, o programa ao ser confrontado com uma situação de erro ou aviso cujo código de erro seja negativo (sqlca.sqlcode < 0 ou status < 0), o programa é abortado e enviada para a tela uma pequena explicação do erro ocorrido.
CONTINUE
Quando é utilizada a cláusula CONTINUE o programa nunca é interrompido em situação de erro do SQL.
Para que possa ser haver controle da execução do programa neste caso, é preciso testar a variável STATUS ou a estrutura SQLCA.
6.2 A variável STATUS
Existente em qualquer programa 4GL, a variável denominada STATUS, pré-definida como global, possui o valor 0 (zero) para indicar que não houve erro e diferente de 0 (zero) para indicar a ocorrência de algum erro na execução de uma instrução.
6.3 A estrutura SQLCA
As vezes a variável STATUS não chega a identificar o erro ou aviso que ocorreu. Neste caso existe um RECORD global chamado SQLCA, que identifica os tipos de erros e avisos. Geralmente usa-se a estrutura SQLCA como adicional ao STATUS que identifica a existência de erro.
SQLCA RECORD |
RECORD SQLCA
O significado de cada uma das variáveis é:
SQLCODE: Indica o resultado de uma instrução de SQL.Toma os valores:
0 instrução bem sucedida.
NOTFOUND busca bem sucedida mas não devolveu nenhuma linha.
SQLERRM: não é utilizado.
SQLERRP: não é utilizado.
SQLERRD: É um ARRAY de 6 inteiros com o seguinte significado:
sqlerrd [1]: não é utilizado.
sqlerrd [2]: Valor retornado pelo C-ISAM (Ver erros do C-isam).
sqlerrd [3]: número de linhas processadas.
sqlerrd [4]: não é utilizado.
sqlerrd [5]: caracter da string em foi encontrado erro.
sqlerrd [6]: é o ROWID da última linha.
SQLWARN: É um ARRAY de 8 caracteres que assinalam várias situações que necessitam de aviso durante a execucão de uma instrução SQL.
sqlwarn[1]: Se contiver:
- Caracter W: Um ou mais dos outros elementos do ARRAY contêm 'W'
- Espaço: Não é necessário verificar os outros elementos do ARRAY.
sqlwarn[2]: Se contiver:
- Caracter W: Os dados de uma ou mais colunas foi truncado para caber dentro de uma variável.
- Espaço: Nenhum dado foi truncado.
sqlwarn[3]: Se contiver:
- Caracter W: Foi encontrado um erro numa função agregada (SUM, AVG, MAX ou MIN) A NULL.
- Espaço: Não houve problemas.
sqlwarn[4]: Se contiver:
- Caracter W: O número de itens de um SELECT é diferente do número de variáveis da cláusula INTO.
- Espaço: Não houve erro.
sqlwarn[5]: Nao é utilizado.
sqlwarn[6]: Nao é utilizado.
sqlwarn[7]: Nao é utilizado.
sqlwarn[8]: Nao é utilizado.
7 Formulários de telas
Antes que um programa 4GL possa usar um formulário de tela, você deve primeiramente criar e compilar uma arquivo de especificação do formulário de tela.
Um formulário de tela é uma representação visual que pode suportar tarefas da entrada ou saída em uma aplicação de INFORMIX-4GL.
Esta especificação é fonte no formato texto onde se descreve o formato lógico do formulário da tela, e fornece instruções ao 4GL sobre como indicar valores dos dados no formulário no momento da execução.
As instruções de acesso as forms fazem parte da linguagem 4GL, e têm como objetivo o acesso á form. As principais são: OPEN FORM; DISPLAY; DISPLAY ARRAY; INPUT; INPUT ARRAY; etc.
Algumas instruções de entrada/saída básicas já foram citadas, elas são: DISPLAY AT; PROMPT; MENU.
A interação com a entrada de dados é sempre realizada por intermédio de um gestor de janelas. Muitas vezes o programador não percebe este fato. Existem algumas instruções e opções para controlar este gestor, das quais pode-se destacar: OPEN WINDOW; CURRENT WINDOW; CLOSE WINDOW; OPTIONS: MESSAGE LINE; etc.
As forms e instruções de INPUT, por si só não acessam nem escrevem em tabelas do banco de dados. Nas forms associam-se colunas de tabelas aos campos para que os programas possam definir os tipos de variáveis internas que vão utilizar, ou declaram-se diretamente os campos a partir dos tipos básicos.
O fluxo de informação de uma tela para a base de dados poderia ser descrito pelo seguinte esquema:
+-------+ +---------------------------------+ |
Comunicação das telas com o banco de dados
7.1 FORM
As forms servem para desenhar e processar entrada de dados.
Uma form é escrita num arquivo, através de um editor de texto, e depois compilada pelo programa form4gl. A versão compilada pode então ser executada sempre que necessário por um programa em 4gl.
Assim, a form tem como suporte físico dois arquivos: o programa fonte com a extensão ".per" e o programa compilado com a extensão ".frm".
Uma form é um programa que se compila com o comando "form4gl" e gera um executável com a extensão .frm. A execução do .frm é feita pelo programa 4GL que, durante a execução abre e manipula a form por intermédio de instruções próprias.
+----------+
+----------+
+----------+ |
Compilação de uma form
7.2 Definição de uma form
Através de um editor de texto define-se um arquivo com a definição da form no seguinte formato:
DATABASE [FORMONLY | <nome banco dados>] [TABLES] ATTRIBUTES [INSTRUCTIONS] |
Exemplo de definição de form
Estas seções são o esqueleto de qualquer form. Manipulando e inserindo instruções nestas seções consegue-se criar e explorar as capacidades das forms.
7.2.1 DATABASE
Quando um dos campos da form fizer referência na sua definição a uma coluna de uma tabela do banco de dados, da mesma forma com é feita definição de variáveis utilizando a cláusula LIKE, deve definir esta seção com o nome do banco de dados na qual as tabelas estão registradas. Exemplo: DATABASE livros.
Caso não seja feita nenhuma referência a tabelas do banco de dados, pode-se utilizar esta instrução como DATABASE FORMONLY. A palavra FORMONLY é reservada da linguagem 4gl para a situação em que não é feita referência de informações de um banco de dados na definição de uma form.
7.2.2 Seção SCREEN
Nesta seção o programador define o desenho da entrada de dados pretendida para a tela, considerando que todos os campos devem estar presentes numa única entrada de dados.
Esta seção é iniciada com o caracter “{“ e finalizada com “}”, sendo que a definição visual do conteúdo da tela é o que estiver entre estes 2 símbolos.
Cada definição de campo utilizado para edição ou apresentação de algum conteúdo variável durante a execução de um programa é englobado pelos símbolos “[]” (colchetes), sendo que o limite de caracteres permitido na entrada de dados para cada campo corresponde ao número de espaços em branco entre os colchetes.
Cada campo delimitado por colchetes precisa receber uma nomenclatura que é referenciada posteriormente na seção ATTRIBUTES para definição de características de cada campo. Esta nomenclatura é geralmente identificada por uma letra, ou letra seguida de número.
7.2.3 Seção TABLES
Esta seção deve ser obrigatoriamente definida quando a cláusula DATABASE faz referencia a um banco de dados válido.
São colocados os nomes das tabelas do banco de dados indicado na cláusula DATABASE e que são referenciadas na definição de campos da seção ATTRIBUTES, sendo que em caso de mais de uma tabela, deve-se separar estas por vírgula.
Quando é utilizada a cláusula DATABASE FORMONLY esta seção não é definida.
TABLES |
Definição da seção TABLES
7.2.4 Seção ATTRIBUTES
Esta seção de definição do arquivo da form tem o comportamento e o aspecto de cada um dos campos da tela definidos na seção SCREEN. Todo e qualquer campo da seção SCREEN deve ser descrito obrigatoriamente na seção ATTRIBUTES.
Na seção ATTRIBUTES define-se:
- Como o 4GL apresenta o conteúdo do campo na tela;
- Limites de tamanho para os valores/conteúdo a ser informado no campo da tela;
- O tipo do campo, de duas formas: a coluna e tabela a que corresponde ou o tipo elementar do 4GL (SMALLINT, DECIMAL, DATE, etc.);
- O nome do campo para as instruções 4GL que tratam da entrada de dados nas telas. Se o campo for definido como FORMONLY, pode-se escolher um nome qualquer, senão o nome é obrigatoriamente o nome da coluna correspondente do banco de dados.
Se qualquer um dos atributos descrito for utilizado pelo programa 4GL, quando se faz um INPUT sem a cláusula WITHOUT DEFAULTS, os defaults utilizados nos campos são os definidos na seção ATTRIBUTES da tela (atributo DEFAULT), quando definidos, caso contrário serão apresentados em branco. A cláusula WITHOUT DEFAULTS faz com que os valores atuais das variáveis vinculadas aos campos da tela no comando INPUT sejam automaticamente apresentados.
Quando se utiliza a cláusula DATABASE FORMONLY, a definição dos nomes e atributos das colunas devem ser feitas utilizando a palavra “formonly” no lugar do nome da tabela do banco de dados.
Na seção ATTRIBUTES pode-se além de definir o nome e o tipo dos campos da form, definir alguns atributos que serão descritos a seguir.
7.2.4.1 AUTONEXT
Este atributo faz com que o cursor, durante uma instrução de INPUT, salte para o campo seguinte quando o campo atual estiver totalmente preenchido.
f011 = livros.data_entrada, AUTONEXT; |
Exemplo atributo AUTONEXT
7.2.4.2 COMMENTS
Este atributo associa uma mensagem a um campo. Esta mensagem aparecerá na linha correspondente da tela sempre que o cursor estiver posicionado sobre o respectivo campo.
f011 = livros.data_entrada, AUTONEXT, |
Exemplo atributo COMMENTS
7.2.4.3 DEFAULT
Este atributo permite definir um valor inicial no campo da tela a que está associado, quando é invocada a instrução INPUT.
f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY; |
Exemplo atributo DEFAULT
7.2.4.4 FORMAT
Permite controlar o formato de display dos campos a que está associado, desde que tenham tipo de dados numéricos ou do tipo data.
Os caracteres de controle do formato são os seguintes:
###.## | Para campos numéricos (decimal, float e smallfloat). Indica o número de campos à esquerda e à direita do ponto decimal. |
Mm | Para datas. Representação do mês através de dois dígitos. |
Mmm | Para datas. Representação do nome do mês através de abreviatura com três letras (em inglês). |
Dd | Para datas. Representação do dia através de dois dígitos. |
Ddd | Para datas. Representação do nome do dia através de abreviatura com três letras (em inglês). |
Yy | Para datas. Representação do ano através de dois dígitos. |
yyyy | Para datas. Representação do ano através de quatro dígitos. |
As datas podem ter os separadores "-" ou "/" à escolha.
f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY, |
Exemplo atributo FORMAT
Se a variável de ambiente DBDATE já estiver no formato “dmy4/” que indica o formato “dd/mm/yyyy”, não será necessário indicar o formato acima, pois o 4GL já assumirá automaticamente este formato.
7.2.4.5 INCLUDE
Permite especificar valores ou intervalos de valores admissíveis a introduzir num campo associado a este atributo.
Pode-se especificar uma série de valores separados por virgulas ou um valor mínimo e um valor máximo separados pela palavra "TO".
f007 = livros.volumes, INCLUDE = (1 to 100); |
Exemplo atributo INCLUDE
7.2.4.6 NOENTRY
Evita a inclusão de dados quando executa uma instrução INPUT, ou seja, o cursor nunca será posicionado no campo definido como NOENTRY através da instrução INPUT.
A instrução CONSTRUCT ignora este atributo, ou seja, mesmo para um campo definido como NOENTRY, a instrução CONSTRUCT permite acesso normalmente.
7.2.4.7 REVERSE
Este atributo mostra os campos, a que está associado, com caracteres em vídeo reverso.
f000 = livros.numero, REVERSE; |
Exemplo atributo REVERSE
7.2.4.8 PICTURE
Permite definir o formato de entrada de um campo da tela, para campos do tipo alfanumérico.
O formato do campo define-se com o atributo PICTURE, combinando o seguinte conjunto de caracteres:
A Representa qualquer letra.
# Representa qualquer dígito.
X Representa qualquer caracter.
f001 = formonly.num_matricula CHAR(08), AUTONEXT, PICTURE = "##.###-#"; |
Exemplo de utilização do atributo PICTURE
7.2.4.9 VERIFY
Este atributo usa-se quando se pretende introduzir, num determinado campo, o mesmo valor duas vezes para reduzir a probabilidade de erro na entrada dos dados.
7.2.4.10DOWNSHIFT
Transforma as letras maiúsculas informadas em um campo alfanumérico em letras minúsculas automaticamente durante a digitação.
7.2.4.11UPSHIFT
Transforma as letras minúsculas informadas em um campo alfanumérico em letras maiúsculas automaticamente durante a digitação.
7.2.5 Seção INSTRUCTION
A seção INSTRUCTION é opcional e é a última seção a ser definida em uma form.
No 4GL, a única operação que podemos realizar nesta seção é a instrução DELIMITERS e a definição de SCREEN RECORDS.
Em um capítulo mais adiante será apresentada a explicação da seção SCREEN RECORD.
Com o comando DELIMITERS pode-se alterar os caracteres delimitadores do campo da tela, quando este é visualizado na execução do programa. Os caracteres default do 4GL são os colchetes "[...]".
DELIMITERS "{}" |
Neste exemplo o símbolo "{" é o caracter de abertura e "}" é o caracter de fechamento.
7.3 O comando FORM4GL
Após a definição, deve-se compilar o arquivo de definição da form utilizando o programa form4gl. Se existirem erros, estes são colocados num arquivo de mesmo nome, com extensão .err, contendo a identificação dos erros, que após corrigidos no arquivo de definição original, deve-se compilá-lo novamente. Estes procedimentos podem ser executados repetidamente até obter uma compilação da form sem erros.
form4gl <arquivo.per> |
Exemplo de compilação de form
O comando form4gl tem a estrutura de um comando LINUX, com três opções disponíveis.
-s
Esta opção compila o fonte da form existente no arquivo cujo nome segue a opção no comando. Note que o verdadeiro nome do arquivo é constituído pelo nome existente no comando seguido pela extensão ".per". No caso de existirem erros, é criado um arquivo com o mesmo nome da form fonte mas com extensão ".err", e neste arquivo contém as mensagens que indicam os pontos onde se encontram os erros. Pode-se editar este arquivo e corrigir os erros e, depois de se apagarem as mensagens de erro, gravá-lo no arquivo com extensão ".per" e compilá-lo novamente.
-v
Esta opção também compila a form fonte mas verifica se o comprimento dos campos definidos na seção SCREEN têm o mesmo comprimento das colunas a que são associados na seção ATTRIBUTES e apresenta as respectivas mensagens no arquivo de erros.
-d
Esta opção cria uma form default. Pode especificar o nome da form, o banco de dados e as tabelas que compõem a form escrevendo-as nesta ordem e a seguir à opção -d do comando. No entanto se escrever apenas o comando seguido da opção -d e pressionar <ENTER> o comando irá solicitar ao usuário que introduza esses elementos uma a um, pressionando <ENTER> após informar cada elemento. Para indicar que não pretende especificar mais tabelas pressione <ENTER> duas vezes.
form4gl -d f_livros livros autores livros |
Cria e compila a form f_livros com as tabelas LIVROS e AUTORES do banco de dados LIVROS.
form4gl -v f_livros |
No comando acima é realizada apenas a compilação da form f_livros.
8 Gestão de janelas – parte 1
Sempre que se pretende manusear uma form deve-se abri-la.
A abertura de uma form pode ser realizada por intermédio da instrução OPEN FORM ou OPEN WINDOW.
8.1 FORM
A abertura de uma form através da instrução OPEN FORM é feita da seguinte forma:
OPEN FORM nome_da_form FROM "arquivo_form" |
Definição genérica da instrução OPEN FORM
O nome da form é dado pelo programador e é com esse nome que se passa a referenciar a entrada de dados dentro do programa. "arquivo_form" é o arquivo em que se encontra a form (arquivo .per) compilada retirando a extensão ".frm".
Antes de qualquer ação sobre a entrada de dados, deve-se mostrar esta form na tela sem qualquer dado. Para efetuar esta ação usa-se a instrução DISPLAY FORM.
DISPLAY FORM nome_da_form ATTRIBUTE(lista_de atributos) |
Definição genérica da instrução DISPLAY FORM
8.2 WINDOW
É comum, em num programa a utilização de pequenas partes da tela para efetuar algumas tarefas, a que se costuma chamar de janelas (Windows).
8.2.1 OPEN WINDOW
As cláusulas desta instrução definem o tamanho e o posicionamento da janela na tela, podendo associar uma form a janela e definir um ou mais atributos para a janela.
Assim que é executada a instrução OPEN WINDOW, a janela aparece na tela.
OPEN WINDOW nome_da_janela AT linha,coluna |
Definição genérica da instrução OPEN WINDOW
Utilizando este comando não é preciso efetuar o comando DISPLAY FORM como é feito para a instrução OPEN FORM para apresentar a form na tela.
Na cláusula AT diz-se quais as coordenadas do canto superior esquerdo da janela. A cláusula WITH serve para dizer qual o tamanho da janela e pode ser feita de duas maneiras: dizendo o numero de linhas e de colunas que se pretende para a janela ou associando uma form. No caso de se associar a janela a uma form, o 4GL atribui como tamanho da janela o tamanho da form. Se escolher esta opção não é necessário chamar a instrução OPEN FORM. A cláusula ATTRIBUTE é opcional e associa um ou mais atributos à janela. Os atributos podem ser utilizados para fazer o seguinte:
- Apresentar borda para a janela (BORDER);
- Mostrar a janela em modo vídeo reverso ou com uma cor específica, conforme os atributos de cores apresentados no capítulo da instrução DISPLAY AT;
- Indicar a posição desejada para apresentação dos comandos PROMPT, MESSAGE, MENU, FORM e COMMENT LINE:
- COMMENT LINE <posição> - default é 1 ou FIRST;
- FORM LINE <posição> - default é 3 ou (FIRST + 2);
- MENU LINE <posição> - default é 1 ou FIRST;
- MESSAGE LINE <posição> - default é 2 ou (FIRST + 1);
- PROMPT LINE <posição> - default é 1 ou (FIRST)
A “posição” pode ser identificada com os seguintes valores:
- FIRST (indica a primeira linha da janela);
- LAST (indica a última linha da janela);
- Número fixo da linha desejada, respeitando o número de linhas definidas para a janela.
OPEN WINDOW wcust AT 3, 6 WITH 10 ROWS, 50 COLUMNS |
Definição genérica da instrução OPEN WINDOW
8.2.2 CLOSE WINDOW
Para retirar a janela da tela utiliza-se a instrução CLOSE WINDOW. Assim que esta instrução é executada, a janela desaparece da tela. Se a janela estiver associada a uma form, quando se fechar a janela, a form é fechada automaticamente.
CLOSE WINDOW nome_da_janela |
Definição genérica da instrução CLOSE WINDOW
8.2.3 CURRENT WINDOW
Durante alguns processamentos, você pode pretender mudar de janela de trabalho (ou janela corrente). A instrução CURRENT WINDOW transforma em janela corrente o nome da janela desejado, que é passado como parâmetro.
CURRENT WINDOW IS nome_da_janela |
Definição genérica da instrução CURRENT WINDOW
A janela para qual se dá o nome precisa estar aberta para utilizar a instrução CURRENT WINDOW. Se a janela especificada estiver associada uma form, essa form passará a ser a form corrente.
Se a janela estiver debaixo de outras, quando invocar a instrução CURRENT WINDOW ela irá sobrepor-se a todas que estejam no espaço utilizado pela janela solicitada.
Existe uma janela especial, chamada SCREEN, que está sempre aberta, e onde são utilizadas as forms não associadas a janelas, feitos os displays, etc.
8.3 OPTIONS
Um programa de 4GL assume valores por default para o funcionamento de diversas instruções. Para alterar esses valores usa-se a instrução OPTIONS.
OPTIONS {MESSAGE LINE linha | |
Definição genérica da instrução OPTIONS
8.4 Instrução INPUT
A instrução INPUT é utilizada para editar uma form (para receber dados por intermédio de uma form).
Esta instrução tem como parâmetros um conjunto de nomes de campos (que correspondem aos campos que se pretende editar) que foram previamente identificados na seção ATTRIBUTES da form e um conjunto de variáveis que também podem ser definidas de várias formas. É também possível executar instruções e controlar o movimento do cursor condicionalmente à posição atual do cursor.
INPUT [BY NAME lista_de_variaveis [{BEFORE INPUT |
Definição genérica de uma instrução INPUT
Se a cláusula WITHOUT DEFAULTS for omitida, faz com que a instrução INPUT, quando chamada, apresente nos campos os defaults definidos na form. Se a cláusula existir, os valores apresentados nos campos durante o INPUT são os valores que estavam atribuídos as variáveis no momento anterior ao acionamento do INPUT.
9 Exercício - Sistema proposto
A medida em que forem feitos avanços nos conhecimentos do 4GL, será feito o desenvolvimento de uma aplicação para utilização em uma biblioteca que tenha acesso a informações de um banco de dados, com cadastro e consulta de livros e cadastro e consulta de requisições de livros.
A entrada de dados que será construída começa por uma proposta genérica, sendo desenvolvida e aperfeiçoada por etapas. A ordem de apresentação destas é a que normalmente se utiliza na prática, salvo em algumas situações para facilitar a entendimento.
A proposta é a seguinte:
- Uma única entrada de dados que trabalhe com as tabelas LIVROS, AUTORES, TEMAS e EDITORAS do banco de dados LIVROS, para poder visualizar simultaneamente um livro (tabela LIVROS), os autores do livro (LIVRO_AUTORES) e os temas focados (LIVRO_TEMAS). As entradas de dados referentes a autores e temas devem aparecer em janelas diferentes.
- Os diversos campos devem ser validados (tipo de dado correto, valores admissíveis, etc.). Sempre que existir um erro, este deve ser assinalado com uma mensagem ao usuário, descrevendo o erro e posicionando o cursor no campo em questão.
- As colunas que contenham códigos a procurar numa tabela (chave estrangeira) devem possuir facilidades de busca na tabela de pesquisa.
Serão descritas a maior parte das instruções de uma form e as instruções do 4GL que permitem a interação com as forms. Estas irão sendo exemplificadas durante as várias fases do processo de desenvolvimento de uma entrada de dados complexa, com várias tabelas, validações, mensagens de erro, etc.
Foram selecionadas as instruções que normalmente são utilizadas nos tipos de entrada de dados que fazem parte de qualquer aplicação.
9.1 Definição da form livros
Como ponto de partida vamos gerar a form de dados de livros para a tabela LIVROS, obtendo-se o esqueleto do programa com o comprimento e o vínculo das colunas às tabelas já definidas.
DATABASE livros SCREEN TABLES ATTRIBUTES |
A seguir vamos trabalhar sobre a seção SCREEN para obter o desenho da entrada de dados pretendida, considerando que todos os campos devem estar presentes numa única entrada de dados.
Uma solução para a entrada de dados pretendida pode ser conforme a seção SCREEN seguinte:
DATABASE livros SCREEN |
Seção SCREEN da form livros
A seção TABLES fica da mesma forma como foi apresentado inicialmente:
TABLES |
Seção TABLES da form livros
Na seção ATTRIBUTES pode-se além de definir o nome e o tipo dos campos da form, definir alguns atributos que serão descritos a seguir. Na form livros serão utilizados os de uso mais comum.
AUTONEXT
Na form livros iremos usá-lo nas datas.
f011 = livros.data_entrada, AUTONEXT; |
COMMENTS
Na form livros iremos aplicá-lo ao campo data_entrada com a seguinte mensagem: "Introduza a data em que o livro entrou na biblioteca"
f011 = livros.data_entrada, AUTONEXT, |
DEFAULT
Na form livros será aplicado aos campos volumes, sala e data da entrada. Neste último campo (data da entrada do livro) irá assumir o valor inicial como a data atual, escrevendo "today" como valor inicial.
f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY; |
FORMAT
Na form livros iremos usar o atributo "format" apenas nas datas e com o formato "dd/mm/yyyy".
f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY, |
INCLUDE
Na form livros vamos usar o atributo INCLUDE nos campo “volumes”, admitindo que um livro não pode ter mais de 100 volumes (1 a 100).
f007 = livros.volumes, INCLUDE = (1 to 100); |
REVERSE
Na form livros vamos usar em vídeo reverso o campo número.
f000 = livros.numero, REVERSE; |
9.2 Programa de cadastro de livros
DATABASE livros MAIN FUNCTION menu() |
Abertura da form livros
A abertura da tela será feita utilizando a instrução OPEN WINDOW.
O nome da tela/window (w_livros) é dado pelo programador e é com esse nome que se passa a referenciar a entrada de dados dentro do programa. "arquivo_form" é o arquivo em que se encontra a form compilada retirando a extensão ".frm".
Na window w_livros vão ser editadas todas as colunas da tabela LIVROS.
O programa deve ter variáveis para todas as colunas que desejar fazer entrada de dados na tela. Neste caso podemos declarar facilmente um RECORD que contenha todas as colunas da tabela LIVROS.
DATABASE livros DEFINE mr_livros LIKE livros.* FUNCTION menu() |
Declaração do RECORD mr_livros
Este programa terá um menu que permitirá as seguintes opções sobre a tabela de LIVROS:
INCLUIR - Adiciona um novo livro na tabela de livros.
CONSULTAR - Procura um livro já cadastrado por número.
MODIFICAR - Modifica o registro atual na entrada de dados, se existir.
EXCLUIR - Exclui, se existir, o registro atual apresentado na entrada e dados.
FIM - Sai do programa.
Para criar menus utiliza-se a instrução MENU já vista anteriormente.
MENU "LIVROS" COMMAND "Consultar" "Consultar um livro pelo numero." COMMAND "Modificar" "Permite modificar o livro corrente." COMMAND "Excluir" "Remove o livro corrente." COMMAND "Fim" "Sai do programa." |
Menu da entrada de dados para livros
Este menu é implementado após a abertura da form principal de cadastro de livros.
Função Incluir
A função incluir recebe os dados de um livro do teclado e o inclui no banco de dados.
Nesta função vamos utilizar a instrução INPUT na sua forma mais simples.
FUNCTION incluir() WHENEVER ERROR CONTINUE IF sqlca.sqlcode = 0 THEN |
Inclusão de novo livro
A lista de campos da cláusula FROM da instrução INPUT, neste caso está implícita no caracter '*' do RECORD. Isto quer dizer que vão ser editados todos os campos que existem na variável composta mr_livros. Como a variável foi declarada LIKE livros.*, vão ser editadas todas as colunas da tabela LIVROS onde os nomes dos componentes forem correspondentes aos nomes dos campos da tela, definidos no arquivo da form, na seção ATTRIBUTES.
A instrução INSERT é realizada como foi definida no comando SQL tendo na cláusula VALUES, as variáveis que contém os valores pretendidos.
As instruções WHENEVER aparecem para que o programa não interrompa a sua execução, e seja emitido um erro de SQL quando houver erro no INSERT (ver tratamento de erros).
Função Consultar
A função consultar, recebe o número do livro que se pretende procurar, procura-o no banco de dados, e mostra na entrada de dados todos os dados correspondentes. Note que o número do livro é introduzido na form.
FUNCTION consultar() INPUT BY NAME mr_livros.numero SELECT * IF status != 0 THEN |
Função que procura um livro com determinado número
A instrução CLEAR FORM serve para limpar todos os campos existentes na form corrente. No exemplo acima, se a busca for bem sucedida é feito um display de todas as colunas da tabela.
Função Modificar
A função modificar altera um livro que tenha sido previamente consultado ou incluído, ou seja, se este tiver sido apresentado na entrada de dados.
Esta função aceita os valores sem inicializar variáveis e sem limpar os campos da form, validando a existência de um livro válido.
FUNCTION modificar() |
Modificação de um livro
É feito um teste da variável mr_livros.numero para garantir que está preenchida com um número de livro existente.
Na instrução UPDATE, descrita em SQL, as variáveis do 4GL são colocadas na cláusula SET.
Função Excluir
A função excluir, exclui o livro corrente.
Esta função exclui do banco de dados o livro correspondente aos dados presentes na entrada de dados.
FUNCTION excluir() IF sqlca.sqlcode <> 0 THEN |
Exclusão de um livro
O teste da existência de livro corrente é feito da mesma forma que na função modificar.
As instruções INITIALIZE e CLEAR FORM aparecem para garantir a não existência do livro corrente após a sua exclusão quando bem sucedida.
10 Gestão de janelas – parte 2
10.1 Outras capacidades da instrução INPUT e outros atributos das forms
No capítulo anterior a instrução INPUT foi utilizada na sua forma mais simples para as ações de consulta, inclusão e modificação de dados. Além da cláusula onde se definem as variáveis, a instrução INPUT normalmente pode ser utilizada com mais cláusulas:
HELP <numero>
Quando a tecla de help for pressionada, durante a edição de uma form, é automaticamente executada a função show_help, que apresenta o help relativo ao número especificado (ver helps).
BEFORE FIELD <nome da coluna>
Antes da edição da coluna, no momento em que o cursor está sendo posicionado sobre a coluna em questão, as instruções especificadas para esta cláusula são executadas.
AFTER FIELD <nome da coluna>
Após a edição da coluna sobre a qual o cursor está posicionado, as instruções especificadas para esta cláusula são executadas.
AFTER INPUT
Depois da edição de todos os campos da form, o programa cumpre as instruções especificadas nesta cláusula.
ON KEY <lista de teclas de atalho>
Se for pressionada uma das teclas definidas nesta cláusula, o programa cumpre as instruções definidas a seguir.
10.2 Teclas de interrupção e confirmação de execução
Existe uma tecla lógica que o usuário pode pressionar dentro de uma aplicação 4GL para interromper a execução da aplicação. Se o programa 4GL não incluir a instrução DEFER INTERRUPT no início do programa, ao pressionar esta tecla, a execução do programa é interrompida. Com DEFER INTERRUPT, pressionando as teclas de interrupção <CTRL+C>, a variável global de controle interno do 4GL chamada INT_FLAG é alterada para 1 (TRUE) e a instrução atual de interação com o usuário é cancelada, continuando a execução a partir da próxima instrução.
A tecla de atalho para confirmação de uma instrução de entrada de dados (INPUT, DISPLAY ARRAY, INPUT ARRAY, PROMPT) antes que esta seja concluída normalmente, ou seja, podendo ser pressionada a qualquer momento, é a tecla ESC. A tecla ENTER é assumida como padrão para navegação entre campos e no caso do cursor estar posicionado no último campo pertencente a entrada de dados atual e o usuário pressionar ENTER, automaticamente a entrada de dados terá seus dados confirmados. Neste caso a variável INT_FLAG terá seu valor inalterado.
10.3 Exercício – novo campo e tratamento de tecla de interrupção
Quando se definiu o programa falou-se na validação do campo “editora“ na tabela EDITORAS, com envio do nome da editora para a tela. Vamos agora alterar o programa e form de modo a cumprir essa tarefa.
A form tem que possuir um novo campo onde será visualizado o nome da editora na seção SCREEN, assim:
Editora: [f009 ] [f9d ] |
Novo campo para visualização do nome de editora
Precisa também introduzir os atributos para este campo na seção ATTRIBUTES:
f9d = FORMONLY.nome_editora TYPE LIKE editoras.nome, NOENTRY; |
Atributos do novo campo
O atributo FORMONLY identifica um campo com um nome permitindo dizer qual o tipo para esse campo. Neste caso definimos o tipo com LIKE , no entanto é possível definir o tipo através dos tipos elementares.
campo = FORMONLY.nome_do_campo [TYPE [tipo_de_dados | LIKE tabela.coluna]] |
Definição genérica do atributo FORMONLY
Utilizou-se também o atributo NOENTRY para forçar a instrução INPUT a não editar este campo, ou seja, para o comando INPUT este campo será somente para visualização.
O programa 4GL ainda não sabe como fazer a validação do código de editor. Para conseguir realizar esta função, utiliza-se a cláusula AFTER FIELD, faz-se uma consulta na tabela de editores e apresenta-se o nome do editor encontrado na tela.
DEFINE l_nome_editora LIKE editoras.nome; AFTER FIELD editora |
Alteração das instruções INPUT para efetuar as validações
Quando a variável SQLCA.SQLCODE indica a constante NOTFOUND, quer dizer que não foi encontrada a editora cujo código foi informado pelo usuário, sendo que neste caso é apresentada uma mensagem de erro e o cursor é retornado novamente para informar o mesmo campo até que o usuário informe um código de editora válido.
Para tratamento das teclas de interrupção ou confirmação, usando a variável INT_FLAG, de forma que a inclusão, modificação, consulta ou exclusão somente sejam efetivadas caso esta variável esteja com seu valor igual a 0 (FALSE), ou seja, se o usuário não pressionar a tecla de interrupção, deve-se implementar da seguinte forma:
DEFINE l_nome_editora LIKE editora.nome; LET int_flag = 0 AFTER FIELD edição AFTER INPUT IF int_flag <> 0 THEN |
Alteração das instruções INPUT para efetuar as validações
11 Interação do 4GL com o banco de dados
11.1 Gestão de cursores
A linguagem 4GL, como linguagem de programação, utiliza-se de variáveis para armazenar dados durante a execução do programa (valores digitados pelo usuário, resultados de cálculos intermediários, etc.).
Tal como na maioria das linguagens, as variáveis 4GL tem uma dimensão fixa e determinada a parte. A característica da linguagem para acessar um banco de dados (através do SQL) faz com que o 4GL tenha também a possibilidade de manusear estes dados de um banco de dados (tabelas, colunas, views, etc). Por esta razão é impossível ao construir um programa declarar variáveis para armazenar o resultado de uma instrução SELECT que retorne mais de um registro, por esta razão tornou-se necessário introduzir a noção de cursor para resolver estas questões.
Uma instrução SELECT pode dar origem a mais de uma linha da dados (depende da cláusula WHERE).
errselect.4gl SELECT numero, nome, edição $ fglpc errselect.4gl |
Leitura com instrução SELECT que dá origem a mais do que uma linha.
Se consultar o manual de 4GL verificará que o erro aconteceu porque uma busca não devolveu exatamente uma linha.
Um cursor é uma forma de acessar individualmente as linhas do resultado de uma instrução SELECT.
Existe um segundo tipo de cursor associado a instruções INSERT de que se falará mais adiante. Para acessar uma linha pertencente a esse cursor usa-se a instrução FETCH.
Ao conjunto de linhas selecionadas com uma instrução SELECT utilizando-se um cursor chama-se conjunto ativo para essa instrução SELECT.
A linha ativa em determinado momento no cursor chama-se linha corrente.
Um cursor pode estar em dois estados: aberto ou fechado. Quando está aberto, o cursor tem associado a ele um conjunto ativo de registros (linhas) e aponta para uma linha corrente. Quando um cursor está fechado, deixa de estar associado a um conjunto ativo de registros (linhas), continuando no entanto associado à instrução SELECT para a qual foi declarado.
As ações que se podem realizar sobre um cursor são:
Declarar o cursor
Esta ação é realizada com o auxilio da instrução DECLARE associada a uma instrução SELECT.
DECLARE cq_livros CURSOR FOR |
Abrir o cursor
Esta ação é realizada com a instrução OPEN, que provoca a execução da instrução SELECT associada ao cursor e a busca correspondente na base de dados é realizada nessa altura. A partir desta instrução até o cursor ser fechado fica associado um conjunto de linhas (conjunto ativo) que corresponde ao resultado da instrução SELECT. O cursor fica posicionado imediatamente antes da primeira linha.
OPEN cq_livros |
Acessar uma ou mais vezes ao cursor
Os acessos são feitos com o auxilio da instrução FETCH que avança a linha corrente para a linha seguinte e armazena os dados retornados desta linha nas variáveis definidas na cláusula INTO. Se o cursor estiver posicionado na ultima linha, a variável sqlca.sqlcode será atualizada com o valor NOTFOUND (ou código 100).
WHILE 1 |
Fechar o cursor
Ação realizada pela instrução CLOSE que faz a colocação do cursor em estado fechado.
Não é possível invocar uma outra instrução sobre o cursor que não esteja aberto. O cursor por estar fechado não deixa de ter uma instrução SELECT associada, que ao ser invocado pela instrução OPEN é executada novamente a instrução SELECT associado ao cursor.
CLOSE cq_livros |
Um cursor pode também ser fechado automaticamente através de uma instrução de fim de transação (COMMIT WORK ou ROLLBACK WORK), já que uma das ações destas instruções é fechar todos os cursores que se encontrarem abertos no momento. Mas isto somente ocorre se na instrução de definição do cursor (DECLARE) tiver sido omitido o atributo WITH HOLD.
Apresenta-se um exemplo de acesso a uma tabela do banco de dados por intermédio de um cursor.
cursor1.4gl DATABASE livros MAIN DECLARE cq_livros CURSOR WITH HOLD FOR LET aux = 1 OPEN cq_livros CLOSE cq_livros $ fglpc cursor1.4gl |
Leitura dos livros com número < 5 usando um cursor
Quando se declara um cursor, pode-se definir a intenção de alterar os valores de algumas coluna das linhas lidas. Essa intenção define-se através da declaração "FOR UPDATE" após a instrução SELECT do cursor, como na figura a seguir.
DECLARE nome_cursor CURSOR FOR |
Definição genérica da declaração de um cursor FOR UPDATE
A alteração faz-se da seguinte forma:
- Declarar um cursor "FOR UPDATE"
DECLARE cq_livros CURSOR FOR |
- Abrir o cursor da forma descrita anteriormente.
OPEN cq_livros |
- Posicionar o cursor na linha que se quer alterar:
FETCH cq_livros INTO ... |
Invocar a instrução UPDATE para alteração das colunas definidas na cláusula SET do registro corrente do cursor utilizando a cláusula CURRENT OF para indicar a atualização do registro correspondente a linha corrente do cursor.
UPDATE |
Depois da instrução UPDATE o cursor continua posicionado na linha corrente.
cursupd.4gl DATABASE livros DECLARE cq_livros CURSOR FOR OPEN cq_livros IF edicao IS NULL THEN UPDATE livros PROMPT "Quer alterar mais livros (s/n):" IF sqlca.sqlcode != 0 THEN END WHILE END MAIN $ fglpc cursupd.4gl Artificial Inteligence using C -Qual a editora para este livro: BERTR |
Cursor para alteração ( FOR UPDATE )
11.1.1 Cursores com atributo SCROLL
O mecanismo descrito anteriormente só permite o posicionamento seqüencial do início até o fim do conjunto ativo de registros do cursor e, quando chegar ao fim só é possível voltar ao início fechando e voltando a abrir o cursor (não garantindo que seja igual ao anterior pois o banco de dados pode ter sido atualizado).
Para evitar estes problemas usa-se os cursores com SCROLL (ou SCROLL cursor). O seu funcionamento é idêntico a um cursor normal sendo declarado, aberto, lido e fechado (DECLARE, OPEN, FETCH e CLOSE). A principal diferença entre os dois tipos de cursores está no fato dos cursores com SCROLL não poderem ser utilizados com a cláusula FOR UPDATE e na instrução FETCH o SCROLL cursor permite utilizar algumas palavras chaves que definem a forma de acesso desejada aos registros ativos num cursor aberto.
As formas de acesso são:
FETCH CURRENT | Registro corrente |
FETCH PREVIOUS | Registro anterior |
FETCH NEXT | Registro seguinte |
FETCH FIRST | Primeiro registro |
FETCH LAST | Último registro |
FETCH RELATIVE | Registro N a partir do registro corrente, respeitando o conjunto ativo do cursor. Quando N for positivo, indica N registros após o registro corrente e quando N for negativo, indica N registros antes do registro corrente |
FETCH ABSOLUTE | Elemento N do conjunto de registros ativo do cursor |
Formas de acesso a um cursor com scroll
Um cursor com SCROLL não pode, no entanto, ser declarado FOR UPDATE.
11.1.2 Cursores para inclusão de dados
Para otimizar a inclusão num banco de dados pode-se utilizar um mecanismo de 4GL chamado cursor de inclusão (INSERT cursor). Através deste mecanismo os dados vão sendo colocados numa área de memória temporária e só são efetivamente gravados no banco de dados quando esta área se encontrar cheia (automaticamente) ou quando o programa assim determinar (instrução FLUSH).
Exemplo proposto de cursores de inclusão:
- Declarar um cursor associando-o a uma instrução INSERT.
DECLARE cq_livros CURSOR FOR |
- Abrir o cursor. Identico a um cursor normal.
OPEN cq_livros |
- Ler os dados para dentro de determinada variáveis (INPUT, LET).
- Escrever as variáveis no buffer com o auxilio da instrução PUT.
PUT cq_livros |
- Fechar o cursor.
CLOSE cq_livros |
O 4GL força a escrita do buffer no banco de dados sempre que o limite do buffer seja atingido ou o cursor seja fechado.
Depois de uma instrução FLUSH deve-se verificar a variável STATUS ou SQLCA.SQLCODE, pois se for diferente de zero indica um erro de inclusão no banco de dados. Se houver necessidade de saber o número de linhas incluídas pode-se consultar o conteúdo da variável SQLCA.SQLERRD[3], que conterá o número de linhas incluídas no banco de dados.
11.2 Instruções sql dinâmicas
Geralmente as aplicações são escritas de forma a executar tarefas pré-determinadas sobre banco de dados de estrutura constante.
Existem situações em que o programador não sabe, em fase de compilação, as instruções de SQL a serem utilizadas. Algumas dessas situações podem ser as seguintes:
- Programas interativos, onde os usuários introduzem os parâmetros de uma instrução pelo teclado
- Programas em que o usuário introduz as instruções de SQL pelo teclado.
- Programas que devem trabalhar com banco de dados em que a estrutura pode variar.
- Programas que recebem parâmetros ou instruções a partir de arquivos de configuração.
Uma instrução de SQL, apesar de ser verificada a sua sintaxe durante a compilação, é interpretada em execução, como tal é executado toda a análise gramatical necessária para reconhecer a instrução e as suas cláusulas, sendo que todas estas tarefas são relativamente necessárias.
Em 4GL pode-se gerar dinamicamente instruções de SQL. Isto quer dizer que as instruções podem ser geradas a partir de um string, preparada e posteriormente executada. Para uma instrução preparada é dada uma identificação que permite a sua utilização. Quando uma instrução é preparada, ao ser executada não é feita a análise gramatical da instrução, aconselhando-se utilizar instruções preparadas somente quando utilizar ciclos a fim de diminuir o tempo de execução do programa.
11.2.1 Instruções PREPARE e EXECUTE
Para executar uma instrução SQL dinâmica seguem os seguintes passos:
- Colocação de uma string com as instruções SQL desejadas dentro de uma variável tipo CHAR.
LET l_sql_delete = “DELETE FROM livros WHERE numero = 10” |
Instrução PREPARE
- Definição de um identificador de instrução a partir da string que contém a instrução. Esta tarefa e executada pela instrução PREPARE. Há validação da sintaxe da instrução contido na string.
PREPARE var_delete FROM l_sql_delete |
Instrução PREPARE
- Execução da instrução através da instrução EXECUTE.
EXECUTE var_delete |
Instrução EXECUTE
As instruções SQL enviadas ao PREPARE em tempo de execução não podem fazer referência a variáveis do 4GL, visto que nesta fase o programa já foi compilado.
Para resolver este problema coloca-se o caracter '?' (interrogação) no local onde se deveria encontrar essa variável.
Para atribuir a variável ao ponto de interrogação usa-se a cláusula USING var1, var2,..., varN na instrução EXECUTE. As variáveis são atribuídas ao ponto de interrogação correspondente á sua posição.
11.2.2 Instrução DECLARE para instruções SQL dinâmicas
Se a instrução dinâmica for um SELECT, não se pode utilizar a instrução EXECUTE, devido a possível ambigüidade relativa ao número de linhas retornadas do banco de dados. Neste caso as fases de atuação são:
- Preparar a instrução com PREPARE.
PREPARE id_expressão FROM expressão_char |
- Declarar o cursor para essa instrução.
DECLARE nome_cursor CURSOR FOR id_expressão |
- Usar o cursor da mesma forma que se usa com instruções definidas antes da compilação. Se for usado o caracter '?' para substituir variáveis, é necessário usar a cláusula USING na abertura do cursor.
OPEN nome_cursor USING var1 var2 ... varn |
11.3 Exercício – Otimização da função de consulta
A função de consulta foi inicialmente implementada de forma que utilizasse o comando INPUT seguido de um comando SELECT para pesquisa do registro no banco de dados.
Agora a função de consulta deverá ser feita da seguinte forma:
- implementar consulta utilizando definição de cursor do tipo SCROLL para leitura dos registros da tabela LIVROS, de forma que ao acionar a opção “Consultar” todos os livros sejam consultados, apresentando um livro de cada vez em tela;
- Criar 2 novas opções de menu (SEGUINTE, ANTERIOR) para permitir a pesquisa do próximo livro ou do livro anterior, conforme os registros carregados na leitura do cursor do tipo SCROLL utilizando as instruções FETCH NEXT e FETCH PREVIOUS.
12 Gestão de janelas – Parte 3
12.1 Instrução CONSTRUCT
Durante a execução de um programa, muitas vezes o usuário necessita fazer uma consulta a várias colunas de uma ou mais tabelas (para fazer alterações em tela, gerar listagens parciais, etc.). Não é viável fazer um programa que preveja todas as possíveis consultas que se pretende efetuar.
A instrução CONSTRUCT edita a form corrente, e a partir dos dados que o usuário informa nas diversas colunas, constrói uma parte de uma instrução SELECT numa variável tipo CHAR que posteriormente pode ser preparada e executada. A variável CHAR preparada pela instrução CONSTRUCT pode ser utilizada como a cláusula WHERE de um SELECT, sem conter a palavra chave WHERE.
CONSTRUCT {BY NAME variavel_char ON lista_de_colunas [{BEFORE CONSTRUCT |
Definição genérica da instrução CONSTRUCT
Esta instrução em relação à cláusula BY NAME, funciona da mesma forma como na instrução INPUT, ou seja, se for utilizada não é necessário indicar o nome das variáveis internas relacionadas às forms a que se pretendem editar.
12.1.1 Exercício – Utilização instrução CONSTRUCT na função “Consultar”
Utilizar a instrução CONSTRUCT para permitir o filtro da consulta de livros. Esta consulta deverá ser implementada antes da definição do cursor tipo SCROLL e o cursor deverá ser criado a partir de um SQL dinâmico em conjunto com a variável resultante do comando CONSTRUCT.
NOTA: Não esqueça que para definição de cursor a partir de SQL dinâmico é necessário utilizar a instrução PREPARE antes da instrução DECLARE do cursor.
12.2 INSTRUÇÃO DISPLAY ARRAY
As vezes uma linha de uma tabela cabe numa linha da tela, e pretender introduzir na tabela várias linhas em seguida (por exemplo vários temas para um mesmo livro). Esta tarefa pode ser executada selecionando várias vezes a opção “incluir” do menu, no entanto, seria muito mais prático introduzir todos os temas de uma só vez, visualizando parte dos anteriores para evitar enganos.
Para tratar este tipo de tela o 4GL possui as instruções DISPLAY ARRAY e INPUT ARRAY, associadas a novas definições nas forms.
DISPLAY ARRAY array_de_records TO array_da_tela.* |
Definição genérica da instrução DISPLAY ARRAY
A instrução DISPLAY ARRAY envia um array de records do programa para a tela, por intermédio de um array de linhas na tela.
O array de records definido no programa pode ser de maior dimensão que o array da tela. Neste caso o usuário pode navegar no array de registros (records) no array da tela (scroll) para cima e para baixo, com as teclas de setas ou, se pretender posicionar-se de uma página a outra, utilizando as teclas F3 e F4 ou as teclas que foram definidas para tal funcionalidade utilizando a instrução OPTIONS (NEXT KEY / PREVIOUS KEY).
Tal como na instrução DISPLAY é possível testar o pressionamento de uma tecla especial, associar atributos á visualização e sair da instrução após determinada situação.
Quando é executada esta instrução, ela fica a espera de instruções do usuário, que, para sair deverá ser pressionar a tecla <ESC> (se estiver definida como ACCEPT KEY).
Geralmente, com esta instrução utiliza-se as funções do 4GL SET_COUNT e ARR_CURR. A função SET_COUNT sempre precisa ser executada antes da instrução DISPLAY ARRAY e serve para informar à instrução a quantidade de linhas que se encontram preenchidas no array de registros. A função ARR_CURR informa qual a linha do array em que o cursor se encontra posicionado antes de pressionar a ACCEPT KEY (geralmente configurada como tecla ESC).
12.3 Exercício – Zoom de editoras
Criar uma função que, quando o usuário digitar um código de editora inválido, abra uma janela com os códigos válidos onde seja permitido o usuário escolher o código desejado. Este código deverá ser retornado para tela principal de cadastro de livros.
Para definição da tela que irá apresentar a lista de editoras deverá ser definida uma nova form para utilização da instrução DISPLAY ARRAY e uma função que irá carregar uma variável do tipo ARRAY com a lista de editoras válidas para apresentar nesta form.
12.4 FORM PARA UTILIZAÇÃO DE DISPLAY ARRAY
Para a utilização das instruções acima definidas é preciso construir uma form que tenha estas capacidades. Assim, na seção SCREEN define-se o número de linhas que se pretende editar de cada vez, cada coluna de cada linha declarada deve ter o mesmo nome de label.
SCREEN |
Seção SCREEN da form de zoom editoras
Como em qualquer form, cada label precisa estar declarado na seção ATTRIBUTES.
ATTRIBUTES |
Seção attributes da form de zoom de editoras
Os campos com o mesmo label, tem que corresponder a um SCREEN RECORD. Um SCREEN RECORD declara-se na seção INSTRUCTIONS e associa-se ao array as colunas que se pretende editar.
INSTRUCTIONS |
Seção INSTRUCTION
Colocou-se a cláusula DELIMITERS com espaços para dar a noção ao usuário como se fosse navegação em opções de um menu.
12.5 GESTÃO DA FORM COM DISPLAY ARRAY
A zona do programa em que se faz o INPUT ARRAY deverá ser alterado de forma que se for informado um código inválido, receba um código válido da função utilizada pra visualizar a lista de editores cadastrados.
AFTER FIELD edição |
A função consiste_editora verifica se foi informado um código de editora válido e apresenta o nome da editora, caso encontre. Se não encontrar a editora ou esta não tiver sido informada será acionada a função zoom_editora que fará a abertura de uma janela com a form descrita anteriormente onde serão visualizados os códigos existentes de editoras. A função zoom_editora sempre irá retorna um código de editora válido e neste caso pode-se apresentar o código e nome da editora sempre pois estará garantida a validade das informações.
OPEN WINDOW w_editoras AT 5, 5 WITH FORM "editoras" |
Para invocar a instrução DISPLAY ARRAY, é necessário declarar um record no programa para fazer display.
DEFINE la_editoras ARRAY[40] OF RECORD LIKE editoras.*, |
O array de records serve para colocar os elementos no cursor. A variável numero_editores serve para verificar o numero de editores obtidos. A variável linha_corrente serve para determinar o elemento do array que foi escolhido.
Para visualizar os dados é preciso agora armazená-los no array de records.
LET numero_editoras = 1 DECLARE cq_editoras CURSOR FOR FOREACH cq_editoras INTO la_editoras[numero_editoras].* IF numero_editoras >= 40 THEN LET numero_editoras = numero_editoras + 1 LET numero_editoras = numero_editoras - 1 |
Nesta versão são apenas visualizados as primeiras quarenta editoras.
CALL set_count(numero_editoras) DISPLAY ARRAY la_editoras TO sr_editoras.* LET linha_corrente = arr_curr() CLOSE WINDOW w_editoras |
Para que a instrução DISPLAY ARRAY funcione corretamente tem de ser informada de quantas linhas se deve visualizar, tarefa que é executada pela função set_count.
A instrução DISPLAY ARRAY é invocada informando a variável array que vai ser apresentada e em que array de tela (SCREEN RECORD).
A função ARR_CURR() é acionada para que se saiba qual o elemento do arrray que o usuário escolheu, para devolver o código selecionado para a tela anterior.
RETURN la_editoras[linha_corrente].codigo |
12.6 INSTRUÇÃO INPUT ARRAY
A instrução INPUT ARRAY, tal como a instrução DISPLAY ARRAY serve para manipular forms com arrays de tela.
Esta instrução permite a manipulação de dados através da form para dentro de um array de records.
INPUT ARRAY array_de_records [WHITHOUT DEFAULTS] [{BEFORE {ROW | INSERT | DELETE |AFTER ROW | INSERT | DELETE |ON KEY(lista_teclas) [NEXT FIELD nome_campo] |
Definição genérica da instrução INPUT ARRAY
As cláusulas WHITHOUT DEFAULTS, AFTER e BEFORE: INSERT, FIELD e INPUT funcionam da mesma forma que na instrução INPUT, assim como as cláusulas ON KEY, NEXT FIELD, EXIT INPUT.
As cláusulas AFTER ROW e BEFORE ROW permitem executar instruções antes ou depois da edição de uma linha da tela.
12.6.1.1Exercício – Cadastro de temas
Como o cadastro de livro já foi concluído, temos agora que permitir registrar um ou mais temas por livro. Neste caso será desenvolvida uma entrada de dados para cadastro dos temas focados em cada livro (tabela LIVRO_TEMAS).
12.6.2 DEFINIÇÃO DA FORM
Uma form para ser manipulada pela instrução INPUT ARRAY é idêntica a uma form utilizando DISPLAY ARRAY.
DATABASE livros TABLES ATTRIBUTES INSTRUCTIONS |
Form de temas
O campo nome foi definido como NOENTRY pois vai servir apenas para informar os respectivos nomes de editoras para cada código informado.
12.6.3 PROGRAMA DE GESTÃO DA FORM DE TEMAS
No menu do programa de entrada de dados de livros será adicionada uma nova opção de menu denominada “Temas”.
COMMAND "Temas" "Introdução de temas focados neste livro." |
Menu da entrada de dados para livros
Faz-se um teste para verificar se existe algum livro corrente, caso contrário não faz sentido a inclusão de temas de um livro.
A função “temas” vai conter os processamentos necessários ao correto cadastro dos temas com visualização dos temas já cadastrados.
FUNCTION temas(l_livro) |
Declaração das variáveis da função temas
O parâmetro livro é repassado na chamada da função com o numero do livro para o qual serão alterados os temas. As variáveis l_idx_arr e l_idx_scr servem como índices de acesso aos arrays respectivamente do programa e da tela. A variável la_temas é o array de registros onde vão ser armazenados os dados relativos a cada tema.
É possível que já existam alguns temas cadastrados para o livro em questão. Neste caso convém consultar os temas já existentes para uma eventual alteração. Se preenchermos o array de registros com os temas existentes, estes irão ser colocados na form quando se chamar a instrução INPUT ARRAY.
DECLARE cq_temas CURSOR FOR INITIALIZE la_temas TO NULL FOREACH cq_temas INTO la_temas[l_idx_arr].* LET l_idx_arr = l_idx_arr - 1 |
Preenchimento do array de records com as editoras já existentes
A forma como é preenchido o record é idêntica a utilizada quando se falou na instrução DISPLAY ARRAY.
A abertura da janela com a form é feita com a instrução OPEN WINDOW.
OPEN WINDOW w_temas AT 5,7 |
Abertura da janela da form
Tal como no DISPLAY ARRAY é necessário informar a instrução de quantas linhas do array se encontram preenchidas. Neste caso utiliza-se a função SET_COUNT().
CALL set_count(l_idx_arr) |
Início da instrução INPUT ARRAY
Na instrução diz-se que será feita a entrada de dados no array la_temas utilizando o array de tela sr_temas. A cláusula WITHOUT DEFAULTS é utilizada para que apareçam na tela os temas já existentes no array de records carregados a partir da leitura utilizando o cursor.
AFTER FIELD código |
Cláusula AFTER FIELD do INPUT ARRAY
Esta cláusula aparece para que depois de informar um código, seja verificada a existência deste código na tabela de temas e se apresente o nome do tema ao lado do código.
A função ARR_CURR () retorna para a variável l_idx_arr o número do elemento do array do programa sobre o qual o cursor está posicionado (linha corrente).
A função SCR_LINE() retorna qual o elemento do array da tela sobre a qual o cursor está posicionado, não esquecendo que podem existir mais elementos no array do programa do que no array de tela pois as instruções fazem scroll automaticamente.
A função GET_TEMAS pesquisa na tabela de temas o nome do tema conforme o código do tema repassado como parâmetro e retorna o seu nome ou NULL se não existir.
Se o código de tema for válido envia-se para a tela o nome retornado na linha corrente de tela, com a instrução DISPLAY TO.
Quando o usuário termina de informar os temas, pressionando ESC (accept key), é feita a exclusão de todos os temas atuais referentes ao livro corrente e depois substituídos por aqueles que se encontram no array de programa, ou seja, os temas que já existiam e os que foram incluídos agora.
AFTER INPUT FOR pr_idx = 1 TO arr_count() |
Atualização da base de dados com os novos temas por livro
Para detectar o fim de inclusão utiliza-se a cláusula AFTER INPUT. A função arr_count() é utilizada para nos informar o número de linhas preenchidas no array da tela.
Neste caso são realizadas 2 instruções SQL para garantir a total atualização das informações no banco de dados. Considerando o conceito de transação de banco de dados, neste caso deveria ser feito o uso de uma transação única para garantir que as 2 instruções fossem executadas com sucesso, caso contrário o processo de atualização dos temas deveria ser desfeito de forma total, retornando a situação anterior a modificação. Esta transação é realizada utilizando-se as instruções BEGIN WORK, COMMIT WORK e ROLLBACK WORK, conforme citado no manual sobre SQL.
AFTER INPUT |
13 RELATÓRIOS (REPORT) EM INFORMIX-4GL
A função do INFORMIX-4GL que permite gerar um relatório (ou uma listagem) é o REPORT. Vamos ver quais as vantagens e a características do gerador de relatórios (REPORT) do INFORMIX-4GL, para extrair informações do banco de dados.
O Report recebe como argumento um conjunto de dados, linha a linha, e devolve a informação formatada. O estudo dos reports de INFORMIX-4GL pode-se dividir em 2 partes:
- O código do report propriamente dito;
- O código que o processa - interação com o INFORMIX-4GL (REPORT DRIVER). Este colhe a informação, processa-a e depois envia-a linha a linha para o report. A construção típica de um REPORT DRIVER consiste numa instrução SELECT que busca a informação do banco de dados e associada a um ciclo FOREACH envia para o REPORT linha a linha o resultado do SELECT.
13.1 INTERAÇÃO COM O INFORMIX-4GL
Vamos considerar como exemplo a geração de um report com a informação da tabela de livros:
DATABASE livros DECLARE cq_livro CURSOR FOR DISPLAY "Inicio do REPORT; espere um momento " AT 15,1 START REPORT r_livro FOREACH cq_livro INTO lr_livro.* FINISH REPORT r_livro DISPLAY "Terminou o report. Encontra-se no arquivo livros.out "AT 15,1 SLEEP 3 |
Exemplo da interação do REPORT com INFORMIX-4GL
Prosseguindo com o programa temos as instruções seguintes:
START REPORT
Instrução que permite iniciar o report.
FOREACH
Executa um ciclo de forma a processar a leitura de todas as linhas resultantes da instrução SELECT, executando a instrução que se segue.
OUTPUT TO REPORT
É a instrução que chama o report, propriamente dito, e que lhe passa linha a linha, as linhas resultantes da instrução SELECT (percorre um cursor), sob a forma de argumentos.
END FOREACH
Termina o ciclo do cursor.
FREE
Libera a memória alocada para a declaração do cursor.
FINISH REPORT
Encerra o report.
Em seguida o programa dá ao usuário uma mensagem que terminou o report e informa o arquivo onde este foi gerado. Com exceção das instruções FOREACH e END FOREACH que já foram apresentadas anteriormente, iremos aprofundar um pouco o restante das instruções.
13.2 START REPORT
Esta instrução é usada em geral como a primeira para iniciar um ciclo que processa um report com a instrução OUTPUT TO REPORT.
START REPORT nome_report [TO {arquivo | PRINTER | PIPE programa} |
Sintaxe da instrução START REPORT
Se usar a cláusula TO, o INFORMIX-4GL ignora a instrução REPORT TO na seção OUTPUT do report.
Se usar a cláusula TO <arquivo>, o INFORMIX-4GL escreve o resultado do report nesse arquivo.
Se usar a cláusula TO PRINTER, o INFORMIX-4GL envia o resultado do report para a impressora. A impressora por padrão é a escolhida pelo programa "lpr", no sistema operacional LINUX, podendo ser alterado reinicializando a variável de ambiente DBPRINT.
Por definição de padrões, a cláusula TO PRINTER não é utilizada, pois o envio do relatório para impressora é realizada de outra forma.
13.3 OUTPUT TO REPORT
Esta instrução serve para passar ao report um linha de dados.
OUTPUT TO REPORT nome_report(linha_dados) |
Sintaxe da instrução OUTPUT TO REPORT
Em geral a instrução "OUTPUT TO REPORT" é utilizada dentro de um ciclo que passa dados para o report. A linha_dados pode ser uma ou mais colunas e/ou uma ou mais expressões, separadas por vírgula.
O número de elementos na linha_dados tem que estar de acordo com o número de argumentos da função REPORT chamada.
13.4 FINISH REPORT
Esta instrução indica ao INFORMIX-4GL que o report terminou.
FINISH REPORT nome_report |
Sintaxe da instrução FINISH REPORT
É necessário usar esta instrução para que o INFORMIX-4GL saiba que terminou o processamento do report.
13.5 ESTRUTURA DO REPORT
Começando pela estrutura do REPORT utilizado no exemplo anterior:
DATABASE livros REPORT r_livro(lr_relat) DEFINE lr_relat RECORD LIKE livros.* OUTPUT REPORT TO "livros.out" LEFT MARGIN 0 FORMAT END REPORT |
Exemplo de um REPORT
A primeira instrução do report é a declaração da base de dados. É necessário definir a base de dados para poder entender a cláusula LIKE da instrução DEFINE.
Um report inicia-se com a instrução REPORT que inclui entre parênteses a lista de argumentos.
Esta lista tem de corresponder exatamente à lista de argumentos enviada pela instrução OUTPUT TO REPORT. As variáveis não precisam ter exatamente o mesmo nome enviado pela instrução OUTPUT TO REPORT, no entanto se o tipo das variáveis não for o mesmo, precisam ao menos compatíveis ao ponto de permitir a conversão automática entre tipos distintos. Por exemplo, podemos passar uma frase entre ("") para uma variável do tipo CHAR, mas não podemos passar uma frase com caracteres alfanuméricos para uma variável do tipo INTEGER.
Tal como nas funções FUNCTION ou MAIN, a instrução que se utiliza logo na seqüência é DEFINE para definição de variáveis locais. Neste caso usamos a cláusula LIKE para definir a variável "lr_relat" como RECORD da tabela de livros. As variáveis do report são sempre do mesmo tipo das variáveis selecionadas, sendo que no caso de efetuar alguma alteração na tabela em questão. Exemplo, se mudar a dimensão de uma variável tipo CHAR não é necessário alterar o report, apenas precisa ser compilado.
Continuando no exemplo do REPORT, em seguida existe a seção OUTPUT. Nesta seção é opcional definir o destino da emissão do relatório e qual o formato da folha, isto é, a margem superior, margem inferior, margem esquerda e o número de linhas na página.
A seção FORMAT é a mais importante. Esta seção pode ter as subseções PAGE HEADER para o cabeçalho, PAGE TRAILLER para o rodapé e ON EVERY ROW para as linhas do corpo do relatório. No exemplo acima, existe apenas a última, utilizada para definir como serão escritas as linhas, usando as instruções seguintes:
- PRINT – imprimir os elementos do RECORD lr_relat.
- 1 SPACE - para deixar um espaço em branco.
- CLIPPED – eliminar os espaços em branco do final de um string.
Finalmente o report termina com a instrução END REPORT.
Depois de analisar este exemplo, vamos ver com mais detalhes as diferentes seções.
O report é composto por seções que são formadas por blocos e/ou instruções. As seções são as seguintes e devem de ser escritas segundo a ordem apresentada:
REPORT nome_report (ListaArgumentos) |
Seções que constituem um REPORT
As seções DEFINE, OUTPUT e ORDER BY são opcionais; a seção FORMAT é obrigatória.
13.5.1 SEÇÃO DEFINE
A rotina REPORT necessita da seção DEFINE quando recebe argumentos ou quando é necessário o uso de variáveis locais no report. É obrigatório existir uma lista de argumentos nas seguintes condições:
- Quando há seção ORDER BY no report, pois neste caso é necessário passar todos os valores para cada linha do report.
- Quando se usam funções de agregação, que dependem das linhas do report, em qualquer parte do report.
- Quando se usa o bloco de controle EVERY ROW na secção FORMAT, sendo que neste caso é obrigatório passar os valores de cada linha do report.
- Quando se usa o bloco de controle AFTER GROUP OF, obrigatoriamente deve-se passar pelos menos o parâmetro a que é feito referência.
A seção DEFINE obedece as mesmas regras já vistas no capítulo sobre definição de variáveis.
13.5.2 SEÇÃO OUTPUT
A rotina REPORT pode ou não conter esta seção. A seção OUTPUT controla a dimensão das margens e o comprimento da página. Permite definir o destino do resultado do report, isto é, vídeo, disco, impressora ou para outro processo através de um pipe.
A seção OUTPUT é formada pela palavra OUTPUT seguida de uma ou mais instruções:
OUTPUT |
Formato da seção OUTPUT
Se a instrução START REPORT tiver a cláusula TO indicando o destino do resultado do report, o INFORMIX-4GL ignora a instrução REPORT TO na seção OUTPUT.
Se o <arquivo> for uma variável, é necessário passá-la como argumento na chamada da função REPORT.
A instrução REPORT TO PRINTER envia o resultado do report para o programa definido pela variável DBPRINT. Se esta variável não estiver definida, então o INFORMIX-4GL envia o resultado para o programa "lpr".
Se quiser enviar o resultado do report para outra impressora que não seja a padrão do sistema, pode-se usar a instrução REPORT TO <arquivo>, que escreve num arquivo podendo depois ser impresso. Pode também usar-se a instrução REPORT TO PIPE para enviar diretamente o resultado para um programa que manda para a impressora correta.
OUTPUT |
Exemplo da instrução REPORT TO da seção OUTPUT
Este exemplo envia o resultado do report para o utilitário "more". Se omitir a instrução REPORT TO na rotina REPORT e se a instrução START REPORT não tiver cláusula TO, o resultado do report vai para o vídeo.
13.5.3 SEÇÃO ORDER BY
A seção ORDER BY é opcional na rotina REPORT. Esta seção especifica a ordem em que os dados devem estar no relatório e a ordem com que o INFORMIX-4GL processará os blocos de controle na seção FORMAT. É necessário o uso desta seção quando:
- Usar blocos de controle (BEFORE GROUP, AFTER GROUP);
- Enviar as linhas sem qualquer ordenação;
- Já foram ordenadas as linhas enviadas, mas pretende-se especificar a ordem exata com que serão processados os blocos de controle. Neste caso usa-se a cláusula EXTERNAL para que as linhas não sejam novamente ordenadas.
A seção ORDER BY tem o seguinte formato:
ORDER [EXTERNAL] BY lista_colunas |
Formato da secção ORDER BY
13.5.4 SEÇÃO FORMAT
Esta seção é obrigatória. É a seção FORMAT que vai determinar a aparência do relatório.
Usa-se os dados repassados à rotina REPORT através da sua lista de argumentos ou dados fornecidos por variáveis globais para cada linha do relatório.
A seção FORMAT tem início com a palavra FORMAT e termina quando a rotina REPORT termina, isto é, com END REPORT.
Existem dois tipo de seção FORMAT. O primeiro e o mais simples contém unicamente a subseção EVERY ROW e não pode conter qualquer outra subseção ou bloco de controle da seção FORMAT.
FORMAT EVERY ROW |
Exemplo da seção FORMAT mais simples
O outro tipo, mais complexo, da seção FORMAT pode ser formado da seguinte forma:
FORMAT |
Exemplo da secção FORMAT
A ordem de escrita dos blocos de controle é arbitrária. O número de blocos BEFORE GROUP OF ou AFTER GROUP OF que podem ser utilizados é igual ao número de colunas existentes na seção ORDER BY. Vejamos as subseções que constituem a seção FORMAT:
EVERY ROW
Esta instrução usa-se quando se pretende gerar um relatório rapidamente. O relatório consiste unicamente nos dados que são passados como argumentos à rotina REPORT.
Ao usar esta instrução não pode-se usar qualquer bloco de controle.
REPORT minimo(lr_livros) |
Exemplo de um REPORT muito simples, usando a instrução EVERY ROW
Cada bloco de controle é opcional mas, se não usar EVERY ROW, é necessário incluir pelos menos um bloco de controle na rotina REPORT. Cada bloco de controle inclui pelo menos uma instrução.
Quando se usa BEFORE GROUP OF, AFTER GROUP OF e ON EVERY ROW numa única rotina REPORT, o INFORMIX-4GL processa em primeiro lugar todos os blocos BEFORE GROUP OF, depois o bloco ON EVERY ROW e finalmente todos os blocos AFTER GROUP OF. A ordem com que o INFORMIX-4GL processa os blocos BEFORE GROUP OF e os blocos AFTER GROUP OF depende da ordem definida para as variáveis na seção ORDER BY.
Suponhamos que fosse definida a seguinte ordenação:
ORDER BY a, b, c |
Um exemplo da instrução ORDER BY
Então na seção FORMAT poderíamos ter:
BEFORE GROUP OF a |
Um exemplo da ordem de execução dos blocos de controle
AFTER GROUP OF
Este bloco de controle define as ações (ou instruções) que devem ser executadas depois de ser processado um determinado grupo de linhas. Um grupo de linhas define-se como um conjunto de linhas que têm o mesmo valor para uma determinada coluna que apareça na seção ORDER BY da rotina REPORT ou na cláusula ORDER BY da instrução SELECT.
AFTER GROUP OF variável |
Formato do bloco de controlo AFTER GROUP OF
O INFORMIX-4GL processa as instruções do bloco AFTER GROUP OF cada vez que a variável mudar de valor.
Pode-se ter tantos blocos AFTER GROUP OF quantas forem as variáveis da seção ou da cláusula ORDER BY.
A ordem em que são escritos estes blocos não tem qualquer importância, pois quando o INFORMIX-4GL terminar o processamento do relatório, executará todos os blocos AFTER GROUP OF antes de executar o bloco ON LAST ROW.
As funções agregadas de grupo dos REPORTS só podem ser usadas nos blocos de controle AFTER GROUP OF.
BEFORE GROUP OF
Este bloco de controle define as ações (ou instruções) que devem ser executadas antes de ser processado um determinado grupo de linhas.
BEFORE GROUP OF variável |
Formato do bloco de controlo BEFORE GROUP OF
O INFORMIX-4GL processa as instruções do bloco BEFORE GROUP OF cada vez que a variável mudar de valor.
Pode-se ter tantos blocos BEFORE GROUP OF quantas forem as variáveis da seção ou da cláusula ORDER BY.
Estes blocos podem ser usados para limpar variáveis utilizadas para acumular totais ou variáveis de controle.
O INFORMIX-4GL, ao gerar um relatório, começa por executar as instruções destes blocos e só depois executa o bloco ON EVERY ROW.
Pode se usar os blocos BEFORE GROUP OF para se iniciar uma nova página para cada grupo de informação com a instrução SKIP TO TOP OF PAGE.
FIRST PAGE HEADER
Este bloco de controle inclui as ações (ou instruções) que devem ser executadas para definir o cabeçalho da primeira página do relatório.
FIRST PAGE HEADER |
Formato do bloco FIRST PAGE HEADER
A instrução TOP MARGIN da seção OUTPUT influencia na linha onde é escrito este cabeçalho.
Não se pode usar a instrução SKIP TO TOP OF PAGE neste bloco.
Se usar a instrução IF..THEN..ELSE neste bloco, então o número de instruções PRINT tem deve ser igual tanto na condição THEN quanto na condição ELSE.
Não se pode usar a instrução PRINT arquivo, para poder despejar o conteúdo de um arquivo texto no FIRST PAGE HEADER.
Pode-se usar este bloco de controle para inicializar variáveis, pois o INFORMIX-4GL executa-o antes de qualquer outro.
ON EVERY ROW
Este bloco define as instruções que o INFORMIX-4GL passa para cada linha de dados como argumento à rotina REPORT, ou seja, os dados impressos no relatório são os dados passados como argumentos na função REPORT.
ON EVERY ROW |
Formato do bloco ON EVERY ROW
Se houver blocos BEFORE GROUP OF na rotina REPORT, estes serão processados antes do bloco ON EVERY ROW.
Se houver blocos AFTER GROUP OF na rotina REPORT, estes serão processado depois do bloco ON EVERY ROW.
ON LAST ROW
Este bloco de controle define as instruções que devem ser executadas depois de processada a última linha passada à rotina REPORT.
ON LAST ROW |
Formato do bloco ON LAST ROW
O INFORMIX-4GL executa este bloco depois dos blocos ON EVERY ROW e AFTER GROUP OF.
Pode-se usar o bloco ON LAST ROW para apresentar totalizações.
PAGE HEADER
Este bloco especifica a informação que vai aparecer no cabeçalho de cada página do relatório.
PAGE HEADER Instruções
|
Formato do bloco PAGE HEADER
A instrução TOP MARGIN da seção OUTPUT influencia na linha em que vai ser escrito este cabeçalho.
Não se pode usar a instrução SKIP TO TOP OF PAGE neste bloco.
O número de linhas do PAGE HEADER tem de ser o mesmo para todas as páginas. Tem de obedecer ás seguintes regras:
- Não se pode usar a instrução SKIP valor_inteiro LINES dentro de um ciclo dentro do bloco PAGE HEADER;
- Não se pode usar a instrução NEED;
- Se usar a instrução IF..THEN..ELSE neste bloco, então o número de instruções PRINT precisam ser iguais tanto na condição THEN quanto na condição ELSE;
- Se usar instruções CASE, FOR ou WHILE que contenham a instrução PRINT no bloco PAGE HEADER, deve ser terminada com ";" (ponto e vírgula);
- Não se pode usar a instrução PRINT <arquivo> para emitir o conteúdo de um arquivo texto no PAGE HEADER.
Pode usar neste bloco a expressão PAGENO para paginar o relatório automaticamente, no cabeçalho.
PAGE TRAILER
Este bloco inclui as instruções que se devem executar para definir o rodapé de cada página.
PAGE TRAILER Instruções
|
Formato do bloco PAGE TRAILER
Não se pode incluir a instrução SKIP TO TOP OF PAGE neste bloco.
A instrução BOTTOM MARGIN, da seção OUTPUT, define a linha em que termina este bloco.
O número de linhas do PAGE TRAILER precisa ser o mesmo para todas as páginas. Tem de obedecer ás regras seguintes:
- Não se pode usar a instrução SKIP <valor_inteiro> LINES dentro de um ciclo dentro do bloco PAGE TRAILER;
- Não se pode usar a instrução NEED;
- Se usar a instrução IF..THEN..ELSE neste bloco, o número de instruções PRINT precisam ser iguais tanto na condição THEN quanto na condição ELSE;
- Se usar as instruções CASE, FOR ou WHILE que contenham a instrução PRINT dentro do bloco PAGE TRAILER, deve ser terminada com ";" (ponto e vírgula);
- Não se pode usar a instrução PRINT <arqvuivo> para emitir o conteúdo de um arquivo de texto no PAGE TRAILER;
Pode usar neste bloco a expressão PAGENO para paginar o relatório automaticamente, no rodapé.
Instruções
Os blocos de controle da seção FORMAT determinam quando uma ou várias ações ocorrem, enquanto que as INSTRUÇÕES determinam qual a ação a ser realizada. Pode-se considerar dois tipos de instruções:
- Simples: constituída por uma única instrução;
- Compostas: constituídas por um grupo de instruções iniciadas pela palavra BEGIN e finalizadas pela palavra END.
FOR
A instrução FOR define um ciclo (loop), executando consecutivamente uma instrução simples ou composta, incrementando o índice e controlando a condição de saída. Quando esta instrução se finaliza, passa o controle do programa para a instrução seguinte ao fim do ciclo.
FOR i=1 TO 10 STEP 2 LET a = a * a + 2 LET b = a * 2 END FOR
|
Exemplo da instrução FOR
NOTA:Não se pode usar incrementos negativos .
IF THEN ELSE
Esta instrução executa um teste de uma condição e processa, alternativamente, 2 instruções (simples ou compostas) conforme a condição verdadeira ou não.
IF paid_date IS NULL THEN LET pg1 = "fal" LET pgc1 = "ta " ELSE LET pg1 = paid_date - ship_date LET pgc1 = " dias" END IF
|
Exemplo da instrução IF-THEN-ELSE
NOTA: Pode-se usar até no máximo 20 IF-THEN-ELSE aninhados.
LET
A instrução LET atribui um valor a uma variável.
LET pg1 = paid_date - ship_date LET pgc1 = " dias"
|
Exemplo da instrução LET
NEED
Esta instrução faz com que a próxima linha seja impressa na página seguinte, se não estiver disponível na página corrente, o número mínimo de linhas especificado na instrução NEED
BEFORE GROUP OF num_livro SKIP 1 LINE NEED 2 LINES PRINT COLUMN 01, "LIVRO:", COLUMN 10, num_livro USING "<<<<", COLUMN 16, nome CLIPPED
|
Exemplo da instrução NEED
PAUSE
Esta instrução faz com que um relatório com destino de emissão para o vídeo possa ter pausas para permitir sua visualização na tela. Pressionando <ENTER> pode-se avançar pelo relatório.
PAGE TRAILER PAUSE "Pressione <ENTER> para continuar"
|
Exemplo da instrução PAUSE
NOTA: Esta instrução não tem nenhum efeito se o relatório for dirigido para uma impressora, arquivo ou uma outra aplicação (pipe).
Esta instrução imprime informação no vídeo, impressora ou num arquivo, conforme estiver especificado na seção OUTPUT.
PRINT COLUMN 10, "Encomenda:", COLUMN 21, ord USING "<<<<", COLUMN 29, "Total:", COLUMN 36, tota1 USING "$$$$$####&.&&", COLUMN 53, "Pagamento em:", COLUMN 67, pg1, pgc1 CLIPPED
|
Exemplo da instrução PRINT
NOTAS:
- Cada instrução PRINT imprime informações numa linha. Pode-se com um vários PRINT escrever uma única linha, finalizando cada instrução PRINT com ";" (ponto e vírgula);
- Conforme os tipos de dados, no PRINT, as colunas ocupam espaços previamente fixados.
- Para controlar o comprimento dos campos no relatório pode-se utilizar as palavras CLIPPED e USING.
SKIP
Esta instrução salta um número de linhas em branco especificadas após o SKIP.
SKIP 2 LINES
|
Exemplo da instrução SKIP
SKIP TO TOP OF PAGE
Esta instrução faz com que a próxima linha seja escrita no início da próxima página, forçando o salto de página.
WHILE
A instrução WHILE define um ciclo, executando consecutivamente uma instrução simples ou composta, enquanto for verdadeira a condição que segue a palavra WHILE. Quando esta se verifica passa, o controlo do programa para a instrução seguinte ao fim do ciclo.
WHILE PAGENO = 1 LET a = a * a + 2 LET b = a * 2 END WHILE
|
Exemplo da instrução WHILE
FUNÇÕES AGREGADAS
As funções agregadas possibilitam a execução de operações sobre colunas das linhas de todo resultado de um SELECT, podendo-se ainda escolher entre estas as que satisfaçam determinado critério.
Existe ainda a hipótese de definir funções agregadas só para grupos de quebra, desde que se utilize a palavra GROUP.
A estrutura da instrução para definir uma função agregada é a seguinte:
[GROUP] <função agregada> OF <coluna ou expressão aritmética envolvendo coluna> [WHERE <expressão lógica>]
|
Formato da instrução para definir funções agregadas
NOTAS:
- GROUP e WHERE são opcionais;
- GROUP só pode ser utilizado num bloco AFTER GROUP.
Estão disponíveis as seguintes funções agregadas:
COUNT | Conta o número total de linhas do resultado ou do grupo e que satisfaçam a cláusula WHERE, se existir. |
PERCENT | Executa um função de contagem semelhante a função COUNT, mas dá o resultado em percentagem em relação ao número total de linhas selecionadas. |
TOTAL | Acumula o valor da coluna especificada para todas as linhas do resultado ou do grupo e que satisfaçam a cláusula WHERE, se existir. |
AVERAGE ou AVG | Calcula o valor médio da coluna especificada para todas as linhas do resultado ou do grupo e que satisfaçam a cláusula WHERE, se existir. |
MIN | Calcula o valor mínimo da coluna especificada para todas as linhas do resultado ou do grupo e que satisfaçam a cláusula WHERE, se existir. |
MAX | Calcula o valor máximo da coluna especificada para todas as linhas do resultado ou do grupo e que satisfaçam a cláusula WHERE, se existir. |
AFTER GROUP OF cust LET totcli = GROUP TOTAL OF total_price LET totger = totger + totcli
PRINT COLUMN 01, "TOTAL CLIENTE:", COLUMN 17, totcli USING "$$$$$####&.&&"
PRINT GROUP TOTAL OF total_price WHERE total_price > 500 USING "$$$$$####&.&&"
|
Exemplos de utilização de funções agregadas
CLIPPED
Esta instrução suprime os espaços em branco a direita do último caracter diferente de espaço em branco dos campos tipo alfanuméricos.
BEFORE GROUP OF cust SKIP 1 LINE NEED 2 LINES
PRINT COLUMN 01, "CLIENTE:", COLUMN 10, cust USING "<<<<", COLUMN 16, company CLIPPED
|
Exemplo da instrução CLIPPED
COLUMN
Esta instrução permite imprimir o campo que se segue a partir da coluna especificada.
BEFORE GROUP OF cust SKIP 1 LINE NEED 2 LINES PRINT COLUMN 01, "CLIENTE:", COLUMN 10, cust USING "<<<<", COLUMN 16, company CLIPPED
|
Exemplo da instrução COLUMN
LINENO
Esta expressão contém o número da linha corrente que o REPORT está para imprimir.
IF LINENO = 24 THEN SKIP TO TOP OF PAGE END IF
|
Exemplo da instrução LINENO
NOTA: Não utilize LINENO em blocos PAGE HEADER ou TRAILER porque não funcionará corretamente.
PAGENO
Esta expressão contém o número da página que o REPORT está imprimindo no momento.
PAGE HEADER PRINT COLUMN 01, "RESUMO DAS ENCOMENDAS POR CLIENTE DE ", inic, " A ", fim, COLUMN 70, "Pagina ", PAGENO USING "<<<"
|
Exemplo da instrução PAGENO
TIME
Esta instrução devolve uma frase com o valor da hora corrente que tem o formato "hh:mm:ss", onde hh é horas, mm é minutos e ss é segundos.
USING
Esta expressão permite definir o formato de impressão dos campos do tipo numérico e data, a que está associada.
PRINT "RESUMO DAS ENCOMENDAS POR CLIENTE DE ", inic, " A ", fim, COLUMN 70, "Pagina ", PAGENO USING "<<<" PRINT COLUMN 10, "Encomenda:", COLUMN 21, ord USING "<<<<", COLUMN 29, "Total:", COLUMN 36, tot1 USING "$$$$$####&.&&", COLUMN 53, "Pagamento em:", COLUMN 67, pg1, pgc1 CLIPPED
|
Exemplos da instrução USING
NOTAS:
- O conjunto de caracteres que definem o formato precisa estar entre " " (aspas);
- USING pode ser usado nas instruções PRINT e LET;
- Se, por acaso, um campo de valor tiver comprimento superior ao espaço definido para a impressão na expressão USING, este será impresso com asteriscos.
A seguir descrevem-se os principais caracteres para definição do formato utilizando a expressão USING:
Números:
* | Imprime asteriscos em vez de zeros não significativos. |
& | Mantém os zeros não significativos. |
# | Imprime espaços em vez de zeros não significativos. |
< | Imprime um número encostado à esquerda. |
, | Este caracter é impresso na posição em que for escrito. Se não existirem números à sua esquerda não é impresso. |
. | Este caracter é impresso na posição em que for escrito. Só pode existir um ponto por campo. |
"-" | Este caracter é impresso quando o número for negativo. |
+ | Este caracter imprime "+" quando o número for positivo e "-" quando for negativo. |
$ | Este caracter é impresso antes do número. |
Datas
dd | Imprime o dia do mês como um número (01 a 31). |
ddd | Imprime o dia da semana usando uma abreviatura com 3 letras. |
mm | Imprime o mês como um número (01 a 12). |
mmm | Imprime o mês usando uma abreviatura com 3 letras. |
yy | Imprime o ano como um número de 2 digitos (01 a 99). |
yyyy | Imprime o ano como um número de 4 digitos (0001 a 9999). |
14 Depurador de programa
Uma das tarefas mais trabalhosas e que os programadores menos apreciam é a fase de testes de um programa.
Quanto existem erros internos no programa (geralmente conhecidos como bugs), geralmente recorre-se a técnicas de visualização do conteúdo das variáveis, utilizando instruções básicas (DISPLAY, PROMPT etc.). Depois de testado o programa é necessário retirar todos estes códigos auxiliares (instruções colocadas para descobrir bugs) do programa, para gerar a versão válida para o usuário.
Estas técnicas são geralmente muito trabalhosas e demandam de muito tempo de desenvolvimento e manutenção de um programa.
Para permitir a fácil manutenção e descoberta de erros, foram criados programas de testes chamados debugger(s). Estes programas, geralmente acompanham a execução de um programa e permitem o controle completo do programa durante a sua execução.
No 4GL foi criado o programa INTERACTIVE DEBUGGER para permitir a depuração de programas em execução, também citado como DEBUGGER somente.
O detalhamento mais a fundo desta ferramenta está em um manual a parte.
14.1 Como executar o depurador
O DEBUGGER é executado a partir do sistema operacional, executando o comando “fgldb”, enviando como argumento o nome do programa que se pretende fazer debug.
14.2 Telas do depurador
O depurador tem duas telas:
- A tela da aplicação. Nesta tela é visualizado o programa tal como é apresentado quando é executado normalmente.
- A tela de DEBUG, que é constituída por duas janelas: a janela do código fonte e a janela de comandos. Na janela do fonte é visualizado o código do programa utilizado. Na janela de comandos, comanda-se toda a execução e parametrização do DEBUGGER.
15 Base de dados de exemplo deste manual
A base de dados utilizada neste manual tem as seguintes características:
Numa primeira visão, verificou-se que é necessário armazenar vários dados sobre cada livro (nome, autor ou autores, número de volumes, tema ou temas do livro). Chama-se a atenção para o fato de um livro poder ter sido escrito por mais de um autor ou incidir sobre vários temas. O nome de um autor ou de um tema geralmente são bastante extensos e são utilizados pelo menos uma vez por livro. Aconselha-se portanto o uso de uma tabela que relacione um código reduzido com o nome.
Pretende-se também que esteja prevista a possível requisição de um livro por eventuais usuários da biblioteca.
15.1 Estrutura da base de dados
+-------+ +--------------+
|LIVROS | | LIVRO_AUTORES| +-------+
+-------+ 1:n +--------------+ |AUTORES|
|numero |<----+------>| livro | n:1 +-------+
|editora|<--+ | | autor |<----------------->| numero|
| ... | | | | ... | | ... |
| ... | | | | ... | | ... |
+-------+ | | +--------------+ +-------+
| |
| |
| |
| |
| | +-----------+
| | |LIVRO_TEMAS| +-------+
| | 1:n +-----------+ | TEMAS |
| +------>| livro | n:1 +-------+
| | | tema |<-------------------->|codigo |
| | | ... | | ... |
| | +-----------+ +-------+
| | +--------------+
| | | REQUISICOES | +-----------+
| | 1:1 +--------------+ | ENTIDADES |
| +------>| livro | n:1 +-----------+
| | entidade |<------------>| numero |
| | ... | | ... |
| | ... | | ... |
| +--------------+ +-----------+
| +----------+
| | EDITORAS |
| n:1 +----------+
+---------------------------------------->| codigo |
| ... |
| ... |
+----------+
A tabela livros contém uma linha para cada livro incluído e contém toda a informação relativa a um livro que seja única por livro. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*numero | integer | Número do livro |
nome | char(60) | Nome do livro |
traducao | char(60) | Nome do tradutor |
volumes | smallint | Número de volumes |
paginas | smallint | Número de páginas |
editora | char(5) | Número da edição |
ano | smallint | Ano de edição |
data_entrada | date | Data da compra |
sala | char(5) | Sala onde está arrumado |
estante | char(5) | Estante onde está arrumado |
prateleira | char(5) | Prateleira onde está arrumado |
observacoes | char(50) | Observações sobre o livro |
Estrutura da tabela livros
A tabela autores relaciona o nome de cada autor com um código reduzido. Não é permitida a repetição nem do código, nem do livro. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*numero | serial | Número seqüencial do autor |
nome | char(70) | Nome do autor |
Estrutura da tabela autores
A tabela temas identifica determinado tema por um código. Não é permitida a repetição de nomes e de códigos. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*numero | char(5) | Código de identificação do tema |
nome | char(50) | Nome do tema |
Estrutura da tabela tabela temas
A tabela editoras identifica uma editora por um código de editora. Tal como nas tabelas anteriores não há repetições do código e nome de editora. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*codigo | char(5) | Código de identificação da editora |
nome | char(50) | Nome da editora |
Estrutura da tabela editoras
A tabela livro_autores relaciona determinados livros com determinados autores, permitindo que um livro possua mais de um autor, não permitindo linhas com os mesmos códigos de livro e autor. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*livro | integer | Número do livro |
*autor | integer | Número do autor |
Estrutura da tabela livro_autores
A tabela livro_temas funciona da mesma forma que a tabela livro_autores, fornecendo a informação sobre os temas focados por livro. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*livro | integer | Número do livro |
*tema | char(5) | Código de identificação do tema |
Estrutura da tabela livro_temas
A tabela requisicoes tem informação acerca de quem e quais os livros que estão requisitados por determinada entidade. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*livro | integer | Número de identificação do livro |
*entidade | integer | Identificação da entidade requisitante |
Estrutura da tabela requisições
A tabela entidades tem os dados gerais de cada entidade. A sua estrutura é a seguinte:
NOME | TIPO | DESCRIÇÃO |
*numero | integer | Número de identificação da entidade |
nome_reduzido | char(20) | Nome de rápido acesso |
nome | char(50) | Nome da entidade |
endereco | char(60) | Endereço da entidade |
Estrutura da tabela entidades