Skip to main content
Moderne OnlyThis recipe is proprietary to Moderne and runs on the Moderne platform or CLI — it isn’t part of the open-source catalog. Available with a Moderne subscription.Contact Sales

Read the schema the DDL creates, and who reaches each table

Recipe IDio.moderne.mainframe.db2.AnalyzeDb2Catalog
Artifactio.moderne.recipe:recipes-mainframe

Record the DB2 schema the portfolio creates: each table with its columns, primary key, foreign keys and indexes, anchored at the member and line it is created on, from both places DDL is written — a member of a DDL library, and the SYSIN stream of the job that submits it. The summary joins each table to the programs whose EXEC SQL names it and to the packages and plans those programs are bound into, an unqualified name resolved against the qualifier its package was bound with, and a foreign key becomes a relationship between the two tables so the model diagram is the same graph everything else is drawn from. FindDb2Catalog answers the same question and marks each statement in the source; this one produces the tables and changes nothing.

Single recipeOpenRewriteModerne Proprietary License
Try in PlatformTry this recipe in the Moderne platform. Not a user yet? You’ll get a no-setup demo environment, with nothing to install or configure.

Usage​

Run this recipe

This recipe has no required configuration options. Users of Moderne can run it via the Moderne CLI.

You will need to have configured the Moderne CLI on your machine before you can run the following command.

shell
mod run . --recipe AnalyzeDb2Catalog

If the recipe is not available locally, then you can install it using:

RELEASE resolves to the newest release and LATEST to the newest build of any kind, including snapshots. Either one lets mod config recipes upgrade pull in later versions without editing this command; a pinned version stays where you put it.

mod config recipes jar install io.moderne.recipe:recipes-mainframe:RELEASE

Data tables​

DB2 tables
io.moderne.mainframe.analysis.table.Db2Tables

One row per table the DDL creates: where it is defined, what it is made of, and who reaches it. This is the summary a person opens a table on — the columns, the primary key, the foreign keys either way and the indexes, with the programs, packages and plans that use it — so the question "what is this table and what would a change to it break" is one row rather than a search.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Db2Tables
ColumnDescription
TableThe table, qualified as the DDL wrote it. This is the name the SQL in a program has to resolve to, and the one an unqualified name is resolved against the bind qualifier to reach.
SchemaThe qualifier the table was created under, empty for a table created unqualified — which leaves it to whatever SET CURRENT SQLID was in force.
NameThe table's own name, without its schema.
Table spaceThe table space the table lives in, empty where the DDL leaves it to DB2. This is what a RUNSTATS or a REORG card names, so it is the join from a table to the utility jobs that maintain it.
MemberThe DDL member the table is created in, or the job that creates it in its own stream.
Source pathThe file the CREATE TABLE was read from, which is the file to open at the line below.
LineThe one-based line of that file the CREATE TABLE begins on, counting from the top of the job for DDL written in a stream.
WrittenWhether the DDL is a member of a library or written in a job's stream. A table created in a stream exists nowhere else, so the job is its definition and not just the thing that ran it.
ColumnsHow many columns the table has.
Primary keyThe primary key's columns in key order, empty for a table declaring none — which happens, and is then enforced by a unique index instead.
Foreign keysHow many foreign keys this table declares, which is how many parents it has.
Referenced byHow many foreign keys point at this table, which is how many children it has. A table with children cannot have a row deleted without deciding what happens to them.
IndexesHow many indexes are defined on the table.
ProgramsHow many programs name the table in an EXEC SQL statement, unqualified names resolved against the qualifier their package was bound with.
PackagesHow many DB2 packages reach the table, which is the programs above joined to the bind decks that bind them.
PlansHow many plans reach the table through those packages, a PKLIST naming a whole collection expanded. Every plan counted here has to be rebound when the table changes.
DB2 columns
io.moderne.mainframe.analysis.table.Db2Columns

Every column of every table the DDL creates, in the order a SELECT * and a host structure both take: what it holds, whether it may be absent, where it sits in the primary key, the table it points at through a foreign key, and the indexes it is a key of. The last is what says whether a predicate written on the column has an access path or a table space scan behind it.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Db2Columns
ColumnDescription
TableThe table the column belongs to, qualified as the DDL wrote it.
OrdinalWhere the column sits in the table, counting from one. This is the order a SELECT * and a host structure both take, so it is what aligns a column with the COBOL field receiving it.
ColumnThe column name.
TypeThe type as the DDL writes it, length and scale included: CHAR(12), DECIMAL(9, 2), DATE.
NullableWhether the column may hold no value. A primary key column may not, whether or not the DDL says NOT NULL — DB2 requires it and supplies it when it is left out. A nullable column is the one a program has to fetch with an indicator variable.
Key sequenceWhere the column sits in the primary key, counting from one, or 0 for a column that is not part of it.
Foreign key toThe table this column points at through a foreign key, empty where it points at none. A column carrying two foreign keys names both.
IndexesThe indexes the column is a key of, each with its position in that key and the direction it is held in — CLM.XPOLICY1(2 ASC). A column with none is a column no predicate can be selective on.
MemberThe DDL member the column is declared in, or the job that declares it in its own stream.
Source pathThe file the column was read from, which is the file to open at the line below.
LineThe one-based line of that file the column is declared on.
DB2 primary keys
io.moderne.mainframe.analysis.table.Db2Keys

The primary key of each table, one row per key column in key order, with the unique index that enforces it. DB2 will not accept a primary key without one, so a key whose index is missing here is DDL that would not run — and the index is also the access path every foreign key check and every keyed read goes through.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Db2Keys
ColumnDescription
TableThe table the key belongs to, qualified as the DDL wrote it.
ConstraintThe name the DDL gives the constraint, empty where it names none — which is usual for a primary key, and leaves DB2 to name it after the index.
ColumnThe key column.
Key sequenceWhere the column sits in the key, counting from one. A composite key is only usable left to right, so the order is the whole of what it is good for.
Enforced byThe unique index whose key is exactly these columns, empty where the DDL read here declares none. DB2 requires one and creates it implicitly when a shop lets it, so an empty value means the index was not supplied rather than that there is none.
MemberThe DDL member the key is declared in, or the job that declares it in its own stream.
Source pathThe file the key was read from, which is the file to open at the line below.
LineThe one-based line of that file the PRIMARY KEY is written on.
DB2 indexes
io.moderne.mainframe.analysis.table.Db2Indexes

Every index the DDL creates, with the table it is on and the key it holds. An index is how a batch job reaches a table cheaply, so which columns it is keyed on is which predicates the schema was designed to answer — and an index no program writes a predicate for is maintenance nothing collects on.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Db2Indexes
ColumnDescription
IndexThe index, qualified as the DDL wrote it.
TableThe table the index is on, qualified as the DDL wrote it.
UniqueWhether the index enforces uniqueness, which is what a primary key needs and what a shop with no primary key uses instead of one.
Key columnsThe key in order, each column with the direction it is held in — STATUS_CODE ASC, POLICY_NO ASC. A composite key is only usable left to right.
Enforces the primary keyWhether this is the unique index whose key is exactly the table's primary key, which is the index DB2 requires a primary key to have.
MemberThe DDL member the index is created in, or the job that creates it in its own stream. An index added to a live table years after its table is routinely in a job of its own, and that job is the only place it exists.
Source pathThe file the CREATE INDEX was read from, which is the file to open at the line below.
LineThe one-based line of that file the CREATE INDEX begins on, counting from the top of the job for DDL written in a stream.
DB2 foreign keys
io.moderne.mainframe.analysis.table.Db2ForeignKeys

One table pointing at another, which is the referential arrow of the model diagram and the one relationship between two tables that can be read without reading a program. A key is written either in the CREATE TABLE or in an ALTER TABLE afterwards, and both are read here.

Export after a run
mod study . --last-recipe-run \
--data-table io.moderne.mainframe.analysis.table.Db2ForeignKeys
ColumnDescription
ConstraintThe name the DDL gives the relationship, empty where it names none. This is the name a -904 or a load utility message reports, so it is worth carrying even though nothing joins on it.
TableThe child table, the one holding the key, as the CREATE TABLE that creates it names it — or as the key names it where nothing here creates one.
ColumnsThe child's columns, in key order.
Referenced tableThe parent table the key points at.
Referenced columnsThe parent's columns, in key order. The DDL usually leaves these out and means the parent's primary key, and that key is filled in here — a row with a parent and no columns would say less than the DDL does.
Delete ruleWhat DB2 does to the child's rows when a parent row goes away: RESTRICT, CASCADE, SET NULL or NO ACTION. Empty where the DDL leaves it to the default of NO ACTION.
MemberThe DDL member the key is declared in, or the job that declares it in its own stream.
Source pathThe file the key was read from, which is the file to open at the line below.
LineThe one-based line of that file the FOREIGN KEY is written on.
COBOL relationships
org.openrewrite.mainframe.cobol.table.CobolRelationships

Relationships between different COBOL resources.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.mainframe.cobol.table.CobolRelationships
ColumnDescription
DependentThe resource that defines the relationship.
Dependent typeThe resource type of the resource that defines the relationship.
ActionThe action that links the dependent and dependency.
DependencyThe resource that is exercised or linked to.
Dependency typeThe resource type of the resource that is exercised or linked to.
Dependency missingIndicates whether the dependency is a known resource.
Action metadataAdditional data about the action.
Dependent pathThe source file the dependent's statement was written in, or null when the dependent is a name that has no source here.
Dependent lineThe one-based line the dependent's statement was written on, or null when it has no source here.
Dependency pathThe source file the dependency was written in, or null when the dependency is a name that has no source here, such as a vendor copybook.
Dependency lineThe one-based line the dependency's statement was written on, or null when the dependency is a whole file rather than a statement within one.
Source files that had results
org.openrewrite.table.SourcesFileResults

Source files that were modified by the recipe run.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SourcesFileResults
ColumnDescription
Source path before the runThe source path of the file before the run. null when a source file was created during the run.
Source path after the runA recipe may modify the source path. This is the path after the run. null when a source file was deleted during the run.
Parent of the recipe that made changesIn a hierarchical recipe, the parent of the recipe that made a change. Empty if this is the root of a hierarchy or if the recipe is not hierarchical at all.
Recipe that made changesThe specific recipe that made a change.
Estimated time savingAn estimated effort that a developer to fix manually instead of using this recipe, in unit of seconds.
CycleThe recipe cycle in which the change was made.
Source files that had search results
org.openrewrite.table.SearchResults

Search results that were found during the recipe run.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SearchResults
ColumnDescription
Source path of search result before the runThe source path of the file with the search result markers present.
Source path of search result after run the runA recipe may modify the source path. This is the path after the run. null when a source file was deleted during the run.
ResultThe trimmed printed tree of the LST element that the marker is attached to.
DescriptionThe content of the description of the marker.
Recipe that added the search markerThe specific recipe that added the Search marker.
Source files that errored on a recipe
org.openrewrite.table.SourcesFileErrors

The details of all errors produced by a recipe run.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.SourcesFileErrors
ColumnDescription
Source pathThe file that failed to parse.
Recipe that made changesThe specific recipe that made a change.
Stack traceThe stack trace of the failure.
Recipe performance
org.openrewrite.table.RecipeRunStats

Statistics used in analyzing the performance of recipes.

Export after a run
mod study . --last-recipe-run \
--data-table org.openrewrite.table.RecipeRunStats
ColumnDescription
The recipeThe recipe whose stats are being measured both individually and cumulatively.
Source file countThe number of source files the recipe ran over.
Source file changed countThe number of source files which were changed in the recipe run. Includes files created, deleted, and edited.
Cumulative scanning time (ns)The total time spent across the scanning phase of this recipe.
Max scanning time (ns)The max time scanning any one source file.
Cumulative edit time (ns)The total time spent across the editing phase of this recipe.
Max edit time (ns)The max time editing any one source file.