handle nil rowID

This commit is contained in:
Linh Vo 2017-06-21 14:38:04 -05:00
parent e0bf37da40
commit 9fd1de8f29
5 changed files with 41 additions and 30 deletions

View file

@ -1121,7 +1121,7 @@ func TestHandler_DeleteInputDefinition(t *testing.T) {
index := hldr.MustCreateIndexIfNotExists("i0", pilosa.IndexOptions{})
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
_, err := index.CreateInputDefinition(&def)
@ -1150,7 +1150,7 @@ func TestHandler_GetInputDefinition(t *testing.T) {
index := hldr.MustCreateIndexIfNotExists("i0", pilosa.IndexOptions{})
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
inputDef, err := index.CreateInputDefinition(&def)

View file

@ -650,7 +650,9 @@ func (i *Index) createInputDefinition(pb *internal.InputDefinition) (*InputDefin
return nil, err
}
inputDef.LoadDefinition(pb)
if err = inputDef.LoadDefinition(pb); err != nil {
return nil, err
}
if err = inputDef.saveMeta(); err != nil {
return nil, err
}

View file

@ -247,7 +247,7 @@ func TestIndex_CreateInputDefinition(t *testing.T) {
// Create Input Definition.
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
inputDef, err := index.CreateInputDefinition(&def)
@ -266,7 +266,7 @@ func TestIndex_CreateExistingInputDefinition(t *testing.T) {
// Create Input Definition.
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
_, err := index.CreateInputDefinition(&def)
@ -297,7 +297,7 @@ func TestIndex_DeleteInputDefinition(t *testing.T) {
// Create Input Definition.
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
_, err := index.CreateInputDefinition(&def)
@ -321,7 +321,7 @@ func TestIndex_CreateFrameWhenOpenInputDefinition(t *testing.T) {
// Create Input Definition.
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
input, err := index.CreateInputDefinition(&def)

View file

@ -25,7 +25,7 @@ import (
"github.com/pilosa/pilosa/internal"
)
var ValidValueDestination = []string{"map", "valueToRow", "stringToBool"}
var ValidValueDestination = []string{"mapping", "value-to-row", "single-row-boolean"}
// InputDefinition represents a container for the data input definition.
type InputDefinition struct {
@ -101,10 +101,10 @@ func (i *InputDefinition) LoadDefinition(pb *internal.InputDefinition) error {
if err := i.ValidateAction(action); err != nil {
return err
}
if action.RowID != 0 && action.Frame != ""{
if action.RowID != 0 && action.Frame != "" {
val, ok := countRowID[action.Frame]
if ok && val == action.RowID {
return fmt.Errorf("duplicate rowID with other field: %s", action.RowID)
return fmt.Errorf("duplicate rowID with other field: %v", action.RowID)
} else {
countRowID[action.Frame] = action.RowID
}
@ -113,7 +113,7 @@ func (i *InputDefinition) LoadDefinition(pb *internal.InputDefinition) error {
Frame: action.Frame,
ValueDestination: action.ValueDestination,
ValueMap: action.ValueMap,
RowID: action.RowID,
RowID: &action.RowID,
})
}
@ -176,7 +176,7 @@ func (i *InputDefinition) saveMeta() error {
Frame: action.Frame,
ValueDestination: action.ValueDestination,
ValueMap: action.ValueMap,
RowID: action.RowID,
RowID: convert(action.RowID),
}
actions = append(actions, actionMeta)
}
@ -226,7 +226,7 @@ type Action struct {
Frame string `json:"frame,omitempty"`
ValueDestination string `json:"valueDestination,omitempty"`
ValueMap map[string]uint64 `json:"valueMap,omitempty"`
RowID uint64 `json:"rowID,omitempty"`
RowID *uint64 `json:"rowID,omitempty"`
}
// Encode converts Action into its internal representation.
@ -235,10 +235,19 @@ func (o *Action) Encode() *internal.Action {
Frame: o.Frame,
ValueDestination: o.ValueDestination,
ValueMap: o.ValueMap,
RowID: o.RowID,
RowID: convert(o.RowID),
}
}
func convert(x *uint64) uint64 {
if x != nil {
return *x
}
var v int64 = -1
var v2 uint64 = uint64(v)
return v2
}
// InputFrame defines the frame used in the input definition.
type InputFrame struct {
Name string `json:"name,omitempty"`
@ -282,17 +291,14 @@ func (i *InputDefinition) ValidateAction(action *internal.Action) error {
}
switch action.ValueDestination {
case "map":
case "mapping":
if len(action.ValueMap) == 0 {
return errors.New("valueMap required for map")
}
case "stringToBool":
if action.RowID == 0 {
return errors.New("rowID required for stringToBool")
case "single-row-boolean":
if int64(action.RowID) == -1 {
return errors.New("rowID required for single-row-boolean")
}
default:
return nil
}
return nil
}

View file

@ -29,7 +29,7 @@ func TestInputDefinition_Open(t *testing.T) {
// Create Input Definition.
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "map", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "mapping", ValueMap: map[string]uint64{"Green": 1}}
fields := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&fields}}
inputDef, err := index.CreateInputDefinition(&def)
@ -102,7 +102,7 @@ func TestInputDefinition_LoadDefinition(t *testing.T) {
// Create Input Definition.
input := pilosa.InputDefinition{}
frames := internal.Frame{Name: "f", Meta: &internal.FrameMeta{RowLabel: "row"}}
action := internal.Action{Frame: "f", ValueDestination: "ValueToRow", ValueMap: map[string]uint64{"Green": 1}}
action := internal.Action{Frame: "f", ValueDestination: "value-to-ROW", ValueMap: map[string]uint64{"Green": 1}}
field := internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def := &internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&field}}
err := input.LoadDefinition(def)
@ -110,22 +110,25 @@ func TestInputDefinition_LoadDefinition(t *testing.T) {
t.Fatalf("Expected invalid ValueDestination error, actual error: %s", err)
}
action = internal.Action{Frame: "f", ValueDestination: "stringToBool", ValueMap: map[string]uint64{"Green": 1}}
act := pilosa.Action{Frame: "f", ValueDestination: "single-row-boolean", ValueMap: map[string]uint64{"Green": 1}}
encodeAction := act.Encode()
field = internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{encodeAction}}
def = &internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&field}}
err = input.LoadDefinition(def)
if !strings.Contains(err.Error(), "rowID required for stringToBool") {
t.Fatalf("Expected rowID required for stringToBool error, actual error: %s", err)
if !strings.Contains(err.Error(), "rowID required for single-row-boolean") {
t.Fatalf("Expected rowID required for single-row-boolean error, actual error: %s", err)
}
action = internal.Action{Frame: "f", ValueDestination: "map", RowID: 100}
action = internal.Action{Frame: "f", ValueDestination: "mapping", RowID: 100}
field = internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action}}
def = &internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&field}}
err = input.LoadDefinition(def)
if !strings.Contains(err.Error(), "valueMap required for map") {
t.Fatalf("Expected valueMap required for map error, actual error: %s", err)
}
action = internal.Action{Frame: "f", ValueDestination: "stringToBool", RowID: 100}
action1 := internal.Action{Frame: "f", ValueDestination: "stringToBool", RowID: 101}
action = internal.Action{Frame: "f", ValueDestination: "single-row-boolean", RowID: 100}
action1 := internal.Action{Frame: "f", ValueDestination: "single-row-boolean", RowID: 0}
field1 := internal.InputDefinitionField{Name: "newID", PrimaryKey: true, Actions: []*internal.Action{&action1}}
def = &internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&field, &field1}}
err = input.LoadDefinition(def)
@ -133,7 +136,7 @@ func TestInputDefinition_LoadDefinition(t *testing.T) {
t.Fatalf("Expected duplicate primaryKey error, actual error: %s", err)
}
action1 = internal.Action{Frame: "f", ValueDestination: "stringToBool", RowID: 100}
action1 = internal.Action{Frame: "f", ValueDestination: "single-row-boolean", RowID: 100}
field1 = internal.InputDefinitionField{Name: "id", PrimaryKey: true, Actions: []*internal.Action{&action1}}
def = &internal.InputDefinition{Name: "test", Frames: []*internal.Frame{&frames}, Fields: []*internal.InputDefinitionField{&field, &field1}}
err = input.LoadDefinition(def)