From 59bf27891d3a058aeefe9ce9d4281e62e75f87d3 Mon Sep 17 00:00:00 2001 From: Gui Iribarren Date: Thu, 8 Aug 2024 14:54:52 +0200 Subject: [PATCH] api: endpoint /elections can now filter startDate and endDate this includes a refactor of parseElectionParams since the args list went wild notably, the indexer.ProcessList method was not refactored. --- api/accounts.go | 25 +++----- api/api.go | 36 ++++++----- api/api_types.go | 16 +++-- api/elections.go | 86 ++++++++++++++------------- api/errors.go | 1 + api/helpers.go | 24 ++++++++ vochain/indexer/db/processes.sql.go | 12 ++++ vochain/indexer/indexer_test.go | 34 +++++------ vochain/indexer/process.go | 9 ++- vochain/indexer/queries/processes.sql | 4 ++ 10 files changed, 148 insertions(+), 99 deletions(-) diff --git a/api/accounts.go b/api/accounts.go index b75b08643..7de92ac00 100644 --- a/api/accounts.go +++ b/api/accounts.go @@ -355,15 +355,9 @@ func (a *API) accountCountHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContex // @Success 200 {object} ElectionsList // @Router /accounts/{organizationId}/elections/page/{page} [get] func (a *API) accountElectionsListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { - params, err := parseElectionParams( - ctx.URLParam(ParamPage), - "", - "", - ctx.URLParam(ParamOrganizationId), - "", - "", - "", - "", + params, err := electionParams(ctx.URLParam, + ParamPage, + ParamOrganizationId, ) if err != nil { return err @@ -391,15 +385,10 @@ func (a *API) accountElectionsListByPageHandler(_ *apirest.APIdata, ctx *httprou // @Success 200 {object} ElectionsList // @Router /accounts/{organizationId}/elections/status/{status}/page/{page} [get] func (a *API) accountElectionsListByStatusAndPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { - params, err := parseElectionParams( - ctx.URLParam(ParamPage), - "", - ctx.URLParam(ParamStatus), - ctx.URLParam(ParamOrganizationId), - "", - "", - "", - "", + params, err := electionParams(ctx.URLParam, + ParamPage, + ParamStatus, + ParamOrganizationId, ) if err != nil { return err diff --git a/api/api.go b/api/api.go index 773b0ff8b..6dcacc5f6 100644 --- a/api/api.go +++ b/api/api.go @@ -60,22 +60,26 @@ const ( // //nolint:revive const ( - ParamAccountId = "accountId" - ParamCensusId = "censusId" - ParamElectionId = "electionId" - ParamOrganizationId = "organizationId" - ParamVoteId = "voteId" - ParamPage = "page" - ParamLimit = "limit" - ParamStatus = "status" - ParamWithResults = "withResults" - ParamFinalResults = "finalResults" - ParamManuallyEnded = "manuallyEnded" - ParamHeight = "height" - ParamReference = "reference" - ParamType = "type" - ParamAccountIdFrom = "accountIdFrom" - ParamAccountIdTo = "accountIdTo" + ParamAccountId = "accountId" + ParamCensusId = "censusId" + ParamElectionId = "electionId" + ParamOrganizationId = "organizationId" + ParamVoteId = "voteId" + ParamPage = "page" + ParamLimit = "limit" + ParamStatus = "status" + ParamWithResults = "withResults" + ParamFinalResults = "finalResults" + ParamManuallyEnded = "manuallyEnded" + ParamHeight = "height" + ParamReference = "reference" + ParamType = "type" + ParamAccountIdFrom = "accountIdFrom" + ParamAccountIdTo = "accountIdTo" + ParamStartDateAfter = "startDateAfter" + ParamStartDateBefore = "startDateBefore" + ParamEndDateAfter = "endDateAfter" + ParamEndDateBefore = "endDateBefore" ) var ( diff --git a/api/api_types.go b/api/api_types.go index e3b3ddd1c..d948b7207 100644 --- a/api/api_types.go +++ b/api/api_types.go @@ -23,12 +23,16 @@ type PaginationParams struct { // ElectionParams allows the client to filter elections type ElectionParams struct { PaginationParams - OrganizationID string `json:"organizationId,omitempty"` - ElectionID string `json:"electionId,omitempty"` - Status string `json:"status,omitempty"` - WithResults *bool `json:"withResults,omitempty"` - FinalResults *bool `json:"finalResults,omitempty"` - ManuallyEnded *bool `json:"manuallyEnded,omitempty"` + OrganizationID string `json:"organizationId,omitempty"` + ElectionID string `json:"electionId,omitempty"` + Status string `json:"status,omitempty"` + WithResults *bool `json:"withResults,omitempty"` + FinalResults *bool `json:"finalResults,omitempty"` + ManuallyEnded *bool `json:"manuallyEnded,omitempty"` + StartDateAfter *time.Time `json:"startDateAfter,omitempty"` + StartDateBefore *time.Time `json:"startDateBefore,omitempty"` + EndDateAfter *time.Time `json:"endDateAfter,omitempty"` + EndDateBefore *time.Time `json:"endDateBefore,omitempty"` } // OrganizationParams allows the client to filter organizations diff --git a/api/elections.go b/api/elections.go index 59da95f68..89b4d7411 100644 --- a/api/elections.go +++ b/api/elections.go @@ -207,15 +207,8 @@ func (a *API) electionListByFilterHandler(msg *apirest.APIdata, ctx *httprouter. // @Success 200 {object} ElectionsList // @Router /elections/page/{page} [get] func (a *API) electionListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { - params, err := parseElectionParams( - ctx.URLParam(ParamPage), - "", - "", - "", - "", - "", - "", - "", + params, err := electionParams(ctx.URLParam, + ParamPage, ) if err != nil { return err @@ -241,15 +234,19 @@ func (a *API) electionListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTP // @Success 200 {object} ElectionsList // @Router /elections [get] func (a *API) electionListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error { - params, err := parseElectionParams( - ctx.QueryParam(ParamPage), - ctx.QueryParam(ParamLimit), - ctx.QueryParam(ParamStatus), - ctx.QueryParam(ParamOrganizationId), - ctx.QueryParam(ParamElectionId), - ctx.QueryParam(ParamWithResults), - ctx.QueryParam(ParamFinalResults), - ctx.QueryParam(ParamManuallyEnded), + params, err := electionParams(ctx.QueryParam, + ParamPage, + ParamLimit, + ParamStatus, + ParamOrganizationId, + ParamElectionId, + ParamWithResults, + ParamFinalResults, + ParamManuallyEnded, + ParamStartDateAfter, + ParamStartDateBefore, + ParamEndDateAfter, + ParamEndDateBefore, ) if err != nil { return err @@ -282,6 +279,10 @@ func (a *API) sendElectionList(ctx *httprouter.HTTPContext, params *ElectionPara params.WithResults, params.FinalResults, params.ManuallyEnded, + params.StartDateAfter, + params.StartDateBefore, + params.EndDateAfter, + params.EndDateBefore, ) if err != nil { return ErrIndexerQueryFailed.WithErr(err) @@ -757,38 +758,43 @@ func (a *API) buildElectionIDHandler(msg *apirest.APIdata, ctx *httprouter.HTTPC return ctx.Send(data, apirest.HTTPstatusOK) } -// parseElectionParams returns an ElectionParams filled with the passed params -func parseElectionParams(paramPage, paramLimit, paramStatus, - paramOrganizationID, paramElectionID, - paramWithResults, paramFinalResults, paramManuallyEnded string, -) (*ElectionParams, error) { - pagination, err := parsePaginationParams(paramPage, paramLimit) - if err != nil { - return nil, err - } +// electionParams produces an ElectionParams, calling the passed func (ctx.QueryParam or ctx.URLParam) +// to retrieve all the values of all keys passed. +func electionParams(f func(key string) string, keys ...string) (*ElectionParams, error) { + strings := paramsFromCtxFunc(f, keys...) - withResults, err := parseBool(paramWithResults) + pagination, err := parsePaginationParams(strings[ParamPage], strings[ParamLimit]) if err != nil { return nil, err } - finalResults, err := parseBool(paramFinalResults) - if err != nil { - return nil, err + bools := make(map[string]*bool) + for _, v := range []string{ParamWithResults, ParamFinalResults, ParamManuallyEnded} { + bools[v], err = parseBool(strings[v]) + if err != nil { + return nil, err + } } - manuallyEnded, err := parseBool(paramManuallyEnded) - if err != nil { - return nil, err + dates := make(map[string]*time.Time) + for _, v := range []string{ParamStartDateAfter, ParamStartDateBefore, ParamEndDateAfter, ParamEndDateBefore} { + dates[v], err = parseDate(strings[v]) + if err != nil { + return nil, err + } } return &ElectionParams{ PaginationParams: pagination, - OrganizationID: util.TrimHex(paramOrganizationID), - ElectionID: util.TrimHex(paramElectionID), - Status: paramStatus, - WithResults: withResults, - FinalResults: finalResults, - ManuallyEnded: manuallyEnded, + OrganizationID: util.TrimHex(strings[ParamOrganizationId]), + ElectionID: util.TrimHex(strings[ParamElectionId]), + Status: strings[ParamStatus], + WithResults: bools[ParamWithResults], + FinalResults: bools[ParamFinalResults], + ManuallyEnded: bools[ParamManuallyEnded], + StartDateAfter: dates[ParamStartDateAfter], + StartDateBefore: dates[ParamStartDateBefore], + EndDateAfter: dates[ParamEndDateAfter], + EndDateBefore: dates[ParamEndDateBefore], }, nil } diff --git a/api/errors.go b/api/errors.go index 3d4e4c31b..f6ed2af3c 100644 --- a/api/errors.go +++ b/api/errors.go @@ -83,6 +83,7 @@ var ( ErrCantParseBoolean = apirest.APIerror{Code: 4055, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("cannot parse string into boolean")} ErrCantParseHexString = apirest.APIerror{Code: 4056, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("cannot parse string into hex bytes")} ErrPageNotFound = apirest.APIerror{Code: 4057, HTTPstatus: apirest.HTTPstatusNotFound, Err: fmt.Errorf("page not found")} + ErrCantParseDate = apirest.APIerror{Code: 4058, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("cannot parse date")} ErrVochainEmptyReply = apirest.APIerror{Code: 5000, HTTPstatus: apirest.HTTPstatusInternalErr, Err: fmt.Errorf("vochain returned an empty reply")} ErrVochainSendTxFailed = apirest.APIerror{Code: 5001, HTTPstatus: apirest.HTTPstatusInternalErr, Err: fmt.Errorf("vochain SendTx failed")} ErrVochainGetTxFailed = apirest.APIerror{Code: 5002, HTTPstatus: apirest.HTTPstatusInternalErr, Err: fmt.Errorf("vochain GetTx failed")} diff --git a/api/helpers.go b/api/helpers.go index b261cb901..1062ed245 100644 --- a/api/helpers.go +++ b/api/helpers.go @@ -9,6 +9,7 @@ import ( "math/big" "strconv" "strings" + "time" cometpool "github.com/cometbft/cometbft/mempool" cometcoretypes "github.com/cometbft/cometbft/rpc/core/types" @@ -275,6 +276,20 @@ func parseBool(s string) (*bool, error) { return &b, nil } +// parseDate parses an RFC3339 string into a time.Time value. +// +// The empty string "" is treated specially, returns a nil pointer with no error. +func parseDate(s string) (*time.Time, error) { + if s == "" { + return nil, nil + } + b, err := time.Parse(time.RFC3339, s) + if err != nil { + return nil, ErrCantParseDate.With(s) + } + return &b, nil +} + // parsePaginationParams returns a PaginationParams filled with the passed params func parsePaginationParams(paramPage, paramLimit string) (PaginationParams, error) { page, err := parsePage(paramPage) @@ -325,3 +340,12 @@ func calculatePagination(page int, limit int, totalItems uint64) (*Pagination, e LastPage: uint64(lastp), }, nil } + +// paramsFromCtxFunc calls f(key) for each key passed, and the resulting value is saved in map[key] of the returned map +func paramsFromCtxFunc(f func(key string) string, keys ...string) map[string]string { + m := make(map[string]string) + for _, key := range keys { + m[key] = f(key) + } + return m +} diff --git a/vochain/indexer/db/processes.sql.go b/vochain/indexer/db/processes.sql.go index 49a851b5a..b274c802c 100644 --- a/vochain/indexer/db/processes.sql.go +++ b/vochain/indexer/db/processes.sql.go @@ -305,6 +305,10 @@ WITH results AS ( OR (?10 = 1 AND manually_ended = TRUE) OR (?10 = 0 AND manually_ended = FALSE) ) + AND (?11 IS NULL OR start_date >= ?11) + AND (?12 IS NULL OR start_date <= ?12) + AND (?13 IS NULL OR end_date >= ?13) + AND (?14 IS NULL OR end_date <= ?14) ) ) SELECT id, total_count @@ -325,6 +329,10 @@ type SearchProcessesParams struct { HaveResults interface{} FinalResults interface{} ManuallyEnded interface{} + StartDateAfter interface{} + StartDateBefore interface{} + EndDateAfter interface{} + EndDateBefore interface{} } type SearchProcessesRow struct { @@ -344,6 +352,10 @@ func (q *Queries) SearchProcesses(ctx context.Context, arg SearchProcessesParams arg.HaveResults, arg.FinalResults, arg.ManuallyEnded, + arg.StartDateAfter, + arg.StartDateBefore, + arg.EndDateAfter, + arg.EndDateBefore, ) if err != nil { return nil, err diff --git a/vochain/indexer/indexer_test.go b/vochain/indexer/indexer_test.go index cdf425388..fad19d248 100644 --- a/vochain/indexer/indexer_test.go +++ b/vochain/indexer/indexer_test.go @@ -332,7 +332,7 @@ func testProcessList(t *testing.T, procsCount int) { for len(procs) < procsCount { fmt.Printf("%x\n", eidProcsCount) fmt.Printf("%s\n", hex.EncodeToString(eidProcsCount)) - list, total, err := idx.ProcessList(10, last, hex.EncodeToString(eidProcsCount), "", 0, 0, 0, nil, nil, nil) + list, total, err := idx.ProcessList(10, last, hex.EncodeToString(eidProcsCount), "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -351,7 +351,7 @@ func testProcessList(t *testing.T, procsCount int) { } qt.Assert(t, procs, qt.HasLen, procsCount) - _, total, err := idx.ProcessList(64, 0, "", "", 0, 0, 0, nil, nil, nil) + _, total, err := idx.ProcessList(64, 0, "", "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) qt.Assert(t, total, qt.Equals, uint64(10+procsCount)) @@ -369,7 +369,7 @@ func testProcessList(t *testing.T, procsCount int) { qt.Assert(t, countEntityProcs([]byte("not an entity id that exists")), qt.Equals, int64(-1)) // Past the end (from=10000) should return an empty list - emptyList, _, err := idx.ProcessList(64, 10000, "", "", 0, 0, 0, nil, nil, nil) + emptyList, _, err := idx.ProcessList(64, 10000, "", "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) qt.Assert(t, emptyList, qt.DeepEquals, [][]byte{}) } @@ -459,7 +459,7 @@ func TestProcessSearch(t *testing.T) { app.AdvanceTestBlock() // Exact process search - list, _, err := idx.ProcessList(10, 0, hex.EncodeToString(eidTest), pidExact, 0, 0, 0, nil, nil, nil) + list, _, err := idx.ProcessList(10, 0, hex.EncodeToString(eidTest), pidExact, 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -468,7 +468,7 @@ func TestProcessSearch(t *testing.T) { } // Exact process search, with it being encrypted. // This once caused a sqlite bug due to a mistake in the SQL query. - list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), pidExactEncrypted, 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), pidExactEncrypted, 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -477,7 +477,7 @@ func TestProcessSearch(t *testing.T) { } // Search for nonexistent process list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), - "4011d50537fa164b6fef261141797bbe4014526f", 0, 0, 0, nil, nil, nil) + "4011d50537fa164b6fef261141797bbe4014526f", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -486,7 +486,7 @@ func TestProcessSearch(t *testing.T) { } // Search containing part of all manually-defined processes list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), - "011d50537fa164b6fef261141797bbe4014526e", 0, 0, 0, nil, nil, nil) + "011d50537fa164b6fef261141797bbe4014526e", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -495,7 +495,7 @@ func TestProcessSearch(t *testing.T) { } list, _, err = idx.ProcessList(100, 0, hex.EncodeToString(eidTest), - "0c6ca22d2c175a1fbdd15d7595ae532bb1094b5", 0, 0, models.ProcessStatus_ENDED, nil, nil, nil) + "0c6ca22d2c175a1fbdd15d7595ae532bb1094b5", 0, 0, models.ProcessStatus_ENDED, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -504,17 +504,17 @@ func TestProcessSearch(t *testing.T) { } // Partial process search as uppercase hex - list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), "011D50537FA164B6FEF261141797BBE4014526E", 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), "011D50537FA164B6FEF261141797BBE4014526E", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) qt.Assert(t, list, qt.HasLen, len(processIds)) // Partial process search as mixed case hex - list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), "011D50537fA164B6FeF261141797BbE4014526E", 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(10, 0, hex.EncodeToString(eidTest), "011D50537fA164B6FeF261141797BbE4014526E", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) qt.Assert(t, list, qt.HasLen, len(processIds)) // Search with an exact Entity ID, but starting with a null byte. // This can trip up sqlite, as it assumes TEXT strings are NUL-terminated. - list, _, err = idx.ProcessList(100, 0, "\x00foobar", "", 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(100, 0, "\x00foobar", "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -523,12 +523,12 @@ func TestProcessSearch(t *testing.T) { } // list all processes, with a max of 10 - list, _, err = idx.ProcessList(10, 0, "", "", 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(10, 0, "", "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) qt.Assert(t, list, qt.HasLen, 10) // list all processes, with a max of 1000 - list, _, err = idx.ProcessList(1000, 0, "", "", 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(1000, 0, "", "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) qt.Assert(t, list, qt.HasLen, 21) } @@ -577,25 +577,25 @@ func TestProcessListWithNamespaceAndStatus(t *testing.T) { app.AdvanceTestBlock() // Get the process list for namespace 123 - list, _, err := idx.ProcessList(100, 0, hex.EncodeToString(eid20), "", 123, 0, 0, nil, nil, nil) + list, _, err := idx.ProcessList(100, 0, hex.EncodeToString(eid20), "", 123, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) // Check there are exactly 10 qt.Assert(t, len(list), qt.CmpEquals(), 10) // Get the process list for all namespaces - list, _, err = idx.ProcessList(100, 0, "", "", 0, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(100, 0, "", "", 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) // Check there are exactly 10 + 10 qt.Assert(t, len(list), qt.CmpEquals(), 20) // Get the process list for namespace 10 - list, _, err = idx.ProcessList(100, 0, "", "", 10, 0, 0, nil, nil, nil) + list, _, err = idx.ProcessList(100, 0, "", "", 10, 0, 0, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) // Check there is exactly 1 qt.Assert(t, len(list), qt.CmpEquals(), 1) // Get the process list for namespace 10 - list, _, err = idx.ProcessList(100, 0, "", "", 0, 0, models.ProcessStatus_READY, nil, nil, nil) + list, _, err = idx.ProcessList(100, 0, "", "", 0, 0, models.ProcessStatus_READY, nil, nil, nil, nil, nil, nil, nil) qt.Assert(t, err, qt.IsNil) // Check there is exactly 1 qt.Assert(t, len(list), qt.CmpEquals(), 10) diff --git a/vochain/indexer/process.go b/vochain/indexer/process.go index cd96227a2..3a33fee32 100644 --- a/vochain/indexer/process.go +++ b/vochain/indexer/process.go @@ -45,12 +45,13 @@ func (idx *Indexer) ProcessInfo(pid []byte) (*indexertypes.Process, error) { } // ProcessList returns a list of process identifiers (PIDs) registered in the Vochain. -// entityID, processID, namespace, status, and withResults are optional filters, if +// all args (entityID, processID, etc) are optional filters, if // declared as zero-values will be ignored. entityID and processID are partial or full hex strings. // Status is one of READY, CANCELED, ENDED, PAUSED, RESULTS func (idx *Indexer) ProcessList(limit, offset int, entityID string, processID string, namespace uint32, srcNetworkID int32, status models.ProcessStatus, withResults, finalResults, manuallyEnded *bool, + startDateAfter, startDateBefore, endDateAfter, endDateBefore *time.Time, ) ([][]byte, uint64, error) { if offset < 0 { return nil, 0, fmt.Errorf("invalid value: offset cannot be %d", offset) @@ -73,6 +74,10 @@ func (idx *Indexer) ProcessList(limit, offset int, entityID string, processID st HaveResults: boolToInt(withResults), FinalResults: boolToInt(finalResults), ManuallyEnded: boolToInt(manuallyEnded), + StartDateAfter: startDateAfter, + StartDateBefore: startDateBefore, + EndDateAfter: endDateAfter, + EndDateBefore: endDateBefore, }) if err != nil { return nil, 0, err @@ -93,7 +98,7 @@ func (idx *Indexer) ProcessExists(processID string) bool { if len(processID) != 64 { return false } - _, count, err := idx.ProcessList(1, 0, "", processID, 0, 0, 0, nil, nil, nil) + _, count, err := idx.ProcessList(1, 0, "", processID, 0, 0, 0, nil, nil, nil, nil, nil, nil, nil) if err != nil { log.Errorw(err, "indexer query failed") } diff --git a/vochain/indexer/queries/processes.sql b/vochain/indexer/queries/processes.sql index 2ee6499a9..afaca4e40 100644 --- a/vochain/indexer/queries/processes.sql +++ b/vochain/indexer/queries/processes.sql @@ -68,6 +68,10 @@ WITH results AS ( OR (sqlc.arg(manually_ended) = 1 AND manually_ended = TRUE) OR (sqlc.arg(manually_ended) = 0 AND manually_ended = FALSE) ) + AND (sqlc.arg(start_date_after) IS NULL OR start_date >= sqlc.arg(start_date_after)) + AND (sqlc.arg(start_date_before) IS NULL OR start_date <= sqlc.arg(start_date_before)) + AND (sqlc.arg(end_date_after) IS NULL OR end_date >= sqlc.arg(end_date_after)) + AND (sqlc.arg(end_date_before) IS NULL OR end_date <= sqlc.arg(end_date_before)) ) ) SELECT id, total_count