From 816866033f3ed42ea0880517de0311ba4b201793 Mon Sep 17 00:00:00 2001 From: Oleg Volchkov Date: Wed, 12 Oct 2022 18:50:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BB=D0=B0=D0=BD=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D1=89=D0=B8=D0=BA=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D0=BE=D0=B2.=20=D0=9F=D0=BB=D0=B0=D0=BD=D1=8B=20#45?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .golangci.yml | 1 + pkg/planner/errors.go | 5 + pkg/planner/plan.go | 15 + pkg/planner/plan_mock_test.go | 1056 +++++++++ pkg/planner/predicate_mock_test.go | 1931 +++++++++++++++++ pkg/planner/product_plan.go | 66 + pkg/planner/product_plan_test.go | 148 ++ pkg/planner/project_plan.go | 67 + pkg/planner/project_plan_test.go | 137 ++ pkg/planner/select_plan.go | 62 + pkg/planner/select_plan_test.go | 168 ++ pkg/planner/table_plan.go | 67 + .../table_plan_metadata_manager_mock_test.go | 517 +++++ pkg/planner/table_plan_test.go | 139 ++ pkg/planner/testitil_test.go | 65 + pkg/planner/utils.go | 9 + pkg/scan/expressions_test.go | 8 +- pkg/scan/predicates_test.go | 4 +- pkg/scan/project_scan_test.go | 6 +- pkg/scan/select_scan_test.go | 6 +- pkg/scan/table_scan.go | 18 +- pkg/scan/table_scan_test.go | 2 +- pkg/scan/terms_test.go | 4 +- pkg/scan/testutil_test.go | 2 +- 24 files changed, 4479 insertions(+), 24 deletions(-) create mode 100644 pkg/planner/errors.go create mode 100644 pkg/planner/plan.go create mode 100644 pkg/planner/plan_mock_test.go create mode 100644 pkg/planner/predicate_mock_test.go create mode 100644 pkg/planner/product_plan.go create mode 100644 pkg/planner/product_plan_test.go create mode 100644 pkg/planner/project_plan.go create mode 100644 pkg/planner/project_plan_test.go create mode 100644 pkg/planner/select_plan.go create mode 100644 pkg/planner/select_plan_test.go create mode 100644 pkg/planner/table_plan.go create mode 100644 pkg/planner/table_plan_metadata_manager_mock_test.go create mode 100644 pkg/planner/table_plan_test.go create mode 100644 pkg/planner/testitil_test.go create mode 100644 pkg/planner/utils.go diff --git a/.golangci.yml b/.golangci.yml index b438a02..0aee91e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -69,3 +69,4 @@ linters-settings: - Constant - Term - Statement$ + - Scan diff --git a/pkg/planner/errors.go b/pkg/planner/errors.go new file mode 100644 index 0000000..4a56699 --- /dev/null +++ b/pkg/planner/errors.go @@ -0,0 +1,5 @@ +package planner + +import "github.com/pkg/errors" + +var ErrFailedToCreatePlan = errors.New("failed to create plan") diff --git a/pkg/planner/plan.go b/pkg/planner/plan.go new file mode 100644 index 0000000..a684882 --- /dev/null +++ b/pkg/planner/plan.go @@ -0,0 +1,15 @@ +package planner + +import ( + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +type Plan interface { + Open() (scan.Scan, error) + Schema() records.Schema + BlocksAccessed() int64 + Records() int64 + DistinctValues(string) (int64, bool) + String() string +} diff --git a/pkg/planner/plan_mock_test.go b/pkg/planner/plan_mock_test.go new file mode 100644 index 0000000..d937e99 --- /dev/null +++ b/pkg/planner/plan_mock_test.go @@ -0,0 +1,1056 @@ +package planner + +// Code generated by http://github.com/gojuno/minimock (dev). DO NOT EDIT. + +//go:generate minimock -i github.com/unhandled-exception/sophiadb/pkg/planner.Plan -o ./plan_mock_test.go -n PlanMock + +import ( + "sync" + mm_atomic "sync/atomic" + mm_time "time" + + "github.com/gojuno/minimock/v3" + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +// PlanMock implements Plan +type PlanMock struct { + t minimock.Tester + + funcBlocksAccessed func() (i1 int64) + inspectFuncBlocksAccessed func() + afterBlocksAccessedCounter uint64 + beforeBlocksAccessedCounter uint64 + BlocksAccessedMock mPlanMockBlocksAccessed + + funcDistinctValues func(s1 string) (i1 int64, b1 bool) + inspectFuncDistinctValues func(s1 string) + afterDistinctValuesCounter uint64 + beforeDistinctValuesCounter uint64 + DistinctValuesMock mPlanMockDistinctValues + + funcOpen func() (s1 scan.Scan, err error) + inspectFuncOpen func() + afterOpenCounter uint64 + beforeOpenCounter uint64 + OpenMock mPlanMockOpen + + funcRecords func() (i1 int64) + inspectFuncRecords func() + afterRecordsCounter uint64 + beforeRecordsCounter uint64 + RecordsMock mPlanMockRecords + + funcSchema func() (s1 records.Schema) + inspectFuncSchema func() + afterSchemaCounter uint64 + beforeSchemaCounter uint64 + SchemaMock mPlanMockSchema + + funcString func() (s1 string) + inspectFuncString func() + afterStringCounter uint64 + beforeStringCounter uint64 + StringMock mPlanMockString +} + +// NewPlanMock returns a mock for Plan +func NewPlanMock(t minimock.Tester) *PlanMock { + m := &PlanMock{t: t} + if controller, ok := t.(minimock.MockController); ok { + controller.RegisterMocker(m) + } + + m.BlocksAccessedMock = mPlanMockBlocksAccessed{mock: m} + + m.DistinctValuesMock = mPlanMockDistinctValues{mock: m} + m.DistinctValuesMock.callArgs = []*PlanMockDistinctValuesParams{} + + m.OpenMock = mPlanMockOpen{mock: m} + + m.RecordsMock = mPlanMockRecords{mock: m} + + m.SchemaMock = mPlanMockSchema{mock: m} + + m.StringMock = mPlanMockString{mock: m} + + return m +} + +type mPlanMockBlocksAccessed struct { + mock *PlanMock + defaultExpectation *PlanMockBlocksAccessedExpectation + expectations []*PlanMockBlocksAccessedExpectation +} + +// PlanMockBlocksAccessedExpectation specifies expectation struct of the Plan.BlocksAccessed +type PlanMockBlocksAccessedExpectation struct { + mock *PlanMock + + results *PlanMockBlocksAccessedResults + Counter uint64 +} + +// PlanMockBlocksAccessedResults contains results of the Plan.BlocksAccessed +type PlanMockBlocksAccessedResults struct { + i1 int64 +} + +// Expect sets up expected params for Plan.BlocksAccessed +func (mmBlocksAccessed *mPlanMockBlocksAccessed) Expect() *mPlanMockBlocksAccessed { + if mmBlocksAccessed.mock.funcBlocksAccessed != nil { + mmBlocksAccessed.mock.t.Fatalf("PlanMock.BlocksAccessed mock is already set by Set") + } + + if mmBlocksAccessed.defaultExpectation == nil { + mmBlocksAccessed.defaultExpectation = &PlanMockBlocksAccessedExpectation{} + } + + return mmBlocksAccessed +} + +// Inspect accepts an inspector function that has same arguments as the Plan.BlocksAccessed +func (mmBlocksAccessed *mPlanMockBlocksAccessed) Inspect(f func()) *mPlanMockBlocksAccessed { + if mmBlocksAccessed.mock.inspectFuncBlocksAccessed != nil { + mmBlocksAccessed.mock.t.Fatalf("Inspect function is already set for PlanMock.BlocksAccessed") + } + + mmBlocksAccessed.mock.inspectFuncBlocksAccessed = f + + return mmBlocksAccessed +} + +// Return sets up results that will be returned by Plan.BlocksAccessed +func (mmBlocksAccessed *mPlanMockBlocksAccessed) Return(i1 int64) *PlanMock { + if mmBlocksAccessed.mock.funcBlocksAccessed != nil { + mmBlocksAccessed.mock.t.Fatalf("PlanMock.BlocksAccessed mock is already set by Set") + } + + if mmBlocksAccessed.defaultExpectation == nil { + mmBlocksAccessed.defaultExpectation = &PlanMockBlocksAccessedExpectation{mock: mmBlocksAccessed.mock} + } + mmBlocksAccessed.defaultExpectation.results = &PlanMockBlocksAccessedResults{i1} + return mmBlocksAccessed.mock +} + +//Set uses given function f to mock the Plan.BlocksAccessed method +func (mmBlocksAccessed *mPlanMockBlocksAccessed) Set(f func() (i1 int64)) *PlanMock { + if mmBlocksAccessed.defaultExpectation != nil { + mmBlocksAccessed.mock.t.Fatalf("Default expectation is already set for the Plan.BlocksAccessed method") + } + + if len(mmBlocksAccessed.expectations) > 0 { + mmBlocksAccessed.mock.t.Fatalf("Some expectations are already set for the Plan.BlocksAccessed method") + } + + mmBlocksAccessed.mock.funcBlocksAccessed = f + return mmBlocksAccessed.mock +} + +// BlocksAccessed implements Plan +func (mmBlocksAccessed *PlanMock) BlocksAccessed() (i1 int64) { + mm_atomic.AddUint64(&mmBlocksAccessed.beforeBlocksAccessedCounter, 1) + defer mm_atomic.AddUint64(&mmBlocksAccessed.afterBlocksAccessedCounter, 1) + + if mmBlocksAccessed.inspectFuncBlocksAccessed != nil { + mmBlocksAccessed.inspectFuncBlocksAccessed() + } + + if mmBlocksAccessed.BlocksAccessedMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmBlocksAccessed.BlocksAccessedMock.defaultExpectation.Counter, 1) + + mm_results := mmBlocksAccessed.BlocksAccessedMock.defaultExpectation.results + if mm_results == nil { + mmBlocksAccessed.t.Fatal("No results are set for the PlanMock.BlocksAccessed") + } + return (*mm_results).i1 + } + if mmBlocksAccessed.funcBlocksAccessed != nil { + return mmBlocksAccessed.funcBlocksAccessed() + } + mmBlocksAccessed.t.Fatalf("Unexpected call to PlanMock.BlocksAccessed.") + return +} + +// BlocksAccessedAfterCounter returns a count of finished PlanMock.BlocksAccessed invocations +func (mmBlocksAccessed *PlanMock) BlocksAccessedAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmBlocksAccessed.afterBlocksAccessedCounter) +} + +// BlocksAccessedBeforeCounter returns a count of PlanMock.BlocksAccessed invocations +func (mmBlocksAccessed *PlanMock) BlocksAccessedBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmBlocksAccessed.beforeBlocksAccessedCounter) +} + +// MinimockBlocksAccessedDone returns true if the count of the BlocksAccessed invocations corresponds +// the number of defined expectations +func (m *PlanMock) MinimockBlocksAccessedDone() bool { + for _, e := range m.BlocksAccessedMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.BlocksAccessedMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterBlocksAccessedCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcBlocksAccessed != nil && mm_atomic.LoadUint64(&m.afterBlocksAccessedCounter) < 1 { + return false + } + return true +} + +// MinimockBlocksAccessedInspect logs each unmet expectation +func (m *PlanMock) MinimockBlocksAccessedInspect() { + for _, e := range m.BlocksAccessedMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PlanMock.BlocksAccessed") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.BlocksAccessedMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterBlocksAccessedCounter) < 1 { + m.t.Error("Expected call to PlanMock.BlocksAccessed") + } + // if func was set then invocations count should be greater than zero + if m.funcBlocksAccessed != nil && mm_atomic.LoadUint64(&m.afterBlocksAccessedCounter) < 1 { + m.t.Error("Expected call to PlanMock.BlocksAccessed") + } +} + +type mPlanMockDistinctValues struct { + mock *PlanMock + defaultExpectation *PlanMockDistinctValuesExpectation + expectations []*PlanMockDistinctValuesExpectation + + callArgs []*PlanMockDistinctValuesParams + mutex sync.RWMutex +} + +// PlanMockDistinctValuesExpectation specifies expectation struct of the Plan.DistinctValues +type PlanMockDistinctValuesExpectation struct { + mock *PlanMock + params *PlanMockDistinctValuesParams + results *PlanMockDistinctValuesResults + Counter uint64 +} + +// PlanMockDistinctValuesParams contains parameters of the Plan.DistinctValues +type PlanMockDistinctValuesParams struct { + s1 string +} + +// PlanMockDistinctValuesResults contains results of the Plan.DistinctValues +type PlanMockDistinctValuesResults struct { + i1 int64 + b1 bool +} + +// Expect sets up expected params for Plan.DistinctValues +func (mmDistinctValues *mPlanMockDistinctValues) Expect(s1 string) *mPlanMockDistinctValues { + if mmDistinctValues.mock.funcDistinctValues != nil { + mmDistinctValues.mock.t.Fatalf("PlanMock.DistinctValues mock is already set by Set") + } + + if mmDistinctValues.defaultExpectation == nil { + mmDistinctValues.defaultExpectation = &PlanMockDistinctValuesExpectation{} + } + + mmDistinctValues.defaultExpectation.params = &PlanMockDistinctValuesParams{s1} + for _, e := range mmDistinctValues.expectations { + if minimock.Equal(e.params, mmDistinctValues.defaultExpectation.params) { + mmDistinctValues.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDistinctValues.defaultExpectation.params) + } + } + + return mmDistinctValues +} + +// Inspect accepts an inspector function that has same arguments as the Plan.DistinctValues +func (mmDistinctValues *mPlanMockDistinctValues) Inspect(f func(s1 string)) *mPlanMockDistinctValues { + if mmDistinctValues.mock.inspectFuncDistinctValues != nil { + mmDistinctValues.mock.t.Fatalf("Inspect function is already set for PlanMock.DistinctValues") + } + + mmDistinctValues.mock.inspectFuncDistinctValues = f + + return mmDistinctValues +} + +// Return sets up results that will be returned by Plan.DistinctValues +func (mmDistinctValues *mPlanMockDistinctValues) Return(i1 int64, b1 bool) *PlanMock { + if mmDistinctValues.mock.funcDistinctValues != nil { + mmDistinctValues.mock.t.Fatalf("PlanMock.DistinctValues mock is already set by Set") + } + + if mmDistinctValues.defaultExpectation == nil { + mmDistinctValues.defaultExpectation = &PlanMockDistinctValuesExpectation{mock: mmDistinctValues.mock} + } + mmDistinctValues.defaultExpectation.results = &PlanMockDistinctValuesResults{i1, b1} + return mmDistinctValues.mock +} + +//Set uses given function f to mock the Plan.DistinctValues method +func (mmDistinctValues *mPlanMockDistinctValues) Set(f func(s1 string) (i1 int64, b1 bool)) *PlanMock { + if mmDistinctValues.defaultExpectation != nil { + mmDistinctValues.mock.t.Fatalf("Default expectation is already set for the Plan.DistinctValues method") + } + + if len(mmDistinctValues.expectations) > 0 { + mmDistinctValues.mock.t.Fatalf("Some expectations are already set for the Plan.DistinctValues method") + } + + mmDistinctValues.mock.funcDistinctValues = f + return mmDistinctValues.mock +} + +// When sets expectation for the Plan.DistinctValues which will trigger the result defined by the following +// Then helper +func (mmDistinctValues *mPlanMockDistinctValues) When(s1 string) *PlanMockDistinctValuesExpectation { + if mmDistinctValues.mock.funcDistinctValues != nil { + mmDistinctValues.mock.t.Fatalf("PlanMock.DistinctValues mock is already set by Set") + } + + expectation := &PlanMockDistinctValuesExpectation{ + mock: mmDistinctValues.mock, + params: &PlanMockDistinctValuesParams{s1}, + } + mmDistinctValues.expectations = append(mmDistinctValues.expectations, expectation) + return expectation +} + +// Then sets up Plan.DistinctValues return parameters for the expectation previously defined by the When method +func (e *PlanMockDistinctValuesExpectation) Then(i1 int64, b1 bool) *PlanMock { + e.results = &PlanMockDistinctValuesResults{i1, b1} + return e.mock +} + +// DistinctValues implements Plan +func (mmDistinctValues *PlanMock) DistinctValues(s1 string) (i1 int64, b1 bool) { + mm_atomic.AddUint64(&mmDistinctValues.beforeDistinctValuesCounter, 1) + defer mm_atomic.AddUint64(&mmDistinctValues.afterDistinctValuesCounter, 1) + + if mmDistinctValues.inspectFuncDistinctValues != nil { + mmDistinctValues.inspectFuncDistinctValues(s1) + } + + mm_params := &PlanMockDistinctValuesParams{s1} + + // Record call args + mmDistinctValues.DistinctValuesMock.mutex.Lock() + mmDistinctValues.DistinctValuesMock.callArgs = append(mmDistinctValues.DistinctValuesMock.callArgs, mm_params) + mmDistinctValues.DistinctValuesMock.mutex.Unlock() + + for _, e := range mmDistinctValues.DistinctValuesMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.i1, e.results.b1 + } + } + + if mmDistinctValues.DistinctValuesMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmDistinctValues.DistinctValuesMock.defaultExpectation.Counter, 1) + mm_want := mmDistinctValues.DistinctValuesMock.defaultExpectation.params + mm_got := PlanMockDistinctValuesParams{s1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmDistinctValues.t.Errorf("PlanMock.DistinctValues got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmDistinctValues.DistinctValuesMock.defaultExpectation.results + if mm_results == nil { + mmDistinctValues.t.Fatal("No results are set for the PlanMock.DistinctValues") + } + return (*mm_results).i1, (*mm_results).b1 + } + if mmDistinctValues.funcDistinctValues != nil { + return mmDistinctValues.funcDistinctValues(s1) + } + mmDistinctValues.t.Fatalf("Unexpected call to PlanMock.DistinctValues. %v", s1) + return +} + +// DistinctValuesAfterCounter returns a count of finished PlanMock.DistinctValues invocations +func (mmDistinctValues *PlanMock) DistinctValuesAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmDistinctValues.afterDistinctValuesCounter) +} + +// DistinctValuesBeforeCounter returns a count of PlanMock.DistinctValues invocations +func (mmDistinctValues *PlanMock) DistinctValuesBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmDistinctValues.beforeDistinctValuesCounter) +} + +// Calls returns a list of arguments used in each call to PlanMock.DistinctValues. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmDistinctValues *mPlanMockDistinctValues) Calls() []*PlanMockDistinctValuesParams { + mmDistinctValues.mutex.RLock() + + argCopy := make([]*PlanMockDistinctValuesParams, len(mmDistinctValues.callArgs)) + copy(argCopy, mmDistinctValues.callArgs) + + mmDistinctValues.mutex.RUnlock() + + return argCopy +} + +// MinimockDistinctValuesDone returns true if the count of the DistinctValues invocations corresponds +// the number of defined expectations +func (m *PlanMock) MinimockDistinctValuesDone() bool { + for _, e := range m.DistinctValuesMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.DistinctValuesMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterDistinctValuesCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcDistinctValues != nil && mm_atomic.LoadUint64(&m.afterDistinctValuesCounter) < 1 { + return false + } + return true +} + +// MinimockDistinctValuesInspect logs each unmet expectation +func (m *PlanMock) MinimockDistinctValuesInspect() { + for _, e := range m.DistinctValuesMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PlanMock.DistinctValues with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.DistinctValuesMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterDistinctValuesCounter) < 1 { + if m.DistinctValuesMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PlanMock.DistinctValues") + } else { + m.t.Errorf("Expected call to PlanMock.DistinctValues with params: %#v", *m.DistinctValuesMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcDistinctValues != nil && mm_atomic.LoadUint64(&m.afterDistinctValuesCounter) < 1 { + m.t.Error("Expected call to PlanMock.DistinctValues") + } +} + +type mPlanMockOpen struct { + mock *PlanMock + defaultExpectation *PlanMockOpenExpectation + expectations []*PlanMockOpenExpectation +} + +// PlanMockOpenExpectation specifies expectation struct of the Plan.Open +type PlanMockOpenExpectation struct { + mock *PlanMock + + results *PlanMockOpenResults + Counter uint64 +} + +// PlanMockOpenResults contains results of the Plan.Open +type PlanMockOpenResults struct { + s1 scan.Scan + err error +} + +// Expect sets up expected params for Plan.Open +func (mmOpen *mPlanMockOpen) Expect() *mPlanMockOpen { + if mmOpen.mock.funcOpen != nil { + mmOpen.mock.t.Fatalf("PlanMock.Open mock is already set by Set") + } + + if mmOpen.defaultExpectation == nil { + mmOpen.defaultExpectation = &PlanMockOpenExpectation{} + } + + return mmOpen +} + +// Inspect accepts an inspector function that has same arguments as the Plan.Open +func (mmOpen *mPlanMockOpen) Inspect(f func()) *mPlanMockOpen { + if mmOpen.mock.inspectFuncOpen != nil { + mmOpen.mock.t.Fatalf("Inspect function is already set for PlanMock.Open") + } + + mmOpen.mock.inspectFuncOpen = f + + return mmOpen +} + +// Return sets up results that will be returned by Plan.Open +func (mmOpen *mPlanMockOpen) Return(s1 scan.Scan, err error) *PlanMock { + if mmOpen.mock.funcOpen != nil { + mmOpen.mock.t.Fatalf("PlanMock.Open mock is already set by Set") + } + + if mmOpen.defaultExpectation == nil { + mmOpen.defaultExpectation = &PlanMockOpenExpectation{mock: mmOpen.mock} + } + mmOpen.defaultExpectation.results = &PlanMockOpenResults{s1, err} + return mmOpen.mock +} + +//Set uses given function f to mock the Plan.Open method +func (mmOpen *mPlanMockOpen) Set(f func() (s1 scan.Scan, err error)) *PlanMock { + if mmOpen.defaultExpectation != nil { + mmOpen.mock.t.Fatalf("Default expectation is already set for the Plan.Open method") + } + + if len(mmOpen.expectations) > 0 { + mmOpen.mock.t.Fatalf("Some expectations are already set for the Plan.Open method") + } + + mmOpen.mock.funcOpen = f + return mmOpen.mock +} + +// Open implements Plan +func (mmOpen *PlanMock) Open() (s1 scan.Scan, err error) { + mm_atomic.AddUint64(&mmOpen.beforeOpenCounter, 1) + defer mm_atomic.AddUint64(&mmOpen.afterOpenCounter, 1) + + if mmOpen.inspectFuncOpen != nil { + mmOpen.inspectFuncOpen() + } + + if mmOpen.OpenMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmOpen.OpenMock.defaultExpectation.Counter, 1) + + mm_results := mmOpen.OpenMock.defaultExpectation.results + if mm_results == nil { + mmOpen.t.Fatal("No results are set for the PlanMock.Open") + } + return (*mm_results).s1, (*mm_results).err + } + if mmOpen.funcOpen != nil { + return mmOpen.funcOpen() + } + mmOpen.t.Fatalf("Unexpected call to PlanMock.Open.") + return +} + +// OpenAfterCounter returns a count of finished PlanMock.Open invocations +func (mmOpen *PlanMock) OpenAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmOpen.afterOpenCounter) +} + +// OpenBeforeCounter returns a count of PlanMock.Open invocations +func (mmOpen *PlanMock) OpenBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmOpen.beforeOpenCounter) +} + +// MinimockOpenDone returns true if the count of the Open invocations corresponds +// the number of defined expectations +func (m *PlanMock) MinimockOpenDone() bool { + for _, e := range m.OpenMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.OpenMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterOpenCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcOpen != nil && mm_atomic.LoadUint64(&m.afterOpenCounter) < 1 { + return false + } + return true +} + +// MinimockOpenInspect logs each unmet expectation +func (m *PlanMock) MinimockOpenInspect() { + for _, e := range m.OpenMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PlanMock.Open") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.OpenMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterOpenCounter) < 1 { + m.t.Error("Expected call to PlanMock.Open") + } + // if func was set then invocations count should be greater than zero + if m.funcOpen != nil && mm_atomic.LoadUint64(&m.afterOpenCounter) < 1 { + m.t.Error("Expected call to PlanMock.Open") + } +} + +type mPlanMockRecords struct { + mock *PlanMock + defaultExpectation *PlanMockRecordsExpectation + expectations []*PlanMockRecordsExpectation +} + +// PlanMockRecordsExpectation specifies expectation struct of the Plan.Records +type PlanMockRecordsExpectation struct { + mock *PlanMock + + results *PlanMockRecordsResults + Counter uint64 +} + +// PlanMockRecordsResults contains results of the Plan.Records +type PlanMockRecordsResults struct { + i1 int64 +} + +// Expect sets up expected params for Plan.Records +func (mmRecords *mPlanMockRecords) Expect() *mPlanMockRecords { + if mmRecords.mock.funcRecords != nil { + mmRecords.mock.t.Fatalf("PlanMock.Records mock is already set by Set") + } + + if mmRecords.defaultExpectation == nil { + mmRecords.defaultExpectation = &PlanMockRecordsExpectation{} + } + + return mmRecords +} + +// Inspect accepts an inspector function that has same arguments as the Plan.Records +func (mmRecords *mPlanMockRecords) Inspect(f func()) *mPlanMockRecords { + if mmRecords.mock.inspectFuncRecords != nil { + mmRecords.mock.t.Fatalf("Inspect function is already set for PlanMock.Records") + } + + mmRecords.mock.inspectFuncRecords = f + + return mmRecords +} + +// Return sets up results that will be returned by Plan.Records +func (mmRecords *mPlanMockRecords) Return(i1 int64) *PlanMock { + if mmRecords.mock.funcRecords != nil { + mmRecords.mock.t.Fatalf("PlanMock.Records mock is already set by Set") + } + + if mmRecords.defaultExpectation == nil { + mmRecords.defaultExpectation = &PlanMockRecordsExpectation{mock: mmRecords.mock} + } + mmRecords.defaultExpectation.results = &PlanMockRecordsResults{i1} + return mmRecords.mock +} + +//Set uses given function f to mock the Plan.Records method +func (mmRecords *mPlanMockRecords) Set(f func() (i1 int64)) *PlanMock { + if mmRecords.defaultExpectation != nil { + mmRecords.mock.t.Fatalf("Default expectation is already set for the Plan.Records method") + } + + if len(mmRecords.expectations) > 0 { + mmRecords.mock.t.Fatalf("Some expectations are already set for the Plan.Records method") + } + + mmRecords.mock.funcRecords = f + return mmRecords.mock +} + +// Records implements Plan +func (mmRecords *PlanMock) Records() (i1 int64) { + mm_atomic.AddUint64(&mmRecords.beforeRecordsCounter, 1) + defer mm_atomic.AddUint64(&mmRecords.afterRecordsCounter, 1) + + if mmRecords.inspectFuncRecords != nil { + mmRecords.inspectFuncRecords() + } + + if mmRecords.RecordsMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmRecords.RecordsMock.defaultExpectation.Counter, 1) + + mm_results := mmRecords.RecordsMock.defaultExpectation.results + if mm_results == nil { + mmRecords.t.Fatal("No results are set for the PlanMock.Records") + } + return (*mm_results).i1 + } + if mmRecords.funcRecords != nil { + return mmRecords.funcRecords() + } + mmRecords.t.Fatalf("Unexpected call to PlanMock.Records.") + return +} + +// RecordsAfterCounter returns a count of finished PlanMock.Records invocations +func (mmRecords *PlanMock) RecordsAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmRecords.afterRecordsCounter) +} + +// RecordsBeforeCounter returns a count of PlanMock.Records invocations +func (mmRecords *PlanMock) RecordsBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmRecords.beforeRecordsCounter) +} + +// MinimockRecordsDone returns true if the count of the Records invocations corresponds +// the number of defined expectations +func (m *PlanMock) MinimockRecordsDone() bool { + for _, e := range m.RecordsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.RecordsMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterRecordsCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcRecords != nil && mm_atomic.LoadUint64(&m.afterRecordsCounter) < 1 { + return false + } + return true +} + +// MinimockRecordsInspect logs each unmet expectation +func (m *PlanMock) MinimockRecordsInspect() { + for _, e := range m.RecordsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PlanMock.Records") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.RecordsMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterRecordsCounter) < 1 { + m.t.Error("Expected call to PlanMock.Records") + } + // if func was set then invocations count should be greater than zero + if m.funcRecords != nil && mm_atomic.LoadUint64(&m.afterRecordsCounter) < 1 { + m.t.Error("Expected call to PlanMock.Records") + } +} + +type mPlanMockSchema struct { + mock *PlanMock + defaultExpectation *PlanMockSchemaExpectation + expectations []*PlanMockSchemaExpectation +} + +// PlanMockSchemaExpectation specifies expectation struct of the Plan.Schema +type PlanMockSchemaExpectation struct { + mock *PlanMock + + results *PlanMockSchemaResults + Counter uint64 +} + +// PlanMockSchemaResults contains results of the Plan.Schema +type PlanMockSchemaResults struct { + s1 records.Schema +} + +// Expect sets up expected params for Plan.Schema +func (mmSchema *mPlanMockSchema) Expect() *mPlanMockSchema { + if mmSchema.mock.funcSchema != nil { + mmSchema.mock.t.Fatalf("PlanMock.Schema mock is already set by Set") + } + + if mmSchema.defaultExpectation == nil { + mmSchema.defaultExpectation = &PlanMockSchemaExpectation{} + } + + return mmSchema +} + +// Inspect accepts an inspector function that has same arguments as the Plan.Schema +func (mmSchema *mPlanMockSchema) Inspect(f func()) *mPlanMockSchema { + if mmSchema.mock.inspectFuncSchema != nil { + mmSchema.mock.t.Fatalf("Inspect function is already set for PlanMock.Schema") + } + + mmSchema.mock.inspectFuncSchema = f + + return mmSchema +} + +// Return sets up results that will be returned by Plan.Schema +func (mmSchema *mPlanMockSchema) Return(s1 records.Schema) *PlanMock { + if mmSchema.mock.funcSchema != nil { + mmSchema.mock.t.Fatalf("PlanMock.Schema mock is already set by Set") + } + + if mmSchema.defaultExpectation == nil { + mmSchema.defaultExpectation = &PlanMockSchemaExpectation{mock: mmSchema.mock} + } + mmSchema.defaultExpectation.results = &PlanMockSchemaResults{s1} + return mmSchema.mock +} + +//Set uses given function f to mock the Plan.Schema method +func (mmSchema *mPlanMockSchema) Set(f func() (s1 records.Schema)) *PlanMock { + if mmSchema.defaultExpectation != nil { + mmSchema.mock.t.Fatalf("Default expectation is already set for the Plan.Schema method") + } + + if len(mmSchema.expectations) > 0 { + mmSchema.mock.t.Fatalf("Some expectations are already set for the Plan.Schema method") + } + + mmSchema.mock.funcSchema = f + return mmSchema.mock +} + +// Schema implements Plan +func (mmSchema *PlanMock) Schema() (s1 records.Schema) { + mm_atomic.AddUint64(&mmSchema.beforeSchemaCounter, 1) + defer mm_atomic.AddUint64(&mmSchema.afterSchemaCounter, 1) + + if mmSchema.inspectFuncSchema != nil { + mmSchema.inspectFuncSchema() + } + + if mmSchema.SchemaMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmSchema.SchemaMock.defaultExpectation.Counter, 1) + + mm_results := mmSchema.SchemaMock.defaultExpectation.results + if mm_results == nil { + mmSchema.t.Fatal("No results are set for the PlanMock.Schema") + } + return (*mm_results).s1 + } + if mmSchema.funcSchema != nil { + return mmSchema.funcSchema() + } + mmSchema.t.Fatalf("Unexpected call to PlanMock.Schema.") + return +} + +// SchemaAfterCounter returns a count of finished PlanMock.Schema invocations +func (mmSchema *PlanMock) SchemaAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmSchema.afterSchemaCounter) +} + +// SchemaBeforeCounter returns a count of PlanMock.Schema invocations +func (mmSchema *PlanMock) SchemaBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmSchema.beforeSchemaCounter) +} + +// MinimockSchemaDone returns true if the count of the Schema invocations corresponds +// the number of defined expectations +func (m *PlanMock) MinimockSchemaDone() bool { + for _, e := range m.SchemaMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.SchemaMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterSchemaCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcSchema != nil && mm_atomic.LoadUint64(&m.afterSchemaCounter) < 1 { + return false + } + return true +} + +// MinimockSchemaInspect logs each unmet expectation +func (m *PlanMock) MinimockSchemaInspect() { + for _, e := range m.SchemaMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PlanMock.Schema") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.SchemaMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterSchemaCounter) < 1 { + m.t.Error("Expected call to PlanMock.Schema") + } + // if func was set then invocations count should be greater than zero + if m.funcSchema != nil && mm_atomic.LoadUint64(&m.afterSchemaCounter) < 1 { + m.t.Error("Expected call to PlanMock.Schema") + } +} + +type mPlanMockString struct { + mock *PlanMock + defaultExpectation *PlanMockStringExpectation + expectations []*PlanMockStringExpectation +} + +// PlanMockStringExpectation specifies expectation struct of the Plan.String +type PlanMockStringExpectation struct { + mock *PlanMock + + results *PlanMockStringResults + Counter uint64 +} + +// PlanMockStringResults contains results of the Plan.String +type PlanMockStringResults struct { + s1 string +} + +// Expect sets up expected params for Plan.String +func (mmString *mPlanMockString) Expect() *mPlanMockString { + if mmString.mock.funcString != nil { + mmString.mock.t.Fatalf("PlanMock.String mock is already set by Set") + } + + if mmString.defaultExpectation == nil { + mmString.defaultExpectation = &PlanMockStringExpectation{} + } + + return mmString +} + +// Inspect accepts an inspector function that has same arguments as the Plan.String +func (mmString *mPlanMockString) Inspect(f func()) *mPlanMockString { + if mmString.mock.inspectFuncString != nil { + mmString.mock.t.Fatalf("Inspect function is already set for PlanMock.String") + } + + mmString.mock.inspectFuncString = f + + return mmString +} + +// Return sets up results that will be returned by Plan.String +func (mmString *mPlanMockString) Return(s1 string) *PlanMock { + if mmString.mock.funcString != nil { + mmString.mock.t.Fatalf("PlanMock.String mock is already set by Set") + } + + if mmString.defaultExpectation == nil { + mmString.defaultExpectation = &PlanMockStringExpectation{mock: mmString.mock} + } + mmString.defaultExpectation.results = &PlanMockStringResults{s1} + return mmString.mock +} + +//Set uses given function f to mock the Plan.String method +func (mmString *mPlanMockString) Set(f func() (s1 string)) *PlanMock { + if mmString.defaultExpectation != nil { + mmString.mock.t.Fatalf("Default expectation is already set for the Plan.String method") + } + + if len(mmString.expectations) > 0 { + mmString.mock.t.Fatalf("Some expectations are already set for the Plan.String method") + } + + mmString.mock.funcString = f + return mmString.mock +} + +// String implements Plan +func (mmString *PlanMock) String() (s1 string) { + mm_atomic.AddUint64(&mmString.beforeStringCounter, 1) + defer mm_atomic.AddUint64(&mmString.afterStringCounter, 1) + + if mmString.inspectFuncString != nil { + mmString.inspectFuncString() + } + + if mmString.StringMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmString.StringMock.defaultExpectation.Counter, 1) + + mm_results := mmString.StringMock.defaultExpectation.results + if mm_results == nil { + mmString.t.Fatal("No results are set for the PlanMock.String") + } + return (*mm_results).s1 + } + if mmString.funcString != nil { + return mmString.funcString() + } + mmString.t.Fatalf("Unexpected call to PlanMock.String.") + return +} + +// StringAfterCounter returns a count of finished PlanMock.String invocations +func (mmString *PlanMock) StringAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmString.afterStringCounter) +} + +// StringBeforeCounter returns a count of PlanMock.String invocations +func (mmString *PlanMock) StringBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmString.beforeStringCounter) +} + +// MinimockStringDone returns true if the count of the String invocations corresponds +// the number of defined expectations +func (m *PlanMock) MinimockStringDone() bool { + for _, e := range m.StringMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.StringMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcString != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + return false + } + return true +} + +// MinimockStringInspect logs each unmet expectation +func (m *PlanMock) MinimockStringInspect() { + for _, e := range m.StringMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PlanMock.String") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.StringMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + m.t.Error("Expected call to PlanMock.String") + } + // if func was set then invocations count should be greater than zero + if m.funcString != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + m.t.Error("Expected call to PlanMock.String") + } +} + +// MinimockFinish checks that all mocked methods have been called the expected number of times +func (m *PlanMock) MinimockFinish() { + if !m.minimockDone() { + m.MinimockBlocksAccessedInspect() + + m.MinimockDistinctValuesInspect() + + m.MinimockOpenInspect() + + m.MinimockRecordsInspect() + + m.MinimockSchemaInspect() + + m.MinimockStringInspect() + m.t.FailNow() + } +} + +// MinimockWait waits for all mocked methods to be called the expected number of times +func (m *PlanMock) MinimockWait(timeout mm_time.Duration) { + timeoutCh := mm_time.After(timeout) + for { + if m.minimockDone() { + return + } + select { + case <-timeoutCh: + m.MinimockFinish() + return + case <-mm_time.After(10 * mm_time.Millisecond): + } + } +} + +func (m *PlanMock) minimockDone() bool { + done := true + return done && + m.MinimockBlocksAccessedDone() && + m.MinimockDistinctValuesDone() && + m.MinimockOpenDone() && + m.MinimockRecordsDone() && + m.MinimockSchemaDone() && + m.MinimockStringDone() +} diff --git a/pkg/planner/predicate_mock_test.go b/pkg/planner/predicate_mock_test.go new file mode 100644 index 0000000..f948cda --- /dev/null +++ b/pkg/planner/predicate_mock_test.go @@ -0,0 +1,1931 @@ +package planner + +// Code generated by http://github.com/gojuno/minimock (dev). DO NOT EDIT. + +//go:generate minimock -i github.com/unhandled-exception/sophiadb/pkg/scan.Predicate -o ./predicate_mock_test.go -n PredicateMock + +import ( + "sync" + mm_atomic "sync/atomic" + mm_time "time" + + "github.com/gojuno/minimock/v3" + "github.com/unhandled-exception/sophiadb/pkg/records" + mm_scan "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +// PredicateMock implements scan.Predicate +type PredicateMock struct { + t minimock.Tester + + funcConjoinWith func(p1 mm_scan.Predicate) + inspectFuncConjoinWith func(p1 mm_scan.Predicate) + afterConjoinWithCounter uint64 + beforeConjoinWithCounter uint64 + ConjoinWithMock mPredicateMockConjoinWith + + funcEquatesWithConstant func(s1 string) (c1 mm_scan.Constant, b1 bool) + inspectFuncEquatesWithConstant func(s1 string) + afterEquatesWithConstantCounter uint64 + beforeEquatesWithConstantCounter uint64 + EquatesWithConstantMock mPredicateMockEquatesWithConstant + + funcEquatesWithField func(s1 string) (s2 string, b1 bool) + inspectFuncEquatesWithField func(s1 string) + afterEquatesWithFieldCounter uint64 + beforeEquatesWithFieldCounter uint64 + EquatesWithFieldMock mPredicateMockEquatesWithField + + funcIsSatisfied func(s1 mm_scan.Scan) (b1 bool, err error) + inspectFuncIsSatisfied func(s1 mm_scan.Scan) + afterIsSatisfiedCounter uint64 + beforeIsSatisfiedCounter uint64 + IsSatisfiedMock mPredicateMockIsSatisfied + + funcJoinSubPred func(s1 records.Schema, s2 records.Schema) (p1 mm_scan.Predicate) + inspectFuncJoinSubPred func(s1 records.Schema, s2 records.Schema) + afterJoinSubPredCounter uint64 + beforeJoinSubPredCounter uint64 + JoinSubPredMock mPredicateMockJoinSubPred + + funcReductionFactor func(p1 mm_scan.Plan) (i1 int64, b1 bool) + inspectFuncReductionFactor func(p1 mm_scan.Plan) + afterReductionFactorCounter uint64 + beforeReductionFactorCounter uint64 + ReductionFactorMock mPredicateMockReductionFactor + + funcSelectSubPred func(s1 records.Schema) (p1 mm_scan.Predicate) + inspectFuncSelectSubPred func(s1 records.Schema) + afterSelectSubPredCounter uint64 + beforeSelectSubPredCounter uint64 + SelectSubPredMock mPredicateMockSelectSubPred + + funcString func() (s1 string) + inspectFuncString func() + afterStringCounter uint64 + beforeStringCounter uint64 + StringMock mPredicateMockString + + funcTerms func() (ta1 []mm_scan.Term) + inspectFuncTerms func() + afterTermsCounter uint64 + beforeTermsCounter uint64 + TermsMock mPredicateMockTerms +} + +// NewPredicateMock returns a mock for scan.Predicate +func NewPredicateMock(t minimock.Tester) *PredicateMock { + m := &PredicateMock{t: t} + if controller, ok := t.(minimock.MockController); ok { + controller.RegisterMocker(m) + } + + m.ConjoinWithMock = mPredicateMockConjoinWith{mock: m} + m.ConjoinWithMock.callArgs = []*PredicateMockConjoinWithParams{} + + m.EquatesWithConstantMock = mPredicateMockEquatesWithConstant{mock: m} + m.EquatesWithConstantMock.callArgs = []*PredicateMockEquatesWithConstantParams{} + + m.EquatesWithFieldMock = mPredicateMockEquatesWithField{mock: m} + m.EquatesWithFieldMock.callArgs = []*PredicateMockEquatesWithFieldParams{} + + m.IsSatisfiedMock = mPredicateMockIsSatisfied{mock: m} + m.IsSatisfiedMock.callArgs = []*PredicateMockIsSatisfiedParams{} + + m.JoinSubPredMock = mPredicateMockJoinSubPred{mock: m} + m.JoinSubPredMock.callArgs = []*PredicateMockJoinSubPredParams{} + + m.ReductionFactorMock = mPredicateMockReductionFactor{mock: m} + m.ReductionFactorMock.callArgs = []*PredicateMockReductionFactorParams{} + + m.SelectSubPredMock = mPredicateMockSelectSubPred{mock: m} + m.SelectSubPredMock.callArgs = []*PredicateMockSelectSubPredParams{} + + m.StringMock = mPredicateMockString{mock: m} + + m.TermsMock = mPredicateMockTerms{mock: m} + + return m +} + +type mPredicateMockConjoinWith struct { + mock *PredicateMock + defaultExpectation *PredicateMockConjoinWithExpectation + expectations []*PredicateMockConjoinWithExpectation + + callArgs []*PredicateMockConjoinWithParams + mutex sync.RWMutex +} + +// PredicateMockConjoinWithExpectation specifies expectation struct of the Predicate.ConjoinWith +type PredicateMockConjoinWithExpectation struct { + mock *PredicateMock + params *PredicateMockConjoinWithParams + + Counter uint64 +} + +// PredicateMockConjoinWithParams contains parameters of the Predicate.ConjoinWith +type PredicateMockConjoinWithParams struct { + p1 mm_scan.Predicate +} + +// Expect sets up expected params for Predicate.ConjoinWith +func (mmConjoinWith *mPredicateMockConjoinWith) Expect(p1 mm_scan.Predicate) *mPredicateMockConjoinWith { + if mmConjoinWith.mock.funcConjoinWith != nil { + mmConjoinWith.mock.t.Fatalf("PredicateMock.ConjoinWith mock is already set by Set") + } + + if mmConjoinWith.defaultExpectation == nil { + mmConjoinWith.defaultExpectation = &PredicateMockConjoinWithExpectation{} + } + + mmConjoinWith.defaultExpectation.params = &PredicateMockConjoinWithParams{p1} + for _, e := range mmConjoinWith.expectations { + if minimock.Equal(e.params, mmConjoinWith.defaultExpectation.params) { + mmConjoinWith.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmConjoinWith.defaultExpectation.params) + } + } + + return mmConjoinWith +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.ConjoinWith +func (mmConjoinWith *mPredicateMockConjoinWith) Inspect(f func(p1 mm_scan.Predicate)) *mPredicateMockConjoinWith { + if mmConjoinWith.mock.inspectFuncConjoinWith != nil { + mmConjoinWith.mock.t.Fatalf("Inspect function is already set for PredicateMock.ConjoinWith") + } + + mmConjoinWith.mock.inspectFuncConjoinWith = f + + return mmConjoinWith +} + +// Return sets up results that will be returned by Predicate.ConjoinWith +func (mmConjoinWith *mPredicateMockConjoinWith) Return() *PredicateMock { + if mmConjoinWith.mock.funcConjoinWith != nil { + mmConjoinWith.mock.t.Fatalf("PredicateMock.ConjoinWith mock is already set by Set") + } + + if mmConjoinWith.defaultExpectation == nil { + mmConjoinWith.defaultExpectation = &PredicateMockConjoinWithExpectation{mock: mmConjoinWith.mock} + } + + return mmConjoinWith.mock +} + +//Set uses given function f to mock the Predicate.ConjoinWith method +func (mmConjoinWith *mPredicateMockConjoinWith) Set(f func(p1 mm_scan.Predicate)) *PredicateMock { + if mmConjoinWith.defaultExpectation != nil { + mmConjoinWith.mock.t.Fatalf("Default expectation is already set for the Predicate.ConjoinWith method") + } + + if len(mmConjoinWith.expectations) > 0 { + mmConjoinWith.mock.t.Fatalf("Some expectations are already set for the Predicate.ConjoinWith method") + } + + mmConjoinWith.mock.funcConjoinWith = f + return mmConjoinWith.mock +} + +// ConjoinWith implements scan.Predicate +func (mmConjoinWith *PredicateMock) ConjoinWith(p1 mm_scan.Predicate) { + mm_atomic.AddUint64(&mmConjoinWith.beforeConjoinWithCounter, 1) + defer mm_atomic.AddUint64(&mmConjoinWith.afterConjoinWithCounter, 1) + + if mmConjoinWith.inspectFuncConjoinWith != nil { + mmConjoinWith.inspectFuncConjoinWith(p1) + } + + mm_params := &PredicateMockConjoinWithParams{p1} + + // Record call args + mmConjoinWith.ConjoinWithMock.mutex.Lock() + mmConjoinWith.ConjoinWithMock.callArgs = append(mmConjoinWith.ConjoinWithMock.callArgs, mm_params) + mmConjoinWith.ConjoinWithMock.mutex.Unlock() + + for _, e := range mmConjoinWith.ConjoinWithMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return + } + } + + if mmConjoinWith.ConjoinWithMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmConjoinWith.ConjoinWithMock.defaultExpectation.Counter, 1) + mm_want := mmConjoinWith.ConjoinWithMock.defaultExpectation.params + mm_got := PredicateMockConjoinWithParams{p1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmConjoinWith.t.Errorf("PredicateMock.ConjoinWith got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + return + + } + if mmConjoinWith.funcConjoinWith != nil { + mmConjoinWith.funcConjoinWith(p1) + return + } + mmConjoinWith.t.Fatalf("Unexpected call to PredicateMock.ConjoinWith. %v", p1) + +} + +// ConjoinWithAfterCounter returns a count of finished PredicateMock.ConjoinWith invocations +func (mmConjoinWith *PredicateMock) ConjoinWithAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmConjoinWith.afterConjoinWithCounter) +} + +// ConjoinWithBeforeCounter returns a count of PredicateMock.ConjoinWith invocations +func (mmConjoinWith *PredicateMock) ConjoinWithBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmConjoinWith.beforeConjoinWithCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.ConjoinWith. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmConjoinWith *mPredicateMockConjoinWith) Calls() []*PredicateMockConjoinWithParams { + mmConjoinWith.mutex.RLock() + + argCopy := make([]*PredicateMockConjoinWithParams, len(mmConjoinWith.callArgs)) + copy(argCopy, mmConjoinWith.callArgs) + + mmConjoinWith.mutex.RUnlock() + + return argCopy +} + +// MinimockConjoinWithDone returns true if the count of the ConjoinWith invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockConjoinWithDone() bool { + for _, e := range m.ConjoinWithMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.ConjoinWithMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterConjoinWithCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcConjoinWith != nil && mm_atomic.LoadUint64(&m.afterConjoinWithCounter) < 1 { + return false + } + return true +} + +// MinimockConjoinWithInspect logs each unmet expectation +func (m *PredicateMock) MinimockConjoinWithInspect() { + for _, e := range m.ConjoinWithMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.ConjoinWith with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.ConjoinWithMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterConjoinWithCounter) < 1 { + if m.ConjoinWithMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.ConjoinWith") + } else { + m.t.Errorf("Expected call to PredicateMock.ConjoinWith with params: %#v", *m.ConjoinWithMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcConjoinWith != nil && mm_atomic.LoadUint64(&m.afterConjoinWithCounter) < 1 { + m.t.Error("Expected call to PredicateMock.ConjoinWith") + } +} + +type mPredicateMockEquatesWithConstant struct { + mock *PredicateMock + defaultExpectation *PredicateMockEquatesWithConstantExpectation + expectations []*PredicateMockEquatesWithConstantExpectation + + callArgs []*PredicateMockEquatesWithConstantParams + mutex sync.RWMutex +} + +// PredicateMockEquatesWithConstantExpectation specifies expectation struct of the Predicate.EquatesWithConstant +type PredicateMockEquatesWithConstantExpectation struct { + mock *PredicateMock + params *PredicateMockEquatesWithConstantParams + results *PredicateMockEquatesWithConstantResults + Counter uint64 +} + +// PredicateMockEquatesWithConstantParams contains parameters of the Predicate.EquatesWithConstant +type PredicateMockEquatesWithConstantParams struct { + s1 string +} + +// PredicateMockEquatesWithConstantResults contains results of the Predicate.EquatesWithConstant +type PredicateMockEquatesWithConstantResults struct { + c1 mm_scan.Constant + b1 bool +} + +// Expect sets up expected params for Predicate.EquatesWithConstant +func (mmEquatesWithConstant *mPredicateMockEquatesWithConstant) Expect(s1 string) *mPredicateMockEquatesWithConstant { + if mmEquatesWithConstant.mock.funcEquatesWithConstant != nil { + mmEquatesWithConstant.mock.t.Fatalf("PredicateMock.EquatesWithConstant mock is already set by Set") + } + + if mmEquatesWithConstant.defaultExpectation == nil { + mmEquatesWithConstant.defaultExpectation = &PredicateMockEquatesWithConstantExpectation{} + } + + mmEquatesWithConstant.defaultExpectation.params = &PredicateMockEquatesWithConstantParams{s1} + for _, e := range mmEquatesWithConstant.expectations { + if minimock.Equal(e.params, mmEquatesWithConstant.defaultExpectation.params) { + mmEquatesWithConstant.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmEquatesWithConstant.defaultExpectation.params) + } + } + + return mmEquatesWithConstant +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.EquatesWithConstant +func (mmEquatesWithConstant *mPredicateMockEquatesWithConstant) Inspect(f func(s1 string)) *mPredicateMockEquatesWithConstant { + if mmEquatesWithConstant.mock.inspectFuncEquatesWithConstant != nil { + mmEquatesWithConstant.mock.t.Fatalf("Inspect function is already set for PredicateMock.EquatesWithConstant") + } + + mmEquatesWithConstant.mock.inspectFuncEquatesWithConstant = f + + return mmEquatesWithConstant +} + +// Return sets up results that will be returned by Predicate.EquatesWithConstant +func (mmEquatesWithConstant *mPredicateMockEquatesWithConstant) Return(c1 mm_scan.Constant, b1 bool) *PredicateMock { + if mmEquatesWithConstant.mock.funcEquatesWithConstant != nil { + mmEquatesWithConstant.mock.t.Fatalf("PredicateMock.EquatesWithConstant mock is already set by Set") + } + + if mmEquatesWithConstant.defaultExpectation == nil { + mmEquatesWithConstant.defaultExpectation = &PredicateMockEquatesWithConstantExpectation{mock: mmEquatesWithConstant.mock} + } + mmEquatesWithConstant.defaultExpectation.results = &PredicateMockEquatesWithConstantResults{c1, b1} + return mmEquatesWithConstant.mock +} + +//Set uses given function f to mock the Predicate.EquatesWithConstant method +func (mmEquatesWithConstant *mPredicateMockEquatesWithConstant) Set(f func(s1 string) (c1 mm_scan.Constant, b1 bool)) *PredicateMock { + if mmEquatesWithConstant.defaultExpectation != nil { + mmEquatesWithConstant.mock.t.Fatalf("Default expectation is already set for the Predicate.EquatesWithConstant method") + } + + if len(mmEquatesWithConstant.expectations) > 0 { + mmEquatesWithConstant.mock.t.Fatalf("Some expectations are already set for the Predicate.EquatesWithConstant method") + } + + mmEquatesWithConstant.mock.funcEquatesWithConstant = f + return mmEquatesWithConstant.mock +} + +// When sets expectation for the Predicate.EquatesWithConstant which will trigger the result defined by the following +// Then helper +func (mmEquatesWithConstant *mPredicateMockEquatesWithConstant) When(s1 string) *PredicateMockEquatesWithConstantExpectation { + if mmEquatesWithConstant.mock.funcEquatesWithConstant != nil { + mmEquatesWithConstant.mock.t.Fatalf("PredicateMock.EquatesWithConstant mock is already set by Set") + } + + expectation := &PredicateMockEquatesWithConstantExpectation{ + mock: mmEquatesWithConstant.mock, + params: &PredicateMockEquatesWithConstantParams{s1}, + } + mmEquatesWithConstant.expectations = append(mmEquatesWithConstant.expectations, expectation) + return expectation +} + +// Then sets up Predicate.EquatesWithConstant return parameters for the expectation previously defined by the When method +func (e *PredicateMockEquatesWithConstantExpectation) Then(c1 mm_scan.Constant, b1 bool) *PredicateMock { + e.results = &PredicateMockEquatesWithConstantResults{c1, b1} + return e.mock +} + +// EquatesWithConstant implements scan.Predicate +func (mmEquatesWithConstant *PredicateMock) EquatesWithConstant(s1 string) (c1 mm_scan.Constant, b1 bool) { + mm_atomic.AddUint64(&mmEquatesWithConstant.beforeEquatesWithConstantCounter, 1) + defer mm_atomic.AddUint64(&mmEquatesWithConstant.afterEquatesWithConstantCounter, 1) + + if mmEquatesWithConstant.inspectFuncEquatesWithConstant != nil { + mmEquatesWithConstant.inspectFuncEquatesWithConstant(s1) + } + + mm_params := &PredicateMockEquatesWithConstantParams{s1} + + // Record call args + mmEquatesWithConstant.EquatesWithConstantMock.mutex.Lock() + mmEquatesWithConstant.EquatesWithConstantMock.callArgs = append(mmEquatesWithConstant.EquatesWithConstantMock.callArgs, mm_params) + mmEquatesWithConstant.EquatesWithConstantMock.mutex.Unlock() + + for _, e := range mmEquatesWithConstant.EquatesWithConstantMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.c1, e.results.b1 + } + } + + if mmEquatesWithConstant.EquatesWithConstantMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmEquatesWithConstant.EquatesWithConstantMock.defaultExpectation.Counter, 1) + mm_want := mmEquatesWithConstant.EquatesWithConstantMock.defaultExpectation.params + mm_got := PredicateMockEquatesWithConstantParams{s1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmEquatesWithConstant.t.Errorf("PredicateMock.EquatesWithConstant got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmEquatesWithConstant.EquatesWithConstantMock.defaultExpectation.results + if mm_results == nil { + mmEquatesWithConstant.t.Fatal("No results are set for the PredicateMock.EquatesWithConstant") + } + return (*mm_results).c1, (*mm_results).b1 + } + if mmEquatesWithConstant.funcEquatesWithConstant != nil { + return mmEquatesWithConstant.funcEquatesWithConstant(s1) + } + mmEquatesWithConstant.t.Fatalf("Unexpected call to PredicateMock.EquatesWithConstant. %v", s1) + return +} + +// EquatesWithConstantAfterCounter returns a count of finished PredicateMock.EquatesWithConstant invocations +func (mmEquatesWithConstant *PredicateMock) EquatesWithConstantAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmEquatesWithConstant.afterEquatesWithConstantCounter) +} + +// EquatesWithConstantBeforeCounter returns a count of PredicateMock.EquatesWithConstant invocations +func (mmEquatesWithConstant *PredicateMock) EquatesWithConstantBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmEquatesWithConstant.beforeEquatesWithConstantCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.EquatesWithConstant. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmEquatesWithConstant *mPredicateMockEquatesWithConstant) Calls() []*PredicateMockEquatesWithConstantParams { + mmEquatesWithConstant.mutex.RLock() + + argCopy := make([]*PredicateMockEquatesWithConstantParams, len(mmEquatesWithConstant.callArgs)) + copy(argCopy, mmEquatesWithConstant.callArgs) + + mmEquatesWithConstant.mutex.RUnlock() + + return argCopy +} + +// MinimockEquatesWithConstantDone returns true if the count of the EquatesWithConstant invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockEquatesWithConstantDone() bool { + for _, e := range m.EquatesWithConstantMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.EquatesWithConstantMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterEquatesWithConstantCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcEquatesWithConstant != nil && mm_atomic.LoadUint64(&m.afterEquatesWithConstantCounter) < 1 { + return false + } + return true +} + +// MinimockEquatesWithConstantInspect logs each unmet expectation +func (m *PredicateMock) MinimockEquatesWithConstantInspect() { + for _, e := range m.EquatesWithConstantMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.EquatesWithConstant with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.EquatesWithConstantMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterEquatesWithConstantCounter) < 1 { + if m.EquatesWithConstantMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.EquatesWithConstant") + } else { + m.t.Errorf("Expected call to PredicateMock.EquatesWithConstant with params: %#v", *m.EquatesWithConstantMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcEquatesWithConstant != nil && mm_atomic.LoadUint64(&m.afterEquatesWithConstantCounter) < 1 { + m.t.Error("Expected call to PredicateMock.EquatesWithConstant") + } +} + +type mPredicateMockEquatesWithField struct { + mock *PredicateMock + defaultExpectation *PredicateMockEquatesWithFieldExpectation + expectations []*PredicateMockEquatesWithFieldExpectation + + callArgs []*PredicateMockEquatesWithFieldParams + mutex sync.RWMutex +} + +// PredicateMockEquatesWithFieldExpectation specifies expectation struct of the Predicate.EquatesWithField +type PredicateMockEquatesWithFieldExpectation struct { + mock *PredicateMock + params *PredicateMockEquatesWithFieldParams + results *PredicateMockEquatesWithFieldResults + Counter uint64 +} + +// PredicateMockEquatesWithFieldParams contains parameters of the Predicate.EquatesWithField +type PredicateMockEquatesWithFieldParams struct { + s1 string +} + +// PredicateMockEquatesWithFieldResults contains results of the Predicate.EquatesWithField +type PredicateMockEquatesWithFieldResults struct { + s2 string + b1 bool +} + +// Expect sets up expected params for Predicate.EquatesWithField +func (mmEquatesWithField *mPredicateMockEquatesWithField) Expect(s1 string) *mPredicateMockEquatesWithField { + if mmEquatesWithField.mock.funcEquatesWithField != nil { + mmEquatesWithField.mock.t.Fatalf("PredicateMock.EquatesWithField mock is already set by Set") + } + + if mmEquatesWithField.defaultExpectation == nil { + mmEquatesWithField.defaultExpectation = &PredicateMockEquatesWithFieldExpectation{} + } + + mmEquatesWithField.defaultExpectation.params = &PredicateMockEquatesWithFieldParams{s1} + for _, e := range mmEquatesWithField.expectations { + if minimock.Equal(e.params, mmEquatesWithField.defaultExpectation.params) { + mmEquatesWithField.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmEquatesWithField.defaultExpectation.params) + } + } + + return mmEquatesWithField +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.EquatesWithField +func (mmEquatesWithField *mPredicateMockEquatesWithField) Inspect(f func(s1 string)) *mPredicateMockEquatesWithField { + if mmEquatesWithField.mock.inspectFuncEquatesWithField != nil { + mmEquatesWithField.mock.t.Fatalf("Inspect function is already set for PredicateMock.EquatesWithField") + } + + mmEquatesWithField.mock.inspectFuncEquatesWithField = f + + return mmEquatesWithField +} + +// Return sets up results that will be returned by Predicate.EquatesWithField +func (mmEquatesWithField *mPredicateMockEquatesWithField) Return(s2 string, b1 bool) *PredicateMock { + if mmEquatesWithField.mock.funcEquatesWithField != nil { + mmEquatesWithField.mock.t.Fatalf("PredicateMock.EquatesWithField mock is already set by Set") + } + + if mmEquatesWithField.defaultExpectation == nil { + mmEquatesWithField.defaultExpectation = &PredicateMockEquatesWithFieldExpectation{mock: mmEquatesWithField.mock} + } + mmEquatesWithField.defaultExpectation.results = &PredicateMockEquatesWithFieldResults{s2, b1} + return mmEquatesWithField.mock +} + +//Set uses given function f to mock the Predicate.EquatesWithField method +func (mmEquatesWithField *mPredicateMockEquatesWithField) Set(f func(s1 string) (s2 string, b1 bool)) *PredicateMock { + if mmEquatesWithField.defaultExpectation != nil { + mmEquatesWithField.mock.t.Fatalf("Default expectation is already set for the Predicate.EquatesWithField method") + } + + if len(mmEquatesWithField.expectations) > 0 { + mmEquatesWithField.mock.t.Fatalf("Some expectations are already set for the Predicate.EquatesWithField method") + } + + mmEquatesWithField.mock.funcEquatesWithField = f + return mmEquatesWithField.mock +} + +// When sets expectation for the Predicate.EquatesWithField which will trigger the result defined by the following +// Then helper +func (mmEquatesWithField *mPredicateMockEquatesWithField) When(s1 string) *PredicateMockEquatesWithFieldExpectation { + if mmEquatesWithField.mock.funcEquatesWithField != nil { + mmEquatesWithField.mock.t.Fatalf("PredicateMock.EquatesWithField mock is already set by Set") + } + + expectation := &PredicateMockEquatesWithFieldExpectation{ + mock: mmEquatesWithField.mock, + params: &PredicateMockEquatesWithFieldParams{s1}, + } + mmEquatesWithField.expectations = append(mmEquatesWithField.expectations, expectation) + return expectation +} + +// Then sets up Predicate.EquatesWithField return parameters for the expectation previously defined by the When method +func (e *PredicateMockEquatesWithFieldExpectation) Then(s2 string, b1 bool) *PredicateMock { + e.results = &PredicateMockEquatesWithFieldResults{s2, b1} + return e.mock +} + +// EquatesWithField implements scan.Predicate +func (mmEquatesWithField *PredicateMock) EquatesWithField(s1 string) (s2 string, b1 bool) { + mm_atomic.AddUint64(&mmEquatesWithField.beforeEquatesWithFieldCounter, 1) + defer mm_atomic.AddUint64(&mmEquatesWithField.afterEquatesWithFieldCounter, 1) + + if mmEquatesWithField.inspectFuncEquatesWithField != nil { + mmEquatesWithField.inspectFuncEquatesWithField(s1) + } + + mm_params := &PredicateMockEquatesWithFieldParams{s1} + + // Record call args + mmEquatesWithField.EquatesWithFieldMock.mutex.Lock() + mmEquatesWithField.EquatesWithFieldMock.callArgs = append(mmEquatesWithField.EquatesWithFieldMock.callArgs, mm_params) + mmEquatesWithField.EquatesWithFieldMock.mutex.Unlock() + + for _, e := range mmEquatesWithField.EquatesWithFieldMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.s2, e.results.b1 + } + } + + if mmEquatesWithField.EquatesWithFieldMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmEquatesWithField.EquatesWithFieldMock.defaultExpectation.Counter, 1) + mm_want := mmEquatesWithField.EquatesWithFieldMock.defaultExpectation.params + mm_got := PredicateMockEquatesWithFieldParams{s1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmEquatesWithField.t.Errorf("PredicateMock.EquatesWithField got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmEquatesWithField.EquatesWithFieldMock.defaultExpectation.results + if mm_results == nil { + mmEquatesWithField.t.Fatal("No results are set for the PredicateMock.EquatesWithField") + } + return (*mm_results).s2, (*mm_results).b1 + } + if mmEquatesWithField.funcEquatesWithField != nil { + return mmEquatesWithField.funcEquatesWithField(s1) + } + mmEquatesWithField.t.Fatalf("Unexpected call to PredicateMock.EquatesWithField. %v", s1) + return +} + +// EquatesWithFieldAfterCounter returns a count of finished PredicateMock.EquatesWithField invocations +func (mmEquatesWithField *PredicateMock) EquatesWithFieldAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmEquatesWithField.afterEquatesWithFieldCounter) +} + +// EquatesWithFieldBeforeCounter returns a count of PredicateMock.EquatesWithField invocations +func (mmEquatesWithField *PredicateMock) EquatesWithFieldBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmEquatesWithField.beforeEquatesWithFieldCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.EquatesWithField. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmEquatesWithField *mPredicateMockEquatesWithField) Calls() []*PredicateMockEquatesWithFieldParams { + mmEquatesWithField.mutex.RLock() + + argCopy := make([]*PredicateMockEquatesWithFieldParams, len(mmEquatesWithField.callArgs)) + copy(argCopy, mmEquatesWithField.callArgs) + + mmEquatesWithField.mutex.RUnlock() + + return argCopy +} + +// MinimockEquatesWithFieldDone returns true if the count of the EquatesWithField invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockEquatesWithFieldDone() bool { + for _, e := range m.EquatesWithFieldMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.EquatesWithFieldMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterEquatesWithFieldCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcEquatesWithField != nil && mm_atomic.LoadUint64(&m.afterEquatesWithFieldCounter) < 1 { + return false + } + return true +} + +// MinimockEquatesWithFieldInspect logs each unmet expectation +func (m *PredicateMock) MinimockEquatesWithFieldInspect() { + for _, e := range m.EquatesWithFieldMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.EquatesWithField with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.EquatesWithFieldMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterEquatesWithFieldCounter) < 1 { + if m.EquatesWithFieldMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.EquatesWithField") + } else { + m.t.Errorf("Expected call to PredicateMock.EquatesWithField with params: %#v", *m.EquatesWithFieldMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcEquatesWithField != nil && mm_atomic.LoadUint64(&m.afterEquatesWithFieldCounter) < 1 { + m.t.Error("Expected call to PredicateMock.EquatesWithField") + } +} + +type mPredicateMockIsSatisfied struct { + mock *PredicateMock + defaultExpectation *PredicateMockIsSatisfiedExpectation + expectations []*PredicateMockIsSatisfiedExpectation + + callArgs []*PredicateMockIsSatisfiedParams + mutex sync.RWMutex +} + +// PredicateMockIsSatisfiedExpectation specifies expectation struct of the Predicate.IsSatisfied +type PredicateMockIsSatisfiedExpectation struct { + mock *PredicateMock + params *PredicateMockIsSatisfiedParams + results *PredicateMockIsSatisfiedResults + Counter uint64 +} + +// PredicateMockIsSatisfiedParams contains parameters of the Predicate.IsSatisfied +type PredicateMockIsSatisfiedParams struct { + s1 mm_scan.Scan +} + +// PredicateMockIsSatisfiedResults contains results of the Predicate.IsSatisfied +type PredicateMockIsSatisfiedResults struct { + b1 bool + err error +} + +// Expect sets up expected params for Predicate.IsSatisfied +func (mmIsSatisfied *mPredicateMockIsSatisfied) Expect(s1 mm_scan.Scan) *mPredicateMockIsSatisfied { + if mmIsSatisfied.mock.funcIsSatisfied != nil { + mmIsSatisfied.mock.t.Fatalf("PredicateMock.IsSatisfied mock is already set by Set") + } + + if mmIsSatisfied.defaultExpectation == nil { + mmIsSatisfied.defaultExpectation = &PredicateMockIsSatisfiedExpectation{} + } + + mmIsSatisfied.defaultExpectation.params = &PredicateMockIsSatisfiedParams{s1} + for _, e := range mmIsSatisfied.expectations { + if minimock.Equal(e.params, mmIsSatisfied.defaultExpectation.params) { + mmIsSatisfied.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmIsSatisfied.defaultExpectation.params) + } + } + + return mmIsSatisfied +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.IsSatisfied +func (mmIsSatisfied *mPredicateMockIsSatisfied) Inspect(f func(s1 mm_scan.Scan)) *mPredicateMockIsSatisfied { + if mmIsSatisfied.mock.inspectFuncIsSatisfied != nil { + mmIsSatisfied.mock.t.Fatalf("Inspect function is already set for PredicateMock.IsSatisfied") + } + + mmIsSatisfied.mock.inspectFuncIsSatisfied = f + + return mmIsSatisfied +} + +// Return sets up results that will be returned by Predicate.IsSatisfied +func (mmIsSatisfied *mPredicateMockIsSatisfied) Return(b1 bool, err error) *PredicateMock { + if mmIsSatisfied.mock.funcIsSatisfied != nil { + mmIsSatisfied.mock.t.Fatalf("PredicateMock.IsSatisfied mock is already set by Set") + } + + if mmIsSatisfied.defaultExpectation == nil { + mmIsSatisfied.defaultExpectation = &PredicateMockIsSatisfiedExpectation{mock: mmIsSatisfied.mock} + } + mmIsSatisfied.defaultExpectation.results = &PredicateMockIsSatisfiedResults{b1, err} + return mmIsSatisfied.mock +} + +//Set uses given function f to mock the Predicate.IsSatisfied method +func (mmIsSatisfied *mPredicateMockIsSatisfied) Set(f func(s1 mm_scan.Scan) (b1 bool, err error)) *PredicateMock { + if mmIsSatisfied.defaultExpectation != nil { + mmIsSatisfied.mock.t.Fatalf("Default expectation is already set for the Predicate.IsSatisfied method") + } + + if len(mmIsSatisfied.expectations) > 0 { + mmIsSatisfied.mock.t.Fatalf("Some expectations are already set for the Predicate.IsSatisfied method") + } + + mmIsSatisfied.mock.funcIsSatisfied = f + return mmIsSatisfied.mock +} + +// When sets expectation for the Predicate.IsSatisfied which will trigger the result defined by the following +// Then helper +func (mmIsSatisfied *mPredicateMockIsSatisfied) When(s1 mm_scan.Scan) *PredicateMockIsSatisfiedExpectation { + if mmIsSatisfied.mock.funcIsSatisfied != nil { + mmIsSatisfied.mock.t.Fatalf("PredicateMock.IsSatisfied mock is already set by Set") + } + + expectation := &PredicateMockIsSatisfiedExpectation{ + mock: mmIsSatisfied.mock, + params: &PredicateMockIsSatisfiedParams{s1}, + } + mmIsSatisfied.expectations = append(mmIsSatisfied.expectations, expectation) + return expectation +} + +// Then sets up Predicate.IsSatisfied return parameters for the expectation previously defined by the When method +func (e *PredicateMockIsSatisfiedExpectation) Then(b1 bool, err error) *PredicateMock { + e.results = &PredicateMockIsSatisfiedResults{b1, err} + return e.mock +} + +// IsSatisfied implements scan.Predicate +func (mmIsSatisfied *PredicateMock) IsSatisfied(s1 mm_scan.Scan) (b1 bool, err error) { + mm_atomic.AddUint64(&mmIsSatisfied.beforeIsSatisfiedCounter, 1) + defer mm_atomic.AddUint64(&mmIsSatisfied.afterIsSatisfiedCounter, 1) + + if mmIsSatisfied.inspectFuncIsSatisfied != nil { + mmIsSatisfied.inspectFuncIsSatisfied(s1) + } + + mm_params := &PredicateMockIsSatisfiedParams{s1} + + // Record call args + mmIsSatisfied.IsSatisfiedMock.mutex.Lock() + mmIsSatisfied.IsSatisfiedMock.callArgs = append(mmIsSatisfied.IsSatisfiedMock.callArgs, mm_params) + mmIsSatisfied.IsSatisfiedMock.mutex.Unlock() + + for _, e := range mmIsSatisfied.IsSatisfiedMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.b1, e.results.err + } + } + + if mmIsSatisfied.IsSatisfiedMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmIsSatisfied.IsSatisfiedMock.defaultExpectation.Counter, 1) + mm_want := mmIsSatisfied.IsSatisfiedMock.defaultExpectation.params + mm_got := PredicateMockIsSatisfiedParams{s1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmIsSatisfied.t.Errorf("PredicateMock.IsSatisfied got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmIsSatisfied.IsSatisfiedMock.defaultExpectation.results + if mm_results == nil { + mmIsSatisfied.t.Fatal("No results are set for the PredicateMock.IsSatisfied") + } + return (*mm_results).b1, (*mm_results).err + } + if mmIsSatisfied.funcIsSatisfied != nil { + return mmIsSatisfied.funcIsSatisfied(s1) + } + mmIsSatisfied.t.Fatalf("Unexpected call to PredicateMock.IsSatisfied. %v", s1) + return +} + +// IsSatisfiedAfterCounter returns a count of finished PredicateMock.IsSatisfied invocations +func (mmIsSatisfied *PredicateMock) IsSatisfiedAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmIsSatisfied.afterIsSatisfiedCounter) +} + +// IsSatisfiedBeforeCounter returns a count of PredicateMock.IsSatisfied invocations +func (mmIsSatisfied *PredicateMock) IsSatisfiedBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmIsSatisfied.beforeIsSatisfiedCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.IsSatisfied. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmIsSatisfied *mPredicateMockIsSatisfied) Calls() []*PredicateMockIsSatisfiedParams { + mmIsSatisfied.mutex.RLock() + + argCopy := make([]*PredicateMockIsSatisfiedParams, len(mmIsSatisfied.callArgs)) + copy(argCopy, mmIsSatisfied.callArgs) + + mmIsSatisfied.mutex.RUnlock() + + return argCopy +} + +// MinimockIsSatisfiedDone returns true if the count of the IsSatisfied invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockIsSatisfiedDone() bool { + for _, e := range m.IsSatisfiedMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.IsSatisfiedMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterIsSatisfiedCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcIsSatisfied != nil && mm_atomic.LoadUint64(&m.afterIsSatisfiedCounter) < 1 { + return false + } + return true +} + +// MinimockIsSatisfiedInspect logs each unmet expectation +func (m *PredicateMock) MinimockIsSatisfiedInspect() { + for _, e := range m.IsSatisfiedMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.IsSatisfied with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.IsSatisfiedMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterIsSatisfiedCounter) < 1 { + if m.IsSatisfiedMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.IsSatisfied") + } else { + m.t.Errorf("Expected call to PredicateMock.IsSatisfied with params: %#v", *m.IsSatisfiedMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcIsSatisfied != nil && mm_atomic.LoadUint64(&m.afterIsSatisfiedCounter) < 1 { + m.t.Error("Expected call to PredicateMock.IsSatisfied") + } +} + +type mPredicateMockJoinSubPred struct { + mock *PredicateMock + defaultExpectation *PredicateMockJoinSubPredExpectation + expectations []*PredicateMockJoinSubPredExpectation + + callArgs []*PredicateMockJoinSubPredParams + mutex sync.RWMutex +} + +// PredicateMockJoinSubPredExpectation specifies expectation struct of the Predicate.JoinSubPred +type PredicateMockJoinSubPredExpectation struct { + mock *PredicateMock + params *PredicateMockJoinSubPredParams + results *PredicateMockJoinSubPredResults + Counter uint64 +} + +// PredicateMockJoinSubPredParams contains parameters of the Predicate.JoinSubPred +type PredicateMockJoinSubPredParams struct { + s1 records.Schema + s2 records.Schema +} + +// PredicateMockJoinSubPredResults contains results of the Predicate.JoinSubPred +type PredicateMockJoinSubPredResults struct { + p1 mm_scan.Predicate +} + +// Expect sets up expected params for Predicate.JoinSubPred +func (mmJoinSubPred *mPredicateMockJoinSubPred) Expect(s1 records.Schema, s2 records.Schema) *mPredicateMockJoinSubPred { + if mmJoinSubPred.mock.funcJoinSubPred != nil { + mmJoinSubPred.mock.t.Fatalf("PredicateMock.JoinSubPred mock is already set by Set") + } + + if mmJoinSubPred.defaultExpectation == nil { + mmJoinSubPred.defaultExpectation = &PredicateMockJoinSubPredExpectation{} + } + + mmJoinSubPred.defaultExpectation.params = &PredicateMockJoinSubPredParams{s1, s2} + for _, e := range mmJoinSubPred.expectations { + if minimock.Equal(e.params, mmJoinSubPred.defaultExpectation.params) { + mmJoinSubPred.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmJoinSubPred.defaultExpectation.params) + } + } + + return mmJoinSubPred +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.JoinSubPred +func (mmJoinSubPred *mPredicateMockJoinSubPred) Inspect(f func(s1 records.Schema, s2 records.Schema)) *mPredicateMockJoinSubPred { + if mmJoinSubPred.mock.inspectFuncJoinSubPred != nil { + mmJoinSubPred.mock.t.Fatalf("Inspect function is already set for PredicateMock.JoinSubPred") + } + + mmJoinSubPred.mock.inspectFuncJoinSubPred = f + + return mmJoinSubPred +} + +// Return sets up results that will be returned by Predicate.JoinSubPred +func (mmJoinSubPred *mPredicateMockJoinSubPred) Return(p1 mm_scan.Predicate) *PredicateMock { + if mmJoinSubPred.mock.funcJoinSubPred != nil { + mmJoinSubPred.mock.t.Fatalf("PredicateMock.JoinSubPred mock is already set by Set") + } + + if mmJoinSubPred.defaultExpectation == nil { + mmJoinSubPred.defaultExpectation = &PredicateMockJoinSubPredExpectation{mock: mmJoinSubPred.mock} + } + mmJoinSubPred.defaultExpectation.results = &PredicateMockJoinSubPredResults{p1} + return mmJoinSubPred.mock +} + +//Set uses given function f to mock the Predicate.JoinSubPred method +func (mmJoinSubPred *mPredicateMockJoinSubPred) Set(f func(s1 records.Schema, s2 records.Schema) (p1 mm_scan.Predicate)) *PredicateMock { + if mmJoinSubPred.defaultExpectation != nil { + mmJoinSubPred.mock.t.Fatalf("Default expectation is already set for the Predicate.JoinSubPred method") + } + + if len(mmJoinSubPred.expectations) > 0 { + mmJoinSubPred.mock.t.Fatalf("Some expectations are already set for the Predicate.JoinSubPred method") + } + + mmJoinSubPred.mock.funcJoinSubPred = f + return mmJoinSubPred.mock +} + +// When sets expectation for the Predicate.JoinSubPred which will trigger the result defined by the following +// Then helper +func (mmJoinSubPred *mPredicateMockJoinSubPred) When(s1 records.Schema, s2 records.Schema) *PredicateMockJoinSubPredExpectation { + if mmJoinSubPred.mock.funcJoinSubPred != nil { + mmJoinSubPred.mock.t.Fatalf("PredicateMock.JoinSubPred mock is already set by Set") + } + + expectation := &PredicateMockJoinSubPredExpectation{ + mock: mmJoinSubPred.mock, + params: &PredicateMockJoinSubPredParams{s1, s2}, + } + mmJoinSubPred.expectations = append(mmJoinSubPred.expectations, expectation) + return expectation +} + +// Then sets up Predicate.JoinSubPred return parameters for the expectation previously defined by the When method +func (e *PredicateMockJoinSubPredExpectation) Then(p1 mm_scan.Predicate) *PredicateMock { + e.results = &PredicateMockJoinSubPredResults{p1} + return e.mock +} + +// JoinSubPred implements scan.Predicate +func (mmJoinSubPred *PredicateMock) JoinSubPred(s1 records.Schema, s2 records.Schema) (p1 mm_scan.Predicate) { + mm_atomic.AddUint64(&mmJoinSubPred.beforeJoinSubPredCounter, 1) + defer mm_atomic.AddUint64(&mmJoinSubPred.afterJoinSubPredCounter, 1) + + if mmJoinSubPred.inspectFuncJoinSubPred != nil { + mmJoinSubPred.inspectFuncJoinSubPred(s1, s2) + } + + mm_params := &PredicateMockJoinSubPredParams{s1, s2} + + // Record call args + mmJoinSubPred.JoinSubPredMock.mutex.Lock() + mmJoinSubPred.JoinSubPredMock.callArgs = append(mmJoinSubPred.JoinSubPredMock.callArgs, mm_params) + mmJoinSubPred.JoinSubPredMock.mutex.Unlock() + + for _, e := range mmJoinSubPred.JoinSubPredMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.p1 + } + } + + if mmJoinSubPred.JoinSubPredMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmJoinSubPred.JoinSubPredMock.defaultExpectation.Counter, 1) + mm_want := mmJoinSubPred.JoinSubPredMock.defaultExpectation.params + mm_got := PredicateMockJoinSubPredParams{s1, s2} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmJoinSubPred.t.Errorf("PredicateMock.JoinSubPred got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmJoinSubPred.JoinSubPredMock.defaultExpectation.results + if mm_results == nil { + mmJoinSubPred.t.Fatal("No results are set for the PredicateMock.JoinSubPred") + } + return (*mm_results).p1 + } + if mmJoinSubPred.funcJoinSubPred != nil { + return mmJoinSubPred.funcJoinSubPred(s1, s2) + } + mmJoinSubPred.t.Fatalf("Unexpected call to PredicateMock.JoinSubPred. %v %v", s1, s2) + return +} + +// JoinSubPredAfterCounter returns a count of finished PredicateMock.JoinSubPred invocations +func (mmJoinSubPred *PredicateMock) JoinSubPredAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmJoinSubPred.afterJoinSubPredCounter) +} + +// JoinSubPredBeforeCounter returns a count of PredicateMock.JoinSubPred invocations +func (mmJoinSubPred *PredicateMock) JoinSubPredBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmJoinSubPred.beforeJoinSubPredCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.JoinSubPred. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmJoinSubPred *mPredicateMockJoinSubPred) Calls() []*PredicateMockJoinSubPredParams { + mmJoinSubPred.mutex.RLock() + + argCopy := make([]*PredicateMockJoinSubPredParams, len(mmJoinSubPred.callArgs)) + copy(argCopy, mmJoinSubPred.callArgs) + + mmJoinSubPred.mutex.RUnlock() + + return argCopy +} + +// MinimockJoinSubPredDone returns true if the count of the JoinSubPred invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockJoinSubPredDone() bool { + for _, e := range m.JoinSubPredMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.JoinSubPredMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterJoinSubPredCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcJoinSubPred != nil && mm_atomic.LoadUint64(&m.afterJoinSubPredCounter) < 1 { + return false + } + return true +} + +// MinimockJoinSubPredInspect logs each unmet expectation +func (m *PredicateMock) MinimockJoinSubPredInspect() { + for _, e := range m.JoinSubPredMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.JoinSubPred with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.JoinSubPredMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterJoinSubPredCounter) < 1 { + if m.JoinSubPredMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.JoinSubPred") + } else { + m.t.Errorf("Expected call to PredicateMock.JoinSubPred with params: %#v", *m.JoinSubPredMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcJoinSubPred != nil && mm_atomic.LoadUint64(&m.afterJoinSubPredCounter) < 1 { + m.t.Error("Expected call to PredicateMock.JoinSubPred") + } +} + +type mPredicateMockReductionFactor struct { + mock *PredicateMock + defaultExpectation *PredicateMockReductionFactorExpectation + expectations []*PredicateMockReductionFactorExpectation + + callArgs []*PredicateMockReductionFactorParams + mutex sync.RWMutex +} + +// PredicateMockReductionFactorExpectation specifies expectation struct of the Predicate.ReductionFactor +type PredicateMockReductionFactorExpectation struct { + mock *PredicateMock + params *PredicateMockReductionFactorParams + results *PredicateMockReductionFactorResults + Counter uint64 +} + +// PredicateMockReductionFactorParams contains parameters of the Predicate.ReductionFactor +type PredicateMockReductionFactorParams struct { + p1 mm_scan.Plan +} + +// PredicateMockReductionFactorResults contains results of the Predicate.ReductionFactor +type PredicateMockReductionFactorResults struct { + i1 int64 + b1 bool +} + +// Expect sets up expected params for Predicate.ReductionFactor +func (mmReductionFactor *mPredicateMockReductionFactor) Expect(p1 mm_scan.Plan) *mPredicateMockReductionFactor { + if mmReductionFactor.mock.funcReductionFactor != nil { + mmReductionFactor.mock.t.Fatalf("PredicateMock.ReductionFactor mock is already set by Set") + } + + if mmReductionFactor.defaultExpectation == nil { + mmReductionFactor.defaultExpectation = &PredicateMockReductionFactorExpectation{} + } + + mmReductionFactor.defaultExpectation.params = &PredicateMockReductionFactorParams{p1} + for _, e := range mmReductionFactor.expectations { + if minimock.Equal(e.params, mmReductionFactor.defaultExpectation.params) { + mmReductionFactor.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmReductionFactor.defaultExpectation.params) + } + } + + return mmReductionFactor +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.ReductionFactor +func (mmReductionFactor *mPredicateMockReductionFactor) Inspect(f func(p1 mm_scan.Plan)) *mPredicateMockReductionFactor { + if mmReductionFactor.mock.inspectFuncReductionFactor != nil { + mmReductionFactor.mock.t.Fatalf("Inspect function is already set for PredicateMock.ReductionFactor") + } + + mmReductionFactor.mock.inspectFuncReductionFactor = f + + return mmReductionFactor +} + +// Return sets up results that will be returned by Predicate.ReductionFactor +func (mmReductionFactor *mPredicateMockReductionFactor) Return(i1 int64, b1 bool) *PredicateMock { + if mmReductionFactor.mock.funcReductionFactor != nil { + mmReductionFactor.mock.t.Fatalf("PredicateMock.ReductionFactor mock is already set by Set") + } + + if mmReductionFactor.defaultExpectation == nil { + mmReductionFactor.defaultExpectation = &PredicateMockReductionFactorExpectation{mock: mmReductionFactor.mock} + } + mmReductionFactor.defaultExpectation.results = &PredicateMockReductionFactorResults{i1, b1} + return mmReductionFactor.mock +} + +//Set uses given function f to mock the Predicate.ReductionFactor method +func (mmReductionFactor *mPredicateMockReductionFactor) Set(f func(p1 mm_scan.Plan) (i1 int64, b1 bool)) *PredicateMock { + if mmReductionFactor.defaultExpectation != nil { + mmReductionFactor.mock.t.Fatalf("Default expectation is already set for the Predicate.ReductionFactor method") + } + + if len(mmReductionFactor.expectations) > 0 { + mmReductionFactor.mock.t.Fatalf("Some expectations are already set for the Predicate.ReductionFactor method") + } + + mmReductionFactor.mock.funcReductionFactor = f + return mmReductionFactor.mock +} + +// When sets expectation for the Predicate.ReductionFactor which will trigger the result defined by the following +// Then helper +func (mmReductionFactor *mPredicateMockReductionFactor) When(p1 mm_scan.Plan) *PredicateMockReductionFactorExpectation { + if mmReductionFactor.mock.funcReductionFactor != nil { + mmReductionFactor.mock.t.Fatalf("PredicateMock.ReductionFactor mock is already set by Set") + } + + expectation := &PredicateMockReductionFactorExpectation{ + mock: mmReductionFactor.mock, + params: &PredicateMockReductionFactorParams{p1}, + } + mmReductionFactor.expectations = append(mmReductionFactor.expectations, expectation) + return expectation +} + +// Then sets up Predicate.ReductionFactor return parameters for the expectation previously defined by the When method +func (e *PredicateMockReductionFactorExpectation) Then(i1 int64, b1 bool) *PredicateMock { + e.results = &PredicateMockReductionFactorResults{i1, b1} + return e.mock +} + +// ReductionFactor implements scan.Predicate +func (mmReductionFactor *PredicateMock) ReductionFactor(p1 mm_scan.Plan) (i1 int64, b1 bool) { + mm_atomic.AddUint64(&mmReductionFactor.beforeReductionFactorCounter, 1) + defer mm_atomic.AddUint64(&mmReductionFactor.afterReductionFactorCounter, 1) + + if mmReductionFactor.inspectFuncReductionFactor != nil { + mmReductionFactor.inspectFuncReductionFactor(p1) + } + + mm_params := &PredicateMockReductionFactorParams{p1} + + // Record call args + mmReductionFactor.ReductionFactorMock.mutex.Lock() + mmReductionFactor.ReductionFactorMock.callArgs = append(mmReductionFactor.ReductionFactorMock.callArgs, mm_params) + mmReductionFactor.ReductionFactorMock.mutex.Unlock() + + for _, e := range mmReductionFactor.ReductionFactorMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.i1, e.results.b1 + } + } + + if mmReductionFactor.ReductionFactorMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmReductionFactor.ReductionFactorMock.defaultExpectation.Counter, 1) + mm_want := mmReductionFactor.ReductionFactorMock.defaultExpectation.params + mm_got := PredicateMockReductionFactorParams{p1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmReductionFactor.t.Errorf("PredicateMock.ReductionFactor got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmReductionFactor.ReductionFactorMock.defaultExpectation.results + if mm_results == nil { + mmReductionFactor.t.Fatal("No results are set for the PredicateMock.ReductionFactor") + } + return (*mm_results).i1, (*mm_results).b1 + } + if mmReductionFactor.funcReductionFactor != nil { + return mmReductionFactor.funcReductionFactor(p1) + } + mmReductionFactor.t.Fatalf("Unexpected call to PredicateMock.ReductionFactor. %v", p1) + return +} + +// ReductionFactorAfterCounter returns a count of finished PredicateMock.ReductionFactor invocations +func (mmReductionFactor *PredicateMock) ReductionFactorAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmReductionFactor.afterReductionFactorCounter) +} + +// ReductionFactorBeforeCounter returns a count of PredicateMock.ReductionFactor invocations +func (mmReductionFactor *PredicateMock) ReductionFactorBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmReductionFactor.beforeReductionFactorCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.ReductionFactor. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmReductionFactor *mPredicateMockReductionFactor) Calls() []*PredicateMockReductionFactorParams { + mmReductionFactor.mutex.RLock() + + argCopy := make([]*PredicateMockReductionFactorParams, len(mmReductionFactor.callArgs)) + copy(argCopy, mmReductionFactor.callArgs) + + mmReductionFactor.mutex.RUnlock() + + return argCopy +} + +// MinimockReductionFactorDone returns true if the count of the ReductionFactor invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockReductionFactorDone() bool { + for _, e := range m.ReductionFactorMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.ReductionFactorMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterReductionFactorCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcReductionFactor != nil && mm_atomic.LoadUint64(&m.afterReductionFactorCounter) < 1 { + return false + } + return true +} + +// MinimockReductionFactorInspect logs each unmet expectation +func (m *PredicateMock) MinimockReductionFactorInspect() { + for _, e := range m.ReductionFactorMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.ReductionFactor with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.ReductionFactorMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterReductionFactorCounter) < 1 { + if m.ReductionFactorMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.ReductionFactor") + } else { + m.t.Errorf("Expected call to PredicateMock.ReductionFactor with params: %#v", *m.ReductionFactorMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcReductionFactor != nil && mm_atomic.LoadUint64(&m.afterReductionFactorCounter) < 1 { + m.t.Error("Expected call to PredicateMock.ReductionFactor") + } +} + +type mPredicateMockSelectSubPred struct { + mock *PredicateMock + defaultExpectation *PredicateMockSelectSubPredExpectation + expectations []*PredicateMockSelectSubPredExpectation + + callArgs []*PredicateMockSelectSubPredParams + mutex sync.RWMutex +} + +// PredicateMockSelectSubPredExpectation specifies expectation struct of the Predicate.SelectSubPred +type PredicateMockSelectSubPredExpectation struct { + mock *PredicateMock + params *PredicateMockSelectSubPredParams + results *PredicateMockSelectSubPredResults + Counter uint64 +} + +// PredicateMockSelectSubPredParams contains parameters of the Predicate.SelectSubPred +type PredicateMockSelectSubPredParams struct { + s1 records.Schema +} + +// PredicateMockSelectSubPredResults contains results of the Predicate.SelectSubPred +type PredicateMockSelectSubPredResults struct { + p1 mm_scan.Predicate +} + +// Expect sets up expected params for Predicate.SelectSubPred +func (mmSelectSubPred *mPredicateMockSelectSubPred) Expect(s1 records.Schema) *mPredicateMockSelectSubPred { + if mmSelectSubPred.mock.funcSelectSubPred != nil { + mmSelectSubPred.mock.t.Fatalf("PredicateMock.SelectSubPred mock is already set by Set") + } + + if mmSelectSubPred.defaultExpectation == nil { + mmSelectSubPred.defaultExpectation = &PredicateMockSelectSubPredExpectation{} + } + + mmSelectSubPred.defaultExpectation.params = &PredicateMockSelectSubPredParams{s1} + for _, e := range mmSelectSubPred.expectations { + if minimock.Equal(e.params, mmSelectSubPred.defaultExpectation.params) { + mmSelectSubPred.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmSelectSubPred.defaultExpectation.params) + } + } + + return mmSelectSubPred +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.SelectSubPred +func (mmSelectSubPred *mPredicateMockSelectSubPred) Inspect(f func(s1 records.Schema)) *mPredicateMockSelectSubPred { + if mmSelectSubPred.mock.inspectFuncSelectSubPred != nil { + mmSelectSubPred.mock.t.Fatalf("Inspect function is already set for PredicateMock.SelectSubPred") + } + + mmSelectSubPred.mock.inspectFuncSelectSubPred = f + + return mmSelectSubPred +} + +// Return sets up results that will be returned by Predicate.SelectSubPred +func (mmSelectSubPred *mPredicateMockSelectSubPred) Return(p1 mm_scan.Predicate) *PredicateMock { + if mmSelectSubPred.mock.funcSelectSubPred != nil { + mmSelectSubPred.mock.t.Fatalf("PredicateMock.SelectSubPred mock is already set by Set") + } + + if mmSelectSubPred.defaultExpectation == nil { + mmSelectSubPred.defaultExpectation = &PredicateMockSelectSubPredExpectation{mock: mmSelectSubPred.mock} + } + mmSelectSubPred.defaultExpectation.results = &PredicateMockSelectSubPredResults{p1} + return mmSelectSubPred.mock +} + +//Set uses given function f to mock the Predicate.SelectSubPred method +func (mmSelectSubPred *mPredicateMockSelectSubPred) Set(f func(s1 records.Schema) (p1 mm_scan.Predicate)) *PredicateMock { + if mmSelectSubPred.defaultExpectation != nil { + mmSelectSubPred.mock.t.Fatalf("Default expectation is already set for the Predicate.SelectSubPred method") + } + + if len(mmSelectSubPred.expectations) > 0 { + mmSelectSubPred.mock.t.Fatalf("Some expectations are already set for the Predicate.SelectSubPred method") + } + + mmSelectSubPred.mock.funcSelectSubPred = f + return mmSelectSubPred.mock +} + +// When sets expectation for the Predicate.SelectSubPred which will trigger the result defined by the following +// Then helper +func (mmSelectSubPred *mPredicateMockSelectSubPred) When(s1 records.Schema) *PredicateMockSelectSubPredExpectation { + if mmSelectSubPred.mock.funcSelectSubPred != nil { + mmSelectSubPred.mock.t.Fatalf("PredicateMock.SelectSubPred mock is already set by Set") + } + + expectation := &PredicateMockSelectSubPredExpectation{ + mock: mmSelectSubPred.mock, + params: &PredicateMockSelectSubPredParams{s1}, + } + mmSelectSubPred.expectations = append(mmSelectSubPred.expectations, expectation) + return expectation +} + +// Then sets up Predicate.SelectSubPred return parameters for the expectation previously defined by the When method +func (e *PredicateMockSelectSubPredExpectation) Then(p1 mm_scan.Predicate) *PredicateMock { + e.results = &PredicateMockSelectSubPredResults{p1} + return e.mock +} + +// SelectSubPred implements scan.Predicate +func (mmSelectSubPred *PredicateMock) SelectSubPred(s1 records.Schema) (p1 mm_scan.Predicate) { + mm_atomic.AddUint64(&mmSelectSubPred.beforeSelectSubPredCounter, 1) + defer mm_atomic.AddUint64(&mmSelectSubPred.afterSelectSubPredCounter, 1) + + if mmSelectSubPred.inspectFuncSelectSubPred != nil { + mmSelectSubPred.inspectFuncSelectSubPred(s1) + } + + mm_params := &PredicateMockSelectSubPredParams{s1} + + // Record call args + mmSelectSubPred.SelectSubPredMock.mutex.Lock() + mmSelectSubPred.SelectSubPredMock.callArgs = append(mmSelectSubPred.SelectSubPredMock.callArgs, mm_params) + mmSelectSubPred.SelectSubPredMock.mutex.Unlock() + + for _, e := range mmSelectSubPred.SelectSubPredMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.p1 + } + } + + if mmSelectSubPred.SelectSubPredMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmSelectSubPred.SelectSubPredMock.defaultExpectation.Counter, 1) + mm_want := mmSelectSubPred.SelectSubPredMock.defaultExpectation.params + mm_got := PredicateMockSelectSubPredParams{s1} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmSelectSubPred.t.Errorf("PredicateMock.SelectSubPred got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmSelectSubPred.SelectSubPredMock.defaultExpectation.results + if mm_results == nil { + mmSelectSubPred.t.Fatal("No results are set for the PredicateMock.SelectSubPred") + } + return (*mm_results).p1 + } + if mmSelectSubPred.funcSelectSubPred != nil { + return mmSelectSubPred.funcSelectSubPred(s1) + } + mmSelectSubPred.t.Fatalf("Unexpected call to PredicateMock.SelectSubPred. %v", s1) + return +} + +// SelectSubPredAfterCounter returns a count of finished PredicateMock.SelectSubPred invocations +func (mmSelectSubPred *PredicateMock) SelectSubPredAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmSelectSubPred.afterSelectSubPredCounter) +} + +// SelectSubPredBeforeCounter returns a count of PredicateMock.SelectSubPred invocations +func (mmSelectSubPred *PredicateMock) SelectSubPredBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmSelectSubPred.beforeSelectSubPredCounter) +} + +// Calls returns a list of arguments used in each call to PredicateMock.SelectSubPred. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmSelectSubPred *mPredicateMockSelectSubPred) Calls() []*PredicateMockSelectSubPredParams { + mmSelectSubPred.mutex.RLock() + + argCopy := make([]*PredicateMockSelectSubPredParams, len(mmSelectSubPred.callArgs)) + copy(argCopy, mmSelectSubPred.callArgs) + + mmSelectSubPred.mutex.RUnlock() + + return argCopy +} + +// MinimockSelectSubPredDone returns true if the count of the SelectSubPred invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockSelectSubPredDone() bool { + for _, e := range m.SelectSubPredMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.SelectSubPredMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterSelectSubPredCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcSelectSubPred != nil && mm_atomic.LoadUint64(&m.afterSelectSubPredCounter) < 1 { + return false + } + return true +} + +// MinimockSelectSubPredInspect logs each unmet expectation +func (m *PredicateMock) MinimockSelectSubPredInspect() { + for _, e := range m.SelectSubPredMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to PredicateMock.SelectSubPred with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.SelectSubPredMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterSelectSubPredCounter) < 1 { + if m.SelectSubPredMock.defaultExpectation.params == nil { + m.t.Error("Expected call to PredicateMock.SelectSubPred") + } else { + m.t.Errorf("Expected call to PredicateMock.SelectSubPred with params: %#v", *m.SelectSubPredMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcSelectSubPred != nil && mm_atomic.LoadUint64(&m.afterSelectSubPredCounter) < 1 { + m.t.Error("Expected call to PredicateMock.SelectSubPred") + } +} + +type mPredicateMockString struct { + mock *PredicateMock + defaultExpectation *PredicateMockStringExpectation + expectations []*PredicateMockStringExpectation +} + +// PredicateMockStringExpectation specifies expectation struct of the Predicate.String +type PredicateMockStringExpectation struct { + mock *PredicateMock + + results *PredicateMockStringResults + Counter uint64 +} + +// PredicateMockStringResults contains results of the Predicate.String +type PredicateMockStringResults struct { + s1 string +} + +// Expect sets up expected params for Predicate.String +func (mmString *mPredicateMockString) Expect() *mPredicateMockString { + if mmString.mock.funcString != nil { + mmString.mock.t.Fatalf("PredicateMock.String mock is already set by Set") + } + + if mmString.defaultExpectation == nil { + mmString.defaultExpectation = &PredicateMockStringExpectation{} + } + + return mmString +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.String +func (mmString *mPredicateMockString) Inspect(f func()) *mPredicateMockString { + if mmString.mock.inspectFuncString != nil { + mmString.mock.t.Fatalf("Inspect function is already set for PredicateMock.String") + } + + mmString.mock.inspectFuncString = f + + return mmString +} + +// Return sets up results that will be returned by Predicate.String +func (mmString *mPredicateMockString) Return(s1 string) *PredicateMock { + if mmString.mock.funcString != nil { + mmString.mock.t.Fatalf("PredicateMock.String mock is already set by Set") + } + + if mmString.defaultExpectation == nil { + mmString.defaultExpectation = &PredicateMockStringExpectation{mock: mmString.mock} + } + mmString.defaultExpectation.results = &PredicateMockStringResults{s1} + return mmString.mock +} + +//Set uses given function f to mock the Predicate.String method +func (mmString *mPredicateMockString) Set(f func() (s1 string)) *PredicateMock { + if mmString.defaultExpectation != nil { + mmString.mock.t.Fatalf("Default expectation is already set for the Predicate.String method") + } + + if len(mmString.expectations) > 0 { + mmString.mock.t.Fatalf("Some expectations are already set for the Predicate.String method") + } + + mmString.mock.funcString = f + return mmString.mock +} + +// String implements scan.Predicate +func (mmString *PredicateMock) String() (s1 string) { + mm_atomic.AddUint64(&mmString.beforeStringCounter, 1) + defer mm_atomic.AddUint64(&mmString.afterStringCounter, 1) + + if mmString.inspectFuncString != nil { + mmString.inspectFuncString() + } + + if mmString.StringMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmString.StringMock.defaultExpectation.Counter, 1) + + mm_results := mmString.StringMock.defaultExpectation.results + if mm_results == nil { + mmString.t.Fatal("No results are set for the PredicateMock.String") + } + return (*mm_results).s1 + } + if mmString.funcString != nil { + return mmString.funcString() + } + mmString.t.Fatalf("Unexpected call to PredicateMock.String.") + return +} + +// StringAfterCounter returns a count of finished PredicateMock.String invocations +func (mmString *PredicateMock) StringAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmString.afterStringCounter) +} + +// StringBeforeCounter returns a count of PredicateMock.String invocations +func (mmString *PredicateMock) StringBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmString.beforeStringCounter) +} + +// MinimockStringDone returns true if the count of the String invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockStringDone() bool { + for _, e := range m.StringMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.StringMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcString != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + return false + } + return true +} + +// MinimockStringInspect logs each unmet expectation +func (m *PredicateMock) MinimockStringInspect() { + for _, e := range m.StringMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PredicateMock.String") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.StringMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + m.t.Error("Expected call to PredicateMock.String") + } + // if func was set then invocations count should be greater than zero + if m.funcString != nil && mm_atomic.LoadUint64(&m.afterStringCounter) < 1 { + m.t.Error("Expected call to PredicateMock.String") + } +} + +type mPredicateMockTerms struct { + mock *PredicateMock + defaultExpectation *PredicateMockTermsExpectation + expectations []*PredicateMockTermsExpectation +} + +// PredicateMockTermsExpectation specifies expectation struct of the Predicate.Terms +type PredicateMockTermsExpectation struct { + mock *PredicateMock + + results *PredicateMockTermsResults + Counter uint64 +} + +// PredicateMockTermsResults contains results of the Predicate.Terms +type PredicateMockTermsResults struct { + ta1 []mm_scan.Term +} + +// Expect sets up expected params for Predicate.Terms +func (mmTerms *mPredicateMockTerms) Expect() *mPredicateMockTerms { + if mmTerms.mock.funcTerms != nil { + mmTerms.mock.t.Fatalf("PredicateMock.Terms mock is already set by Set") + } + + if mmTerms.defaultExpectation == nil { + mmTerms.defaultExpectation = &PredicateMockTermsExpectation{} + } + + return mmTerms +} + +// Inspect accepts an inspector function that has same arguments as the Predicate.Terms +func (mmTerms *mPredicateMockTerms) Inspect(f func()) *mPredicateMockTerms { + if mmTerms.mock.inspectFuncTerms != nil { + mmTerms.mock.t.Fatalf("Inspect function is already set for PredicateMock.Terms") + } + + mmTerms.mock.inspectFuncTerms = f + + return mmTerms +} + +// Return sets up results that will be returned by Predicate.Terms +func (mmTerms *mPredicateMockTerms) Return(ta1 []mm_scan.Term) *PredicateMock { + if mmTerms.mock.funcTerms != nil { + mmTerms.mock.t.Fatalf("PredicateMock.Terms mock is already set by Set") + } + + if mmTerms.defaultExpectation == nil { + mmTerms.defaultExpectation = &PredicateMockTermsExpectation{mock: mmTerms.mock} + } + mmTerms.defaultExpectation.results = &PredicateMockTermsResults{ta1} + return mmTerms.mock +} + +//Set uses given function f to mock the Predicate.Terms method +func (mmTerms *mPredicateMockTerms) Set(f func() (ta1 []mm_scan.Term)) *PredicateMock { + if mmTerms.defaultExpectation != nil { + mmTerms.mock.t.Fatalf("Default expectation is already set for the Predicate.Terms method") + } + + if len(mmTerms.expectations) > 0 { + mmTerms.mock.t.Fatalf("Some expectations are already set for the Predicate.Terms method") + } + + mmTerms.mock.funcTerms = f + return mmTerms.mock +} + +// Terms implements scan.Predicate +func (mmTerms *PredicateMock) Terms() (ta1 []mm_scan.Term) { + mm_atomic.AddUint64(&mmTerms.beforeTermsCounter, 1) + defer mm_atomic.AddUint64(&mmTerms.afterTermsCounter, 1) + + if mmTerms.inspectFuncTerms != nil { + mmTerms.inspectFuncTerms() + } + + if mmTerms.TermsMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmTerms.TermsMock.defaultExpectation.Counter, 1) + + mm_results := mmTerms.TermsMock.defaultExpectation.results + if mm_results == nil { + mmTerms.t.Fatal("No results are set for the PredicateMock.Terms") + } + return (*mm_results).ta1 + } + if mmTerms.funcTerms != nil { + return mmTerms.funcTerms() + } + mmTerms.t.Fatalf("Unexpected call to PredicateMock.Terms.") + return +} + +// TermsAfterCounter returns a count of finished PredicateMock.Terms invocations +func (mmTerms *PredicateMock) TermsAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmTerms.afterTermsCounter) +} + +// TermsBeforeCounter returns a count of PredicateMock.Terms invocations +func (mmTerms *PredicateMock) TermsBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmTerms.beforeTermsCounter) +} + +// MinimockTermsDone returns true if the count of the Terms invocations corresponds +// the number of defined expectations +func (m *PredicateMock) MinimockTermsDone() bool { + for _, e := range m.TermsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.TermsMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterTermsCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcTerms != nil && mm_atomic.LoadUint64(&m.afterTermsCounter) < 1 { + return false + } + return true +} + +// MinimockTermsInspect logs each unmet expectation +func (m *PredicateMock) MinimockTermsInspect() { + for _, e := range m.TermsMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Error("Expected call to PredicateMock.Terms") + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.TermsMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterTermsCounter) < 1 { + m.t.Error("Expected call to PredicateMock.Terms") + } + // if func was set then invocations count should be greater than zero + if m.funcTerms != nil && mm_atomic.LoadUint64(&m.afterTermsCounter) < 1 { + m.t.Error("Expected call to PredicateMock.Terms") + } +} + +// MinimockFinish checks that all mocked methods have been called the expected number of times +func (m *PredicateMock) MinimockFinish() { + if !m.minimockDone() { + m.MinimockConjoinWithInspect() + + m.MinimockEquatesWithConstantInspect() + + m.MinimockEquatesWithFieldInspect() + + m.MinimockIsSatisfiedInspect() + + m.MinimockJoinSubPredInspect() + + m.MinimockReductionFactorInspect() + + m.MinimockSelectSubPredInspect() + + m.MinimockStringInspect() + + m.MinimockTermsInspect() + m.t.FailNow() + } +} + +// MinimockWait waits for all mocked methods to be called the expected number of times +func (m *PredicateMock) MinimockWait(timeout mm_time.Duration) { + timeoutCh := mm_time.After(timeout) + for { + if m.minimockDone() { + return + } + select { + case <-timeoutCh: + m.MinimockFinish() + return + case <-mm_time.After(10 * mm_time.Millisecond): + } + } +} + +func (m *PredicateMock) minimockDone() bool { + done := true + return done && + m.MinimockConjoinWithDone() && + m.MinimockEquatesWithConstantDone() && + m.MinimockEquatesWithFieldDone() && + m.MinimockIsSatisfiedDone() && + m.MinimockJoinSubPredDone() && + m.MinimockReductionFactorDone() && + m.MinimockSelectSubPredDone() && + m.MinimockStringDone() && + m.MinimockTermsDone() +} diff --git a/pkg/planner/product_plan.go b/pkg/planner/product_plan.go new file mode 100644 index 0000000..1d01b51 --- /dev/null +++ b/pkg/planner/product_plan.go @@ -0,0 +1,66 @@ +package planner + +import ( + "fmt" + + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +type ProductPlan struct { + p1 Plan + p2 Plan + schema records.Schema +} + +func NewProductPlan(p1 Plan, p2 Plan) (*ProductPlan, error) { + p := &ProductPlan{ + p1: p1, + p2: p2, + schema: records.NewSchema(), + } + + p.schema.AddAll(p1.Schema()) + p.schema.AddAll(p2.Schema()) + + return p, nil +} + +func (p *ProductPlan) Open() (scan.Scan, error) { + s1, err := p.p1.Open() + if err != nil { + return nil, err + } + + s2, err := p.p2.Open() + if err != nil { + return nil, err + } + + return scan.NewProductScan(s1, s2), nil +} + +func (p *ProductPlan) Schema() records.Schema { + return p.schema +} + +func (p *ProductPlan) BlocksAccessed() int64 { + return p.p1.BlocksAccessed() + + (p.p1.Records() * p.p2.BlocksAccessed()) +} + +func (p *ProductPlan) Records() int64 { + return p.p1.Records() * p.p2.Records() +} + +func (p *ProductPlan) DistinctValues(fieldName string) (int64, bool) { + if v, ok := p.p1.DistinctValues(fieldName); ok { + return v, true + } + + return p.p2.DistinctValues(fieldName) +} + +func (p *ProductPlan) String() string { + return fmt.Sprintf("join (%s) to (%s)", p.p1, p.p2) +} diff --git a/pkg/planner/product_plan_test.go b/pkg/planner/product_plan_test.go new file mode 100644 index 0000000..83273a6 --- /dev/null +++ b/pkg/planner/product_plan_test.go @@ -0,0 +1,148 @@ +package planner_test + +import ( + "fmt" + "testing" + + "github.com/gojuno/minimock/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "github.com/unhandled-exception/sophiadb/pkg/metadata" + "github.com/unhandled-exception/sophiadb/pkg/planner" + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" + "github.com/unhandled-exception/sophiadb/pkg/tx/transaction" +) + +var _ planner.Plan = &planner.ProductPlan{} + +type ProductPlanTestSuite struct { + Suite +} + +func TestProductPlanTestSuite(t *testing.T) { + suite.Run(t, new(ProductPlanTestSuite)) +} + +func (ts *ProductPlanTestSuite) newSUT(dataCount int) (*planner.ProductPlan, *transaction.Transaction, func()) { + t := ts.T() + + trxMan, fm := ts.newTRXManager(defaultLockTimeout, t.TempDir()) + + trx, err := trxMan.Transaction() + require.NoError(t, err) + + md, err := metadata.NewManager(true, trx) + require.NoError(t, err) + + tablename1 := testDataTable + "1" + tablename2 := testDataTable + "2" + + require.NoError(t, md.CreateTable(tablename1, ts.testLayout().Schema, trx)) + require.NoError(t, md.CreateTable(tablename2, ts.secondTestLayout().Schema, trx)) + + if dataCount > 0 { + ts1, werr := scan.NewTableScan(trx, tablename1, ts.testLayout()) + require.NoError(t, werr) + + for i := 0; i < dataCount; i++ { + require.NoErrorf(t, ts1.Insert(), "write insert i == %d", i) + + require.NoErrorf(t, ts1.SetInt64("id", int64(i+1)), "write int64 i == %d", i) + require.NoErrorf(t, ts1.SetInt8("age", int8(i%5)), "write int8 i == %d", i) + require.NoErrorf(t, ts1.SetString("name", fmt.Sprintf("user %d", i)), "write string i == %d", i) + } + + ts2, werr := scan.NewTableScan(trx, tablename2, ts.secondTestLayout()) + require.NoError(t, werr) + + for k := 0; k < dataCount; k++ { + require.NoError(t, ts2.Insert()) + require.NoError(t, ts2.SetInt64("position", int64(k+1))) + require.NoError(t, ts2.SetString("job", fmt.Sprintf("job %d", k))) + require.NoError(t, ts2.SetInt8("room", int8(k%128))) + require.NoError(t, ts2.SetVal("_invisible", scan.NewInt64Constant(int64(k/2)))) + } + } + + tp1, err := planner.NewTablePlan(trx, tablename1, md) + require.NoError(t, err) + + tp2, err := planner.NewTablePlan(trx, tablename2, md) + require.NoError(t, err) + + sut, err := planner.NewProductPlan(tp1, tp2) + require.NoError(t, err) + + return sut, trx, func() { + fm.Close() + } +} + +func (ts *ProductPlanTestSuite) TestPlan() { + t := ts.T() + + const blocks = 50 + cnt := int((defaultTestBlockSize / ts.testLayout().SlotSize) * blocks) + + sut, trx, clean := ts.newSUT(cnt) + defer clean() + + schema := records.NewSchema() + schema.AddAll(ts.testLayout().Schema) + schema.AddAll(ts.secondTestLayout().Schema) + + assert.Equal(t, "join (scan table data1) to (scan table data2)", sut.String()) + assert.Equal(t, schema.String(), sut.Schema().String()) + assert.EqualValues(t, cnt*cnt, sut.Records()) + assert.Greater(t, int64(cnt*blocks*blocks), sut.BlocksAccessed()) + + c, ok := sut.DistinctValues("age") + assert.True(t, ok) + assert.EqualValues(t, 5, c) + + c, ok = sut.DistinctValues("room") + assert.True(t, ok) + assert.EqualValues(t, 128, c) + + sc, err := sut.Open() + require.NoError(t, err) + + i := 0 + + assert.NoError(t, scan.ForEach(sc, func() (bool, error) { + i++ + + _, err := sc.GetInt64("id") + require.NoError(t, err) + + return false, nil + })) + + assert.EqualValues(t, cnt*cnt, i) + + require.NoError(t, trx.Commit()) +} + +func (ts *ProductPlanTestSuite) TestFailedToOpenPlan() { + t := ts.T() + + mc := minimock.NewController(t) + p1 := planner.NewPlanMock(mc).SchemaMock.Return(ts.testLayout().Schema). + OpenMock.Return(nil, scan.ErrScan) + p2 := planner.NewPlanMock(mc).SchemaMock.Return(ts.secondTestLayout().Schema). + OpenMock.Return(nil, nil) + + sut1, err := planner.NewProductPlan(p1, p2) + require.NoError(t, err) + + _, err = sut1.Open() + assert.ErrorIs(t, err, scan.ErrScan) + + sut2, err := planner.NewProductPlan(p2, p1) + require.NoError(t, err) + + _, err = sut2.Open() + assert.ErrorIs(t, err, scan.ErrScan) +} diff --git a/pkg/planner/project_plan.go b/pkg/planner/project_plan.go new file mode 100644 index 0000000..160857d --- /dev/null +++ b/pkg/planner/project_plan.go @@ -0,0 +1,67 @@ +package planner + +import ( + "fmt" + "strings" + + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +type ProjectPlan struct { + plan Plan + schema records.Schema +} + +func NewProjectPlan(plan Plan, fields ...string) (*ProjectPlan, error) { + p := &ProjectPlan{ + plan: plan, + schema: records.NewSchema(), + } + + parentSchema := plan.Schema() + + for _, field := range fields { + fi, ok := parentSchema.Field(field) + if !ok { + continue + } + + p.schema.AddField(field, fi.Type, fi.Length) + } + + return p, nil +} + +func (p *ProjectPlan) Open() (scan.Scan, error) { + s, err := p.plan.Open() + if err != nil { + return nil, err + } + + return scan.NewProjectScan(s, p.schema.Fields()...), nil +} + +func (p *ProjectPlan) Schema() records.Schema { + return p.schema +} + +func (p *ProjectPlan) BlocksAccessed() int64 { + return p.plan.BlocksAccessed() +} + +func (p *ProjectPlan) Records() int64 { + return p.plan.Records() +} + +func (p *ProjectPlan) DistinctValues(fieldName string) (int64, bool) { + return p.plan.DistinctValues(fieldName) +} + +func (p *ProjectPlan) String() string { + return fmt.Sprintf( + "choose %s from (%s)", + strings.Join(p.schema.Fields(), ", "), + p.plan, + ) +} diff --git a/pkg/planner/project_plan_test.go b/pkg/planner/project_plan_test.go new file mode 100644 index 0000000..8cc9950 --- /dev/null +++ b/pkg/planner/project_plan_test.go @@ -0,0 +1,137 @@ +package planner_test + +import ( + "fmt" + "testing" + + "github.com/gojuno/minimock/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "github.com/unhandled-exception/sophiadb/pkg/metadata" + "github.com/unhandled-exception/sophiadb/pkg/planner" + "github.com/unhandled-exception/sophiadb/pkg/scan" + "github.com/unhandled-exception/sophiadb/pkg/tx/transaction" +) + +var _ planner.Plan = &planner.ProjectPlan{} + +type ProjectPlanTestSuite struct { + Suite +} + +func TestProjectPlanTestSuite(t *testing.T) { + suite.Run(t, new(ProjectPlanTestSuite)) +} + +func (ts *ProjectPlanTestSuite) newSUT(dataCount int, fields ...string) (*planner.ProjectPlan, *transaction.Transaction, func()) { + t := ts.T() + + trxMan, fm := ts.newTRXManager(defaultLockTimeout, t.TempDir()) + + trx, err := trxMan.Transaction() + require.NoError(t, err) + + md, err := metadata.NewManager(true, trx) + require.NoError(t, err) + + tablename := testDataTable + + require.NoError(t, md.CreateTable(tablename, ts.testLayout().Schema, trx)) + + if dataCount > 0 { + ts, werr := scan.NewTableScan(trx, tablename, ts.testLayout()) + require.NoError(t, werr) + + for i := 0; i < dataCount; i++ { + require.NoErrorf(t, ts.Insert(), "write insert i == %d", i) + + require.NoErrorf(t, ts.SetInt64("id", int64(i+1)), "write int64 i == %d", i) + require.NoErrorf(t, ts.SetInt8("age", int8(i%5)), "write int8 i == %d", i) + require.NoErrorf(t, ts.SetString("name", fmt.Sprintf("user %d", i)), "write string i == %d", i) + } + } + + tp, err := planner.NewTablePlan(trx, tablename, md) + require.NoError(t, err) + + sut, err := planner.NewProjectPlan(tp, fields...) + require.NoError(t, err) + + return sut, trx, func() { + fm.Close() + } +} + +func (ts *ProjectPlanTestSuite) TestPlan() { + t := ts.T() + + const blocks = 100 + cnt := int((defaultTestBlockSize / ts.testLayout().SlotSize) * blocks) + + sut, trx, clean := ts.newSUT(cnt, "id", "age") + defer clean() + + assert.Equal(t, "choose id, age from (scan table data)", sut.String()) + assert.Equal(t, "id int64, age int8", sut.Schema().String()) + assert.EqualValues(t, cnt, sut.Records()) + assert.EqualValues(t, blocks, sut.BlocksAccessed()) + + c, ok := sut.DistinctValues("age") + assert.True(t, ok) + assert.EqualValues(t, 5, c) + + sc, err := sut.Open() + require.NoError(t, err) + + var i int64 = 0 + + assert.NoError(t, scan.ForEach(sc, func() (bool, error) { + i++ + + v, err := sc.GetInt64("id") + if err != nil { + return true, err + } + + assert.Equal(t, v, i) + + _, err = sc.GetString("name") + assert.ErrorIs(t, err, scan.ErrFieldNotFound) + + return false, nil + })) + + assert.EqualValues(t, cnt, i) + + require.NoError(t, trx.Commit()) +} + +func (ts *ProjectPlanTestSuite) TestFailedToOpenPlan() { + t := ts.T() + + mc := minimock.NewController(t) + plan := planner.NewPlanMock(mc). + OpenMock.Return(nil, scan.ErrScan). + SchemaMock.Return(ts.testLayout().Schema) + + sut, err := planner.NewProjectPlan(plan, "id", "age") + require.NoError(t, err) + + sc, err := sut.Open() + assert.Nil(t, sc) + assert.ErrorIs(t, err, scan.ErrScan) +} + +func (ts *ProjectPlanTestSuite) TestUnexistantPlansFields() { + t := ts.T() + + mc := minimock.NewController(t) + plan := planner.NewPlanMock(mc). + SchemaMock.Return(ts.testLayout().Schema) + + sut, err := planner.NewProjectPlan(plan, "id", "age", "_unexistant") + require.NoError(t, err) + + assert.Equal(t, "id int64, age int8", sut.Schema().String()) +} diff --git a/pkg/planner/select_plan.go b/pkg/planner/select_plan.go new file mode 100644 index 0000000..9de1307 --- /dev/null +++ b/pkg/planner/select_plan.go @@ -0,0 +1,62 @@ +package planner + +import ( + "fmt" + + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +type SelectPlan struct { + plan Plan + pred scan.Predicate +} + +func NewSelectPlan(plan Plan, pred scan.Predicate) (*SelectPlan, error) { + p := &SelectPlan{ + plan: plan, + pred: pred, + } + + return p, nil +} + +func (p *SelectPlan) Open() (scan.Scan, error) { + s, err := p.plan.Open() + if err != nil { + return nil, err + } + + return scan.NewSelectScan(s, p.pred), nil +} + +func (p *SelectPlan) Schema() records.Schema { + return p.plan.Schema() +} + +func (p *SelectPlan) BlocksAccessed() int64 { + return p.plan.BlocksAccessed() +} + +func (p *SelectPlan) Records() int64 { + return p.plan.Records() +} + +func (p *SelectPlan) DistinctValues(fieldName string) (int64, bool) { + if _, ok := p.pred.EquatesWithConstant(fieldName); ok { + return 1, true + } + + if otherFieldName, ok := p.pred.EquatesWithField(fieldName); ok { + dv1, _ := p.plan.DistinctValues(fieldName) + dv2, _ := p.plan.DistinctValues(otherFieldName) + + return max(dv1, dv2), true + } + + return p.plan.DistinctValues(fieldName) +} + +func (p *SelectPlan) String() string { + return fmt.Sprintf("select from (%s) where %s", p.plan, p.pred) +} diff --git a/pkg/planner/select_plan_test.go b/pkg/planner/select_plan_test.go new file mode 100644 index 0000000..5fcb413 --- /dev/null +++ b/pkg/planner/select_plan_test.go @@ -0,0 +1,168 @@ +package planner_test + +import ( + "fmt" + "testing" + + "github.com/gojuno/minimock/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "github.com/unhandled-exception/sophiadb/pkg/metadata" + "github.com/unhandled-exception/sophiadb/pkg/planner" + "github.com/unhandled-exception/sophiadb/pkg/scan" + "github.com/unhandled-exception/sophiadb/pkg/tx/transaction" +) + +var _ planner.Plan = &planner.SelectPlan{} + +type SelectPlanTestSuite struct { + Suite +} + +func TestSelectPlanTestSuite(t *testing.T) { + suite.Run(t, new(SelectPlanTestSuite)) +} + +func (ts *SelectPlanTestSuite) newSUT(pred scan.Predicate, dataCount int) (*planner.SelectPlan, *transaction.Transaction, func()) { + t := ts.T() + + trxMan, fm := ts.newTRXManager(defaultLockTimeout, t.TempDir()) + + trx, err := trxMan.Transaction() + require.NoError(t, err) + + md, err := metadata.NewManager(true, trx) + require.NoError(t, err) + + tablename := testDataTable + + require.NoError(t, md.CreateTable(tablename, ts.testLayout().Schema, trx)) + + if dataCount > 0 { + ts, werr := scan.NewTableScan(trx, tablename, ts.testLayout()) + require.NoError(t, werr) + + for i := 0; i < dataCount; i++ { + require.NoErrorf(t, ts.Insert(), "write insert i == %d", i) + + require.NoErrorf(t, ts.SetInt64("id", int64(i+1)), "write int64 i == %d", i) + require.NoErrorf(t, ts.SetInt8("age", int8(i%5)), "write int8 i == %d", i) + require.NoErrorf(t, ts.SetString("name", fmt.Sprintf("user %d", i)), "write string i == %d", i) + } + } + + tp, err := planner.NewTablePlan(trx, tablename, md) + require.NoError(t, err) + + sut, err := planner.NewSelectPlan(tp, pred) + require.NoError(t, err) + + return sut, trx, func() { + fm.Close() + } +} + +func (ts *SelectPlanTestSuite) TestPlan() { + t := ts.T() + + var testID int64 = 777 + + const blocks = 100 + cnt := int((defaultTestBlockSize / ts.testLayout().SlotSize) * blocks) + + pred := scan.NewAndPredicate( + scan.NewEqualTerm( + scan.NewFieldExpression("id"), + scan.NewScalarExpression(scan.NewInt64Constant(testID)), + ), + ) + + sut, trx, clean := ts.newSUT(pred, cnt) + defer clean() + + assert.Equal(t, "select from (scan table data) where id = 777", sut.String()) + assert.Equal(t, ts.testLayout().Schema.String(), sut.Schema().String()) + assert.EqualValues(t, cnt, sut.Records()) + assert.EqualValues(t, blocks, sut.BlocksAccessed()) + + c, ok := sut.DistinctValues("age") + assert.True(t, ok) + assert.EqualValues(t, 5, c) + + sc, err := sut.Open() + require.NoError(t, err) + + var i int64 = 0 + + assert.NoError(t, scan.ForEach(sc, func() (bool, error) { + i++ + + v, err := sc.GetInt64("id") + if err != nil { + return true, err + } + + assert.EqualValues(t, v, testID) + + return false, nil + })) + + assert.EqualValues(t, 1, i) + + require.NoError(t, trx.Commit()) +} + +func (ts *SelectPlanTestSuite) TestDistinctValues_EquatesConst() { + t := ts.T() + + mc := minimock.NewController(t) + + pred := planner.NewPredicateMock(mc). + EquatesWithConstantMock.Return(nil, true) + + plan := planner.NewPlanMock(mc) + + sut, err := planner.NewSelectPlan(plan, pred) + require.NoError(t, err) + + dv, ok := sut.DistinctValues("field") + assert.EqualValues(t, 1, dv) + assert.True(t, ok) +} + +func (ts *SelectPlanTestSuite) TestDistinctValues_EquatesTwoFields() { + t := ts.T() + + mc := minimock.NewController(t) + + pred := planner.NewPredicateMock(mc). + EquatesWithConstantMock.Return(nil, false). + EquatesWithFieldMock.Return("f2", true) + + plan := planner.NewPlanMock(mc). + DistinctValuesMock.When("f1").Then(345, true). + DistinctValuesMock.When("f2").Then(999, true) + + sut, err := planner.NewSelectPlan(plan, pred) + require.NoError(t, err) + + dv, ok := sut.DistinctValues("f1") + assert.EqualValues(t, 999, dv) + assert.True(t, ok) +} + +func (ts *SelectPlanTestSuite) TestFailedToOpenPlan() { + t := ts.T() + + mc := minimock.NewController(t) + pred := planner.NewPredicateMock(mc) + plan := planner.NewPlanMock(mc).OpenMock.Return(nil, scan.ErrScan) + + sut, err := planner.NewSelectPlan(plan, pred) + require.NoError(t, err) + + sc, err := sut.Open() + assert.Nil(t, sc) + assert.ErrorIs(t, err, scan.ErrScan) +} diff --git a/pkg/planner/table_plan.go b/pkg/planner/table_plan.go new file mode 100644 index 0000000..4e36b81 --- /dev/null +++ b/pkg/planner/table_plan.go @@ -0,0 +1,67 @@ +package planner + +import ( + "fmt" + + "github.com/pkg/errors" + "github.com/unhandled-exception/sophiadb/pkg/metadata" + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +type TablePlan struct { + trx scan.TRXInt + tablename string + layout records.Layout + stats metadata.StatInfo +} + +type tablePlanMetadataManager interface { + Layout(tableName string, trx scan.TRXInt) (records.Layout, error) + GetStatInfo(tableName string, layout records.Layout, trx scan.TRXInt) (metadata.StatInfo, error) +} + +func NewTablePlan(trx scan.TRXInt, tableName string, md tablePlanMetadataManager) (*TablePlan, error) { + p := &TablePlan{ + trx: trx, + tablename: tableName, + } + + var err error + + p.layout, err = md.Layout(tableName, trx) + if err != nil { + return nil, errors.WithMessage(ErrFailedToCreatePlan, err.Error()) + } + + p.stats, err = md.GetStatInfo(tableName, p.layout, trx) + if err != nil { + return nil, errors.WithMessage(ErrFailedToCreatePlan, err.Error()) + } + + return p, nil +} + +func (p *TablePlan) Open() (scan.Scan, error) { + return scan.NewTableScan(p.trx, p.tablename, p.layout) +} + +func (p *TablePlan) Schema() records.Schema { + return p.layout.Schema +} + +func (p *TablePlan) BlocksAccessed() int64 { + return p.stats.Blocks +} + +func (p *TablePlan) Records() int64 { + return p.stats.Records +} + +func (p *TablePlan) DistinctValues(fieldName string) (int64, bool) { + return p.stats.DistinctValues(fieldName) +} + +func (p *TablePlan) String() string { + return fmt.Sprintf("scan table %s", p.tablename) +} diff --git a/pkg/planner/table_plan_metadata_manager_mock_test.go b/pkg/planner/table_plan_metadata_manager_mock_test.go new file mode 100644 index 0000000..799a357 --- /dev/null +++ b/pkg/planner/table_plan_metadata_manager_mock_test.go @@ -0,0 +1,517 @@ +package planner + +// Code generated by http://github.com/gojuno/minimock (dev). DO NOT EDIT. + +//go:generate minimock -i github.com/unhandled-exception/sophiadb/pkg/planner.tablePlanMetadataManager -o ./table_plan_metadata_manager_mock_test.go -n TablePlanMetadataManagerMock + +import ( + "sync" + mm_atomic "sync/atomic" + mm_time "time" + + "github.com/gojuno/minimock/v3" + "github.com/unhandled-exception/sophiadb/pkg/metadata" + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" +) + +// TablePlanMetadataManagerMock implements tablePlanMetadataManager +type TablePlanMetadataManagerMock struct { + t minimock.Tester + + funcGetStatInfo func(tableName string, layout records.Layout, trx scan.TRXInt) (s1 metadata.StatInfo, err error) + inspectFuncGetStatInfo func(tableName string, layout records.Layout, trx scan.TRXInt) + afterGetStatInfoCounter uint64 + beforeGetStatInfoCounter uint64 + GetStatInfoMock mTablePlanMetadataManagerMockGetStatInfo + + funcLayout func(tableName string, trx scan.TRXInt) (l1 records.Layout, err error) + inspectFuncLayout func(tableName string, trx scan.TRXInt) + afterLayoutCounter uint64 + beforeLayoutCounter uint64 + LayoutMock mTablePlanMetadataManagerMockLayout +} + +// NewTablePlanMetadataManagerMock returns a mock for tablePlanMetadataManager +func NewTablePlanMetadataManagerMock(t minimock.Tester) *TablePlanMetadataManagerMock { + m := &TablePlanMetadataManagerMock{t: t} + if controller, ok := t.(minimock.MockController); ok { + controller.RegisterMocker(m) + } + + m.GetStatInfoMock = mTablePlanMetadataManagerMockGetStatInfo{mock: m} + m.GetStatInfoMock.callArgs = []*TablePlanMetadataManagerMockGetStatInfoParams{} + + m.LayoutMock = mTablePlanMetadataManagerMockLayout{mock: m} + m.LayoutMock.callArgs = []*TablePlanMetadataManagerMockLayoutParams{} + + return m +} + +type mTablePlanMetadataManagerMockGetStatInfo struct { + mock *TablePlanMetadataManagerMock + defaultExpectation *TablePlanMetadataManagerMockGetStatInfoExpectation + expectations []*TablePlanMetadataManagerMockGetStatInfoExpectation + + callArgs []*TablePlanMetadataManagerMockGetStatInfoParams + mutex sync.RWMutex +} + +// TablePlanMetadataManagerMockGetStatInfoExpectation specifies expectation struct of the tablePlanMetadataManager.GetStatInfo +type TablePlanMetadataManagerMockGetStatInfoExpectation struct { + mock *TablePlanMetadataManagerMock + params *TablePlanMetadataManagerMockGetStatInfoParams + results *TablePlanMetadataManagerMockGetStatInfoResults + Counter uint64 +} + +// TablePlanMetadataManagerMockGetStatInfoParams contains parameters of the tablePlanMetadataManager.GetStatInfo +type TablePlanMetadataManagerMockGetStatInfoParams struct { + tableName string + layout records.Layout + trx scan.TRXInt +} + +// TablePlanMetadataManagerMockGetStatInfoResults contains results of the tablePlanMetadataManager.GetStatInfo +type TablePlanMetadataManagerMockGetStatInfoResults struct { + s1 metadata.StatInfo + err error +} + +// Expect sets up expected params for tablePlanMetadataManager.GetStatInfo +func (mmGetStatInfo *mTablePlanMetadataManagerMockGetStatInfo) Expect(tableName string, layout records.Layout, trx scan.TRXInt) *mTablePlanMetadataManagerMockGetStatInfo { + if mmGetStatInfo.mock.funcGetStatInfo != nil { + mmGetStatInfo.mock.t.Fatalf("TablePlanMetadataManagerMock.GetStatInfo mock is already set by Set") + } + + if mmGetStatInfo.defaultExpectation == nil { + mmGetStatInfo.defaultExpectation = &TablePlanMetadataManagerMockGetStatInfoExpectation{} + } + + mmGetStatInfo.defaultExpectation.params = &TablePlanMetadataManagerMockGetStatInfoParams{tableName, layout, trx} + for _, e := range mmGetStatInfo.expectations { + if minimock.Equal(e.params, mmGetStatInfo.defaultExpectation.params) { + mmGetStatInfo.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetStatInfo.defaultExpectation.params) + } + } + + return mmGetStatInfo +} + +// Inspect accepts an inspector function that has same arguments as the tablePlanMetadataManager.GetStatInfo +func (mmGetStatInfo *mTablePlanMetadataManagerMockGetStatInfo) Inspect(f func(tableName string, layout records.Layout, trx scan.TRXInt)) *mTablePlanMetadataManagerMockGetStatInfo { + if mmGetStatInfo.mock.inspectFuncGetStatInfo != nil { + mmGetStatInfo.mock.t.Fatalf("Inspect function is already set for TablePlanMetadataManagerMock.GetStatInfo") + } + + mmGetStatInfo.mock.inspectFuncGetStatInfo = f + + return mmGetStatInfo +} + +// Return sets up results that will be returned by tablePlanMetadataManager.GetStatInfo +func (mmGetStatInfo *mTablePlanMetadataManagerMockGetStatInfo) Return(s1 metadata.StatInfo, err error) *TablePlanMetadataManagerMock { + if mmGetStatInfo.mock.funcGetStatInfo != nil { + mmGetStatInfo.mock.t.Fatalf("TablePlanMetadataManagerMock.GetStatInfo mock is already set by Set") + } + + if mmGetStatInfo.defaultExpectation == nil { + mmGetStatInfo.defaultExpectation = &TablePlanMetadataManagerMockGetStatInfoExpectation{mock: mmGetStatInfo.mock} + } + mmGetStatInfo.defaultExpectation.results = &TablePlanMetadataManagerMockGetStatInfoResults{s1, err} + return mmGetStatInfo.mock +} + +//Set uses given function f to mock the tablePlanMetadataManager.GetStatInfo method +func (mmGetStatInfo *mTablePlanMetadataManagerMockGetStatInfo) Set(f func(tableName string, layout records.Layout, trx scan.TRXInt) (s1 metadata.StatInfo, err error)) *TablePlanMetadataManagerMock { + if mmGetStatInfo.defaultExpectation != nil { + mmGetStatInfo.mock.t.Fatalf("Default expectation is already set for the tablePlanMetadataManager.GetStatInfo method") + } + + if len(mmGetStatInfo.expectations) > 0 { + mmGetStatInfo.mock.t.Fatalf("Some expectations are already set for the tablePlanMetadataManager.GetStatInfo method") + } + + mmGetStatInfo.mock.funcGetStatInfo = f + return mmGetStatInfo.mock +} + +// When sets expectation for the tablePlanMetadataManager.GetStatInfo which will trigger the result defined by the following +// Then helper +func (mmGetStatInfo *mTablePlanMetadataManagerMockGetStatInfo) When(tableName string, layout records.Layout, trx scan.TRXInt) *TablePlanMetadataManagerMockGetStatInfoExpectation { + if mmGetStatInfo.mock.funcGetStatInfo != nil { + mmGetStatInfo.mock.t.Fatalf("TablePlanMetadataManagerMock.GetStatInfo mock is already set by Set") + } + + expectation := &TablePlanMetadataManagerMockGetStatInfoExpectation{ + mock: mmGetStatInfo.mock, + params: &TablePlanMetadataManagerMockGetStatInfoParams{tableName, layout, trx}, + } + mmGetStatInfo.expectations = append(mmGetStatInfo.expectations, expectation) + return expectation +} + +// Then sets up tablePlanMetadataManager.GetStatInfo return parameters for the expectation previously defined by the When method +func (e *TablePlanMetadataManagerMockGetStatInfoExpectation) Then(s1 metadata.StatInfo, err error) *TablePlanMetadataManagerMock { + e.results = &TablePlanMetadataManagerMockGetStatInfoResults{s1, err} + return e.mock +} + +// GetStatInfo implements tablePlanMetadataManager +func (mmGetStatInfo *TablePlanMetadataManagerMock) GetStatInfo(tableName string, layout records.Layout, trx scan.TRXInt) (s1 metadata.StatInfo, err error) { + mm_atomic.AddUint64(&mmGetStatInfo.beforeGetStatInfoCounter, 1) + defer mm_atomic.AddUint64(&mmGetStatInfo.afterGetStatInfoCounter, 1) + + if mmGetStatInfo.inspectFuncGetStatInfo != nil { + mmGetStatInfo.inspectFuncGetStatInfo(tableName, layout, trx) + } + + mm_params := &TablePlanMetadataManagerMockGetStatInfoParams{tableName, layout, trx} + + // Record call args + mmGetStatInfo.GetStatInfoMock.mutex.Lock() + mmGetStatInfo.GetStatInfoMock.callArgs = append(mmGetStatInfo.GetStatInfoMock.callArgs, mm_params) + mmGetStatInfo.GetStatInfoMock.mutex.Unlock() + + for _, e := range mmGetStatInfo.GetStatInfoMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.s1, e.results.err + } + } + + if mmGetStatInfo.GetStatInfoMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmGetStatInfo.GetStatInfoMock.defaultExpectation.Counter, 1) + mm_want := mmGetStatInfo.GetStatInfoMock.defaultExpectation.params + mm_got := TablePlanMetadataManagerMockGetStatInfoParams{tableName, layout, trx} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmGetStatInfo.t.Errorf("TablePlanMetadataManagerMock.GetStatInfo got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmGetStatInfo.GetStatInfoMock.defaultExpectation.results + if mm_results == nil { + mmGetStatInfo.t.Fatal("No results are set for the TablePlanMetadataManagerMock.GetStatInfo") + } + return (*mm_results).s1, (*mm_results).err + } + if mmGetStatInfo.funcGetStatInfo != nil { + return mmGetStatInfo.funcGetStatInfo(tableName, layout, trx) + } + mmGetStatInfo.t.Fatalf("Unexpected call to TablePlanMetadataManagerMock.GetStatInfo. %v %v %v", tableName, layout, trx) + return +} + +// GetStatInfoAfterCounter returns a count of finished TablePlanMetadataManagerMock.GetStatInfo invocations +func (mmGetStatInfo *TablePlanMetadataManagerMock) GetStatInfoAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmGetStatInfo.afterGetStatInfoCounter) +} + +// GetStatInfoBeforeCounter returns a count of TablePlanMetadataManagerMock.GetStatInfo invocations +func (mmGetStatInfo *TablePlanMetadataManagerMock) GetStatInfoBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmGetStatInfo.beforeGetStatInfoCounter) +} + +// Calls returns a list of arguments used in each call to TablePlanMetadataManagerMock.GetStatInfo. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmGetStatInfo *mTablePlanMetadataManagerMockGetStatInfo) Calls() []*TablePlanMetadataManagerMockGetStatInfoParams { + mmGetStatInfo.mutex.RLock() + + argCopy := make([]*TablePlanMetadataManagerMockGetStatInfoParams, len(mmGetStatInfo.callArgs)) + copy(argCopy, mmGetStatInfo.callArgs) + + mmGetStatInfo.mutex.RUnlock() + + return argCopy +} + +// MinimockGetStatInfoDone returns true if the count of the GetStatInfo invocations corresponds +// the number of defined expectations +func (m *TablePlanMetadataManagerMock) MinimockGetStatInfoDone() bool { + for _, e := range m.GetStatInfoMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.GetStatInfoMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterGetStatInfoCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcGetStatInfo != nil && mm_atomic.LoadUint64(&m.afterGetStatInfoCounter) < 1 { + return false + } + return true +} + +// MinimockGetStatInfoInspect logs each unmet expectation +func (m *TablePlanMetadataManagerMock) MinimockGetStatInfoInspect() { + for _, e := range m.GetStatInfoMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to TablePlanMetadataManagerMock.GetStatInfo with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.GetStatInfoMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterGetStatInfoCounter) < 1 { + if m.GetStatInfoMock.defaultExpectation.params == nil { + m.t.Error("Expected call to TablePlanMetadataManagerMock.GetStatInfo") + } else { + m.t.Errorf("Expected call to TablePlanMetadataManagerMock.GetStatInfo with params: %#v", *m.GetStatInfoMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcGetStatInfo != nil && mm_atomic.LoadUint64(&m.afterGetStatInfoCounter) < 1 { + m.t.Error("Expected call to TablePlanMetadataManagerMock.GetStatInfo") + } +} + +type mTablePlanMetadataManagerMockLayout struct { + mock *TablePlanMetadataManagerMock + defaultExpectation *TablePlanMetadataManagerMockLayoutExpectation + expectations []*TablePlanMetadataManagerMockLayoutExpectation + + callArgs []*TablePlanMetadataManagerMockLayoutParams + mutex sync.RWMutex +} + +// TablePlanMetadataManagerMockLayoutExpectation specifies expectation struct of the tablePlanMetadataManager.Layout +type TablePlanMetadataManagerMockLayoutExpectation struct { + mock *TablePlanMetadataManagerMock + params *TablePlanMetadataManagerMockLayoutParams + results *TablePlanMetadataManagerMockLayoutResults + Counter uint64 +} + +// TablePlanMetadataManagerMockLayoutParams contains parameters of the tablePlanMetadataManager.Layout +type TablePlanMetadataManagerMockLayoutParams struct { + tableName string + trx scan.TRXInt +} + +// TablePlanMetadataManagerMockLayoutResults contains results of the tablePlanMetadataManager.Layout +type TablePlanMetadataManagerMockLayoutResults struct { + l1 records.Layout + err error +} + +// Expect sets up expected params for tablePlanMetadataManager.Layout +func (mmLayout *mTablePlanMetadataManagerMockLayout) Expect(tableName string, trx scan.TRXInt) *mTablePlanMetadataManagerMockLayout { + if mmLayout.mock.funcLayout != nil { + mmLayout.mock.t.Fatalf("TablePlanMetadataManagerMock.Layout mock is already set by Set") + } + + if mmLayout.defaultExpectation == nil { + mmLayout.defaultExpectation = &TablePlanMetadataManagerMockLayoutExpectation{} + } + + mmLayout.defaultExpectation.params = &TablePlanMetadataManagerMockLayoutParams{tableName, trx} + for _, e := range mmLayout.expectations { + if minimock.Equal(e.params, mmLayout.defaultExpectation.params) { + mmLayout.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmLayout.defaultExpectation.params) + } + } + + return mmLayout +} + +// Inspect accepts an inspector function that has same arguments as the tablePlanMetadataManager.Layout +func (mmLayout *mTablePlanMetadataManagerMockLayout) Inspect(f func(tableName string, trx scan.TRXInt)) *mTablePlanMetadataManagerMockLayout { + if mmLayout.mock.inspectFuncLayout != nil { + mmLayout.mock.t.Fatalf("Inspect function is already set for TablePlanMetadataManagerMock.Layout") + } + + mmLayout.mock.inspectFuncLayout = f + + return mmLayout +} + +// Return sets up results that will be returned by tablePlanMetadataManager.Layout +func (mmLayout *mTablePlanMetadataManagerMockLayout) Return(l1 records.Layout, err error) *TablePlanMetadataManagerMock { + if mmLayout.mock.funcLayout != nil { + mmLayout.mock.t.Fatalf("TablePlanMetadataManagerMock.Layout mock is already set by Set") + } + + if mmLayout.defaultExpectation == nil { + mmLayout.defaultExpectation = &TablePlanMetadataManagerMockLayoutExpectation{mock: mmLayout.mock} + } + mmLayout.defaultExpectation.results = &TablePlanMetadataManagerMockLayoutResults{l1, err} + return mmLayout.mock +} + +//Set uses given function f to mock the tablePlanMetadataManager.Layout method +func (mmLayout *mTablePlanMetadataManagerMockLayout) Set(f func(tableName string, trx scan.TRXInt) (l1 records.Layout, err error)) *TablePlanMetadataManagerMock { + if mmLayout.defaultExpectation != nil { + mmLayout.mock.t.Fatalf("Default expectation is already set for the tablePlanMetadataManager.Layout method") + } + + if len(mmLayout.expectations) > 0 { + mmLayout.mock.t.Fatalf("Some expectations are already set for the tablePlanMetadataManager.Layout method") + } + + mmLayout.mock.funcLayout = f + return mmLayout.mock +} + +// When sets expectation for the tablePlanMetadataManager.Layout which will trigger the result defined by the following +// Then helper +func (mmLayout *mTablePlanMetadataManagerMockLayout) When(tableName string, trx scan.TRXInt) *TablePlanMetadataManagerMockLayoutExpectation { + if mmLayout.mock.funcLayout != nil { + mmLayout.mock.t.Fatalf("TablePlanMetadataManagerMock.Layout mock is already set by Set") + } + + expectation := &TablePlanMetadataManagerMockLayoutExpectation{ + mock: mmLayout.mock, + params: &TablePlanMetadataManagerMockLayoutParams{tableName, trx}, + } + mmLayout.expectations = append(mmLayout.expectations, expectation) + return expectation +} + +// Then sets up tablePlanMetadataManager.Layout return parameters for the expectation previously defined by the When method +func (e *TablePlanMetadataManagerMockLayoutExpectation) Then(l1 records.Layout, err error) *TablePlanMetadataManagerMock { + e.results = &TablePlanMetadataManagerMockLayoutResults{l1, err} + return e.mock +} + +// Layout implements tablePlanMetadataManager +func (mmLayout *TablePlanMetadataManagerMock) Layout(tableName string, trx scan.TRXInt) (l1 records.Layout, err error) { + mm_atomic.AddUint64(&mmLayout.beforeLayoutCounter, 1) + defer mm_atomic.AddUint64(&mmLayout.afterLayoutCounter, 1) + + if mmLayout.inspectFuncLayout != nil { + mmLayout.inspectFuncLayout(tableName, trx) + } + + mm_params := &TablePlanMetadataManagerMockLayoutParams{tableName, trx} + + // Record call args + mmLayout.LayoutMock.mutex.Lock() + mmLayout.LayoutMock.callArgs = append(mmLayout.LayoutMock.callArgs, mm_params) + mmLayout.LayoutMock.mutex.Unlock() + + for _, e := range mmLayout.LayoutMock.expectations { + if minimock.Equal(e.params, mm_params) { + mm_atomic.AddUint64(&e.Counter, 1) + return e.results.l1, e.results.err + } + } + + if mmLayout.LayoutMock.defaultExpectation != nil { + mm_atomic.AddUint64(&mmLayout.LayoutMock.defaultExpectation.Counter, 1) + mm_want := mmLayout.LayoutMock.defaultExpectation.params + mm_got := TablePlanMetadataManagerMockLayoutParams{tableName, trx} + if mm_want != nil && !minimock.Equal(*mm_want, mm_got) { + mmLayout.t.Errorf("TablePlanMetadataManagerMock.Layout got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got)) + } + + mm_results := mmLayout.LayoutMock.defaultExpectation.results + if mm_results == nil { + mmLayout.t.Fatal("No results are set for the TablePlanMetadataManagerMock.Layout") + } + return (*mm_results).l1, (*mm_results).err + } + if mmLayout.funcLayout != nil { + return mmLayout.funcLayout(tableName, trx) + } + mmLayout.t.Fatalf("Unexpected call to TablePlanMetadataManagerMock.Layout. %v %v", tableName, trx) + return +} + +// LayoutAfterCounter returns a count of finished TablePlanMetadataManagerMock.Layout invocations +func (mmLayout *TablePlanMetadataManagerMock) LayoutAfterCounter() uint64 { + return mm_atomic.LoadUint64(&mmLayout.afterLayoutCounter) +} + +// LayoutBeforeCounter returns a count of TablePlanMetadataManagerMock.Layout invocations +func (mmLayout *TablePlanMetadataManagerMock) LayoutBeforeCounter() uint64 { + return mm_atomic.LoadUint64(&mmLayout.beforeLayoutCounter) +} + +// Calls returns a list of arguments used in each call to TablePlanMetadataManagerMock.Layout. +// The list is in the same order as the calls were made (i.e. recent calls have a higher index) +func (mmLayout *mTablePlanMetadataManagerMockLayout) Calls() []*TablePlanMetadataManagerMockLayoutParams { + mmLayout.mutex.RLock() + + argCopy := make([]*TablePlanMetadataManagerMockLayoutParams, len(mmLayout.callArgs)) + copy(argCopy, mmLayout.callArgs) + + mmLayout.mutex.RUnlock() + + return argCopy +} + +// MinimockLayoutDone returns true if the count of the Layout invocations corresponds +// the number of defined expectations +func (m *TablePlanMetadataManagerMock) MinimockLayoutDone() bool { + for _, e := range m.LayoutMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + return false + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.LayoutMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterLayoutCounter) < 1 { + return false + } + // if func was set then invocations count should be greater than zero + if m.funcLayout != nil && mm_atomic.LoadUint64(&m.afterLayoutCounter) < 1 { + return false + } + return true +} + +// MinimockLayoutInspect logs each unmet expectation +func (m *TablePlanMetadataManagerMock) MinimockLayoutInspect() { + for _, e := range m.LayoutMock.expectations { + if mm_atomic.LoadUint64(&e.Counter) < 1 { + m.t.Errorf("Expected call to TablePlanMetadataManagerMock.Layout with params: %#v", *e.params) + } + } + + // if default expectation was set then invocations count should be greater than zero + if m.LayoutMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterLayoutCounter) < 1 { + if m.LayoutMock.defaultExpectation.params == nil { + m.t.Error("Expected call to TablePlanMetadataManagerMock.Layout") + } else { + m.t.Errorf("Expected call to TablePlanMetadataManagerMock.Layout with params: %#v", *m.LayoutMock.defaultExpectation.params) + } + } + // if func was set then invocations count should be greater than zero + if m.funcLayout != nil && mm_atomic.LoadUint64(&m.afterLayoutCounter) < 1 { + m.t.Error("Expected call to TablePlanMetadataManagerMock.Layout") + } +} + +// MinimockFinish checks that all mocked methods have been called the expected number of times +func (m *TablePlanMetadataManagerMock) MinimockFinish() { + if !m.minimockDone() { + m.MinimockGetStatInfoInspect() + + m.MinimockLayoutInspect() + m.t.FailNow() + } +} + +// MinimockWait waits for all mocked methods to be called the expected number of times +func (m *TablePlanMetadataManagerMock) MinimockWait(timeout mm_time.Duration) { + timeoutCh := mm_time.After(timeout) + for { + if m.minimockDone() { + return + } + select { + case <-timeoutCh: + m.MinimockFinish() + return + case <-mm_time.After(10 * mm_time.Millisecond): + } + } +} + +func (m *TablePlanMetadataManagerMock) minimockDone() bool { + done := true + return done && + m.MinimockGetStatInfoDone() && + m.MinimockLayoutDone() +} diff --git a/pkg/planner/table_plan_test.go b/pkg/planner/table_plan_test.go new file mode 100644 index 0000000..a4fc28b --- /dev/null +++ b/pkg/planner/table_plan_test.go @@ -0,0 +1,139 @@ +package planner_test + +import ( + "fmt" + "testing" + + "github.com/gojuno/minimock/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "github.com/unhandled-exception/sophiadb/pkg/metadata" + "github.com/unhandled-exception/sophiadb/pkg/planner" + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/scan" + "github.com/unhandled-exception/sophiadb/pkg/tx/transaction" +) + +var _ planner.Plan = &planner.TablePlan{} + +type TablePlanTestSuite struct { + Suite +} + +func TestTablePlanSuite(t *testing.T) { + suite.Run(t, new(TablePlanTestSuite)) +} + +func (ts *TablePlanTestSuite) newSUT(dataCount int) (*planner.TablePlan, *transaction.Transaction, func()) { + t := ts.T() + + trxMan, fm := ts.newTRXManager(defaultLockTimeout, t.TempDir()) + + trx, err := trxMan.Transaction() + require.NoError(t, err) + + md, err := metadata.NewManager(true, trx) + require.NoError(t, err) + + tablename := testDataTable + + require.NoError(t, md.CreateTable(tablename, ts.testLayout().Schema, trx)) + + if dataCount > 0 { + ts, werr := scan.NewTableScan(trx, tablename, ts.testLayout()) + require.NoError(t, werr) + + for i := 0; i < dataCount; i++ { + require.NoErrorf(t, ts.Insert(), "write insert i == %d", i) + + require.NoErrorf(t, ts.SetInt64("id", int64(i+1)), "write int64 i == %d", i) + require.NoErrorf(t, ts.SetInt8("age", int8(i%5)), "write int8 i == %d", i) + require.NoErrorf(t, ts.SetString("name", fmt.Sprintf("user %d", i)), "write string i == %d", i) + } + } + + sut, err := planner.NewTablePlan(trx, tablename, md) + require.NoError(t, err) + + return sut, trx, func() { + fm.Close() + } +} + +func (ts *TablePlanTestSuite) TestPlan() { + t := ts.T() + + const blocks = 1000 + cnt := int((defaultTestBlockSize / ts.testLayout().SlotSize) * blocks) + + sut, trx, clean := ts.newSUT(cnt) + defer clean() + + assert.Equal(t, "scan table data", sut.String()) + assert.Equal(t, ts.testLayout().Schema.String(), sut.Schema().String()) + assert.EqualValues(t, cnt, sut.Records()) + assert.EqualValues(t, blocks, sut.BlocksAccessed()) + + c, ok := sut.DistinctValues("age") + assert.True(t, ok) + assert.EqualValues(t, 5, c) + + sc, err := sut.Open() + require.NoError(t, err) + + var i int64 = 0 + + assert.NoError(t, scan.ForEach(sc, func() (bool, error) { + i++ + + v, err := sc.GetInt64("id") + if err != nil { + return true, err + } + + assert.Equal(t, v, i) + + return false, nil + })) + + require.NoError(t, trx.Commit()) +} + +func (ts *TablePlanTestSuite) TestUnexistantTable() { + t := ts.T() + + trxMan, fm := ts.newTRXManager(defaultLockTimeout, t.TempDir()) + defer fm.Close() + + trx, err := trxMan.Transaction() + require.NoError(t, err) + + mc := minimock.NewController(t) + md := planner.NewTablePlanMetadataManagerMock(mc).LayoutMock.Return(records.Layout{}, metadata.ErrTableNotFound) + + _, err = planner.NewTablePlan(trx, testDataTable, md) + assert.ErrorIs(t, err, planner.ErrFailedToCreatePlan) + + require.NoError(t, trx.Commit()) +} + +func (ts *TablePlanTestSuite) TestMissedStats() { + t := ts.T() + + trxMan, fm := ts.newTRXManager(defaultLockTimeout, t.TempDir()) + defer fm.Close() + + trx, err := trxMan.Transaction() + require.NoError(t, err) + + mc := minimock.NewController(t) + md := planner.NewTablePlanMetadataManagerMock(mc). + LayoutMock.Return(ts.testLayout(), nil). + GetStatInfoMock.Return(metadata.StatInfo{}, metadata.ErrStatsMetadata) + + _, err = planner.NewTablePlan(trx, testDataTable, md) + assert.ErrorIs(t, err, planner.ErrFailedToCreatePlan) + + require.NoError(t, trx.Commit()) +} diff --git a/pkg/planner/testitil_test.go b/pkg/planner/testitil_test.go new file mode 100644 index 0000000..d0dffbc --- /dev/null +++ b/pkg/planner/testitil_test.go @@ -0,0 +1,65 @@ +package planner_test + +import ( + "path/filepath" + "time" + + "github.com/unhandled-exception/sophiadb/pkg/buffers" + "github.com/unhandled-exception/sophiadb/pkg/records" + "github.com/unhandled-exception/sophiadb/pkg/storage" + "github.com/unhandled-exception/sophiadb/pkg/testutil" + "github.com/unhandled-exception/sophiadb/pkg/tx/transaction" + "github.com/unhandled-exception/sophiadb/pkg/wal" +) + +const ( + testDataTable = "data" + testWALFile = "scan_wal.dat" + defaultTestBlockSize = 4000 + defaultTestBuffersPoolLen = 100 + defaultLockTimeout = 100 * time.Millisecond +) + +type Suite struct { + testutil.Suite +} + +func (ts *Suite) newTRXManager(lockTimeout time.Duration, path string) (*transaction.TRXManager, *storage.Manager) { + if path == "" { + path = ts.CreateTestTemporaryDir() + } + + fm, err := storage.NewFileManager(path, defaultTestBlockSize) + ts.Require().NoError(err) + ts.Require().NotNil(fm) + + lm, err := wal.NewManager(fm, testWALFile) + ts.Require().NoError(err) + ts.Require().FileExists(filepath.Join(path, testWALFile)) + + bm := buffers.NewManager(fm, lm, defaultTestBuffersPoolLen) + + m := transaction.NewTRXManager(fm, bm, lm, transaction.WithLockTimeout(lockTimeout)) + + return m, fm +} + +func (ts *Suite) testLayout() records.Layout { + schema := records.NewSchema() + schema.AddInt64Field("id") + schema.AddStringField("name", 25) + schema.AddInt8Field("age") + schema.AddInt64Field("_hidden") + + return records.NewLayout(schema) +} + +func (ts *Suite) secondTestLayout() records.Layout { + schema := records.NewSchema() + schema.AddField("position", records.Int64Field, 20) + schema.AddField("job", records.StringField, 20) + schema.AddField("room", records.Int8Field, 0) + schema.AddField("_invisible", records.Int64Field, 0) + + return records.NewLayout(schema) +} diff --git a/pkg/planner/utils.go b/pkg/planner/utils.go new file mode 100644 index 0000000..9a06966 --- /dev/null +++ b/pkg/planner/utils.go @@ -0,0 +1,9 @@ +package planner + +func max(x, y int64) int64 { + if x < y { + return y + } + + return x +} diff --git a/pkg/scan/expressions_test.go b/pkg/scan/expressions_test.go index 7f42756..f291ce2 100644 --- a/pkg/scan/expressions_test.go +++ b/pkg/scan/expressions_test.go @@ -67,7 +67,7 @@ func (ts *ExpressionsTestSuite) TestScalarExpression_Evaluate() { require.NoError(t, err) records := 10 - wts, err := scan.NewTableScan(tx1, testDataFile, layout) + wts, err := scan.NewTableScan(tx1, testDataTable, layout) require.NoError(t, err) defer wts.Close() @@ -82,7 +82,7 @@ func (ts *ExpressionsTestSuite) TestScalarExpression_Evaluate() { tx2, err := tm.Transaction() require.NoError(t, err) - rts, err := scan.NewTableScan(tx2, testDataFile, layout) + rts, err := scan.NewTableScan(tx2, testDataTable, layout) require.NoError(t, err) defer rts.Close() @@ -145,7 +145,7 @@ func (ts *ExpressionsTestSuite) TestFieldExpression_Evaluate() { require.NoError(t, err) records := 10 - wts, err := scan.NewTableScan(tx1, testDataFile, layout) + wts, err := scan.NewTableScan(tx1, testDataTable, layout) require.NoError(t, err) defer wts.Close() @@ -160,7 +160,7 @@ func (ts *ExpressionsTestSuite) TestFieldExpression_Evaluate() { tx2, err := tm.Transaction() require.NoError(t, err) - rts, err := scan.NewTableScan(tx2, testDataFile, layout) + rts, err := scan.NewTableScan(tx2, testDataTable, layout) require.NoError(t, err) defer rts.Close() diff --git a/pkg/scan/predicates_test.go b/pkg/scan/predicates_test.go index ebd32ba..f07331c 100644 --- a/pkg/scan/predicates_test.go +++ b/pkg/scan/predicates_test.go @@ -201,7 +201,7 @@ func (ts *PredicatesTestsuite) TestAndPredicate_IsSatisfied() { tx1, err := tm.Transaction() require.NoError(t, err) - wts, err := scan.NewTableScan(tx1, testDataFile, ts.testLayout()) + wts, err := scan.NewTableScan(tx1, testDataTable, ts.testLayout()) require.NoError(t, err) defer wts.Close() @@ -220,7 +220,7 @@ func (ts *PredicatesTestsuite) TestAndPredicate_IsSatisfied() { tx2, err := tm.Transaction() require.NoError(t, err) - rts, err := scan.NewTableScan(tx2, testDataFile, ts.testLayout()) + rts, err := scan.NewTableScan(tx2, testDataTable, ts.testLayout()) require.NoError(t, err) defer rts.Close() diff --git a/pkg/scan/project_scan_test.go b/pkg/scan/project_scan_test.go index b65a13f..b72d0a2 100644 --- a/pkg/scan/project_scan_test.go +++ b/pkg/scan/project_scan_test.go @@ -43,7 +43,7 @@ func (ts *ProjectScanTestsuite) TestSchema() { defer require.NoError(t, tx.Commit()) - ts1, err := scan.NewTableScan(tx, testDataFile, ts.testLayout()) + ts1, err := scan.NewTableScan(tx, testDataTable, ts.testLayout()) require.NoError(t, err) sut := scan.NewProjectScan(ts1, "id", "name", "unexistant") @@ -62,7 +62,7 @@ func (ts *ProjectScanTestsuite) TestIterate() { tx, err := tm.Transaction() require.NoError(t, err) - ts1, err := scan.NewTableScan(tx, testDataFile, ts.testLayout()) + ts1, err := scan.NewTableScan(tx, testDataTable, ts.testLayout()) require.NoError(t, err) records := 1000 @@ -82,7 +82,7 @@ func (ts *ProjectScanTestsuite) TestIterate() { require.NoError(t, tx.Commit()) - ts2, err := scan.NewTableScan(tx, testDataFile, ts.testLayout()) + ts2, err := scan.NewTableScan(tx, testDataTable, ts.testLayout()) require.NoError(t, err) defer require.NoError(t, tx.Commit()) diff --git a/pkg/scan/select_scan_test.go b/pkg/scan/select_scan_test.go index 2340433..a46ccd6 100644 --- a/pkg/scan/select_scan_test.go +++ b/pkg/scan/select_scan_test.go @@ -38,7 +38,7 @@ func (ts *SelectScanTestSuite) TestIterate() { trx1, err := trxMan.Transaction() require.NoError(t, err) - ts1, err := scan.NewTableScan(trx1, testDataFile, ts.testLayout()) + ts1, err := scan.NewTableScan(trx1, testDataTable, ts.testLayout()) require.NoError(t, err) for i := 0; i < records; i++ { @@ -55,7 +55,7 @@ func (ts *SelectScanTestSuite) TestIterate() { trx2, err := trxMan.Transaction() require.NoError(t, err) - ts2, err := scan.NewTableScan(trx2, testDataFile, ts.testLayout()) + ts2, err := scan.NewTableScan(trx2, testDataTable, ts.testLayout()) require.NoError(t, err) sut := scan.NewSelectScan( @@ -110,7 +110,7 @@ func (ts *SelectScanTestSuite) TestUpdate() { trx1, err := trxMan.Transaction() require.NoError(t, err) - ts2, err := scan.NewTableScan(trx1, testDataFile, ts.testLayout()) + ts2, err := scan.NewTableScan(trx1, testDataTable, ts.testLayout()) require.NoError(t, err) sut := scan.NewSelectScan( diff --git a/pkg/scan/table_scan.go b/pkg/scan/table_scan.go index 2a62de4..6b705ea 100644 --- a/pkg/scan/table_scan.go +++ b/pkg/scan/table_scan.go @@ -9,21 +9,23 @@ import ( const tableSuffix = ".tbl" type TableScan struct { - trx TRXInt - Filename string - layout records.Layout + trx TRXInt + Filename string + Tablename string + layout records.Layout rp *records.RecordPage currentSlot types.SlotID } -func NewTableScan(trx TRXInt, filename string, layout records.Layout) (*TableScan, error) { - filename = filename + tableSuffix +func NewTableScan(trx TRXInt, tablename string, layout records.Layout) (*TableScan, error) { + filename := tablename + tableSuffix ts := &TableScan{ - trx: trx, - Filename: filename, - layout: layout, + trx: trx, + Filename: filename, + Tablename: tablename, + layout: layout, } size, err := trx.Size(filename) diff --git a/pkg/scan/table_scan_test.go b/pkg/scan/table_scan_test.go index de0ccc8..00e292e 100644 --- a/pkg/scan/table_scan_test.go +++ b/pkg/scan/table_scan_test.go @@ -36,7 +36,7 @@ func (ts *TableScanTestSuite) newSUT(testPath string) (*scan.TableScan, *transac trx, err := trxMan.Transaction() require.NoError(t, err) - sut, err := scan.NewTableScan(trx, testDataFile, ts.testLayout()) + sut, err := scan.NewTableScan(trx, testDataTable, ts.testLayout()) require.NoError(t, err) return sut, trx, fm, func() { diff --git a/pkg/scan/terms_test.go b/pkg/scan/terms_test.go index 27fa0a5..cba4c99 100644 --- a/pkg/scan/terms_test.go +++ b/pkg/scan/terms_test.go @@ -55,7 +55,7 @@ func (ts *TermsTestSuite) TestEqualTerm_isSatisfied() { tx1, err := tm.Transaction() require.NoError(t, err) - wts, err := scan.NewTableScan(tx1, testDataFile, layout) + wts, err := scan.NewTableScan(tx1, testDataTable, layout) require.NoError(t, err) defer wts.Close() @@ -70,7 +70,7 @@ func (ts *TermsTestSuite) TestEqualTerm_isSatisfied() { tx2, err := tm.Transaction() require.NoError(t, err) - rts, err := scan.NewTableScan(tx2, testDataFile, layout) + rts, err := scan.NewTableScan(tx2, testDataTable, layout) require.NoError(t, err) defer rts.Close() diff --git a/pkg/scan/testutil_test.go b/pkg/scan/testutil_test.go index b6eaadf..92748c4 100644 --- a/pkg/scan/testutil_test.go +++ b/pkg/scan/testutil_test.go @@ -13,7 +13,7 @@ import ( ) const ( - testDataFile = "data.dat" + testDataTable = "data" testWALFile = "scan_wal.dat" defaultTestBlockSize = 4000 defaultTestBuffersPoolLen = 100