diff --git a/handler.go b/handler.go index 341c2d395..a44f05ae9 100644 --- a/handler.go +++ b/handler.go @@ -1628,7 +1628,7 @@ func (h *Handler) handlePostInput(w http.ResponseWriter, r *http.Request) { return } for _, req := range reqs { - bits, err := h.JSONParser(req.(map[string]interface{}), index, inputDefName) + bits, err := h.InputJsonDataParser(req.(map[string]interface{}), index, inputDefName) if err == ErrInputDefinitionNotFound { http.Error(w, err.Error(), http.StatusNotFound) return @@ -1649,8 +1649,8 @@ func (h *Handler) handlePostInput(w http.ResponseWriter, r *http.Request) { } } -// JSONParser validate input json file and execute SetBit -func (h *Handler) JSONParser(req map[string]interface{}, index *Index, name string) (map[string][]*Bit, error) { +// InputJsonDataParser validate input json file and execute SetBit +func (h *Handler) InputJsonDataParser(req map[string]interface{}, index *Index, name string) (map[string][]*Bit, error) { inputDef := index.inputDefinition(name) if inputDef == nil { return nil, ErrInputDefinitionNotFound @@ -1671,11 +1671,9 @@ func (h *Handler) JSONParser(req map[string]interface{}, index *Index, name stri } } - var bits []*Bit setBits := make(map[string][]*Bit) for _, field := range inputDef.Fields() { // skip field that defined in definition but not in input data - //var colValue uint64 if _, ok := req[field.Name]; !ok { continue } @@ -1694,8 +1692,9 @@ func (h *Handler) JSONParser(req map[string]interface{}, index *Index, name stri if err != nil { return nil, fmt.Errorf("error handling action: %s, err: %s", action.ValueDestination, err) } - //bits = append(bits, bit) - setBits[frame] = append(bits, bit) + if bit != nil { + setBits[frame] = append(setBits[frame], bit) + } } } return setBits, nil diff --git a/handler_test.go b/handler_test.go index 0fe1f6c47..37fd9f25c 100644 --- a/handler_test.go +++ b/handler_test.go @@ -1274,6 +1274,32 @@ func TestHandler_CreateInput(t *testing.T) { } else if body := w.Body.String(); body != `{}`+"\n" { t.Fatalf("unexpected body: %s", body) } + + // Verify the bits set per frame + // f := index.Frame("cab-type") + f0 := index.Frame("distance-miles") + v0 := f0.View(pilosa.ViewStandard) + fragment0 := v0.Fragment(0) + + // Verify the distanceMiles Bit was set + if a := fragment0.Row(8).Bits(); !reflect.DeepEqual(a, []uint64{1}) { + t.Fatalf("unexpected bits: %+v", a) + } + + f1 := index.Frame("add-ons") + v1 := f1.View(pilosa.ViewStandard) + fragment1 := v1.Fragment(0) + + // Verify the add-ons frame does not have a distanceMiles Bit set + // The Input process must respect the Action Frame assignments + if a := fragment1.Row(8).Bits(); !reflect.DeepEqual(a, []uint64{}) { + t.Fatalf("unexpected bits: %+v", a) + } + // Verify the withPet Bit was set + if a := fragment1.Row(100).Bits(); !reflect.DeepEqual(a, []uint64{1}) { + t.Fatalf("unexpected bits: %+v", a) + } + } func TestInput_JSON(t *testing.T) { @@ -1325,8 +1351,8 @@ func TestInput_JSON(t *testing.T) { t.Fatalf("Expect error: %s, actual: %s", test.err, body) } } - } + func EncodeInputDef(name string, body []byte) (*internal.InputDefinition, error) { var req pilosa.InputDefinitionInfo err := json.Unmarshal(body, &req) diff --git a/index.go b/index.go index 8d5d4065b..7c97c0498 100644 --- a/index.go +++ b/index.go @@ -766,6 +766,9 @@ func (i *Index) InputBits(frame string, bits []*Bit) error { } for i, bit := range bits { + if bit == nil { + continue + } rowIDs = append(rowIDs, bit.RowID) columnIDs = append(columnIDs, bit.ColumnID) diff --git a/index_test.go b/index_test.go index d7df43da3..8a7367636 100644 --- a/index_test.go +++ b/index_test.go @@ -18,6 +18,7 @@ import ( "io/ioutil" "os" "reflect" + "strings" "testing" "github.com/pilosa/pilosa" @@ -456,6 +457,7 @@ func TestIndex_CreateFrameWhenOpenInputDefinition(t *testing.T) { } func TestIndex_InputBits(t *testing.T) { + var bits []*pilosa.Bit index := MustOpenIndex() defer index.Close() @@ -464,17 +466,22 @@ func TestIndex_InputBits(t *testing.T) { t.Fatal(err) } + err := index.InputBits("f", bits) + if !strings.Contains(err.Error(), "Frame not found") { + t.Fatalf("Expected Frame not found error, actual error: %s", err) + } + // Create frame. if _, err := index.CreateFrameIfNotExists("f", pilosa.FrameOptions{}); err != nil { t.Fatal(err) } - var bits []*pilosa.Bit bits = append(bits, &pilosa.Bit{RowID: 0, ColumnID: 0}) bits = append(bits, &pilosa.Bit{RowID: 0, ColumnID: 1}) bits = append(bits, &pilosa.Bit{RowID: 2, ColumnID: 2, Timestamp: 1}) + bits = append(bits, nil) - err := index.InputBits("f", bits) + err = index.InputBits("f", bits) if err != nil { t.Fatal(err) } diff --git a/input_definition.go b/input_definition.go index 56b5d7705..a8e2e709e 100644 --- a/input_definition.go +++ b/input_definition.go @@ -339,22 +339,14 @@ func HandleAction(a Action, value interface{}, colID uint64) (*Bit, error) { return nil, fmt.Errorf("Value %s does not exist in definition map", v) } case InputSingleRowBool: - switch value.(type) { - case bool: - if value.(bool) { - bit.RowID = *a.RowID - } else { // value is not True. - return nil, err - } - case float64: - if value.(float64) >= 1 { - bit.RowID = *a.RowID - } else { // value is not True. - return nil, err - } - default: + v, ok := value.(bool) + if !ok { return nil, fmt.Errorf("single-row-boolean value %v must equate to a Bool", value) } + if v == false { // False returns a nil error and nil bit. + return nil, err + } + bit.RowID = *a.RowID case InputValueToRow: v, ok := value.(float64) if !ok { diff --git a/input_definition_test.go b/input_definition_test.go index 8adcbc1cc..595f57f10 100644 --- a/input_definition_test.go +++ b/input_definition_test.go @@ -179,17 +179,10 @@ func TestHandleAction(t *testing.T) { t.Fatalf("Expected Unrecognized Value Destination error, actual error: %s", err) } - value = float64(1.5) + value = float64(1) b, err = pilosa.HandleAction(action, value, colID) - if b != nil { - if b.RowID != 100 { - t.Fatalf("Unexpected rowID %v", b.RowID) - } - } - value = float64(0) - b, err = pilosa.HandleAction(action, value, colID) - if b != nil { - t.Fatalf("Expected Ignore values that do not equate to True") + if !strings.Contains(err.Error(), "must equate to a Bool") { + t.Fatalf("Expected Unrecognized Value Destination error, actual error: %s", err) } value = false @@ -204,6 +197,9 @@ func TestHandleAction(t *testing.T) { if b.ColumnID != 0 { t.Fatalf("Unexpected ColumnID %v", b.ColumnID) } + if b.RowID != 100 { + t.Fatalf("Unexpected rowID %v", b.RowID) + } } action.ValueDestination = pilosa.InputValueToRow