Árvore de páginas

Você está vendo a versão antiga da página. Ver a versão atual.

Comparar com o atual Ver Histórico da Página

Versão 1 Próxima »

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
   ...instruções...
 END MAIN 

Exemplo de programa

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

 

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]
OU
l_texto[2,5] 


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

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

   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.

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

Da outra forma, a instrução GLOBALS é constituída por uma instrução DEFINE.

 

 

 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.

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

   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.

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

 

 

Definição genérica da atribuição

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

 

 MAIN

   DEFINE x INTEGER,

          y CHAR(20),

          z DECIMAL(5,2),

          lr_livros RECORD LIKE livros.*,

          lr_livros2 RECORD LIKE livros.*

 

   LET x = 69

   LET y = "Uma string"

   LET z = 120.596

 

   DISPLAY "X tem ", x,", Y tem ", y,"e Z = ",z

 

   SELECT *

     INTO lr_livros.*

     FROM livros

    WHERE numero = x

 

   LET lr_livros2.* = lr_livros.*

   DISPLAY lr_livros2.numero, lr_livros.nome

 END MAIN

 

 RESULTADO:

 X tem 69, Y tem Uma string e Z = 120.60

 69 nome do livro 69

 

 

Inicializações de variáveis

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)

 

   LET y = "Uma string"

 

   IF y > "UMA STRING" THEN

      DISPLAY "Uma string maior que UMA STRING"

   END IF

 

   IF y < "uma string" THEN

      DISPLAY "Uma string menor que UMA STRING"

   END IF

 

   IF y = "Uma string" THEN

      DISPLAY "Uma string igual a UMA STRING"

   END IF

 END MAIN

 

 RESULTADO:

 Uma string maior que UMA STRING

 Uma string menor que UMA STRING

 Uma string igual a UMA STRING

 

 

Vários exemplos de comparações

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

 

 

Definição genérica da instrução INITIALIZE

A instrução INITIALIZE inicializa as variáveis com valor NULL.

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

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

   DEFINE x CHAR(20),

          y CHAR(50)

 

   LET x = "String 1 "

   LET y = "Concatenou ",x CLIPPED," com outras duas strings"

 

   DISPLAY y

 END MAIN

 

 RESULTADO

 Concatenou String 1 com outras duas strings

 

 

Exemplo de concatenação de strings

  • Sem rótulos