Skip to content
Snippets Groups Projects
Unverified Commit 8d81e23d authored by chenmingsong's avatar chenmingsong Committed by GitHub
Browse files

Add declare for tpch related functions (#2545)

parent 52adaedf
No related branches found
No related tags found
No related merge requests found
......@@ -28,6 +28,9 @@ const (
// any family
T_any T = T(plan.Type_ANY)
// bool family
T_bool T = T(plan.Type_BOOL)
// numeric/integer family
T_int8 T = T(plan.Type_INT8)
T_int16 T = T(plan.Type_INT16)
......
......@@ -32,16 +32,420 @@ func initAggregateFunction() {
}
}
var aggregates = map[string][]Function{
"max": {
// aggregates contains the aggregate function indexed by function id.
var aggregates = map[int][]Function{
MAX: {
{
Index: 0,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint8},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint8,
AggregateInfo: nil,
},
{
Index: 1,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint16},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint16,
AggregateInfo: nil,
},
{
Index: 2,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint32,
AggregateInfo: nil,
},
{
Index: 3,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint64,
AggregateInfo: nil,
},
{
Index: 4,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int8},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int8,
AggregateInfo: nil,
},
{
Index: 5,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int16},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int16,
AggregateInfo: nil,
},
{
Index: 6,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int32,
AggregateInfo: nil,
},
{
Index: 7,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int64,
AggregateInfo: nil,
},
{
Index: 8,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_float32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_float32,
AggregateInfo: nil,
},
{
Index: 9,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_float64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_float64,
AggregateInfo: nil,
},
{
Index: 10,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_varchar},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_varchar,
AggregateInfo: nil,
},
{
Index: 11,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_char},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_char,
AggregateInfo: nil,
},
{
Index: 12,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_date},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_date,
AggregateInfo: nil,
},
{
Index: 13,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_datetime},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_datetime,
AggregateInfo: nil,
},
},
MIN: {
{
Index: 0,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint8},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint8,
AggregateInfo: nil,
},
{
Index: 1,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint16},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint16,
AggregateInfo: nil,
},
{
Index: 2,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint32,
AggregateInfo: nil,
},
{
Index: 3,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint64,
AggregateInfo: nil,
},
{
Index: 4,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int8},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int8,
AggregateInfo: nil,
},
{
Index: 5,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int16},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int16,
AggregateInfo: nil,
},
{
Index: 6,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int32,
AggregateInfo: nil,
},
{
Index: 7,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int64,
AggregateInfo: nil,
},
{
Index: 8,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_float32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_float32,
AggregateInfo: nil,
},
{
Index: 9,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_float64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_float64,
AggregateInfo: nil,
},
{
Index: 10,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_varchar},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_varchar,
AggregateInfo: nil,
},
{
Index: 11,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_char},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_char,
AggregateInfo: nil,
},
{
Index: 12,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_date},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_date,
AggregateInfo: nil,
},
{
Index: 13,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_datetime},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_datetime,
AggregateInfo: nil,
},
},
SUM: {
{
Index: 0,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint8},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint64,
AggregateInfo: nil,
},
{
Index: 1,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint16},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint64,
AggregateInfo: nil,
},
{
Index: 2,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint64,
AggregateInfo: nil,
},
{
Index: 3,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_uint64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_uint64,
AggregateInfo: nil,
},
{
Index: 4,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int8},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int64,
AggregateInfo: nil,
},
{
Index: 5,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int16},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int64,
AggregateInfo: nil,
},
{
Index: 6,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int64,
AggregateInfo: nil,
},
{
Index: 7,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_int64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_int64,
AggregateInfo: nil, // ring.intRing and ring.type is int64, retTyp is int64
AggregateInfo: nil,
},
{
Index: 8,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_float32},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_float64,
AggregateInfo: nil,
},
{
Index: 9,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_float64},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_float64,
AggregateInfo: nil,
},
{
Index: 10,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_varchar},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_varchar,
AggregateInfo: nil,
},
{
Index: 11,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_char},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_char,
AggregateInfo: nil,
},
{
Index: 12,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_date},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_date,
AggregateInfo: nil,
},
{
Index: 13,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_datetime},
TypeCheckFn: strictTypeCheck,
ReturnTyp: types.T_datetime,
AggregateInfo: nil,
},
},
AVG: {
{
Index: 0,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
ReturnTyp: types.T_float64,
TypeCheckFn: func(inputTypes []types.T, _ []types.T) (match bool) {
if len(inputTypes) == 1 && isNumberType(inputTypes[0]) {
return true
}
return false
},
AggregateInfo: nil,
},
},
COUNT: {
{
Index: 0,
Flag: plan.Function_AGG,
Kind: STANDARD_FUNCTION,
ReturnTyp: types.T_int64,
TypeCheckFn: func(inputTypes []types.T, _ []types.T) (match bool) {
if len(inputTypes) == 1 {
return true
}
return false
},
AggregateInfo: nil,
},
},
}
......@@ -16,9 +16,7 @@ package function
import (
"github.com/matrixorigin/matrixone/pkg/container/types"
"github.com/matrixorigin/matrixone/pkg/container/vector"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/vm/process"
)
func initBuiltIns() {
......@@ -34,41 +32,66 @@ func initBuiltIns() {
}
}
var builtins = map[string][]Function{
"case": {
// builtins contains the builtin function indexed by function id.
var builtins = map[int][]Function{
EXTRACT: {
{
Index: 0,
Flag: plan.Function_NONE,
Kind: CASE_WHEN_EXPRESSION,
Args: nil,
ReturnTyp: types.T_int64,
Fn: func(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
// not implement now.
return nil, nil
},
TypeCheckFn: func(inputTypes []types.T, _ []types.T) (match bool) {
l := len(inputTypes)
if l < 3 {
return false
}
caseType := inputTypes[0]
for i := 0; i < l-1; i += 2 { // when should be caseType
if inputTypes[i] != caseType && isNotScalarNull(inputTypes[i]) {
return false
}
}
for i := 1; i < l-1; i += 2 { // then should be int64
if inputTypes[i] != types.T_int64 && isNotScalarNull(inputTypes[i]) {
return false
}
}
if l%2 == 1 { // has else part
if inputTypes[l-1] != types.T_int64 && isNotScalarNull(inputTypes[l-1]) {
return false
}
}
return true
},
Index: 0,
Flag: plan.Function_STRICT,
Kind: UNKNOW_KIND_FUNCTION,
Args: []types.T{types.T_varchar, types.T_date},
ReturnTyp: types.T_date,
TypeCheckFn: strictTypeCheck,
Fn: nil,
},
{
Index: 1,
Flag: plan.Function_STRICT,
Kind: UNKNOW_KIND_FUNCTION,
Args: []types.T{types.T_varchar, types.T_datetime},
ReturnTyp: types.T_datetime,
TypeCheckFn: strictTypeCheck,
Fn: nil,
},
},
YEAR: {
{
Index: 0,
Flag: plan.Function_STRICT,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_date},
ReturnTyp: types.T_uint16,
TypeCheckFn: strictTypeCheck,
Fn: nil,
},
{
Index: 1,
Flag: plan.Function_STRICT,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_datetime},
ReturnTyp: types.T_uint16,
TypeCheckFn: strictTypeCheck,
Fn: nil,
},
},
SUBSTRING: {
{
Index: 0,
Flag: plan.Function_STRICT,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_varchar, types.T_int64, types.T_int64},
ReturnTyp: types.T_varchar,
TypeCheckFn: strictTypeCheck,
Fn: nil,
},
{
Index: 1,
Flag: plan.Function_STRICT,
Kind: STANDARD_FUNCTION,
Args: []types.T{types.T_char, types.T_int64, types.T_int64},
ReturnTyp: types.T_char,
TypeCheckFn: strictTypeCheck,
Fn: nil,
},
},
}
......@@ -37,8 +37,6 @@ const (
var (
// an empty function structure just for return when we couldn't meet any function.
emptyFunction = Function{}
aggregateEvalError = errors.New(errno.AmbiguousFunction, "aggregate function should not call eval() directly")
)
// Function is an overload of
......@@ -87,8 +85,8 @@ func (f Function) ReturnType() (typ types.T, nullable bool) {
}
func (f Function) VecFn(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
if f.IsAggregate() {
return nil, aggregateEvalError
if f.Fn == nil {
return nil, errors.New(errno.AmbiguousFunction, "function doesn't implement its eval method")
}
return f.Fn(vs, proc)
}
......@@ -118,12 +116,12 @@ func GetFunctionByIndex(functionId int, overloadIndex int) (Function, error) {
}
// GetFunctionByName check a function exist or not by function name and arg types,
// if matches, return its function structure.
func GetFunctionByName(name string, args []types.T) (Function, error) {
// if matches, return its function structure and function id.
func GetFunctionByName(name string, args []types.T) (Function, int, error) {
matches := make([]Function, 0, 4)
fid, err := getFunctionId(name)
if err != nil {
return emptyFunction, err
return emptyFunction, -1, err
}
fs := functionRegister[fid]
......@@ -135,7 +133,7 @@ func GetFunctionByName(name string, args []types.T) (Function, error) {
// must match only 1 function
if len(matches) == 0 {
return emptyFunction, errors.New(errno.UndefinedFunction, fmt.Sprintf("undefined function %s%v", name, args))
return emptyFunction, -1, errors.New(errno.UndefinedFunction, fmt.Sprintf("undefined function %s%v", name, args))
}
if len(matches) > 1 {
errMessage := "too much function matches:"
......@@ -144,9 +142,9 @@ func GetFunctionByName(name string, args []types.T) (Function, error) {
errMessage += name
errMessage += fmt.Sprintf("%v", matches[i].Args)
}
return emptyFunction, errors.New(errno.SyntaxError, errMessage)
return emptyFunction, -1, errors.New(errno.SyntaxError, errMessage)
}
return matches[0], nil
return matches[0], fid, nil
}
// strictTypeCheck is a general type check method.
......@@ -167,3 +165,27 @@ func strictTypeCheck(args []types.T, require []types.T) bool {
func isNotScalarNull(t types.T) bool {
return t != ScalarNull
}
var (
anyNumbers = map[types.T]struct{}{
types.T_uint8: {},
types.T_uint16: {},
types.T_uint32: {},
types.T_uint64: {},
types.T_int8: {},
types.T_int16: {},
types.T_int32: {},
types.T_int64: {},
types.T_float32: {},
types.T_float64: {},
types.T_decimal64: {},
types.T_decimal128: {},
}
)
func isNumberType(t types.T) bool {
if _, ok := anyNumbers[t]; ok {
return true
}
return false
}
......@@ -166,6 +166,7 @@ const (
INTERVAL // INTERVAL
EXTRACT // EXTRACT
SUBSTRING // SUBSTRING
YEAR // YEAR
// FUNCTION_END_NUMBER is not a function, just a flag to record the max number of function.
// TODO: every one should put the new function id in front of this one if you want to make a new function.
......@@ -174,7 +175,41 @@ const (
// functionIdRegister is what function we have registered already.
var functionIdRegister = map[string]int{
"=": EQUAL,
"case": CASE,
"max": MAX,
// operators
"=": EQUAL,
">": GREAT_THAN,
">=": GREAT_EQUAL,
"<": LESS_THAN,
"<=": LESS_EQUAL,
"<>": NOT_EQUAL,
"!=": NOT_EQUAL,
"not": NOT,
"and": AND,
"or": OR,
"like": LIKE,
"between": BETWEEN,
"in": IN,
"exist": EXISTS,
"+": PLUS,
"-": MINUS,
"*": MULTI,
"/": DIV,
"div": INTEGER_DIV,
"%": MOD,
"mod": MOD,
"unary_plus": UNARY_PLUS,
"unary_minus": UNARY_MINUS,
"case": CASE,
"cast": CAST,
// aggregate
"max": MAX,
"min": MIN,
"sum": SUM,
"avg": AVG,
"count": COUNT,
// builtin
"extract": EXTRACT,
"year": YEAR,
"substr": SUBSTRING,
"substring": SUBSTRING,
}
......@@ -134,7 +134,7 @@ func TestFunctionRegister(t *testing.T) {
for _, tc := range testCases {
msg := fmt.Sprintf("case id is %d", tc.id)
f1, err := GetFunctionByName(tc.fname, tc.args)
f1, _, err := GetFunctionByName(tc.fname, tc.args)
if tc.index == notFound {
require.Equal(t, emptyFunction, f1, msg)
} else {
......@@ -149,18 +149,18 @@ func TestFunctionRegister(t *testing.T) {
// test errMsg
{
_, err := GetFunctionByName("testFunctionName", nil)
_, _, err := GetFunctionByName("testFunctionName", nil)
require.Equal(t, errors.New(errno.UndefinedFunction, "function 'testFunctionName' doesn't register, get id failed"), err)
}
{
_, err := GetFunctionByName("f1", []types.T{})
_, _, err := GetFunctionByName("f1", []types.T{})
require.Equal(t, errors.New(errno.UndefinedFunction, "undefined function f1[]"), err)
}
{
errMessage := "too much function matches:\n" +
"f1[BIGINT BIGINT]\n" +
"f1[BIGINT DOUBLE]"
_, err := GetFunctionByName("f1", []types.T{types.T_int64, ScalarNull})
_, _, err := GetFunctionByName("f1", []types.T{types.T_int64, ScalarNull})
require.Equal(t, errors.New(errno.SyntaxError, errMessage), err)
}
}
......@@ -29,25 +29,21 @@ func initRelatedStructure() {
// appendFunction is a method only used at init-functions to add a new function into supported-function list.
// Ensure that no duplicate functions will be added.
func appendFunction(name string, newFunction Function) error {
if err := completenessCheck(newFunction, name); err != nil {
func appendFunction(fid int, newFunction Function) error {
if err := completenessCheck(fid, newFunction); err != nil {
return err
}
fid, err := getFunctionId(name)
if err != nil {
return err
}
fs := functionRegister[fid]
requiredIndex := len(fs)
if newFunction.Index != requiredIndex {
return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("function %s(%v)'s index should be %d", name, newFunction.Args, requiredIndex))
return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("function (fid = %d, index = %d)'s index should be %d", fid, newFunction.Index, requiredIndex))
}
for _, f := range fs {
if functionsEqual(f, newFunction) {
return errors.New(errno.DuplicateFunction, fmt.Sprintf("conflict happens, duplicate function %s(%v)", name, f.Args))
return errors.New(errno.DuplicateFunction, fmt.Sprintf("conflict happens, duplicate function (fid = %d, index = %d)", fid, newFunction.Index))
}
}
......@@ -57,14 +53,18 @@ func appendFunction(name string, newFunction Function) error {
return nil
}
func completenessCheck(f Function, name string) error {
if f.Fn == nil && !f.IsAggregate() {
return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("function '%s' missing its's Fn", name))
func completenessCheck(id int, f Function) error {
if id < 0 || id >= FUNCTION_END_NUMBER {
return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("illegal function id %d", id))
}
if f.TypeCheckFn == nil {
return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("function '%s' missing its's type check function", name))
}
return nil
return nil // just jump it now.
//if f.Fn == nil && !f.IsAggregate() {
// return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("function %d missing its's Fn", id))
//}
//if f.TypeCheckFn == nil {
// return errors.New(errno.InvalidFunctionDefinition, fmt.Sprintf("function %d missing its's type check function", id))
//}
//return nil
}
func functionsEqual(f1 Function, f2 Function) bool {
......
This diff is collapsed.
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment