From 3e16f3bf8205e310782fdd7a0999ff0d536b354b Mon Sep 17 00:00:00 2001 From: "vitess-bot[bot]" <108069721+vitess-bot[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:45:36 +0200 Subject: [PATCH] Cherry-pick 5fd70c4323680c9bc4efc3aa2ae4715d178b8726 with conflicts --- go/vt/vtgate/engine/projection.go | 34 +++++++++++++++++++++++ go/vt/vtgate/engine/projection_test.go | 38 ++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/go/vt/vtgate/engine/projection.go b/go/vt/vtgate/engine/projection.go index 85800187d1f..af0e39f2ee2 100644 --- a/go/vt/vtgate/engine/projection.go +++ b/go/vt/vtgate/engine/projection.go @@ -74,7 +74,11 @@ func (p *Projection) TryExecute(ctx context.Context, vcursor VCursor, bindVars m resultRows = append(resultRows, resultRow) } if wantfields { +<<<<<<< HEAD result.Fields, err = p.evalFields(env, result.Fields, vcursor) +======= + result.Fields, err = p.evalFields(env, result.Fields, vcursor.ConnCollation()) +>>>>>>> 5fd70c4323 (projection: Return correct collation information (#15801)) if err != nil { return nil, err } @@ -95,7 +99,11 @@ func (p *Projection) TryStreamExecute(ctx context.Context, vcursor VCursor, bind defer mu.Unlock() if wantfields { once.Do(func() { +<<<<<<< HEAD fields, err = p.evalFields(env, qr.Fields, vcursor) +======= + fields, err = p.evalFields(env, qr.Fields, vcursor.ConnCollation()) +>>>>>>> 5fd70c4323 (projection: Return correct collation information (#15801)) if err != nil { return } @@ -134,14 +142,26 @@ func (p *Projection) GetFields(ctx context.Context, vcursor VCursor, bindVars ma return nil, err } env := evalengine.NewExpressionEnv(ctx, bindVars, vcursor) +<<<<<<< HEAD qr.Fields, err = p.evalFields(env, qr.Fields, vcursor) +======= + qr.Fields, err = p.evalFields(env, qr.Fields, vcursor.ConnCollation()) +>>>>>>> 5fd70c4323 (projection: Return correct collation information (#15801)) if err != nil { return nil, err } return qr, nil } +<<<<<<< HEAD func (p *Projection) evalFields(env *evalengine.ExpressionEnv, infields []*querypb.Field, vcursor VCursor) ([]*querypb.Field, error) { +======= +func (p *Projection) evalFields(env *evalengine.ExpressionEnv, infields []*querypb.Field, coll collations.ID) ([]*querypb.Field, error) { + // TODO: once the evalengine becomes smart enough, we should be able to remove the + // dependency on these fields altogether + env.Fields = infields + +>>>>>>> 5fd70c4323 (projection: Return correct collation information (#15801)) var fields []*querypb.Field for i, col := range p.Cols { q, f, err := env.TypeOf(p.Exprs[i], infields) @@ -157,11 +177,25 @@ func (p *Projection) evalFields(env *evalengine.ExpressionEnv, infields []*query if !sqltypes.IsNull(q) && !f.Nullable() { fl |= uint32(querypb.MySqlFlag_NOT_NULL_FLAG) } + typCol := typ.Collation() + if sqltypes.IsTextOrBinary(typ.Type()) && typCol != collations.CollationBinaryID { + typCol = coll + } + fields = append(fields, &querypb.Field{ +<<<<<<< HEAD Name: col, Type: q, Charset: uint32(cs), Flags: fl, +======= + Name: col, + Type: typ.Type(), + Charset: uint32(typCol), + ColumnLength: uint32(typ.Size()), + Decimals: uint32(typ.Scale()), + Flags: fl, +>>>>>>> 5fd70c4323 (projection: Return correct collation information (#15801)) }) } return fields, nil diff --git a/go/vt/vtgate/engine/projection_test.go b/go/vt/vtgate/engine/projection_test.go index 2d260e901ea..6773d31c569 100644 --- a/go/vt/vtgate/engine/projection_test.go +++ b/go/vt/vtgate/engine/projection_test.go @@ -212,3 +212,41 @@ func TestFields(t *testing.T) { }) } } + +func TestFieldConversion(t *testing.T) { + var testCases = []struct { + name string + expr string + typ querypb.Type + collation collations.ID + }{ + { + name: `convert different charset`, + expr: `_latin1 0xFF`, + typ: sqltypes.VarChar, + collation: collations.MySQL8().DefaultConnectionCharset(), + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + arg, err := sqlparser.NewTestParser().ParseExpr(testCase.expr) + require.NoError(t, err) + bindExpr, err := evalengine.Translate(arg, &evalengine.Config{ + Environment: vtenv.NewTestEnv(), + Collation: collations.MySQL8().DefaultConnectionCharset(), + }) + require.NoError(t, err) + proj := &Projection{ + Cols: []string{"col"}, + Exprs: []evalengine.Expr{bindExpr}, + Input: &SingleRow{}, + noTxNeeded: noTxNeeded{}, + } + qr, err := proj.TryExecute(context.Background(), &noopVCursor{}, nil, true) + require.NoError(t, err) + assert.Equal(t, testCase.typ, qr.Fields[0].Type) + assert.Equal(t, testCase.collation, collations.ID(qr.Fields[0].Charset)) + }) + } +}