Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Available Tables

The catalog provides several tables that can be queried using standard SQL syntax. Use LIST CATALOG TABLES to list all available tables in your catalog.

Discovering Tables

LIST CATALOG TABLES;

Core Tables

CATALOG.ENTITIES

Information about all entities in the project.

ColumnDescription
IdUnique identifier
NameEntity name
ModuleNameModule containing the entity
QualifiedNameFull qualified name (Module.Entity)
EntityTypePersistent, Non-Persistent, View, External
DescriptionDocumentation text
AttributeCountNumber of attributes
AccessRuleCountNumber of access rules defined
SELECT Name, EntityType, AttributeCount
FROM CATALOG.ENTITIES
WHERE ModuleName = 'Sales'
ORDER BY Name;

CATALOG.ATTRIBUTES

Information about entity attributes.

ColumnDescription
IdUnique identifier
NameAttribute name
EntityIdParent entity ID
AttributeTypeString, Integer, Decimal, Boolean, DateTime, etc.
SELECT a.Name, a.AttributeType
FROM CATALOG.ATTRIBUTES a
JOIN CATALOG.ENTITIES e ON a.EntityId = e.Id
WHERE e.QualifiedName = 'Sales.Customer';

CATALOG.MODULES

One row per module, including System and Marketplace modules.

ColumnDescription
IdModule UUID
NameModule name
Source"" for your own modules and System; "Marketplace v1.2.3" for a downloaded module
AppStoreVersionMarketplace version, when downloaded
DescriptionAlways empty: a Mendix module has no documentation property
DomainModelDocumentationThe module’s domain model’s documentation — the module-level text an author can write
SELECT Name FROM CATALOG.MODULES
WHERE Source = '' AND COALESCE(DomainModelDocumentation, '') = '';

CATALOG.ASSOCIATIONS

Information about entity associations, same-module and cross-module.

ColumnDescription
IdUnique identifier
NameAssociation name
QualifiedNameModule.Association
ModuleNameModule that owns the association
FromEntityFROM entity qualified name (the one that owns the reference)
ToEntityTO entity qualified name; for a cross-module association, the other module’s entity
AssociationTypeReference or ReferenceSet
OwnerDefault or Both
StorageFormatColumn or Table
DescriptionDocumentation
ToDeleteBehaviorDelete behaviour of the TO end — Mendix’s ChildDeleteBehavior, the end MDL’s on delete clause sets: DeleteMeButKeepReferences (default), DeleteMeAndReferences, DeleteMeIfNoReferences
FromDeleteBehaviorDelete behaviour of the FROM end — Mendix’s ParentDeleteBehavior (Studio Pro only)
ToDeleteErrorMessage / FromDeleteErrorMessageMessage shown when a DeleteMeIfNoReferences delete on that end is refused

Mendix’s Parent/Child pointer names are inverted relative to MDL’s FROM/TO: ParentPointer is the FROM entity and ChildPointer the TO entity, so the Child* delete behaviour belongs to the TO end. Mendix always stores both ends, so an explicitly set behaviour is one that is not the default. System module associations have no stored delete behaviour and read as ''.

SELECT QualifiedName, ToDeleteBehavior, FromDeleteBehavior
FROM CATALOG.ASSOCIATIONS
WHERE ToDeleteBehavior <> 'DeleteMeButKeepReferences'
   OR FromDeleteBehavior <> 'DeleteMeButKeepReferences';

CATALOG.MICROFLOWS

Information about microflows, nanoflows and rules (CATALOG.NANOFLOWS is the nanoflow subset).

ColumnDescription
IdUnique identifier
NameMicroflow name
ModuleNameModule containing the microflow
QualifiedNameFull qualified name
FolderFolder path within the module
MicroflowTypeMICROFLOW, NANOFLOW or RULE
ReturnTypeReturn type of the microflow
DescriptionDocumentation text
ParameterCountNumber of parameters
ActivityCountActivities at the top level of the flow, excluding start/end events and merges. A loop counts as one
TotalActivityCountActivityCount plus every activity inside a loop, at any depth
ComplexityMcCabe cyclomatic complexity
SELECT Name, ReturnType, ActivityCount, TotalActivityCount
FROM CATALOG.MICROFLOWS
WHERE ModuleName = 'Sales'
ORDER BY Name;

CATALOG.ACTIVITIES

One row per object in a microflow, nanoflow or rule body — activities, splits, merges, events, loops and annotations. Populated by REFRESH CATALOG FULL.

Loop bodies are included. The objects inside a loop, at any depth, are rows too, with ParentLoopId naming the loop. Earlier releases left them out; a query written then that should keep its old result filters on ParentLoopId = ''.

ColumnDescription
IdThe object’s ID
MicroflowId, MicroflowQualifiedName, ModuleNameThe flow it belongs to
SequencePre-order position in the flow: a loop, then its body, then the loop’s next sibling
ParentLoopIdId of the enclosing loop; empty at the top level
LoopDepthNumber of enclosing loops; 0 at the top level
ActivityTypeActionActivity, ExclusiveSplit, InheritanceSplit, ExclusiveMerge, LoopedActivity, Annotation, StartEvent, EndEvent, …
ActionTypeThe action of an ActionActivity, e.g. RetrieveAction, JavaActionCallAction, WebServiceCallAction
NameActionType for an action activity, otherwise ActivityType
CaptionThe stored caption: an activity’s, a split’s, or an annotation’s text. Empty for events, merges and loops. With AutoGenerateCaption it holds Studio Pro’s stored placeholder (often Activity)
AutoGenerateCaption1 when Studio Pro generates the activity’s caption
DescriptionDocumentation of an action activity, split or loop
EntityRefEntity of a create object, a database retrieve, or a delete (the deleted variable’s entity, when the flow types it)
ServiceRef, ActionRefCalled service and operation: REST, web service, OData action. For a microflow, nanoflow, Java or JavaScript action call, ActionRef is the called document and ServiceRef is empty
QueueRefTask queue a microflow or Java action call runs in; empty when it runs in place
UseRequestTimeout, TimeoutExpression“Use a timeout” and its seconds, for a REST or web service call
ConditionExpressionAn exclusive split’s expression
ConditionRuleThe rule a rule-based split calls
ErrorHandlingTypeRollback, Custom, CustomWithoutRollBack (capital B), Continue or Abort — read from the action for an action activity
LogLevel, LogNodeExpression, LogMessageA log message action’s level, node expression ('MyNode' or getKey(…)) and template
CommitTypeCreate/change object: Yes, YesWithoutEvents or No
WithEvents1 for a commit with events, and a create/change with CommitType Yes
RetrieveSourcedatabase or association
-- Database retrieves inside a loop (N+1 queries)
SELECT MicroflowQualifiedName, EntityRef, LoopDepth
FROM CATALOG.ACTIVITIES
WHERE ActionType = 'RetrieveAction' AND RetrieveSource = 'database' AND ParentLoopId <> '';

-- Microflows called from inside a loop, synchronously (a queued call runs outside it)
SELECT MicroflowQualifiedName, ActionRef
FROM CATALOG.ACTIVITIES
WHERE ActionType = 'MicroflowCallAction' AND ParentLoopId <> '' AND QueueRef = '';

CATALOG.PAGES

Information about pages and their properties.

ColumnDescription
IdUnique identifier
NamePage name
QualifiedNameFull qualified name
ModuleNameModule containing the page
FolderFolder path within the module
TitlePage title in the project’s default language (else en_US, else the lowest-sorted non-empty language). Every translation is in CATALOG.STRINGS (StringContext = 'Forms$Page.Title')
URLPage URL if configured
LayoutRefQualified name of the layout (full build only)
DescriptionDocumentation text
ParameterCountNumber of page parameters
WidgetCountNumber of widgets (full build only; 0 otherwise)
Excluded1 when the page is excluded from the project
SELECT Name, Title, URL
FROM CATALOG.PAGES
WHERE ModuleName = 'Sales'
ORDER BY Name;

Page templates are not pages and are not in this table — see CATALOG.PAGE_TEMPLATES.

CATALOG.WIDGETS

One row per widget instance on a page or snippet. Full build only (refresh catalog full); a fast build leaves the table empty.

ColumnDescription
IdThe widget’s element ID
NameWidget name
WidgetTypeStorage type (Forms$DataView, Forms$ActionButton, …); a pluggable widget’s id (com.mendix.widget.web.datagrid.Datagrid)
ContainerId, ContainerQualifiedName, ContainerTypeThe page or snippet holding the widget; ContainerType is PAGE or SNIPPET
ModuleName, FolderThe container’s module and folder
EntityRef, AttributeRef, MicroflowRef, NanoflowRef, PageRefWhat the widget’s own content references: datasource entity, bound attribute, action or datasource flow, the page its action opens
ParentWidgetIdId of the nearest widget in this table that encloses it; empty at the page or snippet root. What the catalog skips is transparent: the synthetic conditionalVisibilityWidget… container, layout grid rows and columns, tab pages, a pluggable widget’s properties and object-list items. A widget in a layout grid column or a data grid 2 column has the grid as its parent
DepthNumber of ancestors in this table: 0 at the root. A list view template is a row of its own, so its widgets are two below the list view. A snippet call is not entered: a snippet’s widgets have their own rows, depth 0 at the snippet root
Class, Style, DynamicClassesThe widget’s Appearance
ActionTypeStored type of the primary action — Action (buttons), else OnClickAction (containers), else ClickAction (list views, images): Forms$DeleteClientAction, Forms$MicroflowAction, Forms$CallNanoflowClientAction, Forms$FormAction (show page), Forms$NoAction, …; empty for a widget without one. A pluggable widget’s actions are not read
HasConfirmation1 when the primary action asks for confirmation. Only microflow, nanoflow and workflow calls have that setting; a delete action never does
-- Widgets nested more than five deep, deepest first
SELECT ContainerQualifiedName, Name, WidgetType, Depth
FROM CATALOG.WIDGETS
WHERE Depth > 5
ORDER BY Depth DESC;

-- Buttons that delete without going through a flow
SELECT ContainerQualifiedName, Name
FROM CATALOG.WIDGETS
WHERE ActionType = 'Forms$DeleteClientAction';

CATALOG.PAGE_TEMPLATES

The starting points Studio Pro’s “new page” dialog offers (Forms$PageTemplate). A separate document type from pages: Atlas_Web_Content ships 46 templates and no pages at all.

ColumnDescription
IdUnique identifier
NameTemplate name
ModuleNameModule containing the template
QualifiedNameFull qualified name
FolderFolder path within the module
DescriptionDocumentation

There is no DESCRIBE PAGE TEMPLATE, so a template is indexed but not describable — tools that walk a module report it as unknown, never as unchanged.

CATALOG.LAYOUTS

Page layouts (Forms$Layout), including those in Marketplace modules such as Atlas_Core.

ColumnDescription
IdUnique identifier
NameLayout name
QualifiedNameFull qualified name
ModuleNameModule containing the layout
FolderFolder path within the module
LayoutTypeResponsive, Phone, Tablet, ModalPopup (web); Default, Popup (native)
PlatformWeb or Native — the platform every page on this layout renders on. React-client errors such as CE0582 apply to Web pages only
DescriptionDocumentation text
-- pages on a native layout (needs a full build for LayoutRef)
SELECT p.QualifiedName
FROM CATALOG.PAGES p JOIN CATALOG.LAYOUTS l ON l.QualifiedName = p.LayoutRef
WHERE l.Platform = 'Native';

CATALOG.ACCESS_RULES

Information about entity access rules (available after full refresh).

ColumnDescription
IdUnique identifier
EntityIdEntity this rule applies to
UserRoleRole this rule grants access to
AllowReadWhether read access is granted
AllowWriteWhether write access is granted
SELECT e.QualifiedName, ar.UserRole, ar.AllowRead, ar.AllowWrite
FROM CATALOG.ACCESS_RULES ar
JOIN CATALOG.ENTITIES e ON ar.EntityId = e.Id
WHERE e.ModuleName = 'Sales';

CATALOG.SCHEDULED_EVENTS

Scheduled events — Mendix’s cron.

ColumnDescription
Name, QualifiedName, ModuleName, FolderIdentity
MicroflowQualified name of the microflow the event runs
RepeatSchedule variant: Minute, Hour, Day, Week, MonthDate, MonthWeekday, YearDate, YearWeekday
RepeatDescriptionThe schedule as a phrase, e.g. weekly Mon/Fri at 09:30
IntervalSecondsGap between runs, derived from the schedule
Enabled1 if the event runs
TimeZoneUTC or Server
OnOverlapDelayNext or SkipNext

IntervalSeconds comes from the schedule, not from the stored Interval/IntervalType pair. Those are a legacy sibling that Studio Pro writes and does not keep in sync — a shipped Mendix module stores 0/Minute beside a daily schedule — so a query keyed on them would read a nightly job as firing every 0 seconds. Month and year figures are averages (30 and 365 days): the column is for thresholds and ordering, not calendar arithmetic.

-- Anything that fires more often than once a minute
select QualifiedName, RepeatDescription, Microflow
from CATALOG.SCHEDULED_EVENTS
where Enabled = 1 and IntervalSeconds < 60;

-- Scheduled events whose microflow no longer exists
select se.QualifiedName, se.Microflow
from CATALOG.SCHEDULED_EVENTS se
left join CATALOG.MICROFLOWS m on m.QualifiedName = se.Microflow
where m.Id is null;

A scheduled event also produces a schedule row in CATALOG.REFS, so list callers of <microflow> and the dead-asset analysis both see it. Without that edge a microflow run only by a scheduled event looked unreferenced.

CATALOG.QUEUES

Task queues.

ColumnDescription
Name, QualifiedName, ModuleName, FolderIdentity
ParallelismHow many tasks run at once — an expression string, not a number
ClusterWide1 if the limit applies across the cluster

Parallelism is stored as text because Mendix stores an expression: a query must not assume it parses as an integer.

select QualifiedName, Parallelism, ClusterWide from CATALOG.QUEUES;

Offline synchronization

CATALOG.OFFLINE_ENTITY_CONFIGS — one row per entity an offline navigation profile synchronizes.

select ProfileName, EntityQualifiedName, SyncMode, XPathConstraint
  from CATALOG.OFFLINE_ENTITY_CONFIGS
 where SyncMode = 'All';

CATALOG.NAVIGATION_PROFILES.OfflineEntityCount says how many and nothing else; this table is what makes “which entities does this profile sync, and how?” answerable — the first question anyone auditing an offline app asks.

SyncMode is the value Mendix stores, not the caption Studio Pro shows: All, Constrained, Never, None, NoneAndPreserveData, Online. Its dialog’s “All Objects” is All and “By XPath” is Constrained.

CompatibilityMode is indexed although MDL cannot author it. The catalog reports what is stored, and a flag invisible to every query is one nobody discovers until it matters.

A configured entity also produces a sync row in CATALOG.REFS, so list references to Sales.Order names the profiles that download it:

select SourceName, TargetName from CATALOG.REFS where RefKind = 'sync';

Every mode gets an edge, including the ones that download nothing. A profile with sync Sales.Audit never still names that entity, so renaming or dropping it leaves the configuration dangling — which is precisely what a reference edge exists to reveal.

Entity event handlers

CATALOG.ENTITY_EVENT_HANDLERS — one row per entity event handler: which moment, which event, and which microflow runs.

select EntityQualifiedName, Moment, Event, Microflow
  from CATALOG.ENTITY_EVENT_HANDLERS
 where Moment = 'Before' and Event = 'Commit';

CATALOG.ENTITIES.HasEventHandlers says some exist and nothing else — the same shape NavigationProfile.OfflineEntityCount had. The distinction the flag loses is the one that matters: a Before handler with RaiseErrorOnFalse can veto the commit, an After handler cannot.

Moment is Before or After. Event is the value Mendix stores, not the caption Studio Pro shows: Create, Commit, Delete, RollBack — note the capital B, which generated/metamodel confirms (DomainModelsEventRollBack = "RollBack") and which disagrees with every neighbouring enum in that file, where the same word is Rollback. A query spelling it the expected way returns zero rows rather than an error.

A handler also produces an event row in CATALOG.REFS, so a microflow that runs only as a handler has callers:

select SourceName, TargetName from CATALOG.REFS where RefKind = 'event';

Without that edge the handler microflow was reported dead from three directions at once — list callers said (no callers found), CATALOG.GRAPH_DEAD_ASSETS listed it, and mxcli lint emitted QUAL004 “is not called from anywhere” with the suggestion Remove if unused — on code that runs on every commit (mendixlabs/mxcli#1127).

The edge carries neither the moment nor the event; refs has no column for them, and a kind per combination would put eight kinds into every consumer’s list to say one thing. Which moment and which event is this table’s question.

Graph-Analysis Tables

The dependency graph (CATALOG.REFS, full refresh) is analysed by a family of graph_* views and tables — god nodes, module coupling/cohesion, dead documents, communities, cycles, layers, centrality, and the integration surface. The community/cycle/layer/centrality tables are populated by REFRESH CATALOG COMMUNITIES — a pass, not a build mode, so a full-mode catalog has them empty until it runs and a query against one says so rather than returning 0 rows. See Graph Analysis for the full reference and the mxcli graph-report command.

Cycles come in two flavours, because they are two questions: CATALOG.GRAPH_CYCLES for tangled documents and CATALOG.GRAPH_MODULE_CYCLES for tangled modules — the second is not a rollup of the first, since modules reference each other through documents that need form no cycle themselves. CATALOG.GRAPH_ANALYSIS_SCOPE reports which reference kinds reach the computed asset graph, which is what to check when a graph_module_coupling edge seems to have no effect on cycles or layers.

select * from CATALOG.graph_god_nodes order by Degree desc limit 20;
select * from CATALOG.graph_module_coupling order by Edges desc;
select * from CATALOG.graph_module_cycles order by CycleSize desc;
list communities;

Listing All Tables

To see the complete list of available tables in your catalog (which may vary by project and refresh level):

LIST CATALOG TABLES;
mxcli -p app.mpr -c "LIST CATALOG TABLES"