diff --git a/.github/workflows/PostgreSQL-Integration-Tests.yml b/.github/workflows/PostgreSQL-Integration-Tests.yml index de8d1ac..d8b5c23 100644 --- a/.github/workflows/PostgreSQL-Integration-Tests.yml +++ b/.github/workflows/PostgreSQL-Integration-Tests.yml @@ -1,18 +1,31 @@ name: PostgreSQL Integration Tests - -on: [push,pull_request,workflow_dispatch] - +on: + - push + - pull_request + - workflow_dispatch jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - smalltalk: [ Pharo64-11, Pharo64-10, Pharo64-9.0 ] - rdbms: [ PostgreSQLv9.4, PostgreSQLv9.5, PostgreSQLv9.6, PostgreSQLv10, PostgreSQLv11, PostgreSQLv12 , PostgreSQLv13 , PostgreSQLv14, PostgreSQLv15] + smalltalk: + - Pharo64-9.0 + - Pharo64-10 + - Pharo64-11 + rdbms: + - PostgreSQLv9.4 + - PostgreSQLv9.5 + - PostgreSQLv9.6 + - PostgreSQLv10 + - PostgreSQLv11 + - PostgreSQLv12 + - PostgreSQLv13 + - PostgreSQLv14 + - PostgreSQLv15 name: ${{ matrix.smalltalk }} + ${{ matrix.rdbms }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: hpi-swa/setup-smalltalkCI@v1 with: smalltalk-image: ${{ matrix.smalltalk }} @@ -29,5 +42,5 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: - name: ${{matrix.rdbms}}-${{matrix.smalltalk}} + name: Integration-Tests-${{matrix.rdbms}}-${{matrix.smalltalk}} token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/SQLite3-Integration-Tests.yml b/.github/workflows/SQLite3-Integration-Tests.yml index 97e40fb..00e82ef 100644 --- a/.github/workflows/SQLite3-Integration-Tests.yml +++ b/.github/workflows/SQLite3-Integration-Tests.yml @@ -1,18 +1,23 @@ name: SQLite3 Integration Tests - -on: [push,pull_request,workflow_dispatch] - +on: + - push + - pull_request + - workflow_dispatch jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - smalltalk: [ Pharo64-11, Pharo64-10, Pharo64-9.0 ] - rdbms: [ SQLite3 ] + smalltalk: + - Pharo64-9.0 + - Pharo64-10 + - Pharo64-11 + rdbms: + - SQLite3 name: ${{ matrix.smalltalk }} + ${{ matrix.rdbms }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: hpi-swa/setup-smalltalkCI@v1 with: smalltalk-image: ${{ matrix.smalltalk }} @@ -29,5 +34,5 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: - name: ${{matrix.rdbms}}-${{matrix.smalltalk}} + name: Integration-Tests-${{matrix.rdbms}}-${{matrix.smalltalk}} token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/loading-groups.yml b/.github/workflows/loading-groups.yml index 6a4438d..6e18d22 100644 --- a/.github/workflows/loading-groups.yml +++ b/.github/workflows/loading-groups.yml @@ -1,19 +1,28 @@ name: Baseline groups - -on: [push,pull_request,workflow_dispatch] - +on: + - push + - pull_request + - workflow_dispatch jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - smalltalk: [ Pharo64-11, Pharo64-10, Pharo64-9.0 ] - rdbms: [ SQLite3 ] - load-spec: [ deployment, tests, tools, development] + smalltalk: + - Pharo64-9.0 + - Pharo64-10 + - Pharo64-11 + rdbms: + - SQLite3 + load-spec: + - deployment + - tests + - tools + - development name: ${{ matrix.smalltalk }} + ${{ matrix.rdbms }} + ${{ matrix.load-spec }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: hpi-swa/setup-smalltalkCI@v1 with: smalltalk-image: ${{ matrix.smalltalk }} diff --git a/.github/workflows/loading-gs64-components.yml b/.github/workflows/loading-gs64-components.yml index 483d45d..911b1a2 100644 --- a/.github/workflows/loading-gs64-components.yml +++ b/.github/workflows/loading-gs64-components.yml @@ -3,7 +3,6 @@ on: - push - pull_request - workflow_dispatch - jobs: component-loading: runs-on: ubuntu-latest @@ -15,7 +14,7 @@ jobs: - Dependent-SUnit-Extensions name: GS64 + ${{ matrix.load-spec }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Load component in image uses: ba-st-actions/gs64-ci@v2 with: diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml index fbb50fa..84e4633 100644 --- a/.github/workflows/markdown-lint.yml +++ b/.github/workflows/markdown-lint.yml @@ -1,11 +1,14 @@ name: Markdown Lint -on: [push,pull_request,workflow_dispatch] +on: + - push + - pull_request + - workflow_dispatch jobs: remark-lint: name: runner / markdownlint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: markdownlint uses: reviewdog/action-markdownlint@v0 with: diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 6fe7559..38b6674 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -1,12 +1,13 @@ name: Shellcheck - -on: [push,pull_request] - +on: + - push + - pull_request + - workflow_dispatch jobs: shellcheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run Shellcheck uses: reviewdog/action-shellcheck@v1 with: diff --git a/.github/workflows/unit-tests-gs64.yml b/.github/workflows/unit-tests-gs64.yml index 6d19a48..fbf59cd 100644 --- a/.github/workflows/unit-tests-gs64.yml +++ b/.github/workflows/unit-tests-gs64.yml @@ -3,13 +3,12 @@ on: - push - pull_request - workflow_dispatch - jobs: unit-tests: runs-on: ubuntu-latest name: GS64 Unit Tests steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Load Image and Run Tests uses: ba-st-actions/gs64-ci@v2 with: diff --git a/source/BaselineOfSagan/BaselineOfSagan.class.st b/source/BaselineOfSagan/BaselineOfSagan.class.st index 63ff02c..2ce7b2e 100644 --- a/source/BaselineOfSagan/BaselineOfSagan.class.st +++ b/source/BaselineOfSagan/BaselineOfSagan.class.st @@ -37,16 +37,16 @@ BaselineOfSagan >> projectClass [ BaselineOfSagan >> setUpDependencies: spec [ spec - baseline: 'Kepler' with: [ spec repository: 'github://ba-st/Kepler:v6/source' ]; + baseline: 'Kepler' with: [ spec repository: 'github://ba-st/Kepler:v6' ]; project: 'Kepler-Core' copyFrom: 'Kepler' with: [ spec loads: 'Core' ]; project: 'Kepler-SUnit' copyFrom: 'Kepler' with: [ spec loads: 'Dependent-SUnit-Extensions' ]. spec - baseline: 'ObjectPool' with: [ spec repository: 'github://pharo-ide/ObjectPool:v1.0.3' ]; + baseline: 'ObjectPool' with: [ spec repository: 'github://ba-st-dependencies/ObjectPool:v2' ]; project: 'ObjectPool-Core' copyFrom: 'ObjectPool' with: [ spec loads: 'Core' ]. spec - baseline: 'Buoy' with: [ spec repository: 'github://ba-st/Buoy:v7/source' ]; + baseline: 'Buoy' with: [ spec repository: 'github://ba-st/Buoy:v7' ]; project: 'Buoy-SUnit' copyFrom: 'Buoy' with: [ spec loads: 'Dependent-SUnit-Extensions' ]; project: 'Buoy-Tools' copyFrom: 'Buoy' with: [ spec loads: 'Tools' ]. diff --git a/source/Sagan-Core-Tests/RepositoryBasedTest.class.st b/source/Sagan-Core-Tests/RepositoryBasedTest.class.st index 5aef71b..1c02c2a 100644 --- a/source/Sagan-Core-Tests/RepositoryBasedTest.class.st +++ b/source/Sagan-Core-Tests/RepositoryBasedTest.class.st @@ -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 [ @@ -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 [ diff --git a/source/Sagan-Core/InMemoryRepository.class.st b/source/Sagan-Core/InMemoryRepository.class.st index 077b043..00276e8 100644 --- a/source/Sagan-Core/InMemoryRepository.class.st +++ b/source/Sagan-Core/InMemoryRepository.class.st @@ -38,6 +38,12 @@ InMemoryRepository >> conflictCheckingStrategy [ ^ conflictCheckingStrategy ] +{ #category : 'querying' } +InMemoryRepository >> countAll [ + + ^ contents size +] + { #category : 'querying' } InMemoryRepository >> countMatching: aCriteriaOrBlockClosure [ @@ -121,6 +127,28 @@ 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 | + ( self valueOf: aVariableName in: a ) <= ( self valueOf: aVariableName in: b ) ] ) + copyFrom: from + to: to +] + +{ #category : 'private - accessing' } +InMemoryRepository >> valueOf: aVariableName in: anObject [ + + ^ anObject instVarAt: ( anObject class instVarNames indexOf: aVariableName ) +] + { #category : 'querying' } InMemoryRepository >> withOneMatching: aCriteriaOrBlock do: foundBlock else: noneBlock [ diff --git a/source/Sagan-Core/RepositoryBehavior.class.st b/source/Sagan-Core/RepositoryBehavior.class.st index 27a982b..c7040a2 100644 --- a/source/Sagan-Core/RepositoryBehavior.class.st +++ b/source/Sagan-Core/RepositoryBehavior.class.st @@ -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 [ @@ -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' } @@ -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 ] diff --git a/source/Sagan-GemStone-Tests/GemStoneRepositoryProviderTest.class.st b/source/Sagan-GemStone-Tests/GemStoneRepositoryProviderTest.class.st index ac3babe..bf9cb74 100644 --- a/source/Sagan-GemStone-Tests/GemStoneRepositoryProviderTest.class.st +++ b/source/Sagan-GemStone-Tests/GemStoneRepositoryProviderTest.class.st @@ -86,6 +86,132 @@ 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 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 sortedByAscending: 'lastName'. + self + withTheOnlyOneIn: result + do: [ :extraterrestrial | self assert: extraterrestrial lastName equals: 'Travolta' ]. + 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' + ] +] + { #category : 'tests' } GemStoneRepositoryProviderTest >> testQueryingWhenCollectionIsLargeAndIndexed [ diff --git a/source/Sagan-GemStone/GemStoneRepository.class.st b/source/Sagan-GemStone/GemStoneRepository.class.st index 47e8e69..efb903f 100644 --- a/source/Sagan-GemStone/GemStoneRepository.class.st +++ b/source/Sagan-GemStone/GemStoneRepository.class.st @@ -38,6 +38,12 @@ GemStoneRepository >> conflictCheckingStrategy [ ^ conflictCheckingStrategy ] +{ #category : 'querying' } +GemStoneRepository >> countAll [ + + ^ contents size +] + { #category : 'querying' } GemStoneRepository >> countMatching: aCriteriaOrBlockClosure [ @@ -153,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 [ diff --git a/source/Sagan-RDBMS-Tests/SingleRDBMSSessionProviderTest.class.st b/source/Sagan-RDBMS-Tests/SingleRDBMSSessionProviderTest.class.st index 5e363b4..a7c1c1f 100644 --- a/source/Sagan-RDBMS-Tests/SingleRDBMSSessionProviderTest.class.st +++ b/source/Sagan-RDBMS-Tests/SingleRDBMSSessionProviderTest.class.st @@ -11,14 +11,18 @@ SingleRDBMSSessionProviderTest >> testHandleFailingLogin [ | sessionProvider | self timeLimit: 30 seconds. - self withLoggingAsserterDo: [ :asserter | + self withLoggingAsserterDo: [ :asserter | self - should: [ + should: [ asserter - runMemoryLoggerDuring: [ + runMemoryLoggerDuring: [ sessionProvider := SingleRDBMSSessionProvider loginWith: self class failingLogin - configuredBy: [ :options | options at: #logDatabaseEvents put: true ] + configuredBy: [ :options | + options + at: #logDatabaseEvents put: true; + at: #timeSlotBetweenConnectionRetriesInMs put: 1 second + ] ]; assertLogRecordsMatch: #( ). @@ -29,7 +33,7 @@ SingleRDBMSSessionProviderTest >> testHandleFailingLogin [ raise: DatabaseLoginFailed withMessageText: self expectedFailingLogingMessage. - asserter assertLogRecordsMatch: { + asserter assertLogRecordsMatch: { '[DEBUG] Glorp event received {"detail":"Login"}'. ( '[WARNING] Failed to connect to database after 1 attempts because <1s>' expandMacrosWith: self expectedFailingLogingMessage ). diff --git a/source/Sagan-RDBMS/RDBMSRepository.class.st b/source/Sagan-RDBMS/RDBMSRepository.class.st index 76730d4..af46e53 100644 --- a/source/Sagan-RDBMS/RDBMSRepository.class.st +++ b/source/Sagan-RDBMS/RDBMSRepository.class.st @@ -60,6 +60,12 @@ RDBMSRepository >> conflictCheckingStrategy [ ^ conflictCheckingStrategy ] +{ #category : 'querying' } +RDBMSRepository >> countAll [ + + ^ self withReadSessionDo: [ :session | session count: modelObjectClass ] +] + { #category : 'querying' } RDBMSRepository >> countMatching: aCriteriaOrBlock [ @@ -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 [