Translate

quinta-feira, 20 de outubro de 2022

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

 

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 SELECT simples;

  • 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