arrow/flight/flightsql/column_metadata.go (164 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 flightsql
import (
"strconv"
"github.com/apache/arrow-go/v18/arrow"
)
const (
boolTrueStr = "1"
boolFalseStr = "0"
)
func boolToStr(v bool) string {
if v {
return boolTrueStr
}
return boolFalseStr
}
func strToBool(v string) bool {
return v == boolTrueStr
}
// Metadata Key Constants
const (
CatalogNameKey = "ARROW:FLIGHT:SQL:CATALOG_NAME"
SchemaNameKey = "ARROW:FLIGHT:SQL:SCHEMA_NAME"
TableNameKey = "ARROW:FLIGHT:SQL:TABLE_NAME"
TypeNameKey = "ARROW:FLIGHT:SQL:TYPE_NAME"
PrecisionKey = "ARROW:FLIGHT:SQL:PRECISION"
ScaleKey = "ARROW:FLIGHT:SQL:SCALE"
IsAutoIncrementKey = "ARROW:FLIGHT:SQL:IS_AUTO_INCREMENT"
IsCaseSensitiveKey = "ARROW:FLIGHT:SQL:IS_CASE_SENSITIVE"
IsReadOnlyKey = "ARROW:FLIGHT:SQL:IS_READ_ONLY"
IsSearchableKey = "ARROW:FLIGHT:SQL:IS_SEARCHABLE"
RemarksKey = "ARROW:FLIGHT:SQL:REMARKS"
)
// ColumnMetadata is a helper object for managing and querying the
// standard SQL Column metadata using the expected Metadata Keys.
// It can be created by just Wrapping an existing *arrow.Metadata.
//
// Each of the methods return a value and a boolean indicating if it
// was set in the metadata or not.
type ColumnMetadata struct {
Data *arrow.Metadata
}
func (c *ColumnMetadata) findStrVal(key string) (string, bool) {
idx := c.Data.FindKey(key)
if idx == -1 {
return "", false
}
return c.Data.Values()[idx], true
}
func (c *ColumnMetadata) findBoolVal(key string) (bool, bool) {
idx := c.Data.FindKey(key)
if idx == -1 {
return false, false
}
return strToBool(c.Data.Values()[idx]), true
}
func (c *ColumnMetadata) findInt32Val(key string) (int32, bool) {
idx := c.Data.FindKey(key)
if idx == -1 {
return 0, false
}
v, err := strconv.ParseInt(c.Data.Values()[idx], 10, 32)
if err != nil {
return 0, false
}
return int32(v), true
}
func (c *ColumnMetadata) CatalogName() (string, bool) {
return c.findStrVal(CatalogNameKey)
}
func (c *ColumnMetadata) SchemaName() (string, bool) {
return c.findStrVal(SchemaNameKey)
}
func (c *ColumnMetadata) TableName() (string, bool) {
return c.findStrVal(TableNameKey)
}
func (c *ColumnMetadata) TypeName() (string, bool) {
return c.findStrVal(TypeNameKey)
}
func (c *ColumnMetadata) Precision() (int32, bool) {
return c.findInt32Val(PrecisionKey)
}
func (c *ColumnMetadata) Scale() (int32, bool) {
return c.findInt32Val(ScaleKey)
}
func (c *ColumnMetadata) IsAutoIncrement() (bool, bool) {
return c.findBoolVal(IsAutoIncrementKey)
}
func (c *ColumnMetadata) IsCaseSensitive() (bool, bool) {
return c.findBoolVal(IsCaseSensitiveKey)
}
func (c *ColumnMetadata) IsReadOnly() (bool, bool) {
return c.findBoolVal(IsReadOnlyKey)
}
func (c *ColumnMetadata) IsSearchable() (bool, bool) {
return c.findBoolVal(IsSearchableKey)
}
func (c *ColumnMetadata) Remarks() (string, bool) {
return c.findStrVal(RemarksKey)
}
// ColumnMetadataBuilder is a convenience builder for constructing
// sql column metadata using the expected standard metadata keys.
// All methods return the builder itself so it can be chained
// to easily construct a final metadata object.
type ColumnMetadataBuilder struct {
keys, vals []string
}
func NewColumnMetadataBuilder() *ColumnMetadataBuilder {
return &ColumnMetadataBuilder{make([]string, 0), make([]string, 0)}
}
func (c *ColumnMetadataBuilder) Clear() {
c.keys = c.keys[:0]
c.vals = c.vals[:0]
}
func (c *ColumnMetadataBuilder) Build() ColumnMetadata {
md := c.Metadata()
return ColumnMetadata{&md}
}
func (c *ColumnMetadataBuilder) Metadata() arrow.Metadata {
return arrow.NewMetadata(c.keys, c.vals)
}
func (c *ColumnMetadataBuilder) CatalogName(name string) *ColumnMetadataBuilder {
c.keys = append(c.keys, CatalogNameKey)
c.vals = append(c.vals, name)
return c
}
func (c *ColumnMetadataBuilder) SchemaName(name string) *ColumnMetadataBuilder {
c.keys = append(c.keys, SchemaNameKey)
c.vals = append(c.vals, name)
return c
}
func (c *ColumnMetadataBuilder) TableName(name string) *ColumnMetadataBuilder {
c.keys = append(c.keys, TableNameKey)
c.vals = append(c.vals, name)
return c
}
func (c *ColumnMetadataBuilder) TypeName(name string) *ColumnMetadataBuilder {
c.keys = append(c.keys, TypeNameKey)
c.vals = append(c.vals, name)
return c
}
func (c *ColumnMetadataBuilder) Precision(prec int32) *ColumnMetadataBuilder {
c.keys = append(c.keys, PrecisionKey)
c.vals = append(c.vals, strconv.Itoa(int(prec)))
return c
}
func (c *ColumnMetadataBuilder) Scale(prec int32) *ColumnMetadataBuilder {
c.keys = append(c.keys, ScaleKey)
c.vals = append(c.vals, strconv.Itoa(int(prec)))
return c
}
func (c *ColumnMetadataBuilder) IsAutoIncrement(v bool) *ColumnMetadataBuilder {
c.keys = append(c.keys, IsAutoIncrementKey)
c.vals = append(c.vals, boolToStr(v))
return c
}
func (c *ColumnMetadataBuilder) IsCaseSensitive(v bool) *ColumnMetadataBuilder {
c.keys = append(c.keys, IsCaseSensitiveKey)
c.vals = append(c.vals, boolToStr(v))
return c
}
func (c *ColumnMetadataBuilder) IsReadOnly(v bool) *ColumnMetadataBuilder {
c.keys = append(c.keys, IsReadOnlyKey)
c.vals = append(c.vals, boolToStr(v))
return c
}
func (c *ColumnMetadataBuilder) IsSearchable(v bool) *ColumnMetadataBuilder {
c.keys = append(c.keys, IsSearchableKey)
c.vals = append(c.vals, boolToStr(v))
return c
}
func (c *ColumnMetadataBuilder) Remarks(remarks string) *ColumnMetadataBuilder {
c.keys = append(c.keys, RemarksKey)
c.vals = append(c.vals, remarks)
return c
}