O RPG é um dos pilares da plataforma AS/400. Foi originalmente desenhado como uma ferramenta de consulta foi entretanto expandido e é neste momento uma linguagem de progamação bastante poderosa. Vamos neste capítulo ver como utilizar o RPG.
RPG é uma linguagem vocacionada para aplicações de negócios. Originalmente a sigla significava Report Program Generator, mas actualmente a sigla já não tem oficialmente nenhum significado. A última versão é o RPG IV, que é a versão que vamos utilizar para seguir este tutorial.
O RPG, tal como o DDS, é uma linguagem posicional, apesar de na sua versão 4 existir lugar para um formato livre que dentro de algumas restrições permite a colocação do código em qualquer coluna/linha.
Dentro do código RPG existem vários tipos de expecificações possíveis. Todas seguem uma ordem pela qual devem aparecer no ficheiro e todas têm funções diferentes. Cada letra da expecificação representa a letra que deve ser colocada na posição inicial de cada linha. Segue-se a listagem das especificações segundo a ordem pela qual devem aparecer no ficheiro.
Especificação H (header)
Opções relativas à geração do programa ou à sua execução.
Especificação F (file)
Definição dos ficheiros usados e de como são usados no programa. Opções possiveis na especificação F (para ver ao pormenor o que cada um dos campos representa coloque o cursor no campo e carregue em F1):
Especificação D (definition)
Define os dados utilizados, por exemplo variáveis.
Especificação C
Nesta especificação define-se o código que o programa vai executar. Apenas existe um formato livre para esta especificação (o código pode estar em qualquer posição), mas para isso deve-se delimitar o código livre com free end-free uma posição a seguir ao início da linha. No formato livre não se usa o 'C' no início da linha.
Sintaxe Básica RPG
Operadores válidos
= (comparação e atribuição), +, -, *, /, >, >=, <, <=, <>, NOT, AND, OR.
Expressões Condicionais
if condição;
//código
else;
if outra-condição;
...
endif;
endif;
Ciclo do-while
doW condição;
// código
endDo;
Criação e definição do ficheiro RPG
Vamos criar agora um programa que vai mostrar no ecrã o número de cartões que tem o cliente com ID = 1.
Deve inserir alguns registos na tabela CARDS associados ao cliente 1. Faça-o a partir do STRSQL.
Crie ficheiro de sources DEMO/QplainSRC. Dentro deste ficheio de sources crie um ficheiro com o nome COUNTCARDS do tipo SQLplain.
Como não vamos precisar de abrir explicitamente nenhuma tabela, não vamos ter nenhuma linha da especificação F.
Vamos ter que definir uma variável com o nome count, que vai guardar o número de cartões do cliente. Coloque a letra 'd' na primeira coluna do SEU e carregue F4 para ver os pormenores. Esta vai ser uma variável simples (no campo Declaration Type deve estar 's') do tipo numérico com 5 dígitos de comprimento e zero casas decimais. Inicie a variável a 0 com a ajuda da função INZ(valor-inicial) no campo Keywords. Conseguiu criar a variável com a ajuda do prompt? Se não, pode ver o resultado final mais à frente.
Tente criar os seguintes pontos com atenção a que em formato livre pode identar o código da maneira que preferir e tem que colocar sempre um ponto e vírgula no final de todas as linhas (entre o /free /end-free) e cada linha dentro do formato livre deve começar pelo menos na posição 3 do SEU (na coluna seguinte á barra do /free).
- Inicie (/free) e finalize (/end-free) o bloco de código em linhas separadas, começando na 2º coluna do SEU.
- Mostre o conteúdo da variável count. Para mostrar valores no ecrã usa-se a função dsply, cuja sintaxe é: dsply valor.
- Na última linha, antes do /end-free, deve activar o indicador de fim de código *inlr (in last row) como activo: *inlr = *on; .
Deve ficar com algo deste género.
* definição da variável
Dcount s 5P 0 INZ(0)
/free
dsply count; * //mostra no ecrã o valor contido na variável
*inlr = *on; * //indica ao compilador que se encontra na última linha
/end-free
Se compilar agora este codigo (opção 14 do PDM) e a compilação for bem sucedida chame o programa a partir do prompt:
call DEMO/COUNTCARDS
Deve surgir a seguinte informação:
dsply 0
Podem aparecer vários valores (de eventos anteriores), mas o que lhe interessa é sempre o que está na linha mais em baixo.
Ainda nos falta contar o número de cartões que o cliente tem.
SQL Embutido e Subrotinas
Para fazer consultas e alterações a tabelas vamos usar código SQL, pois já deve saber usá-lo, mas note que é possivel fazer consultas a tabelas usando código especifico do RPG.
Para imbutir SQL no código RPGILE temos que o colocar no formato:
c/EXEC SQL
c+ instrução-SQL
c/END-EXEC
Repare que eu escrevi instrução e não instruções. Isso é porque em cada EXEC só pode existir uma função SQL, mas vamos ver um exemplo melhor mais à frente.
Sendo assim teríamos (escreva o codigo seguinte no final do ficheiro, depois do /end-free):
c/EXEC SQL
c+ SELECT COUNT(*) INTO :count FROM DEMO/CARDS
c+ WHERE CLIENT_CRD = 1
c/END-EXEC
Para poder organizar melhor o código vamos colocar esta instrução SQL dentro de uma subrotina. Uma subrotina é uma espécie de função que não recebe parâmetros, nem devolve nenhum valor, mas pode alterar valores definidos a nível global do programa. Dentro da subrotina pode ter código em formato livre, formato fixo e instruções EXEC.
Fora do bloco /free vou definir a subrotina getNrCards e colocar la dentro o código do EXEC SQL. Pode usar a ajuda do prompt (F4) para situar correctamente as palavras.
Sendo assim teríamos:
c getNrCards begsr
c/EXEC SQL
c+ SELECT COUNT(*) INTO :count FROM DEMO/CARDS
c+ WHERE CLIENT_CRD = 1
c endsr
Para agora conseguir executar este bloco de código preciso invocar a subrotina dentro do bloco /free principal:
exSr getNrCards; //execute sub-routine getNrCards
Não se esqueça que isto tem de estar antes de fazer o display da variável.
Tente agora compilar e correr novamente. Obteve o mesmo resultado? Se sim, certifique-se que o cliente 1 existe e que este tem registos associados na tabela CARDS (e que todo o tutorial até aqui está correctamente concluído!). Se mesmo assim não resultar verifique se o seu codigo está completamente correcto:
Dcount s 5P 0 INZ(0)
*------------------------------------------------*
/free
exSr getNrCards;
dsply count;
*inlr = *on;
/end-free
*------------------------------------------------*
c getNrCards begsr
c/EXEC SQL
c+ SELECT COUNT(*) INTO :count FROM DEMO/CARDS
c+ WHERE CLIENT_CRD = 1
c/END-EXEC
c endsr