Technical specifications
Jump to navigation
Jump to search
3.1 Session tier —
3.2 DAL tier —
3.3 UI tier —
Technical Specification[edit]
Project: pgcobol — Prime Numbers Application
Version: 1.0 (reverse-engineered)
Date: 2026-03-17
1. Technology Stack[edit]
| Component | Technology |
|---|---|
| Runtime | GnuCOBOL 4.0, Linux |
| SQL pre-processor | GixSQL (translates EXEC SQL … END-EXEC to GIXSQLExec calls) |
| Database server | PostgreSQL 11.22, localhost:5432 |
| Database schema | primes
|
| Credentials | user primes_user, password pr1mes_user (hard-coded)
|
| Output file | primes.prt — line-sequential, 132 chars/record, linage 56
|
| Console | GnuCOBOL special-name scherm mapped to system console
|
2. Component Architecture[edit]
┌─────────────────────────────────────────────────────┐
│ primesmain │ ← Entry point / orchestrator
│ WORKING-STORAGE: commandline-args │
│ COPY: primes-session, primes-ui │
└────────────┬────────────────────────────────────────┘
│ CALL "primesgen" USING primes-session
▼
┌─────────────────────────────────────────────────────┐
│ primesgen │ ← Business logic / sieve engine
│ WORKING-STORAGE: primes (local), printer │
│ COPY (linkage): primes-session │
│ COPY (local): primes-ui, primes-dal │
└────────┬──────────────────────┬─────────────────────┘
│ CALL "primes" │ CALL "primesui"
│ USING primes-dal │ USING primes-ui
▼ ▼
┌──────────────────┐ ┌──────────────────────────────┐
│ primes │ │ primesui │ ← Presentation / output
│ (DAL + SQL) │ │ FILE: fprinter → primes.prt │
│ EXEC SQL via │ │ WORKING-STORAGE: primes-table│
│ GixSQL │ │ COPY (linkage): primes-ui │
└──────────────────┘ └──────────────────────────────┘
│
▼
┌──────────────────┐
│ PostgreSQL │
│ schema: primes │
│ table: primes │
└──────────────────┘
3. Inter-Tier Interface Contracts[edit]
All communication between tiers uses method-dispatch over shared copybook control blocks. A caller sets a verb string in the methods field, invokes the subprogram, and reads the result code on return.
3.1 Session tier — primes-session[edit]
primes-session
methods PIC X(32) verb sent by caller
88 report-primes "report"
88 generate-primes "generate"
88 start-primes "start"
88 stop-primes "stop"
88 invalid-method "bad"
session-result PIC 9(2) set by callee
88 session-method-ok 0
88 session-method-nok 1
88 session-method-eof 9
3.2 DAL tier — primes-dal[edit]
primes-dal
dal-methods PIC X(32) verb sent by caller
88 next-prime "next-prime"
88 next-divider "next-divider"
88 write-prime "write"
88 db-cursor "cursor"
88 db-connect "connect"
88 db-disconnect "disconnect"
primes-data data payload (one row)
primes-sequence PIC 9(9) ident from DB
prime-number PIC 9(9) prime value from DB
dal-result PIC 9(2) set by callee
88 dal-method-ok 0
88 dal-method-nok 1
88 dal-method-eof 99
3.3 UI tier — primes-ui[edit]
primes-ui
ui-methods PIC X(32) verb sent by caller
88 start-ui "start"
88 write-ui "write"
88 message-ui "log-message"
88 stop-ui "stop"
process-message structured console message
program-name PIC X(20)
program-paragraph PIC X(20)
program-message PIC X(92)
u-primes one prime row for print output
u-sequence PIC 9(9)
u-number PIC 9(9)
ui-method-result PIC 9(2) set by callee
88 ui-method-ok 0
88 ui-method-nok 1
4. Pseudocode[edit]
4.1 primesmain[edit]
PROGRAM primesmain
INPUT: command-line argument → commandline-args
CALL primesui("start")
IF ui-method-ok THEN
LOG "UI initialisation succeeded."
LOG commandline-args
ELSE
DISPLAY emergency message on console
STOP
CASE commandline-args OF
"report":
LOG "Primes report generation starts."
SET methods = "report"
CALL primesgen(primes-session) -- report flow
"generate":
LOG "Primes generation starts."
SET methods = "generate"
-- NOTE: CALL primesgen commented out in current source
OTHER:
LOG "Bad parameter, program initialisation failed."
CALL primesui("stop")
STOP
END CASE
LOG "Primes run complete, program stops."
CALL primesui("stop")
STOP
END PROGRAM
4.2 primesgen — report path[edit]
PROCEDURE report-path
CALL primes-dal("connect")
IF dal-method-ok THEN
LOG "Database initialisation succeeded."
ELSE
LOG "Database initialisation failed."
SET session-result = 1
RETURN
CALL primes-dal("cursor") -- START TRANSACTION + OPEN primescursor
IF dal-method-ok THEN
LOG "Cursor initialisation succeeded."
ELSE
LOG "Cursor initialisation failed."
SET session-result = 1
RETURN
FETCH first row via primes-dal("next-prime")
IF fetch fails THEN
LOG "Fetch first row nok."
SET dal-result = 1
LOOP UNTIL session-method-eof
SET u-sequence = primes-sequence
SET u-number = prime-number
CALL primesui("write") -- accumulate into print buffer
CALL primes-dal("next-prime") -- advance cursor
END LOOP
END PROCEDURE
4.3 primesgen — generate path[edit]
PROCEDURE generate-path
CALL primes-dal("connect")
IF dal-method-ok THEN
SET test-divider = 2
SET old-ident = 1
SET test-number = 3
SET test-number-sqr = SQRT(3)
LOG "Database initialisation succeeded."
ELSE
LOG "Database initialisation failed."
SET session-result = 1
RETURN
LOOP UNTIL test-number = 999,999,999
DIVIDE test-number BY test-divider → test-quot REMAINDER test-rest
CASE OF
test-rest = 0:
-- test-number is composite; move to next candidate
ADD 2 TO test-number
SET test-number-sqr = SQRT(test-number)
SET old-ident = 1
FETCH divider[old-ident+1] via primes-dal("next-divider")
test-divider > test-number-sqr:
-- no factor found up to sqrt; test-number is prime
CALL primes-dal("write") -- INSERT INTO primes
CALL primesui("write") -- add to print buffer
ADD 2 TO test-number
SET test-number-sqr = SQRT(test-number)
SET old-ident = 1
FETCH divider[old-ident+1] via primes-dal("next-divider")
OTHERWISE:
-- try next divider from DB
FETCH divider[old-ident+1] via primes-dal("next-divider")
END CASE
END LOOP
END PROCEDURE
4.4 primes (DAL)[edit]
PROGRAM primes
LINKAGE: primes-dal
CASE dal-methods OF
"connect":
EXEC SQL CONNECT TO datasrc AS primes USER dbusr USING dbpwd
IF SQLCODE = 0 THEN dal-result = 0 ELSE dal-result = 1
"cursor":
EXEC SQL AT primes START TRANSACTION
IF SQLCODE = 0 THEN
EXEC SQL OPEN primescursor
IF SQLCODE = 0 THEN dal-result = 0 ELSE dal-result = 1
ELSE dal-result = 1
"next-prime":
EXEC SQL FETCH primescursor INTO :primes-row
IF SQLCODE = 0 THEN
primes-sequence = r-ident
prime-number = r-prime
dal-result = 0
ELSE dal-result = 1
"next-divider":
new-ident = old-ident + 1
EXEC SQL SELECT prime INTO :test-divider
FROM primes WHERE ident = :new-ident
old-ident = new-ident
"write":
EXEC SQL INSERT INTO primes (prime) VALUES (:prime)
"disconnect":
EXEC SQL CONNECT RESET primes
IF SQLCODE = 0 THEN dal-result = 0 ELSE dal-result = 1
OTHER:
dal-result = 1
END CASE
EXIT PROGRAM
END PROGRAM
4.5 primesui[edit]
PROGRAM primesui
LINKAGE: primes-ui
CASE ui-methods OF
"start":
OPEN OUTPUT fprinter (primes.prt)
IF file-status = "00" THEN
ui-method-result = 0
primes-idx = 1
ELSE
ui-method-result = 1
"write":
t-ident(primes-idx) = u-sequence
t-prime(primes-idx) = u-number
primes-idx = primes-idx + 1
IF new-page THEN write heading + column header
IF primes-idx = 7 THEN
WRITE primes-table line to fprinter
primes-idx = 1
IF linage-counter = 53 THEN write footing, increment page
"log-message":
DISPLAY process-message ON CONSOLE
"stop":
LOOP writing zero rows UNTIL new-page -- flush partial line
CLOSE fprinter
END CASE
EXIT PROGRAM
END PROGRAM
5. Database Interface Specification[edit]
5.1 Connection[edit]
| Parameter | Value |
|---|---|
| Driver | GixSQL pgsql |
| Host | localhost |
| Port | 5432 |
| Database | primes |
| Schema search path | primes |
| Connection alias | primes |
| User | primes_user |
| Password | pr1mes_user |
5.2 SQL Statements[edit]
| ID | Statement | Called from |
|---|---|---|
| S-01 | CONNECT TO :DATASRC AS primes USER :DBUSR USING :DBPWD
|
s00-connect |
| S-02 | START TRANSACTION
|
s01-cursor |
| S-03 | DECLARE primescursor CURSOR FOR SELECT * FROM primes
|
compile-time |
| S-04 | OPEN primescursor
|
s01-cursor |
| S-05 | FETCH primescursor INTO :primes-row
|
s02-fetch |
| S-06 | SELECT prime INTO :test-divider FROM primes WHERE ident = :new-ident
|
r81-get-next-divider |
| S-07 | INSERT INTO primes (prime) VALUES (:prime)
|
r83-write-prime |
| S-08 | CONNECT RESET primes
|
s99-disconnect |
5.3 Error Handling[edit]
- All SQL paths test
SQLCODE = 0for success. - On failure, a diagnostic string is moved to
program-messageand logged via primesui. dal-resultis set to1(nok) on SQL errors; callers checkdal-method-okbefore continuing.- No retry logic is implemented; errors cause the current operation to be skipped or the session to terminate.
6. Output File Specification[edit]
| Property | Value |
|---|---|
| Filename | primes.prt
|
| Organisation | Line-sequential |
| Record length | 132 characters |
| Linage | 56 lines per page |
| Footing area | 2 lines from bottom |
| Bottom margin | 2 lines |
| Records per data line | 6 primes (sequence + value pairs) |
| Page heading | "primes overview" (col 1)
|
| Column header | "Sequence Prime" × 6 across
|
| Page footing | Spaces + "page: ZZZZ9" (right side)
|
| EOP trigger | linage-counter = 53 |
7. Known Defects and Limitations[edit]
| ID | Severity | Description |
|---|---|---|
| D-01 | High | Generate loop (PERFORM r80-test-number) is commented out in primesmain; generation mode does not execute the sieve.
|
| D-02 | Medium | Prime 2 is never seeded; generation starts at 3 with first divider = 2 retrieved from DB, but DB is empty at start of a fresh run. |
| D-03 | Medium | primes_cbsql.out shows disconnect using alias primesdb; primes.cbl uses alias primes — alias mismatch will cause runtime SQL error.
|
| D-04 | Low | Database credentials are hard-coded in WORKING-STORAGE of primes.cbl. |
| D-05 | Low | No COMMIT after INSERT in r83-write-prime (statement is commented out); relies on PostgreSQL auto-commit or session-level transaction semantics. |
| D-06 | Low | Two almost-identical host-variable copybooks (primes-table.cpy vs primes_table.cpy) suggest unresolved refactoring.
|
Terug naar: Primes_programs_specifications | Cobol and PostgreSQL