Skip to content

Commit 34df154

Browse files
authored
implement quote (#2973)
1 parent eed2800 commit 34df154

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

enginetest/queries/queries.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10146,7 +10146,6 @@ from typestable`,
1014610146
{uint32(1000)},
1014710147
},
1014810148
},
10149-
1015010149
{
1015110150
Query: `select distinct pk1 from two_pk order by pk1`,
1015210151
Expected: []sql.Row{
@@ -10255,14 +10254,12 @@ from typestable`,
1025510254
{""},
1025610255
},
1025710256
},
10258-
1025910257
{
1026010258
Query: "select @@sql_mode = 1",
1026110259
Expected: []sql.Row{
1026210260
{false},
1026310261
},
1026410262
},
10265-
1026610263
{
1026710264
Query: "explain select 1",
1026810265
SkipServerEngine: true,
@@ -10290,6 +10287,20 @@ from typestable`,
1029010287
{" └─ name: "},
1029110288
},
1029210289
},
10290+
{
10291+
Query: "select quote(i), quote(s) from mytable",
10292+
Expected: []sql.Row{
10293+
{"'1'", "'first row'"},
10294+
{"'2'", "'second row'"},
10295+
{"'3'", "'third row'"},
10296+
},
10297+
},
10298+
{
10299+
Query: "select i, s from mytable where quote(i) = quote(2)",
10300+
Expected: []sql.Row{
10301+
{2, "second row"},
10302+
},
10303+
},
1029310304
}
1029410305

1029510306
var KeylessQueries = []QueryTest{

sql/expression/function/registry.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ var BuiltIns = []sql.Function{
190190
sql.Function2{Name: "pow", Fn: NewPower},
191191
sql.Function2{Name: "power", Fn: NewPower},
192192
sql.Function1{Name: "quarter", Fn: NewQuarter},
193+
sql.Function1{Name: "quote", Fn: NewQuote},
193194
sql.Function1{Name: "radians", Fn: NewRadians},
194195
sql.FunctionN{Name: "rand", Fn: NewRand},
195196
sql.FunctionN{Name: "regexp_instr", Fn: NewRegexpInstr},

sql/expression/function/string.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package function
1616

1717
import (
18+
"bytes"
1819
"encoding/hex"
1920
"fmt"
2021
"math"
@@ -614,3 +615,55 @@ func (h *Bitlength) WithChildren(children ...sql.Expression) (sql.Expression, er
614615
}
615616
return NewBitlength(children[0]), nil
616617
}
618+
619+
type Quote struct {
620+
*UnaryFunc
621+
}
622+
623+
var _ sql.FunctionExpression = (*Bitlength)(nil)
624+
var _ sql.CollationCoercible = (*Bitlength)(nil)
625+
626+
func NewQuote(arg sql.Expression) sql.Expression {
627+
return &Quote{UnaryFunc: NewUnaryFunc(arg, "QUOTE", types.Text)}
628+
}
629+
630+
func (q *Quote) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
631+
arg, err := q.EvalChild(ctx, row)
632+
if err != nil {
633+
return nil, err
634+
}
635+
636+
val, _, err := types.Blob.Convert(ctx, arg)
637+
if err != nil {
638+
return nil, err
639+
}
640+
if val == nil {
641+
return nil, nil
642+
}
643+
valBytes := val.([]byte)
644+
645+
ret := new(bytes.Buffer)
646+
ret.WriteByte('\'')
647+
for _, c := range valBytes {
648+
switch c {
649+
// '\032' is CTRL+Z character
650+
case '\\', '\'', '\032':
651+
ret.WriteByte('\\')
652+
ret.WriteByte(c)
653+
case '\000':
654+
ret.WriteByte('\\')
655+
ret.WriteByte('0')
656+
default:
657+
ret.WriteByte(c)
658+
}
659+
}
660+
ret.WriteByte('\'')
661+
return ret.String(), nil
662+
}
663+
664+
func (q *Quote) WithChildren(children ...sql.Expression) (sql.Expression, error) {
665+
if len(children) != 1 {
666+
return nil, sql.ErrInvalidChildrenNumber.New(q, len(children), 1)
667+
}
668+
return NewQuote(children[0]), nil
669+
}

sql/expression/function/string_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,15 @@ func TestBitLength(t *testing.T) {
163163
tf.AddSucceeding(128, time.Now())
164164
tf.Test(t, nil, nil)
165165
}
166+
167+
func TestQuote(t *testing.T) {
168+
f := sql.Function1{Name: "quote", Fn: NewQuote}
169+
tf := NewTestFactory(f.Fn)
170+
tf.AddSucceeding(nil, nil)
171+
tf.AddSucceeding("'test'", "test")
172+
tf.AddSucceeding("'0'", false)
173+
tf.AddSucceeding("'1'", true)
174+
tf.AddSucceeding("'12345'", 12345)
175+
tf.AddSucceeding("'\\\\, \\', \\0, \\\032'", "\\, ', \000, \032")
176+
tf.Test(t, nil, nil)
177+
}

0 commit comments

Comments
 (0)