Primes Software Specification
Software Specification — Primes.cbsql[edit]
Standard: IEEE 830 / ISO/IEC 29148 (Requirements) · IEEE 1016 (Design) · ISO/IEC 11179 (Data Dictionary) · UML 2.x Activity Diagrams
Source:
Primes.cbsql— GnuCOBOL + GixSQL preprocessed source
Date: 2026-03-17
Status: Reverse-engineered
Table of Contents[edit]
1. Business Requirements Document[edit]
1.1 Purpose[edit]
Primes.cbsql is a COBOL Data Access Layer (DAL) module that manages persistent storage of prime numbers in a PostgreSQL database. It is not a standalone program; it is invoked by a calling driver program that selects the desired operation via a shared linkage interface (primes-dal).
1.2 Scope[edit]
The module handles all database interactions for the prime number generation system, including connection lifecycle management, cursor-based sequential reads, row-by-row prime retrieval for trial division, and insertion of newly discovered primes.
1.3 System Context[edit]
| Item | Value |
|---|---|
| Platform | Linux (GnuCOBOL + GixSQL) |
| Database | PostgreSQL 5432 @ localhost |
| Schema | primes
|
| Database name | primes
|
| DB user | primes_user
|
| UI module | primesui (called for all status messages)
|
| Linkage interface | primes-dal (copybook)
|
1.4 Business Functions[edit]
| ID | Method Flag | Description |
|---|---|---|
| BF-01 | db-connect
|
Establish a connection to the PostgreSQL database |
| BF-02 | db-cursor
|
Begin a transaction and open a cursor for reading all primes |
| BF-03 | next-prime
|
Fetch the next prime row from the open cursor |
| BF-04 | next-divider
|
Retrieve a specific prime by identity index to use as a trial divisor |
| BF-05 | write-prime
|
Insert a newly proven prime into the database |
| BF-06 | db-disconnect
|
Close the database connection and release resources |
1.5 Business Rules[edit]
| ID | Rule |
|---|---|
| BR-01 | The initial prime value 2 is inserted as a seed record during first-run initialisation (r90-generate-primes)
|
| BR-02 | All operations must set dal-result to 0 on success or 1 on failure
|
| BR-03 | All status messages (success and error) must be routed through the primesui subprogram
|
| BR-04 | Raw SQL error codes (SQLCODE) must be displayed to the console on failure
|
| BR-05 | Trial division uses stored primes up to the square root of the candidate number |
1.6 Assumptions and Constraints[edit]
- The database schema and table (
primes.primes) must exist prior to program execution. - The calling program is responsible for managing the sequence of DAL method calls.
r90-generate-primes(seed insertion) is not reachable via the DAL dispatch and must be called directly during initial setup.
2. Technical Specification / Pseudocode[edit]
2.1 Program Entry and Dispatch[edit]
PROGRAM primes
CALLED BY: external driver via LINKAGE SECTION (primes-dal)
ON ENTRY:
EVALUATE TRUE on dal-method flag:
WHEN next-prime → PERFORM r80-get-next-prime
WHEN next-divider → PERFORM r81-get-next-divider
WHEN write-prime → PERFORM r83-write-prime
WHEN db-connect → PERFORM s00-connect
WHEN db-cursor → PERFORM s01-cursor
WHEN db-disconnect → PERFORM s99-disconnect
WHEN OTHER → SET dal-result = 1
END-EVALUATE
EXIT PROGRAM
2.2 Paragraph Specifications[edit]
r80-get-next-prime[edit]
PERFORM s02-fetch
r81-get-next-divider[edit]
new-ident = old-ident + 1
SQL: SELECT prime FROM primes WHERE ident = :new-ident
INTO :test-divider
IF SQLCODE = 0
(test-divider now holds the next divisor prime)
ELSE
DISPLAY SQLCODE to console
DISPLAY "select new-divider nok" to console
old-ident = new-ident
r83-write-prime[edit]
SQL: INSERT INTO primes (prime) VALUES (:prime) IF SQLCODE != 0 DISPLAY SQLCODE to console DISPLAY "insert next prime nok" + prime-number to console
r90-generate-primes (first-run initialisation, not via DAL dispatch)[edit]
PERFORM s00-connect
IF dal-method-ok
SQL: INSERT INTO primes (prime) VALUES (2) -- seed record
IF SQLCODE = 0
primes-sequence = 1
prime-number = 2
dal-result = 0
LOG "Initial insert ok."
ELSE
LOG "Initial insert failed, terminating."
dal-result = 1
CALL primesui (log-message)
s00-connect[edit]
SQL: CONNECT TO :DATASRC AS primes USER :DBUSR USING :DBPWD IF SQLCODE = 0 dal-result = 0 LOG "Database initialisation ok." ELSE LOG "Database initialisation failed, terminating." dal-result = 1 CALL primesui
s01-cursor[edit]
SQL: START TRANSACTION
IF SQLCODE = 0
LOG "Start transaction ok."
ELSE
LOG "Start transaction nok."
dal-result = 1
CALL primesui
IF dal-method-ok
OPEN CURSOR primescursor (SELECT * FROM primes)
IF SQLCODE = 0
LOG "Start primescursor ok."
ELSE
LOG "Start primescursor nok."
dal-result = 1
CALL primesui
s02-fetch[edit]
SQL: FETCH primescursor INTO :r-ident, :r-prime IF SQLCODE = 0 primes-sequence = r-ident prime-number = r-prime dal-result = 0 ELSE LOG "Fetch row nok." dal-result = 1 CALL primesui
s99-disconnect[edit]
SQL: CONNECT RESET primes IF SQLCODE = 0 dal-result = 0 LOG "Close database ok." ELSE LOG "Database initialisation failed, ending." dal-result = 1 CALL primesui DISPLAY "s99 disconnect from database" to console DISPLAY SQLCODE to console
3. Data Dictionary[edit]
3.1 Working Storage Fields[edit]
| Field | PIC | COBOL Type | Description |
|---|---|---|---|
DATASRC
|
X(64)
|
Alphanumeric | PostgreSQL connection string |
DBUSR
|
X(64)
|
Alphanumeric | Database login username |
DBPWD
|
X(64)
|
Alphanumeric | Database login password |
CUR-STEP
|
X(16)
|
Alphanumeric | Current processing step label |
prime-count
|
9(9)
|
Numeric | Count of primes (declared; populated by driver) |
prime_seq
|
9(9)
|
Numeric | Prime sequence number (declared; populated by driver) |
divider
|
9(9)
|
Numeric | Trial divider working field |
3.2 Group: primes-row — Database Fetch Buffer[edit]
| Field | PIC | COBOL Type | Description |
|---|---|---|---|
r-ident
|
9(9) COMP-3
|
Packed decimal | Row identity key fetched from cursor |
r-prime
|
9(9) COMP-3
|
Packed decimal | Prime value fetched from cursor |
3.3 Group: primes — Primality Test Working Storage[edit]
| Field | PIC / Value | Description |
|---|---|---|
primes-result
|
9(2)
|
Status code: 1=init ok · 2=first divider ok · 3=next divider ok
|
88 init-primes-ok
|
value 1
|
Condition name: initialisation succeeded |
88 first-divider-ok
|
value 2
|
Condition name: first trial divisor retrieved |
88 next-divider-ok
|
value 3
|
Condition name: subsequent trial divisor retrieved |
test-number
|
9(9)
|
Candidate number under primality test |
test-number-sqr
|
9(9)v9(9)
|
Square root of test-number — upper bound for divisor loop
|
test-divider
|
9(9)
|
Current prime divisor retrieved from DB |
test-rest
|
9(9)v9(9)
|
Remainder of test-number ÷ test-divider
|
old-test-number
|
9(9)
|
Previous candidate number |
old-ident
|
9(9)
|
Row identity of the last retrieved divisor |
new-ident
|
9(9)
|
Row identity of the next divisor (old-ident + 1)
|
3.4 Copybook References[edit]
| Copybook | Contents |
|---|---|
primes-table
|
COBOL record layout mirroring the primes DB table
|
SQLCA
|
Standard SQL Communication Area (SQLCODE, SQLERRM, etc.)
|
primes-ui
|
Data structure for primesui subprogram (messages, program name, methods)
|
primes-dal
|
DAL linkage interface — method flags and dal-result return code
|
3.5 Prepared SQL Statements[edit]
| Ref | SQL Text | Used in |
|---|---|---|
SQ0001
|
SELECT * FROM primes
|
Cursor declaration (s01-cursor) |
SQ0002
|
SELECT prime FROM primes WHERE ident = $1
|
r81-get-next-divider |
SQ0003
|
INSERT INTO primes (prime) VALUES ($1)
|
r83-write-prime |
SQ0004
|
INSERT INTO primes (prime) VALUES (2)
|
r90-generate-primes (seed) |
SQ0005
|
START TRANSACTION
|
s01-cursor |
3.6 Database Table: primes.primes[edit]
| Column | Type | Description |
|---|---|---|
ident
|
INTEGER (serial / sequence) | Auto-generated row identity / primary key |
prime
|
INTEGER | The prime number value stored in this row |
4. Flow Diagrams[edit]
4.1 Program Entry — DAL Dispatch[edit]
┌──────────────────────────┐
│ ENTRY — primes program │
│ (called with primes-dal) │
└────────────┬─────────────┘
│
┌──────────▼──────────┐
│ EVALUATE dal-method │
└──────────┬──────────┘
┌──────────┬────────────┼───────────┬────────────┬──────────┐
▼ ▼ ▼ ▼ ▼ ▼
next-prime next-divider write-prime db-connect db-cursor db-disconnect
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
r80-get- r81-get- r83-write- s00-connect s01-cursor s99-disconnect
next-prime next-divider prime
│ │ │ │ │ │
└──────────┴────────────┴───────────┴────────────┴──────────┘
│
┌────────────▼────────────┐
│ SET dal-result │
│ 0 = success │
│ 1 = failure │
└────────────┬────────────┘
│
┌────────────▼────────────┐
│ EXIT PROGRAM │
└─────────────────────────┘
4.2 Database Connection Lifecycle[edit]
Driver calls db-connect Driver calls db-cursor
│ │
▼ ▼
s00-connect s01-cursor
SQL CONNECT SQL START TRANSACTION
│ │
SQLCODE=0? SQLCODE=0?
├─ yes → dal-result=0 ├─ yes → OPEN primescursor
└─ no → dal-result=1 └─ no → dal-result=1
│ │
CALL primesui CALL primesui
│
┌────────────▼──────────────┐
│ Loop: Driver calls │
│ next-prime repeatedly │
│ │ │
│ r80 → s02-fetch │
│ FETCH primescursor │
│ → primes-sequence │
│ → prime-number │
│ SQLCODE=0? loop / stop │
└────────────┬──────────────┘
│
Driver calls db-disconnect
│
s99-disconnect
SQL CONNECT RESET
│
CALL primesui
4.3 Prime Discovery Flow (cross-module context)[edit]
Driver: candidate number N to test
│
▼
Set old-ident = 0
│
┌───────▼────────────────────────────────┐
│ LOOP: call next-divider │
│ → r81: new-ident = old-ident + 1 │
│ → SQL SELECT prime WHERE ident=new │
│ → test-divider returned │
│ │
│ IF test-divider > SQRT(N) → PRIME! │
│ IF N MOD test-divider = 0 → NOT prime │
│ ELSE continue loop │
└───────────────────────────────────────┘
│
N is prime?
├─ yes → call write-prime
│ → r83: INSERT INTO primes VALUES (N)
└─ no → discard, try N+1 (even numbers typically skipped)
4.4 Cursor Fetch Detail[edit]
s02-fetch
│
GIXSQLStartSQL
│
GIXSQLSetResultParams (:r-ident)
GIXSQLSetResultParams (:r-prime)
│
GIXSQLCursorFetchOne (primes_primescursor)
│
GIXSQLEndSQL
│
SQLCODE = 0?
├─ yes → primes-sequence = r-ident
│ prime-number = r-prime
│ dal-result = 0
└─ no → LOG "Fetch row nok."
dal-result = 1
CALL primesui
End of specification.