diff --git a/go/vt/vtexplain/vtexplain_vttablet.go b/go/vt/vtexplain/vtexplain_vttablet.go index 7a745386cff..457a594925d 100644 --- a/go/vt/vtexplain/vtexplain_vttablet.go +++ b/go/vt/vtexplain/vtexplain_vttablet.go @@ -286,6 +286,15 @@ func initTabletEnvironment(ddls []*sqlparser.DDL, opts *Options) error { {sqltypes.NewVarBinary("1")}, }, }, + "select @@sql_auto_is_null": { + Fields: []*querypb.Field{{ + Type: sqltypes.Uint64, + }}, + RowsAffected: 1, + Rows: [][]sqltypes.Value{ + {sqltypes.NewVarBinary("0")}, + }, + }, "show variables like 'binlog_format'": { Fields: []*querypb.Field{{ Type: sqltypes.VarChar, diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 457a669df27..a72ce18cab6 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -471,6 +471,19 @@ func (e *Executor) handleSet(ctx context.Context, safeSession *SafeSession, sql safeSession.Options = &querypb.ExecuteOptions{} } safeSession.Options.SqlSelectLimit = val + case "sql_auto_is_null": + val, ok := v.(int64) + if !ok { + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected value type for sql_auto_is_null: %T", v) + } + switch val { + case 0: + // This is the default setting for MySQL. Do nothing. + case 1: + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "sql_auto_is_null is not currently supported") + default: + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected value for sql_auto_is_null: %d", val) + } case "character_set_results": // This is a statement that mysql-connector-j sends at the beginning. We return a canned response for it. switch v { diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index 45ee6845494..66e5c77ab09 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -329,6 +329,12 @@ func TestExecutorSet(t *testing.T) { }, { in: "set skip_query_plan_cache = 0", out: &vtgatepb.Session{Autocommit: true, Options: &querypb.ExecuteOptions{}}, + }, { + in: "set sql_auto_is_null = 0", + out: &vtgatepb.Session{Autocommit: true}, // no effect + }, { + in: "set sql_auto_is_null = 1", + err: "sql_auto_is_null is not currently supported", }} for _, tcase := range testcases { session := NewSafeSession(&vtgatepb.Session{Autocommit: true}) diff --git a/go/vt/vttablet/tabletserver/connpool/dbconn.go b/go/vt/vttablet/tabletserver/connpool/dbconn.go index d7ff9157078..1551bb94582 100644 --- a/go/vt/vttablet/tabletserver/connpool/dbconn.go +++ b/go/vt/vttablet/tabletserver/connpool/dbconn.go @@ -216,6 +216,7 @@ func (dbc *DBConn) streamOnce(ctx context.Context, query string, callback func(* var ( getModeSQL = "select @@global.sql_mode" getAutocommit = "select @@autocommit" + getAutoIsNull = "select @@sql_auto_is_null" showBinlog = "show variables like 'binlog_format'" ) @@ -245,6 +246,16 @@ func (dbc *DBConn) VerifyMode(strictTransTables bool) (BinlogFormat, error) { if !strings.Contains(qr.Rows[0][0].ToString(), "1") { return 0, fmt.Errorf("require autocommit to be 1: got %s", qr.Rows[0][0].ToString()) } + qr, err = dbc.conn.ExecuteFetch(getAutoIsNull, 2, false) + if err != nil { + return 0, fmt.Errorf("could not verify mode: %v", err) + } + if len(qr.Rows) != 1 { + return 0, fmt.Errorf("incorrect rowcount received for %s: %d", getAutoIsNull, len(qr.Rows)) + } + if !strings.Contains(qr.Rows[0][0].ToString(), "0") { + return 0, fmt.Errorf("require sql_auto_is_null to be 0: got %s", qr.Rows[0][0].ToString()) + } qr, err = dbc.conn.ExecuteFetch(showBinlog, 10, false) if err != nil { return 0, fmt.Errorf("could not fetch binlog format: %v", err) diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index 031a54e3575..548ff74a061 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -2107,6 +2107,15 @@ func getQueryExecutorSupportedQueries(testTableHasMultipleUniqueKeys bool) map[s {sqltypes.NewVarBinary("1")}, }, }, + "select @@sql_auto_is_null": { + Fields: []*querypb.Field{{ + Type: sqltypes.Uint64, + }}, + RowsAffected: 1, + Rows: [][]sqltypes.Value{ + {sqltypes.NewVarBinary("0")}, + }, + }, "show variables like 'binlog_format'": { Fields: []*querypb.Field{{ Type: sqltypes.VarChar, diff --git a/go/vt/vttablet/tabletserver/schema/schematest/schematest.go b/go/vt/vttablet/tabletserver/schema/schematest/schematest.go index 7b635f5df7a..207ba208d0c 100644 --- a/go/vt/vttablet/tabletserver/schema/schematest/schematest.go +++ b/go/vt/vttablet/tabletserver/schema/schematest/schematest.go @@ -57,6 +57,15 @@ func Queries() map[string]*sqltypes.Result { {sqltypes.NewVarBinary("1")}, }, }, + "select @@sql_auto_is_null": { + Fields: []*querypb.Field{{ + Type: sqltypes.Uint64, + }}, + RowsAffected: 1, + Rows: [][]sqltypes.Value{ + {sqltypes.NewVarBinary("0")}, + }, + }, "show variables like 'binlog_format'": { Fields: []*querypb.Field{{ Type: sqltypes.VarChar, diff --git a/go/vt/vttablet/tabletserver/tabletserver_test.go b/go/vt/vttablet/tabletserver/tabletserver_test.go index 0db326b5b93..2258e2a253d 100644 --- a/go/vt/vttablet/tabletserver/tabletserver_test.go +++ b/go/vt/vttablet/tabletserver/tabletserver_test.go @@ -2897,6 +2897,15 @@ func getSupportedQueries() map[string]*sqltypes.Result { {sqltypes.NewVarBinary("1")}, }, }, + "select @@sql_auto_is_null": { + Fields: []*querypb.Field{{ + Type: sqltypes.Uint64, + }}, + RowsAffected: 1, + Rows: [][]sqltypes.Value{ + {sqltypes.NewVarBinary("0")}, + }, + }, "show variables like 'binlog_format'": { Fields: []*querypb.Field{{ Type: sqltypes.VarChar,