sqlutil

package
v0.44.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2020 License: Apache-2.0 Imports: 4 Imported by: 41

Documentation

Overview

Package sqlutil provides helpers for scanning database/sql responses into a data.Frame.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func FrameFromRows

func FrameFromRows(rows *sql.Rows, converters ...StringConverter) (*data.Frame, map[int]StringConverter, error)

FrameFromRows returns a new Frame populated with the data from rows. The Field Vector types will be Vectors of pointer types, []*T, if the SQL column is nullable or if the nullable property is unknown. Otherwise, they will be []T types.

Fields will be named to match name of the SQL columns and the SQL column names must be unique (https://github.com/grafana/grafana-plugin-sdk-go/issues/59).

All the types must be supported by the Frame or a StringConverter will be created and the resulting Field Vector type will be of type []*string.

The StringConverter's ConversionFunc will be applied to matching rows if it is not nil. Additionally, if the StringConverter's Replacer is not nil, the replacement will be performed. A map of Field/Column index to the corresponding StringConverter is returned so what conversions were done can be inspected.

Example
package main

import (
	"database/sql"

	"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
)

func main() {
	aQuery := "SELECT * FROM GoodData"
	db, err := sql.Open("fancySql", "fancysql://user:pass@localhost:1433")
	if err != nil {
		// return err
	}

	defer db.Close()

	rows, err := db.Query(aQuery)
	if err != nil {
		// return err
	}
	defer rows.Close()

	frame, mappings, err := sqlutil.FrameFromRows(rows)
	if err != nil {
		// return err
	}
	_, _ = frame, mappings
}
Output:

func Replace

func Replace(frame *data.Frame, fieldIdx int, replacer *StringFieldReplacer) error

Replace will replace a *string Vector of the specified Field's index using the StringFieldReplacer.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/grafana/grafana-plugin-sdk-go/data"
	"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
)

func main() {
	i := 0
	getString := func() *string {
		i++
		s := strconv.Itoa(i)
		return &s
	}

	frame := data.NewFrame("Before",
		data.NewField("string", nil, []*string{getString(), getString()}))

	fmt.Println(frame.String()) // Before

	intReplacer := &sqlutil.StringFieldReplacer{
		OutputFieldType: data.FieldTypeNullableInt64,
		ReplaceFunc: func(in *string) (interface{}, error) {
			if in == nil {
				return nil, nil
			}
			v, err := strconv.ParseInt(*in, 10, 64)
			if err != nil {
				return nil, err
			}
			return &v, nil
		},
	}

	err := sqlutil.Replace(frame, 0, intReplacer)
	if err != nil {
		// return err
	}

	frame.Name = "After"
	fmt.Println(frame.String()) // After
}
Output:

Name: Before
Dimensions: 1 Fields by 2 Rows
+-----------------+
| Name: string    |
| Labels:         |
| Type: []*string |
+-----------------+
| 1               |
| 2               |
+-----------------+

Name: After
Dimensions: 1 Fields by 2 Rows
+----------------+
| Name: string   |
| Labels:        |
| Type: []*int64 |
+----------------+
| 1              |
| 2              |
+----------------+

Types

type StringConverter

type StringConverter struct {
	// Name is an optional property that can be used to identify a converter
	Name          string
	InputScanKind reflect.Kind // reflect.Type might better or worse option?
	InputTypeName string

	// Conversion func may be nil to do no additional operations on the string conversion.
	ConversionFunc func(in *string) (*string, error)

	// If the Replacer is not nil, the replacement will be performed.
	Replacer *StringFieldReplacer
}

StringConverter can be used to store types not supported by a Frame into a *string. When scanning, if a SQL's row's InputScanType's Kind and InputScanKind match that returned by the sql response, then the conversion func will be run on the row.

Example
package main

import (
	"reflect"
	"strconv"

	"github.com/grafana/grafana-plugin-sdk-go/data"
	"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
)

func main() {
	_ = sqlutil.StringConverter{
		Name:          "BIGINT to *int64",
		InputScanKind: reflect.Struct,
		InputTypeName: "BIGINT",
		Replacer: &sqlutil.StringFieldReplacer{
			OutputFieldType: data.FieldTypeNullableInt64,
			ReplaceFunc: func(in *string) (interface{}, error) {
				if in == nil {
					return nil, nil
				}
				v, err := strconv.ParseInt(*in, 10, 64)
				if err != nil {
					return nil, err
				}
				return &v, nil
			},
		},
	}
}
Output:

type StringFieldReplacer

type StringFieldReplacer struct {
	OutputFieldType data.FieldType
	ReplaceFunc     func(in *string) (interface{}, error)
}

StringFieldReplacer is used to replace a *string Field in a Frame. The type returned by the ReplaceFunc must match the type of elements of VectorType. Both properties must be non-nil.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL