Skip to content

Commit 3213d84

Browse files
gtopperGal Topper
andauthored
IG-22140, IG-22141: Format key values to match python [integ_0.10] (#654)
Backport of #651. Co-authored-by: Gal Topper <galt@iguazio.com>
1 parent f5d86f5 commit 3213d84

File tree

3 files changed

+152
-21
lines changed

3 files changed

+152
-21
lines changed

backends/kv/writer.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,12 @@ func (a *Appender) Add(frame frames.Frame) error {
363363
}
364364

365365
func (a *Appender) formatKeyName(key interface{}, sortingVal interface{}) string {
366-
var format string
366+
var formattedKey string
367+
formattedKey = valueToKeyString(key)
367368
if sortingVal != nil {
368-
format = fmt.Sprintf("%v.%v", key, sortingVal)
369-
} else {
370-
format = fmt.Sprintf("%v", key)
369+
formattedKey = fmt.Sprintf("%s.%s", formattedKey, valueToKeyString(sortingVal))
371370
}
372-
return format
371+
return formattedKey
373372
}
374373

375374
// update updates rows from a frame
@@ -685,3 +684,28 @@ func valueToTypedExpressionString(value interface{}) string {
685684
return fmt.Sprintf("%v", value)
686685
}
687686
}
687+
688+
func valueToKeyString(value interface{}) string {
689+
switch typedVal := value.(type) {
690+
case string:
691+
return typedVal
692+
case bool:
693+
// Python/storey compatibility by capitalizing
694+
// IG-22141
695+
if typedVal {
696+
return "True"
697+
}
698+
return "False"
699+
case float64, float32:
700+
// Python/storey compatibility by deleting trailing zeros (except one trailing zero after period)
701+
// IG-22140
702+
str := fmt.Sprintf("%f", typedVal)
703+
str = strings.TrimRight(str, "0")
704+
if strings.HasSuffix(str, ".") {
705+
str += "0"
706+
}
707+
return str
708+
default:
709+
return fmt.Sprintf("%v", value)
710+
}
711+
}

test/kv_integration_test.go

Lines changed: 122 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,24 @@ func (kvSuite *KvTestSuite) TestWriteToExistingFolderWithoutSchema() {
180180

181181
}
182182

183+
func (kvSuite *KvTestSuite) generateColumn(columnName string, columnType string, size int) frames.Column {
184+
switch columnType {
185+
case "string":
186+
return StringCol(kvSuite.T(), columnName, size)
187+
case "float":
188+
return FloatCol(kvSuite.T(), columnName, size)
189+
case "bool":
190+
return BoolCol(kvSuite.T(), columnName, size)
191+
case "time":
192+
return TimeCol(kvSuite.T(), columnName, size)
193+
case "int":
194+
return IntCol(kvSuite.T(), columnName, size)
195+
default:
196+
kvSuite.T().Fatalf("type %v not supported", columnType)
197+
return nil // no-op
198+
}
199+
}
200+
183201
func (kvSuite *KvTestSuite) generateSequentialSampleFrameWithTypes(size int, indexName string, columnNames map[string]string) frames.Frame {
184202
var icol frames.Column
185203

@@ -194,21 +212,27 @@ func (kvSuite *KvTestSuite) generateSequentialSampleFrameWithTypes(size int, ind
194212
columns := make([]frames.Column, len(columnNames))
195213
i := 0
196214
for columnName, columnType := range columnNames {
197-
switch columnType {
198-
case "string":
199-
columns[i] = StringCol(kvSuite.T(), columnName, size)
200-
case "float":
201-
columns[i] = FloatCol(kvSuite.T(), columnName, size)
202-
case "bool":
203-
columns[i] = BoolCol(kvSuite.T(), columnName, size)
204-
case "time":
205-
columns[i] = TimeCol(kvSuite.T(), columnName, size)
206-
case "int":
207-
columns[i] = IntCol(kvSuite.T(), columnName, size)
208-
default:
209-
kvSuite.T().Fatalf("type %v not supported", columnType)
210-
}
215+
columns[i] = kvSuite.generateColumn(columnName, columnType, size)
216+
i++
217+
}
211218

219+
frame, err := frames.NewFrame(columns, []frames.Column{icol}, nil)
220+
kvSuite.Require().NoError(err)
221+
222+
return frame
223+
}
224+
225+
func (kvSuite *KvTestSuite) generateSequentialSampleFrameWithTypesV2(size int, indexColumnName string, columnNames map[string]string) frames.Frame {
226+
indexColumnType, ok := columnNames[indexColumnName]
227+
kvSuite.Require().True(ok)
228+
delete(columnNames, indexColumnName)
229+
230+
icol := kvSuite.generateColumn(indexColumnName, indexColumnType, size)
231+
232+
columns := make([]frames.Column, len(columnNames))
233+
i := 0
234+
for columnName, columnType := range columnNames {
235+
columns[i] = kvSuite.generateColumn(columnName, columnType, size)
212236
i++
213237
}
214238

@@ -218,6 +242,90 @@ func (kvSuite *KvTestSuite) generateSequentialSampleFrameWithTypes(size int, ind
218242
return frame
219243
}
220244

245+
// IG-22141
246+
func (kvSuite *KvTestSuite) TestFloatIndexColumn() {
247+
table := fmt.Sprintf("frames_ci/TestFloatIndexColumn%d", time.Now().UnixNano())
248+
249+
columnNames := map[string]string{"idx": "float", "n": "int"}
250+
frame := kvSuite.generateSequentialSampleFrameWithTypesV2(3, "idx", columnNames)
251+
wreq := &frames.WriteRequest{
252+
Backend: kvSuite.backendName,
253+
Table: table,
254+
}
255+
256+
appender, err := kvSuite.client.Write(wreq)
257+
kvSuite.Require().NoError(err)
258+
259+
err = appender.Add(frame)
260+
kvSuite.Require().NoError(err)
261+
262+
err = appender.WaitForComplete(10 * time.Second)
263+
kvSuite.Require().NoError(err)
264+
265+
input := v3io.GetItemsInput{AttributeNames: []string{"__name", "n"}}
266+
267+
iter, err := v3ioutils.NewAsyncItemsCursor(
268+
kvSuite.v3ioContainer, &input, 1,
269+
nil, kvSuite.internalLogger,
270+
0, []string{table + "/"},
271+
"", "")
272+
273+
for iter.Next() {
274+
currentRow := iter.GetItem()
275+
276+
key, _ := currentRow.GetFieldString("__name")
277+
switch key {
278+
case ".#schema":
279+
continue
280+
default:
281+
name := currentRow.GetField("__name").(string)
282+
kvSuite.Require().True(strings.HasSuffix(name, ".0"))
283+
}
284+
}
285+
}
286+
287+
// IG-22140
288+
func (kvSuite *KvTestSuite) TestBoolIndexColumn() {
289+
table := fmt.Sprintf("frames_ci/TestFloatIndexColumn%d", time.Now().UnixNano())
290+
291+
columnNames := map[string]string{"idx": "bool", "n": "int"}
292+
frame := kvSuite.generateSequentialSampleFrameWithTypesV2(1, "idx", columnNames)
293+
wreq := &frames.WriteRequest{
294+
Backend: kvSuite.backendName,
295+
Table: table,
296+
}
297+
298+
appender, err := kvSuite.client.Write(wreq)
299+
kvSuite.Require().NoError(err)
300+
301+
err = appender.Add(frame)
302+
kvSuite.Require().NoError(err)
303+
304+
err = appender.WaitForComplete(10 * time.Second)
305+
kvSuite.Require().NoError(err)
306+
307+
input := v3io.GetItemsInput{AttributeNames: []string{"__name", "n"}}
308+
309+
iter, err := v3ioutils.NewAsyncItemsCursor(
310+
kvSuite.v3ioContainer, &input, 1,
311+
nil, kvSuite.internalLogger,
312+
0, []string{table + "/"},
313+
"", "")
314+
315+
for iter.Next() {
316+
currentRow := iter.GetItem()
317+
318+
key, _ := currentRow.GetFieldString("__name")
319+
switch key {
320+
case ".#schema":
321+
continue
322+
default:
323+
name := currentRow.GetField("__name").(string)
324+
kvSuite.Require().Equal(name, "True")
325+
}
326+
}
327+
}
328+
221329
func (kvSuite *KvTestSuite) TestAll() {
222330
table := fmt.Sprintf("kv_test_all%d", time.Now().UnixNano())
223331

test/test_utils.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ import (
1717
type SuiteCreateFunc = func(frames.Client, v3io.Container, logger.Logger) suite.TestingSuite
1818

1919
func FloatCol(t testing.TB, name string, size int) frames.Column {
20-
random := rand.New(rand.NewSource(time.Now().UnixNano()))
2120
floats := make([]float64, size)
2221
for i := range floats {
23-
floats[i] = random.Float64()
22+
floats[i] = float64(i)
2423
}
2524

2625
col, err := frames.NewSliceColumn(name, floats)

0 commit comments

Comments
 (0)