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

OSCHINA-MIRROR/hanchuanchuan-goInception

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
builtin_string_test.go 64 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
hanchuanchuan Отправлено 6 лет назад 27f3c5a
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150
// Copyright 2015 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 (
"fmt"
"strconv"
"strings"
"time"
"github.com/hanchuanchuan/goInception/ast"
"github.com/hanchuanchuan/goInception/mysql"
"github.com/hanchuanchuan/goInception/sessionctx/stmtctx"
"github.com/hanchuanchuan/goInception/terror"
"github.com/hanchuanchuan/goInception/types"
"github.com/hanchuanchuan/goInception/util/charset"
"github.com/hanchuanchuan/goInception/util/chunk"
"github.com/hanchuanchuan/goInception/util/mock"
"github.com/hanchuanchuan/goInception/util/testleak"
"github.com/hanchuanchuan/goInception/util/testutil"
. "github.com/pingcap/check"
"github.com/pingcap/errors"
)
func (s *testEvaluatorSuite) TestLength(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args interface{}
expected int64
isNil bool
getErr bool
}{
{"abc", 3, false, false},
{"你好", 6, false, false},
{1, 1, false, false},
{3.14, 4, false, false},
{types.NewDecFromFloatForTest(123.123), 7, false, false},
{types.Time{Time: types.FromGoTime(time.Now()), Fsp: 6, Type: mysql.TypeDatetime}, 26, false, false},
{types.NewBinaryLiteralFromUint(0x01, -1), 1, false, false},
{types.Set{Value: 1, Name: "abc"}, 3, false, false},
{types.Duration{Duration: time.Duration(12*time.Hour + 1*time.Minute + 1*time.Second), Fsp: types.DefaultFsp}, 8, false, false},
{nil, 0, true, false},
{errors.New("must error"), 0, false, true},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Length, s.primitiveValsToConstants([]interface{}{t.args})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetInt64(), Equals, t.expected)
}
}
}
_, err := funcs[ast.Length].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestASCII(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args interface{}
expected int64
isNil bool
getErr bool
}{
{"2", 50, false, false},
{2, 50, false, false},
{"23", 50, false, false},
{23, 50, false, false},
{2.3, 50, false, false},
{nil, 0, true, false},
{"", 0, false, false},
{"你好", 228, false, false},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.ASCII, s.primitiveValsToConstants([]interface{}{t.args})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetInt64(), Equals, t.expected)
}
}
}
_, err := funcs[ast.Length].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestConcat(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
retType *types.FieldType
}{
{
[]interface{}{nil},
true, false, "",
&types.FieldType{Tp: mysql.TypeVarString, Flen: 0, Decimal: types.UnspecifiedLength, Charset: charset.CharsetBin, Collate: charset.CollationBin, Flag: mysql.BinaryFlag},
},
{
[]interface{}{"a", "b",
1, 2,
1.1, 1.2,
types.NewDecFromFloatForTest(1.1),
types.Time{
Time: types.FromDate(2000, 1, 1, 12, 01, 01, 0),
Type: mysql.TypeDatetime,
Fsp: types.DefaultFsp},
types.Duration{
Duration: time.Duration(12*time.Hour + 1*time.Minute + 1*time.Second),
Fsp: types.DefaultFsp},
},
false, false, "ab121.11.21.12000-01-01 12:01:0112:01:01",
&types.FieldType{Tp: mysql.TypeVarString, Flen: 40, Decimal: types.UnspecifiedLength, Charset: charset.CharsetBin, Collate: charset.CollationBin, Flag: mysql.BinaryFlag},
},
{
[]interface{}{"a", "b", nil, "c"},
true, false, "",
&types.FieldType{Tp: mysql.TypeVarString, Flen: 3, Decimal: types.UnspecifiedLength, Charset: charset.CharsetBin, Collate: charset.CollationBin, Flag: mysql.BinaryFlag},
},
{
[]interface{}{errors.New("must error")},
false, true, "",
&types.FieldType{Tp: mysql.TypeVarString, Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength, Charset: charset.CharsetBin, Collate: charset.CollationBin, Flag: mysql.BinaryFlag},
},
}
fcName := ast.Concat
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, fcName, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
v, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(v.Kind(), Equals, types.KindNull)
} else {
c.Assert(v.GetString(), Equals, t.res)
}
}
}
}
func (s *testEvaluatorSuite) TestConcatWS(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
expected string
}{
{
[]interface{}{nil, nil},
true, false, "",
},
{
[]interface{}{nil, "a", "b"},
true, false, "",
},
{
[]interface{}{",", "a", "b", "hello", `$^%`},
false, false,
`a,b,hello,$^%`,
},
{
[]interface{}{"|", "a", nil, "b", "c"},
false, false,
"a|b|c",
},
{
[]interface{}{",", "a", ",", "b", "c"},
false, false,
"a,,,b,c",
},
{
[]interface{}{errors.New("must error"), "a", "b"},
false, true, "",
},
{
[]interface{}{",", "a", "b", 1, 2, 1.1, 0.11,
types.NewDecFromFloatForTest(1.1),
types.Time{
Time: types.FromDate(2000, 1, 1, 12, 01, 01, 0),
Type: mysql.TypeDatetime,
Fsp: types.DefaultFsp},
types.Duration{
Duration: time.Duration(12*time.Hour + 1*time.Minute + 1*time.Second),
Fsp: types.DefaultFsp},
},
false, false, "a,b,1,2,1.1,0.11,1.1,2000-01-01 12:01:01,12:01:01",
},
}
fcName := ast.ConcatWS
// ERROR 1582 (42000): Incorrect parameter count in the call to native function 'concat_ws'
f, err := newFunctionForTest(s.ctx, fcName, s.primitiveValsToConstants([]interface{}{nil})...)
c.Assert(err, NotNil)
for _, t := range cases {
f, err = newFunctionForTest(s.ctx, fcName, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
val, err1 := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err1, NotNil)
} else {
c.Assert(err1, IsNil)
if t.isNil {
c.Assert(val.Kind(), Equals, types.KindNull)
} else {
c.Assert(val.GetString(), Equals, t.expected)
}
}
}
_, err = funcs[ast.ConcatWS].getFunction(s.ctx, s.primitiveValsToConstants([]interface{}{nil, nil}))
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestLeft(c *C) {
defer testleak.AfterTest(c)()
stmtCtx := s.ctx.GetSessionVars().StmtCtx
origin := stmtCtx.IgnoreTruncate
stmtCtx.IgnoreTruncate = true
defer func() {
stmtCtx.IgnoreTruncate = origin
}()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{"abcde", 3}, false, false, "abc"},
{[]interface{}{"abcde", 0}, false, false, ""},
{[]interface{}{"abcde", 1.2}, false, false, "a"},
{[]interface{}{"abcde", 1.9}, false, false, "ab"},
{[]interface{}{"abcde", -1}, false, false, ""},
{[]interface{}{"abcde", 100}, false, false, "abcde"},
{[]interface{}{"abcde", nil}, true, false, ""},
{[]interface{}{nil, 3}, true, false, ""},
{[]interface{}{"abcde", "3"}, false, false, "abc"},
{[]interface{}{"abcde", "a"}, false, false, ""},
{[]interface{}{1234, 3}, false, false, "123"},
{[]interface{}{12.34, 3}, false, false, "12."},
{[]interface{}{types.NewBinaryLiteralFromUint(0x0102, -1), 1}, false, false, string([]byte{0x01})},
{[]interface{}{errors.New("must err"), 0}, false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Left, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
v, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(v.Kind(), Equals, types.KindNull)
} else {
c.Assert(v.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Left].getFunction(s.ctx, []Expression{varcharCon, int8Con})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestRight(c *C) {
defer testleak.AfterTest(c)()
stmtCtx := s.ctx.GetSessionVars().StmtCtx
origin := stmtCtx.IgnoreTruncate
stmtCtx.IgnoreTruncate = true
defer func() {
stmtCtx.IgnoreTruncate = origin
}()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{"abcde", 3}, false, false, "cde"},
{[]interface{}{"abcde", 0}, false, false, ""},
{[]interface{}{"abcde", 1.2}, false, false, "e"},
{[]interface{}{"abcde", 1.9}, false, false, "de"},
{[]interface{}{"abcde", -1}, false, false, ""},
{[]interface{}{"abcde", 100}, false, false, "abcde"},
{[]interface{}{"abcde", nil}, true, false, ""},
{[]interface{}{nil, 1}, true, false, ""},
{[]interface{}{"abcde", "3"}, false, false, "cde"},
{[]interface{}{"abcde", "a"}, false, false, ""},
{[]interface{}{1234, 3}, false, false, "234"},
{[]interface{}{12.34, 3}, false, false, ".34"},
{[]interface{}{types.NewBinaryLiteralFromUint(0x0102, -1), 1}, false, false, string([]byte{0x02})},
{[]interface{}{errors.New("must err"), 0}, false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Right, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
v, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(v.Kind(), Equals, types.KindNull)
} else {
c.Assert(v.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Right].getFunction(s.ctx, []Expression{varcharCon, int8Con})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestRepeat(c *C) {
defer testleak.AfterTest(c)()
args := []interface{}{"a", int64(2)}
fc := funcs[ast.Repeat]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.GetString(), Equals, "aa")
args = []interface{}{"a", uint64(2)}
f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.GetString(), Equals, "aa")
args = []interface{}{"a", uint64(16777217)}
f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.IsNull(), IsTrue)
args = []interface{}{"a", uint64(16777216)}
f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.IsNull(), IsFalse)
args = []interface{}{"a", int64(-1)}
f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.GetString(), Equals, "")
args = []interface{}{"a", int64(0)}
f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.GetString(), Equals, "")
args = []interface{}{"a", uint64(0)}
f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(args...)))
c.Assert(err, IsNil)
v, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(v.GetString(), Equals, "")
}
func (s *testEvaluatorSuite) TestRepeatSig(c *C) {
colTypes := []*types.FieldType{
{Tp: mysql.TypeVarchar},
{Tp: mysql.TypeLonglong},
}
resultType := &types.FieldType{Tp: mysql.TypeVarchar, Flen: 1000}
args := []Expression{
&Column{Index: 0, RetType: colTypes[0]},
&Column{Index: 1, RetType: colTypes[1]},
}
base := baseBuiltinFunc{args: args, ctx: s.ctx, tp: resultType}
repeat := &builtinRepeatSig{base, 1000}
cases := []struct {
args []interface{}
warning int
res string
}{
{[]interface{}{"a", int64(6)}, 0, "aaaaaa"},
{[]interface{}{"a", int64(10001)}, 1, ""},
{[]interface{}{"毅", int64(6)}, 0, "毅毅毅毅毅毅"},
{[]interface{}{"毅", int64(334)}, 2, ""},
}
for _, t := range cases {
input := chunk.NewChunkWithCapacity(colTypes, 10)
input.AppendString(0, t.args[0].(string))
input.AppendInt64(1, t.args[1].(int64))
res, isNull, err := repeat.evalString(input.GetRow(0))
c.Assert(res, Equals, t.res)
c.Assert(err, IsNil)
if t.warning == 0 {
c.Assert(isNull, IsFalse)
} else {
c.Assert(isNull, IsTrue)
c.Assert(err, IsNil)
warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings()
c.Assert(len(warnings), Equals, t.warning)
lastWarn := warnings[len(warnings)-1]
c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue)
}
}
}
func (s *testEvaluatorSuite) TestLower(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{nil}, true, false, ""},
{[]interface{}{"ab"}, false, false, "ab"},
{[]interface{}{1}, false, false, "1"},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Lower, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
v, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(v.Kind(), Equals, types.KindNull)
} else {
c.Assert(v.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Lower].getFunction(s.ctx, []Expression{varcharCon})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestUpper(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{nil}, true, false, ""},
{[]interface{}{"ab"}, false, false, "ab"},
{[]interface{}{1}, false, false, "1"},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Upper, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
v, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(v.Kind(), Equals, types.KindNull)
} else {
c.Assert(v.GetString(), Equals, strings.ToUpper(t.res))
}
}
}
_, err := funcs[ast.Upper].getFunction(s.ctx, []Expression{varcharCon})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestReverse(c *C) {
defer testleak.AfterTest(c)()
fc := funcs[ast.Reverse]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(nil)))
c.Assert(err, IsNil)
d, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(d.Kind(), Equals, types.KindNull)
tbl := []struct {
Input interface{}
Expect string
}{
{"abc", "cba"},
{"LIKE", "EKIL"},
{123, "321"},
{"", ""},
}
dtbl := tblToDtbl(tbl)
for _, t := range dtbl {
f, err = fc.getFunction(s.ctx, s.datumsToConstants(t["Input"]))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
d, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(d, testutil.DatumEquals, t["Expect"][0])
}
}
func (s *testEvaluatorSuite) TestStrcmp(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res int64
}{
{[]interface{}{"123", "123"}, false, false, 0},
{[]interface{}{"123", "1"}, false, false, 1},
{[]interface{}{"1", "123"}, false, false, -1},
{[]interface{}{"123", "45"}, false, false, -1},
{[]interface{}{123, "123"}, false, false, 0},
{[]interface{}{"12.34", 12.34}, false, false, 0},
{[]interface{}{nil, "123"}, true, false, 0},
{[]interface{}{"123", nil}, true, false, 0},
{[]interface{}{"", "123"}, false, false, -1},
{[]interface{}{"123", ""}, false, false, 1},
{[]interface{}{"", ""}, false, false, 0},
{[]interface{}{"", nil}, true, false, 0},
{[]interface{}{nil, ""}, true, false, 0},
{[]interface{}{nil, nil}, true, false, 0},
{[]interface{}{"123", errors.New("must err")}, false, true, 0},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Strcmp, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetInt64(), Equals, t.res)
}
}
}
}
func (s *testEvaluatorSuite) TestReplace(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
flen int
}{
{[]interface{}{"www.mysql.com", "mysql", "pingcap"}, false, false, "www.pingcap.com", 17},
{[]interface{}{"www.mysql.com", "w", 1}, false, false, "111.mysql.com", 260},
{[]interface{}{1234, 2, 55}, false, false, "15534", 20},
{[]interface{}{"", "a", "b"}, false, false, "", 0},
{[]interface{}{"abc", "", "d"}, false, false, "abc", 3},
{[]interface{}{"aaa", "a", ""}, false, false, "", 3},
{[]interface{}{nil, "a", "b"}, true, false, "", 0},
{[]interface{}{"a", nil, "b"}, true, false, "", 1},
{[]interface{}{"a", "b", nil}, true, false, "", 1},
{[]interface{}{errors.New("must err"), "a", "b"}, false, true, "", -1},
}
for i, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Replace, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil, Commentf("test %v", i))
c.Assert(f.GetType().Flen, Equals, t.flen, Commentf("test %v", i))
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil, Commentf("test %v", i))
} else {
c.Assert(err, IsNil, Commentf("test %v", i))
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull, Commentf("test %v", i))
} else {
c.Assert(d.GetString(), Equals, t.res, Commentf("test %v", i))
}
}
}
_, err := funcs[ast.Replace].getFunction(s.ctx, []Expression{Zero, Zero, Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestSubstring(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{"Quadratically", 5}, false, false, "ratically"},
{[]interface{}{"Sakila", 1}, false, false, "Sakila"},
{[]interface{}{"Sakila", 2}, false, false, "akila"},
{[]interface{}{"Sakila", -3}, false, false, "ila"},
{[]interface{}{"Sakila", 0}, false, false, ""},
{[]interface{}{"Sakila", 100}, false, false, ""},
{[]interface{}{"Sakila", -100}, false, false, ""},
{[]interface{}{"Quadratically", 5, 6}, false, false, "ratica"},
{[]interface{}{"Sakila", -5, 3}, false, false, "aki"},
{[]interface{}{"Sakila", 2, 0}, false, false, ""},
{[]interface{}{"Sakila", 2, -1}, false, false, ""},
{[]interface{}{"Sakila", 2, 100}, false, false, "akila"},
{[]interface{}{nil, 2, 3}, true, false, ""},
{[]interface{}{"Sakila", nil, 3}, true, false, ""},
{[]interface{}{"Sakila", 2, nil}, true, false, ""},
{[]interface{}{errors.New("must error"), 2, 3}, false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Substring, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Substring].getFunction(s.ctx, []Expression{Zero, Zero, Zero})
c.Assert(err, IsNil)
_, err = funcs[ast.Substring].getFunction(s.ctx, []Expression{Zero, Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestConvert(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
str string
cs string
result string
}{
{"haha", "utf8", "haha"},
{"haha", "ascii", "haha"},
{"haha", "binary", "haha"},
}
for _, v := range tbl {
fc := funcs[ast.Convert]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(v.str, v.cs)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r.Kind(), Equals, types.KindString)
c.Assert(r.GetString(), Equals, v.result)
}
// Test case for error
errTbl := []struct {
str interface{}
cs string
result string
}{
{"haha", "wrongcharset", "haha"},
}
for _, v := range errTbl {
fc := funcs[ast.Convert]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(v.str, v.cs)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
_, err = evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, NotNil)
}
}
func (s *testEvaluatorSuite) TestSubstringIndex(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{"www.pingcap.com", ".", 2}, false, false, "www.pingcap"},
{[]interface{}{"www.pingcap.com", ".", -2}, false, false, "pingcap.com"},
{[]interface{}{"www.pingcap.com", ".", 0}, false, false, ""},
{[]interface{}{"www.pingcap.com", ".", 100}, false, false, "www.pingcap.com"},
{[]interface{}{"www.pingcap.com", ".", -100}, false, false, "www.pingcap.com"},
{[]interface{}{"www.pingcap.com", "d", 0}, false, false, ""},
{[]interface{}{"www.pingcap.com", "d", 1}, false, false, "www.pingcap.com"},
{[]interface{}{"www.pingcap.com", "d", -1}, false, false, "www.pingcap.com"},
{[]interface{}{"www.pingcap.com", "", 0}, false, false, ""},
{[]interface{}{"www.pingcap.com", "", 1}, false, false, ""},
{[]interface{}{"www.pingcap.com", "", -1}, false, false, ""},
{[]interface{}{"", ".", 0}, false, false, ""},
{[]interface{}{"", ".", 1}, false, false, ""},
{[]interface{}{"", ".", -1}, false, false, ""},
{[]interface{}{nil, ".", 1}, true, false, ""},
{[]interface{}{"www.pingcap.com", nil, 1}, true, false, ""},
{[]interface{}{"www.pingcap.com", ".", nil}, true, false, ""},
{[]interface{}{errors.New("must error"), ".", 1}, false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.SubstringIndex, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.SubstringIndex].getFunction(s.ctx, []Expression{Zero, Zero, Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestSpace(c *C) {
defer testleak.AfterTest(c)()
stmtCtx := s.ctx.GetSessionVars().StmtCtx
origin := stmtCtx.IgnoreTruncate
stmtCtx.IgnoreTruncate = true
defer func() {
stmtCtx.IgnoreTruncate = origin
}()
cases := []struct {
arg interface{}
isNil bool
getErr bool
res string
}{
{0, false, false, ""},
{3, false, false, " "},
{mysql.MaxBlobWidth + 1, true, false, ""},
{-1, false, false, ""},
{"abc", false, false, ""},
{"3", false, false, " "},
{1.2, false, false, " "},
{1.9, false, false, " "},
{nil, true, false, ""},
{errors.New("must error"), false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Space, s.primitiveValsToConstants([]interface{}{t.arg})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Space].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestSpaceSig(c *C) {
colTypes := []*types.FieldType{
{Tp: mysql.TypeLonglong},
}
resultType := &types.FieldType{Tp: mysql.TypeVarchar, Flen: 1000}
args := []Expression{
&Column{Index: 0, RetType: colTypes[0]},
}
base := baseBuiltinFunc{args: args, ctx: s.ctx, tp: resultType}
space := &builtinSpaceSig{base, 1000}
input := chunk.NewChunkWithCapacity(colTypes, 10)
input.AppendInt64(0, 6)
input.AppendInt64(0, 1001)
res, isNull, err := space.evalString(input.GetRow(0))
c.Assert(res, Equals, " ")
c.Assert(isNull, IsFalse)
c.Assert(err, IsNil)
res, isNull, err = space.evalString(input.GetRow(1))
c.Assert(res, Equals, "")
c.Assert(isNull, IsTrue)
c.Assert(err, IsNil)
warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings()
c.Assert(len(warnings), Equals, 1)
lastWarn := warnings[len(warnings)-1]
c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
}
func (s *testEvaluatorSuite) TestLocate(c *C) {
// 1. Test LOCATE without binary input.
defer testleak.AfterTest(c)()
tbl := []struct {
Args []interface{}
Want interface{}
}{
{[]interface{}{"bar", "foobarbar"}, 4},
{[]interface{}{"xbar", "foobar"}, 0},
{[]interface{}{"", "foobar"}, 1},
{[]interface{}{"foobar", ""}, 0},
{[]interface{}{"", ""}, 1},
{[]interface{}{"好世", "你好世界"}, 2},
{[]interface{}{"界面", "你好世界"}, 0},
{[]interface{}{"b", "中a英b文"}, 4},
{[]interface{}{"BaR", "foobArbar"}, 4},
{[]interface{}{nil, "foobar"}, nil},
{[]interface{}{"bar", nil}, nil},
{[]interface{}{"bar", "foobarbar", 5}, 7},
{[]interface{}{"xbar", "foobar", 1}, 0},
{[]interface{}{"", "foobar", 2}, 2},
{[]interface{}{"foobar", "", 1}, 0},
{[]interface{}{"", "", 2}, 0},
{[]interface{}{"A", "大A写的A", 0}, 0},
{[]interface{}{"A", "大A写的A", 1}, 2},
{[]interface{}{"A", "大A写的A", 2}, 2},
{[]interface{}{"A", "大A写的A", 3}, 5},
{[]interface{}{"bAr", "foobarBaR", 5}, 7},
{[]interface{}{nil, nil}, nil},
{[]interface{}{"", nil}, nil},
{[]interface{}{nil, ""}, nil},
{[]interface{}{nil, nil, 1}, nil},
{[]interface{}{"", nil, 1}, nil},
{[]interface{}{nil, "", 1}, nil},
{[]interface{}{"foo", nil, -1}, nil},
{[]interface{}{nil, "bar", 0}, nil},
}
Dtbl := tblToDtbl(tbl)
instr := funcs[ast.Locate]
for i, t := range Dtbl {
f, err := instr.getFunction(s.ctx, s.datumsToConstants(t["Args"]))
c.Assert(err, IsNil)
got, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(f, NotNil)
c.Assert(got, DeepEquals, t["Want"][0], Commentf("[%d]: args: %v", i, t["Args"]))
}
// 2. Test LOCATE with binary input
tbl2 := []struct {
Args []interface{}
Want interface{}
}{
{[]interface{}{[]byte("BaR"), "foobArbar"}, 0},
{[]interface{}{"BaR", []byte("foobArbar")}, 0},
{[]interface{}{[]byte("bAr"), "foobarBaR", 5}, 0},
{[]interface{}{"bAr", []byte("foobarBaR"), 5}, 0},
{[]interface{}{"bAr", []byte("foobarbAr"), 5}, 7},
}
Dtbl2 := tblToDtbl(tbl2)
for i, t := range Dtbl2 {
exprs := s.datumsToConstants(t["Args"])
types.SetBinChsClnFlag(exprs[0].GetType())
types.SetBinChsClnFlag(exprs[1].GetType())
f, err := instr.getFunction(s.ctx, exprs)
c.Assert(err, IsNil)
got, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(f, NotNil)
c.Assert(got, DeepEquals, t["Want"][0], Commentf("[%d]: args: %v", i, t["Args"]))
}
}
func (s *testEvaluatorSuite) TestTrim(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args []interface{}
isNil bool
getErr bool
res string
}{
{[]interface{}{" bar "}, false, false, "bar"},
{[]interface{}{"\t bar \n"}, false, false, "\t bar \n"},
{[]interface{}{"\r bar \t"}, false, false, "\r bar \t"},
{[]interface{}{" \tbar\n "}, false, false, "\tbar\n"},
{[]interface{}{""}, false, false, ""},
{[]interface{}{nil}, true, false, ""},
{[]interface{}{"xxxbarxxx", "x"}, false, false, "bar"},
{[]interface{}{"bar", "x"}, false, false, "bar"},
{[]interface{}{" bar ", ""}, false, false, " bar "},
{[]interface{}{"", "x"}, false, false, ""},
{[]interface{}{"bar", nil}, true, false, ""},
{[]interface{}{nil, "x"}, true, false, ""},
{[]interface{}{"xxxbarxxx", "x", int(ast.TrimLeading)}, false, false, "barxxx"},
{[]interface{}{"barxxyz", "xyz", int(ast.TrimTrailing)}, false, false, "barx"},
{[]interface{}{"xxxbarxxx", "x", int(ast.TrimBoth)}, false, false, "bar"},
// FIXME: the result for this test shuold be nil, current is "bar"
{[]interface{}{"bar", nil, int(ast.TrimLeading)}, false, false, "bar"},
{[]interface{}{errors.New("must error")}, false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Trim, s.primitiveValsToConstants(t.args)...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Trim].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
_, err = funcs[ast.Trim].getFunction(s.ctx, []Expression{Zero, Zero})
c.Assert(err, IsNil)
_, err = funcs[ast.Trim].getFunction(s.ctx, []Expression{Zero, Zero, Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestLTrim(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
arg interface{}
isNil bool
getErr bool
res string
}{
{" bar ", false, false, "bar "},
{"\t bar ", false, false, "\t bar "},
{" \tbar ", false, false, "\tbar "},
{"\t bar ", false, false, "\t bar "},
{" \tbar ", false, false, "\tbar "},
{"\r bar ", false, false, "\r bar "},
{" \rbar ", false, false, "\rbar "},
{"\n bar ", false, false, "\n bar "},
{" \nbar ", false, false, "\nbar "},
{"bar", false, false, "bar"},
{"", false, false, ""},
{nil, true, false, ""},
{errors.New("must error"), false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.LTrim, s.primitiveValsToConstants([]interface{}{t.arg})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.LTrim].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestRTrim(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
arg interface{}
isNil bool
getErr bool
res string
}{
{" bar ", false, false, " bar"},
{"bar", false, false, "bar"},
{"bar \n", false, false, "bar \n"},
{"bar\n ", false, false, "bar\n"},
{"bar \r", false, false, "bar \r"},
{"bar\r ", false, false, "bar\r"},
{"bar \t", false, false, "bar \t"},
{"bar\t ", false, false, "bar\t"},
{"", false, false, ""},
{nil, true, false, ""},
{errors.New("must error"), false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.RTrim, s.primitiveValsToConstants([]interface{}{t.arg})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.RTrim].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestHexFunc(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
arg interface{}
isNil bool
getErr bool
res string
}{
{"abc", false, false, "616263"},
{"你好", false, false, "E4BDA0E5A5BD"},
{12, false, false, "C"},
{12.3, false, false, "C"},
{12.8, false, false, "D"},
{-1, false, false, "FFFFFFFFFFFFFFFF"},
{-12.3, false, false, "FFFFFFFFFFFFFFF4"},
{-12.8, false, false, "FFFFFFFFFFFFFFF3"},
{types.NewBinaryLiteralFromUint(0xC, -1), false, false, "C"},
{0x12, false, false, "12"},
{nil, true, false, ""},
{errors.New("must err"), false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Hex, s.primitiveValsToConstants([]interface{}{t.arg})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Hex].getFunction(s.ctx, []Expression{int8Con})
c.Assert(err, IsNil)
_, err = funcs[ast.Hex].getFunction(s.ctx, []Expression{varcharCon})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestUnhexFunc(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
arg interface{}
isNil bool
getErr bool
res string
}{
{"4D7953514C", false, false, "MySQL"},
{"1267", false, false, string([]byte{0x12, 0x67})},
{"126", false, false, string([]byte{0x01, 0x26})},
{"", false, false, ""},
{1267, false, false, string([]byte{0x12, 0x67})},
{126, false, false, string([]byte{0x01, 0x26})},
{1267.3, true, false, ""},
{"string", true, false, ""},
{"你好", true, false, ""},
{nil, true, false, ""},
{errors.New("must error"), false, true, ""},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Unhex, s.primitiveValsToConstants([]interface{}{t.arg})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, t.res)
}
}
}
_, err := funcs[ast.Unhex].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestBitLength(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args interface{}
expected int64
isNil bool
getErr bool
}{
{"hi", 16, false, false},
{"你好", 48, false, false},
{"", 0, false, false},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.BitLength, s.primitiveValsToConstants([]interface{}{t.args})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetInt64(), Equals, t.expected)
}
}
}
_, err := funcs[ast.BitLength].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestChar(c *C) {
defer testleak.AfterTest(c)()
stmtCtx := s.ctx.GetSessionVars().StmtCtx
origin := stmtCtx.IgnoreTruncate
stmtCtx.IgnoreTruncate = true
defer func() {
stmtCtx.IgnoreTruncate = origin
}()
tbl := []struct {
str string
iNum int64
fNum float64
result string
}{
{"65", 66, 67.5, "ABD"}, // float
{"65", 16740, 67.5, "AAdD"}, // large num
{"65", -1, 67.5, "A\xff\xff\xff\xffD"}, // nagtive int
{"a", -1, 67.5, "\x00\xff\xff\xff\xffD"}, // invalid 'a'
}
for _, v := range tbl {
for _, char := range []interface{}{"utf8", nil} {
fc := funcs[ast.CharFunc]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(v.str, v.iNum, v.fNum, char)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
if err != nil {
fmt.Printf("%s\n", err.Error())
}
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result))
}
}
fc := funcs[ast.CharFunc]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums("65", 66, nil)))
c.Assert(err, IsNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum("AB"))
}
func (s *testEvaluatorSuite) TestCharLength(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
input interface{}
result interface{}
}{
{"33", 2}, // string
{"你好", 2}, // mb string
{33, 2}, // int
{3.14, 4}, // float
{nil, nil}, // nil
}
for _, v := range tbl {
fc := funcs[ast.CharLength]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(v.input)))
c.Assert(err, IsNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result))
}
// Test binary string
tbl = []struct {
input interface{}
result interface{}
}{
{"33", 2}, // string
{"你好", 6}, // mb string
{"CAFÉ", 5}, // mb string
{"", 0}, // mb string
{nil, nil}, // nil
}
for _, v := range tbl {
fc := funcs[ast.CharLength]
arg := s.datumsToConstants(types.MakeDatums(v.input))
tp := arg[0].GetType()
tp.Tp = mysql.TypeVarString
tp.Charset = charset.CharsetBin
tp.Collate = charset.CollationBin
tp.Flen = types.UnspecifiedLength
tp.Flag = mysql.BinaryFlag
f, err := fc.getFunction(s.ctx, arg)
c.Assert(err, IsNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result))
}
}
func (s *testEvaluatorSuite) TestFindInSet(c *C) {
defer testleak.AfterTest(c)()
for _, t := range []struct {
str interface{}
strlst interface{}
ret interface{}
}{
{"foo", "foo,bar", 1},
{"foo", "foobar,bar", 0},
{" foo ", "foo, foo ", 2},
{"", "foo,bar,", 3},
{"", "", 0},
{1, 1, 1},
{1, "1", 1},
{"1", 1, 1},
{"a,b", "a,b,c", 0},
{"foo", nil, nil},
{nil, "bar", nil},
} {
fc := funcs[ast.FindInSet]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(t.str, t.strlst)))
c.Assert(err, IsNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(t.ret), Commentf("FindInSet(%s, %s)", t.str, t.strlst))
}
}
func (s *testEvaluatorSuite) TestField(c *C) {
defer testleak.AfterTest(c)()
stmtCtx := s.ctx.GetSessionVars().StmtCtx
origin := stmtCtx.IgnoreTruncate
stmtCtx.IgnoreTruncate = true
defer func() {
stmtCtx.IgnoreTruncate = origin
}()
tbl := []struct {
argLst []interface{}
ret interface{}
}{
{[]interface{}{"ej", "Hej", "ej", "Heja", "hej", "foo"}, int64(2)},
{[]interface{}{"fo", "Hej", "ej", "Heja", "hej", "foo"}, int64(0)},
{[]interface{}{"ej", "Hej", "ej", "Heja", "ej", "hej", "foo"}, int64(2)},
{[]interface{}{1, 2, 3, 11, 1}, int64(4)},
{[]interface{}{nil, 2, 3, 11, 1}, int64(0)},
{[]interface{}{1.1, 2.1, 3.1, 11.1, 1.1}, int64(4)},
{[]interface{}{1.1, "2.1", "3.1", "11.1", "1.1"}, int64(4)},
{[]interface{}{"1.1a", 2.1, 3.1, 11.1, 1.1}, int64(4)},
{[]interface{}{1.10, 0, 11e-1}, int64(2)},
{[]interface{}{"abc", 0, 1, 11.1, 1.1}, int64(1)},
}
for _, t := range tbl {
fc := funcs[ast.Field]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(t.argLst...)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(t.ret))
}
}
func (s *testEvaluatorSuite) TestLpad(c *C) {
tests := []struct {
str string
len int64
padStr string
expect interface{}
}{
{"hi", 5, "?", "???hi"},
{"hi", 1, "?", "h"},
{"hi", 0, "?", ""},
{"hi", -1, "?", nil},
{"hi", 1, "", "h"},
{"hi", 5, "", nil},
{"hi", 5, "ab", "abahi"},
{"hi", 6, "ab", "ababhi"},
}
fc := funcs[ast.Lpad]
for _, test := range tests {
str := types.NewStringDatum(test.str)
length := types.NewIntDatum(test.len)
padStr := types.NewStringDatum(test.padStr)
f, err := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{str, length, padStr}))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
result, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
if test.expect == nil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
expect, _ := test.expect.(string)
c.Assert(result.GetString(), Equals, expect)
}
}
}
func (s *testEvaluatorSuite) TestRpad(c *C) {
tests := []struct {
str string
len int64
padStr string
expect interface{}
}{
{"hi", 5, "?", "hi???"},
{"hi", 1, "?", "h"},
{"hi", 0, "?", ""},
{"hi", -1, "?", nil},
{"hi", 1, "", "h"},
{"hi", 5, "", nil},
{"hi", 5, "ab", "hiaba"},
{"hi", 6, "ab", "hiabab"},
}
fc := funcs[ast.Rpad]
for _, test := range tests {
str := types.NewStringDatum(test.str)
length := types.NewIntDatum(test.len)
padStr := types.NewStringDatum(test.padStr)
f, err := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{str, length, padStr}))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
result, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
if test.expect == nil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
expect, _ := test.expect.(string)
c.Assert(result.GetString(), Equals, expect)
}
}
}
func (s *testEvaluatorSuite) TestRpadSig(c *C) {
colTypes := []*types.FieldType{
{Tp: mysql.TypeVarchar},
{Tp: mysql.TypeLonglong},
{Tp: mysql.TypeVarchar},
}
resultType := &types.FieldType{Tp: mysql.TypeVarchar, Flen: 1000}
args := []Expression{
&Column{Index: 0, RetType: colTypes[0]},
&Column{Index: 1, RetType: colTypes[1]},
&Column{Index: 2, RetType: colTypes[2]},
}
base := baseBuiltinFunc{args: args, ctx: s.ctx, tp: resultType}
rpad := &builtinRpadSig{base, 1000}
input := chunk.NewChunkWithCapacity(colTypes, 10)
input.AppendString(0, "abc")
input.AppendString(0, "abc")
input.AppendInt64(1, 6)
input.AppendInt64(1, 10000)
input.AppendString(2, "123")
input.AppendString(2, "123")
res, isNull, err := rpad.evalString(input.GetRow(0))
c.Assert(res, Equals, "abc123")
c.Assert(isNull, IsFalse)
c.Assert(err, IsNil)
res, isNull, err = rpad.evalString(input.GetRow(1))
c.Assert(res, Equals, "")
c.Assert(isNull, IsTrue)
c.Assert(err, IsNil)
warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings()
c.Assert(len(warnings), Equals, 1)
lastWarn := warnings[len(warnings)-1]
c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
}
func (s *testEvaluatorSuite) TestInsertBinarySig(c *C) {
colTypes := []*types.FieldType{
{Tp: mysql.TypeVarchar},
{Tp: mysql.TypeLonglong},
{Tp: mysql.TypeLonglong},
{Tp: mysql.TypeVarchar},
}
resultType := &types.FieldType{Tp: mysql.TypeVarchar, Flen: 3}
args := []Expression{
&Column{Index: 0, RetType: colTypes[0]},
&Column{Index: 1, RetType: colTypes[1]},
&Column{Index: 2, RetType: colTypes[2]},
&Column{Index: 3, RetType: colTypes[3]},
}
base := baseBuiltinFunc{args: args, ctx: s.ctx, tp: resultType}
insert := &builtinInsertBinarySig{base, 3}
input := chunk.NewChunkWithCapacity(colTypes, 2)
input.AppendString(0, "abc")
input.AppendString(0, "abc")
input.AppendInt64(1, 3)
input.AppendInt64(1, 3)
input.AppendInt64(2, -1)
input.AppendInt64(2, -1)
input.AppendString(3, "d")
input.AppendString(3, "de")
res, isNull, err := insert.evalString(input.GetRow(0))
c.Assert(res, Equals, "abd")
c.Assert(isNull, IsFalse)
c.Assert(err, IsNil)
res, isNull, err = insert.evalString(input.GetRow(1))
c.Assert(res, Equals, "")
c.Assert(isNull, IsTrue)
c.Assert(err, IsNil)
warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings()
c.Assert(len(warnings), Equals, 1)
lastWarn := warnings[len(warnings)-1]
c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
}
func (s *testEvaluatorSuite) TestInstr(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
Args []interface{}
Want interface{}
}{
{[]interface{}{"foobarbar", "bar"}, 4},
{[]interface{}{"xbar", "foobar"}, 0},
{[]interface{}{123456234, 234}, 2},
{[]interface{}{123456, 567}, 0},
{[]interface{}{1e10, 1e2}, 1},
{[]interface{}{1.234, ".234"}, 2},
{[]interface{}{1.234, ""}, 1},
{[]interface{}{"", 123}, 0},
{[]interface{}{"", ""}, 1},
{[]interface{}{"中文美好", "美好"}, 3},
{[]interface{}{"中文美好", "世界"}, 0},
{[]interface{}{"中文abc", "a"}, 3},
{[]interface{}{"live LONG and prosper", "long"}, 6},
{[]interface{}{"not BINARY string", "binary"}, 5},
{[]interface{}{"UPPER case", "upper"}, 1},
{[]interface{}{"UPPER case", "CASE"}, 7},
{[]interface{}{"中文abc", "abc"}, 3},
{[]interface{}{"foobar", nil}, nil},
{[]interface{}{nil, "foobar"}, nil},
{[]interface{}{nil, nil}, nil},
}
Dtbl := tblToDtbl(tbl)
instr := funcs[ast.Instr]
for i, t := range Dtbl {
f, err := instr.getFunction(s.ctx, s.datumsToConstants(t["Args"]))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
got, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(got, DeepEquals, t["Want"][0], Commentf("[%d]: args: %v", i, t["Args"]))
}
}
func (s *testEvaluatorSuite) TestMakeSet(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
argList []interface{}
ret interface{}
}{
{[]interface{}{1, "a", "b", "c"}, "a"},
{[]interface{}{1 | 4, "hello", "nice", "world"}, "hello,world"},
{[]interface{}{1 | 4, "hello", "nice", nil, "world"}, "hello"},
{[]interface{}{0, "a", "b", "c"}, ""},
{[]interface{}{nil, "a", "b", "c"}, nil},
{[]interface{}{-100 | 4, "hello", "nice", "abc", "world"}, "abc,world"},
{[]interface{}{-1, "hello", "nice", "abc", "world"}, "hello,nice,abc,world"},
}
for _, t := range tbl {
fc := funcs[ast.MakeSet]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(t.argList...)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(t.ret))
}
}
func (s *testEvaluatorSuite) TestOct(c *C) {
defer testleak.AfterTest(c)()
octTests := []struct {
origin interface{}
ret string
}{
{"-2.7", "1777777777777777777776"},
{-1.5, "1777777777777777777777"},
{-1, "1777777777777777777777"},
{"0", "0"},
{"1", "1"},
{"8", "10"},
{"12", "14"},
{"20", "24"},
{"100", "144"},
{"1024", "2000"},
{"2048", "4000"},
{1.0, "1"},
{9.5, "11"},
{13, "15"},
{1025, "2001"},
{"8a8", "10"},
{"abc", "0"},
//overflow uint64
{"9999999999999999999999999", "1777777777777777777777"},
{"-9999999999999999999999999", "1777777777777777777777"},
{types.NewBinaryLiteralFromUint(255, -1), "377"}, // b'11111111'
{types.NewBinaryLiteralFromUint(10, -1), "12"}, // b'1010'
{types.NewBinaryLiteralFromUint(5, -1), "5"}, // b'0101'
}
fc := funcs[ast.Oct]
for _, tt := range octTests {
in := types.NewDatum(tt.origin)
f, _ := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{in}))
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
res, err := r.ToString()
c.Assert(err, IsNil)
c.Assert(res, Equals, tt.ret, Commentf("select oct(%v);", tt.origin))
}
// tt NULL input for sha
var argNull types.Datum
f, _ := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{argNull}))
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r.IsNull(), IsTrue)
}
func (s *testEvaluatorSuite) TestFormat(c *C) {
defer testleak.AfterTest(c)()
formatTests := []struct {
number interface{}
precision interface{}
locale string
ret interface{}
}{
{12332.1234561111111111111111111111111111111111111, 4, "en_US", "12,332.1234"},
{nil, 22, "en_US", nil},
}
formatTests1 := []struct {
number interface{}
precision interface{}
ret interface{}
}{
{12332.123456, 4, "12,332.1234"},
{12332.123456, 0, "12,332"},
{12332.123456, -4, "12,332"},
{-12332.123456, 4, "-12,332.1234"},
{-12332.123456, 0, "-12,332"},
{-12332.123456, -4, "-12,332"},
{"12332.123456", "4", "12,332.1234"},
{"12332.123456A", "4", "12,332.1234"},
{"-12332.123456", "4", "-12,332.1234"},
{"-12332.123456A", "4", "-12,332.1234"},
{"A123345", "4", "0.0000"},
{"-A123345", "4", "0.0000"},
{"-12332.123456", "A", "-12,332"},
{"12332.123456", "A", "12,332"},
{"-12332.123456", "4A", "-12,332.1234"},
{"12332.123456", "4A", "12,332.1234"},
{"-A12332.123456", "A", "0"},
{"A12332.123456", "A", "0"},
{"-A12332.123456", "4A", "0.0000"},
{"A12332.123456", "4A", "0.0000"},
{"-.12332.123456", "4A", "-0.1233"},
{".12332.123456", "4A", "0.1233"},
{"12332.1234567890123456789012345678901", 22, "12,332.1234567890123456789012"},
{nil, 22, nil},
}
formatTests2 := struct {
number interface{}
precision interface{}
locale string
ret interface{}
}{-12332.123456, -4, "zh_CN", nil}
formatTests3 := struct {
number interface{}
precision interface{}
locale string
ret interface{}
}{"-12332.123456", "4", "de_GE", nil}
for _, tt := range formatTests {
fc := funcs[ast.Format]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(tt.number, tt.precision, tt.locale)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(tt.ret))
}
for _, tt := range formatTests1 {
fc := funcs[ast.Format]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(tt.number, tt.precision)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(tt.ret))
}
fc2 := funcs[ast.Format]
f2, err := fc2.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(formatTests2.number, formatTests2.precision, formatTests2.locale)))
c.Assert(err, IsNil)
c.Assert(f2, NotNil)
r2, err := evalBuiltinFunc(f2, chunk.Row{})
c.Assert(types.NewDatum(err), testutil.DatumEquals, types.NewDatum(errors.New("not implemented")))
c.Assert(r2, testutil.DatumEquals, types.NewDatum(formatTests2.ret))
fc3 := funcs[ast.Format]
f3, err := fc3.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(formatTests3.number, formatTests3.precision, formatTests3.locale)))
c.Assert(err, IsNil)
c.Assert(f3, NotNil)
r3, err := evalBuiltinFunc(f3, chunk.Row{})
c.Assert(types.NewDatum(err), testutil.DatumEquals, types.NewDatum(errors.New("not support for the specific locale")))
c.Assert(r3, testutil.DatumEquals, types.NewDatum(formatTests3.ret))
}
func (s *testEvaluatorSuite) TestFromBase64(c *C) {
tests := []struct {
args interface{}
expect interface{}
}{
{string(""), string("")},
{string("YWJj"), string("abc")},
{string("YWIgYw=="), string("ab c")},
{string("YWIKYw=="), string("ab\nc")},
{string("YWIJYw=="), string("ab\tc")},
{string("cXdlcnR5MTIzNDU2"), string("qwerty123456")},
{
string("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0\nNTY3ODkrL0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4\neXowMTIzNDU2Nzg5Ky9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3Bx\ncnN0dXZ3eHl6MDEyMzQ1Njc4OSsv"),
string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),
},
{
string("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLw=="),
string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),
},
{
string("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLw=="),
string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),
},
{
string("QUJDREVGR0hJSkt\tMTU5PUFFSU1RVVld\nYWVphYmNkZ\rWZnaGlqa2xt bm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLw=="),
string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),
},
}
fc := funcs[ast.FromBase64]
for _, test := range tests {
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(test.args)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
result, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
if test.expect == nil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
expect, _ := test.expect.(string)
c.Assert(result.GetString(), Equals, expect)
}
}
}
func (s *testEvaluatorSuite) TestFromBase64Sig(c *C) {
colTypes := []*types.FieldType{
{Tp: mysql.TypeVarchar},
}
tests := []struct {
args string
expect string
isNil bool
maxAllowPacket uint64
}{
{string("YWJj"), string("abc"), false, 3},
{string("YWJj"), "", true, 2},
{
string("QUJDREVGR0hJSkt\tMTU5PUFFSU1RVVld\nYWVphYmNkZ\rWZnaGlqa2xt bm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLw=="),
string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),
false,
70,
},
{
string("QUJDREVGR0hJSkt\tMTU5PUFFSU1RVVld\nYWVphYmNkZ\rWZnaGlqa2xt bm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLw=="),
"",
true,
69,
},
}
args := []Expression{
&Column{Index: 0, RetType: colTypes[0]},
}
for _, test := range tests {
resultType := &types.FieldType{Tp: mysql.TypeVarchar, Flen: mysql.MaxBlobWidth}
base := baseBuiltinFunc{args: args, ctx: s.ctx, tp: resultType}
fromBase64 := &builtinFromBase64Sig{base, test.maxAllowPacket}
input := chunk.NewChunkWithCapacity(colTypes, 1)
input.AppendString(0, test.args)
res, isNull, err := fromBase64.evalString(input.GetRow(0))
c.Assert(err, IsNil)
c.Assert(isNull, Equals, test.isNil)
if isNull {
warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings()
c.Assert(len(warnings), Equals, 1)
lastWarn := warnings[len(warnings)-1]
c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue)
s.ctx.GetSessionVars().StmtCtx.SetWarnings([]stmtctx.SQLWarn{})
}
c.Assert(res, Equals, test.expect)
}
}
func (s *testEvaluatorSuite) TestInsert(c *C) {
tests := []struct {
args []interface{}
expect interface{}
}{
{[]interface{}{"Quadratic", 3, 4, "What"}, "QuWhattic"},
{[]interface{}{"Quadratic", -1, 4, "What"}, "Quadratic"},
{[]interface{}{"Quadratic", 3, 100, "What"}, "QuWhat"},
{[]interface{}{nil, 3, 100, "What"}, nil},
{[]interface{}{"Quadratic", nil, 4, "What"}, nil},
{[]interface{}{"Quadratic", 3, nil, "What"}, nil},
{[]interface{}{"Quadratic", 3, 4, nil}, nil},
{[]interface{}{"Quadratic", 3, -1, "What"}, "QuWhat"},
{[]interface{}{"Quadratic", 3, 1, "What"}, "QuWhatdratic"},
{[]interface{}{"我叫小雨呀", 3, 2, "王雨叶"}, "我叫王雨叶呀"},
{[]interface{}{"我叫小雨呀", -1, 2, "王雨叶"}, "我叫小雨呀"},
{[]interface{}{"我叫小雨呀", 3, 100, "王雨叶"}, "我叫王雨叶"},
{[]interface{}{nil, 3, 100, "王雨叶"}, nil},
{[]interface{}{"我叫小雨呀", nil, 4, "王雨叶"}, nil},
{[]interface{}{"我叫小雨呀", 3, nil, "王雨叶"}, nil},
{[]interface{}{"我叫小雨呀", 3, 4, nil}, nil},
{[]interface{}{"我叫小雨呀", 3, -1, "王雨叶"}, "我叫王雨叶"},
{[]interface{}{"我叫小雨呀", 3, 1, "王雨叶"}, "我叫王雨叶雨呀"},
}
fc := funcs[ast.InsertFunc]
for _, test := range tests {
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(test.args...)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
result, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
if test.expect == nil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
expect, _ := test.expect.(string)
c.Assert(result.GetString(), Equals, expect)
}
}
}
func (s *testEvaluatorSuite) TestOrd(c *C) {
defer testleak.AfterTest(c)()
cases := []struct {
args interface{}
expected int64
isNil bool
getErr bool
}{
{"2", 50, false, false},
{2, 50, false, false},
{"23", 50, false, false},
{23, 50, false, false},
{2.3, 50, false, false},
{nil, 0, true, false},
{"", 0, false, false},
{"你好", 14990752, false, false},
{"にほん", 14909867, false, false},
{"한국", 15570332, false, false},
{"👍", 4036989325, false, false},
{"א", 55184, false, false},
}
for _, t := range cases {
f, err := newFunctionForTest(s.ctx, ast.Ord, s.primitiveValsToConstants([]interface{}{t.args})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if t.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if t.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetInt64(), Equals, t.expected)
}
}
}
_, err := funcs[ast.Ord].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestElt(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
argLst []interface{}
ret interface{}
}{
{[]interface{}{1, "Hej", "ej", "Heja", "hej", "foo"}, "Hej"},
{[]interface{}{9, "Hej", "ej", "Heja", "hej", "foo"}, nil},
{[]interface{}{-1, "Hej", "ej", "Heja", "ej", "hej", "foo"}, nil},
{[]interface{}{0, 2, 3, 11, 1}, nil},
{[]interface{}{3, 2, 3, 11, 1}, "11"},
{[]interface{}{1.1, "2.1", "3.1", "11.1", "1.1"}, "2.1"},
}
for _, t := range tbl {
fc := funcs[ast.Elt]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(t.argLst...)))
c.Assert(err, IsNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(t.ret))
}
}
func (s *testEvaluatorSuite) TestExportSet(c *C) {
defer testleak.AfterTest(c)()
estd := []struct {
argLst []interface{}
res string
}{
{[]interface{}{-9223372036854775807, "Y", "N", ",", 5}, "Y,N,N,N,N"},
{[]interface{}{-6, "Y", "N", ",", 5}, "N,Y,N,Y,Y"},
{[]interface{}{5, "Y", "N", ",", 4}, "Y,N,Y,N"},
{[]interface{}{5, "Y", "N", ",", 0}, ""},
{[]interface{}{5, "Y", "N", ",", 1}, "Y"},
{[]interface{}{6, "1", "0", ",", 10}, "0,1,1,0,0,0,0,0,0,0"},
{[]interface{}{333333, "Ysss", "sN", "---", 9}, "Ysss---sN---Ysss---sN---Ysss---sN---sN---sN---sN"},
{[]interface{}{7, "Y", "N"}, "Y,Y,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N"},
{[]interface{}{7, "Y", "N", 6}, "Y6Y6Y6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N"},
{[]interface{}{7, "Y", "N", 6, 133}, "Y6Y6Y6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N6N"},
}
fc := funcs[ast.ExportSet]
for _, t := range estd {
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(t.argLst...)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
exportSetRes, err := evalBuiltinFunc(f, chunk.Row{})
res, err := exportSetRes.ToString()
c.Assert(err, IsNil)
c.Assert(res, Equals, t.res)
}
}
func (s *testEvaluatorSuite) TestBin(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
Input interface{}
Expected interface{}
}{
{"10", "1010"},
{"10.2", "1010"},
{"10aa", "1010"},
{"10.2aa", "1010"},
{"aaa", "0"},
{"", nil},
{10, "1010"},
{10.0, "1010"},
{-1, "1111111111111111111111111111111111111111111111111111111111111111"},
{"-1", "1111111111111111111111111111111111111111111111111111111111111111"},
{nil, nil},
}
fc := funcs[ast.Bin]
dtbl := tblToDtbl(tbl)
ctx := mock.NewContext()
ctx.GetSessionVars().StmtCtx.IgnoreTruncate = true
for _, t := range dtbl {
f, err := fc.getFunction(ctx, s.datumsToConstants(t["Input"]))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(t["Expected"][0]))
}
}
func (s *testEvaluatorSuite) TestQuote(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
arg interface{}
ret interface{}
}{
{`Don\'t!`, `'Don\\\'t!'`},
{`Don't`, `'Don\'t'`},
{`Don"`, `'Don"'`},
{`Don\"`, `'Don\\"'`},
{`\'`, `'\\\''`},
{`\"`, `'\\"'`},
{`萌萌哒(๑•ᴗ•๑)😊`, `'萌萌哒(๑•ᴗ•๑)😊'`},
{`㍿㌍㍑㌫`, `'㍿㌍㍑㌫'`},
{string([]byte{0, 26}), `'\0\Z'`},
{nil, nil},
}
for _, t := range tbl {
fc := funcs[ast.Quote]
f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeDatums(t.arg)))
c.Assert(err, IsNil)
c.Assert(f, NotNil)
r, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
c.Assert(r, testutil.DatumEquals, types.NewDatum(t.ret))
}
}
func (s *testEvaluatorSuite) TestToBase64(c *C) {
defer testleak.AfterTest(c)()
tests := []struct {
args interface{}
expect string
isNil bool
getErr bool
}{
{"", "", false, false},
{"abc", "YWJj", false, false},
{"ab c", "YWIgYw==", false, false},
{1, "MQ==", false, false},
{1.1, "MS4x", false, false},
{"ab\nc", "YWIKYw==", false, false},
{"ab\tc", "YWIJYw==", false, false},
{"qwerty123456", "cXdlcnR5MTIzNDU2", false, false},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0\nNTY3ODkrLw==",
false,
false,
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0\nNTY3ODkrL0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4\neXowMTIzNDU2Nzg5Ky9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3Bx\ncnN0dXZ3eHl6MDEyMzQ1Njc4OSsv",
false,
false,
},
{
"ABCD EFGHI\nJKLMNOPQRSTUVWXY\tZabcdefghijklmnopqrstuv wxyz012\r3456789+/",
"QUJDRCAgRUZHSEkKSktMTU5PUFFSU1RVVldYWQlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1diAgd3h5\nejAxMg0zNDU2Nzg5Ky8=",
false,
false,
},
{nil, "", true, false},
}
if strconv.IntSize == 32 {
tests = append(tests, struct {
args interface{}
expect string
isNil bool
getErr bool
}{
strings.Repeat("a", 1589695687),
"",
true,
false,
})
}
for _, test := range tests {
f, err := newFunctionForTest(s.ctx, ast.ToBase64, s.primitiveValsToConstants([]interface{}{test.args})...)
c.Assert(err, IsNil)
d, err := f.Eval(chunk.Row{})
if test.getErr {
c.Assert(err, NotNil)
} else {
c.Assert(err, IsNil)
if test.isNil {
c.Assert(d.Kind(), Equals, types.KindNull)
} else {
c.Assert(d.GetString(), Equals, test.expect)
}
}
}
_, err := funcs[ast.ToBase64].getFunction(s.ctx, []Expression{Zero})
c.Assert(err, IsNil)
}
func (s *testEvaluatorSuite) TestToBase64Sig(c *C) {
colTypes := []*types.FieldType{
{Tp: mysql.TypeVarchar},
}
tests := []struct {
args string
expect string
isNil bool
maxAllowPacket uint64
}{
{"abc", "YWJj", false, 4},
{"abc", "", true, 3},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0\nNTY3ODkrLw==",
false,
89,
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"",
true,
88,
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0\nNTY3ODkrL0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4\neXowMTIzNDU2Nzg5Ky9BQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3Bx\ncnN0dXZ3eHl6MDEyMzQ1Njc4OSsv",
false,
259,
},
{
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"",
true,
258,
},
}
args := []Expression{
&Column{Index: 0, RetType: colTypes[0]},
}
for _, test := range tests {
resultType := &types.FieldType{Tp: mysql.TypeVarchar, Flen: base64NeededEncodedLength(len(test.args))}
base := baseBuiltinFunc{args: args, ctx: s.ctx, tp: resultType}
toBase64 := &builtinToBase64Sig{base, test.maxAllowPacket}
input := chunk.NewChunkWithCapacity(colTypes, 1)
input.AppendString(0, test.args)
res, isNull, err := toBase64.evalString(input.GetRow(0))
c.Assert(err, IsNil)
if test.isNil {
c.Assert(isNull, IsTrue)
warnings := s.ctx.GetSessionVars().StmtCtx.GetWarnings()
c.Assert(len(warnings), Equals, 1)
lastWarn := warnings[len(warnings)-1]
c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue)
s.ctx.GetSessionVars().StmtCtx.SetWarnings([]stmtctx.SQLWarn{})
} else {
c.Assert(isNull, IsFalse)
}
c.Assert(res, Equals, test.expect)
}
}
func (s *testEvaluatorSuite) TestStringRight(c *C) {
defer testleak.AfterTest(c)()
fc := funcs[ast.Right]
tests := []struct {
str interface{}
length interface{}
expect interface{}
}{
{"helloworld", 5, "world"},
{"helloworld", 10, "helloworld"},
{"helloworld", 11, "helloworld"},
{"helloworld", -1, ""},
{"", 2, ""},
{nil, 2, nil},
}
for _, test := range tests {
str := types.NewDatum(test.str)
length := types.NewDatum(test.length)
f, _ := fc.getFunction(s.ctx, s.datumsToConstants([]types.Datum{str, length}))
result, err := evalBuiltinFunc(f, chunk.Row{})
c.Assert(err, IsNil)
if result.IsNull() {
c.Assert(test.expect, IsNil)
continue
}
res, err := result.ToString()
c.Assert(err, IsNil)
c.Assert(res, Equals, test.expect)
}
}

Комментарий ( 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.4