Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Índice

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.

...

O desenvolvimento e compilação das aplicações desenvolvidas em 4GL são realizadas via ferramenta de desenvolvimento Totvs Developer Studio disponivel 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.

...

 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.

...

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
 OU
DEFINE nome_da_variavel LIKE tabela.coluna 

 

...

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:

...

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 [, ...]

 

...

 

 varlocal.4gl

MAIN
   DEFINE l_inteiro INTEGER   
   LET l_inteiro = 1
   CALL mostra_local()
   CALL mostra_local_agora(l_inteiro)
END MAIN

FUNCTION mostra_local()
  DEFINE l_inteiro INTEGER
  DISPLAY “INTEIRO: “, l_inteiro
  SLEEP 2
END FUNCTION

FUNCTION mostra_local_agora(l_inteiro)
DEFINE l_inteiro INTEGER
DISPLAY “INTEIRO AGORA: “,l_inteiro
  SLEEP 2
END FUNCTION

RESULTADO:
INTEIRO:           0
INTEIRO AGORA: 1

 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
   {instrução DEFINE}
END 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.

...

 

 varglob1.4gl

GLOBALS
   DEFINE g_inteiro INTEGER
END GLOBALS

MAIN
   LET g_inteiro = 5
  DISPLAY "inteiro VARGLOB1: ",g_inteiro
   SLEEP 2
   CALL mostra_varglob2()
   DISPLAY "VARGLOB1 após VARGLOB2: ",g_inteiro
   SLEEP 2
END MAIN

 

varglob2.4gl

GLOBALS
   DEFINE g_inteiro INTEGER
END GLOBALS

FUNCTION mostra_varglob2()
   DISPLAY "inteiro VARGLOB2: ",g_inteiro
   SLEEP 2
   LET g_inteiro = 10
END FUNCTION

RESULTADO:
 inteiro VARGLOB1:           5
 inteiro VARGLOB2:           5
 VARGLOB1 após VARGLOB2: 10

 

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 [, ...]

 

...

 

varmod1.4gl

DEFINE m_inteiro INTEGER

MAIN
   LET m_inteiro = 1
   DISPLAY “inteiro VARMOD1: “,m_inteiro
   SLEEP 2
   CALL mostra_varmod2()
   DISPLAY "VARMOD1 após VARMOD2: ",g_inteiro
   SLEEP 2
END MAIN

varmod2.4gl

DEFINE m_inteiro INTEGER
FUNCTION mostra_varmod2()
DISPLAY “inteiro VARMOD2: “,m_inteiro
SLEEP 2
LET m_inteiro = 3

 END FUNCTION

RESULTADO
inteiro VARMOD1:           1
inteiro VARMOD2:           0 
VARMOD1 após VARMOD2:           1

            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.

...

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

.

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).

...

É 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
   DEFINE x INTEGER
          y CHAR(100)

   CALL func() RETURNING x,y

   DISPLAY x
   DISPLAY y

END MAIN

FUNCTION func()
  RETURN 100,"Esta string vai ser devolvida"
END FUNCTION

RESTULTADO:
 100
 Esta string vai ser devolvida

Função com retorno de vários valores

...

Em português esta instrução poderia ser explicada por:

   

Se esta expressão é verdadeira
    Então faz isto
Senão faz aquilo 

 

...

Esta instrução de repetição pode ser explicada por:

   

...

   

Enquanto esta_expressão_for_verdadeira faz_isto 

 

...

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"
    CALL bebe_mais_cerveja()
 END WHILE 

Ciclo WHILE

...

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)
 DISPLAY l_str 

 Exemplo de utilização da função UPSHIFT

...

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
        [HELP numero_do_help]
        [ON KEY (tecla)
   instrução
   ...
   ...
END PROMPT

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 pretender enviar pequenas mensagens ao usuário utiliza-se no 4GL a instrução DISPLAY AT.

 

DISPLAY lista_de_variaveis
        [AT linha_do_tela,coluna_da_tela]
        [ATTRIBUTE (lista_de_atributos)] 

 Definição da instrução DISPLAY AT

...

Os atributos possiveis são:

 

...

 

WHITE
YELLOW
MAGENTA
RED
CYAN
GREEN
BLUE
BLACK

 

 

REVERSE
BLINK
UNDERLINE
NORMAL
BOLD
DIM
INVISIBLE

 

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.

 

 

 

  displaydisplay.4gl MAIN

MAIN
   DISPLAY "Isto vai aparecer na tela na linha 10 coluna 3"
           AT 10,3 ATTRIBUTE(BOLD)
 END END MAIN

 

 $ $ fglpc display.4gl
 $ $ fglgo display.4go

 

 

 

 

 

 

 

 

 

   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

...

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}
          {GOTO label | CALL nome_de_função | CONTINUE | STOP

 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.

...

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 FUNCTION exp()
    WHENEVER ERROR GOTO erro
  SELECT *
    INTO pr_livros.*
    FROM livroslivros 

    RETURNRETURN 

    LABEL erro:
     DISPLAY "ERRO"
 END END FUNCTION

 

 

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 FUNCTION exp()
     WHENEVER ERROR GOTO CALL erro()
  SELECT *
    INTO pr_livros.*
    FROM livroslivros 

  RETURN
  RETURNEND FUNCTION 

 END FUNCTION

 

 FUNCTION erro()
    DISPLAY "ERRO"

 END FUNCTION

 END FUNCTION 

 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.

...

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
       SQLCODE INTEGER,
       SQLERRM CHAR[71],
       SQLERRP CHAR(8);
       SQLERRD ARRAY[6] OF INTEGER,
       SQLAWARN CHAR(8)
 END END RECORD

 

 

RECORD SQLCA

O significado de cada uma das variáveis é:

 SQLCODE: Indica o resultado de uma instrução de SQL.Toma os valores:

...

O fluxo de informação de uma tela para a base de dados poderia ser descrito pelo seguinte esquema:

 

 

 

+-------+           +---------------------------------+
| Tela  |<--------->| Variáveis internas ao programa  |<-+
+-------+     |     +---------------------------------+  |
              |                                          |
forms e instruções de input/output                       |
                                           SQL___________|
    +----------------+       +---------+                 |
    | Banco de dados |<----->| SQLEXEC |<----------------+
    +----------------+       +---------+

 

 

Comunicação das telas com o banco de dados

7.1      FORM

As forms servem para desenhar e processar entrada de dados.

...

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.

 

 

 

...

 

+----------+|

form.per
|

+----------+
     |
     |____form4gl
     |
+----------+|

form.frm
|

+----------+ 

 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 DATABASE [FORMONLY | <nome banco dados>]
   SCREEN
  {
 numero   numero [f000 ]
 nome     nome   [f001                   ]
                 [f002                   ]
 }
 END 

 [TABLES]
 <tabela1>,
 <tabela2>,
 ...,

 <tabelaN>

  <tabelaN> 

 ATTRIBUTES
 f000 = <tabela>.<coluna>;
 f001 = formonly.<nome campo>;
 f002 = formonly.<nome campo TYPE LIKE <tabela.coluna>;
 END 

 [INSTRUCTIONS]
     [DELIMITERS]
   [SCREEN RECORD...]
 [END]

 

 

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.

...

Quando é utilizada a cláusula DATABASE FORMONLY esta seção não é definida.

 

 

 

TABLES
<tabela1>,
<tabela2>,
...,

<tabelaN>

 <tabelaN> 

 Definição da seção TABLES

7.2.4       Seção ATTRIBUTES

...

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 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 f011 = livros.data_entrada, AUTONEXT,
        COMMENTS = "Informe a data em que o livro entrou na biblioteca"; 

 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 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.

...

As datas podem ter os separadores "-" ou "/" à escolha.

 

 

 

 f011 f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY, 
                             FORMAT = "dd/mm/yyyy "; 

 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.

...

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 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.

...

Este atributo mostra os campos, a que está associado, com caracteres em vídeo reverso.

 

 

 

 f000 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.

...

X Representa qualquer caracter.

 

 

 

 f001 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.

...

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>per> 

 

 

Exemplo de compilação de form

O comando form4gl tem a estrutura de um comando LINUX, com três opções disponíveis.

...

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 form4gl -d f_livros livros autores livros

 

 

livros 

 

...

Cria e compila a form f_livros com as tabelas LIVROS e AUTORES do banco de dados LIVROS.

 

 

 

 

 form4gl form4gl -v f_livros

 

 

 

livros 

No comando acima é realizada apenas a compilação da form f_livros.

8       Gestão de janelas – parte 1

...

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
      WITH {numero_de_linhas ROWS numero_de_colunas COLUMNS
           |FORM "ficheiro_da_form"}
     [ATTRIBUTE (lista_de atributos)] 

 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);

...

  • 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
      ATTRIBUTE (BORDER, MESSAGE LINE LAST,
                 PROMPT LINE LAST-2) 

 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_janelajanela 

 

 

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 CURRENT WINDOW IS nome_da_janela 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.

...

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 |
          PROMPT  LINE linha |
          COMMENT LINE linha |
          ERROR   LINE linha |
          FORM LINE linha |
          INPUT {WRAP | NO WRAP} |
          INSERT KEY tecla |
          DELETE KEY tecla |
                    NEXT KEY tecla |
          PREVIOUS KEY tecla |
          ACCEPT KEY tecla |
          HELP FILE "ficheiro" |
          HELP KEY tecla }

 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
       [WHITHOUT DEFAULTS]
       |lista_de_variaveis [WITHOUT DEFAULTS]
  FROM {lista_campos|screen_record[[n]].*}[,...}}
       [HELP numero_do_help]

 

 

[{BEFORE INPUT
 |AFTER INPUT
 |BEFORE FIELD sublista_de_campos
 |AFTER {FIELD sublista_de_campos|INPUT}
 |ON KEY(lista_de_teclas)}
    instrução
    ...

    

    [NEXT FIELD nome_do_campo]
    ...
    [EXIT INPUT]
    ...
    ...

 

END 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

...

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 

 

 DATABASE livros

 

 SCREEN
 {       número: [f000 ]
         nome: [f001          f001]
     tradução         tradução: [f003          f003]
               volumes: [f005]
         páginas: [f006]
         edição: [f007]
          ano         ano: [f008]
 data          data entrada: [f009      f009]
         sala: [f010]
               estante: [f011]
            prateleira: [f012]
           observações: [f013                                       f013] }
 END 

 TABLES

 livros

        livros 

 ATTRIBUTES
      
 f000 = livros.numero;
 f001         f001 = livros.nome;
        f003 = livros.traducao;
        f005 = livros.volumes;
        f006 = livros.paginas;
        f007 = livros.edicao;
        f008 = livros.ano;
 f009         f009 = livros.data_entrada;
        f010 = livros.sala;
        f011 = livros.estante;
        f012 = livros.prateleira;
        f013 = livros.observacoes;

 END

 

 

...

END

  

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 DATABASE livros 

 SCREEN
 { Número do livro: [f000]
       Nome do livro: [f001                          f001]
            Tradução: [f004                          f004]
              Volumes: [f007]         
     Páginas: [f008]
              Editora: [f009]
             Ano     Ano: [f010]  
     Data de entrada: [f011      f011]
                Local:            Sala: [f012]
                          Estante: [f013]
                       Prateleira: [f014]
     Observações: [f015                                         f015]    } 

 Seção SCREEN da form livros

A seção TABLES fica da mesma forma como foi apresentado inicialmente:

 

...

 

 TABLES
  
 livros 

 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.

...

Na form livros iremos usá-lo nas datas.

 

 

 

 f011 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 f011 = livros.data_entrada, AUTONEXT,
        COMMENTS = "Informe a data em que o livro entrou na biblioteca";

 

 

 

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 f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY

   FORMAT

 

FORMAT

Na form livros iremos usar o atributo "format" apenas nas datas e com o formato "dd/mm/yyyy".

 

 

 

 f011 = f011 = livros.data_entrada, AUTONEXT, DEFAULT = TODAY, 
                             FORMAT = "dd/mm/yyyy ";

 

 

 

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 f007 = livros.volumes, INCLUDE = (1 to 100); 

 

...

  

REVERSE

Na form livros vamos usar em vídeo reverso o campo número.

 

 

 

 f000 f000 = livros.numero, REVERSE

 

...

 9.2      Programa de cadastro de livros

 

 DATABASE

DATABASE livros

 MAIN

MAIN
    CALL menu()

 END MAIN

 

 FUNCTION

END MAIN 

FUNCTION menu()
   OPEN WINDOW w_livros AT 2,2 WITH FORM "livros"

 END FUNCTION

 

END FUNCTION 

Abertura da form livros

A abertura da tela será feita utilizando a instrução OPEN WINDOW.

...

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

DATABASE livros 

 

 DEFINE mr_livros LIKE livros.*

 MAIN

MAIN
    CALL menu()

 END MAIN

 

 FUNCTION

END MAIN 

FUNCTION menu()
   OPEN WINDOW w_livros AT 2,2 WITH FORM "livros"

 END FUNCTION

 

END FUNCTION 

Declaração do RECORD mr_livros

Este programa terá um menu que permitirá as seguintes opções sobre a tabela de LIVROS:

...

Para criar menus utiliza-se a instrução MENU já vista anteriormente.

 

...

 

 MENU "LIVROS"
 COMMAND COMMAND "Incluir" "Incluir um novo livro."
    CALL incluir() 

 COMMAND COMMAND "Consultar" "Consultar um livro pelo numero."
    CALL consultar() 

 COMMAND COMMAND "Modificar" "Permite modificar o livro corrente."
    CALL modificar() 

 COMMAND COMMAND "Excluir" "Remove o livro corrente."
    CALL excluir() 

 COMMAND COMMAND "Fim" "Sai do programa."
    EXIT MENU
 END END MENU

 

 

Menu da entrada de dados para livros

Este menu é implementado após a abertura da form principal de cadastro de livros.

...

Nesta função vamos utilizar a instrução INPUT na sua forma mais simples.

 

 

 

 FUNCTION FUNCTION incluir()
  INPUT BY NAME mr_livros.* 

  WHENEVER ERROR CONTINUE
  INSERT INTO livros VALUES (mr_livros.*)
  WHENEVER ERROR STOP STOP 

  IF sqlca.sqlcode = 0 THEN
     ERROR "Livro incluído"
  ELSE
     ERROR "Erro na inclusão do livro ",status
  END IF

 END FUNCTION

 

 

END FUNCTION 

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 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 FUNCTION consultar()
  CLEAR FORM FORM 

  INPUT BY NAME mr_livros.numero numero 

  SELECT *
    INTO mr_livros.*
    FROM livros
       WHERE numero = mr_livros.numeronumero 

 

  IF status != 0 THEN
     ERROR "Livro não cadastrado"
  ELSE
     DISPLAY BY NAME mr_livros.*
  END IF

 END FUNCTION

 

 

END FUNCTION 

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.

...

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

FUNCTION modificar()
  IF mr_livros.numero IS NULL THEN
     ERROR "Nao ha nenhum livro para mudar"
  ELSE
     INPUT BY NAME mr_livros.* WITHOUT DEFAULTS

 

     WHENEVER ERROR CONTINUE
     UPDATE livros
        SET livros.* = mr_livros.*
      WHERE livros.numero = mr_livros.numero
     WHENEVER ERROR STOP
     IF sqlca.sqlcode <> 0 THEN
        ERROR “Erro na modificação – “,sqlca.sqlcode
     ELSE
        ERROR “Livro modificado.”
     END IF
  END IF

 END

END FUNCTION

 

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.

...

Esta função exclui do banco de dados o livro correspondente aos dados presentes na entrada de dados.

 

 

 

 FUNCTION

FUNCTION excluir()
  IF mr_livros.numero IS NULL THEN
     ERROR "Não há nenhum livro para excluir"
  ELSE
     WHENEVER ERROR CONTINUE
     DELETE FROM livros
      WHERE numero = mr_livros.numero
     WHENEVER ERROR

STOP 

STOP 

     IF sqlca.sqlcode <> 0 THEN
        ERROR "Erro na exclusão - ",sqlca.sqlcode
     ELSE
        INITIALIZE mr_livros.* TO NULL
        CLEAR FORM
        ERROR "Livro excluído"
     END IF
  END IF

 END

END FUNCTION

 

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

...

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

...

A form tem que possuir um novo campo onde será visualizado o nome da editora na seção SCREEN, assim:

 

 

 

 EditoraEditora: [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 = 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 campo = FORMONLY.nome_do_campo [TYPE [tipo_de_dados | LIKE tabela.coluna]]
                                [NOT NULL][,lista_de_atributos] 

 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 DEFINE l_nome_editora LIKE editoras.nome;

 

 INPUT BY NAME mr_livros.* 

 AFTER FIELD editora
    INITIALIZE l_nome_editora TO NULL
    WHENEVER ERROR CONTINUE
    SELECT nome
      INTO l_nome_editora
      FROM editoras
     WHERE codigo = mr_livros.editora
    WHENEVER ERROR STOP
    IF sqlca.sqlcode = NOTFOUND THEN
       ERROR "Editora não cadastrada."
       NEXT FIELD edicaoedição
    ELSE
       DISPLAY l_nome_editora TO nome _ editora
    END IF

 END INPUT

 

 

END INPUT 

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 DEFINE l_nome_editora LIKE editora.nome; 

 LET int_flag = 0
   INPUT BY NAME mr_livros.*

 

 AFTER AFTER FIELD edicaoedição
    INITIALIZE l_nome_editora TO NULL
    WHENEVER ERROR CONTINUE
    SELECT nome
      INTO l_nome_editora
      FROM editoras
     WHERE codigo = mr_livros.editora
    WHENEVER ERROR STOP
    IF sqlca.sqlcode = NOTFOUND THEN
       ERROR "Editora não cadastrada."
       NEXT FIELD editora
    ELSE
       DISPLAY l_nome_editora TO nome _ editora
    END IFIF 

 

 AFTER AFTER INPUT
    IF int_flag = 0 THEN
       #Consistências da entrada de dados
    END IF

 END INPUT

 

END INPUT 

IF  IF int_flag <> 0 THEN
 
    ERROR “Inclusão cancelada.”
 ELSEELSE
    #Realizar a inclusão do livro(INSERT)

 END IF

 

 

END IF 

Alteração das instruções INPUT para efetuar as validações

...

11    Interação do 4GL com o banco de dados

...

Uma instrução SELECT pode dar origem a mais de uma linha da dados (depende da cláusula WHERE).

 

 

 

  errselecterrselect.4gl
 DATABASE
DATABASE livros
 MAIN

 MAIN

   DEFINE l_numero LIKE livros.numero,
          l_nome LIKE livros.nome,
          l          l_edicao LIKE livros.edicaoedicao 

 

   SELECT numero, nome, edicaoedição
     INTO l_numero, l_nome, l_edicao
     FROM livros

 END MAIN

 

END MAIN 

$  $ fglpc errselect.4gl
 $ $ fglgo errselect.4go
 Program Program stopped at "errselect.4gl" line number 9.
 SQL SQL statement error number -284.
 A A subquery has returned not exactly one row. 

 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.

...

Esta ação é realizada com o auxilio da instrução DECLARE associada a  uma instrução SELECT.

 

 

 DECLARE cq_livros CURSOR FOR
  SELECT numero, nome, edicaoedição
    FROM livros
       WHERE numero < 5

 

   

 

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_livroslivros  

  

 

 

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 WHILE 1
    FETCH cq_livros INTO numero, nome, edicao;
    IF sqlca.sqlcode != 0 THEN
       EXIT WHILE
    END IF
    DISPLAY numero, nome, editora
 END WHILEWHILE 

 

 

 

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 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 DATABASE livros 

MAIN

 MAIN

   DEFINE numero LIKE livros.numero,
          nome   LIKE livros.nome,
          aux    SMALLINTSMALLINT 

 

   DECLARE cq_livros CURSOR WITH HOLD FOR
          SELECT numero, @nome
      FROM livros
     WHERE numero < 5 

   LET aux = 1

 

   OPEN cq_livros

 

   WHILE aux = 1
      FETCH cq_livros INTO numero, nome
      IF sqlca.sqlcode != 0 THEN
         EXIT WHILE
      END IF 
      DISPLAY numero, nome
   END WHILEWHILE 

 

   CLOSE cq_livros
 END END MAIN

 

 $ fglpc cursor1.4gl
 $ fglgo cursor1.4go
 1Artificial 1Artificial Inteligence Using C
 2C 2C Power User's Guide
 3Microprocessors3Microprocessors
 4The 4The Complete ReferenceReference 

 

 

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
  SELECT ...
 FOR UPDATE 

 

Definição genérica da declaração de um cursor FOR UPDATE

A alteração faz-se da seguinte forma: 

  1. Declarar um cursor "FOR UPDATE"

 

  1.  

 

 DECLARE cq_livros CURSOR FOR
  SELECT   SELECT numero, nome, edicaoedição
    FROM livros
   WHERE numero < 5
 FOR UPDATE 

 

 

  1. Abrir o cursor da forma descrita anteriormente.

 

...

 

 OPEN cq_livros livros 

 

 

  1. 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 

 UPDATE

    SET <colunas a modificar>
    WHERE CURRENT OF cq_livroslivros 

 

   

 

Depois da instrução UPDATE o cursor continua posicionado na linha corrente.

 

...

 

  cursupd.4gl

 DATABASE DATABASE livros 
 MAIN
   DEFINE numero LIKE livros.numero,
         nome   LIKE livros.nome,
         edicao LIKE livros.edicao,
         ans    CHAR(1),
         aux    SMALLINT SMALLINT 

   DECLARE cq_livros CURSOR FOR
    SELECT numero, nome, edicaoedição
      FROM livros
     WHERE numero < 5
   FOR UPDATE OF edicao edicao 

   OPEN cq_livros 
   WHILE aux = 1
      FETCH cq_livros INTO numero, nome, edicao edição

      IF edicao IS NULL THEN
         PROMPT nome CLIPPED,"-Qual a editora para este livro: "
            FOR edicao edição

         UPDATE livros
            SET edicao = edicaoedição
          WHERE CURRENT OF cq_livros livros 

         PROMPT "Quer alterar mais livros (s/n):"
                               FOR CHAR ans
         IF ans != "s" THEN
            EXIT WHILE
         END IF
      END IF IF 

      IF sqlca.sqlcode != 0 THEN
         EXIT WHILE
      END IF

   END WHILE

 END MAIN

 

 $ fglpc cursupd.4gl
 $ fglgo cursupd.4go

 Artificial Artificial Inteligence using C

 -Qual a editora para este livro: BERTR
 Quer Quer alterar mais livros (s/n): n
 $ 

 

Cursor para alteração ( FOR UPDATE )

11.1.1    Cursores com atributo SCROLL

...

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

 

...

  1. Declarar um cursor associando-o a uma instrução INSERT.

 

 

 

 DECLARE DECLARE cq_livros CURSOR FOR
  INSERT INTO livros
         (numero, nome, edicao)
  VALUES (l_numero, l_nome, l_edicao) 

   

 

  1. Abrir o cursor. Identico a um cursor normal.

 

 

 

 OPEN OPEN cq_livros

 

 

...

livros 

  

  1. Ler os dados para dentro de determinada variáveis (INPUT, LET).

...

  1. Escrever as variáveis no buffer com o auxilio da instrução PUT.

 

 

 

 

 PUT PUT cq_livros livros 

 

  1. Fechar o cursor. 

 

 

 CLOSE CLOSE cq_livroslivros 

 

 

 

 

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.

...

  1. Colocação de uma string com as instruções SQL desejadas dentro de uma variável tipo CHAR.

 

 

 

 LET LET l_sql_delete = “DELETE FROM livros WHERE numero = 10” 10” 

 

Instrução PREPARE

  1. 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 PREPARE var_delete FROM l_sql_delete delete 

 

Instrução PREPARE

  1. Execução da instrução através da instrução EXECUTE.

 

 

 

 EXECUTE EXECUTE var_deletedelete 

 

 

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.

...

  1. Preparar a instrução com PREPARE.

 

...

 

 PREPARE id_expressão FROM expressão_char

 

 

...

char 

  

  1. Declarar o cursor para essa instrução.

 

 

 

 DECLARE DECLARE nome_cursor CURSOR FOR id_expressão

 

 

...

expressão 

  

  1. 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 OPEN nome_cursor USING var1 var2 ... varn

 

 

...

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.

...

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
           |variavel_char ON lista_de_colunas
      FROM {lista_de_campos|record_tela[[n]].*}{[,...]} 

[{BEFORE CONSTRUCT
 |AFTER CONSTRUCT
 |BEFORE FIELD sublista_de_campos
 |AFTER {FIELD sublista_de_campos|INPUT}
 |ON KEY(lista_de_teclas)}
    instrução
    ...
    [NEXT FIELD nome_do_campo]
    ...
    [EXIT CONSTRUCT]
    ...
    ...
 END 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.

...

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.*
         [ATTRIBUTE(lista_de atributos)]
 {ON KEY (lista_de_teclas)
     instrução
     ...
     [EXIT DISPLAY]
 ...
 END DISPLAY

 

 

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.

...

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
 {
 Código  Nome
 ------- ----------------------------------------------------
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 [f000 ] [f001                                              ]
 }
 END

 

 

Seção SCREEN da form de zoom editoras

Como em qualquer form, cada label precisa estar declarado na seção ATTRIBUTES.

 

...

 

 ATTRIBUTES
 f000 = editoras.codigo;
 f001 = editoras.nome;
 END

 

 

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
 DELIMITERS " "
 SCREEN RECORD sr_editoras[8] (editoras.codigo,editores.nome) 

 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.

...

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

 

 AFTER FIELD edicao
    CALL consiste_editora()
    IF status = NOTFOUND THEN
       LET mr_livros.editora = zoom_editora()
       CALL consiste_editora()
    END IF
    DISPLAY BY NAME mr_livros.editora, <variável nome_editora>

 

 

...

editora> 

  

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 OPEN WINDOW w_editoras AT 5, 5 WITH FORM "editoras"
      ATTRIBUTE(BORDER)

 

 

 

Para invocar a instrução DISPLAY ARRAY, é necessário declarar um record no programa para fazer display.

 

 

 

 

 DEFINE DEFINE la_editoras ARRAY[40] OF RECORD LIKE editoras.*,
        numero_editoras INTEGER,
        linha_corrente INTEGER

 

 

INTEGER 

 

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 LET numero_editoras =

 DECLARE cq_editoras CURSOR FOR
  SELECT *
    FROM editores editores 

 FOREACH cq_editoras INTO la_editoras[numero_editoras].*
    IF status != 0 THEN
       EXIT FOREACH
    END IFIF 

 

    IF numero_editoras >= 40 THEN
       ERROR "Editoras a mais"
       EXIT FOREACH
    END IF IF 

    LET numero_editoras = numero_editoras + 1
 END FOREACH
 FREE cq_editoraseditoras 

 

 LET numero_editoras = numero_editoras - 1

 

 

 

Nesta versão são apenas visualizados as primeiras quarenta editoras.

 

 

 

 CALL CALL set_count(numero_editoras) 

 DISPLAY ARRAY la_editoras TO sr_editoras.* 

 LET linha_corrente = arr_curr() 

 CLOSE WINDOW w_editoras 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 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 RETURN la_editoras[linha_corrente].codigo

 

 

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]
       FROM array_tela.* [HELP numero_help] 

 [{BEFORE {ROW | INSERT | DELETE
                              | FIELD lista_de_campos | INPUT}[,...] 

  |AFTER ROW | INSERT | DELETE
             | FIELD lista_de_campos | INPUT}[,...] 

  |ON KEY(lista_teclas)
      instruçãoinstrução 

  [NEXT FIELD nome_campo]
 ...
 [EXIT INPUT]
 ...
 END INPUT]

 

 

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

...

Uma form para ser manipulada pela instrução INPUT ARRAY é idêntica a uma form utilizando DISPLAY ARRAY.

 

 

 

 DATABASE DATABASE livros

 

 SCREEN
 {
  codigo | tema
 --------+-----------------------------------------------------
 [f000 ] | [f001                                              ]
 [f000 ] | [f001                                              ]
 [f000 ] | [f001                                              ] 
 [f000 ] | [f001                                              ]
 [f000 ] | [f001                                              ]
 [f000 ] | [f001                                              ]
 }

 END

  END 

 TABLES
 temas

 

 ATTRIBUTES
 f000 = temas.codigo;
 f001 = temas.nome, NOENTRY;

 END

  END 

 INSTRUCTIONS
   SCREEN RECORD sr_temas[6] (temas.codigo, temas.nome)

 

 

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.

...

No menu do programa de entrada de dados de livros será adicionada uma nova opção de menu denominada “Temas”.

 

 

 

 COMMAND COMMAND "Temas" "Introdução de temas focados neste livro."
    IF mr_livros.numero IS NULL THEN
       ERROR "Nao há nenhum livro para informar temas."
    ELSE
       CALL temas(mr_livros.numero)
    END IFIF 

 

 

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 FUNCTION temas(l_livro)
  DEFINE l_livro   LIKE livros.numero,
         l_idx_arr INTEGER,
         l_idx_scr INTEGER,
         la_temas ARRAY[15] OF RECORD LIKE temas.* 

 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

 

 

 DECLARE cq_temas CURSOR FOR
  SELECT livro_temas.tema, temas.nome
    FROM livro_temas, temas
   WHERE livro_temas.livro  = l_livro
     AND temas.codigo = livro_temas.tema tema 

 INITIALIZE la_temas TO NULL
 LET l_idx_arr =

 FOREACH cq_temas INTO la_temas[l_idx_arr].*
    LET l_idx_arr = l_idx_arr + 1
    IF l_idx_arr > 15 THEN
       ERROR "Temas a mais."
       EXIT FOREACH
    END IF
 END FOREACH
 FREE cq_temas temas 

 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 OPEN WINDOW w_temas AT 5,7
      WITH FORM "temas" ATTRIBUTE(BORDER) 

 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 CALL set_count(l_idx_arr) 
 LET int_flag = 0
 INPUT ARRAY la_temas WITHOUT DEFAULTS FROM sr_temas.* 

 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

 

 AFTER FIELD codigo
    LET l_idx_arr = arr_curr()
    LET l_idx_scr = scr_line()
    LET la_temas[l_idx_arr].nome = get_temas(la_temas[l_idx_arr].codigo)
    IF la_temas[l_idx_arr].nome IS NULL THEN
       ERROR "TEMA “,la_temas[l_icx_arr].código,” INVÁLIDO."
    ELSE    ELSE
       DISPLAY la_temas[l_idx_arr].nome TO sr_temas[l_idx_scr].nome
    END IF IF 

 

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.

...

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 AFTER INPUT
    IF     IF int_flag = 0 THEN
       DELETE FROM livro_temas WHERE livro_temas.livro = livro livro 

       FOR pr_idx = 1 TO arr_count()
          INSERT INTO livro _ temas
          VALUES (l_livro, la_temas[l_idx_arr].codigo)
          IF sqlca.sqlcode <> 0 THEN
             ERROR              ERROR "Erro na inclusão"
          END IF
       END FOR FOR 

 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 AFTER INPUT
    #Se usuário confirmou a alteração, pressionando <ESC>
    IF int_flag = 0 THEN
       WHENEVER ERROR CONTINUE
       BEGIN WORK
       DELETE FROM temas WHERE temas.livro = l_livro
       WHENEVER ERROR STOP
       IF sqlca.sqlcode = 0 THEN

 

          LET l_erro = FALSE
          FOR l_idx_arr = 1 TO arr_count()
             WHENEVER ERROR CONTINUE
             INSERT INTO temas
             VALUES (l_livro, la_temas[l_idx_arr].codigo)
             WHENEVER ERROR STOP
             IF sqlca.sqlcode <> 0 THEN
                ERROR "Erro na inclusão."
                LET l_erro = TRUE
                EXIT FOR
             END IF
          END FOR
          IF l_erro THEN
             WHENEVER ERROR CONTINUE
             ROLLBACK WORK         
             WHENEVER ERROR STOP
          ELSE
             WHENEVER ERROR CONTINUE
             COMMIT WORK
             WHENEVER ERROR STOP
             IF sqlca.sqlcode <> 0 THEN
                ERROR “Erro na efetivação.”
             END IF            
          END IF
       ELSE
          ERROR “Erro na exclusão.”
          WHENEVER ERROR CONTINUE
          ROLLBACK WORK
          WHENEVER ERROR STOP
       END IF

    END IF

 

 

 

...

    END IF 

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.

...

Vamos considerar como exemplo a geração de um report com a informação da tabela de livros:

 

 

 

 DATABASE DATABASE livros
  {REPORT com a informação da TABELA DE LIVROS}
 FUNCTION lista_livros()
  DEFINE lr_livro RECORD LIKE livros.* 

  DECLARE cq_livro CURSOR FOR
   SELECT *
     FROM livros
    ORDER BY numero

    DISPLAY "Inicio do REPORT; espere um momento " AT 15,

  START REPORT r_livro livro 

  FOREACH cq_livro INTO lr_livro.*
     OUTPUT TO REPORT r_liv(lr_livro.*)
  END FOREACH
  FREE cq_livro 

  FINISH REPORT r_livro 

  DISPLAY "Terminou o report. Encontra-se no arquivo livros.out "AT 15,1

    SLEEP 3
  DISPLAY "" AT 15,1

 END FUNCTION

 

 

END FUNCTION 

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.

...

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.

...

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.

...

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.

...

Esta instrução indica ao INFORMIX-4GL que o report terminou.

 

 

 

 FINISH FINISH REPORT nome_reportreport 

 

 

Sintaxe da instrução FINISH REPORT

É necessário usar esta instrução para que o INFORMIX-4GL saiba que terminou o processamento do report.

...

Começando pela estrutura do REPORT utilizado no exemplo anterior:

 

 

 

 DATABASE livros

 DATABASE livros 

 REPORT r_livro(lr_relat)
  {r_livro é o report que escreve a informacão da tabela de
   livros e este report é enviado para o arquivo livros.out
  } 

  DEFINE lr_relat RECORD LIKE livros.* 

  OUTPUT REPORT TO "livros.out" 

  LEFT MARGIN 0
  TOP MARGIN 0
  BOTTOM MARGIN 0
  PAGE LENGH

  FORMAT
  ON EVERY ROW
     PRINT lr_relat.numero, 1 SPACE, lr_relat.nome CLIPPED
     PRINT lr_relat.autor,  1 SPACE, lr_relat.editora 

 END REPORT

 

 

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.

...

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 REPORT nome_report (ListaArgumentos)
  [DEFINE seção]
  [OUTPUT seção]
  [ORDER BY seção]
  FORMAT seção
 END REPORT

 

 

REPORT 

Seções que constituem um REPORT

As seções DEFINE, OUTPUT e ORDER BY são opcionais; a seção FORMAT é obrigatória.

...

A seção OUTPUT é formada pela palavra OUTPUT seguida de uma ou mais instruções:

 

...

 

 OUTPUT
 [REPORT TO instrução]
 [LEFT MARGIN valor]
 [RIGHT MARGIN valor]
 [TOP MARGIN valor]
 [BOTTOM MARGIN valor]
 [PAGE LENGHT valor]
 [REPORT TO {"arquivo" | PIPE programa | PRINTER}] 

 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 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 

 OUTPUT

 REPORT TO PIPE "more" 

 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.

...

A seção ORDER BY tem o seguinte formato:

 

 

 

 ORDER [EXTERNAL] BY lista_colunas 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.

...

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
 END REPORT 

 

...

 Exemplo da seção FORMAT mais simples

O outro tipo, mais complexo, da seção FORMAT pode ser formado da seguinte forma:

 

 

 

 FORMAT
 [PAGE HEADER bloco_de_controle]
 [PAGE TRAILER bloco_de_controle]
 [FIRST PAGE HEADER bloco_de_controle]
 [ON EVERY ROW bloco_de_controle]
 [ON LAST ROW bloco_de_controle]
 [BEFORE GROUP OF N blocos_de_controle]
 [AFTER GROUP OF N blocos_controle]
 END REPORT

 

 

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:

...

Ao usar esta instrução não pode-se usar qualquer bloco de controle.

 

...

 

 REPORT minimo(lr_livros)
  DEFINE lr_livros RECORD LIKE livros.* 
  FORMAT 
  EVERY ROW
  ENDREPORT

 

 

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.

...

Suponhamos que fosse definida a seguinte ordenação:

 

 

 

 ORDER 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
 BEFORE GROUP OF b
 BEFORE GROUP OF c
 ON EVERY ROW
 AFTER GROUP OF c
 AFTER GROUP OF b
 AFTER 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
    instruções

 

 

instruções 

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.

...

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
    Instruções Instruções 

 

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.

...

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
    InstruçõesInstruções 

 

 

Formato do bloco FIRST PAGE HEADER

A instrução TOP MARGIN da seção OUTPUT influencia na linha onde é escrito este cabeçalho.

...

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
    Instruções Instruções 

 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.

...

Este bloco de controle define as instruções que devem ser executadas depois de processada a última linha passada à rotina REPORT.

 

 

 

 ON LAST ROW
    InstruçõesInstruções 

 

 

Formato do bloco ON LAST ROW

O INFORMIX-4GL executa este bloco depois dos blocos ON EVERY ROW e AFTER GROUP OF.

...

Este bloco especifica a informação que vai aparecer no cabeçalho de cada página do relatório.

 

...

 

 PAGE HEADER
    Instruções 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.

...

Este bloco inclui as instruções que se devem executar para definir o rodapé de cada página. 

 

 

 PAGE TRAILER
    InstruçõesInstruções 

 

 

Formato do bloco PAGE TRAILER

Não se pode incluir a instrução SKIP TO TOP OF PAGE neste bloco.

...

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 FOR i=1 TO 10 STEP 2
    LET a = a * a + 2
    LET b = a * 2

 END FOR

 

 

END FOR 

Exemplo da instrução FOR

NOTA:Não se pode usar incrementos negativos .

...

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 IF paid_date IS NULL THEN
    LET pg1 = "fal"
    LET pgc1 = "ta "
 ELSE
    LET pg1 = paid_date - ship_date
    LET pgc1 = " dias"
END IF IF 

 Exemplo da instrução IF-THEN-ELSE

NOTA: Pode-se usar até no máximo 20 IF-THEN-ELSE aninhados.

...

A instrução LET atribui um valor a uma variável.

 

 

 

 LET LET pg1  = paid_date - ship_date
 LET 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 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 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 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);

...

Esta instrução salta um número de linhas em branco especificadas após o SKIP. 

 

 

 SKIP 2 LINESLINES 

 

 

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.

...

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 WHILE PAGENO = 1
    LET a = a * a + 2
    LET b = a * 2
 END WHILEEND 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.

...

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;

...

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 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 BEFORE GROUP OF cust
    SKIP 1 LINE
    NEED 2 LINES

 

    PRINT COLUMN 01, "CLIENTE:",
          COLUMN 10, cust USING "<<<<",
          COLUMN 16, company CLIPPED CLIPPED 

 Exemplo da instrução CLIPPED

COLUMN

Esta instrução permite imprimir o campo que se segue a partir da coluna especificada.

 

 

 

 BEFORE BEFORE GROUP OF cust
    SKIP 1 LINE
    NEED 2 LINES
    PRINT COLUMN 01, "CLIENTE:",
          COLUMN 10, cust USING "<<<<",
          COLUMN 16, company CLIPPED 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 IF LINENO = 24 THEN
    SKIP TO TOP OF PAGE

 END IF

 

 

END IF 

Exemplo da instrução LINENO

NOTA: Não utilize LINENO em blocos PAGE HEADER ou TRAILER porque não funcionará corretamente.

...

Esta expressão contém o número da página que o REPORT está imprimindo no momento.

 

 

 

 PAGE 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.

...

Esta expressão permite definir o formato de impressão dos campos do tipo numérico e data, a que está associada.

 

 

 

 PRINT PRINT "RESUMO DAS ENCOMENDAS POR CLIENTE DE ", inic, " A ", fim,
       COLUMN 70, "Pagina ", PAGENO USING "<<<"
 PRINT PRINT COLUMN 10, "Encomenda:",
       COLUMN 21, ord USING "<<<<",
       COLUMN 29, "Total:",
       COLUMN 36, tot1 USING "$$$$$####&.&&",
       COLUMN 53, "Pagamento em:",
       COLUMN 67, pg1, pgc1 CLIPPED

 

 

CLIPPED 

Exemplos da instrução USING

NOTAS:

-          O conjunto de caracteres que definem o formato precisa estar entre " " (aspas);

...

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

...

-          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

...

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      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:

...

                           Estrutura  Estrutura da tabela requisições

A tabela entidades tem os dados gerais de cada entidade. A sua estrutura é a seguinte:

...