Skip to content

Commit

Permalink
Added support for interval queries
Browse files Browse the repository at this point in the history
  • Loading branch information
mtabacman committed Mar 22, 2024
1 parent 1b6a558 commit 2aad432
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
16 changes: 16 additions & 0 deletions source/Sagan-Core/InMemoryRepository.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ InMemoryRepository >> findAll [
^ contents copy
]

{ #category : 'querying' }
InMemoryRepository >> findAllFrom: aFromIndex to: 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
133 changes: 133 additions & 0 deletions source/Sagan-GemStone-Tests/GemStoneRepositoryProviderTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,139 @@ GemStoneRepositoryProviderTest >> testQueryReturningBeforeAllIndexedResultsAreRe
]
]

{ #category : 'tests' }
GemStoneRepositoryProviderTest >> testQueryingIndexedCollectionByStreaming [

1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta
].

self extraterrestrials store: self silvesterStallone.

1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta
].

self extraterrestrials withQueryFrom: 'each.firstName >= ''''' do: [ :query |
| stream silvesterStallone |

stream := query readStream.
stream skip: 2000 * 3.
silvesterStallone := stream next.
self assert:
( silvesterStallone firstName = 'Silvester' and: [ silvesterStallone lastName = 'Stallone' ] ).
self assert: stream atEnd
]
]

{ #category : 'tests' }
GemStoneRepositoryProviderTest >> testQueryingIndexedCollectionForAllElements [

4 timesRepeat: [
1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta
].

self extraterrestrials store: self silvesterStallone.

1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta
]
].
self extraterrestrials withQueryFrom: 'true' do: [ :query |
self assert: query size equals: 3000 + 1 + 3000 * 4.
self
assert: ( query select: [ :extraterrestrial |
extraterrestrial firstName = 'Silvester' and: [ extraterrestrial lastName = 'Stallone' ] ] )
size
equals: 4.
self
assert: ( query select: [ :extraterrestrial |
extraterrestrial firstName = 'John' and: [ extraterrestrial lastName = 'Travolta' ] ] ) size
equals: 2000 * 4.
self
assert: ( query select: [ :extraterrestrial |
extraterrestrial firstName = 'John' and: [ extraterrestrial lastName = 'Lock' ] ] ) size
equals: 2000 * 4.
self
assert: ( query select: [ :extraterrestrial |
extraterrestrial firstName = 'Ella' and: [ extraterrestrial lastName = 'Travolta' ] ] ) size
equals: 2000 * 4
]
]

{ #category : 'tests' }
GemStoneRepositoryProviderTest >> testQueryingIndexedCollectionForNoElements [

4 timesRepeat: [
1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta
].

self extraterrestrials store: self silvesterStallone.

1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta
]
].
self extraterrestrials withQueryFrom: 'false' do: [ :query | self assert: query isEmpty ]
]

{ #category : 'tests' }
GemStoneRepositoryProviderTest >> testQueryingInterval [

| result |

1000 timesRepeat: [
self extraterrestrials
store: self johnTravolta;
store: self johnLock;
store: self ellaTravolta;
store: self silvesterStallone
].

result := self extraterrestrials findAllFrom: 1000 to: 1001 sortedBy: '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 to: 4005 sortedBy: 'lastName'.
self
withTheOnlyOneIn: result
do: [ :extraterrestrial | self assert: extraterrestrial lastName equals: 'Travolta' ].
result := self extraterrestrials findAllFrom: 4000 to: 4005 sortedBy: 'firstName'.
self withTheOnlyOneIn: result do: [ :extraterrestrial |
self
assert: extraterrestrial firstName equals: 'Silvester';
assert: extraterrestrial lastName equals: 'Stallone'
].

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

{ #category : 'tests' }
GemStoneRepositoryProviderTest >> testQueryingWhenCollectionIsLargeAndIndexed [

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

{ #category : 'querying' }
GemStoneRepository >> findAllFrom: aFromIndex to: aToIndex sortedBy: anIndexName [

| results |

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

stream := query readStream.
start := aFromIndex - 1 max: 0.
limit := aToIndex - start max: 0.
stream skip: start.
limit timesRepeat: [ stream atEnd ifFalse: [ results add: stream next ] ]
].
^ results
]

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

Expand Down

0 comments on commit 2aad432

Please sign in to comment.