1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hanchuanchuan-goInception

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
builtin_json.go 24 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
hanchuanchuan Отправлено 6 лет назад 27f3c5a
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
// Copyright 2017 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.
package expression
import (
"github.com/hanchuanchuan/goInception/ast"
"github.com/hanchuanchuan/goInception/mysql"
"github.com/hanchuanchuan/goInception/sessionctx"
"github.com/hanchuanchuan/goInception/types"
"github.com/hanchuanchuan/goInception/types/json"
"github.com/hanchuanchuan/goInception/util/chunk"
"github.com/pingcap/errors"
"github.com/pingcap/tipb/go-tipb"
)
var (
_ functionClass = &jsonTypeFunctionClass{}
_ functionClass = &jsonExtractFunctionClass{}
_ functionClass = &jsonUnquoteFunctionClass{}
_ functionClass = &jsonSetFunctionClass{}
_ functionClass = &jsonInsertFunctionClass{}
_ functionClass = &jsonReplaceFunctionClass{}
_ functionClass = &jsonRemoveFunctionClass{}
_ functionClass = &jsonMergeFunctionClass{}
_ functionClass = &jsonObjectFunctionClass{}
_ functionClass = &jsonArrayFunctionClass{}
_ functionClass = &jsonContainsFunctionClass{}
_ functionClass = &jsonContainsPathFunctionClass{}
_ functionClass = &jsonValidFunctionClass{}
_ functionClass = &jsonArrayAppendFunctionClass{}
_ functionClass = &jsonArrayInsertFunctionClass{}
_ functionClass = &jsonMergePatchFunctionClass{}
_ functionClass = &jsonMergePreserveFunctionClass{}
_ functionClass = &jsonPrettyFunctionClass{}
_ functionClass = &jsonQuoteFunctionClass{}
_ functionClass = &jsonSearchFunctionClass{}
_ functionClass = &jsonStorageSizeFunctionClass{}
_ functionClass = &jsonDepthFunctionClass{}
_ functionClass = &jsonKeysFunctionClass{}
_ functionClass = &jsonLengthFunctionClass{}
_ builtinFunc = &builtinJSONTypeSig{}
_ builtinFunc = &builtinJSONUnquoteSig{}
_ builtinFunc = &builtinJSONArraySig{}
_ builtinFunc = &builtinJSONObjectSig{}
_ builtinFunc = &builtinJSONExtractSig{}
_ builtinFunc = &builtinJSONSetSig{}
_ builtinFunc = &builtinJSONInsertSig{}
_ builtinFunc = &builtinJSONReplaceSig{}
_ builtinFunc = &builtinJSONRemoveSig{}
_ builtinFunc = &builtinJSONMergeSig{}
_ builtinFunc = &builtinJSONContainsSig{}
_ builtinFunc = &builtinJSONLengthSig{}
)
type jsonTypeFunctionClass struct {
baseFunctionClass
}
type builtinJSONTypeSig struct {
baseBuiltinFunc
}
func (b *builtinJSONTypeSig) Clone() builtinFunc {
newSig := &builtinJSONTypeSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonTypeFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETString, types.ETJson)
bf.tp.Flen = 51 // Flen of JSON_TYPE is length of UNSIGNED INTEGER.
sig := &builtinJSONTypeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonTypeSig)
return sig, nil
}
func (b *builtinJSONTypeSig) evalString(row chunk.Row) (res string, isNull bool, err error) {
var j json.BinaryJSON
j, isNull, err = b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return "", isNull, errors.Trace(err)
}
return j.Type(), false, nil
}
type jsonExtractFunctionClass struct {
baseFunctionClass
}
type builtinJSONExtractSig struct {
baseBuiltinFunc
}
func (b *builtinJSONExtractSig) Clone() builtinFunc {
newSig := &builtinJSONExtractSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonExtractFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := make([]types.EvalType, 0, len(args))
argTps = append(argTps, types.ETJson)
for range args[1:] {
argTps = append(argTps, types.ETString)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
sig := &builtinJSONExtractSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonExtractSig)
return sig, nil
}
func (b *builtinJSONExtractSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
res, isNull, err = b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return
}
pathExprs := make([]json.PathExpression, 0, len(b.args)-1)
for _, arg := range b.args[1:] {
var s string
s, isNull, err = arg.EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
pathExpr, err := json.ParseJSONPathExpr(s)
if err != nil {
return res, true, errors.Trace(err)
}
pathExprs = append(pathExprs, pathExpr)
}
var found bool
if res, found = res.Extract(pathExprs); !found {
return res, true, nil
}
return res, false, nil
}
type jsonUnquoteFunctionClass struct {
baseFunctionClass
}
type builtinJSONUnquoteSig struct {
baseBuiltinFunc
}
func (b *builtinJSONUnquoteSig) Clone() builtinFunc {
newSig := &builtinJSONUnquoteSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonUnquoteFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETString, types.ETJson)
args[0].GetType().Flag &= ^mysql.ParseToJSONFlag
sig := &builtinJSONUnquoteSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonUnquoteSig)
return sig, nil
}
func (b *builtinJSONUnquoteSig) evalString(row chunk.Row) (res string, isNull bool, err error) {
var j json.BinaryJSON
j, isNull, err = b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return "", isNull, errors.Trace(err)
}
res, err = j.Unquote()
return res, err != nil, errors.Trace(err)
}
type jsonSetFunctionClass struct {
baseFunctionClass
}
type builtinJSONSetSig struct {
baseBuiltinFunc
}
func (b *builtinJSONSetSig) Clone() builtinFunc {
newSig := &builtinJSONSetSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonSetFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
if len(args)&1 != 1 {
return nil, ErrIncorrectParameterCount.GenWithStackByArgs(c.funcName)
}
argTps := make([]types.EvalType, 0, len(args))
argTps = append(argTps, types.ETJson)
for i := 1; i < len(args)-1; i += 2 {
argTps = append(argTps, types.ETString, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
for i := 2; i < len(args); i += 2 {
args[i].GetType().Flag &= ^mysql.ParseToJSONFlag
}
sig := &builtinJSONSetSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonSetSig)
return sig, nil
}
func (b *builtinJSONSetSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
res, isNull, err = jsonModify(b.ctx, b.args, row, json.ModifySet)
return res, isNull, errors.Trace(err)
}
type jsonInsertFunctionClass struct {
baseFunctionClass
}
type builtinJSONInsertSig struct {
baseBuiltinFunc
}
func (b *builtinJSONInsertSig) Clone() builtinFunc {
newSig := &builtinJSONInsertSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonInsertFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
if len(args)&1 != 1 {
return nil, ErrIncorrectParameterCount.GenWithStackByArgs(c.funcName)
}
argTps := make([]types.EvalType, 0, len(args))
argTps = append(argTps, types.ETJson)
for i := 1; i < len(args)-1; i += 2 {
argTps = append(argTps, types.ETString, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
for i := 2; i < len(args); i += 2 {
args[i].GetType().Flag &= ^mysql.ParseToJSONFlag
}
sig := &builtinJSONInsertSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonInsertSig)
return sig, nil
}
func (b *builtinJSONInsertSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
res, isNull, err = jsonModify(b.ctx, b.args, row, json.ModifyInsert)
return res, isNull, errors.Trace(err)
}
type jsonReplaceFunctionClass struct {
baseFunctionClass
}
type builtinJSONReplaceSig struct {
baseBuiltinFunc
}
func (b *builtinJSONReplaceSig) Clone() builtinFunc {
newSig := &builtinJSONReplaceSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonReplaceFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
if len(args)&1 != 1 {
return nil, ErrIncorrectParameterCount.GenWithStackByArgs(c.funcName)
}
argTps := make([]types.EvalType, 0, len(args))
argTps = append(argTps, types.ETJson)
for i := 1; i < len(args)-1; i += 2 {
argTps = append(argTps, types.ETString, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
for i := 2; i < len(args); i += 2 {
args[i].GetType().Flag &= ^mysql.ParseToJSONFlag
}
sig := &builtinJSONReplaceSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonReplaceSig)
return sig, nil
}
func (b *builtinJSONReplaceSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
res, isNull, err = jsonModify(b.ctx, b.args, row, json.ModifyReplace)
return res, isNull, errors.Trace(err)
}
type jsonRemoveFunctionClass struct {
baseFunctionClass
}
type builtinJSONRemoveSig struct {
baseBuiltinFunc
}
func (b *builtinJSONRemoveSig) Clone() builtinFunc {
newSig := &builtinJSONRemoveSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonRemoveFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := make([]types.EvalType, 0, len(args))
argTps = append(argTps, types.ETJson)
for range args[1:] {
argTps = append(argTps, types.ETString)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
sig := &builtinJSONRemoveSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonRemoveSig)
return sig, nil
}
func (b *builtinJSONRemoveSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
res, isNull, err = b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
pathExprs := make([]json.PathExpression, 0, len(b.args)-1)
for _, arg := range b.args[1:] {
var s string
s, isNull, err = arg.EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
var pathExpr json.PathExpression
pathExpr, err = json.ParseJSONPathExpr(s)
if err != nil {
return res, true, errors.Trace(err)
}
pathExprs = append(pathExprs, pathExpr)
}
res, err = res.Remove(pathExprs)
if err != nil {
return res, true, errors.Trace(err)
}
return res, false, nil
}
type jsonMergeFunctionClass struct {
baseFunctionClass
}
type builtinJSONMergeSig struct {
baseBuiltinFunc
}
func (b *builtinJSONMergeSig) Clone() builtinFunc {
newSig := &builtinJSONMergeSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonMergeFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := make([]types.EvalType, 0, len(args))
for range args {
argTps = append(argTps, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
sig := &builtinJSONMergeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonMergeSig)
return sig, nil
}
func (b *builtinJSONMergeSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
values := make([]json.BinaryJSON, 0, len(b.args))
for _, arg := range b.args {
var value json.BinaryJSON
value, isNull, err = arg.EvalJSON(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
values = append(values, value)
}
res = json.MergeBinary(values)
return res, false, nil
}
type jsonObjectFunctionClass struct {
baseFunctionClass
}
type builtinJSONObjectSig struct {
baseBuiltinFunc
}
func (b *builtinJSONObjectSig) Clone() builtinFunc {
newSig := &builtinJSONObjectSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonObjectFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
if len(args)&1 != 0 {
return nil, ErrIncorrectParameterCount.GenWithStackByArgs(c.funcName)
}
argTps := make([]types.EvalType, 0, len(args))
for i := 0; i < len(args)-1; i += 2 {
argTps = append(argTps, types.ETString, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
for i := 1; i < len(args); i += 2 {
args[i].GetType().Flag &= ^mysql.ParseToJSONFlag
}
sig := &builtinJSONObjectSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonObjectSig)
return sig, nil
}
func (b *builtinJSONObjectSig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
if len(b.args)&1 == 1 {
err = ErrIncorrectParameterCount.GenWithStackByArgs(ast.JSONObject)
return res, true, errors.Trace(err)
}
jsons := make(map[string]interface{}, len(b.args)>>1)
var key string
var value json.BinaryJSON
for i, arg := range b.args {
if i&1 == 0 {
key, isNull, err = arg.EvalString(b.ctx, row)
if err != nil {
return res, true, errors.Trace(err)
}
if isNull {
err = errors.New("JSON documents may not contain NULL member names")
return res, true, errors.Trace(err)
}
} else {
value, isNull, err = arg.EvalJSON(b.ctx, row)
if err != nil {
return res, true, errors.Trace(err)
}
if isNull {
value = json.CreateBinary(nil)
}
jsons[key] = value
}
}
return json.CreateBinary(jsons), false, nil
}
type jsonArrayFunctionClass struct {
baseFunctionClass
}
type builtinJSONArraySig struct {
baseBuiltinFunc
}
func (b *builtinJSONArraySig) Clone() builtinFunc {
newSig := &builtinJSONArraySig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonArrayFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := make([]types.EvalType, 0, len(args))
for range args {
argTps = append(argTps, types.ETJson)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETJson, argTps...)
for i := range args {
args[i].GetType().Flag &= ^mysql.ParseToJSONFlag
}
sig := &builtinJSONArraySig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonArraySig)
return sig, nil
}
func (b *builtinJSONArraySig) evalJSON(row chunk.Row) (res json.BinaryJSON, isNull bool, err error) {
jsons := make([]interface{}, 0, len(b.args))
for _, arg := range b.args {
j, isNull, err := arg.EvalJSON(b.ctx, row)
if err != nil {
return res, true, errors.Trace(err)
}
if isNull {
j = json.CreateBinary(nil)
}
jsons = append(jsons, j)
}
return json.CreateBinary(jsons), false, nil
}
type jsonContainsPathFunctionClass struct {
baseFunctionClass
}
type builtinJSONContainsPathSig struct {
baseBuiltinFunc
}
func (b *builtinJSONContainsPathSig) Clone() builtinFunc {
newSig := &builtinJSONContainsPathSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonContainsPathFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := []types.EvalType{types.ETJson, types.ETString}
for i := 3; i <= len(args); i++ {
argTps = append(argTps, types.ETString)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETInt, argTps...)
sig := &builtinJSONContainsPathSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonContainsPathSig)
return sig, nil
}
func (b *builtinJSONContainsPathSig) evalInt(row chunk.Row) (res int64, isNull bool, err error) {
obj, isNull, err := b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
containType, isNull, err := b.args[1].EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
if containType != json.ContainsPathAll && containType != json.ContainsPathOne {
return res, true, json.ErrInvalidJSONContainsPathType
}
var pathExpr json.PathExpression
contains := int64(1)
for i := 2; i < len(b.args); i++ {
path, isNull, err := b.args[i].EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
if pathExpr, err = json.ParseJSONPathExpr(path); err != nil {
return res, true, errors.Trace(err)
}
_, exists := obj.Extract([]json.PathExpression{pathExpr})
switch {
case exists && containType == json.ContainsPathOne:
return 1, false, nil
case !exists && containType == json.ContainsPathOne:
contains = 0
case !exists && containType == json.ContainsPathAll:
return 0, false, nil
}
}
return contains, false, nil
}
func jsonModify(ctx sessionctx.Context, args []Expression, row chunk.Row, mt json.ModifyType) (res json.BinaryJSON, isNull bool, err error) {
res, isNull, err = args[0].EvalJSON(ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
pathExprs := make([]json.PathExpression, 0, (len(args)-1)/2+1)
for i := 1; i < len(args); i += 2 {
// TODO: We can cache pathExprs if args are constants.
var s string
s, isNull, err = args[i].EvalString(ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
var pathExpr json.PathExpression
pathExpr, err = json.ParseJSONPathExpr(s)
if err != nil {
return res, true, errors.Trace(err)
}
pathExprs = append(pathExprs, pathExpr)
}
values := make([]json.BinaryJSON, 0, (len(args)-1)/2+1)
for i := 2; i < len(args); i += 2 {
var value json.BinaryJSON
value, isNull, err = args[i].EvalJSON(ctx, row)
if err != nil {
return res, true, errors.Trace(err)
}
if isNull {
value = json.CreateBinary(nil)
}
values = append(values, value)
}
res, err = res.Modify(pathExprs, values, mt)
if err != nil {
return res, true, errors.Trace(err)
}
return res, false, nil
}
type jsonContainsFunctionClass struct {
baseFunctionClass
}
type builtinJSONContainsSig struct {
baseBuiltinFunc
}
func (b *builtinJSONContainsSig) Clone() builtinFunc {
newSig := &builtinJSONContainsSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonContainsFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := []types.EvalType{types.ETJson, types.ETJson}
if len(args) == 3 {
argTps = append(argTps, types.ETString)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETInt, argTps...)
sig := &builtinJSONContainsSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonContainsSig)
return sig, nil
}
func (b *builtinJSONContainsSig) evalInt(row chunk.Row) (res int64, isNull bool, err error) {
obj, isNull, err := b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
target, isNull, err := b.args[1].EvalJSON(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
var pathExpr json.PathExpression
if len(b.args) == 3 {
path, isNull, err := b.args[2].EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
pathExpr, err = json.ParseJSONPathExpr(path)
if err != nil {
return res, true, errors.Trace(err)
}
if pathExpr.ContainsAnyAsterisk() {
return res, true, json.ErrInvalidJSONPathWildcard
}
var exists bool
obj, exists = obj.Extract([]json.PathExpression{pathExpr})
if !exists {
return res, true, nil
}
}
if json.ContainsBinary(obj, target) {
return 1, false, nil
}
return 0, false, nil
}
type jsonValidFunctionClass struct {
baseFunctionClass
}
func (c *jsonValidFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_VALID")
}
type jsonArrayAppendFunctionClass struct {
baseFunctionClass
}
func (c *jsonArrayAppendFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_ARRAY_APPEND")
}
type jsonArrayInsertFunctionClass struct {
baseFunctionClass
}
func (c *jsonArrayInsertFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_ARRAY_INSERT")
}
type jsonMergePatchFunctionClass struct {
baseFunctionClass
}
func (c *jsonMergePatchFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_MERGE_PATCH")
}
type jsonMergePreserveFunctionClass struct {
baseFunctionClass
}
func (c *jsonMergePreserveFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_MERGE_PRESERVE")
}
type jsonPrettyFunctionClass struct {
baseFunctionClass
}
func (c *jsonPrettyFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_PRETTY")
}
type jsonQuoteFunctionClass struct {
baseFunctionClass
}
func (c *jsonQuoteFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_QUOTE")
}
type jsonSearchFunctionClass struct {
baseFunctionClass
}
func (c *jsonSearchFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_SEARCH")
}
type jsonStorageSizeFunctionClass struct {
baseFunctionClass
}
func (c *jsonStorageSizeFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_STORAGE_SIZE")
}
type jsonDepthFunctionClass struct {
baseFunctionClass
}
func (c *jsonDepthFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_DEPTH")
}
type jsonKeysFunctionClass struct {
baseFunctionClass
}
func (c *jsonKeysFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "JSON_KEYS")
}
type jsonLengthFunctionClass struct {
baseFunctionClass
}
type builtinJSONLengthSig struct {
baseBuiltinFunc
}
func (b *builtinJSONLengthSig) Clone() builtinFunc {
newSig := &builtinJSONLengthSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (c *jsonLengthFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTps := make([]types.EvalType, 0, len(args))
argTps = append(argTps, types.ETJson)
if len(args) == 2 {
argTps = append(argTps, types.ETString)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETInt, argTps...)
sig := &builtinJSONLengthSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_JsonLengthSig)
return sig, nil
}
func (b *builtinJSONLengthSig) evalInt(row chunk.Row) (res int64, isNull bool, err error) {
obj, isNull, err := b.args[0].EvalJSON(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
if obj.TypeCode != json.TypeCodeObject && obj.TypeCode != json.TypeCodeArray {
return 1, false, nil
}
if len(b.args) == 2 {
path, isNull, err := b.args[1].EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
pathExpr, err := json.ParseJSONPathExpr(path)
if err != nil {
return res, true, errors.Trace(err)
}
if pathExpr.ContainsAnyAsterisk() {
return res, true, json.ErrInvalidJSONPathWildcard
}
var exists bool
obj, exists = obj.Extract([]json.PathExpression{pathExpr})
if !exists {
return res, true, nil
}
if obj.TypeCode != json.TypeCodeObject && obj.TypeCode != json.TypeCodeArray {
return 1, false, nil
}
}
return int64(obj.GetElemCount()), false, nil
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/hanchuanchuan-goInception.git
git@gitlife.ru:oschina-mirror/hanchuanchuan-goInception.git
oschina-mirror
hanchuanchuan-goInception
hanchuanchuan-goInception
v1.2.5