mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			127 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| //go:build !arm
 | |
| 
 | |
| package sql
 | |
| 
 | |
| import (
 | |
| 	"io"
 | |
| 	"strings"
 | |
| 
 | |
| 	mysql "github.com/dolthub/go-mysql-server/sql"
 | |
| 	"github.com/grafana/grafana-plugin-sdk-go/data"
 | |
| )
 | |
| 
 | |
| // FrameTable fulfills the mysql.Table interface for a data.Frame.
 | |
| type FrameTable struct {
 | |
| 	Frame  *data.Frame
 | |
| 	schema mysql.Schema
 | |
| }
 | |
| 
 | |
| // Name implements the sql.Nameable interface
 | |
| func (ft *FrameTable) Name() string {
 | |
| 	return ft.Frame.RefID
 | |
| }
 | |
| 
 | |
| // String implements the fmt.Stringer interface
 | |
| func (ft *FrameTable) String() string {
 | |
| 	return ft.Name()
 | |
| }
 | |
| 
 | |
| func schemaFromFrame(frame *data.Frame) mysql.Schema {
 | |
| 	schema := make(mysql.Schema, len(frame.Fields))
 | |
| 
 | |
| 	for i, field := range frame.Fields {
 | |
| 		schema[i] = &mysql.Column{
 | |
| 			Name:     field.Name,
 | |
| 			Type:     convertDataType(field.Type()),
 | |
| 			Nullable: field.Type().Nullable(),
 | |
| 			Source:   strings.ToLower(frame.RefID),
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return schema
 | |
| }
 | |
| 
 | |
| // Schema implements the mysql.Table interface
 | |
| func (ft *FrameTable) Schema() mysql.Schema {
 | |
| 	if ft.schema == nil {
 | |
| 		ft.schema = schemaFromFrame(ft.Frame)
 | |
| 	}
 | |
| 	return ft.schema
 | |
| }
 | |
| 
 | |
| // Collation implements the mysql.Table interface
 | |
| func (ft *FrameTable) Collation() mysql.CollationID {
 | |
| 	return mysql.Collation_Unspecified
 | |
| }
 | |
| 
 | |
| // Partitions implements the mysql.Table interface
 | |
| func (ft *FrameTable) Partitions(ctx *mysql.Context) (mysql.PartitionIter, error) {
 | |
| 	return &noopPartitionIter{}, nil
 | |
| }
 | |
| 
 | |
| // PartitionRows implements the mysql.Table interface
 | |
| func (ft *FrameTable) PartitionRows(ctx *mysql.Context, _ mysql.Partition) (mysql.RowIter, error) {
 | |
| 	return &rowIter{ft: ft, row: 0}, nil
 | |
| }
 | |
| 
 | |
| type rowIter struct {
 | |
| 	ft  *FrameTable
 | |
| 	row int
 | |
| }
 | |
| 
 | |
| func (ri *rowIter) Next(_ *mysql.Context) (mysql.Row, error) {
 | |
| 	// We assume each field in the Frame has the same number of rows.
 | |
| 	numRows := 0
 | |
| 	if len(ri.ft.Frame.Fields) > 0 {
 | |
| 		numRows = ri.ft.Frame.Fields[0].Len()
 | |
| 	}
 | |
| 
 | |
| 	// If we've already exhausted all rows, return EOF
 | |
| 	if ri.row >= numRows {
 | |
| 		return nil, io.EOF
 | |
| 	}
 | |
| 
 | |
| 	// Construct a Row (which is []interface{} under the hood) by pulling
 | |
| 	// the value from each column at the current row index.
 | |
| 	row := make(mysql.Row, len(ri.ft.Frame.Fields))
 | |
| 	for colIndex, field := range ri.ft.Frame.Fields {
 | |
| 		if nilAt(*field, ri.row) {
 | |
| 			continue
 | |
| 		}
 | |
| 		row[colIndex], _ = field.ConcreteAt(ri.row)
 | |
| 	}
 | |
| 
 | |
| 	ri.row++
 | |
| 	return row, nil
 | |
| }
 | |
| 
 | |
| // Close implements the mysql.RowIter interface.
 | |
| // In this no-op example, there isn't anything to do here.
 | |
| func (ri *rowIter) Close(*mysql.Context) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type noopPartitionIter struct {
 | |
| 	done bool
 | |
| }
 | |
| 
 | |
| func (i *noopPartitionIter) Next(*mysql.Context) (mysql.Partition, error) {
 | |
| 	if !i.done {
 | |
| 		i.done = true
 | |
| 		return noopParition, nil
 | |
| 	}
 | |
| 	return nil, io.EOF
 | |
| }
 | |
| 
 | |
| func (i *noopPartitionIter) Close(*mysql.Context) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| var noopParition = partition(nil)
 | |
| 
 | |
| type partition []byte
 | |
| 
 | |
| func (p partition) Key() []byte {
 | |
| 	return p
 | |
| }
 |