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
15 changes: 15 additions & 0 deletions docs/mooseide-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,18 @@ 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.

## SQL CoUsage

Select **SQL relation references** as the inner-box extractor in the standard
CoUsage map settings, or use:

```smalltalk
FmxSQLCoUsageExtractor openOn: (model allWithType: FmxSQLStoredProcedure).
```

Containers are routines, views or tables; inner boxes are referenced database
tables/views. Column references are projected to their owning relation, and
foreign keys contribute referenced relations. Repeated references retain usage
counts. Empty results mean no modeled references, not proof that dynamic SQL has
no dependencies. The helper rejects mixed/unsupported input before opening.
41 changes: 41 additions & 0 deletions src/FamixNGSQL-MooseIDE-Tests/FmxSQLCoUsageTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Class {
#name : #FmxSQLCoUsageTest,
#superclass : #TestCase,
#category : #'FamixNGSQL-MooseIDE-Tests'
}
{ #category : #tests }
FmxSQLCoUsageTest >> testSharedRelationsAndRepeatedReferences [
| model table column first second extractor browser |
model := FmxSQLModel new.
table := FmxSQLTable new name: 'records'; mooseModel: model; yourself.
column := FmxSQLColumn new name: 'id'; columnsContainer: table; mooseModel: model; yourself.
first := FmxSQLStoredProcedure new name: 'first'; mooseModel: model; yourself.
second := FmxSQLStoredProcedure new name: 'second'; mooseModel: model; yourself.
FmxSQLColumnReference new source: first; column: column; mooseModel: model.
FmxSQLTableReference new source: first; table: table; mooseModel: model.
FmxSQLTableReference new source: second; table: table; mooseModel: model.
extractor := FmxSQLCoUsageExtractor new.
self assert: (extractor innerEntitiesFor: first) asArray equals: { table. table }.
self assert: (extractor innerEntitiesFor: second) asArray equals: { table }.
browser := FmxSQLCoUsageExtractor openOn: { first. second }.
[ self assert: browser specModel containerBoxes size equals: 2.
self assert: browser specModel innerBoxes size equals: 1 ]
ensure: [ browser window close ]
]
{ #category : #tests }
FmxSQLCoUsageTest >> testForeignKeyAndEmptyTable [
| model source target column constraint |
model := FmxSQLModel new.
source := FmxSQLTable new name: 'source'; mooseModel: model; yourself.
target := FmxSQLTable new name: 'target'; mooseModel: model; yourself.
column := FmxSQLColumn new name: 'id'; columnsContainer: target; mooseModel: model; yourself.
constraint := FmxSQLForeignKeyConstraint new name: 'fk'; table: source; mooseModel: model; yourself.
FmxSQLColumnReference new foreignKeyConstraintSource: constraint; column: column; mooseModel: model.
self assert: (FmxSQLCoUsageExtractor new innerEntitiesFor: source) asArray equals: { target }.
self assertEmpty: (FmxSQLCoUsageExtractor new innerEntitiesFor: target)
]
{ #category : #tests }
FmxSQLCoUsageTest >> testUnsupportedInputIsRejectedBeforeOpening [
self should: [ FmxSQLCoUsageExtractor openOn: { Object new } ] raise: Error.
self should: [ FmxSQLCoUsageExtractor new innerEntitiesFor: Object new ] raise: Error
]
46 changes: 46 additions & 0 deletions src/FamixNGSQL-MooseIDE/FmxSQLCoUsageExtractor.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"Co-usage of database relations: containers are routines, views or tables;
inner boxes are referenced tables/views. Repeated references retain their frequency."
Class {
#name : #FmxSQLCoUsageExtractor,
#superclass : #MiCoInnerEntitiesAbstractExtractor,
#category : #'FamixNGSQL-MooseIDE'
}
{ #category : #accessing }
FmxSQLCoUsageExtractor class >> menuItemName [ ^ 'SQL relation references' ]
{ #category : #accessing }
FmxSQLCoUsageExtractor class >> description [
^ 'Referenced tables and views, including column and foreign-key references. Repeated references count as repeated uses.'
]
{ #category : #testing }
FmxSQLCoUsageExtractor class >> accepts: entity [
^ { FmxSQLTable. FmxSQLForeignTable. FmxSQLView. FmxSQLStoredProcedure }
anySatisfy: [ :class | entity isKindOf: class ]
]
{ #category : #opening }
FmxSQLCoUsageExtractor class >> openOn: entities [
| browser |
(entities allSatisfy: [ :entity | self accepts: entity ]) ifFalse: [
self error: 'SQL CoUsage expects only tables, views or routines' ].
browser := MiCoUsageMapBrowser new.
browser specModel settings innerBoxExtractor: self.
browser open.
browser followEntity: entities asMooseGroup.
^ browser
]
{ #category : #querying }
FmxSQLCoUsageExtractor >> innerEntitiesFor: entity [
| relations |
(self class accepts: entity) ifFalse: [ self error: 'Unsupported SQL CoUsage entity' ].
relations := OrderedCollection new.
entity queryAllOutgoing do: [ :reference |
((reference isKindOf: FmxSQLColumnReference) or: [
(reference isKindOf: FmxSQLTableReference) or: [ reference isKindOf: FmxSQLViewReference ] ]) ifTrue: [
reference allTargets asSet do: [ :target |
| relation |
relation := (target isKindOf: FmxSQLColumn)
ifTrue: [ target columnsContainer ] ifFalse: [ target ].
((relation isKindOf: FmxSQLTable) or: [
(relation isKindOf: FmxSQLForeignTable) or: [ relation isKindOf: FmxSQLView ] ])
ifTrue: [ relations add: relation ] ] ] ].
^ relations
]