Module 07
IDMS SQL & the relational option
This database can also speak SQL — both over tables it defines itself, and over the existing pointer-linked records. For a migration project that second ability is often the cheapest way to read the source at all. It also comes with a semantic gap you need to understand before trusting it.
Good news: you may be able to point ordinary SQL tools at this database over a normal network connection, without writing any mainframe code. One statement makes the pointer-linked records visible as tables. No data moves, and the same bytes stay readable by the existing programs at the same time.
The catch is that these records have no concept of an empty value. There is no NULL. Fifty years of programs have used spaces, zeros or a date of 00000000 to mean “we don’t know”. Your target database has real NULLs, so every one of those needs a deliberate, written decision — and not all of them mean “unknown”.
New words on this page, one line each
- SQL option
- A licensed add-on giving this database an SQL engine and a catalog. May not be installed — check.
- catalog
- Tables describing the tables. Queryable with ordinary SQL, and a useful second source of field definitions.
- access module
- A stored, pre-compiled plan for a program’s fixed SQL. Like a saved query plan.
- CA IDMS Server
- The JDBC and ODBC drivers that let a Linux or Windows process connect over the network.
- sentinel
- A special value standing in for “missing”, because there is no NULL. Usually zeros, spaces, or 00000000.
Two kinds of table living side by side
The warehouse gets a front-of-house counter where you can ask questions in a language you already speak.
Nothing in the back is rearranged. The cards stay exactly where they were, still reachable by the old routes at the same time. Someone has simply written a translation layer that turns your question into the same walking-the-string journey a program would have made by hand.
The SQL option adds an SQL engine, an optimiser and a catalog to IDMS. What it addresses falls into two categories that look identical from a JDBC connection and behave rather differently underneath.
SQL-defined tables
Created with CREATE TABLE. IDMS chooses the storage, maintains the indexes, enforces the
constraints. Nulls exist. This is a relational database that happens to run inside IDMS.
Network records exposed as tables
An SQL schema is defined for an existing non-SQL schema. Each network record type becomes a table; the underlying storage is unchanged, and the same bytes are simultaneously readable by navigational DML.
CREATE SCHEMA EMPSQL
FOR NONSQL SCHEMA EMPSCHM VERSION 100
DBNAME EMPDB;
-- now the network records look like tables
SELECT EMP_ID_0415, EMP_LAST_NAME_0415, STATUS_0415
FROM EMPSQL.EMPLOYEE
WHERE STATUS_0415 = '01';
No data moves. No records are copied. The SQL engine navigates the same pointers your COBOL program does — it simply generates the navigation for you instead of making you write it.
What the pointer-linked records look like through SQL
Everything else on this list maps tidily. The missing-value problem does not, and it is not a technical problem — it is a business one.
A termination date of 00000000 almost certainly means “still employed”, so NULL is right. A national insurance number of all zeros might mean “unknown”, or it might mean “this person is not a national” — which is real information that NULL would destroy. You have to ask, per field, and write the answer down.
| Network | SQL view of it | Caveat |
|---|---|---|
| Record type | Table | Group items are flattened; element names typically become column names with hyphens as underscores |
| Element | Column | OCCURS arrays and REDEFINES do not map cleanly and may be excluded or exposed as raw bytes |
| CALC key | An index, often the effective primary key | Only DUPLICATES NOT ALLOWED makes it truly unique |
| Set | A relationship the optimiser can use to join owner and member | The join column may be implicit — the linkage is pointers, not values |
| Sorted set key | An index | Ordering within a set occurrence, not globally |
| Area | Storage the table lives in | Still the unit of READY and locking underneath |
| Missing value | Whatever sentinel the application used | There is no NULL in a network record. Spaces, zeros, low-values and 00000000 dates are all "missing" in the application's mind and are ordinary values to SQL. |
00000000. Your target schema will have real nulls, and every one of those encodings needs an
explicit, documented mapping decision. Nobody else on the project will make it for you.
Asking the database to describe itself
Same idea, same usefulness. These catalog tables give you column names, types, lengths and declared constraints as ordinary query results.
Use it as a cross-check rather than a primary source: query the catalog, compare it against the blueprint from Module 04, and investigate anything that disagrees. Structures SQL cannot represent are still real data that still changes.
IDMS SQL keeps its metadata in catalog tables under the SYSTEM schema. They are queryable with
ordinary SQL, which makes them an excellent second source of metadata alongside the dictionary.
-- every table visible to you
SELECT SCHEMA, NAME, TABLE_TYPE
FROM SYSTEM.TABLE
ORDER BY SCHEMA, NAME;
-- the full column list for one table, in order
SELECT NAME, DATATYPE, LENGTH, SCALE, NULLS
FROM SYSTEM.COLUMN
WHERE TABLE_NAME = 'EMPLOYEE'
AND SCHEMA = 'EMPSQL'
ORDER BY SEQ_NO;
-- declared referential constraints
SELECT NAME, REFERENCING_TABLE, REFERENCED_TABLE
FROM SYSTEM.CONSTRAINT;
-- indexes
SELECT NAME, TABLE_NAME, UNIQUE_RULE
FROM SYSTEM.INDEX;
Catalog table and column names vary by release. Run SELECT * FROM SYSTEM.TABLE WHERE SCHEMA =
'SYSTEM' on your system to discover the actual layout before scripting against it.
Referential constraints, and the linked variety
SQL-defined tables support ordinary declared referential constraints. IDMS additionally lets a constraint be implemented physically as a set — pointers rather than value matching — which gives relational syntax with network performance characteristics.
CREATE TABLE EMPSQL.PROJECT
( PROJ_ID UNSIGNED NUMERIC(6) NOT NULL,
PROJ_NAME CHAR(40) NOT NULL,
DEPT_ID UNSIGNED NUMERIC(4) NOT NULL,
BUDGET DECIMAL(11,2),
START_DATE DATE,
CONSTRAINT PROJ_PK PRIMARY KEY (PROJ_ID) );
CREATE INDEX PROJ_DEPT_NDX ON EMPSQL.PROJECT (DEPT_ID);
CREATE TABLE EMPSQL.TASK
( TASK_ID UNSIGNED NUMERIC(8) NOT NULL,
PROJ_ID UNSIGNED NUMERIC(6) NOT NULL,
DESCRIPTION VARCHAR(120),
CONSTRAINT TASK_PK PRIMARY KEY (TASK_ID),
CONSTRAINT TASK_PROJ FOREIGN KEY (PROJ_ID)
REFERENCES EMPSQL.PROJECT (PROJ_ID) );
The point to take away: an IDMS installation can have genuinely relational tables sitting next to network records in the same database, in the same areas, under the same journals and the same recovery. When you inventory a source system, do not assume everything is CODASYL.
Why a schema change can force a code rebuild
Static SQL embedded in a program is compiled into an access module: a stored, named object containing the chosen access paths, analogous to a Db2 package. Dynamic SQL — which is what a JDBC client issues — is optimised at execution time instead.
CREATE ACCESS MODULE EMPSQL.PAYROLL01
FOR PROGRAM PAYROL01
DEFAULT SCHEMA EMPSQL
ISOLATION LEVEL CURSOR STABILITY;
-- after a schema change, plans must be regenerated
DROP ACCESS MODULE EMPSQL.PAYROLL01;
The practical consequence for you: if the source team changes an index or a schema, static SQL programs may need their access modules recreated. That is a change window, and a change window is something your replication cutover plan has to be aware of.
Connecting from a Linux or Windows machine
It is ordinary JDBC. You get a connection string, a driver, and you write SELECT statements against tables.
Two cautions. Row-at-a-time over a network is slow for bulk movement, so this is not how you do the initial load. And every connection consumes one of a limited number of outside-connection slots that production batch jobs also need — so agree an allocation before you open twenty of them.
CA IDMS Server provides JDBC and ODBC drivers plus a server component. From a Linux or Windows process you connect over TCP/IP to a listener, naming the node, dictionary and database.
jdbc:idms://mfhost:3709/EMPDB?dictname=APPLDICT&node=SYSTEM71
-- and then perfectly ordinary SQL
SELECT e.EMP_ID_0415,
e.EMP_LAST_NAME_0415,
d.DEPT_NAME_0410,
p.SALARY_AMOUNT_0420
FROM EMPSQL.EMPLOYEE e
JOIN EMPSQL.DEPARTMENT d ON ...
JOIN EMPSQL.EMPOSITION p ON ...
WHERE e.STATUS_0415 = '01';
URL syntax, ports and property names are installation- and release-specific. Treat the above as shape, not as something to paste.
Lab — generate a target table from a network record
Pick a record and a key strategy, and read the generated DDL and the warnings. This is exactly the decision you will make for every record type in scope.
What it will not do, before you plan around it
Not moving bulk data. Its real value is checking your work: counting rows, adding up a column, spot-checking records the target says are wrong.
Being able to ask the source a direct question from the same machine your pipeline runs on is worth a great deal at three in the morning during a cutover.
- It is a licensed option and may not be installed. Confirm before designing around it.
- Not every network structure maps. Repeating groups, redefines and variable-length structures may be excluded from the SQL view or exposed in a form that needs interpretation.
- Performance is not free. The SQL optimiser works with the access paths the network schema happens to provide. A predicate with no supporting path becomes a sweep, exactly as it would in DML.
- External run units are consumed. Every JDBC connection counts against
MAXERUS. - Locking still happens at the IDMS level. An SQL query readying an area participates in the same lock manager as everything else.
What this means for replication
- Use SQL for metadata and validation, not for bulk. The catalog gives you column types and lengths in machine-readable form; validation queries give you an independent check on the target.
- The SQL view is a good sanity check on your own model. If IDMS's own mapping of a record to a table disagrees with the model you designed from the schema, one of you has misread something.
- Do not assume the SQL view is complete. Structures it cannot represent are still real data that still changes. Cross-check the SQL column list against the schema element list.
- Null handling is your decision to document. Write the sentinel-to-null mapping table early, get it agreed by the business, and put it in version control alongside the DDL.
- Watch the run-unit budget. A validation harness that opens twenty connections is twenty external run units competing with production batch.
Exercise 7.1 — Write the sentinel mapping
For the sample EMPLOYEE record, produce the table you would hand to the business for sign-off.
A row per field where a sentinel is possible:
| Field | Sentinel observed | Business meaning | Target representation |
|---|---|---|---|
TERMINATION-DATE-0415 | 00000000 | Still employed | NULL |
STATUS-0415 | spaces | Unknown / never set | NULL |
EMP-PHONE-0415 | all zeros | No phone recorded | NULL |
SS-NUMBER-0415 | all zeros | ? | Ask — it may mean "not a US national", which is not the same as unknown |
The fourth row is the important one. Not every sentinel means "null", and mapping a meaningful sentinel to null destroys information that no amount of downstream cleverness can recover.