chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Any is a type that may contain any type.
|
||||
var Any = &DoltgresType{
|
||||
ID: toInternal("any"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("any_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("any_out", toInternal("any")),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// AnyArray is a pseudo-type that can represent any type
|
||||
// that is an array type that may contain elements of any type.
|
||||
var AnyArray = &DoltgresType{
|
||||
ID: toInternal("anyarray"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("anyarray_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("anyarray_out", toInternal("anyarray")),
|
||||
ReceiveFunc: toFuncID("anyarray_recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("anyarray_send", toInternal("anyarray")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btarraycmp", toInternal("anyarray"), toInternal("anyarray")),
|
||||
SerializationFunc: serializeTypeAnyArray,
|
||||
DeserializationFunc: deserializeTypeAnyArray,
|
||||
}
|
||||
|
||||
// serializeTypeAnyArray handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeAnyArray(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return nil, errors.New("anyarray serialization is not yet implemented")
|
||||
}
|
||||
|
||||
// deserializeTypeAnyArray handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeAnyArray(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
return nil, errors.New("anyarray serialization is not yet implemented")
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// AnyElement is a pseudo-type that can represent any type.
|
||||
var AnyElement = &DoltgresType{
|
||||
ID: toInternal("anyelement"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("anyelement_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("anyelement_out", toInternal("anyelement")),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// AnyEnum is a pseudo-type that can represent any type that is an enum type.
|
||||
var AnyEnum = &DoltgresType{
|
||||
ID: toInternal("anyenum"),
|
||||
TypLength: 4,
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("anyenum_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("anyenum_out", toInternal("anyenum")),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// AnyNonArray is a pseudo-type that can represent any type that isn't an array type.
|
||||
var AnyNonArray = &DoltgresType{
|
||||
ID: toInternal("anynonarray"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("anynonarray_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("anynonarray_out", toInternal("anynonarray")),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// CreateArrayTypeFromBaseType create array type from given type. This also sets the `Array` on the given base type if
|
||||
// it has not already been set.
|
||||
func CreateArrayTypeFromBaseType(baseType *DoltgresType) *DoltgresType {
|
||||
align := TypeAlignment_Int
|
||||
if baseType.Align == TypeAlignment_Double {
|
||||
align = TypeAlignment_Double
|
||||
}
|
||||
var arrayID id.Type
|
||||
if baseType.Array == nil || baseType.Array == internalNullType || baseType.Array.ID == id.NullType {
|
||||
arrayID = id.NewType(baseType.ID.SchemaName(), "_"+baseType.ID.TypeName())
|
||||
} else {
|
||||
arrayID = baseType.Array.ID
|
||||
}
|
||||
arrayType := &DoltgresType{
|
||||
ID: arrayID,
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_ArrayTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("array_subscript_handler", toInternal("internal")),
|
||||
Elem: baseType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("array_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("array_out", toInternal("anyarray")),
|
||||
ReceiveFunc: toFuncID("array_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("array_send", toInternal("anyarray")),
|
||||
ModInFunc: baseType.ModInFunc,
|
||||
ModOutFunc: baseType.ModOutFunc,
|
||||
AnalyzeFunc: toFuncID("array_typanalyze", toInternal("internal")),
|
||||
Align: align,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: baseType.TypCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
InternalName: fmt.Sprintf("%s[]", baseType.Name()), // This will be set to the proper name in ToArrayType
|
||||
attTypMod: baseType.attTypMod, // TODO: check
|
||||
CompareFunc: toFuncID("btarraycmp", toInternal("anyarray"), toInternal("anyarray")),
|
||||
SerializationFunc: serializeTypeArray,
|
||||
DeserializationFunc: deserializeTypeArray,
|
||||
}
|
||||
if baseType.Array == nil || baseType.Array == internalNullType || baseType.Array.ID == id.NullType {
|
||||
baseType.Array = arrayType
|
||||
}
|
||||
return arrayType
|
||||
}
|
||||
|
||||
// serializeTypeArray handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeArray(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return serializeArray(ctx, val.([]any), t.ArrayBaseType())
|
||||
}
|
||||
|
||||
// deserializeTypeArray handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeArray(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
return deserializeArray(ctx, data, t.ArrayBaseType())
|
||||
}
|
||||
|
||||
// deserializeArray serializes an array of given base type.
|
||||
func serializeArray(ctx *sql.Context, vals []any, baseType *DoltgresType) ([]byte, error) {
|
||||
bb := bytes.Buffer{}
|
||||
// Write the element count to a buffer. We're using an array since it's stack-allocated, so no need for pooling.
|
||||
var elementCount [4]byte
|
||||
binary.LittleEndian.PutUint32(elementCount[:], uint32(len(vals)))
|
||||
bb.Write(elementCount[:])
|
||||
// Create an array that contains the offsets for each value. Since we can't update the offset portion of the buffer
|
||||
// as we determine the offsets, we have to track them outside the buffer. We'll overwrite the buffer later with the
|
||||
// correct offsets. The last offset represents the end of the slice, which simplifies the logic for reading elements
|
||||
// using the "current offset to next offset" strategy. We use a byte slice since the buffer only works with byte
|
||||
// slices.
|
||||
offsets := make([]byte, (len(vals)+1)*4)
|
||||
bb.Write(offsets)
|
||||
// The starting offset for the first element is Count(uint32) + (NumberOfElementOffsets * sizeof(uint32))
|
||||
currentOffset := uint32(4 + (len(vals)+1)*4)
|
||||
for i := range vals {
|
||||
// Write the current offset
|
||||
binary.LittleEndian.PutUint32(offsets[i*4:], currentOffset)
|
||||
// Handle serialization of the value
|
||||
// TODO: ARRAYs may be multidimensional, such as ARRAY[[4,2],[6,3]], which isn't accounted for here
|
||||
serializedVal, err := baseType.SerializeValue(ctx, vals[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Handle the nil case and non-nil case
|
||||
if serializedVal == nil {
|
||||
bb.WriteByte(1)
|
||||
currentOffset += 1
|
||||
} else {
|
||||
bb.WriteByte(0)
|
||||
bb.Write(serializedVal)
|
||||
currentOffset += 1 + uint32(len(serializedVal))
|
||||
}
|
||||
}
|
||||
// Write the final offset, which will equal the length of the serialized slice
|
||||
binary.LittleEndian.PutUint32(offsets[len(offsets)-4:], currentOffset)
|
||||
// Get the final output, and write the updated offsets to it
|
||||
outputBytes := bb.Bytes()
|
||||
copy(outputBytes[4:], offsets)
|
||||
return outputBytes, nil
|
||||
}
|
||||
|
||||
// deserializeArray deserializes an array of given base type.
|
||||
func deserializeArray(ctx *sql.Context, data []byte, baseType *DoltgresType) ([]any, error) {
|
||||
// Check for the nil value, then ensure the minimum length of the slice
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(data) < 4 {
|
||||
return nil, errors.Errorf("deserializing non-nil array value has invalid length of %d", len(data))
|
||||
}
|
||||
// Grab the number of elements and construct an output slice of the appropriate size
|
||||
elementCount := binary.LittleEndian.Uint32(data)
|
||||
output := make([]any, elementCount)
|
||||
// Read all elements
|
||||
for i := uint32(0); i < elementCount; i++ {
|
||||
// We read from i+1 to account for the element count at the beginning
|
||||
offset := binary.LittleEndian.Uint32(data[(i+1)*4:])
|
||||
// If the value is null, then we can skip it, since the output slice default initializes all values to nil
|
||||
if data[offset] == 1 {
|
||||
continue
|
||||
}
|
||||
// The element data is everything from the offset to the next offset, excluding the null determinant
|
||||
nextOffset := binary.LittleEndian.Uint32(data[(i+2)*4:])
|
||||
o, err := baseType.DeserializeValue(ctx, data[offset+1:nextOffset])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
output[i] = o
|
||||
}
|
||||
// Returns all read elements
|
||||
return output, nil
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// ErrWrongLengthBit is returned when a value with the incorrect length is inserted into a Bit column.
|
||||
var ErrWrongLengthBit = errors.NewKind(`bit string length %d does not match type bit(%d)`)
|
||||
|
||||
// Bit is a fixed-length bit string.
|
||||
var Bit = &DoltgresType{
|
||||
ID: toInternal("bit"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_BitStringTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("bit_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("bit_out", toInternal("bit")),
|
||||
ReceiveFunc: toFuncID("bit_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("bit_send", toInternal("bit")),
|
||||
ModInFunc: toFuncID("bittypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("bittypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NewCollation("pg_catalog", "default"),
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("bitcmp", toInternal("bit"), toInternal("bit")),
|
||||
SerializationFunc: serializeTypeBit,
|
||||
DeserializationFunc: deserializeTypeBit,
|
||||
}
|
||||
|
||||
// NewBitType returns a Bit type with type modifier set
|
||||
// representing the number of bits in the string.
|
||||
func NewBitType(width int32) (*DoltgresType, error) {
|
||||
if width < 1 {
|
||||
return nil, ErrLengthMustBeAtLeast1.New("bit")
|
||||
} else if width > StringMaxLength {
|
||||
return nil, ErrLengthCannotExceed.New("bit")
|
||||
}
|
||||
newType := *Bit.WithAttTypMod(width)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// serializeTypeBit handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeBit(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
wr := utils.NewWriter(uint64(4 + len(str)))
|
||||
wr.String(str)
|
||||
return wr.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeBit handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeBit(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2025 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// BitArray is the array variant of Bit.
|
||||
var BitArray = CreateArrayTypeFromBaseType(Bit)
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Bool is the bool type.
|
||||
var Bool = &DoltgresType{
|
||||
ID: toInternal("bool"),
|
||||
TypLength: int16(1),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_BooleanTypes,
|
||||
IsPreferred: true,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("boolin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("boolout", toInternal("bool")),
|
||||
ReceiveFunc: toFuncID("boolrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("boolsend", toInternal("bool")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btboolcmp", toInternal("bool"), toInternal("bool")),
|
||||
InternalName: "boolean",
|
||||
SerializationFunc: serializeTypeBool,
|
||||
DeserializationFunc: deserializeTypeBool,
|
||||
}
|
||||
|
||||
// serializeTypeBool handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeBool(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
if val.(bool) {
|
||||
return []byte{1}, nil
|
||||
} else {
|
||||
return []byte{0}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// deserializeTypeBool handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeBool(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return data[0] != 0, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// BoolArray is the array variant of Bool.
|
||||
var BoolArray = CreateArrayTypeFromBaseType(Bool)
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// Bytea is the byte string type.
|
||||
var Bytea = &DoltgresType{
|
||||
ID: toInternal("bytea"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_UserDefinedTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("byteain", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("byteaout", toInternal("bytea")),
|
||||
ReceiveFunc: toFuncID("bytearecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("byteasend", toInternal("bytea")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("byteacmp", toInternal("bytea"), toInternal("bytea")),
|
||||
SerializationFunc: serializeTypeBytea,
|
||||
DeserializationFunc: deserializeTypeBytea,
|
||||
}
|
||||
|
||||
// serializeTypeBytea handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeBytea(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
res, err := sql.UnwrapAny(ctx, val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
str := res.([]byte)
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.ByteSlice(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeBytea handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeBytea(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
reader := utils.NewReader(data)
|
||||
return reader.ByteSlice(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// ByteaArray is the array variant of Bytea.
|
||||
var ByteaArray = CreateArrayTypeFromBaseType(Bytea)
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// BpChar is a char that has an unbounded length.
|
||||
var BpChar = &DoltgresType{
|
||||
ID: toInternal("bpchar"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_StringTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("bpcharin", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("bpcharout", toInternal("bpchar")),
|
||||
ReceiveFunc: toFuncID("bpcharrecv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("bpcharsend", toInternal("bpchar")),
|
||||
ModInFunc: toFuncID("bpchartypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("bpchartypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NewCollation("pg_catalog", "default"),
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("bpcharcmp", toInternal("bpchar"), toInternal("bpchar")),
|
||||
SerializationFunc: serializeTypeBpChar,
|
||||
DeserializationFunc: deserializeTypeBpChar,
|
||||
}
|
||||
|
||||
// NewCharType returns BpChar type with typmod set.
|
||||
func NewCharType(length int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypModFromCharLength("char", length)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *BpChar.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// serializeTypeBpChar handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeBpChar(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeBpChar handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeBpChar(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// BpCharArray is the array variant of BpChar.
|
||||
var BpCharArray = CreateArrayTypeFromBaseType(BpChar)
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// NewCompositeType creates new instance of composite DoltgresType.
|
||||
func NewCompositeType(_ context.Context, relID id.Id, arrayType *DoltgresType, typeID id.Type, attrs []CompositeAttribute) *DoltgresType {
|
||||
if arrayType == nil {
|
||||
arrayType = internalNullType
|
||||
}
|
||||
return &DoltgresType{
|
||||
ID: typeID,
|
||||
TypLength: -1,
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Composite,
|
||||
TypCategory: TypeCategory_CompositeTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: relID,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: arrayType,
|
||||
InputFunc: toFuncID("record_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("record_out", toInternal("record")),
|
||||
ReceiveFunc: toFuncID("record_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("record_send", toInternal("record")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btrecordcmp", toInternal("record"), toInternal("record")),
|
||||
CompositeAttrs: attrs,
|
||||
SerializationFunc: serializeTypeRecord,
|
||||
DeserializationFunc: deserializeTypeRecord,
|
||||
}
|
||||
}
|
||||
|
||||
// CompositeAttribute represents a composite type attribute.
|
||||
// This is a partial pg_attribute row entry.
|
||||
type CompositeAttribute struct {
|
||||
RelID id.Id // ID of the relation it belongs to
|
||||
Name string
|
||||
Type *DoltgresType // ID of DoltgresType
|
||||
Num int16 // 1-based number of the column in relation
|
||||
Collation string
|
||||
}
|
||||
|
||||
// NewCompositeAttribute creates new instance of composite type attribute. `num` is 1-based rather than 0-based.
|
||||
func NewCompositeAttribute(ctx *sql.Context, relID id.Id, name string, typ *DoltgresType, num int16, collation string) CompositeAttribute {
|
||||
return CompositeAttribute{
|
||||
RelID: relID,
|
||||
Name: name,
|
||||
Type: typ,
|
||||
Num: num,
|
||||
Collation: collation,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Cstring is the cstring type.
|
||||
var Cstring = &DoltgresType{
|
||||
ID: toInternal("cstring"),
|
||||
TypLength: int16(-2),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("cstring_in", toInternal("cstring")), // TODO: implement these functions
|
||||
OutputFunc: toFuncID("cstring_out", toInternal("cstring")),
|
||||
ReceiveFunc: toFuncID("cstring_recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("cstring_send", toInternal("cstring")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: nil,
|
||||
DeserializationFunc: nil,
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// CstringArray is the cstring type.
|
||||
var CstringArray = CreateArrayTypeFromBaseType(Cstring)
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Date is the day, month, and year.
|
||||
var Date = &DoltgresType{
|
||||
ID: toInternal("date"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_DateTimeTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("date_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("date_out", toInternal("date")),
|
||||
ReceiveFunc: toFuncID("date_recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("date_send", toInternal("date")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("date_cmp", toInternal("date"), toInternal("date")),
|
||||
SerializationFunc: serializeTypeDate,
|
||||
DeserializationFunc: deserializeTypeDate,
|
||||
}
|
||||
|
||||
// serializeTypeDate handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeDate(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return val.(time.Time).MarshalBinary()
|
||||
}
|
||||
|
||||
// deserializeTypeDate handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeDate(ctx *sql.Context, _ *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
t := time.Time{}
|
||||
if err := t.UnmarshalBinary(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// DateArray is the day, month, and year array.
|
||||
var DateArray = CreateArrayTypeFromBaseType(Date)
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
)
|
||||
|
||||
// ErrDomainDoesNotAllowNullValues is returned when given value is NULL and a domain is non-nullable.
|
||||
var ErrDomainDoesNotAllowNullValues = errors.NewKind(`domain %s does not allow null values`)
|
||||
|
||||
// ErrDomainValueViolatesCheckConstraint is returned when given value violates a domain check.
|
||||
var ErrDomainValueViolatesCheckConstraint = errors.NewKind(`value for domain %s violates check constraint "%s"`)
|
||||
|
||||
// NewDomainType creates new instance of domain DoltgresType. The `Array` field is created in an unresolved state, and
|
||||
// should be resolved immediately after creation.
|
||||
func NewDomainType(
|
||||
ctx *sql.Context,
|
||||
asType *DoltgresType,
|
||||
defaultExpr string,
|
||||
notNull bool,
|
||||
checks []*sql.CheckDefinition,
|
||||
arrayID, internalID id.Type,
|
||||
) *DoltgresType {
|
||||
return &DoltgresType{
|
||||
ID: internalID,
|
||||
TypLength: asType.TypLength,
|
||||
PassedByVal: asType.PassedByVal,
|
||||
TypType: TypeType_Domain,
|
||||
TypCategory: asType.TypCategory,
|
||||
IsPreferred: asType.IsPreferred,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: NewUnresolvedDoltgresTypeFromID(arrayID),
|
||||
InputFunc: toFuncID("domain_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: asType.OutputFunc,
|
||||
ReceiveFunc: toFuncID("domain_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: asType.SendFunc,
|
||||
ModInFunc: asType.ModInFunc,
|
||||
ModOutFunc: asType.ModOutFunc,
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: asType.Align,
|
||||
Storage: asType.Storage,
|
||||
NotNull: notNull,
|
||||
BaseTypeType: asType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: defaultExpr,
|
||||
Acl: nil,
|
||||
Checks: checks,
|
||||
attTypMod: -1,
|
||||
CompareFunc: asType.CompareFunc,
|
||||
SerializationFunc: nil,
|
||||
DeserializationFunc: deserializeTypeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
// deserializeTypeDomain handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeDomain(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
return t.BaseTypeType.DeserializeValue(ctx, data)
|
||||
// TODO: DELETE ME UNDERNEATH
|
||||
/*typeColl, err := GetTypesCollectionFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseType, err := typeColl.GetType(ctx, t.BaseTypeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if baseType == nil {
|
||||
return nil, ErrTypeDoesNotExist.New(t.BaseTypeID.TypeName())
|
||||
}
|
||||
return baseType.DeserializeValue(ctx, data)*/
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
srcdErrors "gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// ErrInvalidInputValueForEnum is returned when the input value does not match given enum type's labels.
|
||||
var ErrInvalidInputValueForEnum = srcdErrors.NewKind(`invalid input value for enum %s: "%s"`)
|
||||
|
||||
// NewEnumType creates new instance of enum DoltgresType. The `Array` field is created in an unresolved state, and
|
||||
// should be resolved immediately after creation.
|
||||
func NewEnumType(ctx *sql.Context, arrayID, typeID id.Type, labels map[string]EnumLabel) *DoltgresType {
|
||||
return &DoltgresType{
|
||||
ID: typeID,
|
||||
TypLength: 4,
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Enum,
|
||||
TypCategory: TypeCategory_EnumTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: NewUnresolvedDoltgresTypeFromID(arrayID),
|
||||
InputFunc: toFuncID("enum_in", toInternal("cstring"), toInternal("oid")),
|
||||
OutputFunc: toFuncID("enum_out", toInternal("anyenum")),
|
||||
ReceiveFunc: toFuncID("enum_recv", toInternal("internal"), toInternal("oid")),
|
||||
SendFunc: toFuncID("enum_send", toInternal("anyenum")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("enum_cmp", toInternal("anyenum"), toInternal("anyenum")),
|
||||
EnumLabels: labels,
|
||||
SerializationFunc: serializeTypeEnum,
|
||||
DeserializationFunc: deserializeTypeEnum,
|
||||
}
|
||||
}
|
||||
|
||||
// EnumLabel represents an enum type label.
|
||||
// This is a pg_enum row entry.
|
||||
type EnumLabel struct {
|
||||
ID id.EnumLabel
|
||||
SortOrder float32
|
||||
}
|
||||
|
||||
// NewEnumLabel creates new instance of enum type label.
|
||||
func NewEnumLabel(ctx *sql.Context, labelID id.EnumLabel, so float32) EnumLabel {
|
||||
return EnumLabel{
|
||||
ID: labelID,
|
||||
SortOrder: so,
|
||||
}
|
||||
}
|
||||
|
||||
// serializeTypeEnum handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeEnum(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeEnum handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeEnum(ctx *sql.Context, typ *DoltgresType, data []byte) (any, error) {
|
||||
// TODO: should return the index instead of label?
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
value := reader.String()
|
||||
if ctx == nil {
|
||||
// TODO: currently, in some places we use nil context, should fix it.
|
||||
return value, nil
|
||||
}
|
||||
if typ.TypCategory != TypeCategory_EnumTypes {
|
||||
return nil, errors.Errorf(`"%s" is not an enum type`, typ.Name())
|
||||
}
|
||||
if _, exists := typ.EnumLabels[value]; !exists {
|
||||
return nil, ErrInvalidInputValueForEnum.New(typ.Name(), value)
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Float32 is a float32.
|
||||
var Float32 = &DoltgresType{
|
||||
ID: toInternal("float4"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("float4in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("float4out", toInternal("float4")),
|
||||
ReceiveFunc: toFuncID("float4recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("float4send", toInternal("float4")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btfloat4cmp", toInternal("float4"), toInternal("float4")),
|
||||
InternalName: "real",
|
||||
SerializationFunc: serializeTypeFloat32,
|
||||
DeserializationFunc: deserializeTypeFloat32,
|
||||
}
|
||||
|
||||
// serializeTypeFloat32 handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeFloat32(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
f32 := val.(float32)
|
||||
retVal := make([]byte, 4)
|
||||
// Make the serialized form trivially comparable using bytes.Compare: https://stackoverflow.com/a/54557561
|
||||
unsignedBits := math.Float32bits(f32)
|
||||
if f32 >= 0 {
|
||||
unsignedBits ^= 1 << 31
|
||||
} else {
|
||||
unsignedBits = ^unsignedBits
|
||||
}
|
||||
binary.BigEndian.PutUint32(retVal, unsignedBits)
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// deserializeTypeFloat32 handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeFloat32(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
unsignedBits := binary.BigEndian.Uint32(data)
|
||||
if unsignedBits&(1<<31) != 0 {
|
||||
unsignedBits ^= 1 << 31
|
||||
} else {
|
||||
unsignedBits = ^unsignedBits
|
||||
}
|
||||
return math.Float32frombits(unsignedBits), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Float32Array is the array variant of Float32.
|
||||
var Float32Array = CreateArrayTypeFromBaseType(Float32)
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Float64 is a float64.
|
||||
var Float64 = &DoltgresType{
|
||||
ID: toInternal("float8"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: true,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("float8in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("float8out", toInternal("float8")),
|
||||
ReceiveFunc: toFuncID("float8recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("float8send", toInternal("float8")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btfloat8cmp", toInternal("float8"), toInternal("float8")),
|
||||
InternalName: "double precision",
|
||||
SerializationFunc: serializeTypeFloat64,
|
||||
DeserializationFunc: deserializeTypeFloat64,
|
||||
}
|
||||
|
||||
// serializeTypeFloat64 handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeFloat64(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
f64 := val.(float64)
|
||||
retVal := make([]byte, 8)
|
||||
// Make the serialized form trivially comparable using bytes.Compare: https://stackoverflow.com/a/54557561
|
||||
unsignedBits := math.Float64bits(f64)
|
||||
if f64 >= 0 {
|
||||
unsignedBits ^= 1 << 63
|
||||
} else {
|
||||
unsignedBits = ^unsignedBits
|
||||
}
|
||||
binary.BigEndian.PutUint64(retVal, unsignedBits)
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// deserializeTypeFloat64 handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeFloat64(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
unsignedBits := binary.BigEndian.Uint64(data)
|
||||
if unsignedBits&(1<<63) != 0 {
|
||||
unsignedBits ^= 1 << 63
|
||||
} else {
|
||||
unsignedBits = ^unsignedBits
|
||||
}
|
||||
return math.Float64frombits(unsignedBits), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Float64Array is the array variant of Float64.
|
||||
var Float64Array = CreateArrayTypeFromBaseType(Float64)
|
||||
@@ -0,0 +1,161 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// QuickFunction is an interface redefinition of the one defined in the `server/functions/framework` package to avoid cycles.
|
||||
type QuickFunction interface {
|
||||
CallVariadic(ctx *sql.Context, args ...any) (interface{}, error)
|
||||
ResolvedTypes() []*DoltgresType
|
||||
WithResolvedTypes(newTypes []*DoltgresType) any
|
||||
}
|
||||
|
||||
// LoadFunctionFromCatalog returns the function matching the given name and parameter types. This is intended solely for
|
||||
// functions that are used for types, as the returned functions are not valid using the Eval function.
|
||||
var LoadFunctionFromCatalog func(ctx *sql.Context, funcName string, parameterTypes []*DoltgresType) any
|
||||
|
||||
// functionRegistry is a local registry that holds a mapping from ID to QuickFunction. This is done as types are now
|
||||
// passed by struct, meaning that we need to cache the loading of functions somewhere. In addition, we don't yet support
|
||||
// deleting built-in functions, so we can make a global cache. This makes a hard assumption that all functions being
|
||||
// referenced actually exist, which should be true until built-in function deletion is implemented.
|
||||
//
|
||||
// In a way, one can view this as associated an OID to a function. With a proper OID system, this would not need to
|
||||
// exist. It should be removed once OIDs are figured out.
|
||||
type functionRegistry struct {
|
||||
mutex *sync.Mutex
|
||||
counter uint32
|
||||
mapping map[id.Function]uint32
|
||||
revMapping map[uint32]id.Function
|
||||
functions [256]QuickFunction // Arbitrary number, big enough for now to fit every function in it
|
||||
}
|
||||
|
||||
// globalFunctionRegistry is the global functionRegistry. Only one needs to exist since we do not yet allow deleting
|
||||
// built-in functions.
|
||||
var globalFunctionRegistry = functionRegistry{
|
||||
mutex: &sync.Mutex{},
|
||||
counter: 1,
|
||||
mapping: map[id.Function]uint32{id.NullFunction: 0},
|
||||
revMapping: map[uint32]id.Function{0: id.NullFunction},
|
||||
}
|
||||
|
||||
// InternalToRegistryID returns an ID for the given Internal ID.
|
||||
func (r *functionRegistry) InternalToRegistryID(functionID id.Function) uint32 {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
if registryID, ok := r.mapping[functionID]; ok {
|
||||
return registryID
|
||||
}
|
||||
if r.counter >= uint32(len(r.functions)) {
|
||||
panic("max function count reached in static array")
|
||||
}
|
||||
r.mapping[functionID] = r.counter
|
||||
r.revMapping[r.counter] = functionID
|
||||
r.counter++
|
||||
return r.counter - 1
|
||||
}
|
||||
|
||||
// GetFunction returns the associated function for the given ID. This will always return a valid function.
|
||||
func (r *functionRegistry) GetFunction(ctx *sql.Context, id uint32) QuickFunction {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
f := r.functions[id]
|
||||
if f != nil {
|
||||
return f
|
||||
}
|
||||
if id == 0 {
|
||||
return nil
|
||||
}
|
||||
f = r.loadFunction(ctx, id)
|
||||
if f == nil {
|
||||
// If we hit this panic, then we're missing a test that uses this function (and we should add that test)
|
||||
panic(errors.Errorf("cannot find function: `%s`", r.revMapping[id]))
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// GetInternalID returns the function's Internal ID associated with the given registry ID.
|
||||
func (r *functionRegistry) GetInternalID(registryID uint32) id.Function {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
return r.revMapping[registryID]
|
||||
}
|
||||
|
||||
// GetString returns the extracted function name from the function string associated with the given ID.
|
||||
func (r *functionRegistry) GetString(id uint32) string {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
return r.nameWithoutParams(r.revMapping[id])
|
||||
}
|
||||
|
||||
// loadFunction loads the given function
|
||||
func (r *functionRegistry) loadFunction(ctx *sql.Context, id uint32) QuickFunction {
|
||||
// We make this check a second time (first in GetFunction) since the function may have been added while another
|
||||
// function acquired the lock.
|
||||
f := r.functions[id]
|
||||
if f != nil {
|
||||
return f
|
||||
}
|
||||
if LoadFunctionFromCatalog == nil {
|
||||
return nil
|
||||
}
|
||||
functionID := r.revMapping[id]
|
||||
if !functionID.IsValid() {
|
||||
return nil
|
||||
}
|
||||
funcName, types := r.toFuncSignature(functionID)
|
||||
potentialFunction := LoadFunctionFromCatalog(ctx, funcName, types)
|
||||
if potentialFunction == nil {
|
||||
return nil
|
||||
}
|
||||
f = potentialFunction.(QuickFunction)
|
||||
r.functions[id] = f
|
||||
return f
|
||||
}
|
||||
|
||||
// nameWithoutParams returns the name only from the given function string.
|
||||
func (*functionRegistry) nameWithoutParams(functionID id.Function) string {
|
||||
if !functionID.IsValid() {
|
||||
return "-"
|
||||
}
|
||||
return functionID.FunctionName()
|
||||
}
|
||||
|
||||
// toFuncSignature returns a function signature for the given Internal ID.
|
||||
func (*functionRegistry) toFuncSignature(functionID id.Function) (string, []*DoltgresType) {
|
||||
internalParams := functionID.Parameters()
|
||||
params := make([]*DoltgresType, len(internalParams))
|
||||
for i, internalParam := range internalParams {
|
||||
params[i] = IDToBuiltInDoltgresType[internalParam]
|
||||
}
|
||||
return functionID.FunctionName(), params
|
||||
}
|
||||
|
||||
// toFuncID creates a valid function string for the given name and parameters, then registers the name with the
|
||||
// global functionRegistry. The ID from the registry is returned.
|
||||
func toFuncID(functionName string, params ...id.Type) uint32 {
|
||||
if functionName == "-" || len(functionName) == 0 {
|
||||
return 0
|
||||
}
|
||||
functionID := id.NewFunction("pg_catalog", functionName, params...)
|
||||
return globalFunctionRegistry.InternalToRegistryID(functionID)
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/lib/pq/oid"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/postgres/parser/types"
|
||||
)
|
||||
|
||||
// TypeAlignment represents the alignment required when storing a value of this type.
|
||||
type TypeAlignment string
|
||||
|
||||
const (
|
||||
TypeAlignment_Char TypeAlignment = "c"
|
||||
TypeAlignment_Short TypeAlignment = "s"
|
||||
TypeAlignment_Int TypeAlignment = "i"
|
||||
TypeAlignment_Double TypeAlignment = "d"
|
||||
)
|
||||
|
||||
// TypeCategory represents the type category that a type belongs to. These are used by Postgres to group similar types
|
||||
// for parameter resolution, operator resolution, etc.
|
||||
type TypeCategory string
|
||||
|
||||
const (
|
||||
TypeCategory_ArrayTypes TypeCategory = "A"
|
||||
TypeCategory_BooleanTypes TypeCategory = "B"
|
||||
TypeCategory_CompositeTypes TypeCategory = "C"
|
||||
TypeCategory_DateTimeTypes TypeCategory = "D"
|
||||
TypeCategory_EnumTypes TypeCategory = "E"
|
||||
TypeCategory_GeometricTypes TypeCategory = "G"
|
||||
TypeCategory_NetworkAddressTypes TypeCategory = "I"
|
||||
TypeCategory_NumericTypes TypeCategory = "N"
|
||||
TypeCategory_PseudoTypes TypeCategory = "P"
|
||||
TypeCategory_RangeTypes TypeCategory = "R"
|
||||
TypeCategory_StringTypes TypeCategory = "S"
|
||||
TypeCategory_TimespanTypes TypeCategory = "T"
|
||||
TypeCategory_UserDefinedTypes TypeCategory = "U"
|
||||
TypeCategory_BitStringTypes TypeCategory = "V"
|
||||
TypeCategory_UnknownTypes TypeCategory = "X"
|
||||
TypeCategory_InternalUseTypes TypeCategory = "Z"
|
||||
)
|
||||
|
||||
// TypeStorage represents the storage strategy for storing `varlena` (typlen = -1) types.
|
||||
type TypeStorage string
|
||||
|
||||
const (
|
||||
TypeStorage_Plain TypeStorage = "p"
|
||||
TypeStorage_External TypeStorage = "e"
|
||||
TypeStorage_Main TypeStorage = "m"
|
||||
TypeStorage_Extended TypeStorage = "x"
|
||||
)
|
||||
|
||||
// TypeType represents the type of types that can be created/used.
|
||||
// This includes 'base', 'composite', 'domain', 'enum', 'shell', 'range' and 'multirange'.
|
||||
type TypeType string
|
||||
|
||||
const (
|
||||
TypeType_Base TypeType = "b"
|
||||
TypeType_Composite TypeType = "c"
|
||||
TypeType_Domain TypeType = "d"
|
||||
TypeType_Enum TypeType = "e"
|
||||
TypeType_Pseudo TypeType = "p"
|
||||
TypeType_Range TypeType = "r"
|
||||
TypeType_MultiRange TypeType = "m"
|
||||
)
|
||||
|
||||
// GetTypeByID returns the DoltgresType matching the given Internal ID.
|
||||
// If the Internal ID does not match a type, then nil is returned.
|
||||
func GetTypeByID(internalID id.Type) *DoltgresType {
|
||||
t, ok := IDToBuiltInDoltgresType[internalID]
|
||||
if !ok {
|
||||
// TODO: return UNKNOWN?
|
||||
return nil
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// GetAllBuitInTypes returns a slice containing all registered types.
|
||||
// The slice is sorted by each type's ID.
|
||||
func GetAllBuitInTypes() []*DoltgresType {
|
||||
pgTypes := make([]*DoltgresType, 0, len(IDToBuiltInDoltgresType))
|
||||
for internalID, typ := range IDToBuiltInDoltgresType {
|
||||
if typ.ID == Unknown.ID && internalID.TypeName() != "unknown" {
|
||||
continue
|
||||
}
|
||||
pgTypes = append(pgTypes, typ)
|
||||
}
|
||||
sort.Slice(pgTypes, func(i, j int) bool {
|
||||
return pgTypes[i].ID < pgTypes[j].ID
|
||||
})
|
||||
return pgTypes
|
||||
}
|
||||
|
||||
// IDToBuiltInDoltgresType is a map of id.Id to Doltgres' built-in type.
|
||||
var IDToBuiltInDoltgresType map[id.Type]*DoltgresType
|
||||
|
||||
// NameToInternalID is a mapping from a given name to its respective Internal ID.
|
||||
var NameToInternalID = map[string]id.Type{}
|
||||
|
||||
// idToInternalSerializationFunc is a map from the `send` function ID to the internal serialization function.
|
||||
var idToInternalSerializationFunc = map[id.Function]internalSerializationFunc{}
|
||||
|
||||
// idToInternalDeserializationFunc is a map from the `receive` function ID to the internal deserialization function.
|
||||
var idToInternalDeserializationFunc = map[id.Function]internalDeserializationFunc{}
|
||||
|
||||
// init, for now, fills the contents of IDToBuiltInDoltgresType and NameToInternalID, so that we may search for types
|
||||
// using regtype. This should be replaced with a better abstraction at some point.
|
||||
func init() {
|
||||
// For some reason, Go refuses to compile if this map is declared globally.
|
||||
// Serialization references functions that eventually reference this map, and this map references all types such
|
||||
// that Go thinks there's a reference cycle. It's not a real cycle though since the functions aren't evaluated at
|
||||
// compile time, but Go finds an issue with it, so this is a workaround.
|
||||
IDToBuiltInDoltgresType = map[id.Type]*DoltgresType{
|
||||
toInternal("_abstime"): Unknown,
|
||||
toInternal("_aclitem"): Unknown,
|
||||
toInternal("_bit"): BitArray,
|
||||
toInternal("_bool"): BoolArray,
|
||||
toInternal("_box"): Unknown,
|
||||
toInternal("_bpchar"): BpCharArray,
|
||||
toInternal("_bytea"): ByteaArray,
|
||||
toInternal("_char"): InternalCharArray,
|
||||
toInternal("_cid"): Unknown,
|
||||
toInternal("_cidr"): Unknown,
|
||||
toInternal("_circle"): Unknown,
|
||||
toInternal("_cstring"): CstringArray,
|
||||
toInternal("_date"): DateArray,
|
||||
toInternal("_daterange"): Unknown,
|
||||
toInternal("_float4"): Float32Array,
|
||||
toInternal("_float8"): Float64Array,
|
||||
toInternal("_gtsvector"): Unknown,
|
||||
toInternal("_inet"): Unknown,
|
||||
toInternal("_int2"): Int16Array,
|
||||
toInternal("_int2vector"): Int16vectorArray,
|
||||
toInternal("_int4"): Int32Array,
|
||||
toInternal("_int4range"): Unknown,
|
||||
toInternal("_int8"): Int64Array,
|
||||
toInternal("_int8range"): Unknown,
|
||||
toInternal("_interval"): IntervalArray,
|
||||
toInternal("_json"): JsonArray,
|
||||
toInternal("_jsonb"): JsonBArray,
|
||||
toInternal("_line"): Unknown,
|
||||
toInternal("_lseg"): Unknown,
|
||||
toInternal("_macaddr"): Unknown,
|
||||
toInternal("_money"): Unknown,
|
||||
toInternal("_name"): NameArray,
|
||||
toInternal("_numeric"): NumericArray,
|
||||
toInternal("_numrange"): Unknown,
|
||||
toInternal("_oid"): OidArray,
|
||||
toInternal("_oidvector"): OidvectorArray,
|
||||
toInternal("_path"): Unknown,
|
||||
toInternal("_pg_lsn"): Unknown,
|
||||
toInternal("_point"): Unknown,
|
||||
toInternal("_polygon"): Unknown,
|
||||
toInternal("_record"): RecordArray,
|
||||
toInternal("_refcursor"): Unknown,
|
||||
toInternal("_regclass"): RegclassArray,
|
||||
toInternal("_regconfig"): Unknown,
|
||||
toInternal("_regdictionary"): Unknown,
|
||||
toInternal("_regnamespace"): Unknown,
|
||||
toInternal("_regoper"): Unknown,
|
||||
toInternal("_regoperator"): Unknown,
|
||||
toInternal("_regproc"): RegprocArray,
|
||||
toInternal("_regprocedure"): Unknown,
|
||||
toInternal("_regrole"): Unknown,
|
||||
toInternal("_regtype"): RegtypeArray,
|
||||
toInternal("_reltime"): Unknown,
|
||||
toInternal("_text"): TextArray,
|
||||
toInternal("_tid"): Unknown,
|
||||
toInternal("_time"): TimeArray,
|
||||
toInternal("_timestamp"): TimestampArray,
|
||||
toInternal("_timestamptz"): TimestampTZArray,
|
||||
toInternal("_timetz"): TimeTZArray,
|
||||
toInternal("_tinterval"): Unknown,
|
||||
toInternal("_tsquery"): Unknown,
|
||||
toInternal("_tsrange"): Unknown,
|
||||
toInternal("_tstzrange"): Unknown,
|
||||
toInternal("_tsvector"): Unknown,
|
||||
toInternal("_txid_snapshot"): Unknown,
|
||||
toInternal("_uuid"): UuidArray,
|
||||
toInternal("_varbit"): VarBitArray,
|
||||
toInternal("_varchar"): VarCharArray,
|
||||
toInternal("_xid"): XidArray,
|
||||
toInternal("_xml"): Unknown,
|
||||
toInternal("abstime"): Unknown,
|
||||
toInternal("aclitem"): Unknown,
|
||||
toInternal("any"): Any,
|
||||
toInternal("anyarray"): AnyArray,
|
||||
toInternal("anyelement"): AnyElement,
|
||||
toInternal("anyenum"): AnyEnum,
|
||||
toInternal("anynonarray"): AnyNonArray,
|
||||
toInternal("anyrange"): Unknown,
|
||||
toInternal("bit"): Bit,
|
||||
toInternal("bool"): Bool,
|
||||
toInternal("box"): Unknown,
|
||||
toInternal("bpchar"): BpChar,
|
||||
toInternal("bytea"): Bytea,
|
||||
toInternal("char"): InternalChar,
|
||||
toInternal("cid"): Unknown,
|
||||
toInternal("cidr"): Unknown,
|
||||
toInternal("circle"): Unknown,
|
||||
toInternal("cstring"): Cstring,
|
||||
toInternal("date"): Date,
|
||||
toInternal("daterange"): Unknown,
|
||||
toInternal("event_trigger"): Unknown,
|
||||
toInternal("fdw_handler"): Unknown,
|
||||
toInternal("float4"): Float32,
|
||||
toInternal("float8"): Float64,
|
||||
toInternal("gtsvector"): Unknown,
|
||||
toInternal("index_am_handler"): Unknown,
|
||||
toInternal("inet"): Unknown,
|
||||
toInternal("int2"): Int16,
|
||||
toInternal("int2vector"): Int16vector,
|
||||
toInternal("int4"): Int32,
|
||||
toInternal("int4range"): Unknown,
|
||||
toInternal("int8"): Int64,
|
||||
toInternal("int8range"): Unknown,
|
||||
toInternal("internal"): Internal,
|
||||
toInternal("interval"): Interval,
|
||||
toInternal("json"): Json,
|
||||
toInternal("jsonb"): JsonB,
|
||||
toInternal("language_handler"): Unknown,
|
||||
toInternal("line"): Unknown,
|
||||
toInternal("lseg"): Unknown,
|
||||
toInternal("macaddr"): Unknown,
|
||||
toInternal("money"): Unknown,
|
||||
toInternal("name"): Name,
|
||||
toInternal("numeric"): Numeric,
|
||||
toInternal("numrange"): Unknown,
|
||||
toInternal("oid"): Oid,
|
||||
toInternal("oidvector"): Oidvector,
|
||||
toInternal("opaque"): Unknown,
|
||||
toInternal("path"): Unknown,
|
||||
toInternal("pg_attribute"): Unknown,
|
||||
toInternal("pg_auth_members"): Unknown,
|
||||
toInternal("pg_authid"): Unknown,
|
||||
toInternal("pg_class"): Unknown,
|
||||
toInternal("pg_database"): Unknown,
|
||||
toInternal("pg_ddl_command"): Unknown,
|
||||
toInternal("pg_lsn"): Unknown,
|
||||
toInternal("pg_node_tree"): Unknown,
|
||||
toInternal("pg_proc"): Unknown,
|
||||
toInternal("pg_shseclabel"): Unknown,
|
||||
toInternal("pg_type"): Unknown,
|
||||
toInternal("point"): Unknown,
|
||||
toInternal("polygon"): Unknown,
|
||||
toInternal("record"): Record,
|
||||
toInternal("refcursor"): Unknown,
|
||||
toInternal("regclass"): Regclass,
|
||||
toInternal("regconfig"): Unknown,
|
||||
toInternal("regdictionary"): Unknown,
|
||||
toInternal("regnamespace"): Unknown,
|
||||
toInternal("regoper"): Unknown,
|
||||
toInternal("regoperator"): Unknown,
|
||||
toInternal("regproc"): Regproc,
|
||||
toInternal("regprocedure"): Unknown,
|
||||
toInternal("regrole"): Unknown,
|
||||
toInternal("regtype"): Regtype,
|
||||
toInternal("reltime"): Unknown,
|
||||
toInternal("smgr"): Unknown,
|
||||
toInternal("text"): Text,
|
||||
toInternal("tid"): Unknown,
|
||||
toInternal("time"): Time,
|
||||
toInternal("timestamp"): Timestamp,
|
||||
toInternal("timestamptz"): TimestampTZ,
|
||||
toInternal("timetz"): TimeTZ,
|
||||
toInternal("tinterval"): Unknown,
|
||||
toInternal("trigger"): Trigger,
|
||||
toInternal("tsm_handler"): Unknown,
|
||||
toInternal("tsquery"): Unknown,
|
||||
toInternal("tsrange"): Unknown,
|
||||
toInternal("tstzrange"): Unknown,
|
||||
toInternal("tsvector"): Unknown,
|
||||
toInternal("txid_snapshot"): Unknown,
|
||||
toInternal("unknown"): Unknown,
|
||||
toInternal("uuid"): Uuid,
|
||||
toInternal("varbit"): VarBit,
|
||||
toInternal("varchar"): VarChar,
|
||||
toInternal("void"): Void,
|
||||
toInternal("xid"): Xid,
|
||||
toInternal("xml"): Unknown,
|
||||
}
|
||||
for _, t := range GetAllBuitInTypes() {
|
||||
NameToInternalID[t.Name()] = t.ID
|
||||
pt, ok := types.OidToType[oid.Oid(id.Cache().ToOID(t.ID.AsId()))]
|
||||
if ok {
|
||||
NameToInternalID[pt.SQLStandardName()] = t.ID
|
||||
}
|
||||
if t.SendFunc != 0 && t.SerializationFunc != nil {
|
||||
idToInternalSerializationFunc[globalFunctionRegistry.GetInternalID(t.SendFunc)] = t.SerializationFunc
|
||||
}
|
||||
if t.ReceiveFunc != 0 && t.DeserializationFunc != nil {
|
||||
idToInternalDeserializationFunc[globalFunctionRegistry.GetInternalID(t.ReceiveFunc)] = t.DeserializationFunc
|
||||
}
|
||||
}
|
||||
// Add the created types to the deserialization map
|
||||
idToInternalDeserializationFunc[globalFunctionRegistry.GetInternalID(toFuncID("domain_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")))] = deserializeTypeDomain
|
||||
idToInternalDeserializationFunc[globalFunctionRegistry.GetInternalID(toFuncID("enum_recv", toInternal("internal"), toInternal("oid")))] = deserializeTypeEnum
|
||||
// Add the created types to the serialization map
|
||||
idToInternalSerializationFunc[globalFunctionRegistry.GetInternalID(toFuncID("enum_send", toInternal("anyenum")))] = serializeTypeEnum
|
||||
}
|
||||
|
||||
// ErrCastOutOfRange is returned when a value is out of range for a given cast function.
|
||||
// We use this error type as a sentinel error when a type conversion function fails only due to the range of the
|
||||
// input in order to conform to expectations in go-mysql-server.
|
||||
var ErrCastOutOfRange = errors.New("out of range")
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2026 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Init initializes this package.
|
||||
func Init() {
|
||||
internalNullType.Array = internalNullType
|
||||
internalNullType.Elem = internalNullType
|
||||
internalNullType.BaseTypeType = internalNullType
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int16 is an int16.
|
||||
var Int16 = &DoltgresType{
|
||||
ID: toInternal("int2"),
|
||||
TypLength: int16(2),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int2in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int2out", toInternal("int2")),
|
||||
ReceiveFunc: toFuncID("int2recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("int2send", toInternal("int2")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Short,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btint2cmp", toInternal("int2"), toInternal("int2")),
|
||||
InternalName: "smallint",
|
||||
SerializationFunc: serializeTypeInt16,
|
||||
DeserializationFunc: deserializeTypeInt16,
|
||||
}
|
||||
|
||||
// serializeTypeInt16 handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeInt16(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
retVal := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(retVal, uint16(val.(int16))+(1<<15))
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// deserializeTypeInt16 handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeInt16(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return int16(binary.BigEndian.Uint16(data) - (1 << 15)), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Int16Array is the array variant of Int16.
|
||||
var Int16Array = CreateArrayTypeFromBaseType(Int16)
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int16Serial is an int16 serial type.
|
||||
var Int16Serial = &DoltgresType{
|
||||
ID: toInternal("smallserial"),
|
||||
TypLength: int16(2),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int2in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int2out", toInternal("int2")),
|
||||
ReceiveFunc: toFuncID("int2recv"),
|
||||
SendFunc: toFuncID("int2send"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Short,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btint2cmp", toInternal("int2"), toInternal("int2")),
|
||||
IsSerial: true,
|
||||
SerializationFunc: serializeTypeInt16,
|
||||
DeserializationFunc: deserializeTypeInt16,
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2026 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int16vector is the vector variant of Int16.
|
||||
var Int16vector = &DoltgresType{
|
||||
ID: toInternal("int2vector"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_ArrayTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("array_subscript_handler", toInternal("internal")),
|
||||
Elem: Int16,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int2vectorin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int2vectorout", toInternal("int2vector")),
|
||||
ReceiveFunc: toFuncID("int2vectorrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("int2vectorsend", toInternal("int2vector")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
SerializationFunc: serializeTypeInt16Vector,
|
||||
DeserializationFunc: deserializeTypeInt16Vector,
|
||||
}
|
||||
|
||||
// serializeTypeInt16Vector handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeInt16Vector(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
vals := val.([]any)
|
||||
return serializeArray(ctx, vals, Int16)
|
||||
}
|
||||
|
||||
// deserializeTypeInt16Vector handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeInt16Vector(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
return deserializeArray(ctx, data, Int16)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2026 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Int16vectorArray is the array variant of Int16vector.
|
||||
var Int16vectorArray = CreateArrayTypeFromBaseType(Int16vector)
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int32 is an int32.
|
||||
var Int32 = &DoltgresType{
|
||||
ID: toInternal("int4"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int4in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int4out", toInternal("int4")),
|
||||
ReceiveFunc: toFuncID("int4recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("int4send", toInternal("int4")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btint4cmp", toInternal("int4"), toInternal("int4")),
|
||||
InternalName: "integer",
|
||||
SerializationFunc: serializeTypeInt32,
|
||||
DeserializationFunc: deserializeTypeInt32,
|
||||
}
|
||||
|
||||
// serializeTypeInt32 handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeInt32(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
retVal := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(retVal, uint32(val.(int32))+(1<<31))
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// deserializeTypeInt32 handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeInt32(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return int32(binary.BigEndian.Uint32(data) - (1 << 31)), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Int32Array is the array variant of Int32.
|
||||
var Int32Array = CreateArrayTypeFromBaseType(Int32)
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int32Serial is an int32 serial type.
|
||||
var Int32Serial = &DoltgresType{
|
||||
ID: toInternal("serial"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int4in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int4out", toInternal("int4")),
|
||||
ReceiveFunc: toFuncID("int4recv"),
|
||||
SendFunc: toFuncID("int4send"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btint4cmp", toInternal("int4"), toInternal("int4")),
|
||||
IsSerial: true,
|
||||
SerializationFunc: serializeTypeInt32,
|
||||
DeserializationFunc: deserializeTypeInt32,
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int64 is an int64.
|
||||
var Int64 = &DoltgresType{
|
||||
ID: toInternal("int8"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int8in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int8out", toInternal("int8")),
|
||||
ReceiveFunc: toFuncID("int8recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("int8send", toInternal("int8")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btint8cmp", toInternal("int8"), toInternal("int8")),
|
||||
InternalName: "bigint",
|
||||
SerializationFunc: serializeTypeInt64,
|
||||
DeserializationFunc: deserializeTypeInt64,
|
||||
}
|
||||
|
||||
// serializeTypeInt64 handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeInt64(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
retVal := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(retVal, uint64(val.(int64))+(1<<63))
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// deserializeTypeInt64 handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeInt64(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return int64(binary.BigEndian.Uint64(data) - (1 << 63)), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// Int64Array is the array variant of Int64.
|
||||
var Int64Array = CreateArrayTypeFromBaseType(Int64)
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Int64Serial is an int64 serial type.
|
||||
var Int64Serial = &DoltgresType{
|
||||
ID: toInternal("bigserial"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("int8in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("int8out", toInternal("int8")),
|
||||
ReceiveFunc: toFuncID("int8recv"),
|
||||
SendFunc: toFuncID("int8send"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btint8cmp", toInternal("int8"), toInternal("int8")),
|
||||
IsSerial: true,
|
||||
SerializationFunc: serializeTypeInt64,
|
||||
DeserializationFunc: deserializeTypeInt64,
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import "github.com/dolthub/doltgresql/core/id"
|
||||
|
||||
// Internal is an internal type, which means `external binary` type.
|
||||
var Internal = &DoltgresType{
|
||||
ID: toInternal("internal"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("internal_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("internal_out", toInternal("internal")),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
|
||||
// NewInternalTypeWithBaseType returns Internal type with
|
||||
// internal base type set with given type.
|
||||
func NewInternalTypeWithBaseType(internalID id.Type) *DoltgresType {
|
||||
it := Internal
|
||||
it.BaseTypeForInternal = internalID
|
||||
return it
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// InternalCharLength will always be 1.
|
||||
const InternalCharLength = 1
|
||||
|
||||
// InternalChar is a single-byte internal type. In Postgres, it's displayed as `"char"`.
|
||||
var InternalChar = &DoltgresType{
|
||||
ID: toInternal("char"),
|
||||
TypLength: int16(InternalCharLength),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_InternalUseTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("charin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("charout", toInternal("char")),
|
||||
ReceiveFunc: toFuncID("charrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("charsend", toInternal("char")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btcharcmp", toInternal("char"), toInternal("char")),
|
||||
InternalName: `"char"`,
|
||||
SerializationFunc: serializeTypeInternalChar,
|
||||
DeserializationFunc: deserializeTypeInternalChar,
|
||||
}
|
||||
|
||||
// serializeTypeInternalChar handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeInternalChar(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeInternalChar handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeInternalChar(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// InternalCharArray is the array variant of InternalChar.
|
||||
var InternalCharArray = CreateArrayTypeFromBaseType(InternalChar)
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/postgres/parser/duration"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// Interval is the interval type.
|
||||
var Interval = &DoltgresType{
|
||||
ID: toInternal("interval"),
|
||||
TypLength: int16(16),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_TimespanTypes,
|
||||
IsPreferred: true,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("interval_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("interval_out", toInternal("interval")),
|
||||
ReceiveFunc: toFuncID("interval_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("interval_send", toInternal("interval")),
|
||||
ModInFunc: toFuncID("intervaltypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("intervaltypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("interval_cmp", toInternal("interval"), toInternal("interval")),
|
||||
SerializationFunc: serializeTypeInterval,
|
||||
DeserializationFunc: deserializeTypeInterval,
|
||||
}
|
||||
|
||||
// serializeTypeInterval handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeInterval(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
sortNanos, months, days, err := val.(duration.Duration).Encode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writer := utils.NewWriter(0)
|
||||
writer.Int64(sortNanos)
|
||||
writer.Int32(int32(months))
|
||||
writer.Int32(int32(days))
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeInterval handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeInterval(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
sortNanos := reader.Int64()
|
||||
months := reader.Int32()
|
||||
days := reader.Int32()
|
||||
return duration.Decode(sortNanos, int64(months), int64(days))
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// IntervalArray is the array variant of Interval.
|
||||
var IntervalArray = CreateArrayTypeFromBaseType(Interval)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Json is the standard JSON type.
|
||||
var Json = &DoltgresType{
|
||||
ID: toInternal("json"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_UserDefinedTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("json_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("json_out", toInternal("json")),
|
||||
ReceiveFunc: toFuncID("json_recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("json_send", toInternal("json")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeJson,
|
||||
DeserializationFunc: deserializeTypeJson,
|
||||
}
|
||||
|
||||
// serializeTypeJson handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeJson(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return []byte(val.(string)), nil
|
||||
}
|
||||
|
||||
// deserializeTypeJson handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeJson(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// JsonArray is the array variant of Json.
|
||||
var JsonArray = CreateArrayTypeFromBaseType(Json)
|
||||
@@ -0,0 +1,331 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/cockroachdb/apd/v3"
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// jsonDocumentStringUnicodeRegex is used on a JsonDocument's string to find all Unicode escape sequences that have an
|
||||
// additional backslash.
|
||||
var jsonDocumentStringUnicodeRegex = regexp.MustCompile(`\\\\u([0-9A-Fa-f]{4})`)
|
||||
|
||||
// JsonValueType represents a JSON value type. These values are serialized, and therefore should never be modified.
|
||||
type JsonValueType byte
|
||||
|
||||
const (
|
||||
JsonValueType_Object JsonValueType = 0
|
||||
JsonValueType_Array JsonValueType = 1
|
||||
JsonValueType_String JsonValueType = 2
|
||||
JsonValueType_Number JsonValueType = 3
|
||||
JsonValueType_Boolean JsonValueType = 4
|
||||
JsonValueType_Null JsonValueType = 5
|
||||
)
|
||||
|
||||
// JsonDocument represents an entire JSON document.
|
||||
type JsonDocument struct {
|
||||
Value JsonValue
|
||||
}
|
||||
|
||||
// JsonValue is a value that represents some kind of data in JSON.
|
||||
type JsonValue interface {
|
||||
// enforceJsonInterfaceInheritance is a special function that ensures only the expected types inherit this interface.
|
||||
enforceJsonInterfaceInheritance(error)
|
||||
}
|
||||
|
||||
// JsonValueObject represents a JSON object.
|
||||
type JsonValueObject struct {
|
||||
Items []JsonValueObjectItem
|
||||
Index map[string]int
|
||||
}
|
||||
|
||||
// JsonValueObjectItem represents a specific item inside a JsonObject.
|
||||
type JsonValueObjectItem struct {
|
||||
Key string
|
||||
Value JsonValue
|
||||
}
|
||||
|
||||
// JsonValueArray represents a JSON array.
|
||||
type JsonValueArray []JsonValue
|
||||
|
||||
// JsonValueString represents a string value.
|
||||
type JsonValueString string
|
||||
|
||||
// JsonValueNumber represents a number.
|
||||
type JsonValueNumber apd.Decimal
|
||||
|
||||
// JsonValueBoolean represents a boolean value.
|
||||
type JsonValueBoolean bool
|
||||
|
||||
// JsonValueNull represents a null value.
|
||||
type JsonValueNull byte
|
||||
|
||||
var _ JsonValue = JsonValueObject{}
|
||||
var _ JsonValue = JsonValueArray{}
|
||||
var _ JsonValue = JsonValueString("")
|
||||
var _ JsonValue = JsonValueNumber{}
|
||||
var _ JsonValue = JsonValueBoolean(false)
|
||||
var _ JsonValue = JsonValueNull(0)
|
||||
|
||||
// enforceJsonInterfaceInheritance implements the JsonValue interface.
|
||||
func (JsonValueObject) enforceJsonInterfaceInheritance(error) {}
|
||||
|
||||
// enforceJsonInterfaceInheritance implements the JsonValue interface.
|
||||
func (JsonValueArray) enforceJsonInterfaceInheritance(error) {}
|
||||
|
||||
// enforceJsonInterfaceInheritance implements the JsonValue interface.
|
||||
func (JsonValueString) enforceJsonInterfaceInheritance(error) {}
|
||||
|
||||
// enforceJsonInterfaceInheritance implements the JsonValue interface.
|
||||
func (JsonValueNumber) enforceJsonInterfaceInheritance(error) {}
|
||||
|
||||
// enforceJsonInterfaceInheritance implements the JsonValue interface.
|
||||
func (JsonValueBoolean) enforceJsonInterfaceInheritance(error) {}
|
||||
|
||||
// enforceJsonInterfaceInheritance implements the JsonValue interface.
|
||||
func (JsonValueNull) enforceJsonInterfaceInheritance(error) {}
|
||||
|
||||
// JsonValueSerialize is the recursive serializer for JSON values.
|
||||
func JsonValueSerialize(writer *utils.Writer, value JsonValue) {
|
||||
switch value := value.(type) {
|
||||
case JsonValueObject:
|
||||
writer.Byte(byte(JsonValueType_Object))
|
||||
writer.VariableUint(uint64(len(value.Items)))
|
||||
for _, item := range value.Items {
|
||||
writer.String(item.Key)
|
||||
JsonValueSerialize(writer, item.Value)
|
||||
}
|
||||
case JsonValueArray:
|
||||
writer.Byte(byte(JsonValueType_Array))
|
||||
writer.VariableUint(uint64(len(value)))
|
||||
for _, item := range value {
|
||||
JsonValueSerialize(writer, item)
|
||||
}
|
||||
case JsonValueString:
|
||||
writer.Byte(byte(JsonValueType_String))
|
||||
writer.String(string(value))
|
||||
case JsonValueNumber:
|
||||
writer.Byte(byte(JsonValueType_Number))
|
||||
// MarshalBinary cannot error, so we can safely ignore it
|
||||
v := apd.Decimal(value)
|
||||
bytes, _ := Numeric.SerializationFunc(nil, Numeric, &v)
|
||||
writer.ByteSlice(bytes)
|
||||
case JsonValueBoolean:
|
||||
writer.Byte(byte(JsonValueType_Boolean))
|
||||
writer.Bool(bool(value))
|
||||
case JsonValueNull:
|
||||
writer.Byte(byte(JsonValueType_Null))
|
||||
}
|
||||
}
|
||||
|
||||
// JsonValueDeserialize is the recursive deserializer for JSON values.
|
||||
func JsonValueDeserialize(reader *utils.Reader) (_ JsonValue, err error) {
|
||||
switch JsonValueType(reader.Byte()) {
|
||||
case JsonValueType_Object:
|
||||
items := make([]JsonValueObjectItem, reader.VariableUint())
|
||||
index := make(map[string]int)
|
||||
for i := range items {
|
||||
items[i].Key = reader.String()
|
||||
items[i].Value, err = JsonValueDeserialize(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
index[items[i].Key] = i
|
||||
}
|
||||
return JsonValueObject{
|
||||
Items: items,
|
||||
Index: index,
|
||||
}, nil
|
||||
case JsonValueType_Array:
|
||||
values := make(JsonValueArray, reader.VariableUint())
|
||||
for i := range values {
|
||||
values[i], err = JsonValueDeserialize(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
case JsonValueType_String:
|
||||
return JsonValueString(reader.String()), nil
|
||||
case JsonValueType_Number:
|
||||
d, err := Numeric.DeserializationFunc(nil, Numeric, reader.ByteSlice())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d == nil {
|
||||
d = apd.Decimal{}
|
||||
}
|
||||
return JsonValueNumber(*(d.(*apd.Decimal))), err
|
||||
case JsonValueType_Boolean:
|
||||
return JsonValueBoolean(reader.Bool()), nil
|
||||
case JsonValueType_Null:
|
||||
return JsonValueNull(0), nil
|
||||
default:
|
||||
return nil, errors.Errorf("unknown json value type")
|
||||
}
|
||||
}
|
||||
|
||||
// JsonValueFormatter is the recursive formatter for JSON values.
|
||||
func JsonValueFormatter(sb *strings.Builder, value JsonValue) {
|
||||
switch value := value.(type) {
|
||||
case JsonValueObject:
|
||||
sb.WriteRune('{')
|
||||
for i, item := range value.Items {
|
||||
if i > 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteRune('"')
|
||||
sb.WriteString(strings.ReplaceAll(item.Key, `"`, `\"`))
|
||||
sb.WriteString(`": `)
|
||||
JsonValueFormatter(sb, item.Value)
|
||||
}
|
||||
sb.WriteRune('}')
|
||||
case JsonValueArray:
|
||||
sb.WriteRune('[')
|
||||
for i, item := range value {
|
||||
if i > 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
JsonValueFormatter(sb, item)
|
||||
}
|
||||
sb.WriteRune(']')
|
||||
case JsonValueString:
|
||||
sb.WriteRune('"')
|
||||
sb.WriteString(strings.ReplaceAll(string(value), `"`, `\"`))
|
||||
sb.WriteRune('"')
|
||||
case JsonValueNumber:
|
||||
d := apd.Decimal(value)
|
||||
sb.WriteString(d.Text('f'))
|
||||
case JsonValueBoolean:
|
||||
if value {
|
||||
sb.WriteString(`true`)
|
||||
} else {
|
||||
sb.WriteString(`false`)
|
||||
}
|
||||
case JsonValueNull:
|
||||
sb.WriteString(`null`)
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalToJsonDocument converts a JSON document byte slice into the actual JSON document.
|
||||
func UnmarshalToJsonDocument(val []byte) (JsonDocument, error) {
|
||||
var decoded interface{}
|
||||
decoder := json.NewDecoder(bytes.NewReader(val))
|
||||
// UseNumber causes JSON numbers to be decoded as json.Number (string-backed) instead of
|
||||
// float64, which ensures we preserve values and precision.
|
||||
decoder.UseNumber()
|
||||
if err := decoder.Decode(&decoded); err != nil {
|
||||
return JsonDocument{}, err
|
||||
}
|
||||
jsonValue, err := ConvertToJsonDocument(decoded)
|
||||
if err != nil {
|
||||
return JsonDocument{}, err
|
||||
}
|
||||
return JsonDocument{Value: jsonValue}, nil
|
||||
}
|
||||
|
||||
// ConvertToJsonDocument recursively constructs a valid JsonDocument based on the structures returned by the decoder.
|
||||
func ConvertToJsonDocument(val interface{}) (JsonValue, error) {
|
||||
var err error
|
||||
switch val := val.(type) {
|
||||
case map[string]interface{}:
|
||||
keys := utils.GetMapKeys(val)
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
// Key length is sorted before key contents
|
||||
if len(keys[i]) < len(keys[j]) {
|
||||
return true
|
||||
} else if len(keys[i]) > len(keys[j]) {
|
||||
return false
|
||||
} else {
|
||||
return keys[i] < keys[j]
|
||||
}
|
||||
})
|
||||
items := make([]JsonValueObjectItem, len(val))
|
||||
index := make(map[string]int)
|
||||
for i, key := range keys {
|
||||
items[i].Key = key
|
||||
items[i].Value, err = ConvertToJsonDocument(val[key])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
index[key] = i
|
||||
}
|
||||
return JsonValueObject{
|
||||
Items: items,
|
||||
Index: index,
|
||||
}, nil
|
||||
case []interface{}:
|
||||
values := make(JsonValueArray, len(val))
|
||||
for i, item := range val {
|
||||
values[i], err = ConvertToJsonDocument(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
case string:
|
||||
// JSON parsing will convert some escaped whitespace characters to their actual characters, which is incorrect.
|
||||
// We must retain their escaped form to be considered valid JSON.
|
||||
val = strings.ReplaceAll(val, "\\", `\\`)
|
||||
val = strings.ReplaceAll(val, "\n", `\n`)
|
||||
val = strings.ReplaceAll(val, "\t", `\t`)
|
||||
val = strings.ReplaceAll(val, "\r", `\r`)
|
||||
// We specifically don't want Unicode escape sequences to be replaced, so we revert those.
|
||||
// This is safe as we double backslashes before this step, so this will return it to its original input.
|
||||
val = jsonDocumentStringUnicodeRegex.ReplaceAllString(val, `\u$1`)
|
||||
return JsonValueString(val), nil
|
||||
case json.Number:
|
||||
str := string(val)
|
||||
// Strip trailing fractional zeros: "25.0"→{250,-1} and "25"→{25,0} differ in MarshalBinary, breaking GROUP BY hash equality.
|
||||
if strings.IndexByte(str, '.') != -1 && strings.IndexByte(str, 'e') == -1 {
|
||||
// remove trailing 0s after '.'
|
||||
str = strings.TrimRightFunc(str, func(r rune) bool {
|
||||
return r == '0'
|
||||
})
|
||||
str = strings.TrimRight(str, ".")
|
||||
}
|
||||
d := new(apd.Decimal)
|
||||
err = d.Scan(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return JsonValueNumber(*d), nil
|
||||
case float64:
|
||||
// TODO: handle this as a proper numeric as float64 is not precise enough
|
||||
d := new(apd.Decimal)
|
||||
err = d.Scan(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return JsonValueNumber(*d), nil
|
||||
case *apd.Decimal:
|
||||
return JsonValueNumber(*val), nil
|
||||
case bool:
|
||||
return JsonValueBoolean(val), nil
|
||||
case nil:
|
||||
return JsonValueNull(0), nil
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected type while constructing JsonDocument: %T", val)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/apd/v3"
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
gmstypes "github.com/dolthub/go-mysql-server/sql/types"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// JsonB is the deserialized and structured version of JSON that deals with JsonDocument.
|
||||
var JsonB = &DoltgresType{
|
||||
ID: toInternal("jsonb"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_UserDefinedTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("jsonb_subscript_handler", toInternal("internal")),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("jsonb_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("jsonb_out", toInternal("jsonb")),
|
||||
ReceiveFunc: toFuncID("jsonb_recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("jsonb_send", toInternal("jsonb")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("jsonb_cmp", toInternal("jsonb"), toInternal("jsonb")),
|
||||
SerializationFunc: serializeTypeJsonB,
|
||||
DeserializationFunc: deserializeTypeJsonB,
|
||||
}
|
||||
|
||||
// serializeTypeJsonB handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt. This is used for the legacy ExtendedEnc storage path.
|
||||
// Deprecated. These values are now serialized and deserialized by Dolt natively.
|
||||
func serializeTypeJsonB(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
res, err := sql.UnwrapAny(ctx, val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var doc JsonDocument
|
||||
switch v := res.(type) {
|
||||
case sql.JSONWrapper:
|
||||
j, err := v.ToInterface(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jsonVal, err := ConvertToJsonDocument(j)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
doc = JsonDocument{Value: jsonVal}
|
||||
default:
|
||||
return nil, errors.Newf("jsonb: unexpected types %T, %T", res, val)
|
||||
}
|
||||
|
||||
writer := utils.NewWriter(256)
|
||||
JsonValueSerialize(writer, doc.Value)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeJsonB handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes. This is used for the legacy ExtendedEnc storage path.
|
||||
// Deprecated. These values are now serialized and deserialized by Dolt natively, but previous releases still write
|
||||
// values in this old format.
|
||||
func deserializeTypeJsonB(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
jsonValue, err := JsonValueDeserialize(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gmstypes.JSONDocument{Val: jsonValueToInterface(jsonValue)}, nil
|
||||
}
|
||||
|
||||
// jsonValueToInterface converts a legacy JsonValue to a native Go interface value.
|
||||
func jsonValueToInterface(value JsonValue) any {
|
||||
switch v := value.(type) {
|
||||
case JsonValueObject:
|
||||
obj := make(map[string]any, len(v.Items))
|
||||
for _, item := range v.Items {
|
||||
obj[item.Key] = jsonValueToInterface(item.Value)
|
||||
}
|
||||
return obj
|
||||
case JsonValueArray:
|
||||
arr := make([]any, len(v))
|
||||
for i, item := range v {
|
||||
arr[i] = jsonValueToInterface(item)
|
||||
}
|
||||
return arr
|
||||
case JsonValueString:
|
||||
return string(v)
|
||||
case JsonValueNumber:
|
||||
d := apd.Decimal(v)
|
||||
return &d
|
||||
case JsonValueBoolean:
|
||||
return bool(v)
|
||||
case JsonValueNull:
|
||||
return nil
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// JsonBArray is the array variant of JsonB.
|
||||
var JsonBArray = CreateArrayTypeFromBaseType(JsonB)
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// NameLength is the constant length of Name in Postgres 15. Represents (NAMEDATALEN-1)
|
||||
const NameLength = 63
|
||||
|
||||
// Name is a 63-byte internal type for object names.
|
||||
var Name = &DoltgresType{
|
||||
ID: toInternal("name"),
|
||||
TypLength: int16(64),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_StringTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("raw_array_subscript_handler", toInternal("internal")),
|
||||
Elem: InternalChar,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("namein", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("nameout", toInternal("name")),
|
||||
ReceiveFunc: toFuncID("namerecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("namesend", toInternal("name")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NewCollation("pg_catalog", "C"),
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btnamecmp", toInternal("name"), toInternal("name")),
|
||||
SerializationFunc: serializeTypeName,
|
||||
DeserializationFunc: deserializeTypeName,
|
||||
}
|
||||
|
||||
// serializeTypeName handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeName(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(str) + 1))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeName handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeName(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// NameArray is the array variant of Name.
|
||||
var NameArray = CreateArrayTypeFromBaseType(Name)
|
||||
@@ -0,0 +1,199 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/cockroachdb/apd/v3"
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"github.com/dolthub/go-mysql-server/sql/types"
|
||||
"github.com/shopspring/decimal"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
var (
|
||||
NumericValueMaxInt16 = types.DecimalFromInt64(math.MaxInt16) // NumericValueMaxInt16 is the max Int16 value for NUMERIC types
|
||||
NumericValueMaxInt32 = types.DecimalFromInt64(math.MaxInt32) // NumericValueMaxInt32 is the max Int32 value for NUMERIC types
|
||||
NumericValueMaxInt64 = types.DecimalFromInt64(math.MaxInt64) // NumericValueMaxInt64 is the max Int64 value for NUMERIC types
|
||||
NumericValueMinInt16 = types.DecimalFromInt64(math.MinInt16) // NumericValueMinInt16 is the min Int16 value for NUMERIC types
|
||||
NumericValueMinInt32 = types.DecimalFromInt64(math.MinInt32) // NumericValueMinInt32 is the min Int32 value for NUMERIC types
|
||||
NumericValueMinInt64 = types.DecimalFromInt64(math.MinInt64) // NumericValueMinInt64 is the min Int64 value for NUMERIC types
|
||||
NumericNaN = &apd.Decimal{Form: apd.NaN}
|
||||
NumericInf = &apd.Decimal{Form: apd.Infinite}
|
||||
NumericNegInf = &apd.Decimal{Form: apd.Infinite, Negative: true}
|
||||
)
|
||||
|
||||
// Numeric is a precise and unbounded decimal value.
|
||||
var Numeric = &DoltgresType{
|
||||
ID: toInternal("numeric"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("numeric_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("numeric_out", toInternal("numeric")),
|
||||
ReceiveFunc: toFuncID("numeric_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("numeric_send", toInternal("numeric")),
|
||||
ModInFunc: toFuncID("numerictypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("numerictypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Main,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("numeric_cmp", toInternal("numeric"), toInternal("numeric")),
|
||||
SerializationFunc: serializeTypeNumeric,
|
||||
DeserializationFunc: deserializeTypeNumeric,
|
||||
}
|
||||
|
||||
// NewNumericTypeWithPrecisionAndScale returns Numeric type with typmod set.
|
||||
func NewNumericTypeWithPrecisionAndScale(precision, scale int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypmodFromNumericPrecisionAndScale(precision, scale)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *Numeric.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// GetTypmodFromNumericPrecisionAndScale takes Numeric type precision and scale and returns the type modifier value.
|
||||
func GetTypmodFromNumericPrecisionAndScale(precision, scale int32) (int32, error) {
|
||||
if precision < 1 || precision > 1000 {
|
||||
return 0, errors.Errorf("NUMERIC precision %v must be between 1 and 1000", precision)
|
||||
}
|
||||
if scale < -1000 || scale > 1000 {
|
||||
return 0, errors.Errorf("NUMERIC scale 20000 must be between -1000 and 1000")
|
||||
}
|
||||
return ((precision << 16) | scale) + 4, nil
|
||||
}
|
||||
|
||||
// GetPrecisionAndScaleFromTypmod takes Numeric type modifier and returns precision and scale values.
|
||||
func GetPrecisionAndScaleFromTypmod(typmod int32) (int32, int32) {
|
||||
typmod -= 4
|
||||
scale := typmod & 0xFFFF
|
||||
precision := (typmod >> 16) & 0xFFFF
|
||||
return precision, scale
|
||||
}
|
||||
|
||||
// GetNumericValueWithTypmod returns either given numeric value or truncated or error
|
||||
// depending on the precision and scale decoded from given type modifier value.
|
||||
func GetNumericValueWithTypmod(val *apd.Decimal, typmod int32) (*apd.Decimal, error) {
|
||||
if typmod == -1 {
|
||||
return val, nil
|
||||
}
|
||||
res := new(apd.Decimal)
|
||||
precision, scale := GetPrecisionAndScaleFromTypmod(typmod)
|
||||
_, err := sql.DecimalCtx.WithPrecision(uint32(precision)).Quantize(res, val, -scale)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("numeric field overflow - A field with precision %v, scale %v must round to an absolute value less than 10^%v", precision, scale, precision-scale)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetNumericValueFromStringWithTypmod returns either given numeric value or truncated or error
|
||||
// depending on the precision and scale decoded from given type modifier value.
|
||||
func GetNumericValueFromStringWithTypmod(val string, typmod int32) (*apd.Decimal, error) {
|
||||
dec, cond, err := sql.DecimalHighPrecisionCtx.NewFromString(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cond.Inexact() || cond.Rounded() {
|
||||
return nil, errors.Errorf(`numeric precision was lost or truncated for %s`, val)
|
||||
}
|
||||
return GetNumericValueWithTypmod(dec, typmod)
|
||||
}
|
||||
|
||||
// serializeTypeNumeric handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
// Note: this function is only used for values serialized by older clients, which is why it uses a decimal.Decimal.
|
||||
// Newer clients will use Dolt's serialization, which uses apd.Decimal directly.
|
||||
// Deprecated.
|
||||
func serializeTypeNumeric(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
switch d := val.(type) {
|
||||
case decimal.Decimal:
|
||||
return d.MarshalBinary()
|
||||
case *apd.Decimal:
|
||||
bigInt := d.Coeff.MathBigInt()
|
||||
if d.Negative {
|
||||
bigInt.Neg(bigInt)
|
||||
}
|
||||
dec := decimal.NewFromBigInt(bigInt, d.Exponent)
|
||||
return dec.MarshalBinary()
|
||||
default:
|
||||
return nil, errors.Errorf("cannot serialize value of type %T as numeric", val)
|
||||
}
|
||||
}
|
||||
|
||||
// deserializeTypeNumeric handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
// Note: this function is only used for values serialized by older clients, which is why it uses a decimal.Decimal.
|
||||
// Newer clients will use Dolt's serialization, which uses apd.Decimal directly.
|
||||
// Deprecated.
|
||||
func deserializeTypeNumeric(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
retVal := decimal.NewFromInt(0)
|
||||
err := retVal.UnmarshalBinary(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Coefficient() returns a *big.Int; CoefficientInt64() would silently overflow for
|
||||
// values whose coefficient exceeds int64 (e.g. large JSONB numbers in legacy format).
|
||||
coeff := retVal.Coefficient()
|
||||
d := new(apd.Decimal)
|
||||
d.Exponent = retVal.Exponent()
|
||||
if coeff.Sign() < 0 {
|
||||
d.Negative = true
|
||||
d.Coeff.SetMathBigInt(new(big.Int).Neg(coeff))
|
||||
} else {
|
||||
d.Coeff.SetMathBigInt(coeff)
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// NumericCompare compares two *apd.Decimal values handling NaN separately.
|
||||
func NumericCompare(ab, bb *apd.Decimal) int {
|
||||
if (ab.Form == apd.NaN && bb.Form == apd.NaN) ||
|
||||
(ab.Form == apd.Infinite && bb.Form == apd.Infinite && ab.Negative == bb.Negative) {
|
||||
return 0
|
||||
}
|
||||
if ab.Form == apd.NaN {
|
||||
return 1
|
||||
}
|
||||
if bb.Form == apd.NaN {
|
||||
return -1
|
||||
}
|
||||
return ab.Cmp(bb)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// NumericArray is the array variant of Numeric.
|
||||
var NumericArray = CreateArrayTypeFromBaseType(Numeric)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Oid is a data type used for identifying internal objects. It is implemented as an unsigned 32-bit integer.
|
||||
var Oid = &DoltgresType{
|
||||
ID: toInternal("oid"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: true,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("oidin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("oidout", toInternal("oid")),
|
||||
ReceiveFunc: toFuncID("oidrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("oidsend", toInternal("oid")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btoidcmp", toInternal("oid"), toInternal("oid")),
|
||||
SerializationFunc: serializeTypeOid,
|
||||
DeserializationFunc: deserializeTypeOid,
|
||||
}
|
||||
|
||||
// serializeTypeOid handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeOid(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return []byte(val.(id.Id)), nil
|
||||
}
|
||||
|
||||
// deserializeTypeOid handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeOid(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return id.Id(data), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// OidArray is the array variant of Oid.
|
||||
var OidArray = CreateArrayTypeFromBaseType(Oid)
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2026 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Oidvector is the vector variant of Oid.
|
||||
var Oidvector = &DoltgresType{
|
||||
ID: toInternal("oidvector"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_ArrayTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("array_subscript_handler", toInternal("internal")),
|
||||
Elem: Oid,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("oidvectorin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("oidvectorout", toInternal("oidvector")),
|
||||
ReceiveFunc: toFuncID("oidvectorrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("oidvectorsend", toInternal("oidvector")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("btoidvectorcmp", toInternal("oidvector"), toInternal("oidvector")),
|
||||
SerializationFunc: serializeTypeOidvector,
|
||||
DeserializationFunc: deserializeTypeOidvector,
|
||||
}
|
||||
|
||||
// serializeTypeOidvector handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeOidvector(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
vals := val.([]any)
|
||||
return serializeArray(ctx, vals, Oid)
|
||||
}
|
||||
|
||||
// deserializeTypeOidvector handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeOidvector(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
return deserializeArray(ctx, data, Oid)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2026 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// OidvectorArray is the array variant of Oidvector.
|
||||
var OidvectorArray = CreateArrayTypeFromBaseType(Oidvector)
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Record is a generic, anonymous record type, without field type information supplied yet. When used with RecordExpr,
|
||||
// the field type information will be created once the field expressions are analyzed and type information is available,
|
||||
// and a new DoltgresType instance will be created with the field type information populated.
|
||||
var Record = &DoltgresType{
|
||||
ID: toInternal("record"),
|
||||
TypLength: -1,
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("record_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("record_out", toInternal("record")),
|
||||
ReceiveFunc: toFuncID("record_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("record_send", toInternal("record")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeRecord,
|
||||
DeserializationFunc: deserializeTypeRecord,
|
||||
}
|
||||
|
||||
// RecordValue represents a single value in a record, along with its
|
||||
// associated type.
|
||||
type RecordValue struct {
|
||||
Value any
|
||||
Type sql.Type
|
||||
}
|
||||
|
||||
// serializeTypeRecord handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeRecord(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
values, ok := val.([]RecordValue)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected []RecordValue, but got %T", val)
|
||||
}
|
||||
writer := utils.NewWriter(uint64(16 * len(values)))
|
||||
writer.Byte(0) // Version
|
||||
writer.VariableUint(uint64(len(values)))
|
||||
for _, value := range values {
|
||||
dgtype, ok := value.Type.(*DoltgresType)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("record_send only supports Doltgres types, but received `%T`", value.Type)
|
||||
}
|
||||
valBytes, err := dgtype.SerializeValue(ctx, value.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writer.Id(dgtype.ID.AsId())
|
||||
writer.ByteSlice(valBytes)
|
||||
}
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeRecord handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeRecord(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
typeColl, err := GetTypesCollectionFromContext(ctx, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
version := reader.Byte()
|
||||
switch version {
|
||||
case 0:
|
||||
valuesLen := reader.VariableUint()
|
||||
values := make([]RecordValue, valuesLen)
|
||||
for i := uint64(0); i < valuesLen; i++ {
|
||||
typeId := id.Type(reader.Id())
|
||||
valueData := reader.ByteSlice()
|
||||
dgtype, err := typeColl.GetType(ctx, typeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if dgtype == nil {
|
||||
return nil, errors.Errorf("record_recv encountered type `%s.%s` which could not be found",
|
||||
typeId.SchemaName(), typeId.TypeName())
|
||||
}
|
||||
value, err := dgtype.DeserializeValue(ctx, valueData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values[i] = RecordValue{
|
||||
Value: value,
|
||||
Type: dgtype,
|
||||
}
|
||||
}
|
||||
if reader.RemainingBytes() > 0 {
|
||||
return nil, errors.New("record_recv encountered extra data during deserialization")
|
||||
}
|
||||
return values, nil
|
||||
default:
|
||||
return nil, errors.Errorf("version %d of record serialization is not supported, please upgrade the server", version)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// RecordArray is the array variant of Record.
|
||||
var RecordArray = CreateArrayTypeFromBaseType(Record)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Regclass is the OID type for finding items in pg_class.
|
||||
var Regclass = &DoltgresType{
|
||||
ID: toInternal("regclass"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("regclassin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("regclassout", toInternal("regclass")),
|
||||
ReceiveFunc: toFuncID("regclassrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("regclasssend", toInternal("regclass")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeRegclass,
|
||||
DeserializationFunc: deserializeTypeRegclass,
|
||||
}
|
||||
|
||||
// serializeTypeRegclass handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeRegclass(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return []byte(val.(id.Id)), nil
|
||||
}
|
||||
|
||||
// deserializeTypeRegclass handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeRegclass(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return id.Id(data), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// RegclassArray is the array variant of Regclass.
|
||||
var RegclassArray = CreateArrayTypeFromBaseType(Regclass)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Regproc is the OID type for finding function names.
|
||||
var Regproc = &DoltgresType{
|
||||
ID: toInternal("regproc"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("regprocin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("regprocout", toInternal("regproc")),
|
||||
ReceiveFunc: toFuncID("regprocrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("regprocsend", toInternal("regproc")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeRegproc,
|
||||
DeserializationFunc: deserializeTypeRegproc,
|
||||
}
|
||||
|
||||
// serializeTypeRegproc handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeRegproc(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return []byte(val.(id.Id)), nil
|
||||
}
|
||||
|
||||
// deserializeTypeRegproc handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeRegproc(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return id.Id(data), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// RegprocArray is the array variant of Regproc.
|
||||
var RegprocArray = CreateArrayTypeFromBaseType(Regproc)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Regtype is the OID type for finding items in pg_type.
|
||||
var Regtype = &DoltgresType{
|
||||
ID: toInternal("regtype"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_NumericTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("regtypein", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("regtypeout", toInternal("regtype")),
|
||||
ReceiveFunc: toFuncID("regtyperecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("regtypesend", toInternal("regtype")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeRegtype,
|
||||
DeserializationFunc: deserializeTypeRegtype,
|
||||
}
|
||||
|
||||
// serializeTypeRegtype handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeRegtype(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return []byte(val.(id.Id)), nil
|
||||
}
|
||||
|
||||
// deserializeTypeRegtype handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeRegtype(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return id.Id(data), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// RegtypeArray is the array variant of Regtype.
|
||||
var RegtypeArray = CreateArrayTypeFromBaseType(Regtype)
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Row is a pseudo-type that is solely used as a return type for set returning functions.
|
||||
var Row = &DoltgresType{
|
||||
ID: toInternal("row"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("_"),
|
||||
OutputFunc: toFuncID("_"),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
|
||||
// RowTypeWithReturnType returns Row type with Elem set to given type id.
|
||||
// We reuse the Elem field to store the given type as it's only used for array types, which it's safely checked if
|
||||
// the type is array type before used.
|
||||
func RowTypeWithReturnType(baseType *DoltgresType) *DoltgresType {
|
||||
rt := Row.Copy()
|
||||
rt.Elem = baseType
|
||||
rt.InputFunc = baseType.InputFunc
|
||||
rt.OutputFunc = baseType.OutputFunc
|
||||
return rt
|
||||
}
|
||||
|
||||
var _ sql.RowIter = (*SetReturningFunctionRowIter)(nil)
|
||||
|
||||
// SetReturningFunctionRowIter is used for value returned from functions that return multiple rows.
|
||||
type SetReturningFunctionRowIter struct {
|
||||
next func(ctx *sql.Context) (sql.Row, error)
|
||||
}
|
||||
|
||||
// NewSetReturningFunctionRowIter creates a new SetReturningFunctionRowIter as value returned from set returning functions that return Row Type.
|
||||
func NewSetReturningFunctionRowIter(next func(ctx *sql.Context) (sql.Row, error)) *SetReturningFunctionRowIter {
|
||||
return &SetReturningFunctionRowIter{
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
|
||||
// Next implements the interface sql.RowIter.
|
||||
func (s *SetReturningFunctionRowIter) Next(ctx *sql.Context) (sql.Row, error) {
|
||||
return s.next(ctx)
|
||||
}
|
||||
|
||||
// Close implements the interface sql.RowIter.
|
||||
func (s *SetReturningFunctionRowIter) Close(_ *sql.Context) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"github.com/dolthub/go-mysql-server/sql/types"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// init sets the serialization and deserialization functions.
|
||||
func init() {
|
||||
types.SetExtendedTypeSerializers(SerializeType, DeserializeType)
|
||||
}
|
||||
|
||||
// SerializeType is able to serialize the given extended type into a byte slice. All extended types will be defined
|
||||
// by DoltgreSQL.
|
||||
func SerializeType(ctx *sql.Context, extendedType sql.ExtendedType) ([]byte, error) {
|
||||
if doltgresType, ok := extendedType.(*DoltgresType); ok {
|
||||
if doltgresType.IsUnresolved {
|
||||
return nil, errors.Errorf(`attempted to serialize the unresolved type: %s`, doltgresType.Name())
|
||||
}
|
||||
return doltgresType.Serialize(), nil
|
||||
}
|
||||
return nil, errors.Errorf("unknown type to serialize")
|
||||
}
|
||||
|
||||
// DeserializeType is able to deserialize the given serialized type into an appropriate extended type. All extended
|
||||
// types will be defined by DoltgreSQL.
|
||||
func DeserializeType(ctx *sql.Context, serializedType []byte) (sql.ExtendedType, error) {
|
||||
if len(serializedType) == 0 {
|
||||
return nil, errors.Errorf("deserializing empty type data")
|
||||
}
|
||||
|
||||
typ := &DoltgresType{}
|
||||
var typeColl TypeCollection
|
||||
reader := utils.NewReader(serializedType)
|
||||
version := reader.VariableUint()
|
||||
if version != 0 {
|
||||
return nil, errors.Errorf("version %d of types is not supported, please upgrade the server", version)
|
||||
}
|
||||
|
||||
typ.ID = id.Type(reader.Id())
|
||||
typ.TypLength = reader.Int16()
|
||||
typ.PassedByVal = reader.Bool()
|
||||
typ.TypType = TypeType(reader.String())
|
||||
typ.TypCategory = TypeCategory(reader.String())
|
||||
typ.IsPreferred = reader.Bool()
|
||||
typ.IsDefined = reader.Bool()
|
||||
typ.Delimiter = reader.String()
|
||||
typ.RelID = reader.Id()
|
||||
typ.SubscriptFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
typ.Elem = prefillTypeDuringDeserialization(id.Type(reader.Id()))
|
||||
typ.Array = prefillTypeDuringDeserialization(id.Type(reader.Id()))
|
||||
typ.InputFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
typ.OutputFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
receiveFunc := id.Function(reader.Id())
|
||||
typ.ReceiveFunc = globalFunctionRegistry.InternalToRegistryID(receiveFunc)
|
||||
sendFunc := id.Function(reader.Id())
|
||||
typ.SendFunc = globalFunctionRegistry.InternalToRegistryID(sendFunc)
|
||||
typ.ModInFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
typ.ModOutFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
typ.AnalyzeFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
typ.Align = TypeAlignment(reader.String())
|
||||
typ.Storage = TypeStorage(reader.String())
|
||||
typ.NotNull = reader.Bool()
|
||||
typ.BaseTypeType = prefillTypeDuringDeserialization(id.Type(reader.Id()))
|
||||
typ.TypMod = reader.Int32()
|
||||
typ.NDims = reader.Int32()
|
||||
typ.TypCollation = id.Collation(reader.Id())
|
||||
typ.DefaulBin = reader.String()
|
||||
typ.Default = reader.String()
|
||||
numOfAcl := reader.VariableUint()
|
||||
for k := uint64(0); k < numOfAcl; k++ {
|
||||
ac := reader.String()
|
||||
typ.Acl = append(typ.Acl, ac)
|
||||
}
|
||||
numOfChecks := reader.VariableUint()
|
||||
for k := uint64(0); k < numOfChecks; k++ {
|
||||
checkName := reader.String()
|
||||
checkExpr := reader.String()
|
||||
typ.Checks = append(typ.Checks, &sql.CheckDefinition{
|
||||
Name: checkName,
|
||||
CheckExpression: checkExpr,
|
||||
Enforced: true,
|
||||
})
|
||||
}
|
||||
typ.attTypMod = reader.Int32()
|
||||
typ.CompareFunc = globalFunctionRegistry.InternalToRegistryID(id.Function(reader.Id()))
|
||||
numOfEnumLabels := reader.VariableUint()
|
||||
if numOfEnumLabels > 0 {
|
||||
typ.EnumLabels = make(map[string]EnumLabel)
|
||||
for k := uint64(0); k < numOfEnumLabels; k++ {
|
||||
typeID := reader.Id()
|
||||
sortOrder := reader.Float32()
|
||||
typ.EnumLabels[typeID.Segment(1)] = EnumLabel{
|
||||
ID: id.EnumLabel(typeID),
|
||||
SortOrder: sortOrder,
|
||||
}
|
||||
}
|
||||
}
|
||||
numOfCompAttrs := reader.VariableUint()
|
||||
if numOfCompAttrs > 0 {
|
||||
typ.CompositeAttrs = make([]CompositeAttribute, numOfCompAttrs)
|
||||
for k := uint64(0); k < numOfCompAttrs; k++ {
|
||||
relID := reader.Id()
|
||||
name := reader.String()
|
||||
attrType := prefillTypeDuringDeserialization(id.Type(reader.Id()))
|
||||
num := reader.Int16()
|
||||
collation := reader.String()
|
||||
typ.CompositeAttrs[k] = CompositeAttribute{
|
||||
RelID: relID,
|
||||
Name: name,
|
||||
Type: attrType,
|
||||
Num: num,
|
||||
Collation: collation,
|
||||
}
|
||||
}
|
||||
}
|
||||
typ.InternalName = reader.String()
|
||||
if !reader.IsEmpty() {
|
||||
return nil, errors.Errorf("extra data found while deserializing type %s", typ.Name())
|
||||
}
|
||||
|
||||
// Grab the serialization and deserialization functions for the built-in types
|
||||
if f, ok := idToInternalSerializationFunc[sendFunc]; ok {
|
||||
typ.SerializationFunc = f
|
||||
}
|
||||
if f, ok := idToInternalDeserializationFunc[receiveFunc]; ok {
|
||||
typ.DeserializationFunc = f
|
||||
}
|
||||
|
||||
// Resolve all of the potentially unresolved types
|
||||
var err error
|
||||
typ.Elem, typeColl, err = recursiveDeserializeType(ctx, typ, typeColl, typ.Elem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typ.Array, typeColl, err = recursiveDeserializeType(ctx, typ, typeColl, typ.Array)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
typ.BaseTypeType, typeColl, err = recursiveDeserializeType(ctx, typ, typeColl, typ.BaseTypeType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range typ.CompositeAttrs {
|
||||
typ.CompositeAttrs[i].Type, typeColl, err = recursiveDeserializeType(ctx, typ, typeColl, typ.CompositeAttrs[i].Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Return the deserialized object
|
||||
return typ, nil
|
||||
}
|
||||
|
||||
// Serialize returns the DoltgresType as a byte slice.
|
||||
func (t *DoltgresType) Serialize() []byte {
|
||||
writer := utils.NewWriter(256)
|
||||
writer.VariableUint(0) // Version
|
||||
// Write the type to the writer
|
||||
writer.Id(t.ID.AsId())
|
||||
writer.Int16(t.TypLength)
|
||||
writer.Bool(t.PassedByVal)
|
||||
writer.String(string(t.TypType))
|
||||
writer.String(string(t.TypCategory))
|
||||
writer.Bool(t.IsPreferred)
|
||||
writer.Bool(t.IsDefined)
|
||||
writer.String(t.Delimiter)
|
||||
writer.Id(t.RelID)
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.SubscriptFunc).AsId())
|
||||
writer.Id(t.Elem.ID.AsId())
|
||||
writer.Id(t.Array.ID.AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.InputFunc).AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.OutputFunc).AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.ReceiveFunc).AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.SendFunc).AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.ModInFunc).AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.ModOutFunc).AsId())
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.AnalyzeFunc).AsId())
|
||||
writer.String(string(t.Align))
|
||||
writer.String(string(t.Storage))
|
||||
writer.Bool(t.NotNull)
|
||||
writer.Id(t.BaseTypeType.ID.AsId())
|
||||
writer.Int32(t.TypMod)
|
||||
writer.Int32(t.NDims)
|
||||
writer.Id(t.TypCollation.AsId())
|
||||
writer.String(t.DefaulBin)
|
||||
writer.String(t.Default)
|
||||
writer.VariableUint(uint64(len(t.Acl)))
|
||||
for _, ac := range t.Acl {
|
||||
writer.String(ac)
|
||||
}
|
||||
writer.VariableUint(uint64(len(t.Checks)))
|
||||
for _, check := range t.Checks {
|
||||
writer.String(check.Name)
|
||||
writer.String(check.CheckExpression)
|
||||
}
|
||||
writer.Int32(t.attTypMod)
|
||||
writer.Id(globalFunctionRegistry.GetInternalID(t.CompareFunc).AsId())
|
||||
writer.VariableUint(uint64(len(t.EnumLabels)))
|
||||
if len(t.EnumLabels) > 0 {
|
||||
labels := slices.SortedFunc(maps.Values(t.EnumLabels), func(v1 EnumLabel, v2 EnumLabel) int {
|
||||
return cmp.Compare(v1.ID, v2.ID)
|
||||
})
|
||||
for _, l := range labels {
|
||||
writer.Id(l.ID.AsId())
|
||||
writer.Float32(l.SortOrder)
|
||||
}
|
||||
}
|
||||
writer.VariableUint(uint64(len(t.CompositeAttrs)))
|
||||
if len(t.CompositeAttrs) > 0 {
|
||||
for _, l := range t.CompositeAttrs {
|
||||
writer.Id(l.RelID)
|
||||
writer.String(l.Name)
|
||||
writer.Id(l.Type.ID.AsId())
|
||||
writer.Int16(l.Num)
|
||||
writer.String(l.Collation)
|
||||
}
|
||||
}
|
||||
writer.String(t.InternalName)
|
||||
return writer.Data()
|
||||
}
|
||||
|
||||
// prefillTypeDuringDeserialization attempts to return a suitable type if it's one that relies strictly on built-in
|
||||
// types.
|
||||
func prefillTypeDuringDeserialization(target id.Type) *DoltgresType {
|
||||
if target == id.NullType {
|
||||
return internalNullType
|
||||
}
|
||||
if builtin, ok := IDToBuiltInDoltgresType[target]; ok {
|
||||
return builtin
|
||||
}
|
||||
return NewUnresolvedDoltgresTypeFromID(target)
|
||||
}
|
||||
|
||||
// recursiveDeserializeType handles recursive type initialization by caching the type-in-progress and returning the
|
||||
// target type. This also takes a TypeCollection so that it may be reused if multiple calls are made without having to
|
||||
// fetch it at each instance.
|
||||
func recursiveDeserializeType(ctx *sql.Context, typ *DoltgresType, typeColl TypeCollection, target *DoltgresType) (*DoltgresType, TypeCollection, error) {
|
||||
if !target.IsUnresolved {
|
||||
return target, typeColl, nil
|
||||
}
|
||||
|
||||
// If there is no Doltgres context/session yet, then we can't load types from the context.
|
||||
// This can happen when Dolt's AutoIncrementTracker scans tables at db-load time.
|
||||
if ctx == nil {
|
||||
return target, typeColl, nil
|
||||
}
|
||||
|
||||
var recursedType *DoltgresType
|
||||
var err error
|
||||
if typeColl == nil {
|
||||
typeColl, err = GetTypesCollectionFromContext(ctx, "")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
typeColl.WithCachedType(typ, func() {
|
||||
t, nErr := typeColl.GetType(ctx, target.ID)
|
||||
recursedType = t
|
||||
err = nErr
|
||||
})
|
||||
// `GetType` returns a nil type if it cannot be found, so we want to error in that case
|
||||
if err == nil && recursedType == nil {
|
||||
return target, typeColl, errors.Errorf("unable to resolve type `%s` during deserialization", target.ID.TypeName())
|
||||
}
|
||||
return recursedType, typeColl, err
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestSerializationConsistency checks that all types serialization and deserialization.
|
||||
func TestSerializationConsistency(t *testing.T) {
|
||||
for _, typ := range GetAllBuitInTypes() {
|
||||
t.Run(typ.Name(), func(t *testing.T) {
|
||||
serializedType := typ.Serialize()
|
||||
dt, err := DeserializeType(sql.NewEmptyContext(), serializedType)
|
||||
require.NoError(t, err)
|
||||
dgt := dt.(*DoltgresType)
|
||||
// require.Equal: Function equality cannot be determined and will always fail.
|
||||
typ.SerializationFunc = nil
|
||||
typ.DeserializationFunc = nil
|
||||
dgt.SerializationFunc = nil
|
||||
dgt.DeserializationFunc = nil
|
||||
require.Equal(t, typ, dgt)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestJsonValueType operates as a line of defense to prevent accidental changes to JSON type values. If this test
|
||||
// fails, then a JsonValueType was changed that should not have been changed.
|
||||
func TestJsonValueType(t *testing.T) {
|
||||
types := []struct {
|
||||
JsonValueType
|
||||
Value byte
|
||||
Name string
|
||||
}{
|
||||
{JsonValueType_Object, 0, "Object"},
|
||||
{JsonValueType_Array, 1, "Array"},
|
||||
{JsonValueType_String, 2, "String"},
|
||||
{JsonValueType_Number, 3, "Number"},
|
||||
{JsonValueType_Boolean, 4, "Boolean"},
|
||||
{JsonValueType_Null, 5, "Null"},
|
||||
}
|
||||
allValues := make(map[byte]string)
|
||||
for _, typ := range types {
|
||||
if byte(typ.JsonValueType) != typ.Value {
|
||||
t.Logf("JSON value type `%s` has been changed from its permanent value of `%d` to `%d`",
|
||||
typ.Name, typ.Value, byte(typ.JsonValueType))
|
||||
t.Fail()
|
||||
} else if existingName, ok := allValues[typ.Value]; ok {
|
||||
t.Logf("JSON value type `%s` has the same value as `%s`: `%d`",
|
||||
typ.Name, existingName, typ.Value)
|
||||
t.Fail()
|
||||
} else {
|
||||
allValues[typ.Value] = typ.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// ErrTypeIsOnlyAShell is returned when given shell type is attempted to be used.
|
||||
var ErrTypeIsOnlyAShell = errors.NewKind(`type "%s" is only a shell`)
|
||||
|
||||
// NewShellType creates new instance of shell DoltgresType.
|
||||
func NewShellType(ctx *sql.Context, internalID id.Type) *DoltgresType {
|
||||
return &DoltgresType{
|
||||
ID: internalID,
|
||||
TypLength: 4,
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: false,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("shell_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("shell_out", toInternal("void")),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// Text is the text type.
|
||||
var Text = &DoltgresType{
|
||||
ID: toInternal("text"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_StringTypes,
|
||||
IsPreferred: true,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("textin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("textout", toInternal("text")),
|
||||
ReceiveFunc: toFuncID("textrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("textsend", toInternal("text")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NewCollation("pg_catalog", "default"),
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("bttextcmp", toInternal("text"), toInternal("text")),
|
||||
SerializationFunc: serializeTypeText,
|
||||
DeserializationFunc: deserializeTypeText,
|
||||
}
|
||||
|
||||
// serializeTypeText handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeText(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str, ok, err := sql.Unwrap[string](ctx, val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`"text" serialization requires a string argument, got %T`, val)
|
||||
}
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeText handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeText(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// TextArray is the array variant of Text.
|
||||
var TextArray = CreateArrayTypeFromBaseType(Text)
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/postgres/parser/timeofday"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Time is the time without a time zone. Precision is unbounded.
|
||||
var Time = &DoltgresType{
|
||||
ID: toInternal("time"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_DateTimeTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("time_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("time_out", toInternal("time")),
|
||||
ReceiveFunc: toFuncID("time_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("time_send", toInternal("time")),
|
||||
ModInFunc: toFuncID("timetypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("timetypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("time_cmp", toInternal("time"), toInternal("time")),
|
||||
SerializationFunc: serializeTypeTime,
|
||||
DeserializationFunc: deserializeTypeTime,
|
||||
}
|
||||
|
||||
// NewTimeType returns Time type with typmod set. // TODO: implement precision
|
||||
func NewTimeType(precision int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypmodFromTimePrecision(precision)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *Time.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// GetTypmodFromTimePrecision takes Time type precision and returns the type modifier value.
|
||||
func GetTypmodFromTimePrecision(precision int32) (int32, error) {
|
||||
if precision < 0 {
|
||||
// TIME(-1) precision must not be negative
|
||||
return 0, errors.Errorf("TIME(%v) precision must be not be negative", precision)
|
||||
}
|
||||
if precision > 6 {
|
||||
precision = 6
|
||||
//WARNING: TIME(7) precision reduced to maximum allowed, 6
|
||||
}
|
||||
return precision, nil
|
||||
}
|
||||
|
||||
// GetTimePrecisionFromTypMod takes Time type modifier and returns precision value.
|
||||
func GetTimePrecisionFromTypMod(typmod int32) int32 {
|
||||
return typmod
|
||||
}
|
||||
|
||||
// serializeTypeTime handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeTime(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
v := val.(timeofday.TimeOfDay)
|
||||
writer := utils.NewWriter(8)
|
||||
writer.Int64(int64(v))
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeTime handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeTime(ctx *sql.Context, _ *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return timeofday.TimeOfDay(reader.Int64()), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// TimeArray is the array variant of Time.
|
||||
var TimeArray = CreateArrayTypeFromBaseType(Time)
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Timestamp is the timestamp without a time zone. Precision is unbounded.
|
||||
var Timestamp = &DoltgresType{
|
||||
ID: toInternal("timestamp"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_DateTimeTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("timestamp_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("timestamp_out", toInternal("timestamp")),
|
||||
ReceiveFunc: toFuncID("timestamp_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("timestamp_send", toInternal("timestamp")),
|
||||
ModInFunc: toFuncID("timestamptypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("timestamptypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("timestamp_cmp", toInternal("timestamp"), toInternal("timestamp")),
|
||||
SerializationFunc: serializeTypeTimestamp,
|
||||
DeserializationFunc: deserializeTypeTimestamp,
|
||||
}
|
||||
|
||||
// NewTimestampType returns Timestamp type with typmod set. // TODO: implement precision
|
||||
func NewTimestampType(precision int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypmodFromTimePrecision(precision)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *Timestamp.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// serializeTypeTimestamp handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeTimestamp(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return val.(time.Time).MarshalBinary()
|
||||
}
|
||||
|
||||
// deserializeTypeTimestamp handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeTimestamp(ctx *sql.Context, _ *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
t := time.Time{}
|
||||
if err := t.UnmarshalBinary(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// TimestampArray is the array variant of Timestamp.
|
||||
var TimestampArray = CreateArrayTypeFromBaseType(Timestamp)
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// TimestampTZ is the timestamp with a time zone. Precision is unbounded.
|
||||
var TimestampTZ = &DoltgresType{
|
||||
ID: toInternal("timestamptz"),
|
||||
TypLength: int16(8),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_DateTimeTypes,
|
||||
IsPreferred: true,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("timestamptz_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("timestamptz_out", toInternal("timestamptz")),
|
||||
ReceiveFunc: toFuncID("timestamptz_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("timestamptz_send", toInternal("timestamptz")),
|
||||
ModInFunc: toFuncID("timestamptztypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("timestamptztypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("timestamptz_cmp", toInternal("timestamptz"), toInternal("timestamptz")),
|
||||
SerializationFunc: serializeTypeTimestampTZ,
|
||||
DeserializationFunc: deserializeTypeTimestampTZ,
|
||||
}
|
||||
|
||||
// NewTimestampTZType returns TimestampTZ type with typmod set. // TODO: implement precision
|
||||
func NewTimestampTZType(precision int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypmodFromTimePrecision(precision)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *TimestampTZ.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// serializeTypeTimestampTZ handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeTimestampTZ(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return val.(time.Time).MarshalBinary()
|
||||
}
|
||||
|
||||
// deserializeTypeTimestampTZ handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeTimestampTZ(ctx *sql.Context, _ *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
t := time.Time{}
|
||||
if err := t.UnmarshalBinary(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// TimestampTZArray is the array variant of TimestampTZ.
|
||||
var TimestampTZArray = CreateArrayTypeFromBaseType(TimestampTZ)
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/postgres/parser/timeofday"
|
||||
"github.com/dolthub/doltgresql/postgres/parser/timetz"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// TimeTZ is the time with a time zone. Precision is unbounded.
|
||||
var TimeTZ = &DoltgresType{
|
||||
ID: toInternal("timetz"),
|
||||
TypLength: int16(12),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_DateTimeTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("timetz_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("timetz_out", toInternal("timetz")),
|
||||
ReceiveFunc: toFuncID("timetz_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("timetz_send", toInternal("timetz")),
|
||||
ModInFunc: toFuncID("timetztypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("timetztypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Double,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("timetz_cmp", toInternal("timetz"), toInternal("timetz")),
|
||||
SerializationFunc: serializeTypeTimeTZ,
|
||||
DeserializationFunc: deserializeTypeTimeTZ,
|
||||
}
|
||||
|
||||
// NewTimeTZType returns TimeTZ type with typmod set. // TODO: implement precision
|
||||
func NewTimeTZType(precision int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypmodFromTimePrecision(precision)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *TimeTZ.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// serializeTypeTimeTZ handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeTimeTZ(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
v := val.(timetz.TimeTZ)
|
||||
writer := utils.NewWriter(12)
|
||||
writer.Int64(int64(v.TimeOfDay))
|
||||
writer.Int32(v.OffsetSecs)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeTimeTZ handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeTimeTZ(ctx *sql.Context, _ *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
tod := reader.Int64()
|
||||
offset := reader.Int32()
|
||||
return timetz.MakeTimeTZ(timeofday.TimeOfDay(tod), offset), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// TimeTZArray is the array variant of TimeTZ.
|
||||
var TimeTZArray = CreateArrayTypeFromBaseType(TimeTZ)
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Trigger is a pseudo-type that is solely used as a return type for TRIGGER functions.
|
||||
var Trigger = &DoltgresType{
|
||||
ID: toInternal("trigger"),
|
||||
TypLength: 4,
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("_"),
|
||||
OutputFunc: toFuncID("_"),
|
||||
ReceiveFunc: toFuncID("-"),
|
||||
SendFunc: toFuncID("-"),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
// Copyright 2026 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo"
|
||||
doltTypes "github.com/dolthub/dolt/go/store/types"
|
||||
"github.com/dolthub/dolt/go/store/val"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
)
|
||||
|
||||
// typeInfo is the implementation of typeinfo.TypeInfo for DoltgresType.
|
||||
type typeInfo struct {
|
||||
Type *DoltgresType
|
||||
encoding val.Encoding
|
||||
}
|
||||
|
||||
var _ typeinfo.TypeInfo = (*typeInfo)(nil)
|
||||
|
||||
// Equals implements typeinfo.TypeInfo.
|
||||
func (t typeInfo) Equals(other typeinfo.TypeInfo) bool {
|
||||
ot, ok := other.(typeInfo)
|
||||
return ok && t.Type.Equals(ot.Type) && t.encoding == ot.encoding
|
||||
}
|
||||
|
||||
// NomsKind implements typeinfo.TypeInfo.
|
||||
func (t typeInfo) NomsKind() doltTypes.NomsKind {
|
||||
// This kind is only ever used when determining column tags, so we won't worry about encoding here.
|
||||
return doltTypes.ExtendedKind
|
||||
}
|
||||
|
||||
// ToSqlType implements typeinfo.TypeInfo.
|
||||
func (t typeInfo) ToSqlType() sql.Type {
|
||||
return t.Type
|
||||
}
|
||||
|
||||
// Encoding implements typeinfo.TypeInfo.
|
||||
func (t typeInfo) Encoding() val.Encoding {
|
||||
if t.encoding > 0 {
|
||||
return t.encoding
|
||||
}
|
||||
|
||||
switch t.Type.ID.TypeName() {
|
||||
case "int2":
|
||||
return val.Int16Enc
|
||||
case "int4":
|
||||
return val.Int32Enc
|
||||
case "int8":
|
||||
return val.Int64Enc
|
||||
case "float4":
|
||||
return val.Float32Enc
|
||||
case "float8":
|
||||
return val.Float64Enc
|
||||
case "numeric", "decimal":
|
||||
return val.DecimalEnc
|
||||
case "bytea":
|
||||
return val.BytesAdaptiveEnc
|
||||
case "json", "jsonb":
|
||||
return val.JsonAdaptiveEnc
|
||||
case "xid":
|
||||
return val.Uint32Enc
|
||||
// TODO: uuid is represented as a uuid.Uuid in doltgres, but dolt wants []byte for BytesAdaptiveEnc
|
||||
// case "uuid":
|
||||
// return val.BytesAdaptiveEnc
|
||||
case "varchar":
|
||||
if t.Type.attTypMod == -1 {
|
||||
return val.StringAdaptiveEnc
|
||||
}
|
||||
return val.StringEnc
|
||||
case "name", "char":
|
||||
return val.StringEnc
|
||||
case "bpchar", "text":
|
||||
return val.StringAdaptiveEnc
|
||||
default:
|
||||
switch t.Type.MaxSerializedWidth() {
|
||||
case sql.ExtendedTypeSerializedWidth_64K:
|
||||
return val.ExtendedEnc
|
||||
case sql.ExtendedTypeSerializedWidth_Unbounded:
|
||||
return val.ExtendedAdaptiveEnc
|
||||
default:
|
||||
panic(fmt.Errorf("unknown extended type serialization width"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithEncoding implements typeinfo.TypeInfo.
|
||||
func (t typeInfo) WithEncoding(enc val.Encoding) typeinfo.TypeInfo {
|
||||
return typeInfo{
|
||||
Type: t.Type,
|
||||
encoding: enc,
|
||||
}
|
||||
}
|
||||
|
||||
// String implements typeinfo.TypeInfo.
|
||||
func (t typeInfo) String() string {
|
||||
return fmt.Sprintf("TypeInfo(%s, encoding=%d)", t.Type.String(), t.encoding)
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// Unknown represents an invalid or indeterminate type. This is primarily used internally.
|
||||
var Unknown = &DoltgresType{
|
||||
ID: toInternal("unknown"),
|
||||
TypLength: int16(-2),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_UnknownTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("unknownin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("unknownout", toInternal("unknown")),
|
||||
ReceiveFunc: toFuncID("unknownrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("unknownsend", toInternal("unknown")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeUnknown,
|
||||
DeserializationFunc: deserializeTypeUnknown,
|
||||
}
|
||||
|
||||
// serializeTypeUnknown handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeUnknown(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeUnknown handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeUnknown(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
cerrors "github.com/cockroachdb/errors"
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"github.com/dolthub/go-mysql-server/sql/types"
|
||||
"github.com/dolthub/vitess/go/vt/proto/query"
|
||||
"gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
)
|
||||
|
||||
// ErrTypeAlreadyExists is returned when creating given type when it already exists.
|
||||
var ErrTypeAlreadyExists = errors.NewKind(`type "%s" already exists`)
|
||||
|
||||
// ErrTypeDoesNotExist is returned when using given type that does not exist.
|
||||
var ErrTypeDoesNotExist = errors.NewKind(`type "%s" does not exist`)
|
||||
|
||||
// ErrUnhandledType is returned when the type of value does not match given type.
|
||||
var ErrUnhandledType = errors.NewKind(`%s: unhandled type: %T`)
|
||||
|
||||
// ErrInvalidSyntaxForType is returned when the type of value is invalid for given type.
|
||||
var ErrInvalidSyntaxForType = errors.NewKind(`invalid input syntax for type %s: %q`)
|
||||
|
||||
// ErrValueIsOutOfRangeForType is returned when the value is out-of-range for given type.
|
||||
var ErrValueIsOutOfRangeForType = errors.NewKind(`value %q is out of range for type %s`)
|
||||
|
||||
// ErrTypmodArrayMustBe1D is returned when type modifier value is empty array.
|
||||
var ErrTypmodArrayMustBe1D = errors.NewKind(`typmod array must be one-dimensional`)
|
||||
|
||||
// ErrInvalidTypMod is returned when given value is invalid for type modifier.
|
||||
var ErrInvalidTypMod = errors.NewKind(`invalid %s type modifier`)
|
||||
|
||||
// ErrCannotDropSystemType is returned when given type is system/pg_catalog type.
|
||||
var ErrCannotDropSystemType = errors.NewKind(`cannot drop type %s because it is required by the database system`)
|
||||
|
||||
// ErrCannotDropArrayType is returned when given type to drop is array type that is required for its base type.
|
||||
var ErrCannotDropArrayType = errors.NewKind(`cannot drop type %s because type %s requires it`)
|
||||
|
||||
// TypeCollection is an interface from the core package, redeclared here to get around import cycles.
|
||||
type TypeCollection interface {
|
||||
GetType(context.Context, id.Type) (*DoltgresType, error)
|
||||
ResolveType(ctx context.Context, name id.Type) (*DoltgresType, error)
|
||||
WithCachedType(typeToCache *DoltgresType, f func())
|
||||
}
|
||||
|
||||
// Cast is an interface from the core package, redeclared here to get around import cycles.
|
||||
type Cast interface {
|
||||
Eval(ctx *sql.Context, val any, sourceType *DoltgresType, targetType *DoltgresType) (any, error)
|
||||
}
|
||||
|
||||
// CastsCollection is an interface from the core package, redeclared here to get around import cycles.
|
||||
type CastsCollection interface {
|
||||
GetExplicitCast(ctx *sql.Context, sourceType *DoltgresType, targetType *DoltgresType) (Cast, error)
|
||||
GetAssignmentCast(ctx *sql.Context, sourceType *DoltgresType, targetType *DoltgresType) (Cast, error)
|
||||
GetImplicitCast(ctx *sql.Context, sourceType *DoltgresType, targetType *DoltgresType) (Cast, error)
|
||||
}
|
||||
|
||||
// GetTypesCollectionFromContext is a function from the core package, redeclared here to get around import cycles.
|
||||
var GetTypesCollectionFromContext func(*sql.Context, string) (TypeCollection, error)
|
||||
|
||||
// GetCastsCollectionFromContext is a function from the core package, redeclared here to get around import cycles.
|
||||
var GetCastsCollectionFromContext func(*sql.Context, string) (CastsCollection, error)
|
||||
|
||||
// FromGmsType returns a DoltgresType that is most similar to the given GMS type.
|
||||
// It returns UNKNOWN type for GMS types that are not handled.
|
||||
func FromGmsType(typ sql.Type) *DoltgresType {
|
||||
dt, err := FromGmsTypeToDoltgresType(typ)
|
||||
if err != nil {
|
||||
return Unknown
|
||||
}
|
||||
return dt
|
||||
}
|
||||
|
||||
// FromGmsTypeToDoltgresType returns a DoltgresType that is most similar to the given GMS type.
|
||||
// It errors if GMS type is not handled.
|
||||
func FromGmsTypeToDoltgresType(typ sql.Type) (*DoltgresType, error) {
|
||||
switch typ.Type() {
|
||||
case query.Type_INT8:
|
||||
// Special treatment for boolean types when we can detect them
|
||||
if typ == types.Boolean {
|
||||
return Bool, nil
|
||||
}
|
||||
return Int32, nil
|
||||
case query.Type_INT16, query.Type_INT24, query.Type_INT32, query.Type_YEAR:
|
||||
return Int32, nil
|
||||
case query.Type_INT64, query.Type_BIT, query.Type_UINT8, query.Type_UINT16, query.Type_UINT24, query.Type_UINT32:
|
||||
return Int64, nil
|
||||
case query.Type_UINT64:
|
||||
return Numeric, nil
|
||||
case query.Type_FLOAT32:
|
||||
return Float32, nil
|
||||
case query.Type_FLOAT64:
|
||||
return Float64, nil
|
||||
case query.Type_DECIMAL:
|
||||
return Numeric, nil
|
||||
case query.Type_DATE:
|
||||
return Date, nil
|
||||
case query.Type_TIME:
|
||||
return Text, nil
|
||||
case query.Type_DATETIME, query.Type_TIMESTAMP:
|
||||
return Timestamp, nil
|
||||
case query.Type_CHAR, query.Type_VARCHAR, query.Type_TEXT, query.Type_BINARY, query.Type_VARBINARY, query.Type_BLOB, query.Type_SET, query.Type_ENUM:
|
||||
return Text, nil
|
||||
case query.Type_JSON:
|
||||
return Json, nil
|
||||
case query.Type_NULL_TYPE, query.Type_EXPRESSION, query.Type_GEOMETRY:
|
||||
return Unknown, nil
|
||||
default:
|
||||
return nil, cerrors.Errorf("encountered a GMS type that cannot be handled: %d", int32(typ.Type()))
|
||||
}
|
||||
}
|
||||
|
||||
// serializedStringCompare handles the efficient comparison of two strings that have been serialized using utils.Writer.
|
||||
// The writer writes the string by prepending the string length, which prevents direct comparison of the byte slices. We
|
||||
// thus read the string length manually, and extract the byte slices without converting to a string. This function
|
||||
// assumes that neither byte slice is nil nor empty.
|
||||
func serializedStringCompare(v1 []byte, v2 []byte) int {
|
||||
readerV1 := utils.NewReader(v1)
|
||||
readerV2 := utils.NewReader(v2)
|
||||
v1Bytes := utils.AdvanceReader(readerV1, readerV1.VariableUint())
|
||||
v2Bytes := utils.AdvanceReader(readerV2, readerV2.VariableUint())
|
||||
return bytes.Compare(v1Bytes, v2Bytes)
|
||||
}
|
||||
|
||||
// sqlString converts given type value to output string. This is the same as IoOutput function
|
||||
// with an exception to BOOLEAN type. It returns "t" instead of "true".
|
||||
func sqlString(ctx *sql.Context, t *DoltgresType, val any) (string, error) {
|
||||
if t.IsArrayType() {
|
||||
baseType := t.ArrayBaseType()
|
||||
return ArrToString(ctx, val.([]any), baseType, true)
|
||||
} else if t.ID == Bool.ID {
|
||||
if val.(bool) {
|
||||
return "t", nil
|
||||
} else {
|
||||
return "f", nil
|
||||
}
|
||||
}
|
||||
return t.IoOutput(ctx, val)
|
||||
}
|
||||
|
||||
// ArrToString is used for array_out function. |trimBool| parameter allows replacing
|
||||
// boolean result of "true" to "t" if the function is `Type.SQL()`.
|
||||
func ArrToString(ctx *sql.Context, arr []any, baseType *DoltgresType, trimBool bool) (string, error) {
|
||||
sb := strings.Builder{}
|
||||
sb.WriteRune('{')
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteString(",")
|
||||
}
|
||||
if v != nil {
|
||||
str, err := baseType.IoOutput(ctx, v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if baseType.ID == Bool.ID && trimBool {
|
||||
str = string(str[0])
|
||||
}
|
||||
sb.WriteString(quoteString(str))
|
||||
} else {
|
||||
sb.WriteString("NULL")
|
||||
}
|
||||
}
|
||||
sb.WriteRune('}')
|
||||
return sb.String(), nil
|
||||
}
|
||||
|
||||
// RecordToString is used for the record_out function, to serialize record values for wire transfer.
|
||||
// |fields| contains the values to serialize.
|
||||
func RecordToString(ctx *sql.Context, fields []RecordValue) (any, error) {
|
||||
sb := strings.Builder{}
|
||||
sb.WriteRune('(')
|
||||
for i, value := range fields {
|
||||
if i > 0 {
|
||||
sb.WriteString(",")
|
||||
}
|
||||
|
||||
if value.Value == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
doltgresType, ok := value.Type.(*DoltgresType)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`expected *DoltgresType but found: %T`, value.Type)
|
||||
}
|
||||
|
||||
str, err := doltgresType.IoOutput(ctx, value.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if doltgresType.ID == Bool.ID {
|
||||
str = string(str[0])
|
||||
}
|
||||
|
||||
sb.WriteString(quoteString(str))
|
||||
}
|
||||
sb.WriteRune(')')
|
||||
|
||||
return sb.String(), nil
|
||||
}
|
||||
|
||||
// VectorToString is used for *vectorout functions, to serialize vector values for wire transfer.
|
||||
func VectorToString(ctx *sql.Context, arr []any, baseType *DoltgresType) (string, error) {
|
||||
sb := strings.Builder{}
|
||||
for i, v := range arr {
|
||||
if i > 0 {
|
||||
sb.WriteString(" ")
|
||||
}
|
||||
if v != nil {
|
||||
str, err := baseType.IoOutput(ctx, v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sb.WriteString(quoteString(str))
|
||||
} else {
|
||||
sb.WriteString("NULL")
|
||||
}
|
||||
}
|
||||
return sb.String(), nil
|
||||
}
|
||||
|
||||
// ParseCompositeLiteral parses a Postgres composite literal string like "(1,2,hello)" into a slice
|
||||
// of RecordValues using the field types from |compositeType|.
|
||||
func ParseCompositeLiteral(ctx *sql.Context, input string, compositeType *DoltgresType) ([]RecordValue, error) {
|
||||
if len(input) < 2 || input[0] != '(' || input[len(input)-1] != ')' {
|
||||
return nil, cerrors.Errorf(`malformed composite literal: "%s"`, input)
|
||||
}
|
||||
inner := input[1 : len(input)-1]
|
||||
|
||||
attrs := compositeType.CompositeAttrs
|
||||
if len(attrs) == 0 {
|
||||
return []RecordValue{}, nil
|
||||
}
|
||||
|
||||
fieldStrs, err := parseCompositeLiteralFields(inner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(fieldStrs) != len(attrs) {
|
||||
return nil, cerrors.Errorf("composite literal has %d fields but type %s has %d",
|
||||
len(fieldStrs), compositeType.ID.TypeName(), len(attrs))
|
||||
}
|
||||
|
||||
values := make([]RecordValue, len(attrs))
|
||||
for i, attr := range attrs {
|
||||
if fieldStrs[i] == nil {
|
||||
values[i] = RecordValue{Value: nil, Type: attr.Type}
|
||||
} else {
|
||||
val, err := attr.Type.IoInput(ctx, *fieldStrs[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values[i] = RecordValue{Value: val, Type: attr.Type}
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// parseCompositeLiteralFields splits the inner part of a composite literal (with parens already
|
||||
// removed) into per-field string pointers. A nil pointer indicates a SQL NULL value.
|
||||
func parseCompositeLiteralFields(input string) ([]*string, error) {
|
||||
if len(input) == 0 {
|
||||
return []*string{}, nil
|
||||
}
|
||||
var fields []*string
|
||||
i := 0
|
||||
for {
|
||||
if i >= len(input) {
|
||||
fields = append(fields, nil)
|
||||
break
|
||||
}
|
||||
if input[i] == '"' {
|
||||
// Double-quoted field value
|
||||
i++ // skip opening quote
|
||||
var sb strings.Builder
|
||||
for i < len(input) && input[i] != '"' {
|
||||
if input[i] == '\\' && i+1 < len(input) {
|
||||
i++
|
||||
sb.WriteByte(input[i])
|
||||
} else {
|
||||
sb.WriteByte(input[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i >= len(input) {
|
||||
return nil, cerrors.Errorf("unterminated quoted string in composite literal")
|
||||
}
|
||||
i++ // skip closing quote
|
||||
s := sb.String()
|
||||
fields = append(fields, &s)
|
||||
} else {
|
||||
// Unquoted field value — read until next comma
|
||||
start := i
|
||||
for i < len(input) && input[i] != ',' {
|
||||
i++
|
||||
}
|
||||
fieldStr := input[start:i]
|
||||
if fieldStr == "" || strings.EqualFold(fieldStr, "NULL") {
|
||||
fields = append(fields, nil)
|
||||
} else {
|
||||
s := fieldStr
|
||||
fields = append(fields, &s)
|
||||
}
|
||||
}
|
||||
|
||||
if i >= len(input) {
|
||||
break
|
||||
}
|
||||
if input[i] != ',' {
|
||||
return nil, cerrors.Errorf("expected ',' in composite literal, got '%c'", input[i])
|
||||
}
|
||||
i++ // skip comma
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
// quoteString determines if |s| needs to be quoted, by looking for special characters like ' ' or ',',
|
||||
// and if so, quotes the string and returns it. If quoting is not needed, then |s| is returned as is.
|
||||
func quoteString(s string) string {
|
||||
shouldQuote := false
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case ' ', ',', '{', '}', '\\', '"':
|
||||
shouldQuote = true
|
||||
}
|
||||
}
|
||||
if shouldQuote || strings.EqualFold(s, "NULL") || len(s) == 0 {
|
||||
return fmt.Sprintf(`"%s"`, strings.ReplaceAll(s, `"`, `\"`))
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// toInternal returns an Internal ID for the given type. This is only used for the built-in types, since they all share
|
||||
// the same schema (pg_catalog).
|
||||
func toInternal(typeName string) id.Type {
|
||||
return id.NewType("pg_catalog", typeName)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
"github.com/dolthub/doltgresql/postgres/parser/uuid"
|
||||
)
|
||||
|
||||
// Uuid is the UUID type.
|
||||
var Uuid = &DoltgresType{
|
||||
ID: toInternal("uuid"),
|
||||
TypLength: int16(16),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_UserDefinedTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("uuid_in", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("uuid_out", toInternal("uuid")),
|
||||
ReceiveFunc: toFuncID("uuid_recv", toInternal("internal")),
|
||||
SendFunc: toFuncID("uuid_send", toInternal("uuid")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Char,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("uuid_cmp", toInternal("uuid"), toInternal("uuid")),
|
||||
SerializationFunc: serializeTypeUuid,
|
||||
DeserializationFunc: deserializeTypeUuid,
|
||||
}
|
||||
|
||||
// serializeTypeUuid handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeUuid(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
return val.(uuid.UUID).GetBytes(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeUuid handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeUuid(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return uuid.FromBytes(data)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// UuidArray is the array variant of Uuid.
|
||||
var UuidArray = CreateArrayTypeFromBaseType(Uuid)
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// ErrVarBitLengthExceeded is returned when a varbit value exceeds the defined length.
|
||||
var ErrVarBitLengthExceeded = errors.NewKind(`bit string too long for type bit varying(%d)`)
|
||||
|
||||
// VarBit is a varying-length bit string.
|
||||
var VarBit = &DoltgresType{
|
||||
ID: toInternal("varbit"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_BitStringTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("varbit_in", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("varbit_out", toInternal("varbit")),
|
||||
ReceiveFunc: toFuncID("varbit_recv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("varbit_send", toInternal("varbit")),
|
||||
ModInFunc: toFuncID("varbittypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("varbittypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NewCollation("pg_catalog", "default"),
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("varbitcmp", toInternal("varbit"), toInternal("varbit")),
|
||||
SerializationFunc: serializeTypeVarbit,
|
||||
DeserializationFunc: deserializeTypeVarbit,
|
||||
}
|
||||
|
||||
// NewVarBitType returns a VarBit type with type modifier set
|
||||
// representing the max number of bits in the string.
|
||||
func NewVarBitType(width int32) (*DoltgresType, error) {
|
||||
if width < 1 {
|
||||
return nil, ErrLengthMustBeAtLeast1.New("varbit")
|
||||
} else if width > StringMaxLength {
|
||||
return nil, ErrLengthCannotExceed.New("varbit")
|
||||
}
|
||||
newType := *VarBit.WithAttTypMod(width)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// serializeTypeVarbit handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeVarbit(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
bitStr := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(bitStr) + 4))
|
||||
writer.String(bitStr)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeVarbit handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeVarbit(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2025 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// VarBitArray is the array variant of VarBit.
|
||||
var VarBitArray = CreateArrayTypeFromBaseType(VarBit)
|
||||
@@ -0,0 +1,130 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"gopkg.in/src-d/go-errors.v1"
|
||||
|
||||
"github.com/dolthub/doltgresql/utils"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
const (
|
||||
// StringMaxLength is the maximum number of characters (not bytes) that a Char, VarChar, or BpChar may contain.
|
||||
StringMaxLength = 10485760
|
||||
// StringUnbounded is used to represent that a type does not define a limit on the strings that it accepts. Values
|
||||
// are still limited by the field size limit, but it won't be enforced by the type.
|
||||
StringUnbounded = 0
|
||||
)
|
||||
|
||||
// ErrLengthMustBeAtLeast1 is returned when given character length is less than 1.
|
||||
var ErrLengthMustBeAtLeast1 = errors.NewKind(`length for type %s must be at least 1`)
|
||||
|
||||
// ErrLengthCannotExceed is returned when given character length exceeds the upper bound, 10485760.
|
||||
var ErrLengthCannotExceed = errors.NewKind(`length for type %s cannot exceed 10485760`)
|
||||
|
||||
// VarChar is a varchar that has an unbounded length.
|
||||
var VarChar = &DoltgresType{
|
||||
ID: toInternal("varchar"),
|
||||
TypLength: int16(-1),
|
||||
PassedByVal: false,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_StringTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("varcharin", toInternal("cstring"), toInternal("oid"), toInternal("int4")),
|
||||
OutputFunc: toFuncID("varcharout", toInternal("varchar")),
|
||||
ReceiveFunc: toFuncID("varcharrecv", toInternal("internal"), toInternal("oid"), toInternal("int4")),
|
||||
SendFunc: toFuncID("varcharsend", toInternal("varchar")),
|
||||
ModInFunc: toFuncID("varchartypmodin", toInternal("_cstring")),
|
||||
ModOutFunc: toFuncID("varchartypmodout", toInternal("int4")),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Extended,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NewCollation("pg_catalog", "default"),
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("bttextcmp", toInternal("text"), toInternal("text")), // TODO: temporarily added
|
||||
SerializationFunc: serializeTypeVarChar,
|
||||
DeserializationFunc: deserializeTypeVarChar,
|
||||
}
|
||||
|
||||
// NewVarCharType returns VarChar type with type modifier set
|
||||
// representing the maximum number of characters that the type may hold.
|
||||
func NewVarCharType(maxChars int32) (*DoltgresType, error) {
|
||||
typmod, err := GetTypModFromCharLength("varchar", maxChars)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newType := *VarChar.WithAttTypMod(typmod)
|
||||
return &newType, nil
|
||||
}
|
||||
|
||||
// MustCreateNewVarCharType panics if used with out-of-bound value.
|
||||
func MustCreateNewVarCharType(maxChars int32) *DoltgresType {
|
||||
newType, err := NewVarCharType(maxChars)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return newType
|
||||
}
|
||||
|
||||
// GetTypModFromCharLength takes character type and its length and returns the type modifier value.
|
||||
func GetTypModFromCharLength(typName string, l int32) (int32, error) {
|
||||
if l < 1 {
|
||||
return 0, ErrLengthMustBeAtLeast1.New(typName)
|
||||
} else if l > StringMaxLength {
|
||||
return 0, ErrLengthCannotExceed.New(typName)
|
||||
}
|
||||
return l + 4, nil
|
||||
}
|
||||
|
||||
// GetCharLengthFromTypmod takes character type modifier and returns length value.
|
||||
func GetCharLengthFromTypmod(typmod int32) int32 {
|
||||
return typmod - 4
|
||||
}
|
||||
|
||||
// serializeTypeVarChar handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeVarChar(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
str := val.(string)
|
||||
writer := utils.NewWriter(uint64(len(str) + 4))
|
||||
writer.String(str)
|
||||
return writer.Data(), nil
|
||||
}
|
||||
|
||||
// deserializeTypeVarChar handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeVarChar(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
reader := utils.NewReader(data)
|
||||
return reader.String(), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// VarCharArray is the array variant of VarChar.
|
||||
var VarCharArray = CreateArrayTypeFromBaseType(VarChar)
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Void is the void type.
|
||||
var Void = &DoltgresType{
|
||||
ID: toInternal("void"),
|
||||
TypLength: 4,
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Pseudo,
|
||||
TypCategory: TypeCategory_PseudoTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("void_in", toInternal("cstring"), toInternal("oid")),
|
||||
OutputFunc: toFuncID("void_out", toInternal("void")),
|
||||
ReceiveFunc: toFuncID("void_recv", toInternal("internal"), toInternal("oid")),
|
||||
SendFunc: toFuncID("void_send", toInternal("void")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: nil,
|
||||
DeserializationFunc: nil,
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/doltgresql/core/id"
|
||||
)
|
||||
|
||||
// Xid is a data type used for internal transaction IDs. It is implemented as an unsigned 32 bit integer.
|
||||
var Xid = &DoltgresType{
|
||||
ID: toInternal("xid"),
|
||||
TypLength: int16(4),
|
||||
PassedByVal: true,
|
||||
TypType: TypeType_Base,
|
||||
TypCategory: TypeCategory_UserDefinedTypes,
|
||||
IsPreferred: false,
|
||||
IsDefined: true,
|
||||
Delimiter: ",",
|
||||
RelID: id.Null,
|
||||
SubscriptFunc: toFuncID("-"),
|
||||
Elem: internalNullType,
|
||||
Array: internalNullType,
|
||||
InputFunc: toFuncID("xidin", toInternal("cstring")),
|
||||
OutputFunc: toFuncID("xidout", toInternal("xid")),
|
||||
ReceiveFunc: toFuncID("xidrecv", toInternal("internal")),
|
||||
SendFunc: toFuncID("xidsend", toInternal("xid")),
|
||||
ModInFunc: toFuncID("-"),
|
||||
ModOutFunc: toFuncID("-"),
|
||||
AnalyzeFunc: toFuncID("-"),
|
||||
Align: TypeAlignment_Int,
|
||||
Storage: TypeStorage_Plain,
|
||||
NotNull: false,
|
||||
BaseTypeType: internalNullType,
|
||||
TypMod: -1,
|
||||
NDims: 0,
|
||||
TypCollation: id.NullCollation,
|
||||
DefaulBin: "",
|
||||
Default: "",
|
||||
Acl: nil,
|
||||
Checks: nil,
|
||||
attTypMod: -1,
|
||||
CompareFunc: toFuncID("-"),
|
||||
SerializationFunc: serializeTypeXid,
|
||||
DeserializationFunc: deserializeTypeXid,
|
||||
}
|
||||
|
||||
// serializeTypeXid handles serialization from the standard representation to our serialized representation that is
|
||||
// written in Dolt.
|
||||
func serializeTypeXid(ctx *sql.Context, t *DoltgresType, val any) ([]byte, error) {
|
||||
retVal := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(retVal, val.(uint32))
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// deserializeTypeXid handles deserialization from the Dolt serialized format to our standard representation used by
|
||||
// expressions and nodes.
|
||||
func deserializeTypeXid(ctx *sql.Context, t *DoltgresType, data []byte) (any, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return binary.BigEndian.Uint32(data), nil
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2024 Dolthub, Inc.
|
||||
//
|
||||
// Licensed 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 types
|
||||
|
||||
// XidArray is the array variant of Xid.
|
||||
var XidArray = CreateArrayTypeFromBaseType(Xid)
|
||||
Reference in New Issue
Block a user