Skip to content

Commit 761620d

Browse files
authored
Merge pull request #1437 from dolthub/zachmu/literals-alt
Fixes for prepared statements, removed custom literal type
2 parents 40960ac + 278e6c6 commit 761620d

18 files changed

+159
-359
lines changed

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi v0.0.0-20241119094239-f4e529af734d
1111
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2
1212
github.com/dolthub/go-icu-regex v0.0.0-20250327004329-6799764f2dad
13-
github.com/dolthub/go-mysql-server v0.19.1-0.20250430183344-d3b95b2013dd
13+
github.com/dolthub/go-mysql-server v0.19.1-0.20250501222915-ec787601a4cb
1414
github.com/dolthub/sqllogictest/go v0.0.0-20240618184124-ca47f9354216
1515
github.com/dolthub/vitess v0.0.0-20250430180243-0eee73763bc5
1616
github.com/fatih/color v1.13.0
@@ -124,7 +124,7 @@ require (
124124
github.com/jackc/pgtype v1.14.0 // indirect
125125
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d // indirect
126126
github.com/kch42/buzhash v0.0.0-20160816060738-9bdec3dec7c6 // indirect
127-
github.com/klauspost/compress v1.10.5 // indirect
127+
github.com/klauspost/compress v1.10.10 // indirect
128128
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
129129
github.com/kr/pretty v0.3.0 // indirect
130130
github.com/kr/text v0.2.0 // indirect

go.sum

+4-3
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
266266
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
267267
github.com/dolthub/go-icu-regex v0.0.0-20250327004329-6799764f2dad h1:66ZPawHszNu37VPQckdhX1BPPVzREsGgNxQeefnlm3g=
268268
github.com/dolthub/go-icu-regex v0.0.0-20250327004329-6799764f2dad/go.mod h1:ylU4XjUpsMcvl/BKeRRMXSH7e7WBrPXdSLvnRJYrxEA=
269-
github.com/dolthub/go-mysql-server v0.19.1-0.20250430183344-d3b95b2013dd h1:WC8c6Wh+kWxw4xNQruFtqkDxTw3PMeFcS57ok3+rUV4=
270-
github.com/dolthub/go-mysql-server v0.19.1-0.20250430183344-d3b95b2013dd/go.mod h1:pj8c/fGAEdKYy1BZWcN0xO+vEgMRI+kWVXhuEy1BN+Q=
269+
github.com/dolthub/go-mysql-server v0.19.1-0.20250501222915-ec787601a4cb h1:T+/YvBBXMMl13Mmu0PJzpA7IKv8rqLOOSQMSj/tL+28=
270+
github.com/dolthub/go-mysql-server v0.19.1-0.20250501222915-ec787601a4cb/go.mod h1:pj8c/fGAEdKYy1BZWcN0xO+vEgMRI+kWVXhuEy1BN+Q=
271271
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI=
272272
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q=
273273
github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE=
@@ -617,8 +617,9 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
617617
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
618618
github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
619619
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
620-
github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc=
621620
github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
621+
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
622+
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
622623
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
623624
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
624625
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=

server/analyzer/serial.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
2323
"github.com/dolthub/go-mysql-server/sql"
2424
"github.com/dolthub/go-mysql-server/sql/analyzer"
25+
"github.com/dolthub/go-mysql-server/sql/expression"
2526
"github.com/dolthub/go-mysql-server/sql/plan"
2627
"github.com/dolthub/go-mysql-server/sql/transform"
2728

@@ -61,7 +62,7 @@ func ReplaceSerial(ctx *sql.Context, a *analyzer.Analyzer, node sql.Node, scope
6162
if strings.ToLower(expr.Name) == "nextval" {
6263
seenNextVal = true
6364
}
64-
case *pgexprs.Literal:
65+
case *expression.Literal:
6566
placeholderName := fmt.Sprintf("'%s'", ast.DoltCreateTablePlaceholderSequenceName)
6667
if expr.String() == placeholderName {
6768
isGeneratedFromSequence = true

server/ast/group_by.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package ast
1616

1717
import (
18+
"github.com/dolthub/go-mysql-server/sql/expression"
1819
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
1920

2021
pgexprs "github.com/dolthub/doltgresql/server/expression"
@@ -41,8 +42,8 @@ func nodeGroupBy(ctx *Context, node tree.GroupBy) (vitess.GroupBy, error) {
4142
// the query, which is not a requirement for Postgres. Whenever we add that functionality, we also need to
4243
// remove the dependency on vitess.SQLVal. For now, we'll just convert our literals to a vitess.SQLVal.
4344
if injectedExpr, ok := groupBys[i].(vitess.InjectedExpr); ok {
44-
if literal, ok := injectedExpr.Expression.(*pgexprs.Literal); ok {
45-
groupBys[i] = literal.ToVitessLiteral()
45+
if literal, ok := injectedExpr.Expression.(*expression.Literal); ok {
46+
groupBys[i] = pgexprs.ToVitessLiteral(literal)
4647
}
4748
}
4849
}

server/ast/limit.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package ast
1616

1717
import (
1818
"github.com/cockroachdb/errors"
19+
"github.com/dolthub/go-mysql-server/sql/expression"
1920

2021
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
2122

@@ -43,7 +44,7 @@ func nodeLimit(ctx *Context, node *tree.Limit) (*vitess.Limit, error) {
4344
// GMS is hardcoded to expect vitess.SQLVal for expressions such as `LIMIT 1 OFFSET 1`.
4445
// We need to remove the hard dependency, but for now, we'll just convert our literals to a vitess.SQLVal.
4546
if injectedExpr, ok := count.(vitess.InjectedExpr); ok {
46-
if literal, ok := injectedExpr.Expression.(*pgexprs.Literal); ok {
47+
if literal, ok := injectedExpr.Expression.(*expression.Literal); ok {
4748
l := literal.Value()
4849
limitValue, err := int64ValueForLimit(l)
4950
if err != nil {
@@ -54,11 +55,11 @@ func nodeLimit(ctx *Context, node *tree.Limit) (*vitess.Limit, error) {
5455
return nil, errors.Errorf("LIMIT must be greater than or equal to 0")
5556
}
5657

57-
count = literal.ToVitessLiteral()
58+
count = pgexprs.ToVitessLiteral(literal)
5859
}
5960
}
6061
if injectedExpr, ok := offset.(vitess.InjectedExpr); ok {
61-
if literal, ok := injectedExpr.Expression.(*pgexprs.Literal); ok {
62+
if literal, ok := injectedExpr.Expression.(*expression.Literal); ok {
6263
o := literal.Value()
6364
offsetVal, err := int64ValueForLimit(o)
6465
if err != nil {
@@ -69,7 +70,7 @@ func nodeLimit(ctx *Context, node *tree.Limit) (*vitess.Limit, error) {
6970
return nil, errors.Errorf("OFFSET must be greater than or equal to 0")
7071
}
7172

72-
offset = literal.ToVitessLiteral()
73+
offset = pgexprs.ToVitessLiteral(literal)
7374
}
7475
}
7576
return &vitess.Limit{

server/ast/order_by.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package ast
1616

1717
import (
1818
"github.com/cockroachdb/errors"
19+
"github.com/dolthub/go-mysql-server/sql/expression"
1920

2021
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
2122

@@ -69,8 +70,8 @@ func nodeOrderBy(ctx *Context, node tree.OrderBy) (vitess.OrderBy, error) {
6970
// the query, which is not a requirement for Postgres. Whenever we add that functionality, we also need to
7071
// remove the dependency on vitess.SQLVal. For now, we'll just convert our literals to a vitess.SQLVal.
7172
if injectedExpr, ok := expr.(vitess.InjectedExpr); ok {
72-
if literal, ok := injectedExpr.Expression.(*pgexprs.Literal); ok {
73-
expr = literal.ToVitessLiteral()
73+
if literal, ok := injectedExpr.Expression.(*expression.Literal); ok {
74+
expr = pgexprs.ToVitessLiteral(literal)
7475
}
7576
}
7677
orderBys[i] = &vitess.Order{

server/ast/select_clause.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package ast
1616

1717
import (
1818
"github.com/cockroachdb/errors"
19+
"github.com/dolthub/go-mysql-server/sql/expression"
1920

2021
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
2122

@@ -141,8 +142,8 @@ PostJoinRewrite:
141142
for _, fExpr := range funcExpr.Exprs {
142143
if aliasedExpr, ok := fExpr.(*vitess.AliasedExpr); ok {
143144
if injectedExpr, ok := aliasedExpr.Expr.(vitess.InjectedExpr); ok {
144-
if literal, ok := injectedExpr.Expression.(*pgexprs.Literal); ok {
145-
aliasedExpr.Expr = literal.ToVitessLiteral()
145+
if literal, ok := injectedExpr.Expression.(*expression.Literal); ok {
146+
aliasedExpr.Expr = pgexprs.ToVitessLiteral(literal)
146147
}
147148
}
148149
}

server/connection_data.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,32 @@ func extractBindVarTypes(queryPlan sql.Node) ([]uint32, error) {
113113

114114
types := make([]uint32, 0)
115115
var err error
116-
extractBindVars := func(expr sql.Expression) bool {
116+
var extractBindVars func(n sql.Node, expr sql.Expression) bool
117+
extractBindVars = func(n sql.Node, expr sql.Expression) bool {
117118
if err != nil {
118119
return false
119120
}
121+
120122
switch e := expr.(type) {
123+
// Subquery doesn't walk its Node child via Expressions, so we must walk it separately here
124+
case *plan.Subquery:
125+
transform.InspectExpressionsWithNode(e.Query, extractBindVars)
121126
case *expression.BindVar:
122127
var typOid uint32
123128
if doltgresType, ok := e.Type().(*pgtypes.DoltgresType); ok {
124129
typOid = id.Cache().ToOID(doltgresType.ID.AsId())
130+
} else if _, ok := e.Type().(sql.DeferredType); ok {
131+
// for a deferred type, we can make a guess to its type based on the containing node
132+
switch n.(type) {
133+
case *plan.Limit:
134+
typOid = uint32(oid.T_int4)
135+
default:
136+
typOid, err = VitessTypeToObjectID(e.Type().Type())
137+
if err != nil {
138+
err = errors.Errorf("could not determine OID for placeholder %s: %w", e.Name, err)
139+
return false
140+
}
141+
}
125142
} else {
126143
// TODO: should remove usage non doltgres type
127144
typOid, err = VitessTypeToObjectID(e.Type().Type())
@@ -159,11 +176,10 @@ func extractBindVarTypes(queryPlan sql.Node) ([]uint32, error) {
159176
return false
160177
}
161178
}
162-
163179
return true
164180
}
165181

166-
transform.InspectExpressions(inspectNode, extractBindVars)
182+
transform.InspectExpressionsWithNode(inspectNode, extractBindVars)
167183
return types, err
168184
}
169185

server/expression/any.go

+17-14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"github.com/cockroachdb/errors"
2121
"github.com/dolthub/go-mysql-server/sql"
22+
"github.com/dolthub/go-mysql-server/sql/expression"
2223
"github.com/dolthub/go-mysql-server/sql/plan"
2324

2425
"github.com/dolthub/doltgresql/server/functions/framework"
@@ -39,16 +40,16 @@ type AnyExpr struct {
3940
// subqueryAnyExpr represents the resolved comparison functions for a plan.Subquery.
4041
type subqueryAnyExpr struct {
4142
rightSub *plan.Subquery
42-
staticLiteral *Literal
43-
arrayLiterals []*Literal
43+
staticLiteral *expression.Literal
44+
arrayLiterals []*expression.Literal
4445
compFuncs []framework.Function
4546
}
4647

4748
// expressionAnyExpr represents the resolved comparison function for a sql.Expression.
4849
type expressionAnyExpr struct {
4950
rightExpr sql.Expression
50-
staticLiteral *Literal
51-
arrayLiteral *Literal
51+
staticLiteral *expression.Literal
52+
arrayLiteral *expression.Literal
5253
compFunc framework.Function
5354
}
5455

@@ -130,7 +131,7 @@ func (a *subqueryAnyExpr) eval(ctx *sql.Context, subOperator string, row sql.Row
130131
}
131132

132133
for i := len(a.arrayLiterals); i < len(rightValues); i++ {
133-
arrayLiteral := &Literal{typ: a.arrayLiterals[0].typ}
134+
arrayLiteral := expression.NewLiteral(nil, a.arrayLiterals[0].Type())
134135
a.arrayLiterals = append(a.arrayLiterals, arrayLiteral)
135136
compFunc := framework.GetBinaryFunction(op).Compile("internal_any_comparison", a.staticLiteral, a.arrayLiterals[i])
136137
a.compFuncs = append(a.compFuncs, compFunc)
@@ -142,9 +143,10 @@ func (a *subqueryAnyExpr) eval(ctx *sql.Context, subOperator string, row sql.Row
142143
}
143144

144145
// Next we'll assign our evaluated values to the expressions that the comparison functions reference
145-
a.staticLiteral.value = left
146+
// Note that the compiled function has a reference to the staticLiteral and arrayLiterals, so we must alter them in place
147+
a.staticLiteral.Val = left
146148
for i, rightValue := range rightValues {
147-
a.arrayLiterals[i].value = rightValue
149+
a.arrayLiterals[i].Val = rightValue
148150
}
149151
// Now we can loop over all comparison functions, as they'll reference their respective values
150152
for _, compFunc := range a.compFuncs {
@@ -192,9 +194,10 @@ func (a *expressionAnyExpr) eval(ctx *sql.Context, row sql.Row, left interface{}
192194
}
193195

194196
// Next we'll assign our evaluated values to the expressions that the comparison function reference
195-
a.staticLiteral.value = left
197+
// Note that the compiled function has a reference to the staticLiteral and arrayLiteral, so we must alter them in place
198+
a.staticLiteral.Val = left
196199
for _, rightValue := range rightValues {
197-
a.arrayLiteral.value = rightValue
200+
a.arrayLiteral.Val = rightValue
198201
result, err := a.compFunc.Eval(ctx, row)
199202
if err != nil {
200203
return nil, err
@@ -293,12 +296,12 @@ func anySubqueryWithChildren(anyExpr *AnyExpr, sub *plan.Subquery) (sql.Expressi
293296

294297
if leftType, ok := anyExpr.leftExpr.Type().(*pgtypes.DoltgresType); ok {
295298
// Resolve comparison functions once and reuse the functions in Eval.
296-
staticLiteral := &Literal{typ: leftType}
297-
arrayLiterals := make([]*Literal, len(subTypes))
299+
staticLiteral := expression.NewLiteral(nil, leftType)
300+
arrayLiterals := make([]*expression.Literal, len(subTypes))
298301
// Each expression may be a different type (which is valid), so we need a comparison function for each expression.
299302
compFuncs := make([]framework.Function, len(subTypes))
300303
for i, rightType := range subTypes {
301-
arrayLiterals[i] = &Literal{typ: rightType}
304+
arrayLiterals[i] = expression.NewLiteral(nil, rightType)
302305
compFuncs[i] = framework.GetBinaryFunction(op).Compile("internal_any_comparison", staticLiteral, arrayLiterals[i])
303306
if compFuncs[i] == nil {
304307
return nil, errors.Errorf("operator does not exist: %s = %s", leftType.String(), rightType.String())
@@ -334,8 +337,8 @@ func anyExpressionWithChildren(anyExpr *AnyExpr) (sql.Expression, error) {
334337

335338
if leftType, ok := anyExpr.leftExpr.Type().(*pgtypes.DoltgresType); ok {
336339
// Resolve comparison function once and reuse the function in Eval.
337-
staticLiteral := &Literal{typ: leftType}
338-
arrayLiteral := &Literal{typ: rightType}
340+
staticLiteral := expression.NewLiteral(nil, leftType)
341+
arrayLiteral := expression.NewLiteral(nil, rightType)
339342
compFunc := framework.GetBinaryFunction(op).Compile("internal_any_comparison", staticLiteral, arrayLiteral)
340343
if compFunc == nil {
341344
return nil, errors.Errorf("operator does not exist: %s = %s", leftType.String(), rightType.String())

server/expression/in_subquery.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ type InSubquery struct {
3535

3636
// These variables are used so that we can resolve the comparison functions once and reuse them as we iterate over rows.
3737
// These are assigned in WithChildren, so refer there for more information.
38-
leftLiteral *Literal
39-
rightLiterals []*Literal
38+
leftLiteral *expression.Literal
39+
rightLiterals []*expression.Literal
4040
compFuncs []framework.Function
4141
}
4242

@@ -127,9 +127,10 @@ func (in *InSubquery) Eval(ctx *sql.Context, row sql.Row) (any, error) {
127127
// assigned to |compFuncs| during analysis. If the left value is a single scalar, then |row| has a single value as
128128
// well. Otherwise, (left is a tuple), |row| has a matching number of values.
129129
func (in *InSubquery) valuesEqual(ctx *sql.Context, left interface{}, row sql.Row) (bool, error) {
130-
in.leftLiteral.value = left
130+
// Note that we have to edit the literals in place, since the comparison functions reference them directly.
131+
in.leftLiteral.Val = left
131132
for i, v := range row {
132-
in.rightLiterals[i].value = v
133+
in.rightLiterals[i].Val = v
133134
}
134135

135136
for _, compFunc := range in.compFuncs {
@@ -198,8 +199,8 @@ func (in *InSubquery) WithChildren(children ...sql.Expression) (sql.Expression,
198199

199200
// We need a comparison function for each type in the query result
200201
sch := sq.Query.Schema()
201-
leftLiteral := &Literal{typ: leftType}
202-
rightLiterals := make([]*Literal, len(sch))
202+
leftLiteral := expression.NewLiteral(nil, leftType)
203+
rightLiterals := make([]*expression.Literal, len(sch))
203204
compFuncs := make([]framework.Function, len(sch))
204205
allValidChildren := true
205206
for i, rightCol := range sch {
@@ -208,7 +209,7 @@ func (in *InSubquery) WithChildren(children ...sql.Expression) (sql.Expression,
208209
allValidChildren = false
209210
break
210211
}
211-
rightLiterals[i] = &Literal{typ: rightType}
212+
rightLiterals[i] = expression.NewLiteral(nil, rightType)
212213
compFuncs[i] = framework.GetBinaryFunction(framework.Operator_BinaryEqual).Compile("internal_in_comparison", leftLiteral, rightLiterals[i])
213214
if compFuncs[i] == nil {
214215
return nil, errors.Errorf("operator does not exist: %s = %s", leftType.String(), rightType.String())

server/expression/in_tuple.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ type InTuple struct {
3333

3434
// These variables are used so that we can resolve the comparison functions once and reuse them as we iterate over rows.
3535
// These are assigned in WithChildren, so refer there for more information.
36-
staticLiteral *Literal
37-
arrayLiterals []*Literal
36+
staticLiteral *expression.Literal
37+
arrayLiterals []*expression.Literal
3838
compFuncs []framework.Function
3939
}
4040

@@ -112,9 +112,10 @@ func (it *InTuple) Eval(ctx *sql.Context, row sql.Row) (any, error) {
112112
}
113113
}
114114
// Next we'll assign our evaluated values to the expressions that the comparison functions reference
115-
it.staticLiteral.value = left
115+
// Note that the compiled functions already have a reference to this literal, so we have to edit it in place
116+
it.staticLiteral.Val = left
116117
for i, rightValue := range rightValues {
117-
it.arrayLiterals[i].value = rightValue
118+
it.arrayLiterals[i].Val = rightValue
118119
}
119120

120121
// Now we can loop over all of the comparison functions, as they'll reference their respective values
@@ -195,8 +196,8 @@ func (it *InTuple) WithChildren(children ...sql.Expression) (sql.Expression, err
195196
// the parameters, and assigning the values to our own literals, we do not have to worry. This offers a
196197
// significant speedup as function resolution is very expensive, so we want to do it as few times as possible
197198
// (preferably once).
198-
staticLiteral := &Literal{typ: leftType}
199-
arrayLiterals := make([]*Literal, len(rightTuple))
199+
staticLiteral := expression.NewLiteral(nil, leftType)
200+
arrayLiterals := make([]*expression.Literal, len(rightTuple))
200201
// Each expression may be a different type (which is valid), so we need a comparison function for each expression.
201202
compFuncs := make([]framework.Function, len(rightTuple))
202203
allValidChildren := true
@@ -206,7 +207,7 @@ func (it *InTuple) WithChildren(children ...sql.Expression) (sql.Expression, err
206207
allValidChildren = false
207208
break
208209
}
209-
arrayLiterals[i] = &Literal{typ: rightType}
210+
arrayLiterals[i] = expression.NewLiteral(nil, rightType)
210211
compFuncs[i] = framework.GetBinaryFunction(framework.Operator_BinaryEqual).Compile("internal_in_comparison", staticLiteral, arrayLiterals[i])
211212
if compFuncs[i] == nil {
212213
return nil, errors.Errorf("operator does not exist: %s = %s", leftType.String(), rightType.String())

0 commit comments

Comments
 (0)