| Bellacosa Mainframe e o db2i run sem misterios |
☕ Um Café no Bellacosa Mainframe
DB2I RUN sem Mistérios
O Guia do Programador COBOL Padawan para Executar um Programa Db2, Entender PLAN, PACKAGE, LOAD MODULE e o JCL que Trabalha nos Bastidores
Imagine a cena.
Você está diante de um terminal 3270. O fundo é negro, os caracteres brilham em ciano e, no alto da tela, aparece uma palavra aparentemente inocente:
RUN
Logo ao lado, outra informação chama a atenção:
SSID: DB9G
No centro da tela existem apenas cinco campos:
1 DATA SET NAME
2 PASSWORD
3 PARAMETERS
4 PLAN NAME
5 WHERE TO RUN
Para um programador COBOL padawan, isso pode parecer apenas um formulário antigo para executar um programa. Mas essa tela é muito mais profunda do que aparenta.
Ela é a porta final de uma cadeia que envolve:
COBOL;
SQL;
Db2 Precompiler;
DBRM;
compilação;
binder;
load module;
package;
collection;
plan;
TSO;
ISPF;
DSN Command Processor;
JES;
JCL;
Language Environment;
subsistema Db2.
Ao pressionar Enter, você não está simplesmente “rodando um programa”.
Você está convocando várias camadas do z/OS para localizar um executável, conectar-se a um subsistema Db2, encontrar um plano, carregar packages, validar autorizações, criar uma thread e finalmente executar as instruções SQL.
Prepare a caneca, jovem padawan, porque hoje vamos abrir o capô dessa tela clássica e descobrir o que realmente acontece nos bastidores.
| Be |
1. O que é o painel RUN do DB2I?
O painel mostrado pertence ao DB2I, sigla para:
Db2 Interactive
O DB2I é uma interface baseada em painéis ISPF que facilita diversas tarefas relacionadas ao Db2 for z/OS.
Entre suas funções tradicionais estão:
executar comandos SQL;
utilizar o SPUFI;
gerar DCLGEN;
realizar precompile;
compilar programas;
executar BIND;
executar programas;
acessar utilitários;
gerar JCL.
O painel RUN é usado para iniciar um programa aplicativo que utiliza Db2.
Esse programa pode ter sido escrito em:
COBOL;
PL/I;
Assembler;
C;
C++;
outra linguagem suportada pelo ambiente.
No universo Bellacosa Mainframe, o cenário mais comum é um programa COBOL contendo SQL estático:
EXEC SQL
SELECT NOME_CLIENTE
INTO :WS-NOME-CLIENTE
FROM CLIENTES
WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC.
Esse SQL não é executado diretamente pelo compilador COBOL. Antes disso, o programa precisa atravessar várias etapas.
2. A jornada completa do programa COBOL/Db2
Antes de chegar ao painel RUN, normalmente o programa percorreu este caminho:
Fonte COBOL com EXEC SQL
|
v
Db2 Precompiler
|
+-------+--------+
| |
v v
Fonte COBOL DBRM
modificado gerado
| |
v |
Compilador COBOL |
| |
v |
Object Module |
| |
v v
Binder BIND PACKAGE
| |
v v
Load Module Package Db2
| |
+-------+--------+
|
v
Execução
O painel RUN aparece somente no final dessa viagem.
Ele não substitui as etapas anteriores.
Se o programa não foi corretamente preparado, o painel não fará milagres.
3. O que significa SSID?
No topo da tela aparece:
SSID: DB9G
SSID significa:
Subsystem Identifier
É o identificador do subsistema Db2 no qual o programa será executado.
Em um grande ambiente corporativo podem existir vários subsistemas:
DB2D
DB2T
DB2H
DB2P
DB9G
DB01
D91A
Uma empresa pode usar uma convenção como:
DB2D = Desenvolvimento
DB2T = Teste
DB2H = Homologação
DB2P = Produção
Mas isso não é obrigatório.
Cada instalação cria seus próprios padrões.
Por que isso é tão importante?
Porque o mesmo programa pode existir em vários ambientes.
Imagine:
Programa: CADCLI01
Plano: PLNCLI01
Tabela: CLIENTES
No desenvolvimento, a tabela pode conter 500 clientes fictícios.
Na produção, pode conter 20 milhões de registros reais.
Executar o programa no SSID errado pode provocar:
leitura de dados reais;
atualização indevida;
SQLCODE
-204;SQLCODE
-805;SQLCODE
-551;bloqueios;
commits inesperados;
incidentes operacionais.
Antes de pressionar Enter, sempre confirme:
Qual é o LPAR?
Qual é o SSID?
Qual é o ambiente?
Qual é o plano?
Qual é o qualifier das tabelas?
Uma simples letra no SSID pode separar um teste inocente de uma madrugada inteira em war room.
4. Campo 1 — DATA SET NAME
O primeiro campo é:
1 DATA SET NAME ===>
Esse campo informa onde se encontra o programa executável.
No z/OS, o executável normalmente está em uma biblioteca de carga:
VAGNER.COBOL.LOAD
O programa pode estar armazenado como membro:
VAGNER.COBOL.LOAD(CADCLI01)
Fonte não é executável
O fonte COBOL pode estar em:
VAGNER.COBOL.SOURCE(CADCLI01)
Mas o programa executável está em:
VAGNER.COBOL.LOAD(CADCLI01)
Esses objetos não são a mesma coisa.
O fonte é texto.
O load module é código de máquina preparado para execução.
Exemplo
Se o programa se chama:
CADCLI01
e foi linkeditado na biblioteca:
VAGNER.DB2.LOAD
o campo pode receber:
'VAGNER.DB2.LOAD(CADCLI01)'
Em algumas configurações, o painel pode pedir apenas a biblioteca ou ter outra convenção de preenchimento.
Por que as aspas são importantes?
No TSO, quando você informa:
VAGNER.DB2.LOAD
sem aspas, o sistema pode acrescentar automaticamente o seu prefixo de usuário.
Se seu user ID for:
VAGNER
o sistema pode interpretar:
VAGNER.VAGNER.DB2.LOAD
Com aspas:
'VAGNER.DB2.LOAD'
o nome é tratado como absoluto.
Erros comuns
Biblioteca inexistente
IKJ56228I DATA SET NOT IN CATALOG
Possíveis causas:
nome digitado incorretamente;
data set não catalogado;
aspas ausentes;
HLQ errado;
biblioteca excluída.
Membro inexistente
MEMBER CADCLI01 NOT FOUND
Possíveis causas:
o programa não foi linkeditado;
o link-edit falhou;
o membro foi criado com outro nome;
a biblioteca informada é a biblioteca de fontes;
o executável está em outro PDSE.
Versão antiga
Esse é um dos erros mais traiçoeiros.
Você altera o fonte:
VAGNER.COBOL.SOURCE(CADCLI01)
compila e acredita estar executando a nova versão.
Mas o painel aponta para:
VAGNER.OLD.LOAD(CADCLI01)
O programa roda normalmente, porém com comportamento antigo.
O programador então olha o fonte e pensa:
“Isso é impossível. Eu alterei essa linha.”
O mainframe responde silenciosamente:
“Você alterou o fonte certo, mas executou o load errado.”
5. Campo 2 — PASSWORD
O segundo campo é:
2 PASSWORD ===>
A própria tela explica:
Required if data set is password protected
Esse campo pertence a um tempo em que data sets podiam ser protegidos diretamente por senha.
Hoje, a segurança normalmente é controlada por:
RACF;
ACF2;
Top Secret;
SAF.
Na maioria dos ambientes modernos, esse campo permanece vazio.
Atenção
Essa senha não é necessariamente:
senha do TSO;
senha do RACF;
senha do Db2;
senha do usuário SQL;
senha de aplicativo.
Ela seria a senha associada diretamente ao data set.
É uma relíquia histórica, quase um fóssil vivo dentro do painel.
Easter egg histórico
O fato de o campo ainda existir mostra como o z/OS preserva compatibilidade.
Em outros ambientes, uma interface antiga seria simplesmente removida.
No mainframe, ela pode permanecer por décadas porque ainda existe a possibilidade de algum processo legado depender dela.
No reino IBM Z, compatibilidade não é nostalgia.
É estratégia operacional.
6. Campo 3 — PARAMETERS
O terceiro campo é:
3 PARAMETERS ===>
Aqui são informados parâmetros enviados ao programa.
Exemplo:
CONSULTA,000123
O programa pode interpretar isso como:
Operação = CONSULTA
Cliente = 000123
Mas o COBOL não entende automaticamente vírgulas, palavras ou intenções.
Ele recebe bytes.
A aplicação precisa possuir uma lógica específica para interpretar o parâmetro.
7. Como o COBOL recebe parâmetros?
Existem diferentes formas, dependendo do ambiente e da implementação.
Uma forma conceitual seria usar ACCEPT FROM PARM:
IDENTIFICATION DIVISION.
PROGRAM-ID. CADCLI01.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-PARAMETRO PIC X(100).
01 WS-OPERACAO PIC X(10).
01 WS-COD-CLIENTE PIC X(06).
PROCEDURE DIVISION.
ACCEPT WS-PARAMETRO FROM PARM
DISPLAY 'PARAMETRO RECEBIDO: ' WS-PARAMETRO
UNSTRING WS-PARAMETRO
DELIMITED BY ','
INTO WS-OPERACAO
WS-COD-CLIENTE
END-UNSTRING
DISPLAY 'OPERACAO: ' WS-OPERACAO
DISPLAY 'CLIENTE : ' WS-COD-CLIENTE
GOBACK.
Explicando o exemplo
ACCEPT WS-PARAMETRO FROM PARM
Recebe o conteúdo passado durante a execução.
UNSTRING
Divide o conteúdo utilizando a vírgula como delimitador.
Entrada:
CONSULTA,000123
Resultado:
WS-OPERACAO = CONSULTA
WS-COD-CLIENTE = 000123
Cuidado com espaços
Estes parâmetros podem parecer iguais:
CONSULTA,000123
CONSULTA, 000123
CONSULTA ,000123
Mas não são necessariamente iguais.
O segundo pode gerar:
WS-COD-CLIENTE = ' 00012'
dependendo do tamanho do campo.
O terceiro pode gerar:
WS-OPERACAO = 'CONSULTA '
Por isso, programas robustos normalmente usam:
FUNCTION TRIM;validação;
teste de tamanho;
verificação de conteúdo numérico;
mensagens claras de erro.
8. Parâmetro em JCL
Em JCL, um parâmetro pode aparecer assim:
//STEP01 EXEC PGM=CADCLI01,PARM='CONSULTA,000123'
Quando a execução ocorre através do processador DSN, pode surgir como:
RUN PROGRAM(CADCLI01) PLAN(PLNCLI01)
PARMS('CONSULTA,000123')
A palavra usada pode variar conforme a interface e o comando específico, mas o conceito é o mesmo: entregar uma cadeia de caracteres ao programa.
9. Campo 4 — PLAN NAME
O quarto campo é:
4 PLAN NAME ===>
A tela informa:
Required if different from program name
Esse campo é um dos mais importantes e também um dos mais confundidos por iniciantes.
Programa e plano não são a mesma coisa
Considere:
Programa: CADCLI01
Plano: PLNCLI01
O programa é o executável COBOL.
O plano é um objeto do Db2 usado durante a execução.
O programa pode ter o mesmo nome do plano, mas continuam sendo objetos completamente diferentes.
10. DBRM, PACKAGE, COLLECTION e PLAN
Para entender o plano, precisamos conhecer quatro conceitos.
DBRM
DBRM significa:
Database Request Module
Ele é gerado pelo Db2 Precompiler.
Contém informações sobre o SQL extraído do programa.
Exemplo:
CADCLI01
O DBRM pode ser armazenado em:
VAGNER.DBRMLIB(CADCLI01)
PACKAGE
O package é criado pelo comando:
BIND PACKAGE
Exemplo:
BIND PACKAGE(COLCLI)
MEMBER(CADCLI01)
ACTION(REPLACE)
ISOLATION(CS)
VALIDATE(BIND)
RELEASE(COMMIT)
Esse comando pega o DBRM e cria um package dentro da collection COLCLI.
O package pode ser identificado como:
COLCLI.CADCLI01
COLLECTION
A collection é um agrupador lógico de packages.
Exemplos:
COLDEV
COLTST
COLPRD
COLCLI
COLFIN
A mesma aplicação pode ter packages em collections diferentes:
COLDEV.CADCLI01
COLTST.CADCLI01
COLPRD.CADCLI01
PLAN
O plan é criado pelo comando:
BIND PLAN
Exemplo:
BIND PLAN(PLNCLI01)
PKLIST(COLCLI.*)
ACTION(REPLACE)
ISOLATION(CS)
VALIDATE(BIND)
O plan aponta para os packages que poderão ser utilizados.
A relação fica assim:
Programa CADCLI01
|
v
Plan PLNCLI01
|
v
Collection COLCLI
|
v
Package CADCLI01
|
v
SQL preparado
11. Exemplo detalhado de BIND PACKAGE
BIND PACKAGE(COLCLI)
MEMBER(CADCLI01)
ACTION(REPLACE)
ISOLATION(CS)
VALIDATE(BIND)
RELEASE(COMMIT)
EXPLAIN(YES)
PACKAGE(COLCLI)
Define a collection onde o package será criado.
MEMBER(CADCLI01)
Informa o membro do DBRM.
ACTION(REPLACE)
Se o package já existir, será substituído.
Outras possibilidades incluem:
ACTION(ADD)
ISOLATION(CS)
Define o nível de isolamento Cursor Stability.
Isso influencia locking e concorrência.
VALIDATE(BIND)
Solicita validação dos objetos no momento do bind.
Alternativamente:
VALIDATE(RUN)
algumas verificações podem ser adiadas até a execução.
RELEASE(COMMIT)
Libera determinados recursos no commit.
EXPLAIN(YES)
Grava informações do access path nas tabelas de EXPLAIN, quando configuradas.
12. Exemplo detalhado de BIND PLAN
BIND PLAN(PLNCLI01)
PKLIST(COLCLI.*)
ACTION(REPLACE)
ISOLATION(CS)
VALIDATE(BIND)
RETAIN
PLAN(PLNCLI01)
Nome do plano.
PKLIST(COLCLI.*)
Permite que o plano utilize os packages da collection COLCLI.
O asterisco significa múltiplos packages.
ACTION(REPLACE)
Substitui o plano existente.
RETAIN
Pode preservar determinadas autorizações anteriores, conforme as regras do ambiente e da operação realizada.
13. Erro clássico: SQLCODE -805
Quando o Db2 não encontra o package necessário, pode ocorrer:
SQLCODE = -805
A mensagem normalmente menciona:
collection;
package;
consistency token;
plan.
Possíveis causas:
package não foi criado;
package foi criado em outra collection;
plan aponta para collection errada;
programa foi recompilado;
bind não foi refeito;
package está em outro subsistema;
versão incorreta.
Exemplo
Programa:
CADCLI01
Plan:
PLNCLI01
Package existente:
COLDEV.CADCLI01
Mas o plan aponta para:
COLTST.*
Resultado:
-805
Checklist para resolver
Verifique:
1. Qual programa foi executado?
2. Qual plan foi informado?
3. Qual collection está no PKLIST?
4. O package existe?
5. O consistency token corresponde?
6. O bind ocorreu no mesmo SSID?
14. Erro clássico: SQLCODE -818
O SQLCODE -818 indica incompatibilidade entre o executável e o DBRM/package.
Em termos simples:
Load Module versão A
Package versão B
O programa e o package não pertencem à mesma geração.
Isso pode acontecer quando alguém executa:
Precompile
Compile
Link-edit
mas esquece:
BIND PACKAGE
Ou faz o contrário:
BIND PACKAGE
usando um DBRM antigo, mas executa um load novo.
A solução correta
Refaça a cadeia de forma consistente:
1. Precompile
2. Compile
3. Link-edit
4. Bind Package
5. Bind ou Rebind Plan, se necessário
6. Execute novamente
Easter egg do consistency token
Durante o precompile, o Db2 gera um identificador usado para garantir que:
executável e SQL preparado pertencem à mesma família
É quase como um selo de autenticidade.
O -818 é o Db2 dizendo:
“Esses dois artefatos afirmam ser parentes, mas o DNA não confere.”
15. Campo 5 — WHERE TO RUN
O quinto campo é:
5 WHERE TO RUN ===> FOREGROUND
As opções indicadas são:
FOREGROUND
BACKGROUND
EDITJCL
Cada uma representa um modo diferente de execução.
16. FOREGROUND
Em foreground, o programa executa dentro da sessão TSO atual.
WHERE TO RUN ===> FOREGROUND
Vantagens
execução imediata;
ideal para pequenos testes;
mensagens aparecem rapidamente;
não exige consultar o spool;
ótimo para laboratórios.
Desvantagens
ocupa a sessão;
um loop pode travar o terminal;
saída extensa pode ser difícil de acompanhar;
não é adequado para grandes processamentos;
pode ser difícil analisar dumps.
Use foreground para
um
SELECTsimples;testar conexão;
validar plan/package;
executar um programa pequeno;
verificar SQLCODE;
testar parâmetros.
Evite foreground para
milhões de registros;
relatórios longos;
programas com muitos DDs;
atualizações massivas;
programas sujeitos a abend;
processos demorados.
17. BACKGROUND
Em background, o DB2I gera e submete um job.
WHERE TO RUN ===> BACKGROUND
O fluxo passa a ser:
DB2I
|
v
JCL gerado
|
v
SUBMIT
|
v
JES2
|
v
Initiator
|
v
Programa COBOL/Db2
|
v
Spool
Vantagens
libera a sessão TSO;
saída fica no spool;
facilita análise;
suporta DD statements;
ideal para processos longos;
permite guardar dumps e logs.
Depois da submissão, o usuário pode consultar o SDSF.
Exemplo:
SDSF
ST
E localizar o job pelo nome ou owner.
18. EDITJCL
A opção EDITJCL é uma das mais educativas.
WHERE TO RUN ===> EDITJCL
O DB2I gera o JCL, mas permite que o programador o revise antes da submissão.
Isso é excelente para compreender o que o painel esconde.
É como escolher:
FOREGROUND = ligue o motor agora
BACKGROUND = ligue o motor e siga a rota
EDITJCL = abra o capô antes de sair
19. Primeiro exemplo de JCL — Execução simples com IKJEFT01
//VAGRUN01 JOB (DB2),'RUN COBOL DB2',
// CLASS=A,
// MSGCLASS=X,
// MSGLEVEL=(1,1),
// NOTIFY=&SYSUID
//*------------------------------------------------------*
//* EXECUCAO DO PROGRAMA CADCLI01 NO DB2 DB9G
//*------------------------------------------------------*
//RUNDB2 EXEC PGM=IKJEFT01,DYNAMNBR=20
//STEPLIB DD DISP=SHR,DSN=VAGNER.DB2.LOAD
// DD DISP=SHR,DSN=DB9G.SDSNLOAD
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(CADCLI01) PLAN(PLNCLI01)
END
/*
Agora vamos analisar linha por linha.
20. JOB statement
//VAGRUN01 JOB (DB2),'RUN COBOL DB2',
VAGRUN01
É o nome do job.
Dependendo da instalação, o nome pode precisar começar com o user ID.
(DB2)
É a informação contábil.
Pode representar:
centro de custo;
projeto;
departamento;
conta de cobrança.
'RUN COBOL DB2'
É a descrição do job.
21. CLASS
// CLASS=A,
Define a classe de execução.
A classe influencia:
prioridade;
initiator;
regras locais;
recursos;
janela operacional.
O significado de CLASS=A varia entre empresas.
Em um ambiente, pode ser teste rápido.
Em outro, pode ser processamento normal.
Nunca assuma que a classe tem o mesmo significado em todos os z/OS.
22. MSGCLASS
// MSGCLASS=X,
Define a classe de saída no spool.
Ela controla onde e como as mensagens do job serão armazenadas ou tratadas.
23. MSGLEVEL
// MSGLEVEL=(1,1),
Controla quais instruções JCL e mensagens serão impressas no spool.
O primeiro valor está relacionado às instruções JCL.
O segundo, às mensagens de alocação e término.
Para diagnóstico, (1,1) costuma ser bastante útil.
24. NOTIFY
// NOTIFY=&SYSUID
Solicita notificação ao usuário que submeteu o job.
&SYSUID é substituído pelo user ID.
Quando o job termina, pode surgir uma mensagem como:
VAGRUN01 ENDED - RC=0000
25. EXEC PGM=IKJEFT01
//RUNDB2 EXEC PGM=IKJEFT01,DYNAMNBR=20
IKJEFT01 permite executar comandos TSO em batch.
É frequentemente utilizado para chamar o processador DSN.
DYNAMNBR=20
Define a quantidade de alocações dinâmicas disponíveis.
Alguns processos TSO/Db2 podem precisar alocar data sets dinamicamente.
Valores exatos seguem os padrões do ambiente.
26. STEPLIB
//STEPLIB DD DISP=SHR,DSN=VAGNER.DB2.LOAD
// DD DISP=SHR,DSN=DB9G.SDSNLOAD
A STEPLIB indica onde o sistema deve procurar programas e módulos.
Primeira biblioteca
VAGNER.DB2.LOAD
Contém o programa da aplicação:
CADCLI01
Segunda biblioteca
DB9G.SDSNLOAD
Pode conter módulos de carga do Db2.
O nome real varia conforme a instalação.
Ordem importa
O z/OS procura os módulos na ordem das bibliotecas.
Se o mesmo programa existir em duas bibliotecas, a primeira ocorrência pode ser utilizada.
Isso pode causar o fantasma da versão antiga.
27. SYSTSPRT
//SYSTSPRT DD SYSOUT=*
Recebe mensagens produzidas pelo ambiente TSO e pelo processador de comandos.
Pode conter informações importantes sobre:
início do DSN;
conexão com subsistema;
execução;
mensagens de erro;
término.
28. SYSPRINT
//SYSPRINT DD SYSOUT=*
É uma saída comum para mensagens impressas por programas e utilitários.
Nem todo programa usa SYSPRINT, mas ela costuma ser incluída por convenção.
29. SYSOUT
//SYSOUT DD SYSOUT=*
Pode receber mensagens produzidas pela aplicação.
Se o COBOL possuir:
DISPLAY 'INICIO DO PROGRAMA'
a saída pode aparecer em SYSOUT, conforme a configuração de runtime.
30. SYSUDUMP
//SYSUDUMP DD SYSOUT=*
Solicita dump em caso de abend.
É útil para investigar erros como:
S0C4
S0C7
S0CB
S806
O dump pode mostrar:
PSW;
registradores;
área de memória;
offset;
módulo;
traceback.
31. SYSTSIN
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(CADCLI01) PLAN(PLNCLI01)
END
/*
Essa DD contém os comandos enviados ao IKJEFT01.
DSN SYSTEM(DB9G)
Inicia o processador DSN e conecta ao subsistema DB9G.
RUN PROGRAM(CADCLI01)
Solicita a execução do programa.
PLAN(PLNCLI01)
Indica o plano Db2.
END
Encerra o processador DSN.
32. Segundo exemplo de JCL — Programa com parâmetros
//VAGRUN02 JOB (DB2),'RUN COM PARAMETRO',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//RUNDB2 EXEC PGM=IKJEFT01,DYNAMNBR=30
//STEPLIB DD DISP=SHR,DSN=VAGNER.DB2.LOAD
// DD DISP=SHR,DSN=DB9G.SDSNLOAD
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//CEEOUT DD SYSOUT=*
//CEEDUMP DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(CADCLI01) -
PLAN(PLNCLI01) -
PARMS('CONSULTA,000123')
END
/*
Continuação com hífen
O hífen indica continuação lógica do comando DSN.
RUN PROGRAM(CADCLI01) -
PLAN(PLNCLI01) -
PARMS('CONSULTA,000123')
Isso melhora a leitura.
Cuidado com aspas
O parâmetro está entre aspas:
'CONSULTA,000123'
Aspas mal posicionadas podem provocar erro de sintaxe ou alterar o conteúdo entregue.
33. Terceiro exemplo de JCL — Programa com arquivo de entrada e saída
//VAGRUN03 JOB (DB2),'PROCESSA CLIENTES',
// CLASS=A,
// MSGCLASS=X,
// MSGLEVEL=(1,1),
// NOTIFY=&SYSUID
//*------------------------------------------------------*
//* PROGRAMA COBOL DB2 COM ARQUIVO DE ENTRADA E SAIDA
//*------------------------------------------------------*
//RUNDB2 EXEC PGM=IKJEFT01,DYNAMNBR=50,REGION=0M
//STEPLIB DD DISP=SHR,DSN=VAGNER.DB2.LOAD
// DD DISP=SHR,DSN=DB9G.SDSNLOAD
//*
//ENTRADA DD DISP=SHR,
// DSN=VAGNER.CLIENTES.ENTRADA
//*
//SAIDA DD DISP=(NEW,CATLG,DELETE),
// DSN=VAGNER.CLIENTES.SAIDA,
// SPACE=(CYL,(1,1),RLSE),
// DCB=(RECFM=FB,LRECL=200,BLKSIZE=0)
//*
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//CEEOUT DD SYSOUT=*
//CEEDUMP DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD *
DSN SYSTEM(DB9G)
RUN PROGRAM(PROCCLI1) -
PLAN(PLNPROC1) -
PARMS('PROCESSAR')
END
/*
34. DD ENTRADA
//ENTRADA DD DISP=SHR,
// DSN=VAGNER.CLIENTES.ENTRADA
O nome ENTRADA deve corresponder ao nome usado no COBOL:
SELECT ARQ-ENTRADA
ASSIGN TO ENTRADA.
DISP=SHR
O data set já existe e será compartilhado para leitura.
DSN
É o nome do arquivo.
35. DD SAIDA
//SAIDA DD DISP=(NEW,CATLG,DELETE),
NEW
O arquivo será criado.
CATLG
Se o step terminar normalmente, o data set será catalogado.
DELETE
Se o step falhar, o data set será excluído.
Esse trio é um clássico:
DISP=(NEW,CATLG,DELETE)
36. SPACE
// SPACE=(CYL,(1,1),RLSE),
CYL
A unidade de alocação será cilindro.
(1,1)
1 cilindro primário;
1 cilindro secundário.
RLSE
Libera espaço não utilizado ao final.
37. DCB
// DCB=(RECFM=FB,LRECL=200,BLKSIZE=0)
RECFM=FB
Registros de tamanho fixo e blocados.
LRECL=200
Cada registro possui 200 bytes.
BLKSIZE=0
Solicita ao sistema um tamanho de bloco adequado.
38. REGION=0M
//RUNDB2 EXEC PGM=IKJEFT01,DYNAMNBR=50,REGION=0M
REGION=0M solicita o máximo de memória permitido pelas regras do sistema.
Não significa memória infinita.
O z/OS ainda aplica:
limites da instalação;
políticas;
WLM;
storage disponível;
regras do job class.
39. Language Environment: CEEOUT e CEEDUMP
//CEEOUT DD SYSOUT=*
//CEEDUMP DD SYSOUT=*
O Language Environment fornece serviços comuns para linguagens como COBOL, PL/I e C.
CEEOUT
Recebe saídas relacionadas ao Language Environment.
CEEDUMP
Recebe dump formatado pelo Language Environment.
Em muitos casos, o CEEDUMP é mais fácil de analisar do que um dump bruto.
40. Um programa COBOL/Db2 de exemplo
IDENTIFICATION DIVISION.
PROGRAM-ID. CADCLI01.
DATA DIVISION.
WORKING-STORAGE SECTION.
EXEC SQL
INCLUDE SQLCA
END-EXEC.
01 WS-PARAMETRO.
05 WS-OPERACAO PIC X(10).
05 WS-COD-CLIENTE PIC 9(06).
01 WS-NOME-CLIENTE PIC X(40).
01 WS-STATUS-CLIENTE PIC X.
PROCEDURE DIVISION.
0000-PRINCIPAL.
DISPLAY '*** INICIO CADCLI01 ***'
ACCEPT WS-PARAMETRO FROM PARM
DISPLAY 'OPERACAO: ' WS-OPERACAO
DISPLAY 'CLIENTE : ' WS-COD-CLIENTE
EXEC SQL
SELECT NOME_CLIENTE,
STATUS_CLIENTE
INTO :WS-NOME-CLIENTE,
:WS-STATUS-CLIENTE
FROM CLIENTES
WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC
EVALUATE SQLCODE
WHEN 0
DISPLAY 'CLIENTE ENCONTRADO'
DISPLAY 'NOME : ' WS-NOME-CLIENTE
DISPLAY 'STATUS: ' WS-STATUS-CLIENTE
WHEN 100
DISPLAY 'CLIENTE NAO ENCONTRADO'
WHEN OTHER
DISPLAY 'ERRO SQL'
DISPLAY 'SQLCODE : ' SQLCODE
DISPLAY 'SQLSTATE: ' SQLSTATE
DISPLAY 'SQLERRMC: ' SQLERRMC
END-EVALUATE
EXEC SQL
COMMIT
END-EXEC
DISPLAY '*** FIM CADCLI01 ***'
GOBACK.
41. SQLCA
A instrução:
EXEC SQL
INCLUDE SQLCA
END-EXEC.
inclui a SQL Communication Area.
Ela contém informações sobre o último comando SQL executado.
Campos importantes:
SQLCODE
SQLSTATE
SQLERRMC
SQLERRD
SQLWARN
SQLCODE
Código de retorno tradicional.
Exemplos:
0 Sucesso
+100 Não encontrado
-204 Objeto não definido
-305 Indicador necessário
-551 Sem autorização
-805 Package não encontrado
-811 Mais de uma linha retornada
-818 Timestamp inconsistente
-911 Rollback por deadlock ou timeout
-913 Execução sem rollback completo
42. SQLCODE +100
O +100 não significa abend.
Significa, geralmente:
não foi encontrada nenhuma linha
No exemplo:
SELECT NOME_CLIENTE
FROM CLIENTES
WHERE COD_CLIENTE = 123456
Se o cliente não existir:
SQLCODE = +100
O programa deve tratar isso como condição de negócio.
43. SQLCODE -204
OBJECT NOT DEFINED
Pode ocorrer quando:
tabela não existe;
qualifier está errado;
subsistema é incorreto;
tabela existe em outro schema;
alias não está disponível.
Exemplo:
SELECT *
FROM CLIENTES;
O Db2 pode procurar:
VAGNER.CLIENTES
quando a tabela real é:
APPDB.CLIENTES
Uma solução seria qualificar:
SELECT *
FROM APPDB.CLIENTES;
44. SQLCODE -551
Indica falta de autorização.
Exemplo:
AUTHORIZATION ID VAGNER DOES NOT HAVE SELECT PRIVILEGE
Verifique:
grant direto;
role;
grupo RACF;
secondary auth ID;
autorização do package;
autorização do plan.
O Db2 pode executar com diferentes contextos de autorização, dependendo do bind e do ambiente.
45. S806 — módulo não encontrado
Se o sistema não localizar o executável, pode ocorrer:
ABEND S806
Verifique:
STEPLIB;
JOBLIB;
nome do programa;
biblioteca de load;
link-edit;
membro;
APF, quando aplicável;
ordem das bibliotecas.
Exemplo:
RUN PROGRAM(CADCLI01)
mas o membro se chama:
CADCLIO1
Note a diferença entre zero e letra O.
Esse erro é tão clássico quanto café frio ao lado do terminal.
46. S0C7 — dado numérico inválido
Um S0C7 ocorre quando o programa tenta usar como número algo que não é numérico.
Exemplo:
01 WS-VALOR PIC 9(05).
Mas o conteúdo é:
12A45
Uma operação matemática pode gerar:
S0C7
Parâmetros malformados podem causar esse problema.
Entrada:
CONSULTA,00A123
Se o programa mover diretamente para um campo numérico, o abend pode surgir.
47. S0C4 — endereço inválido
O S0C4 costuma estar relacionado a:
subscrito fora da tabela;
ponteiro inválido;
linkage incorreto;
área não inicializada;
comprimento errado;
acesso indevido à memória.
Pode acontecer se o programa espera um parâmetro de 100 bytes, mas recebe uma estrutura incompatível.
48. Commit e rollback
O painel RUN pode iniciar programas que atualizam dados reais.
Exemplo:
UPDATE CLIENTES
SET STATUS_CLIENTE = 'I'
WHERE ULTIMO_ACESSO < CURRENT DATE - 5 YEARS;
Se o programa executar:
EXEC SQL
COMMIT
END-EXEC.
as alterações serão confirmadas.
Antes de executar um programa de atualização, confirme:
1. Estou no ambiente correto?
2. O WHERE está correto?
3. O parâmetro está correto?
4. Existe backup?
5. Existe estratégia de rollback?
6. Qual será a frequência de commit?
7. O programa foi testado com poucos registros?
Rollback
Se ocorrer erro antes do commit:
EXEC SQL
ROLLBACK
END-EXEC.
pode desfazer as alterações da unidade de trabalho.
Mas atenção: a capacidade de rollback depende dos commits já realizados.
Depois de confirmado, um commit não é apagado por um rollback posterior.
49. Foreground não significa ausência de infraestrutura
Mesmo em foreground, o programa ainda utiliza:
thread Db2;
packages;
buffer pools;
logs;
locks;
WLM;
Language Environment;
storage;
catalog;
directories;
módulos de runtime;
autorização SAF.
A diferença está na forma de iniciar e acompanhar a execução.
Foreground = sessão TSO
Background = job JES
O Db2 continua sendo o mesmo motor.
50. IKJEFT01, IKJEFT1A e IKJEFT1B
Você pode encontrar JCLs usando:
IKJEFT01
IKJEFT1A
IKJEFT1B
Todos pertencem ao universo de execução TSO em batch.
As diferenças estão principalmente no comportamento de término e propagação de códigos de retorno.
Em ambientes corporativos, siga o padrão oficial.
Não substitua um pelo outro apenas porque “parece parecido”.
Um JCL homologado pode depender do comportamento específico de retorno.
51. Um roteiro seguro antes de pressionar Enter
Passo 1 — Confirme o SSID
SSID: DB9G
Saiba se ele representa:
desenvolvimento;
teste;
homologação;
produção.
Passo 2 — Confirme o load module
No ISPF 3.4:
VAGNER.DB2.LOAD
Verifique:
CADCLI01
Passo 3 — Confirme a data
Veja se o membro foi atualizado após a última compilação.
Passo 4 — Confirme o package
O package foi criado ou rebindeado?
Passo 5 — Confirme o plan
O plano aponta para a collection correta?
Passo 6 — Valide parâmetros
Confira vírgulas, espaços, tamanhos e valores.
Passo 7 — Escolha o modo correto
FOREGROUND
BACKGROUND
EDITJCL
Passo 8 — Revise os DDs
O programa precisa de:
ENTRADA
SAIDA
SYSIN
SYSOUT
ARQERRO
Passo 9 — Execute com poucos dados
Primeiro teste com um conjunto reduzido.
Passo 10 — Analise resultado e SQLCODE
RC=0000 não garante que a regra de negócio funcionou corretamente.
Um programa pode terminar com RC zero e ainda ter tratado incorretamente um +100.
52. O grande easter egg do painel
A frase:
Required if different from program name
esconde uma convenção histórica.
Muitas instalações utilizavam nomes iguais:
Programa = CADCLI01
DBRM = CADCLI01
Package = CADCLI01
Plan = CADCLI01
Isso facilitava a administração, mas confundia iniciantes.
O padawan olhava para quatro objetos chamados CADCLI01 e imaginava que eram o mesmo.
Não são.
Programa = executável
DBRM = SQL extraído
Package = SQL preparado
Plan = caminho para packages
Podem compartilhar o mesmo nome, mas possuem naturezas diferentes.
É como ter quatro pessoas chamadas João trabalhando no mesmo datacenter.
O nome é igual.
A função não.
53. O verdadeiro valor do EDITJCL
Para aprender, a melhor opção muitas vezes é:
EDITJCL
Ela mostra o JCL que o painel geraria.
Isso permite estudar:
JOB card;
EXEC;
STEPLIB;
SYSTSIN;
SYSTSPRT;
SYSOUT;
parâmetros;
DDs;
comandos DSN.
Depois de revisar, você pode:
salvar o JCL em uma biblioteca;
documentar;
versionar;
adaptar;
submeter novamente;
transformar em PROC;
integrar a uma esteira.
O painel deixa de ser uma caixa-preta e vira uma ferramenta de ensino.
54. Do DB2I ao DevOps moderno
Hoje, o mesmo fluxo pode ser automatizado por ferramentas como:
IBM Dependency Based Build;
zBuilder;
Jenkins;
GitHub Actions;
GitLab CI;
UrbanCode Deploy;
Endevor;
ISPW;
IBM Developer for z/OS;
VS Code;
Zowe CLI.
Um pipeline pode executar:
Checkout
Precompile
Compile
Link-edit
Bind Package
Test
Deploy
Run
Validate
Mas por trás da automação continuam existindo os mesmos conceitos:
fonte;
DBRM;
load;
package;
plan;
ambiente;
autorização.
Quem entende o painel RUN compreende melhor o que o pipeline está automatizando.
A modernização não elimina os fundamentos.
Ela os organiza, automatiza e observa.
Conclusão
O painel DB2I RUN parece pequeno, quase humilde.
Cinco campos, um SSID e uma tecla Enter.
Mas atrás dele existe um dos mais ricos ecossistemas da computação corporativa.
Ao preencher:
DATA SET NAME
PASSWORD
PARAMETERS
PLAN NAME
WHERE TO RUN
você está conectando:
Programa COBOL
Load Module
Language Environment
DSN Command Processor
Plano Db2
Package
Collection
Subsistema
JES
TSO
ISPF
JCL
O painel não compila o programa.
Não cria magicamente o package.
Não corrige um bind quebrado.
Não sincroniza um load antigo.
Ele apenas reúne as peças que já deveriam estar preparadas.
Quando tudo está alinhado, o resultado pode ser:
RC=0000
SQLCODE=0
Quando algo está fora do lugar, entram em cena os grandes vilões:
-204
-551
-805
-818
S806
S0C4
S0C7
A grande lição para o programador COBOL padawan é simples:
Nunca veja o RUN apenas como uma tela de execução. Veja-o como o ponto de encontro entre o mundo do COBOL e o mundo do Db2.
Quando você entende load module, DBRM, package, collection, plan, SSID, JCL e DSN, deixa de ser alguém que apenas pressiona Enter.
Você passa a compreender cada peça da engrenagem.
E nesse momento, jovem padawan, a tela verde deixa de ser um mistério.
Ela se transforma em mapa.
Sem comentários:
Enviar um comentário