From f2928881955c27b7b19682c320c597d18ff5c2e0 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman Date: Thu, 13 Jun 2019 11:53:48 -0500 Subject: [PATCH] Refactor checked column specific SQL --- libraries/shared/repository/repository.go | 48 ++++++++------ .../shared/repository/repository_test.go | 66 ++++++++++++------- libraries/shared/watcher/event_watcher.go | 2 +- 3 files changed, 72 insertions(+), 44 deletions(-) diff --git a/libraries/shared/repository/repository.go b/libraries/shared/repository/repository.go index bab8aa9d..d88f1600 100644 --- a/libraries/shared/repository/repository.go +++ b/libraries/shared/repository/repository.go @@ -121,37 +121,47 @@ func GetCheckedColumnNames(db *postgres.DB) ([]string, error) { return columnNames, nil } -// Builds a SQL string that checks if any column value is 0, given the column names. +// Builds a SQL string that checks if any column should be checked/rechecked. // Defaults to FALSE when no columns are provided. // Ex: ["columnA", "columnB"] => "NOT (columnA!=0 AND columnB!=0)" // [] => "FALSE" -func CreateNotCheckedSQL(boolColumns []string, recheckHeaders constants.TransformerExecution) string { - - var result bytes.Buffer - +func CreateHeaderCheckedPredicateSQL(boolColumns []string, recheckHeaders constants.TransformerExecution) string { if len(boolColumns) == 0 { return "FALSE" } - result.WriteString("NOT (") + if recheckHeaders { + return createHeaderCheckedPredicateSQLForRecheckedHeaders(boolColumns) + } else { + return createHeaderCheckedPredicateSQLForMissingHeaders(boolColumns) + } +} + +func createHeaderCheckedPredicateSQLForMissingHeaders(boolColumns []string) string { + var result bytes.Buffer + result.WriteString(" (") // Loop excluding last column name for _, column := range boolColumns[:len(boolColumns)-1] { - - if recheckHeaders { - result.WriteString(fmt.Sprintf("%v>=%s AND ", column, constants.RecheckHeaderCap)) - } else { - result.WriteString(fmt.Sprintf("%v!=0 AND ", column)) - } + result.WriteString(fmt.Sprintf("%v=0 OR ", column)) } - // No trailing "OR" for the last column name - if recheckHeaders { - result.WriteString(fmt.Sprintf("%v>=%s)", boolColumns[len(boolColumns)-1], constants.RecheckHeaderCap)) - } else { - result.WriteString(fmt.Sprintf("%v!=0)", boolColumns[len(boolColumns)-1])) - - } + result.WriteString(fmt.Sprintf("%v=0)", boolColumns[len(boolColumns)-1])) + + return result.String() +} + +func createHeaderCheckedPredicateSQLForRecheckedHeaders(boolColumns []string) string { + var result bytes.Buffer + result.WriteString(" (") + + // Loop excluding last column name + for _, column := range boolColumns[:len(boolColumns)-1] { + result.WriteString(fmt.Sprintf("%v<%s OR ", column, constants.RecheckHeaderCap)) + } + + // No trailing "OR" for the last column name + result.WriteString(fmt.Sprintf("%v<%s)", boolColumns[len(boolColumns)-1], constants.RecheckHeaderCap)) return result.String() } diff --git a/libraries/shared/repository/repository_test.go b/libraries/shared/repository/repository_test.go index d56aa794..3413fd40 100644 --- a/libraries/shared/repository/repository_test.go +++ b/libraries/shared/repository/repository_test.go @@ -135,7 +135,7 @@ var _ = Describe("Repository", func() { columnNames, err := shared.GetCheckedColumnNames(db) Expect(err).NotTo(HaveOccurred()) - notCheckedSQL = shared.CreateNotCheckedSQL(columnNames, constants.HeaderMissing) + notCheckedSQL = shared.CreateHeaderCheckedPredicateSQL(columnNames, constants.HeaderMissing) startingBlockNumber = rand.Int63() eventSpecificBlockNumber = startingBlockNumber + 1 @@ -285,33 +285,51 @@ var _ = Describe("Repository", func() { }) }) - Describe("CreateNotCheckedSQL", func() { - It("generates a correct SQL string for one column", func() { - columns := []string{"columnA"} - expected := "NOT (columnA!=0)" - actual := shared.CreateNotCheckedSQL(columns, constants.HeaderMissing) - Expect(actual).To(Equal(expected)) + Describe("CreateCustomColumnNamesSQL", func() { + Describe("for MissingHeaders", func() { + It("generates a correct SQL string for one column", func() { + columns := []string{"columnA"} + expected := " (columnA=0)" + actual := shared.CreateHeaderCheckedPredicateSQL(columns, constants.HeaderMissing) + Expect(actual).To(Equal(expected)) + }) + + It("generates a correct SQL string for several columns", func() { + columns := []string{"columnA", "columnB"} + expected := " (columnA=0 OR columnB=0)" + actual := shared.CreateHeaderCheckedPredicateSQL(columns, constants.HeaderMissing) + Expect(actual).To(Equal(expected)) + }) + + It("defaults to FALSE when there are no columns", func() { + expected := "FALSE" + actual := shared.CreateHeaderCheckedPredicateSQL([]string{}, constants.HeaderMissing) + Expect(actual).To(Equal(expected)) + }) }) - It("generates a correct SQL string for several columns", func() { - columns := []string{"columnA", "columnB"} - expected := "NOT (columnA!=0 AND columnB!=0)" - actual := shared.CreateNotCheckedSQL(columns, constants.HeaderMissing) - Expect(actual).To(Equal(expected)) + Describe("RecheckHeadersCustomColumnNames", func() { + It("defaults to FALSE when there are no columns", func() { + expected := "FALSE" + actual := shared.CreateHeaderCheckedPredicateSQL([]string{}, constants.HeaderRecheck) + Expect(actual).To(Equal(expected)) + }) + + It("generates a correct SQL string for rechecking headers for one column", func() { + columns := []string{"columnA"} + expected := fmt.Sprintf(" (columnA<%s)", constants.RecheckHeaderCap) + actual := shared.CreateHeaderCheckedPredicateSQL(columns, constants.HeaderRecheck) + Expect(actual).To(Equal(expected)) + }) + + It("generates a correct SQL string for rechecking headers for several columns", func() { + columns := []string{"columnA", "columnB"} + expected := fmt.Sprintf(" (columnA<%s OR columnB<%s)", constants.RecheckHeaderCap, constants.RecheckHeaderCap) + actual := shared.CreateHeaderCheckedPredicateSQL(columns, constants.HeaderRecheck) + Expect(actual).To(Equal(expected)) + }) }) - It("defaults to FALSE when there are no columns", func() { - expected := "FALSE" - actual := shared.CreateNotCheckedSQL([]string{}, constants.HeaderMissing) - Expect(actual).To(Equal(expected)) - }) - - It("generates a correct SQL string for rechecking headers", func() { - columns := []string{"columnA", "columnB"} - expected := fmt.Sprintf("NOT (columnA>=%s AND columnB>=%s)", constants.RecheckHeaderCap, constants.RecheckHeaderCap) - actual := shared.CreateNotCheckedSQL(columns, constants.HeaderRecheck) - Expect(actual).To(Equal(expected)) - }) }) }) diff --git a/libraries/shared/watcher/event_watcher.go b/libraries/shared/watcher/event_watcher.go index 4c5d2958..99ea5ccc 100644 --- a/libraries/shared/watcher/event_watcher.go +++ b/libraries/shared/watcher/event_watcher.go @@ -96,7 +96,7 @@ func (watcher *EventWatcher) Execute(recheckHeaders constants.TransformerExecuti if err != nil { return err } - notCheckedSQL := repository.CreateNotCheckedSQL(checkedColumnNames, recheckHeaders) + notCheckedSQL := repository.CreateHeaderCheckedPredicateSQL(checkedColumnNames, recheckHeaders) missingHeaders, err := repository.MissingHeaders(*watcher.StartingBlock, -1, watcher.DB, notCheckedSQL) if err != nil {