diff --git a/duck/duckdb.go b/duck/duckdb.go index e4cde58..cdaaef9 100644 --- a/duck/duckdb.go +++ b/duck/duckdb.go @@ -12,6 +12,7 @@ import ( sdk "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data/framestruct" "github.com/hairyhenderson/go-which" + "github.com/iancoleman/orderedmap" "github.com/scottlepp/go-duck/duck/data" ) @@ -181,12 +182,33 @@ func resultsToFrame(name string, res string, f *sdk.Frame, frames []*sdk.Frame) } converters := data.Converters(frames) resultsFrame, err := framestruct.ToDataFrame(name, results, converters...) + if err != nil { logger.Error("error converting results to frame", "error", err) return err } - f.Fields = resultsFrame.Fields + // Order the fields in the same order as the source frame: + // Build a slice of ordered keys + + var orderedKeys []string + var temp []orderedmap.OrderedMap + err = json.Unmarshal([]byte(res), &temp) + if err == nil { + orderedKeys = temp[0].Keys() + } + + // Create a map of column names to indexes + columnIndex := make(map[string]int) + for i, field := range resultsFrame.Fields { + columnIndex[field.Name] = i + } + // Add columns to the DataFrame + for _, key := range orderedKeys { + i := columnIndex[key] + f.Fields = append(f.Fields, resultsFrame.Fields[i]) + } + f.Name = resultsFrame.Name f.Meta = resultsFrame.Meta f.RefID = resultsFrame.RefID diff --git a/duck/duckdb_test.go b/duck/duckdb_test.go index 016ef3c..f173138 100644 --- a/duck/duckdb_test.go +++ b/duck/duckdb_test.go @@ -149,6 +149,33 @@ func TestQueryFrameIntoFrame(t *testing.T) { fmt.Printf("GOT: %s", txt) } +func TestQueryFrameIntoFrameMultipleColumns(t *testing.T) { + db := NewInMemoryDB() + + frame := data.NewFrame( + "A", + data.NewField("Z State", nil, []string{"Alaska"}), + data.NewField("Y Lat", nil, []string{"61"}), + data.NewField("X Lng", nil, []string{"32"}), + ) + frame.RefID = "A" + + frames := []*data.Frame{frame} + + model := &data.Frame{} + err := db.QueryFramesInto("B", "select * from A", frames, model) + assert.Nil(t, err) + + assert.Equal(t, "Z State", model.Fields[0].Name) + assert.Equal(t, "Y Lat", model.Fields[1].Name) + assert.Equal(t, "X Lng", model.Fields[2].Name) + + txt, err := model.StringTable(-1, -1) + assert.Nil(t, err) + + fmt.Printf("GOT: %s", txt) +} + func TestMultiFrame(t *testing.T) { db := NewInMemoryDB() diff --git a/go.mod b/go.mod index de4697f..a3e491d 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/apache/arrow/go/v15 v15.0.2 github.com/grafana/grafana-plugin-sdk-go v0.234.0 github.com/hairyhenderson/go-which v0.2.0 + github.com/iancoleman/orderedmap v0.3.0 github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 1d2c4b1..4f9d23c 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,8 @@ github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOs github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= +github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=