2021-04-18 15:41:13 -04:00
|
|
|
// Copyright (c) 2015-2021 MinIO, Inc.
|
|
|
|
//
|
|
|
|
// This file is part of MinIO Object Storage stack
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2019-01-08 19:53:04 -05:00
|
|
|
|
|
|
|
package sql
|
|
|
|
|
2019-08-31 03:07:40 -04:00
|
|
|
import (
|
2020-02-13 17:03:52 -05:00
|
|
|
"fmt"
|
2019-08-31 03:07:40 -04:00
|
|
|
"io"
|
|
|
|
|
2020-02-13 17:03:52 -05:00
|
|
|
"github.com/minio/simdjson-go"
|
2019-08-31 03:07:40 -04:00
|
|
|
)
|
2019-03-09 11:13:37 -05:00
|
|
|
|
|
|
|
// SelectObjectFormat specifies the format of the underlying data
|
|
|
|
type SelectObjectFormat int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// SelectFmtUnknown - unknown format (default value)
|
|
|
|
SelectFmtUnknown SelectObjectFormat = iota
|
|
|
|
// SelectFmtCSV - CSV format
|
|
|
|
SelectFmtCSV
|
|
|
|
// SelectFmtJSON - JSON format
|
|
|
|
SelectFmtJSON
|
2020-02-13 17:03:52 -05:00
|
|
|
// SelectFmtSIMDJSON - SIMD JSON format
|
|
|
|
SelectFmtSIMDJSON
|
2019-03-09 11:13:37 -05:00
|
|
|
// SelectFmtParquet - Parquet format
|
|
|
|
SelectFmtParquet
|
|
|
|
)
|
|
|
|
|
2020-04-01 18:39:34 -04:00
|
|
|
// WriteCSVOpts - encapsulates options for Select CSV output
|
|
|
|
type WriteCSVOpts struct {
|
|
|
|
FieldDelimiter rune
|
|
|
|
Quote rune
|
|
|
|
QuoteEscape rune
|
|
|
|
AlwaysQuote bool
|
|
|
|
}
|
|
|
|
|
2019-01-08 19:53:04 -05:00
|
|
|
// Record - is a type containing columns and their values.
|
|
|
|
type Record interface {
|
|
|
|
Get(name string) (*Value, error)
|
2020-02-13 17:03:52 -05:00
|
|
|
|
|
|
|
// Set a value.
|
|
|
|
// Can return a different record type.
|
|
|
|
Set(name string, value *Value) (Record, error)
|
2020-04-01 18:39:34 -04:00
|
|
|
WriteCSV(writer io.Writer, opts WriteCSVOpts) error
|
2019-08-31 03:07:40 -04:00
|
|
|
WriteJSON(writer io.Writer) error
|
2019-03-09 11:13:37 -05:00
|
|
|
|
2019-09-27 15:33:14 -04:00
|
|
|
// Clone the record and if possible use the destination provided.
|
|
|
|
Clone(dst Record) Record
|
2019-09-16 20:26:27 -04:00
|
|
|
Reset()
|
|
|
|
|
2019-03-09 11:13:37 -05:00
|
|
|
// Returns underlying representation
|
|
|
|
Raw() (SelectObjectFormat, interface{})
|
|
|
|
|
|
|
|
// Replaces the underlying data
|
2020-02-13 17:03:52 -05:00
|
|
|
Replace(k interface{}) error
|
|
|
|
}
|
|
|
|
|
|
|
|
// IterToValue converts a simdjson Iter to its underlying value.
|
|
|
|
// Objects are returned as simdjson.Object
|
|
|
|
// Arrays are returned as []interface{} with parsed values.
|
|
|
|
func IterToValue(iter simdjson.Iter) (interface{}, error) {
|
|
|
|
switch iter.Type() {
|
|
|
|
case simdjson.TypeString:
|
|
|
|
v, err := iter.String()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return v, nil
|
|
|
|
case simdjson.TypeFloat:
|
|
|
|
v, err := iter.Float()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return v, nil
|
|
|
|
case simdjson.TypeInt:
|
|
|
|
v, err := iter.Int()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return v, nil
|
|
|
|
case simdjson.TypeUint:
|
|
|
|
v, err := iter.Int()
|
|
|
|
if err != nil {
|
|
|
|
// Can't fit into int, convert to float.
|
|
|
|
v, err := iter.Float()
|
|
|
|
return v, err
|
|
|
|
}
|
|
|
|
return v, nil
|
|
|
|
case simdjson.TypeBool:
|
|
|
|
v, err := iter.Bool()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return v, nil
|
|
|
|
case simdjson.TypeObject:
|
|
|
|
obj, err := iter.Object(nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return *obj, err
|
|
|
|
case simdjson.TypeArray:
|
|
|
|
arr, err := iter.Array(nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
iter := arr.Iter()
|
|
|
|
var dst []interface{}
|
|
|
|
var next simdjson.Iter
|
|
|
|
for {
|
|
|
|
typ, err := iter.AdvanceIter(&next)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if typ == simdjson.TypeNone {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
v, err := IterToValue(next)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
dst = append(dst, v)
|
|
|
|
}
|
|
|
|
return dst, err
|
|
|
|
case simdjson.TypeNull:
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("IterToValue: unknown JSON type: %s", iter.Type().String())
|
2019-01-08 19:53:04 -05:00
|
|
|
}
|