Translate

Mostrar mensagens com a etiqueta Precompile. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Precompile. Mostrar todas as mensagens

terça-feira, 22 de novembro de 2022

BIND PACKAGE e BIND PLAN sem Mistérios O guia do programador COBOL Padawan para transformar um DBRM em SQL executável no Db2 for z/OS

 

Bellacosa Mainframe apresenta bind package e bin plan sem misterios

☕ Um Café no Bellacosa Mainframe

BIND PACKAGE e BIND PLAN sem Mistérios

O guia do programador COBOL Padawan para transformar um DBRM em SQL executável no Db2 for z/OS

Imagine a seguinte cena.

Você passou horas escrevendo um programa COBOL. Revisou a WORKING-STORAGE, declarou corretamente as host variables, incluiu a SQLCA, fechou todos os END-EXEC, compilou o fonte e recebeu um belo retorno RC=0000.

Orgulhoso, você executa o programa.

De repente, o Db2 responde:

SQLCODE = -805

Ou talvez:

SQLCODE = -818

Você olha para o load module, olha para o JCL e pensa:

“Mas o programa compilou! Por que o Db2 diz que não consegue executá-lo?”

É nesse momento que o programador COBOL Padawan descobre uma das grandes verdades do universo mainframe:

Um programa COBOL com SQL não vive apenas dentro do load module.

Ele possui duas metades.

A primeira metade é o código executável:

Fonte COBOL
   ↓
Compilação
   ↓
Objeto
   ↓
Link-edit
   ↓
Load module

A segunda metade é o SQL preparado para o Db2:

SQL embutido
   ↓
DBRM
   ↓
BIND PACKAGE
   ↓
PACKAGE
   ↓
PLAN

Essas duas metades precisam permanecer sincronizadas. Quando isso não acontece, surgem os lendários -805, -818, packages não encontrados, plans inconsistentes e deploys que pareciam perfeitos até o momento em que chegaram à produção.

Neste artigo, vamos desmontar cuidadosamente o JCL apresentado, explicar cada instrução, compreender a relação entre DBRM, package e plan, analisar os erros mais frequentes e construir uma versão mais segura, legível e moderna.

Prepare o café. O ritual do BIND vai começar.


Bellacosa Mainframe e o bind no db2

1. O que é o BIND no Db2?

O BIND é o processo por meio do qual o Db2 recebe as informações SQL extraídas de um programa e as transforma em uma estrutura executável chamada package.

Quando você escreve:

EXEC SQL
    SELECT NOME_CLIENTE
      INTO :WS-NOME-CLIENTE
      FROM CLIENTES
     WHERE COD_CLIENTE = :WS-COD-CLIENTE
END-EXEC.

o compilador COBOL não sabe interpretar diretamente:

EXEC SQL

Por isso, antes da compilação propriamente dita, o programa passa por um precompiler Db2.

O precompiler separa o programa em duas trilhas.

Trilha COBOL

Ele produz um fonte COBOL modificado, no qual as instruções SQL são substituídas por chamadas apropriadas ao runtime Db2.

Trilha Db2

Ele produz um arquivo chamado:

DBRM

DBRM significa:

Database Request Module

O DBRM contém a representação das instruções SQL estáticas encontradas no programa.

Depois, o comando BIND PACKAGE lê esse DBRM e cria o package.

Em termos simples:

DBRM + opções de BIND + catálogo Db2 = PACKAGE

Durante o BIND, o Db2 pode:

  • verificar os objetos referenciados;

  • conferir autorizações;

  • resolver tabelas, views e aliases;

  • avaliar índices disponíveis;

  • selecionar caminhos de acesso;

  • registrar dependências;

  • definir isolamento;

  • definir encoding;

  • armazenar informações no catálogo;

  • criar o package que será usado durante a execução.

Portanto, o BIND não é uma simples cópia.

Ele é uma etapa de preparação, validação, autorização e otimização.


2. O JCL analisado

O trecho apresentado segue esta estrutura:

//BINDPK03 EXEC PGM=IKJEFT01,COND=(4,LT,COB),
//             DYNAMNBR=20
//DBRMLIB  DD DSN=&&DBRMDB2(COBDB501),DISP=(OLD,DELETE)
//SYSUDUMP DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSTSIN  DD *

 DSN SYSTEM(DB9G)

 BIND PACKAGE(HERPACK) OWNER(INEFE00) MEMBER(COBDB501) -
 ACTION(REP) VALIDATE(BIND) EXPLAIN(NO) DEGREE(1) ISO(UR) -
 ENABLE(*) ENCODING(EBCDIC)

 BIND PLAN(HERP0001) -
 PKLIST(HERPACK.*,HERPACK.COBDB501) -
 ACTION(REP) ISO(UR) ENCODING(EBCDIC)

/*

Esse passo possui duas grandes responsabilidades:

  1. Criar ou substituir o package HERPACK.COBDB501.

  2. Criar ou substituir o plan HERP0001.

Vamos analisar cada parte.


3. O step BINDPK03

//BINDPK03 EXEC PGM=IKJEFT01,COND=(4,LT,COB),
//             DYNAMNBR=20

O nome do step é:

BINDPK03

O nome não possui significado obrigatório para o sistema. Ele é uma convenção criada pela equipe.

Pode significar:

BIND = etapa de bind
PK   = package
03   = terceiro passo do processo

Uma boa nomenclatura ajuda muito durante a análise do spool.

Compare:

//STEP7 EXEC ...

com:

//BINDPKG EXEC ...

Quando há uma falha às duas da manhã, o segundo nome é muito mais amigável.


4. Por que executar IKJEFT01?

PGM=IKJEFT01

O IKJEFT01 permite executar comandos TSO em batch.

Normalmente, pensamos no TSO como uma sessão interativa acessada pelo terminal 3270. Porém, o IKJEFT01 cria uma espécie de sessão TSO sem uma pessoa digitando comandos.

Por meio dele, podemos executar:

  • comandos TSO;

  • CLIST;

  • execs REXX;

  • o command processor DSN;

  • alguns programas Db2;

  • comandos de execução de programas COBOL Db2.

No exemplo, ele recebe os comandos pelo DD:

//SYSTSIN DD *

O primeiro comando importante será:

DSN SYSTEM(DB9G)

Esse comando inicia o processador DSN e conecta o job ao subsistema Db2 chamado DB9G.

IKJEFT01 versus IKJEFT1B

Um detalhe interessante é que muitas instalações preferem:

PGM=IKJEFT1B

O IKJEFT1B é semelhante ao IKJEFT01, mas costuma ser escolhido em procedures nas quais a propagação do return code dos comandos internos precisa ser mais previsível.

Em uma esteira de build, isso é extremamente importante.

Imagine que o BIND falhou, mas o step terminou com retorno aparentemente aceitável. O pipeline poderia continuar, copiar o load module e declarar sucesso.

Resultado:

Load module novo
Package antigo

Na execução, aparece:

SQLCODE -818

Por isso, não basta olhar apenas o nome do programa executado. É preciso testar como a procedure trata códigos de retorno.


5. Entendendo COND=(4,LT,COB)

COND=(4,LT,COB)

A cláusula COND é uma das pegadinhas clássicas do JCL.

Ela não informa diretamente quando o step será executado. Ela informa quando o step deverá ser ignorado.

A expressão significa:

Se 4 for menor que o RC do step COB, não execute este step.

Em forma matemática:

4 < COB.RC

Tabela prática

RC do step COB4 menor que RC?Executa o BIND?
0NãoSim
4NãoSim
8SimNão
12SimNão
16SimNão

Portanto, o BIND será executado se o step COB retornar:

RC 0 ou RC 4

Isso faz sentido porque compiladores COBOL frequentemente usam:

RC 0 = compilação limpa
RC 4 = mensagens ou warnings aceitáveis
RC 8 = erro que impede uso seguro
RC 12+ = falha grave

Versão mais legível com IF

Uma alternativa moderna e mais fácil para iniciantes seria:

// IF COB.RC LE 4 THEN
//BINDPKG EXEC PGM=IKJEFT1B,DYNAMNBR=20
...
// ENDIF

Essa versão comunica diretamente a intenção:

Execute o bind se o retorno da compilação for menor ou igual a 4.

O COND é poderoso, mas sua lógica invertida provoca muitos erros de interpretação.


6. DYNAMNBR=20

DYNAMNBR=20

Esse parâmetro define uma quantidade de alocações dinâmicas que o ambiente TSO poderá administrar.

Durante a execução, o processador DSN e outros componentes podem precisar abrir datasets dinamicamente.

O valor 20 costuma ser suficiente para procedimentos simples.

Entretanto, em execuções mais complexas, encontramos:

DYNAMNBR=50

ou:

DYNAMNBR=100

Não existe mérito em aumentar esse número sem necessidade. Porém, um valor pequeno demais pode provocar falhas de alocação.

A regra é:

Use o valor padronizado pela instalação e ajuste apenas quando houver evidência de necessidade.


7. DBRMLIB: onde está o mapa SQL

//DBRMLIB DD DSN=&&DBRMDB2(COBDB501),DISP=(OLD,DELETE)

Esse DD aponta para o DBRM criado em uma etapa anterior.

Vamos desmontar a instrução.

DBRMLIB

É o DDNAME esperado pelo processo de BIND para localizar os DBRMs.

&&DBRMDB2

Os dois sinais de && indicam um dataset temporário criado dentro do job.

Ele provavelmente foi criado pelo precompiler com algo semelhante a:

//DBRMLIB DD DSN=&&DBRMDB2,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(5,5,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//            DSNTYPE=LIBRARY

O PASS indica que o dataset deve ser passado para outro step do mesmo job.

No step de BIND, ele é reutilizado.

(COBDB501)

Esse é o nome do membro contendo o DBRM.

Geralmente, o nome acompanha o programa:

Programa:    COBDB501
DBRM:        COBDB501
Package:     COBDB501
Load module: COBDB501

Essa padronização facilita:

  • pesquisa no catálogo;

  • leitura de spool;

  • manutenção;

  • comparação entre versões;

  • análise de problemas.

DISP=(OLD,DELETE)

OLD solicita acesso exclusivo ao dataset.

DELETE solicita sua remoção após o uso.

Isso é aceitável para um dataset temporário, mas existe um ponto de atenção.

Se o DBRM for apagado e não houver uma biblioteca permanente, uma falha posterior pode dificultar:

  • análise;

  • rebind;

  • comparação;

  • reconstrução do package;

  • rollback.

Em esteiras corporativas, o DBRM muitas vezes é preservado em uma biblioteca controlada por versão.


8. Uma possível redundância no DBRMLIB

O JCL usa:

DSN=&&DBRMDB2(COBDB501)

e o comando BIND usa:

MEMBER(COBDB501)

Ou seja, o membro está sendo indicado duas vezes.

O formato mais comum e flexível seria:

//DBRMLIB DD DSN=&&DBRMDB2,DISP=(OLD,DELETE)

E depois:

MEMBER(COBDB501)

Assim, DBRMLIB aponta para a biblioteca, enquanto MEMBER informa qual membro será processado.

Isso também permite executar vários binds com a mesma biblioteca:

BIND PACKAGE(APPPACK) MEMBER(PROGA)
BIND PACKAGE(APPPACK) MEMBER(PROGB)
BIND PACKAGE(APPPACK) MEMBER(PROGC)

9. Os DDs de saída

SYSUDUMP

//SYSUDUMP DD SYSOUT=*

Solicita um dump caso ocorra um abend.

O dump pode conter:

  • PSW;

  • registradores;

  • áreas de memória;

  • módulos carregados;

  • endereço da falha;

  • cadeia de chamadas.

Para erros comuns de BIND, normalmente você consultará primeiro o SYSTSPRT. Porém, se o processador sofrer um abend, SYSUDUMP pode ser indispensável.


SYSTSPRT

//SYSTSPRT DD SYSOUT=*

É a saída principal do ambiente TSO batch.

Nela aparecem:

  • mensagens do IKJEFT01;

  • mensagens do processador DSN;

  • confirmação da conexão;

  • mensagens de BIND;

  • return codes;

  • mensagens DSN;

  • erros de autorização;

  • packages criados ou substituídos.

Esta deve ser uma das primeiras saídas verificadas no SDSF.


SYSPRINT

//SYSPRINT DD SYSOUT=*

É uma saída genérica usada por diversos utilitários.

Dependendo da procedure, pode conter mensagens adicionais ou ficar praticamente vazia.

O importante para o iniciante é não assumir que todos os erros estarão em um único DD. Em incidentes, consulte:

JESMSGLG
JESJCL
JESYSMSG
SYSTSPRT
SYSPRINT
SYSUDUMP

10. SYSTSIN: os comandos começam aqui

//SYSTSIN DD *

O conteúdo abaixo é enviado como entrada para a sessão TSO batch.

O primeiro comando é:

DSN SYSTEM(DB9G)

Esse comando solicita conexão com o subsistema Db2 DB9G.

O identificador poderia representar:

DB9G = Db2 geração 9, ambiente G

ou qualquer convenção local.

Algumas empresas usam:

DB2D = desenvolvimento
DB2Q = qualidade
DB2P = produção

Outras usam códigos menos óbvios, especialmente em data sharing.

Um erro simples no SSID pode fazer o bind ocorrer no ambiente errado ou falhar completamente.

Imagine promover um package acreditando estar em homologação e descobrir que o SSID era o de produção. É por isso que procedures bem desenhadas recebem o subsistema por parâmetro:

// SET DB2SSID=DB9G

E depois:

DSN SYSTEM(&DB2SSID)

11. BIND PACKAGE(HERPACK)

BIND PACKAGE(HERPACK)

O nome entre parênteses representa a collection.

A collection é um agrupador lógico de packages.

Neste caso:

Collection: HERPACK
Package:    COBDB501

O package final será identificado conceitualmente como:

HERPACK.COBDB501

Collections podem representar:

  • uma aplicação;

  • um domínio;

  • uma versão;

  • um ambiente;

  • uma release;

  • uma equipe;

  • uma linha de negócio.

Exemplos:

FINANCEIRO
PAGAMENTOS
CADASTRO
APPV1
APPV2
HOMOLOG
PROD

Dica de arquitetura

Usar collections diferentes por versão pode facilitar rollback.

Exemplo:

APPV001.COBDB501
APPV002.COBDB501

O novo package pode ser preparado sem remover imediatamente o anterior.

Depois, o plan ou a estratégia de execução passa a usar a nova collection.

Isso é muito mais seguro do que substituir tudo sem possibilidade de retorno.


12. OWNER(INEFE00)

OWNER(INEFE00)

Define o authorization ID proprietário do package.

Esse owner pode influenciar:

  • propriedade;

  • administração;

  • autorizações;

  • resolução de privilégios;

  • auditoria;

  • governança.

Se INEFE00 for um usuário pessoal, isso merece atenção.

Imagine que a pessoa:

  • mudou de projeto;

  • saiu da empresa;

  • teve o usuário revogado;

  • perdeu privilégios;

  • teve o ID protegido por nova política.

Por isso, packages de produção geralmente deveriam pertencer a IDs funcionais, como:

APPDB2O
BINDUSER
FINOWNER
HEROWNR

O owner funcional reduz dependência de indivíduos.


13. MEMBER(COBDB501)

MEMBER(COBDB501)

Essa opção informa qual DBRM será utilizado.

O Db2 procurará o membro dentro da biblioteca indicada por:

//DBRMLIB

Se o membro não existir, o BIND falhará.

Antes de culpar o Db2, verifique:

  • o precompile foi executado?

  • o DBRM foi realmente criado?

  • o dataset foi passado com DISP=PASS?

  • o nome do membro está correto?

  • houve exclusão prematura do dataset?

  • o DBRMLIB aponta para a biblioteca correta?


14. ACTION(REP)

ACTION(REP)

REP significa REPLACE.

Isso informa:

Se o package já existir, substitua-o.

É uma opção comum em ambientes de desenvolvimento, mas precisa de cautela em produção.

Substituir um package pode alterar:

  • access path;

  • comportamento de locking;

  • consumo de CPU;

  • tempo de resposta;

  • dependências;

  • compatibilidade com o load module.

O package antigo pode ter sido extremamente estável. O novo BIND pode escolher um caminho de acesso diferente por causa de:

  • estatísticas atualizadas;

  • novo índice;

  • índice removido;

  • alteração de cardinalidade;

  • mudança de parâmetros;

  • nova versão do Db2;

  • mudança no catálogo.

Dica importante

Antes de substituir packages críticos, considere mecanismos de preservação e reutilização de access paths, além do gerenciamento de planos oferecido pelo Db2.

Em outras palavras:

Não trate ACTION(REPLACE) como um simples “salvar por cima”.


15. VALIDATE(BIND)

VALIDATE(BIND)

Solicita validação no momento do BIND.

Se o programa referencia:

SELECT NOME
  FROM CLIENTES;

o Db2 tentará verificar a existência e a validade dos objetos durante o bind.

Isso é positivo porque antecipa problemas.

Melhor descobrir durante o deploy que a tabela está ausente do que descobrir durante o fechamento financeiro.

A alternativa conhecida é:

VALIDATE(RUN)

Nesse caso, parte da validação pode ocorrer apenas quando a instrução for executada.

Comparação

OpçãoMomento da validaçãoPrincipal benefícioPrincipal risco
BINDDurante a implantaçãoFalha antecipadaExige ambiente pronto
RUNDurante a execuçãoMaior flexibilidadeErro pode aparecer em produção

Para programas batch tradicionais, VALIDATE(BIND) costuma ser uma escolha mais segura.


16. EXPLAIN(NO)

EXPLAIN(NO)

Indica que o BIND não deve gerar informações de EXPLAIN nas tabelas correspondentes.

O EXPLAIN ajuda a entender o caminho de acesso escolhido pelo otimizador.

Ele pode revelar:

  • table space scan;

  • index scan;

  • matching index;

  • nonmatching index;

  • sort;

  • prefetch;

  • ordem de join;

  • método de join;

  • paralelismo;

  • estimativas de custo.

Em desenvolvimento, EXPLAIN(YES) pode ser extremamente útil.

Por exemplo:

EXPLAIN(YES)

permite analisar por que um SQL está fazendo table scan mesmo com um índice aparentemente disponível.

Por que alguém usa EXPLAIN(NO)?

Possíveis razões:

  • reduzir geração de dados;

  • procedure antiga;

  • ambiente sem tabelas EXPLAIN configuradas;

  • processo separado de análise;

  • ferramenta externa de monitoramento;

  • package simples e já conhecido.

Entretanto, para SQL crítico, abrir mão completamente da análise de access path é arriscado.


17. DEGREE(1)

DEGREE(1)

Define grau de paralelismo igual a 1.

Em linguagem prática:

Execute sem paralelismo de query.

Isso pode ser apropriado para:

  • transações curtas;

  • consultas pequenas;

  • programas COBOL tradicionais;

  • workloads sensíveis ao consumo;

  • ambientes que desejam comportamento previsível.

Uma alternativa seria:

DEGREE(ANY)

permitindo que o Db2 avalie paralelismo.

Vantagem de DEGREE(1)

  • previsibilidade;

  • menor risco de consumo inesperado;

  • comportamento mais estável;

  • adequado a muitas transações OLTP.

Desvantagem

Consultas analíticas grandes podem demorar mais.

Não existe valor universalmente melhor. A escolha depende do workload.


18. ISO(UR): velocidade com risco

ISO(UR)

UR significa:

Uncommitted Read

É o nível de isolamento mais permissivo.

Ele pode permitir a leitura de dados ainda não confirmados por outra transação.

Exemplo:

Uma transação altera um saldo:

UPDATE CONTA
   SET SALDO = 100
 WHERE NUMERO = 999;

Mas ainda não executou COMMIT.

Um programa com UR pode enxergar o valor 100.

Depois, a transação executa:

ROLLBACK;

O dado lido nunca foi realmente confirmado.

Essa é a chamada leitura suja.

Quando UR pode ser aceitável?

  • relatório estatístico;

  • dashboard;

  • consulta aproximada;

  • monitoração;

  • dados sem impacto transacional;

  • leitura informativa.

Quando UR é perigoso?

  • saldo;

  • faturamento;

  • pagamento;

  • estoque;

  • contabilidade;

  • cálculo fiscal;

  • autorização de crédito;

  • tomada de decisão baseada em consistência.

Para muitos programas COBOL corporativos, CS pode ser uma opção mais equilibrada:

ISOLATION(CS)

CS significa Cursor Stability.

O grande conselho é:

Nunca copie ISO(UR) de outro JCL sem entender a regra de negócio.


19. ENABLE(*)

ENABLE(*)

Essa cláusula está associada à habilitação do package para contextos de conexão suportados.

O asterisco representa uma habilitação ampla.

Ela pode ser conveniente em procedures genéricas, mas vale avaliar se o package realmente precisa estar habilitado para todos os contextos aplicáveis.

A lógica de segurança é semelhante ao princípio do menor privilégio:

Habilite apenas o necessário.

Em muitas instalações, esse detalhe é controlado por padrões corporativos e deve ser validado com o DBA.


20. ENCODING(EBCDIC)

ENCODING(EBCDIC)

Define EBCDIC como encoding do package.

Isso é natural para muitos programas COBOL executados em z/OS.

Porém, encoding não é um detalhe cosmético.

Ele afeta:

  • caracteres acentuados;

  • conversão de strings;

  • integração com ASCII;

  • Unicode;

  • APIs;

  • XML;

  • JSON;

  • Java;

  • clientes distribuídos.

Imagine os caracteres:

ã
é
ç

Em ambientes com conversão incorreta, eles podem virar símbolos estranhos ou provocar erros de conversão.

Quando uma aplicação COBOL conversa com sistemas distribuídos, é necessário observar:

  • CCSID das tabelas;

  • CCSID da aplicação;

  • encoding do package;

  • encoding da conexão;

  • formato dos dados recebidos.


21. BIND PLAN(HERP0001)

BIND PLAN(HERP0001)

Depois do package, o JCL cria ou substitui um plan chamado:

HERP0001

O plan fornece um contexto de execução e referencia packages.

Visualmente:

PLAN HERP0001
    |
    +-- HERPACK.COBDB501
    +-- HERPACK.COBDB502
    +-- HERPACK.COBDB503

Historicamente, plans tinham um papel ainda mais central. Com a adoção de packages, passou a ser comum pensar assim:

DBRM → PACKAGE
PLAN → lista de packages

22. PKLIST e a possível redundância

PKLIST(HERPACK.*,HERPACK.COBDB501)

A PKLIST informa onde o plan deverá procurar packages.

A entrada:

HERPACK.*

significa, de forma geral:

Packages da collection HERPACK

A entrada:

HERPACK.COBDB501

indica especificamente o package COBDB501.

O problema é que:

HERPACK.*

aparentemente já cobre:

HERPACK.COBDB501

Portanto, há uma possível redundância.

Para um plan exclusivo:

PKLIST(HERPACK.COBDB501)

Para um plan compartilhado:

PKLIST(HERPACK.*)

A lista original pode ter sido criada por:

  • geração automática;

  • procedure antiga;

  • manutenção parcial;

  • tentativa de reforçar a resolução;

  • simples excesso de cautela.

Mesmo quando algo funciona, vale perguntar:

Está claro, necessário e fácil de manter?


23. Um JCL completo de precompile, compile, link e bind

A seguir, um exemplo educacional simplificado.

Passo 1 — Precompile

//PRECOMP EXEC PGM=DSNHPC,
//             PARM='HOST(IBMCOB),APOST,SQL'
//STEPLIB  DD DISP=SHR,DSN=DB2.SDSNLOAD
//SYSIN    DD DISP=SHR,DSN=ALUNO.COBOL(COBDB501)
//SYSCIN   DD DSN=&&COBSRC,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(10,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//DBRMLIB  DD DSN=&&DBRMDB2,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(5,5,5)),
//            DSNTYPE=LIBRARY,
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSPRINT DD SYSOUT=*
//SYSTERM  DD SYSOUT=*

O que acontece?

  • DSNHPC executa o precompiler.

  • SYSIN contém o fonte COBOL com SQL.

  • SYSCIN recebe o fonte COBOL modificado.

  • DBRMLIB recebe o DBRM.

  • SYSPRINT recebe mensagens.


Passo 2 — Compile

//COB EXEC PGM=IGYCRCTL,
//         PARM='LIB,OBJECT,LIST,MAP,XREF'
//SYSIN    DD DSN=&&COBSRC,DISP=(OLD,DELETE)
//SYSLIN   DD DSN=&&OBJ,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(10,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSLIB   DD DISP=SHR,DSN=DB2.SDSNMACS
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT2   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT3   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT4   DD UNIT=SYSDA,SPACE=(CYL,(1,1))

O que acontece?

  • IGYCRCTL executa o compilador COBOL.

  • SYSIN recebe o fonte alterado pelo precompiler.

  • SYSLIN recebe o object module.

  • SYSPRINT contém a listagem.


Passo 3 — Link-edit

//LKED EXEC PGM=IEWL,
//         PARM='LIST,XREF,LET,MAP'
//SYSLIN   DD DSN=&&OBJ,DISP=(OLD,DELETE)
//         DD DISP=SHR,DSN=DB2.SDSNLOAD(DSNELI)
//SYSLMOD  DD DISP=SHR,DSN=ALUNO.LOADLIB(COBDB501)
//SYSLIB   DD DISP=SHR,DSN=CEE.SCEELKED
//SYSPRINT DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))

O que acontece?

  • IEWL executa o binder/link-editor.

  • SYSLIN recebe o object module.

  • O módulo de interface Db2 é incluído conforme o tipo de execução.

  • SYSLMOD recebe o load module final.


Passo 4 — Bind package e plan

// IF COB.RC LE 4 THEN
//BIND EXEC PGM=IKJEFT1B,DYNAMNBR=20
//STEPLIB  DD DISP=SHR,DSN=DB2.SDSNLOAD
//DBRMLIB  DD DSN=&&DBRMDB2,DISP=(OLD,DELETE)
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN  DD *
 DSN SYSTEM(DB9G)

 BIND PACKAGE(HERPACK)          -
      MEMBER(COBDB501)          -
      OWNER(HEROWNR)            -
      ACTION(REPLACE)           -
      VALIDATE(BIND)            -
      EXPLAIN(YES)              -
      DEGREE(1)                 -
      ISOLATION(CS)             -
      ENCODING(EBCDIC)

 BIND PLAN(HERP0001)            -
      PKLIST(HERPACK.COBDB501)  -
      ACTION(REPLACE)           -
      ISOLATION(CS)             -
      ENCODING(EBCDIC)

 END
/*
// ENDIF

Observe as melhorias:

  • uso de IF;

  • IKJEFT1B;

  • biblioteca inteira em DBRMLIB;

  • owner funcional;

  • EXPLAIN(YES);

  • isolamento CS;

  • PKLIST sem redundância;

  • comando END explícito.


24. JCL de execução

Depois da construção, o programa poderia ser executado assim:

//RUNDB2 EXEC PGM=IKJEFT1B,DYNAMNBR=20
//STEPLIB  DD DISP=SHR,DSN=ALUNO.LOADLIB
//         DD DISP=SHR,DSN=DB2.SDSNLOAD
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN  DD *
 DSN SYSTEM(DB9G)

 RUN PROGRAM(COBDB501)          -
     PLAN(HERP0001)             -
     LIB('ALUNO.LOADLIB')

 END
/*

O fluxo será:

RUN PROGRAM(COBDB501)
          ↓
Load module COBDB501
          ↓
PLAN HERP0001
          ↓
PKLIST
          ↓
PACKAGE HERPACK.COBDB501
          ↓
Execução das instruções SQL

25. Erros comuns e soluções

SQLCODE -805

O -805 geralmente indica que o package necessário não foi encontrado ou não corresponde ao contexto procurado.

Possíveis causas:

  • package não bindado;

  • collection errada;

  • plan com PKLIST incorreta;

  • subsistema errado;

  • package removido;

  • load module de outro ambiente;

  • versão inexistente;

  • consistency token incompatível.

Checklist

1. O BIND PACKAGE terminou com sucesso?
2. A collection é HERPACK?
3. O package é COBDB501?
4. O plan HERP0001 inclui essa collection?
5. A execução está no subsistema DB9G?
6. O load module pertence ao mesmo build?
7. O package foi substituído depois do link?

Solução típica

Refazer o build completo:

Precompile
Compile
Link
Bind package
Bind plan
Deploy

Evite refazer apenas uma etapa sem saber exatamente o motivo.


SQLCODE -818

O -818 normalmente indica inconsistência entre o programa e o package.

Em termos didáticos:

Load module versão A
Package versão B

Isso acontece quando:

  • o programa foi recompilado e não houve novo bind;

  • o package foi substituído, mas o load module não;

  • houve deploy parcial;

  • o DBRM usado não pertence ao objeto compilado;

  • arquivos de builds diferentes foram misturados.

Solução

Reconstruir e promover os artefatos juntos.

Pense no load module e no package como irmãos gêmeos de build. Separá-los é pedir confusão.


Erro de autorização

O usuário do job pode não possuir:

  • privilégio de BIND;

  • autorização sobre a collection;

  • autorização para usar o owner;

  • acesso aos objetos SQL;

  • autorização de replace;

  • privilégio para criar o plan.

Solução

Consultar mensagens no SYSTSPRT e trabalhar com o DBA ou segurança.

Não resolva concedendo privilégios amplos sem análise.

O correto é identificar precisamente o privilégio necessário.


DBRM não encontrado

Possíveis causas:

  • erro no nome do membro;

  • precompile falhou;

  • DISP=PASS ausente;

  • dataset temporário deletado;

  • DD apontando para biblioteca errada;

  • membro indicado duas vezes de forma problemática;

  • job reiniciado a partir do step de BIND, mas o dataset temporário já não existe.

Solução

Use uma biblioteca permanente de DBRMs quando o processo precisar suportar restart independente.

Dataset temporário desaparece ao final do job. Portanto, reiniciar apenas o step de BIND em outro job pode não funcionar.


Objetos inexistentes

Com VALIDATE(BIND), tabelas ou views ausentes podem causar falha.

Possíveis causas:

  • ambiente incompleto;

  • DDL não aplicado;

  • qualificador incorreto;

  • tabela criada em outro schema;

  • alias ausente;

  • deploy executado fora de ordem.

Solução

Aplicar primeiro as mudanças de banco e depois executar o BIND.

Uma esteira madura respeita dependências:

DDL
RUNSTATS quando necessário
BIND
Deploy do executável
Execução

Access path pior após o BIND

O BIND pode escolher um caminho de acesso diferente.

Sintomas:

  • maior CPU;

  • mais GETPAGE;

  • batch mais lento;

  • aumento de I/O;

  • timeout;

  • lock escalation;

  • duração imprevisível.

Causas:

  • estatísticas desatualizadas;

  • mudança de índice;

  • alteração de cardinalidade;

  • parâmetros diferentes;

  • novo release;

  • BIND executado após mudanças no catálogo.

Soluções

  • executar RUNSTATS adequadamente;

  • usar EXPLAIN;

  • comparar access paths;

  • preservar opções de estabilidade;

  • testar antes da produção;

  • monitorar packages críticos;

  • usar mecanismos de gerenciamento de planos.


26. Como otimizar o processo

1. Padronize opções de BIND

Não permita que cada programador invente suas próprias opções.

Crie procedures corporativas para:

  • batch;

  • CICS;

  • IMS;

  • programas de consulta;

  • programas críticos;

  • packages distribuídos.


2. Use owners funcionais

Evite IDs pessoais em produção.


3. Versione packages e collections

Isso facilita rollback e coexistência entre releases.


4. Preserve os DBRMs

Principalmente em ambientes com auditoria, rebind ou recuperação.


5. Use EXPLAIN de forma consciente

Não espere uma crise de performance para descobrir o access path.


6. Monitore o RC real do BIND

O pipeline precisa falhar quando o BIND falhar.

“Job terminou” não significa “package válido”.


7. Evite UR por hábito

Escolha o isolamento conforme a regra de negócio.


8. Elimine redundâncias

Uma PKLIST limpa é mais fácil de auditar.


9. Mantenha compile, link e bind na mesma unidade de mudança

Essa é uma das melhores formas de evitar -805 e -818.


10. Planeje rollback

Antes de substituir um package, responda:

Como volto à versão anterior?

Se ninguém souber responder, o deploy ainda não está pronto.


27. Dicas para o programador COBOL iniciante

Quando um programa Db2 falhar, não olhe apenas o fonte COBOL.

Investigue a cadeia completa:

Fonte
Precompile
DBRM
Compile
Object
Link
Load module
Package
Collection
Plan
PKLIST
Subsistema
Autorização

Aprenda a ler mensagens no spool. Muitas respostas estão no SYSTSPRT, mas o iniciante frequentemente olha apenas o MAXCC.

Nunca suponha que RC=0 em um step significa que todos os comandos internos tiveram sucesso. Verifique as mensagens e a forma como os retornos são propagados.

Não copie opções de BIND cegamente. Cada uma carrega uma decisão:

UR
CS
RR
DEGREE
VALIDATE
EXPLAIN
OWNER
ENCODING
ACTION

Toda opção deveria conseguir responder à pergunta:

Por que estamos usando isso?

Se a única resposta for “sempre foi assim”, há uma dívida técnica escondida.


28. Easter egg: o package é a memória Jedi do SQL

Existe uma analogia divertida para guardar esse fluxo.

O fonte COBOL é o Padawan.

O DBRM é o pergaminho contendo as técnicas SQL aprendidas.

O BIND é o Conselho que examina o pergaminho, verifica permissões e escolhe como cada técnica será executada.

O package é o Holocron pronto para uso.

O plan é a autorização de missão que informa quais Holocrons o Padawan pode consultar.

Quando ocorre -805, o guerreiro chegou à missão, mas o Holocron não estava na lista.

Quando ocorre -818, ele trouxe um Holocron de outra geração.

E quando alguém usa ISO(UR) em um sistema financeiro sem entender o motivo, é como desligar os escudos para ganhar velocidade.

Pode funcionar.

Até o momento em que não funciona.


Conclusão

O JCL de BIND é uma das peças mais importantes do ciclo de construção de um programa COBOL Db2.

Ele não é apenas um passo burocrático depois da compilação.

É nele que o Db2 recebe o DBRM, valida objetos, verifica autorizações, prepara as instruções SQL, cria o package e associa esse package ao contexto de execução fornecido pelo plan.

O fluxo completo é:

COBOL com SQL
      ↓
Precompile
      ↓
DBRM + fonte modificado
      ↓
Compile
      ↓
Object module
      ↓
Link-edit
      ↓
Load module
      ↓
BIND PACKAGE
      ↓
Package
      ↓
BIND PLAN
      ↓
Execução

No exemplo analisado:

DBRM:       COBDB501
Collection: HERPACK
Package:    HERPACK.COBDB501
Plan:       HERP0001
Subsistema: DB9G

O JCL funciona como uma ponte entre o mundo executável do COBOL e o mundo relacional do Db2.

Entretanto, ele também revela diversos pontos para melhoria:

  • avaliar IKJEFT1B;

  • usar IF para maior clareza;

  • remover redundância no DBRMLIB;

  • usar owner funcional;

  • revisar ISO(UR);

  • eliminar redundância na PKLIST;

  • considerar EXPLAIN(YES);

  • planejar rollback;

  • preservar DBRMs;

  • garantir sincronização entre package e load module.

O programador que domina o BIND deixa de tratar -805 e -818 como magia obscura.

Ele passa a enxergar exatamente onde cada artefato nasceu, como foi preparado, qual plan o referencia e por que o Db2 aceitou ou rejeitou sua execução.

E essa é uma das passagens mais importantes na jornada de um COBOL Padawan:

Compreender que compilar o programa cria o corpo, mas executar o BIND prepara a inteligência SQL que permite ao programa conversar com o coração do Db2.

quinta-feira, 23 de junho de 2022

DB2I sem Mistérios: o Portal Clássico que Leva o Programador COBOL Padawan do Primeiro SELECT ao BIND de Produção

 

Bellacosa Mainframe apresenta o db2i

☕ Um Café no Bellacosa Mainframe

DB2I sem Mistérios: o Portal Clássico que Leva o Programador COBOL Padawan do Primeiro SELECT ao BIND de Produção

Imagine a seguinte cena.

Você acabou de entrar no TSO. A tela preta surgiu diante de seus olhos como a entrada de uma antiga fortaleza digital. Depois de informar seu usuário, sua senha e atravessar os corredores do ISPF, você finalmente executa o comando que abre uma das áreas mais tradicionais do universo IBM Z.

Na tela aparece:

DB2I PRIMARY OPTION MENU

No canto superior direito:

SSID: DB9G

E logo abaixo, um conjunto de opções aparentemente simples:

1  SPUFI
2  DCLGEN
3  PROGRAM PREPARATION
4  PRECOMPILE
5  BIND/REBIND/FREE
6  RUN
7  DB2 COMMANDS
8  UTILITIES
D  DB2I DEFAULTS
X  EXIT

Para um iniciante, isso pode parecer apenas mais um menu antigo em modo texto.

Mas não se engane, jovem padawan.

Essa tela é uma verdadeira central de comando para o desenvolvimento de aplicações COBOL com Db2 no mainframe. Ela reúne, em um único lugar, grande parte da jornada que transforma uma instrução SQL escrita dentro de um programa COBOL em uma operação real, autorizada, otimizada e executada contra um banco de dados corporativo.

Estamos diante do DB2I, sigla para Db2 Interactive.

Ele é um dos portais clássicos do desenvolvimento no IBM Z.

Neste café, vamos atravessar cada porta desse menu, entender sua história, observar como ele funciona, descobrir o que acontece nos bastidores e acompanhar, passo a passo, o nascimento de um programa COBOL com SQL embutido.

Prepare sua caneca.

O Db2 está acordado.


Bellacosa Mainframe e o db2i no emulador 3270

1. O que é o DB2I?

O DB2I é uma interface interativa integrada ao ISPF que permite acessar diversas funções relacionadas ao Db2 for z/OS.

Ele não é o banco de dados propriamente dito.

Também não é o compilador COBOL.

Ele funciona como um grande painel de controle que organiza diferentes ferramentas, processos e utilitários do ecossistema Db2.

Por meio dele, o usuário pode:

  • executar comandos SQL;

  • gerar declarações de tabelas;

  • preparar programas para execução;

  • realizar precompile;

  • executar BIND e REBIND;

  • rodar programas;

  • emitir comandos administrativos;

  • executar utilitários;

  • configurar parâmetros pessoais.

Sua grande virtude é a integração.

Em vez de o programador precisar decorar vários comandos, jobs e programas utilitários, o DB2I apresenta painéis que solicitam os parâmetros necessários e, em muitos casos, gera ou submete o JCL correspondente.

É importante entender que o DB2I não eliminou o JCL.

Ele apenas oferece uma interface mais amigável para preparar ou executar processos que, por baixo da superfície, continuam dependendo de datasets, procedimentos catalogados, módulos de carga, bibliotecas, parâmetros, planos e packages.

O DB2I é, portanto, uma espécie de ponte entre o usuário e a complexidade da infraestrutura.


2. Em que ambiente estamos trabalhando?

A tela mostrada é acessada por meio de um emulador TN3270.

A arquitetura normalmente segue este caminho:

Computador do usuário
        |
        v
Emulador TN3270
        |
        v
TSO/E
        |
        v
ISPF
        |
        v
DB2I
        |
        v
Subsistema Db2

Cada camada possui uma função.

O TN3270 permite que o computador moderno se comporte como um terminal IBM 3270.

O TSO/E oferece a sessão interativa no z/OS.

O ISPF fornece os painéis, menus, editores e serviços de produtividade.

O DB2I organiza as funções relacionadas ao Db2.

Finalmente, o subsistema Db2 executa o trabalho real de gerenciamento de dados, SQL, locks, buffer pools, logs, recuperação, autorização e otimização.

O programador enxerga uma tela.

O sistema enxerga uma cadeia inteira de componentes.


3. O significado de SSID

No canto superior direito aparece:

SSID: DB9G

SSID significa:

Subsystem Identifier

É o identificador do subsistema Db2 ao qual a sessão está associada.

Em um mesmo ambiente z/OS podem existir vários subsistemas Db2.

Por exemplo:

DB2D = desenvolvimento
DB2T = testes
DB2H = homologação
DB2P = produção

Também podem existir subsistemas diferentes por aplicação, unidade de negócio, versão, data sharing group ou finalidade técnica.

O nome não precisa obrigatoriamente indicar o ambiente. Cada empresa define sua convenção.

O ponto essencial é este:

Sempre confirme em qual SSID você está trabalhando antes de executar comandos.

Essa é uma regra de ouro.

Um SELECT executado no ambiente errado pode causar apenas confusão.

Um DELETE executado no ambiente errado pode causar uma reunião de emergência com vinte pessoas, três gerentes, dois DBAs e um café que já perdeu a temperatura.


4. Opção 1 — SPUFI

A primeira opção é:

1 SPUFI

SPUFI significa:

SQL Processor Using File Input

Em muitas documentações antigas, também é descrito como uma interface para processar SQL armazenado em um dataset de entrada.

Na prática, ele permite escrever instruções SQL em um arquivo, executá-las e armazenar os resultados em outro arquivo.

É uma das ferramentas mais tradicionais do Db2 for z/OS.


4.1 Como o SPUFI funciona?

O fluxo básico é:

Dataset de entrada
       |
       v
Instruções SQL
       |
       v
SPUFI
       |
       v
Db2
       |
       v
Dataset de saída

O usuário informa:

  • o dataset que contém o SQL;

  • o dataset em que deseja receber o resultado;

  • parâmetros de execução;

  • formato da saída;

  • número máximo de linhas;

  • opções de commit;

  • isolamento.

Um exemplo de dataset de entrada:

SELECT EMPNO,
       FIRSTNME,
       LASTNAME,
       SALARY
FROM DSN8C10.EMP
ORDER BY LASTNAME;

O SPUFI envia a instrução ao Db2 e grava a resposta no dataset de saída.


4.2 Primeiro passo a passo com SPUFI

Suponha que você queira consultar uma tabela chamada CLIENTE.

Entre na opção 1.

Informe um dataset de entrada, por exemplo:

VAGNER.SQL.CONSULTA

Caso o dataset não exista, o DB2I poderá permitir sua alocação, dependendo das configurações.

No editor ISPF, escreva:

SELECT ID_CLIENTE,
       NOME_CLIENTE,
       LIMITE_CREDITO
FROM APP.CLIENTE
FETCH FIRST 20 ROWS ONLY;

Salve o membro ou dataset.

Retorne ao painel do SPUFI.

Informe o dataset de saída:

VAGNER.SQL.RESULTADO

Execute.

Depois, abra o resultado.

Você poderá ver algo semelhante a:

---------+---------+---------+---------+
ID_CLIENTE NOME_CLIENTE          LIMITE_CREDITO
---------+---------+---------+---------+
000001     ANA SILVA                    5000.00
000002     JOAO SOUZA                   3500.00
000003     MARIA COSTA                  8000.00
DSNE610I NUMBER OF ROWS DISPLAYED IS 3
DSNE616I STATEMENT EXECUTION WAS SUCCESSFUL

O formato real varia conforme parâmetros, versão e configuração do ambiente.


4.3 Cuidados com SPUFI

O SPUFI não é apenas uma ferramenta de consulta.

Ele também pode executar:

INSERT
UPDATE
DELETE
CREATE
ALTER
DROP
GRANT
REVOKE

Portanto, trate-o com respeito.

Antes de executar:

DELETE FROM APP.CLIENTE;

verifique se faltou uma cláusula WHERE.

Uma pequena ausência pode transformar uma manutenção de um registro em uma limpeza completa da tabela.

Uma boa prática é primeiro executar:

SELECT COUNT(*)
FROM APP.CLIENTE
WHERE STATUS = 'I';

Depois:

SELECT *
FROM APP.CLIENTE
WHERE STATUS = 'I'
FETCH FIRST 50 ROWS ONLY;

Somente após validar os dados, executar:

DELETE FROM APP.CLIENTE
WHERE STATUS = 'I';

O padawan prudente consulta antes de alterar.


5. Opção 2 — DCLGEN

A segunda opção é:

2 DCLGEN

DCLGEN significa:

Declarations Generator

Sua finalidade é gerar declarações de tabela e estruturas de host variables para linguagens como COBOL.

Suponha que exista a tabela:

CREATE TABLE APP.CLIENTE
(
    ID_CLIENTE      INTEGER       NOT NULL,
    NOME_CLIENTE    VARCHAR(80)   NOT NULL,
    LIMITE_CREDITO  DECIMAL(11,2),
    DATA_CADASTRO   DATE,
    STATUS          CHAR(1)
);

O programa COBOL precisa conhecer a estrutura dos campos que serão usados nas instruções SQL.

O DCLGEN pode gerar algo semelhante a:

       EXEC SQL DECLARE APP.CLIENTE TABLE
       ( ID_CLIENTE      INTEGER NOT NULL,
         NOME_CLIENTE    VARCHAR(80) NOT NULL,
         LIMITE_CREDITO  DECIMAL(11,2),
         DATA_CADASTRO   DATE,
         STATUS          CHAR(1)
       ) END-EXEC.

Também gera a estrutura COBOL:

       01  DCLCLIENTE.
           10  ID-CLIENTE          PIC S9(9) COMP.
           10  NOME-CLIENTE.
               49 NOME-CLIENTE-LEN PIC S9(4) COMP.
               49 NOME-CLIENTE-TEXT PIC X(80).
           10  LIMITE-CREDITO      PIC S9(9)V99 COMP-3.
           10  DATA-CADASTRO       PIC X(10).
           10  STATUS-CLIENTE      PIC X(1).

Os nomes e formatos podem variar de acordo com as opções escolhidas.


5.1 Por que o DCLGEN é tão importante?

Sem ele, o programador teria que converter manualmente cada tipo SQL em um formato COBOL.

Exemplos:

INTEGER       -> PIC S9(9) COMP
SMALLINT      -> PIC S9(4) COMP
DECIMAL(9,2)  -> PIC S9(7)V99 COMP-3
CHAR(10)      -> PIC X(10)
DATE          -> PIC X(10)
VARCHAR       -> campo de tamanho + texto

Essa conversão manual pode gerar erros.

Um campo definido incorretamente pode resultar em:

  • truncamento;

  • dados corrompidos;

  • SQLCODE negativo;

  • valores numéricos inválidos;

  • ABEND S0C7;

  • comportamento imprevisível.

O DCLGEN reduz essa possibilidade.


5.2 DCLGEN não substitui governança

Há um detalhe importante.

Gerar o DCLGEN é apenas o começo.

A empresa precisa controlar:

  • onde o copybook será armazenado;

  • qual versão está em produção;

  • quais programas usam aquela estrutura;

  • o que acontece quando a tabela muda;

  • se os programas precisam ser recompilados;

  • se o BIND precisa ser renovado.

Em ambientes maduros, alterações de tabela seguem processos rigorosos.

Não basta alterar uma coluna e esperar que todos os programas se adaptem magicamente.

No mainframe, magia sem controle costuma receber outro nome: incidente.


6. Opção 3 — Program Preparation

A opção 3 é:

3 PROGRAM PREPARATION

Ela reúne etapas necessárias para preparar uma aplicação Db2 para execução.

Um programa COBOL com SQL embutido precisa passar por várias fases:

Fonte COBOL com EXEC SQL
          |
          v
Precompile
          |
          +----> DBRM
          |
          v
Fonte COBOL transformado
          |
          v
Compilação
          |
          v
Objeto
          |
          v
Link-edit
          |
          v
Load module
          |
          v
BIND
          |
          v
Package ou plan

A opção Program Preparation tenta coordenar essas etapas.

É excelente para laboratórios, ambientes educacionais e processos padronizados.

Em grandes empresas, porém, muitas dessas fases são executadas por pipelines, ferramentas de change management ou JCLs corporativos.

Entre as ferramentas modernas ou tradicionais podem aparecer:

  • Endevor;

  • ISPW;

  • Changeman;

  • DBB;

  • Jenkins;

  • GitLab;

  • GitHub Actions;

  • IBM Developer for z/OS;

  • zBuilder.

Mesmo assim, o conceito permanece exatamente o mesmo.


7. Opção 4 — Precompile

A opção 4 chama o precompiler do Db2.

Essa é uma das etapas mais fascinantes.

O compilador COBOL não compreende diretamente uma instrução como:

       EXEC SQL
           SELECT NOME_CLIENTE,
                  LIMITE_CREDITO
             INTO :WS-NOME,
                  :WS-LIMITE
             FROM APP.CLIENTE
            WHERE ID_CLIENTE = :WS-ID
       END-EXEC.

O SQL embutido precisa ser tratado antes da compilação COBOL.

O precompiler percorre o fonte e identifica blocos entre:

EXEC SQL

e:

END-EXEC

Ele separa as instruções SQL e gera dois resultados principais:

  1. Um fonte COBOL modificado.

  2. Um DBRM.


7.1 O que é o DBRM?

DBRM significa:

Database Request Module

Ele contém representações das instruções SQL extraídas do programa.

O DBRM não é o executável.

Ele também não é uma tabela.

Ele é um artefato intermediário utilizado posteriormente no BIND.

Pense nele como um dossiê contendo os pedidos de acesso ao banco feitos pelo programa.

Exemplo conceitual:

Programa: PGMCAD01

SQL 1:
SELECT NOME_CLIENTE
FROM APP.CLIENTE
WHERE ID_CLIENTE = ?

SQL 2:
UPDATE APP.CLIENTE
SET STATUS = ?
WHERE ID_CLIENTE = ?

Esse conjunto de solicitações será analisado pelo Db2 durante o BIND.


7.2 O que acontece com o fonte COBOL?

O SQL é substituído ou acompanhado por chamadas apropriadas à interface do Db2.

O fonte resultante pode conter referências a módulos e estruturas necessárias para a comunicação com o banco.

Depois disso, o compilador COBOL consegue processar o programa.

O fluxo é:

COBOL + SQL
    |
    v
Precompiler Db2
    |
    +----> DBRM
    |
    v
COBOL sem SQL nativo
    |
    v
Compiler

8. SQLCA: o mensageiro do Db2

Quase todo programa COBOL com Db2 possui:

       EXEC SQL
           INCLUDE SQLCA
       END-EXEC.

SQLCA significa:

SQL Communication Area

É uma estrutura usada para receber informações sobre a execução da instrução SQL.

O campo mais famoso é:

SQLCODE

Exemplos:

SQLCODE = 0      sucesso
SQLCODE = 100    nenhuma linha encontrada
SQLCODE = -811   mais de uma linha retornada
SQLCODE = -904   recurso indisponível
SQLCODE = -911   deadlock ou timeout com rollback
SQLCODE = -913   deadlock ou timeout
SQLCODE = -805   package não encontrado
SQLCODE = -818   timestamp inconsistente

Um programa sério deve testar o SQLCODE após cada operação relevante.

Exemplo:

       EXEC SQL
           SELECT NOME_CLIENTE
             INTO :WS-NOME
             FROM APP.CLIENTE
            WHERE ID_CLIENTE = :WS-ID
       END-EXEC.

       EVALUATE SQLCODE
           WHEN 0
               DISPLAY 'CLIENTE ENCONTRADO: ' WS-NOME
           WHEN 100
               DISPLAY 'CLIENTE NAO ENCONTRADO'
           WHEN OTHER
               DISPLAY 'ERRO SQLCODE: ' SQLCODE
       END-EVALUATE.

Ignorar o SQLCODE é como pilotar uma nave sem olhar o painel.

Talvez ela continue voando.

Talvez o motor já esteja em chamas.


9. Opção 5 — BIND, REBIND e FREE

A opção 5 é uma das mais importantes do menu:

5 BIND/REBIND/FREE

Esses três comandos controlam packages e plans.


10. O que é BIND?

O BIND pega o DBRM e cria uma estrutura executável pelo Db2, geralmente um package.

Durante o BIND, o Db2:

  • valida as instruções SQL;

  • verifica objetos referenciados;

  • avalia autorizações;

  • analisa estatísticas;

  • escolhe caminhos de acesso;

  • registra dependências;

  • cria o package;

  • armazena informações no catálogo.

O otimizador decide como acessar os dados.

Ele pode escolher:

  • table space scan;

  • index scan;

  • index-only access;

  • nested loop join;

  • merge scan join;

  • hybrid join;

  • acesso por particionamento;

  • paralelismo.

Duas instruções SQL textualmente iguais podem receber caminhos de acesso diferentes dependendo de:

  • índices;

  • cardinalidade;

  • distribuição de dados;

  • estatísticas;

  • parâmetros de BIND;

  • versão do Db2;

  • nível de função;

  • configuração do subsistema.


10.1 Package e plan

Um package contém a forma preparada das instruções SQL de um programa ou unidade lógica.

Um plan organiza a execução e pode referenciar collections e packages.

No modelo moderno, é comum trabalhar principalmente com packages.

Fluxo simplificado:

Programa COBOL
      |
      v
Package
      |
      v
Collection
      |
      v
Plan
      |
      v
Db2

Nem todas as empresas usam exatamente a mesma convenção, mas o conceito geral permanece.


11. O que é REBIND?

O REBIND recria o package ou plan sem precisar gerar um novo DBRM.

Ele é útil quando:

  • estatísticas foram atualizadas;

  • índices foram criados;

  • índices foram removidos;

  • o volume de dados mudou;

  • houve alteração de parâmetros;

  • o Db2 foi atualizado;

  • deseja-se obter um novo access path.

Exemplo clássico:

RUNSTATS
   |
   v
Novas estatísticas
   |
   v
REBIND
   |
   v
Novo caminho de acesso

O programa COBOL pode permanecer o mesmo.

O executável pode permanecer o mesmo.

Mas o Db2 pode escolher uma estratégia diferente para acessar os dados.

Esse desacoplamento é uma das maiores forças da arquitetura Db2.


12. O que é FREE?

FREE remove packages ou plans do catálogo.

É uma operação poderosa e potencialmente perigosa.

Se você remover um package necessário, o programa poderá falhar com erro semelhante ao:

SQLCODE -805

Esse erro normalmente indica que o package esperado não foi encontrado, não está disponível na collection correta ou não corresponde ao que o programa está tentando usar.

Nunca execute FREE por curiosidade em ambiente corporativo.

Curiosidade é excelente para estudar.

Em produção, curiosidade sem mudança aprovada pode virar RCA.


13. Opção 6 — RUN

A opção 6 permite executar um programa SQL.

Dependendo da instalação, o painel solicita:

  • nome do programa;

  • plan;

  • parâmetros;

  • bibliotecas de carga;

  • datasets;

  • ambiente;

  • opções de execução.

Essa função é bastante útil para testes.

Em ambientes reais, programas batch normalmente são executados por JCL.

Um exemplo conceitual:

//RUNDB2   JOB ...
//STEP01   EXEC PGM=IKJEFT01
//STEPLIB  DD DISP=SHR,DSN=APP.LOADLIB
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSTSIN  DD *
  DSN SYSTEM(DB9G)
  RUN PROGRAM(PGMCAD01) PLAN(PLANAPP) -
      LIB('APP.LOADLIB')
  END
/*

O exemplo exato varia conforme o ambiente.

O programa pode também ser executado em:

  • CICS;

  • IMS;

  • stored procedure;

  • WLM;

  • batch;

  • TSO;

  • z/OS Unix;

  • aplicações distribuídas.


14. Opção 7 — Db2 Commands

A opção 7 permite emitir comandos administrativos do Db2.

Exemplos:

-DISPLAY DATABASE
-DISPLAY THREAD
-DISPLAY UTILITY
-DISPLAY BUFFERPOOL
-START DATABASE
-STOP DATABASE
-RECOVER INDOUBT

Esses comandos não são SQL.

Eles são comandos do subsistema Db2.

Por exemplo:

-DISPLAY DATABASE(APPDB)

Pode mostrar o estado dos objetos relacionados ao banco.

Outro exemplo:

-DISPLAY THREAD(*)

Pode exibir threads conectadas.

Essas funções geralmente são controladas por autorização.

Um programador comum talvez possa executar alguns comandos de consulta, mas não terá autoridade para iniciar, parar ou alterar recursos críticos.

E isso é saudável.

Segurança não é um obstáculo.

É o cinto de segurança da operação.


15. Opção 8 — Utilities

Os utilitários do Db2 são responsáveis por diversas tarefas essenciais de manutenção.

Entre os principais:

LOAD
UNLOAD
REORG
RUNSTATS
COPY
RECOVER
CHECK DATA
CHECK INDEX
REBUILD INDEX
QUIESCE
MODIFY RECOVERY

15.1 RUNSTATS

Coleta estatísticas sobre:

  • quantidade de linhas;

  • cardinalidade;

  • distribuição;

  • frequência;

  • índices;

  • colunas;

  • partições.

O otimizador usa essas informações para escolher access paths.

Estatística desatualizada pode levar a decisões ruins.

É como usar um mapa de uma cidade de 1995 para dirigir em 2026.

Algumas ruas ainda existem.

Outras viraram avenidas, túneis, condomínios e rotatórias criadas por alguém que parecia gostar muito de rotatórias.


15.2 REORG

Reorganiza os dados fisicamente.

Pode ajudar a:

  • reduzir fragmentação;

  • recuperar espaço;

  • melhorar clustering;

  • restaurar organização física;

  • tratar estados pendentes;

  • melhorar acesso.


15.3 COPY

Cria cópias de imagem para recuperação.

Sem cópias adequadas, uma falha pode se tornar uma tragédia operacional.


15.4 RECOVER

Restaura objetos após falhas ou perda de dados.

Pode utilizar:

  • image copies;

  • logs;

  • pontos de recuperação;

  • informações do catálogo.


15.5 LOAD

Carrega grandes volumes de dados com eficiência.

É muito mais apropriado para cargas massivas do que executar milhões de INSERTs individuais.


16. Opção D — DB2I Defaults

A opção D permite configurar padrões utilizados pelo DB2I.

Podem existir parâmetros para:

  • nomes de datasets;

  • classes de job;

  • opções de saída;

  • SQL terminator;

  • parâmetros de execução;

  • bibliotecas;

  • identificadores;

  • formato dos resultados.

Esses defaults economizam tempo.

Em vez de digitar os mesmos valores em todos os painéis, o usuário configura uma vez e reaproveita.

Porém, sempre revise os parâmetros antes de executar.

Um default antigo pode apontar para:

  • SSID incorreto;

  • biblioteca obsoleta;

  • plan antigo;

  • collection inadequada;

  • dataset inexistente.

Automação ajuda.

Automação desatualizada ajuda a errar mais rápido.


17. Passo a passo completo: criando um programa COBOL com Db2

Agora vamos juntar tudo.

Imagine um programa que consulta o nome de um cliente.


Passo 1 — Criar o DCLGEN

Use a opção 2.

Informe:

TABLE OWNER: APP
TABLE NAME: CLIENTE

Defina o dataset de saída:

VAGNER.COBOL.COPYLIB(DCLCLI)

O DCLGEN será gerado.


Passo 2 — Escrever o programa COBOL

Exemplo simplificado:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PGCLI001.

       DATA DIVISION.
       WORKING-STORAGE SECTION.

       EXEC SQL
           INCLUDE SQLCA
       END-EXEC.

       EXEC SQL
           INCLUDE DCLCLI
       END-EXEC.

       01  WS-ID-CLIENTE      PIC S9(9) COMP VALUE 100.
       01  WS-NOME-CLIENTE    PIC X(80).

       PROCEDURE DIVISION.

           EXEC SQL
               SELECT NOME_CLIENTE
                 INTO :WS-NOME-CLIENTE
                 FROM APP.CLIENTE
                WHERE ID_CLIENTE = :WS-ID-CLIENTE
           END-EXEC

           EVALUATE SQLCODE
               WHEN 0
                   DISPLAY 'CLIENTE: ' WS-NOME-CLIENTE
               WHEN 100
                   DISPLAY 'CLIENTE NAO ENCONTRADO'
               WHEN OTHER
                   DISPLAY 'ERRO SQL: ' SQLCODE
           END-EVALUATE

           GOBACK.

Passo 3 — Precompile

Use a opção 4 ou Program Preparation.

Entradas:

Fonte COBOL
DBRM library
Copy library
Parâmetros SQL

Saídas:

Fonte COBOL modificado
DBRM
Listing
Mensagens

Verifique erros de sintaxe SQL.


Passo 4 — Compilar

O fonte modificado segue para o Enterprise COBOL.

O compilador gera:

Object deck
Compiler listing
Mensagens

Corrija qualquer erro COBOL.


Passo 5 — Link-edit

O objeto é transformado em load module ou program object.

Ele será armazenado em uma biblioteca de carga.

Exemplo:

VAGNER.APP.LOADLIB

Passo 6 — BIND PACKAGE

Use a opção 5.

Informe:

DBRM: PGCLI001
COLLECTION: APPDEV
PACKAGE: PGCLI001
OWNER: VAGNER
QUALIFIER: APP

Parâmetros comuns podem incluir:

ACTION(REPLACE)
ISOLATION(CS)
VALIDATE(BIND)
RELEASE(COMMIT)
CURRENTDATA(NO)

Os parâmetros exatos dependem dos padrões da empresa.


Passo 7 — BIND PLAN

Caso o ambiente utilize plan explícito para a execução, associe a package list ou collection.

Exemplo conceitual:

PLAN: PLANAPP
PKLIST: APPDEV.*

Passo 8 — Executar

Use a opção 6 ou submeta o JCL.

Observe:

  • retorno do job;

  • SQLCODE;

  • mensagens;

  • dumps;

  • saídas;

  • tempo de CPU;

  • quantidade de linhas.


18. Erros clássicos do padawan

SQLCODE -805

Package não encontrado.

Possíveis causas:

  • BIND não executado;

  • collection errada;

  • plan incorreto;

  • package removido;

  • versão incompatível.


SQLCODE -818

Incompatibilidade de timestamp entre programa e package.

Pode acontecer quando o programa foi recompilado, mas o package não foi gerado de forma correspondente.

A solução geralmente envolve sincronizar:

Precompile
Compile
Link-edit
Bind

SQLCODE -811

Um SELECT INTO retornou mais de uma linha.

Exemplo perigoso:

SELECT NOME_CLIENTE
INTO :WS-NOME
FROM APP.CLIENTE
WHERE STATUS = 'A';

Se existem mil clientes ativos, o Db2 não sabe qual retornar.

Use chave única, agregação ou cursor.


SQLCODE +100

Nenhuma linha encontrada.

Não é necessariamente erro.

Pode ser uma condição normal de negócio.


SQLCODE -911

Deadlock ou timeout com rollback.

O programa perdeu uma disputa por recurso e a unidade de trabalho foi desfeita.

É necessário avaliar:

  • ordem de acesso;

  • tempo entre commits;

  • índices;

  • isolamento;

  • concorrência;

  • volume de processamento.


19. Curiosidades históricas

O DB2I carrega a filosofia de uma época em que memória, largura de banda e espaço de tela eram recursos valiosos.

Por isso, seus painéis são diretos.

Não existem animações.

Não existem botões brilhantes.

Não existem notificações perguntando se você gostaria de conhecer cinco novidades.

Existe uma linha de comando, campos objetivos e uma tecla Enter.

Essa simplicidade ajudou o ambiente a permanecer produtivo por décadas.

Outra curiosidade é que muitos profissionais que começaram no Db2 em versões antigas ainda reconhecem imediatamente o menu.

Os detalhes evoluíram.

O banco ganhou novos tipos, novos níveis de função, novas capacidades e otimizações.

Mas a lógica fundamental continua familiar.

Isso é compatibilidade cultural.

Não apenas compatibilidade técnica.


20. Easter egg Bellacosa Mainframe

Vamos transformar a jornada em uma aventura galáctica.

O programa COBOL é um jovem Jedi.

O DCLGEN entrega o mapa da estrutura do planeta-tabela.

O precompiler é C-3PO, traduzindo SQL para uma linguagem compreendida pela infraestrutura.

O DBRM é o pergaminho contendo todas as missões de acesso ao banco.

O compilador COBOL treina o guerreiro.

O link-editor entrega o sabre de luz.

O BIND apresenta a missão ao Conselho Jedi.

O otimizador decide a rota: índice, scan, join, paralelismo.

O package é a autorização oficial.

O plan é o plano de batalha.

O SQLCA é o comunicador preso ao cinto.

E o SQLCODE informa se a missão foi cumprida ou se o grupo acabou preso em um compactador de lixo da Estrela da Morte.

O mais importante é compreender que nenhuma etapa existe por acaso.

O mainframe não gosta de improviso.

Ele gosta de processos repetíveis, auditáveis e previsíveis.

Essa disciplina é uma das razões pelas quais sistemas IBM Z sustentam bancos, governos, seguradoras, companhias aéreas, indústrias e cadeias globais de negócios.


Conclusão

A tela do DB2I pode parecer modesta, mas ela concentra uma quantidade impressionante de conhecimento.

Por trás de suas opções existem:

  • linguagens;

  • compiladores;

  • catálogos;

  • packages;

  • plans;

  • access paths;

  • estatísticas;

  • segurança;

  • recuperação;

  • concorrência;

  • utilitários;

  • JCL;

  • datasets;

  • décadas de engenharia.

Dominar o DB2I não significa apenas aprender a navegar em um menu.

Significa compreender o ciclo de vida de uma aplicação Db2 no z/OS.

O programador COBOL padawan que aprende apenas a escrever SELECT conhece a superfície.

O profissional que compreende precompile, DBRM, BIND, package, plan, SQLCA, utilitários e access path começa a enxergar o sistema inteiro.

E é nesse momento que a velha tela preta deixa de parecer antiga.

Ela passa a parecer aquilo que realmente é:

Um painel de controle compacto para uma das plataformas de dados mais robustas já construídas pela indústria da computação.

Portanto, na próxima vez que você entrar no DB2I e enxergar suas opções em ciano, não veja apenas números.

Veja uma linha de produção.

Veja o SQL sendo extraído.

Veja o DBRM sendo criado.

Veja o compilador trabalhando.

Veja o otimizador avaliando caminhos.

Veja o package sendo autorizado.

Veja o programa entrando em execução.

Porque, no IBM Z, quase sempre existe muito mais acontecendo por trás da tela do que o terminal permite enxergar.

E essa, jovem padawan, é parte da beleza do mainframe.