1. DBD completo — todas as macros
O DBD é escrito em assembler usando macros IBM e compilado pelo utilitário DBDGEN. O resultado é um módulo em IMS.DBDLIB que o IMS carrega quando o banco é aberto.
PRINT NOGEN
*
* DBD do banco de clientes - organização HDAM
*
DBD NAME=BANCOCLI, NOME DO BANCO (8 chars) X
ACCESS=HDAM TIPO DE ORGANIZACAO
*
* Dataset group: define o arquivo VSAM que armazena o banco
*
DATASET DD1=BANCOCLID, DDNAME no JCL X
DEVICE=3390, TIPO DE DISPOSITIVO X
SIZE=4096 TAMANHO DO BLOCO FISICO
*
* RANDOMIZER: funcao de hash para HDAM
*
RMNAME NAME=DFSHDC40, MODULO RANDOMIZADOR IBM X
NUMENTRIES=50000, NUMERO RAIZ ESTIMADO X
NUMBLOCKS=10, BLOCOS POR RAIZ X
BYTESLEFT=5 BYTES LIVRES NO ROOT ANCHOR
*
* SEGMENTO RAIZ: CLIENTE
*
SEGM NAME=CLIENTE, NOME (8 chars) X
BYTES=80, TAMANHO EM BYTES X
PARENT=0, 0 = SEGMENTO RAIZ X
PTR=T TWIN FORWARD POINTER
FIELD NAME=(CLICPF,SEQ,U), SEQUENCE FIELD UNICO X
BYTES=11, COMPRIMENTO X
START=1, POSICAO NO SEGMENTO (1-base) X
TYPE=P TIPO: P=PACKED DECIMAL
FIELD NAME=CLINOME, CAMPO NOME X
BYTES=40,START=12,TYPE=C
FIELD NAME=CLINASC, DATA NASCIMENTO X
BYTES=8,START=52,TYPE=P
FIELD NAME=CLITIPO, F=FISICO / J=JURIDICO X
BYTES=1,START=60,TYPE=C
*
* SEGMENTO FILHO: CONTA
*
SEGM NAME=CONTA, X
BYTES=60, X
PARENT=((CLIENTE,SNGL)) PAI = CLIENTE, PTR=SNGL
FIELD NAME=(CTANUM,SEQ,U), NUMERO DA CONTA (CHAVE) X
BYTES=10,START=1,TYPE=C
FIELD NAME=CTATIPO,BYTES=2,START=11,TYPE=C
FIELD NAME=CTASLDO,BYTES=8,START=13,TYPE=P
FIELD NAME=CTASTTS,BYTES=1,START=29,TYPE=C
*
* SEGMENTO NETO: MOVIMENT
*
SEGM NAME=MOVIMENT, X
BYTES=30, X
PARENT=((CONTA,SNGL)) PAI = CONTA
FIELD NAME=(MOVDATA,SEQ), DATA (NAO UNICA - twins) X
BYTES=8,START=1,TYPE=P
FIELD NAME=MOVVALOR,BYTES=8,START=9,TYPE=P
FIELD NAME=MOVTIPO,BYTES=1,START=17,TYPE=C
*
DBDGEN GERA O DBD
FINISH
END
2. SEGM — definindo segmentos
A macro SEGM define cada tipo de segmento da hierarquia. Seus parâmetros controlam tamanho, relacionamento com o pai e tipo de ponteiro usado internamente.
| Parâmetro SEGM | Valores | Significado |
|---|---|---|
| NAME | 1–8 chars | Nome do tipo de segmento — usado nos SSAs do programa |
| BYTES | 1–32767 | Comprimento máximo em bytes. Para segmentos de tamanho variável, use BYTES=(min,max) |
| PARENT | 0 ou nome | 0 = segmento raiz. Nome = pai direto na hierarquia |
| PTR | T, TB, TF, TFB, SNGL, SNGLB, DBLE, DBLEB | Tipo de ponteiro físico. T = twin forward. SNGL = forward only. DBLE = forward + backward |
| RULES | R, LAST, HERE | Regra de inserção de novos twins. R = pela chave (default). LAST = sempre no fim. HERE = na posição atual |
| FREQ | Número | Estimativa de número médio de ocorrências por pai — ajuda o IMS a alocar buffers |
SNGL (ponteiro só para o próximo twin) é mais eficiente em espaço e funciona bem para varredura sequencial. DBLE (ponteiro para próximo e anterior) permite GHN + DLET sem precisar reposicionar do pai, mas usa 8 bytes extras de ponteiro por segmento. T (twin) é o mais comum em HDAM — armazena ponteiro forward no próprio segmento.
3. FIELD — definindo campos e sequence field
A macro FIELD define cada campo dentro de um segmento. O campo de sequência (SEQ) é especial — determina a ordem dos twins e é o campo usado nos SSAs qualificados.
| Parâmetro FIELD | Valores | Significado |
|---|---|---|
| NAME | (nome,SEQ,U) ou (nome,SEQ,M) ou nome | Nome do campo (8 chars). SEQ = campo de sequência. U = único. M = múltiplo (twins com mesmo valor permitidos) |
| BYTES | 1–255 | Comprimento em bytes |
| START | 1–n | Posição inicial dentro do segmento (começa em 1) |
| TYPE | C, P, Z, X, F, H | C=character, P=packed decimal, Z=zoned decimal, X=hexadecimal, F=fullword binary, H=halfword binary |
* Campo de chave único (SEQ,U) - CHARACTER
FIELD NAME=(CTANUM,SEQ,U),BYTES=10,START=1,TYPE=C
* Campo de chave não-único (SEQ,M) - PACKED DECIMAL
* Permite twins com mesma data (vários movimentos no mesmo dia)
FIELD NAME=(MOVDATA,SEQ,M),BYTES=8,START=1,TYPE=P
* Campo normal sem SEQ - ZONED DECIMAL (display numérico)
FIELD NAME=CLIIDADE,BYTES=3,START=61,TYPE=Z
* Campo binário FULLWORD (4 bytes)
FIELD NAME=CLIFLAGS,BYTES=4,START=64,TYPE=F
* Campo sem definição explícita de TYPE - padrão é C
FIELD NAME=CLIEMAIL,BYTES=50,START=30
Você não precisa definir FIELD para cada byte do segmento — apenas para os campos que serão usados em SSAs qualificados ou que o DBA quer documentar. Os bytes não cobertos por um FIELD são acessíveis ao programa COBOL através da área de dados do segmento, mas o IMS não os conhece pelo nome.
4. LCHILD e XDFLD — índice secundário no DBD
O IMS suporta índice secundário — acesso a um segmento por um campo que não é o sequence field. A definição envolve dois DBDs: o DBD do banco original (com LCHILD e XDFLD) e um DBD especial do índice.
* No banco BANCOCLI, queremos acessar CLIENTE por CLINOME
* além do acesso primário por CLICPF
SEGM NAME=CLIENTE,BYTES=80,PARENT=0
FIELD NAME=(CLICPF,SEQ,U),BYTES=11,START=1,TYPE=P
FIELD NAME=CLINOME,BYTES=40,START=12,TYPE=C
*
* LCHILD: aponta para o DBD do índice secundário
*
LCHILD NAME=(CLINOMIDX,BANCOCLII), SEGM,DBD DO INDICE X
POINTER=INDX, TIPO INDIRETO X
RULES=LAST
*
* XDFLD: define o campo indexado e a chave no índice
*
XDFLD NAME=CLINOMX, NOME LOGICO X
SRCH=CLINOME, CAMPO DE BUSCA X
SEGMENT=CLIENTE, SEGMENTO ONDE ESTA X
SUBSEQ=CLICPF DESEMPATE = CHAVE PRIM
DBD NAME=BANCOCLII,ACCESS=INDEX
DATASET DD1=BANCLIID,DEVICE=3390,SIZE=4096
SEGM NAME=CLINOMIDX,BYTES=51,PARENT=0
FIELD NAME=(CLINOMX,SEQ,M),BYTES=40,START=1,TYPE=C
FIELD NAME=CLICPFX,BYTES=11,START=41,TYPE=P
DBDGEN
FINISH
END
5. ACCESS — tipos de organização física
| ACCESS | Nome | Dataset VSAM | Acesso root | Quando usar |
|---|---|---|---|---|
| HDAM | Hierarchical Direct | ESDS (data) + ESDS (overflow) | Hash direto | Acesso aleatório dominante — o mais comum em produção |
| HIDAM | Hierarchical Indexed Direct | KSDS (index) + ESDS (data) | Índice B+ | Acesso sequencial por chave importa; grandes bancos |
| HISAM | Hierarchical Indexed Sequential | KSDS (primário) + ESDS (overflow) | KSDS | Bancos pequenos; acesso misto mas predominantemente sequencial |
| HSAM | Hierarchical Sequential | QSAM (sequencial) | Sequencial | Tape ou datasets de arquivo; raramente novo hoje |
| SHDAM | Simple HDAM | ESDS | Hash direto | Variante do HDAM sem overflow separado; bancos menores |
| INDEX | Secondary Index | KSDS | Índice B+ | Exclusivo para DBDs de índice secundário |
6. PSB completo — todas as macros
O PSB (Program Specification Block) define a visão do programa sobre um ou mais bancos. Um PSB contém um ou mais PCBs — cada PCB aponta para um DBD e define quais segmentos o programa pode acessar e com quais permissões.
PRINT NOGEN
*
* PCB 1: acesso ao banco de clientes (leitura e atualização)
*
PCB TYPE=DB, TIPO BANCO X
DBDNAME=BANCOCLI, NOME DO DBD X
KEYLEN=21, KEYLEN (ver secao 10) X
PROCOPT=A A = TODAS AS OPERACOES
SENSEG NAME=CLIENTE, SEGMENTO SENSIVELX
PROCOPT=A
SENSEG NAME=CONTA, FILHO CONTA X
PROCOPT=A
SENSEG NAME=MOVIMENT, NETO MOVIMENT X
PROCOPT=GD APENAS LEITURA E DELETE
*
* PCB 2: acesso pelo indice secundario de nome
*
PCB TYPE=DB, X
DBDNAME=BANCOCLII, DBD DO INDICE X
KEYLEN=51, KEYLEN DO INDICE X
PROCOPT=G SO LEITURA VIA INDICE
SENSEG NAME=CLINOMIDX,PROCOPT=G
*
* Gera o PSB para COBOL
*
PSBGEN LANG=COBOL,PSBNAME=PGMBANKI
END
O PSB é o que o programa "assina" quando é carregado pelo IMS. Ele diz exatamente: "este programa pode ler CLIENTE, ler/inserir/atualizar/deletar CONTA, só ler e deletar MOVIMENT". O IMS verifica o PSB em cada DL/I call — qualquer tentativa de operação não autorizada retorna status AM (access method error).
7. PROCOPT — tabela completa de opções
PROCOPT (Processing Option) aparece em dois lugares: no PCB (opção geral do banco) e no SENSEG (opção por segmento individual). O SENSEG refina o que o PCB permite.
| PROCOPT | Calls DL/I permitidas | Descrição |
|---|---|---|
| G | GU, GN, GNP | Get only — somente leitura. Mais restritivo. |
| GU | GU somente | Apenas Get Unique — sem GN ou GNP |
| I | ISRT | Insert only — apenas inserção, sem leitura prévia |
| D | GHU, GHN, GHNP, DLET | Delete — inclui Get Hold para posicionamento |
| R | GHU, GHN, GHNP, REPL | Replace — inclui Get Hold para posicionamento |
| A | Todas | All — G + I + D + R. Acesso completo. |
| GO | GU, GN, GNP (sem lock) | Get Optional — leitura sem lock (não bloqueia escritores) |
| GR | GU, GN, GNP, REPL | Get + Replace |
| GD | GU, GN, GNP, DLET (+ hold) | Get + Delete |
| LS | GU, GN, GNP | Load Sequential — para carga inicial de banco |
* PCB com PROCOPT=A mas restringindo segmentos individuais
PCB TYPE=DB,DBDNAME=BANCOCLI,KEYLEN=21,PROCOPT=A
*
* CLIENTE: só leitura (programa não altera dados cadastrais)
SENSEG NAME=CLIENTE,PROCOPT=G
*
* CONTA: leitura e atualização (atualiza saldo)
SENSEG NAME=CONTA,PROCOPT=GR
*
* MOVIMENT: leitura e inserção (nunca deleta movimentos)
SENSEG NAME=MOVIMENT,PROCOPT=GI
O PROCOPT no PCB é o limite superior de permissão. O SENSEG só pode restringir, nunca ampliar. Se o PCB tem PROCOPT=G (somente leitura) e um SENSEG tem PROCOPT=A, o IMS honra apenas G — o SENSEG não pode dar mais permissão que o PCB. Na prática: defina PROCOPT=A no PCB e use SENSEG para restringir segmentos específicos.
8. Múltiplos PCBs num mesmo PSB
Um PSB pode conter vários PCBs — um para cada banco que o programa acessa. No COBOL, cada PCB corresponde a um item na LINKAGE SECTION, e todos aparecem no ENTRY 'DLITCBL' USING.
LINKAGE SECTION.
*
* PCB 1 — banco principal de clientes
01 PCB-BANCOCLI.
05 PCB-DBD-NAME PIC X(08).
05 PCB-SEG-LEVEL PIC XX.
05 PCB-STATUS PIC XX.
05 PCB-PROC-OPT PIC X(04).
05 FILLER PIC X(04).
05 PCB-SEG-NAME PIC X(08).
05 PCB-KEY-LEN PIC S9(05) COMP.
05 PCB-NUMB-SENS PIC S9(05) COMP.
05 PCB-KEY-FDBK PIC X(21).
* PCB 2 — índice secundário de nome
01 PCB-INDICE.
05 PCB-I-DBD-NAME PIC X(08).
05 PCB-I-SEG-LEVEL PIC XX.
05 PCB-I-STATUS PIC XX.
05 PCB-I-PROC-OPT PIC X(04).
05 FILLER PIC X(04).
05 PCB-I-SEG-NAME PIC X(08).
05 PCB-I-KEY-LEN PIC S9(05) COMP.
05 PCB-I-NUMB-SENS PIC S9(05) COMP.
05 PCB-I-KEY-FDBK PIC X(51).
PROCEDURE DIVISION.
* Todos os PCBs listados na ordem do PSB
ENTRY 'DLITCBL' USING PCB-BANCOCLI
PCB-INDICE.
0000-PRINCIPAL.
* Busca por nome via PCB-INDICE
CALL 'CBLTDLI' USING
WS-SSA-1 WS-FUNC-GU PCB-INDICE
WS-SEG-IDXNOME WS-SSA-IDX-NOME
* Agora usa a chave primária recuperada para buscar no banco real
MOVE IDX-CPF TO SSA-CLI-CPF
CALL 'CBLTDLI' USING
WS-SSA-1 WS-FUNC-GU PCB-BANCOCLI
WS-SEG-CLIENTE WS-SSA-CLI-QUAL.
9. PCB mask — todos os campos
A PCB mask é a estrutura que o IMS atualiza após cada DL/I call. Conhecer todos os seus campos permite extrair informações detalhadas sobre cada operação.
| Campo | PIC | Conteúdo após a call |
|---|---|---|
| DBD-NAME | PIC X(08) | Nome do DBD que o PCB está acessando |
| SEG-LEVEL | PIC XX | Nível hierárquico do segmento retornado (01, 02, 03...) |
| STATUS | PIC XX | Código de status da call (espaços = sucesso, GE, GB, etc.) |
| PROC-OPT | PIC X(04) | PROCOPT definido no PSB para este PCB |
| FILLER | PIC X(04) | Reservado — não usar |
| SEG-NAME | PIC X(08) | Nome do tipo de segmento acessado na última call |
| KEY-LENGTH | PIC S9(05) COMP | Comprimento da concatenated key no campo KEY-FEEDBACK |
| NUMB-SENS-SEGS | PIC S9(05) COMP | Número de segmentos sensitivos definidos no PCB |
| KEY-FEEDBACK | PIC X(n) — n = KEYLEN | Concatenated key: chaves de todos os segmentos no caminho desde o root até o segmento atual |
Usando KEY-FEEDBACK para diagnóstico
O KEY-FEEDBACK contém as chaves concatenadas de todos os segmentos no caminho hierárquico até o segmento atual. É a "trilha de pão" do IMS — mostra exatamente onde você está na hierarquia.
* Após GU bem-sucedido em MOVIMENT (3 níveis):
* KEY-FDBK contém:
* [CPF do cliente (11 bytes)] [NUM conta (10 bytes)] [DATA mov (8 bytes)]
01 PCB-BANCO.
05 PCB-DBD-NAME PIC X(08).
05 PCB-SEG-LEVEL PIC XX.
05 PCB-STATUS PIC XX.
05 PCB-PROC-OPT PIC X(04).
05 FILLER PIC X(04).
05 PCB-SEG-NAME PIC X(08).
05 PCB-KEY-LEN PIC S9(05) COMP.
05 PCB-NUMB-SENS PIC S9(05) COMP.
05 PCB-KEY-FDBK.
10 KF-CLI-CPF PIC 9(11). -- chave do CLIENTE
10 KF-CTA-NUM PIC X(10). -- chave da CONTA
10 KF-MOV-DATA PIC 9(08). -- chave do MOVIMENT
PROCEDURE DIVISION.
1000-LER-MOVIMENT.
CALL 'CBLTDLI' USING
WS-SSA-3 WS-FUNC-GU PCB-BANCO
WS-SEG-MOVIMENT
WS-SSA-CLI-QUAL
WS-SSA-CTA-QUAL
WS-SSA-MOV-QUAL
IF PCB-STATUS = SPACES
DISPLAY 'CLIENTE CPF : ' KF-CLI-CPF
DISPLAY 'CONTA NUM : ' KF-CTA-NUM
DISPLAY 'MOVIMENTO : ' KF-MOV-DATA
DISPLAY 'SEGMENTO : ' PCB-SEG-NAME
DISPLAY 'NIVEL : ' PCB-SEG-LEVEL
END-IF.
10. KEYLEN — calculando o valor correto
KEYLEN no PCB especifica o tamanho máximo da concatenated key — a soma dos sequence fields de todos os segmentos no caminho mais longo do root até o segmento mais profundo acessado pelo PCB. O IMS usa isso para alocar o buffer do KEY-FEEDBACK.
Hierarquia:
CLIENTE — sequence field CLICPF = 11 bytes (packed, 6 bytes físicos)
CONTA — sequence field CTANUM = 10 bytes (character)
MOVIMENT — sequence field MOVDATA = 8 bytes (packed, 5 bytes físicos)
KEYLEN = BYTES de cada sequence field (tamanho lógico, não físico)
= 11 + 10 + 8 = 29 bytes... mas o IMS usa regras de arredondamento:
Regra: KEYLEN = soma dos comprimentos definidos em BYTES= no FIELD SEQ
= 11 (CLICPF) + 10 (CTANUM) + 8 (MOVDATA) = 29
Convenção segura: arredondar para cima ao próximo múltiplo ímpar
ou simplesmente usar 21 (se KEY-FEEDBACK for CHARACTER concatenado)
Na prática: consulte o DBA ou use KEYLEN gerado automaticamente.
Um KEYLEN maior que o necessário não causa erro — apenas aloca um pouco mais de memória. Um KEYLEN menor que o necessário faz o IMS truncar o KEY-FEEDBACK. A prática mais segura é somar os BYTES de todos os sequence fields no caminho mais longo e adicionar 1 como margem.
11. DBDGEN, PSBGEN e ACBGEN
DBD e PSB são escritos em assembler mas nunca rodados diretamente — eles passam por utilitários que os compilam em módulos binários usados pelo IMS em runtime.
//DBDGEN JOB (ACCT),'DBDGEN',CLASS=A,MSGCLASS=X //STEP1 EXEC PGM=ASMA90, // PARM='DECK,NOOBJECT' //SYSLIB DD DSN=IMS.SDFSMAC,DISP=SHR -- macros IMS //SYSPRINT DD SYSOUT=* //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(2,1)) //SYSUT2 DD UNIT=SYSDA,SPACE=(CYL,(2,1)) //SYSUT3 DD UNIT=SYSDA,SPACE=(CYL,(2,1)) //SYSPUNCH DD DSN=&&OBJDBD,DISP=(NEW,PASS), // SPACE=(CYL,(1,1)) //SYSIN DD DSN=PROD.IMS.SOURCE(BANCOCLI),DISP=SHR //* //STEP2 EXEC PGM=IEBGENER //SYSPRINT DD SYSOUT=* //SYSUT1 DD DSN=&&OBJDBD,DISP=(OLD,DELETE) //SYSUT2 DD DSN=IMS.DBDLIB(BANCOCLI),DISP=SHR //SYSIN DD DUMMY
//PSBGEN JOB (ACCT),'PSBGEN',CLASS=A,MSGCLASS=X //STEP1 EXEC PGM=ASMA90, // PARM='DECK,NOOBJECT' //SYSLIB DD DSN=IMS.SDFSMAC,DISP=SHR //SYSPRINT DD SYSOUT=* //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(2,1)) //SYSUT2 DD UNIT=SYSDA,SPACE=(CYL,(2,1)) //SYSUT3 DD UNIT=SYSDA,SPACE=(CYL,(2,1)) //SYSPUNCH DD DSN=&&OBJPSB,DISP=(NEW,PASS), // SPACE=(CYL,(1,1)) //SYSIN DD DSN=PROD.IMS.SOURCE(PGMBANKI),DISP=SHR //* //STEP2 EXEC PGM=IEBGENER //SYSPRINT DD SYSOUT=* //SYSUT1 DD DSN=&&OBJPSB,DISP=(OLD,DELETE) //SYSUT2 DD DSN=IMS.PSBLIB(PGMBANKI),DISP=SHR //SYSIN DD DUMMY
//ACBGEN JOB (ACCT),'ACBGEN',CLASS=A,MSGCLASS=X //STEP1 EXEC PGM=DFSRRC00, // PARM='UPB,ACBGEN' //STEPLIB DD DSN=IMS.RESLIB,DISP=SHR //IMS DD DSN=IMS.PSBLIB,DISP=SHR // DD DSN=IMS.DBDLIB,DISP=SHR //IMSACB DD DSN=IMS.ACBLIB,DISP=SHR //SYSPRINT DD SYSOUT=* //SYSIN DD * BUILD PSB(PGMBANKI) /*
Pense no DBD como código-fonte (assembler), o DBDGEN como compilador (gera módulo em DBDLIB), e o ACBGEN como o linker (combina DBD + PSB num ACB em ACBLIB que o IMS carrega em milissegundos na abertura do banco). Qualquer mudança no DBD ou PSB exige reexecutar DBDGEN/PSBGEN e depois ACBGEN antes que o programa veja a mudança.
12. Índice secundário — acesso por campo não-chave
O índice secundário do IMS permite que um programa acesse segmentos por um campo que não é o sequence field primário. O fluxo é: buscar no banco de índice pelo campo secundário → obter a chave primária → buscar no banco principal pela chave primária.
* Área do segmento índice
01 WS-SEG-IDX.
05 IDX-NOME PIC X(40).
05 IDX-CPF PIC 9(11).
* SSA para busca no índice por nome
01 WS-SSA-IDX-NOME.
05 FILLER PIC X(08) VALUE 'CLINOMIDX'.
05 FILLER PIC X(01) VALUE '('.
05 FILLER PIC X(08) VALUE 'CLINOMX '.
05 FILLER PIC X(02) VALUE '= '.
05 SSA-NOME PIC X(40).
05 FILLER PIC X(01) VALUE ')'.
2000-BUSCA-POR-NOME.
MOVE 'MARIA SILVA '
TO SSA-NOME
* Passo 1: busca no banco índice (PCB-INDICE)
CALL 'CBLTDLI' USING
WS-SSA-1 WS-FUNC-GU PCB-INDICE
WS-SEG-IDX WS-SSA-IDX-NOME
EVALUATE PCB-I-STATUS
WHEN SPACES
CONTINUE
WHEN 'GE'
DISPLAY 'NOME NAO ENCONTRADO'
GOBACK
WHEN OTHER
PERFORM 9999-ERRO-IMS
END-EVALUATE
* Passo 2: usa CPF retornado pelo índice para buscar no banco real
MOVE IDX-CPF TO SSA-CLI-CPF
CALL 'CBLTDLI' USING
WS-SSA-1 WS-FUNC-GU PCB-BANCOCLI
WS-SEG-CLIENTE WS-SSA-CLI-QUAL
IF PCB-STATUS = SPACES
DISPLAY 'CLIENTE ENCONTRADO: ' CLI-NOME
' CPF: ' CLI-CPF
END-IF.
O índice secundário do IMS não é transparente — o programa precisa explicitamente acessar o banco de índice (PCB-INDICE) para obter a chave primária e depois acessar o banco real (PCB-BANCOCLI). Isso é diferente do DB2, onde um índice secundário é transparente ao SQL. A vantagem do IMS é controle explícito e previsibilidade de performance; a desvantagem é código mais verboso.
Resumo do fluxo completo: DBD a runtime
DBA escreve:
BANCOCLI.asm (DBD source) → DBDGEN → IMS.DBDLIB(BANCOCLI)
PGMBANKI.asm (PSB source) → PSBGEN → IMS.PSBLIB(PGMBANKI)
↓
ACBGEN
↓
IMS.ACBLIB(PGMBANKI)
↓
Programador compila:
PGMCRUD.cbl → compilador COBOL → IMS.LOADLIB(PGMCRUD)
↓
IMS em runtime:
JCL executa DFSRRC00 com PARM='DLI,PGMCRUD,PGMBANKI,...'
1. Carrega PGMBANKI de ACBLIB (PSB + DBDs pré-ligados)
2. Carrega PGMCRUD de LOADLIB
3. Chama ENTRY 'DLITCBL' passando PCBs na LINKAGE
4. Processa cada CALL 'CBLTDLI' contra BANCOCLI