odps/data/array.go (127 lines of code) (raw):
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package data
import (
"strings"
"github.com/pkg/errors"
"github.com/aliyun/aliyun-odps-go-sdk/odps/datatype"
)
type Array struct {
typ datatype.ArrayType
data []Data
Valid bool
}
func NewArray() *Array {
return &Array{
typ: datatype.ArrayType{},
data: make([]Data, 0),
}
}
func NewArrayWithType(typ datatype.ArrayType) *Array {
return &Array{
typ: typ,
data: make([]Data, 0),
Valid: true,
}
}
func (a Array) Type() datatype.DataType {
return a.typ
}
func (a Array) String() string {
n := len(a.data)
if n == 0 {
return "array()"
}
sb := strings.Builder{}
sb.WriteString("array(")
for i, d := range a.data {
sb.WriteString(d.String())
if i+1 < n {
sb.WriteString(", ")
}
}
sb.WriteString(")")
return sb.String()
}
func (a Array) Sql() string {
n := len(a.data)
if n == 0 {
return "array()"
}
sb := strings.Builder{}
sb.WriteString("array(")
for i, d := range a.data {
if d != nil {
sb.WriteString(d.Sql())
} else {
sb.WriteString("null")
}
if i+1 < n {
sb.WriteString(", ")
}
}
sb.WriteString(")")
return sb.String()
}
func (a *Array) Scan(value interface{}) error {
return errors.WithStack(tryConvertType(value, a))
}
func (a *Array) SetType(typ datatype.ArrayType) {
a.typ = typ
}
func (a *Array) UnSafeAppend(data ...Data) {
a.data = append(a.data, data...)
}
func (a *Array) Append(data ...interface{}) error {
for _, d := range data {
o, err := TryConvertGoToOdpsData(d)
if err != nil {
return errors.WithStack(err)
}
a.data = append(a.data, o)
}
return nil
}
func (a *Array) SafeAppend(data ...interface{}) error {
if a.typ.ElementType == nil {
return errors.New("element type of Array has not be set")
}
for _, d := range data {
o, err := TryConvertGoToOdpsData(d)
if err != nil {
return errors.WithStack(err)
}
if !datatype.IsTypeEqual(o.Type(), a.typ.ElementType) {
return errors.Errorf("expect %s element type for array, but get %s", a.typ.ElementType, o.Type())
}
a.data = append(a.data, o)
}
return nil
}
func (a *Array) Len() int {
return len(a.data)
}
func (a *Array) Index(i int) Data {
return a.data[i]
}
func (a *Array) TypeInfer() (datatype.DataType, error) {
if len(a.data) == 0 {
return nil, errors.Errorf("cannot infer type for empty array")
}
et := a.data[0].Type()
for _, e := range a.data[1:] {
if !datatype.IsTypeEqual(e.Type(), et) {
return nil, errors.Errorf("element type is not the same in array, find %s, %s types", et, e.Type())
}
}
return datatype.NewArrayType(et), nil
}
func ArrayFromSlice(data ...interface{}) (*Array, error) {
a := NewArray()
err := a.Append(data...)
if err != nil {
return nil, errors.WithStack(err)
}
return a, nil
}
func (a *Array) ToSlice() []Data {
return a.data
}