Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ immutable Moose 13 release. smalltalkCI selects it with `Moose64-13`.
| `Tests` | Core, importer tests and PgMetadata scenario-test support |
| `Generator` | Core and the metamodel generator |
| `GeneratorTests` | Generator plus its global-regeneration selection regression test |
| `LegacyUI` | Historical GT Inspector, analysis, Telescope and connection-manager packages |
| `MooseIDE` | Optional standard Moose tool adapters and Roassal 3 SQL views (requires Moose 13) |
| `MooseIDETests` | Optional tool and visualization regression tests |

`LegacyUI` has not been ported or validated on the current image. Core usage does
The unsupported `LegacyUI` load group is removed for v3. Historical sources remain archived in `src`; use the [Roassal 3 SQL views](docs/mooseide-integration.md) instead. Core usage does
not require those UI packages or a Genie MCP server. Loading modern Genie in a
historical Pharo 7 image is not part of the installation procedure.

Expand Down
14 changes: 14 additions & 0 deletions docs/mooseide-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ fork-first v3 development work, not a published v3 release.

GitHub CI loads these optional tests in the ready-made Moose image. The plain
Pharo job continues to test Core without GUI dependencies.

## Roassal 3 SQL views

The builders return unopened `RSCanvas` objects. Use any imported SQL model; there is no global `mi` dependency or implicit schema filter. For large databases pass a deliberately selected model, since all matching entities are drawn.

```smalltalk
(FmxSQLRoassalViews schemaTablesIn: model) openWithTitle: 'Schemas and tables'.
(FmxSQLRoassalViews foreignKeysIn: model) openWithTitle: 'Foreign keys'.
(FmxSQLRoassalViews routineCallsIn: model) openWithTitle: 'Routine call candidates'.
```

Schema boxes contain table boxes, like class/method nesting examples. Foreign-key arrows point from the referencing table to the referenced table; composite references collapse to one edge. Call arrows point from the enclosing routine to every candidate routine, including trigger routines. Candidate edges are static-analysis evidence, not proof of runtime calls. Disconnected entities remain visible; endpoints outside the supplied model are omitted. Edges are placed above nodes, and no entities or relationships are changed. Empty models yield empty canvases.

The historical Roassal 2/GT/Telescope sources remain in the repository for migration reference, but the unsupported `LegacyUI` load group is retired in v3. These Roassal 3 builders use current association APIs and replace the advertised visualization entry points.
3 changes: 1 addition & 2 deletions src/BaselineOfFAMIXNGSQL/BaselineOfFAMIXNGSQL.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,5 @@ BaselineOfFAMIXNGSQL >> baseline: spec [
group: 'GeneratorTests' with: #('Generator' 'FAMIXNGSQLMetamodelGenerator-Tests');
group: 'Tests' with: #('Core' 'FamixNGSQL-Importer-Tests');
group: 'MooseIDE' with: #('Core' 'FamixNGSQL-MooseIDE');
group: 'MooseIDETests' with: #('MooseIDE' 'FamixNGSQL-MooseIDE-Tests');
group: 'LegacyUI' with: #('Core' 'FamixNGSQL-GTInspectorExtension' 'FAMIXNGSQLAnalysis' 'FAMIXNGSQLAnalysis-ConnectionsManager') ]
group: 'MooseIDETests' with: #('MooseIDE' 'FamixNGSQL-MooseIDE-Tests') ]
]
60 changes: 60 additions & 0 deletions src/FamixNGSQL-MooseIDE-Tests/FmxSQLRoassalViewsTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Class {
#name : #FmxSQLRoassalViewsTest,
#superclass : #TestCase,
#category : #'FamixNGSQL-MooseIDE-Tests'
}
{ #category : #tests }
FmxSQLRoassalViewsTest >> testEmptyModel [
| model |
model := FmxSQLModel new.
#(schemaTablesIn: foreignKeysIn: routineCallsIn:) do: [ :selector |
| canvas |
canvas := FmxSQLRoassalViews perform: selector with: model.
self assert: canvas nodes isEmpty.
self assert: canvas edges isEmpty ]
]
{ #category : #tests }
FmxSQLRoassalViewsTest >> testCompositeForeignKeysAndDisconnectedTable [
| model source target lonely foreignKey canvas before |
model := FmxSQLModel new.
source := FmxSQLTable new name: 'orders'; mooseModel: model; yourself.
target := FmxSQLTable new name: 'customers'; mooseModel: model; yourself.
lonely := FmxSQLTable new name: 'disconnected'; mooseModel: model; yourself.
foreignKey := FmxSQLForeignKeyConstraint new table: source; mooseModel: model; yourself.
2 timesRepeat: [ | column |
column := FmxSQLColumn new columnsContainer: target; mooseModel: model; yourself.
FmxSQLColumnReference new foreignKeyConstraintSource: foreignKey; target: column; mooseModel: model ].
before := model entities size.
self assert: (FmxSQLRoassalViews foreignKeyPairsIn: model) asArray equals: { { source. target } }.
canvas := FmxSQLRoassalViews foreignKeysIn: model.
self assert: canvas nodes size equals: 3.
self assert: canvas edges size equals: 1.
self assert: canvas edges first from model identicalTo: source.
self assert: canvas edges first to model identicalTo: target.
self assert: model entities size equals: before
]
{ #category : #tests }
FmxSQLRoassalViewsTest >> testCallCandidatesIncludingTriggerAndExternalTarget [
| model caller target trigger external canvas |
model := FmxSQLModel new.
caller := FmxSQLStoredProcedure new name: 'caller'; mooseModel: model; yourself.
target := FmxSQLStoredProcedure new name: 'callee'; mooseModel: model; yourself.
trigger := FmxSQLTriggerStoredProcedure new name: 'trigger'; mooseModel: model; yourself.
external := FmxSQLStoredProcedure new name: 'outside'; yourself.
FmxSQLStoredProcedureCall new sender: caller; candidates: { target. trigger. external }; mooseModel: model.
self assert: (FmxSQLRoassalViews routineCallPairsIn: model) size equals: 2.
canvas := FmxSQLRoassalViews routineCallsIn: model.
self assert: canvas nodes size equals: 3.
self assert: canvas edges size equals: 2
]
{ #category : #tests }
FmxSQLRoassalViewsTest >> testSchemaContainsTableShapes [
| model schema table canvas |
model := FmxSQLModel new.
schema := FmxSQLNamespace new name: 'app'; mooseModel: model; yourself.
table := FmxSQLTable new name: 'items'; parentNamespace: schema; mooseModel: model; yourself.
canvas := FmxSQLRoassalViews schemaTablesIn: model.
self assert: canvas nodes size equals: 1.
self assert: canvas nodes first model identicalTo: schema.
self assert: (canvas nodes first allChildren anySatisfy: [ :shape | shape model == table ])
]
78 changes: 78 additions & 0 deletions src/FamixNGSQL-MooseIDE/FmxSQLRoassalViews.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"Roassal 3 views using SQL containment and association APIs. Builders return unopened canvases."
Class {
#name : #FmxSQLRoassalViews,
#superclass : #Object,
#category : #'FamixNGSQL-MooseIDE'
}
{ #category : #building }
FmxSQLRoassalViews class >> schemaTablesIn: model [
| graph |
graph := RSMondrian new.
graph shape box color: Color veryLightGray; labeled: #name.
graph nodes: (model allWithType: FmxSQLNamespace) forEach: [ :schema |
| tables |
tables := schema namespaceEntities select: [ :e | e isKindOf: FmxSQLTable ].
graph shape box color: Color blue lighter; labeled: #name.
graph nodes: tables.
graph layout grid ].
graph layout grid.
graph build.
^ graph canvas
]
{ #category : #building }
FmxSQLRoassalViews class >> foreignKeysIn: model [
^ self graphOf: (model allWithType: FmxSQLTable) pairs: (self foreignKeyPairsIn: model)
]
{ #category : #building }
FmxSQLRoassalViews class >> routineCallsIn: model [
^ self graphOf: (self routinesIn: model) pairs: (self routineCallPairsIn: model)
]
{ #category : #private }
FmxSQLRoassalViews class >> graphOf: entities pairs: pairs [
| graph |
graph := RSMondrian new.
graph shape box color: Color green muchLighter; labeled: [ :entity | self labelFor: entity ].
graph nodes: entities.
graph arrowedLine color: Color gray; connectToAll: [ :entity |
(pairs select: [ :pair | pair first == entity ]) collect: #second ].
graph layout circle.
graph build.
graph canvas edges do: #pushFront.
^ graph canvas
]
{ #category : #private }
FmxSQLRoassalViews class >> labelFor: entity [
^ (entity parentNamespace ifNil: [ '' ] ifNotNil: [ :ns | ns name, '.' ]), entity name
]
{ #category : #extracting }
FmxSQLRoassalViews class >> foreignKeyPairsIn: model [
| tables pairs |
tables := IdentitySet withAll: (model allWithType: FmxSQLTable).
pairs := Set new.
(model allWithType: FmxSQLForeignKeyConstraint) do: [ :foreignKey |
foreignKey outgoingForeignKeyColumnReferences do: [ :reference |
| target |
target := reference target ifNotNil: [ :column | column columnsContainer ].
((tables includes: foreignKey table) and: [ tables includes: target ]) ifTrue: [
pairs add: { foreignKey table. target } ] ] ].
^ pairs
]
{ #category : #extracting }
FmxSQLRoassalViews class >> routinesIn: model [
^ ((model allWithType: FmxSQLStoredProcedure) asOrderedCollection
addAll: (model allWithType: FmxSQLTriggerStoredProcedure); yourself) asIdentitySet
]
{ #category : #extracting }
FmxSQLRoassalViews class >> routineCallPairsIn: model [
| routines pairs |
routines := self routinesIn: model.
pairs := Set new.
(model allWithType: FmxSQLStoredProcedureCall) do: [ :call |
| caller |
caller := call source.
(caller notNil and: [ (routines includes: caller) not ]) ifTrue: [
caller := caller allParents detect: [ :parent | routines includes: parent ] ifNone: [ nil ] ].
(routines includes: caller) ifTrue: [
call allTargets do: [ :target | (routines includes: target) ifTrue: [ pairs add: { caller. target } ] ] ] ].
^ pairs
]