Skip to content

Commit

Permalink
feat: support alternative indices and default value (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
veezhang authored Dec 7, 2022
1 parent b76a852 commit 398992c
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 14 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,20 @@ schema:
index: 1
- name: gender
type: string
defaultValue: "male"
- name: phone
type: string
nullable: true
- name: wechat
- name: email
type: string
nullable: true
nullValue: "__NULL__"
- name: address
type: string
nullable: true
alternativeIndices:
- 7
- 8
```

##### `schema.vertex.vid`
Expand All @@ -233,7 +240,9 @@ Each tag contains the following two properties:
* `type`: **Optional**. The property type, currently `bool`, `int`, `float`, `double`, `string`, `time`, `timestamp`, `date`, `datetime`, `geography`, `geography(point)`, `geography(linestring)` and `geography(polygon)` are supported.
* `index`: **Optional**. The column number in the CSV file.
* `nullable`: **Optional**. Whether this prop property can be `NULL`, optional values is `true` or `false`, default `false`.
* `nullValue`: **Optional**. If `nullable` is set to `true`, the property will be set to `NULL` when the value is equal to `nullValue`, default `""`.
* `nullValue`: **Optional**. Ignored when `nullable` is `false`. The property is set to `NULL` when the value is equal to `nullValue`, default `""`.
* `alternativeIndices`: **Optional**. Ignored when `nullable` is `false`. The property is fetched from csv according to the indices in order until not equal to `nullValue`.
* `defaultValue`: **Optional**. Ignored when `nullable` is `false`. The property default value, when all the values obtained by `index` and `alternativeIndices` are `nullValue`.

> **NOTE**: The properties in the preceding `prop` parameter must be sorted in the **same** way as in the CSV data file.

Expand Down
18 changes: 17 additions & 1 deletion README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ schema:
index: 1
- name: gender
type: string
defaultValue: "male"
- name: phone
type: string
nullable: true
- name: email
type: string
nullable: true
nullValue: "__NULL__"
- name: address
type: string
nullable: true
alternativeIndices:
- 7
- 8
```
##### `schema.vertex.vid`
Expand All @@ -199,7 +213,9 @@ schema:
- `type`:**必填**。属性类型,目前支持 `bool`、`int`、`float`、`double`、`timestamp`、`string`、`geography`、`geography(point)`、`geography(linestring)`和`geography(polygon)` 几种类型。
- `index`:**可选**。在 CSV 文件中的列标。
- `nullable`:**可选**。此属性是否可以为 `NULL`,可选 `true` 或者 `false`,默认值为 `false` 。
- `nullValue`:**可选**。如果 `nullable` 设置为 `true`,则当值等于 `nullValue` 的时候属性将被设置为 `NULL` ,默认值为 `""`。
- `nullValue`:**可选**。当 `nullable` 为 `false` 时被忽略。当值等于 `nullValue` 的时候属性将被设置为 `NULL` ,默认值为 `""`。
- `alternativeIndices`: **可选**。当 `nullable` 为 `false` 时被忽略。该属性根据索引顺序从 csv 中获取,直到不等于 `nullValue`。
- `defaultValue`: **可选**。当 `nullable` 为 `false` 时被忽略。属性默认值,当根据 `index` 和 `alternativeIndices` 获取的所有值为 `nullValue` 时设置默认值。
> **注意**:上述 `props` 中的属性描述**顺序**必须同数据文件中的对应数据排列顺序一致。
Expand Down
5 changes: 5 additions & 0 deletions examples/v2/basic_type_test.csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ b4,false,3,2.0,3.3,0a bd
b5,true,-3,2,3,abcd efg
bnull1,,,,,
bnull2,,,,,__NULL__
bnull3,,-4,4,4.4,
bnull4,,-4,,4.4,
bnull5,,,4,,
bnull6,,,4,4.4,
bnull7,,,,4.4,
13 changes: 13 additions & 0 deletions examples/v2/example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,21 @@ files:
type: int
index: 2
nullable: true
defaultValue: "0"
- name: f
type: float
index: 3
nullable: true
alternativeIndices:
- 2
- name: d
type: double
index: 4
nullable: true
alternativeIndices:
- 3
- 2
defaultValue: "0"
- name: s
type: string
index: 5
Expand Down Expand Up @@ -528,10 +535,16 @@ files:
type: float
index: 3
nullable: true
alternativeIndices:
- 2
defaultValue: "0"
- name: d
type: double
index: 4
nullable: true
alternativeIndices:
- 3
- 2
- name: s
type: string
index: 5
Expand Down
51 changes: 41 additions & 10 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ type NebulaClientSettings struct {
}

type Prop struct {
Name *string `json:"name" yaml:"name"`
Type *string `json:"type" yaml:"type"`
Index *int `json:"index" yaml:"index"`
Nullable bool `json:"nullable" yaml:"nullable"`
NullValue string `json:"nullValue" yaml:"nullValue"`
Name *string `json:"name" yaml:"name"`
Type *string `json:"type" yaml:"type"`
Index *int `json:"index" yaml:"index"`
Nullable bool `json:"nullable" yaml:"nullable"`
NullValue string `json:"nullValue" yaml:"nullValue"`
AlternativeIndices []int `json:"alternativeIndices" yaml:"alternativeIndices"`
DefaultValue *string `json:"defaultValue" yaml:"defaultValue"`
}

type VID struct {
Expand Down Expand Up @@ -832,12 +834,12 @@ func (p *Prop) IsGeographyType() bool {
}

func (p *Prop) FormatValue(record base.Record) (string, error) {
if p.Index != nil && *p.Index >= len(record) {
return "", fmt.Errorf("Prop index %d out range %d of record(%v)", *p.Index, len(record), record)
r, isNull, err := p.getValue(record)
if err != nil {
return "", err
}
r := record[*p.Index]
if p.Nullable && r == p.NullValue {
return dbNULL, nil
if isNull {
return r, err
}
if p.IsStringType() {
return fmt.Sprintf("%q", r), nil
Expand All @@ -856,6 +858,35 @@ func (p *Prop) FormatValue(record base.Record) (string, error) {
return r, nil
}

func (p *Prop) getValue(record base.Record) (string, bool, error) {
if p.Index != nil && *p.Index >= len(record) {
return "", false, fmt.Errorf("Prop index %d out range %d of record(%v)", *p.Index, len(record), record)
}

r := record[*p.Index]
if !p.Nullable {
return r, false, nil
}

if r != p.NullValue {
return r, false, nil
}

for _, idx := range p.AlternativeIndices {
if idx >= len(record) {
return "", false, fmt.Errorf("Prop index %d out range %d of record(%v)", idx, len(record), record)
}
r = record[idx]
if r != p.NullValue {
return r, false, nil
}
}
if p.DefaultValue != nil {
return *p.DefaultValue, false, nil
}
return dbNULL, true, nil
}

func (p *Prop) String(prefix string) string {
return fmt.Sprintf("%s.%s:%s", prefix, *p.Name, *p.Type)
}
Expand Down
104 changes: 103 additions & 1 deletion pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ func TestPropFormatValue(t *testing.T) {
var (
idx0 = 0
idx1 = 1
vZero = "0"
tBool = "bool"
tInt = "int"
tFloat = "float"
Expand Down Expand Up @@ -898,6 +899,107 @@ func TestPropFormatValue(t *testing.T) {
record: base.Record{""},
want: dbNULL,
},
{
name: "alternative indices 0",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{},
},
record: base.Record{""},
want: dbNULL,
},
{
name: "alternative indices 1 out range",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{1},
},
record: base.Record{""},
wantErrString: "out range",
},
{
name: "alternative indices 1 use index",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{1},
},
record: base.Record{"1"},
want: "1",
},
{
name: "alternative indices 1 null",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{1},
},
record: base.Record{"", ""},
want: dbNULL,
},
{
name: "alternative indices 1 not null",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{2},
},
record: base.Record{"", "1", "2"},
want: "2",
},
{
name: "alternative indices n not null",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{3, 2, 1},
},
record: base.Record{"", "1", "2", ""},
want: "2",
},
{
name: "default value not nullable",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: false,
AlternativeIndices: []int{1},
DefaultValue: &vZero,
},
record: base.Record{"", "1", "2"},
want: "",
},
{
name: "default value nullable",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
DefaultValue: &vZero,
},
record: base.Record{""},
want: "0",
},
{
name: "default value nullable alternative indices",
prop: Prop{
Index: &idx0,
Type: &tInt,
Nullable: true,
AlternativeIndices: []int{1, 2, 3, 4, 5, 6},
DefaultValue: &vZero,
},
record: base.Record{"", "", "", "", "", "", ""},
want: "0",
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
Expand All @@ -908,7 +1010,7 @@ func TestPropFormatValue(t *testing.T) {
ast.Contains(err.Error(), tc.wantErrString)
} else {
ast.NoError(err)
ast.Contains(str, tc.want)
ast.Equal(str, tc.want)
}
})
}
Expand Down

0 comments on commit 398992c

Please sign in to comment.