Translate

Mostrar mensagens com a etiqueta Tabelas COBOL. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Tabelas COBOL. Mostrar todas as mensagens

quinta-feira, 14 de julho de 2022

☕💥 Arrays em COBOL: O Poder Oculto do OCCURS, SSRANGE e a Guerra Contra a Invasão de Memória

 

Bellacosa Mainframe e as tabelas internas no COBOL occurs e arrays

☕💥 Arrays em COBOL: O Poder Oculto do OCCURS, SSRANGE e a Guerra Contra a Invasão de Memória

Ou como evitar transformar seu Address Space em um filme de terror para Sysprogs



Introdução

Existe um momento na vida de todo desenvolvedor COBOL júnior em que ele descobre duas verdades universais:

A primeira é que OCCURS parece simples até deixar de ser simples.

A segunda é que existe uma entidade maligna chamada:

SSRANGE

capaz de transformar uma manhã tranquila em uma reunião emergencial envolvendo desenvolvimento, suporte, infraestrutura, DBA, operador e um sysprog segurando uma caneca de café já fria.

E tudo isso por causa de um pequeno detalhe:

MOVE WS-NOME(9999)

quando a tabela possui apenas:

OCCURS 100 TIMES.

Bem-vindo ao fascinante mundo das tabelas COBOL.


Capítulo 1 – O que é OCCURS?

OCCURS é o mecanismo utilizado pelo COBOL para criar estruturas repetitivas.

Em linguagens modernas chamaríamos isso de:

  • Array

  • Vetor

  • Lista fixa

  • Matriz

Exemplo:

01 CLIENTES.

   05 CLIENTE OCCURS 10 TIMES.

      10 NOME PIC X(30).
      10 IDADE PIC 99.

Memória:

CLIENTE(1)
CLIENTE(2)
CLIENTE(3)
...
CLIENTE(10)

COBOL simplesmente reserva um bloco contínuo.


A origem histórica

Década de 60.

Memória era absurdamente cara.

IBM 1401

4 KB

IBM System/360

256 KB

370

1 MB

Não existia:

  • Java Collections

  • Python List

  • C++ Vector

Era necessário reservar memória antecipadamente.

Daí nasceu:

OCCURS

Curiosidade histórica

Os engenheiros da IBM chamavam essas estruturas de:

Table Handling

Muito antes da expressão Array Processing se popularizar.


Capítulo 2 — Como a memória é organizada

Exemplo:

01 TAB.

   05 ITEM OCCURS 5 TIMES.

      10 CODIGO PIC 9(5).

Cada item ocupa:

5 bytes

Total

25 bytes

Layout:

0000 ITEM(1)
0005 ITEM(2)
0010 ITEM(3)
0015 ITEM(4)
0020 ITEM(5)

Acesso:

MOVE ITEM(3) TO WS-X

COBOL faz:

Base + ((3-1)*5)

Capítulo 3 – O Terror do Out of Bounds

Tabela:

05 CLIENTE OCCURS 100 TIMES.

Código:

MOVE NOME(101)

Problema.

A posição não existe.


Antigamente

Compilador:

NOSSRANGE

Padrão.

Nenhuma verificação.

Resultado:

Leitura aleatória.

Sobrescrever memória.

Corrupção.


O verdadeiro vilão

Imagine:

01 TABELA.

05 DADOS OCCURS 100 TIMES.

05 FLAG-FINAL PIC X.

Erro:

MOVE "S" TO DADOS(101)

Na prática:

FLAG-FINAL = S

ou pior.

Modifica outra estrutura.


Isso é invasão de memória?

Sim.

Tecnicamente:

Buffer overflow

Memory overwrite

Storage corruption


Capítulo 4 — Address Space

No zOS cada Job possui.

Address Space.

Exemplo

JOB1234



Private Area


LSQA


SWA


Subpools


Heap


Stack

Seu programa COBOL vive ali.


Se escrever fora da tabela:

pode corromper:

Working Storage

Heap

LE Runtime

Control Blocks


Em casos extremos:

S0C4

S878

U4038


Capítulo 5 — SSRANGE

A melhor invenção desde o café expresso.

Compilação:

SSRANGE

ou

CBL SSRANGE

Exemplo

MOVE WS-NOME(101)

Resultado:

Abend imediato.

Mensagem:

IGZxxxx

Subscript out of range


Excelente para:

Homologação

Teste

QA


Produção?

Normalmente:

NOSSRANGE

Performance melhor.


Dica Bellacosa

Desenvolvimento

SSRANGE

Produção

NOSSRANGE


Capítulo 6 — Índices

Ruim:

77 WS-I PIC 999.

Melhor:

05 CLIENTE OCCURS 100 TIMES
   INDEXED BY IDX.

SET

SET IDX TO 1

Próximo

SET IDX UP BY 1

Anterior

SET IDX DOWN BY 1

Por que índice é melhor?

Subscript:

CLIENTE(I)

Cálculo toda vez.


Index

Endereço pronto.

Ponteiro interno.

Mais rápido.


Capítulo 7 – Navegação

Crescente

SET IDX TO 1


PERFORM UNTIL IDX > MAX

PROCESSA

SET IDX UP BY 1

END-PERFORM

Decrescente

SET IDX TO MAX


PERFORM UNTIL IDX = 0


PROCESSA


SET IDX DOWN BY 1


END-PERFORM

Muito usado em:

Compressão

Ordenação

Rollback


Capítulo 8 — SEARCH

Busca sequencial.

SEARCH CLIENTE


AT END


DISPLAY "NAO ACHOU"


WHEN ID = WS-ID


DISPLAY NOME

END-SEARCH

Complexidade

O(n)


100 mil registros.

50 mil leituras médias.


SEARCH ALL

Arma secreta.

Busca binária.


Tabela obrigatoriamente ordenada.

SEARCH ALL CLIENTE


WHEN ID(IDX)=WS-ID


DISPLAY "ACHOU"

END-SEARCH

Complexidade

O(log n)


1000000 itens.

Comparações:

~20


Magia matemática.


Capítulo 9 — OCCURS DEPENDING ON

Tabela variável.

05 QTDE PIC 9(4).


05 CLIENTE OCCURS 1 TO 1000 TIMES

DEPENDING ON QTDE.

Muito usado em:

MQ

Copybooks

APIs

Arquivos


Capítulo 10 — Bidimensional

Exemplo.

Agência x Dia

05 MOVIMENTO.

10 AG OCCURS 100.

15 DIA OCCURS 31.

20 TOTAL PIC 9(10).

Uso:

TOTAL(10,15)

Agência 10.

Dia 15.


Tridimensional

ANO

MES

DIA
VENDAS(2026,6,23)

N dimensões

Teoricamente ilimitado.

Exemplo.

Banco.

País

Estado

Agência

Conta

Produto

Dia


Capítulo 11 — Ordenação

Tabela ordenada.

ASCENDING KEY

Muito útil para:

SEARCH ALL

Caches

Lookup


Capítulo 12 – Quando usar tabela

Excelente:

Parâmetros

Cache

Código UF

Tabela IR

CEP

Conversões


Ruim:

Milhões registros.


Melhor:

DB2

VSAM

IMS


Capítulo 13 – Performance

SEARCH

O(n)

SEARCH ALL

O(log n)

Index

Muito rápido

Subscript

Mais lento

SSRANGE

Seguro

NOSSRANGE

Rápido


Easter Egg COBOL

Existe uma lenda entre veteranos de mainframe.

Diz-se que em algum datacenter esquecido dos anos 80 existe um programa COBOL compilado com:

NOSSRANGE
OPT(2)
FASTSRT
ARITH(EXTEND)

executando desde 1987.

Ninguém sabe exatamente o que ele faz.

Ninguém possui o código-fonte.

Ninguém ousa recompilar.

Mas toda madrugada, às 02h17, ele produz um relatório financeiro perfeito, movimenta bilhões de dólares e desaparece novamente nas profundezas do JES2.

Os sysprogs apenas observam o spool, tomam um gole de café e repetem o antigo mantra do reino z/OS:

"Se está funcionando há 39 anos, não toque."


Conclusão

OCCURS é muito mais do que um simples array.

É uma das construções mais antigas, elegantes e eficientes já criadas para processamento em lote de grande volume.

Dominar:

  • OCCURS

  • INDEXED BY

  • SET

  • SEARCH

  • SEARCH ALL

  • SSRANGE

  • OCCURS DEPENDING ON

  • Tabelas multidimensionais

  • Navegação UP e DOWN

  • Layout de memória

  • Address Space do z/OS

é um dos marcos que separam o Padawan COBOL do Cavaleiro do Batch Jedi Council.

Porque no universo do Mainframe existe uma verdade absoluta:

"DB2 pode falhar, CICS pode reciclar, VSAM pode corromper, mas um OCCURS acessado fora dos limites sempre encontrará uma maneira criativa de arruinar o dia de alguém."