github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/s3select/sql/record.go (about)

     1  // Copyright (c) 2015-2021 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package sql
    19  
    20  import (
    21  	"fmt"
    22  	"io"
    23  
    24  	"github.com/minio/simdjson-go"
    25  )
    26  
    27  // SelectObjectFormat specifies the format of the underlying data
    28  type SelectObjectFormat int
    29  
    30  const (
    31  	// SelectFmtUnknown - unknown format (default value)
    32  	SelectFmtUnknown SelectObjectFormat = iota
    33  	// SelectFmtCSV - CSV format
    34  	SelectFmtCSV
    35  	// SelectFmtJSON - JSON format
    36  	SelectFmtJSON
    37  	// SelectFmtSIMDJSON - SIMD JSON format
    38  	SelectFmtSIMDJSON
    39  	// SelectFmtParquet - Parquet format
    40  	SelectFmtParquet
    41  )
    42  
    43  // WriteCSVOpts - encapsulates options for Select CSV output
    44  type WriteCSVOpts struct {
    45  	FieldDelimiter rune
    46  	Quote          rune
    47  	QuoteEscape    rune
    48  	AlwaysQuote    bool
    49  }
    50  
    51  // Record - is a type containing columns and their values.
    52  type Record interface {
    53  	Get(name string) (*Value, error)
    54  
    55  	// Set a value.
    56  	// Can return a different record type.
    57  	Set(name string, value *Value) (Record, error)
    58  	WriteCSV(writer io.Writer, opts WriteCSVOpts) error
    59  	WriteJSON(writer io.Writer) error
    60  
    61  	// Clone the record and if possible use the destination provided.
    62  	Clone(dst Record) Record
    63  	Reset()
    64  
    65  	// Returns underlying representation
    66  	Raw() (SelectObjectFormat, interface{})
    67  
    68  	// Replaces the underlying data
    69  	Replace(k interface{}) error
    70  }
    71  
    72  // IterToValue converts a simdjson Iter to its underlying value.
    73  // Objects are returned as simdjson.Object
    74  // Arrays are returned as []interface{} with parsed values.
    75  func IterToValue(iter simdjson.Iter) (interface{}, error) {
    76  	switch iter.Type() {
    77  	case simdjson.TypeString:
    78  		v, err := iter.String()
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  		return v, nil
    83  	case simdjson.TypeFloat:
    84  		v, err := iter.Float()
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  		return v, nil
    89  	case simdjson.TypeInt:
    90  		v, err := iter.Int()
    91  		if err != nil {
    92  			return nil, err
    93  		}
    94  		return v, nil
    95  	case simdjson.TypeUint:
    96  		v, err := iter.Int()
    97  		if err != nil {
    98  			// Can't fit into int, convert to float.
    99  			v, err := iter.Float()
   100  			return v, err
   101  		}
   102  		return v, nil
   103  	case simdjson.TypeBool:
   104  		v, err := iter.Bool()
   105  		if err != nil {
   106  			return nil, err
   107  		}
   108  		return v, nil
   109  	case simdjson.TypeObject:
   110  		obj, err := iter.Object(nil)
   111  		if err != nil {
   112  			return nil, err
   113  		}
   114  		return *obj, err
   115  	case simdjson.TypeArray:
   116  		arr, err := iter.Array(nil)
   117  		if err != nil {
   118  			return nil, err
   119  		}
   120  		iter := arr.Iter()
   121  		var dst []interface{}
   122  		var next simdjson.Iter
   123  		for {
   124  			typ, err := iter.AdvanceIter(&next)
   125  			if err != nil {
   126  				return nil, err
   127  			}
   128  			if typ == simdjson.TypeNone {
   129  				break
   130  			}
   131  			v, err := IterToValue(next)
   132  			if err != nil {
   133  				return nil, err
   134  			}
   135  			dst = append(dst, v)
   136  		}
   137  		return dst, err
   138  	case simdjson.TypeNull:
   139  		return nil, nil
   140  	}
   141  	return nil, fmt.Errorf("IterToValue: unknown JSON type: %s", iter.Type().String())
   142  }