Skip to content

Commit

Permalink
Support limit and offset in RDBMS
Browse files Browse the repository at this point in the history
  • Loading branch information
mtabacman committed Mar 25, 2024
1 parent bf216d6 commit 9dc3aac
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 52 deletions.
50 changes: 50 additions & 0 deletions source/Sagan-Core-Tests/RepositoryBasedTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@ RepositoryBasedTest >> sistineStallone [
^ self extraterrestrialNamedFirst: 'Sistine' last: 'Stallone' bornOn: (Date year: 1998 month: 6 day: 27)
]

{ #category : 'tests - querying' }
RepositoryBasedTest >> testCountAll [

self extraterrestrials
store: self silvesterStallone;
store: self sistineStallone.

self assert: self extraterrestrials countAll equals: 2
]

{ #category : 'tests - querying' }
RepositoryBasedTest >> testCountMatching [

Expand All @@ -153,6 +163,46 @@ RepositoryBasedTest >> testCountMatching [
assert: ( self extraterrestrials countMatching: [ :person | person birthDate = (Date year: 1998 month: 6 day: 27) ] ) equals: 1
]

{ #category : 'tests - querying' }
RepositoryBasedTest >> testFindAllFromUpToSortedByAscending [

| found |

self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self silvesterStallone.

found := self extraterrestrials findAllFrom: 2 upTo: 2 sortedByAscending: #lastName.
self
withTheOnlyOneIn: found
do: [ :extraterrestrial | self assert: extraterrestrial lastName equals: 'Stallone' ].

found := self extraterrestrials findAllFrom: 1 upTo: 1 sortedByAscending: #lastName.
self
withTheOnlyOneIn: found
do: [ :extraterrestrial | self assert: extraterrestrial lastName equals: 'Lock' ].

found := self extraterrestrials findAllFrom: 1 upTo: 2 sortedByAscending: #firstName.
self assert: ( found allSatisfy: [ :extraterrestrial | extraterrestrial firstName = 'John' ] ).

found := self extraterrestrials findAllFrom: 8 upTo: 9 sortedByAscending: #lastName.
self assert: found isEmpty.

self
should: [ self extraterrestrials findAllFrom: 0 upTo: 0 sortedByAscending: #lastName ]
raise: PersistenceCommandFailed
withMessageText: 'Starting position must be strictly positive.'.
self
should: [ self extraterrestrials findAllFrom: -6 upTo: 1 sortedByAscending: #lastName ]
raise: PersistenceCommandFailed
withMessageText: 'Starting position must be strictly positive.'.
self
should: [ self extraterrestrials findAllFrom: 3 upTo: 1 sortedByAscending: #lastName ]
raise: PersistenceCommandFailed
withMessageText: 'Maximum position must be equal or greater than starting position.'
]

{ #category : 'tests - querying' }
RepositoryBasedTest >> testFindAllMatching [

Expand Down
32 changes: 16 additions & 16 deletions source/Sagan-Core/InMemoryRepository.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,6 @@ InMemoryRepository >> findAll [
^ contents copy
]

{ #category : 'querying' }
InMemoryRepository >> findAllFrom: aFromIndex upTo: aToIndex sortedBy: anIndexName [

| from to |

contents ifEmpty: [ ^ contents ].

from := ( aFromIndex min: contents size ) max: 0.
to := ( aToIndex min: contents size ) max: 0.

^ ( contents sorted: [ :a :b |
( a instVarNamed: anIndexName asString ) <= ( b instVarNamed: anIndexName asString ) ] )
copyFrom: from
to: to
]

{ #category : 'querying' }
InMemoryRepository >> findAllMatching: aCriteriaOrBlock [

Expand Down Expand Up @@ -143,6 +127,22 @@ InMemoryRepository >> updateAfterCheckingConflicts: aDomainObject with: anUpdate
^ aDomainObject
]

{ #category : 'private - querying' }
InMemoryRepository >> validatedFindAllFrom: aStartingPosition upTo: aMaximumPosition sortedByAscending: aVariableName [

| from to |

( contents isEmpty or: [ aStartingPosition > contents size ] ) ifTrue: [ ^ Set new ].

from := aStartingPosition max: 1.
to := ( aMaximumPosition min: contents size ) max: 1.

^ ( contents sorted: [ :a :b |
( a instVarNamed: aVariableName asString ) <= ( b instVarNamed: aVariableName asString ) ] )
copyFrom: from
to: to
]

{ #category : 'querying' }
InMemoryRepository >> withOneMatching: aCriteriaOrBlock do: foundBlock else: noneBlock [

Expand Down
49 changes: 41 additions & 8 deletions source/Sagan-Core/RepositoryBehavior.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ RepositoryBehavior >> asMatchingCriteria: aBlockOrCriteria [
^ aBlockOrCriteria asMatchingCriteriaIn: self
]

{ #category : 'private - preconditions' }
RepositoryBehavior >> assertBoundariesAreValidFrom: aStartingPosition upTo: aMaximumPosition [

aStartingPosition strictlyPositive ifFalse: [
PersistenceCommandFailed signal: 'Starting position must be strictly positive.' ].

aStartingPosition <= aMaximumPosition ifFalse: [
PersistenceCommandFailed signal:
'Maximum position must be equal or greater than starting position.' ]
]

{ #category : 'private - preconditions' }
RepositoryBehavior >> assertIncludes: inMemoryObject [

Expand Down Expand Up @@ -62,28 +73,44 @@ RepositoryBehavior >> conflictCheckingStrategy [
^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> countAll [

^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> countMatching: aCriteria [

self subclassResponsibility
^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> findAll [

self subclassResponsibility
RepositoryBehavior >> findAll [

^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> findAllFrom: aStartingPosition upTo: aMaximumPosition sortedByAscending: aVariableName [

self assertBoundariesAreValidFrom: aStartingPosition upTo: aMaximumPosition.
^ self
validatedFindAllFrom: aStartingPosition
upTo: aMaximumPosition
sortedByAscending: aVariableName
]

{ #category : 'querying' }
RepositoryBehavior >> findAllMatching: aCriteria [

self subclassResponsibility
^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> findAllMatching: aCriteria sortedBy: aSortCriteria [

self subclassResponsibility
^ self subclassResponsibility
]

{ #category : 'private - accessing' }
Expand Down Expand Up @@ -153,14 +180,20 @@ RepositoryBehavior >> updateAfterCheckingConflicts: aDomainObject with: anUpdate
^ self subclassResponsibility
]

{ #category : 'private - querying' }
RepositoryBehavior >> validatedFindAllFrom: aStartingPosition upTo: aMaximumPosition sortedByAscending: aVariableName [

^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> withOneMatching: aCriteria do: foundBlock else: noneBlock [

self subclassResponsibility
^ self subclassResponsibility
]

{ #category : 'querying' }
RepositoryBehavior >> withOneMatching: aCriteria sortedBy: aSortCriteria do: foundBlock else: noneBlock [

self subclassResponsibility
^ self subclassResponsibility
]
Original file line number Diff line number Diff line change
Expand Up @@ -195,27 +195,27 @@ GemStoneRepositoryProviderTest >> testQueryingInterval [
store: self silvesterStallone
].

result := self extraterrestrials findAllFrom: 1000 upTo: 1001 sortedBy: 'lastName'.
result := self extraterrestrials findAllFrom: 1000 upTo: 1001 sortedByAscending: 'lastName'.
self assert: result size equals: 2.
self assert: ( result first firstName = 'John' and: [ result first lastName = 'Lock' ] ).
self assert: ( result last firstName = 'Silvester' and: [ result last lastName = 'Stallone' ] ).

result := self extraterrestrials findAllFrom: 4000 upTo: 4005 sortedBy: 'lastName'.
result := self extraterrestrials findAllFrom: 4000 upTo: 4005 sortedByAscending: 'lastName'.
self
withTheOnlyOneIn: result
do: [ :extraterrestrial | self assert: extraterrestrial lastName equals: 'Travolta' ].
result := self extraterrestrials findAllFrom: 4000 upTo: 4005 sortedBy: 'firstName'.
result := self extraterrestrials findAllFrom: 4000 upTo: 4005 sortedByAscending: 'firstName'.
self withTheOnlyOneIn: result do: [ :extraterrestrial |
self
assert: extraterrestrial firstName equals: 'Silvester';
assert: extraterrestrial lastName equals: 'Stallone'
].

result := self extraterrestrials findAllFrom: -50 upTo: 0 sortedBy: 'lastName'.
result := self extraterrestrials findAllFrom: -50 upTo: 0 sortedByAscending: 'lastName'.
self assert: result isEmpty.
result := self extraterrestrials findAllFrom: 6 upTo: -2 sortedBy: 'lastName'.
result := self extraterrestrials findAllFrom: 6 upTo: -2 sortedByAscending: 'lastName'.
self assert: result isEmpty.
result := self extraterrestrials findAllFrom: 5000 upTo: 10000 sortedBy: 'lastName'.
result := self extraterrestrials findAllFrom: 5000 upTo: 10000 sortedByAscending: 'lastName'.
self assert: result isEmpty
]

Expand Down
46 changes: 24 additions & 22 deletions source/Sagan-GemStone/GemStoneRepository.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,6 @@ GemStoneRepository >> findAll [
^ contents copy
]

{ #category : 'querying' }
GemStoneRepository >> findAllFrom: aStartingPosition upTo: aMaximumPosition sortedBy: anIndexName [

| results |

results := OrderedCollection new.
self withQueryFrom: ( 'each.<1s> >= ''''' expandMacrosWith: anIndexName asString ) do: [ :query |
| stream skipped limit |

stream := query readStream.
skipped := aStartingPosition - 1 max: 0.
limit := aMaximumPosition - skipped max: 0.
stream skip: skipped.
limit timesRepeat: [
stream atEnd
ifTrue: [ ^ results ]
ifFalse: [ results add: stream next ]
]
].
^ results
]

{ #category : 'querying' }
GemStoneRepository >> findAllMatching: aCriteriaOrBlock [

Expand Down Expand Up @@ -181,6 +159,30 @@ GemStoneRepository >> updateAfterCheckingConflicts: aDomainObject with: anUpdate
^ aDomainObject
]

{ #category : 'private - querying' }
GemStoneRepository >> validatedFindAllFrom: aStartingPosition upTo: aMaximumPosition sortedByAscending: aVariableName [

| results |

results := OrderedCollection new.
self
withQueryFrom: ( 'each.<1s> >= ''''' expandMacrosWith: aVariableName asString )
do: [ :query |
| stream limit offset |

stream := query readStream.
limit := aMaximumPosition - aStartingPosition + 1.
offset := aStartingPosition - 1.
stream skip: offset.
limit timesRepeat: [
stream atEnd
ifTrue: [ ^ results ]
ifFalse: [ results add: stream next ]
]
].
^ results
]

{ #category : 'querying' }
GemStoneRepository >> withOneMatching: aCriteriaOrBlock do: foundBlock else: noneBlock [

Expand Down
19 changes: 19 additions & 0 deletions source/Sagan-RDBMS/RDBMSRepository.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ RDBMSRepository >> conflictCheckingStrategy [
^ conflictCheckingStrategy
]

{ #category : 'querying' }
RDBMSRepository >> countAll [

^ self withReadSessionDo: [ :session | session count: modelObjectClass ]
]

{ #category : 'querying' }
RDBMSRepository >> countMatching: aCriteriaOrBlock [

Expand Down Expand Up @@ -183,6 +189,19 @@ RDBMSRepository >> updateAfterCheckingConflicts: aDomainObject with: anUpdatedDo
^self update: aDomainObject executing: [:original | original synchronizeWith: anUpdatedDomainObject]
]

{ #category : 'private - querying' }
RDBMSRepository >> validatedFindAllFrom: aStartingPosition upTo: aMaximumPosition sortedByAscending: aVariableName [

| query limit offset |

limit := aMaximumPosition - aStartingPosition + 1.
offset := aStartingPosition - 1.
query := SimpleQuery read: modelObjectClass limit: limit.
query offset: offset.
aVariableName ascending asSortFunction asOrderByIn: query.
^ self executeQuery: query
]

{ #category : 'querying' }
RDBMSRepository >> withOneMatching: aCriteriaOrBlock do: foundBlock else: noneBlock [

Expand Down

0 comments on commit 9dc3aac

Please sign in to comment.