From 0fbce9c0197753fe0411177e70c9e71ecb5d5469 Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Sun, 15 Nov 2020 13:59:25 +0200 Subject: [PATCH 1/5] Adding ddl_strategy session variable Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- go/test/endtoend/onlineddl/onlineddl_test.go | 38 ++++++++++++-------- go/vt/schema/online_ddl.go | 13 +++++++ go/vt/schema/online_ddl_test.go | 22 ++++++++++++ go/vt/sqlparser/expression_rewriting.go | 1 + go/vt/sqlparser/expression_rewriting_test.go | 6 ++++ go/vt/sysvars/sysvars.go | 3 ++ go/vt/vtgate/engine/fake_vcursor_test.go | 4 +++ go/vt/vtgate/engine/primitive.go | 2 ++ go/vt/vtgate/engine/set.go | 11 ++++++ go/vt/vtgate/safe_session.go | 8 +++++ go/vt/vtgate/vcursor_impl.go | 5 +++ proto/vtgate.proto | 3 ++ 12 files changed, 102 insertions(+), 14 deletions(-) diff --git a/go/test/endtoend/onlineddl/onlineddl_test.go b/go/test/endtoend/onlineddl/onlineddl_test.go index 41f63843ef3..3ec883c7071 100644 --- a/go/test/endtoend/onlineddl/onlineddl_test.go +++ b/go/test/endtoend/onlineddl/onlineddl_test.go @@ -46,18 +46,22 @@ var ( msg varchar(64), PRIMARY KEY (id) ) ENGINE=InnoDB;` + // To verify non online-DDL behavior + alterTableNormalStatement = ` + ALTER TABLE %s + ADD COLUMN non_online INT UNSIGNED NOT NULL` // The following statement is valid - alterTableSuccessfulStatament = ` + alterTableSuccessfulStatement = ` ALTER WITH 'gh-ost' TABLE %s MODIFY id BIGINT UNSIGNED NOT NULL, ADD COLUMN ghost_col INT NOT NULL, ADD INDEX idx_msg(msg)` // The following statement will fail because gh-ost requires some shared unique key - alterTableFailedStatament = ` + alterTableFailedStatement = ` ALTER WITH 'gh-ost' TABLE %s DROP PRIMARY KEY, DROP COLUMN ghost_col` - alterTableThrottlingStatament = ` + alterTableThrottlingStatement = ` ALTER WITH 'gh-ost' '--max-load=Threads_running=1' TABLE %s DROP COLUMN ghost_col` ) @@ -123,20 +127,23 @@ func TestSchemaChange(t *testing.T) { assert.Equal(t, 2, len(clusterInstance.Keyspaces[0].Shards)) testWithInitialSchema(t) { - uuid := testAlterTable(t, alterTableSuccessfulStatament) + _ = testAlterTable(t, alterTableNormalStatement, false, "non_online") + } + { + uuid := testAlterTable(t, alterTableSuccessfulStatement, true, "ghost_col") checkRecentMigrations(t, uuid, schema.OnlineDDLStatusComplete) checkCancelMigration(t, uuid, false) checkRetryMigration(t, uuid, false) } { - uuid := testAlterTable(t, alterTableThrottlingStatament) + uuid := testAlterTable(t, alterTableThrottlingStatement, true, "ghost_col") checkRecentMigrations(t, uuid, schema.OnlineDDLStatusRunning) checkCancelMigration(t, uuid, true) time.Sleep(2 * time.Second) checkRecentMigrations(t, uuid, schema.OnlineDDLStatusFailed) } { - uuid := testAlterTable(t, alterTableFailedStatament) + uuid := testAlterTable(t, alterTableFailedStatement, true, "ghost_col") checkRecentMigrations(t, uuid, schema.OnlineDDLStatusFailed) checkCancelMigration(t, uuid, false) checkRetryMigration(t, uuid, true) @@ -157,16 +164,20 @@ func testWithInitialSchema(t *testing.T) { } // testAlterTable runs an online DDL, ALTER statement -func testAlterTable(t *testing.T, alterStatement string) (uuid string) { +func testAlterTable(t *testing.T, alterStatement string, isOnlineDDL bool, expectColumn string) (uuid string) { tableName := fmt.Sprintf("vt_onlineddl_test_%02d", 3) sqlQuery := fmt.Sprintf(alterStatement, tableName) uuid, err := clusterInstance.VtctlclientProcess.ApplySchemaWithOutput(keyspaceName, sqlQuery) require.Nil(t, err) uuid = strings.TrimSpace(uuid) - require.NotEmpty(t, uuid) - // Migration is asynchronous. Give it some time. - time.Sleep(time.Second * 20) - checkMigratedTable(t, tableName) + if isOnlineDDL { + require.NotEmpty(t, uuid) + // Migration is asynchronous. Give it some time. + time.Sleep(time.Second * 20) + } else { + require.Empty(t, uuid) + } + checkMigratedTable(t, tableName, expectColumn) return uuid } @@ -239,11 +250,10 @@ func checkRetryMigration(t *testing.T, uuid string, expectRetryPossible bool) { } // checkMigratedTables checks the CREATE STATEMENT of a table after migration -func checkMigratedTable(t *testing.T, tableName string) { - expect := "ghost_col" +func checkMigratedTable(t *testing.T, tableName, expectColumn string) { for i := range clusterInstance.Keyspaces[0].Shards { createStatement := getCreateTableStatement(t, clusterInstance.Keyspaces[0].Shards[i].Vttablets[0], tableName) - assert.Contains(t, createStatement, expect) + assert.Contains(t, createStatement, expectColumn) } } diff --git a/go/vt/schema/online_ddl.go b/go/vt/schema/online_ddl.go index 9d6c736f8c1..644a7382548 100644 --- a/go/vt/schema/online_ddl.go +++ b/go/vt/schema/online_ddl.go @@ -99,6 +99,19 @@ type OnlineDDL struct { Retries int64 `json:"retries,omitempty"` } +func ValidateDDLStrategy(strategy string) (sqlparser.DDLStrategy, error) { + switch sqlparser.DDLStrategy(strategy) { + case DDLStrategyGhost: + return DDLStrategyGhost, nil + case DDLStrategyPTOSC: + return DDLStrategyPTOSC, nil + case DDLStrategyNormal: + return DDLStrategyNormal, nil + default: + return DDLStrategyNormal, fmt.Errorf("Unknown online DDL strategy: '%v'", strategy) + } +} + // FromJSON creates an OnlineDDL from json func FromJSON(bytes []byte) (*OnlineDDL, error) { onlineDDL := &OnlineDDL{} diff --git a/go/vt/schema/online_ddl_test.go b/go/vt/schema/online_ddl_test.go index 4475fcc632c..f0bf0e9b5f2 100644 --- a/go/vt/schema/online_ddl_test.go +++ b/go/vt/schema/online_ddl_test.go @@ -27,6 +27,28 @@ func TestCreateUUID(t *testing.T) { assert.NoError(t, err) } +func TestValidateDDLStrategy(t *testing.T) { + { + strategy, err := ValidateDDLStrategy("gh-ost") + assert.NoError(t, err) + assert.Equal(t, DDLStrategyGhost, strategy) + } + { + strategy, err := ValidateDDLStrategy("pt-osc") + assert.NoError(t, err) + assert.Equal(t, DDLStrategyPTOSC, strategy) + } + { + strategy, err := ValidateDDLStrategy("") + assert.NoError(t, err) + assert.Equal(t, DDLStrategyNormal, strategy) + } + { + _, err := ValidateDDLStrategy("other") + assert.Error(t, err) + } +} + func TestIsOnlineDDLUUID(t *testing.T) { for i := 0; i < 20; i++ { uuid, err := CreateUUID() diff --git a/go/vt/sqlparser/expression_rewriting.go b/go/vt/sqlparser/expression_rewriting.go index 444a01d6137..7fc90d779d3 100644 --- a/go/vt/sqlparser/expression_rewriting.go +++ b/go/vt/sqlparser/expression_rewriting.go @@ -127,6 +127,7 @@ func (er *expressionRewriter) sysVarRewrite(cursor *Cursor, node *ColName) { sysvars.SQLSelectLimit.Name, sysvars.TransactionMode.Name, sysvars.Workload.Name, + sysvars.DDLStrategy.Name, sysvars.ReadAfterWriteGTID.Name, sysvars.ReadAfterWriteTimeOut.Name, sysvars.SessionTrackGTIDs.Name: diff --git a/go/vt/sqlparser/expression_rewriting_test.go b/go/vt/sqlparser/expression_rewriting_test.go index 1d5cf1eff63..25a3a0abbc2 100644 --- a/go/vt/sqlparser/expression_rewriting_test.go +++ b/go/vt/sqlparser/expression_rewriting_test.go @@ -28,6 +28,7 @@ import ( type myTestCase struct { in, expected string liid, db, foundRows, rowCount, rawGTID, rawTimeout, sessTrackGTID bool + ddlStrategy bool udv int autocommit, clientFoundRows, skipQueryPlanCache bool sqlSelectLimit, transactionMode, workload bool @@ -145,6 +146,10 @@ func TestRewrites(in *testing.T) { in: `select (select (select (select (select (select last_insert_id()))))) as x`, expected: "select :__lastInsertId as x from dual", liid: true, + }, { + in: `select * from user where col = @@ddl_strategy`, + expected: "select * from user where col = :__vtddl_strategy", + ddlStrategy: true, }, { in: `select * from user where col = @@read_after_write_gtid OR col = @@read_after_write_timeout OR col = @@session_track_gtids`, expected: "select * from user where col = :__vtread_after_write_gtid or col = :__vtread_after_write_timeout or col = :__vtsession_track_gtids", @@ -177,6 +182,7 @@ func TestRewrites(in *testing.T) { assert.Equal(tc.sqlSelectLimit, result.NeedsSysVar(sysvars.SQLSelectLimit.Name), "should need :__vtsqlSelectLimit") assert.Equal(tc.transactionMode, result.NeedsSysVar(sysvars.TransactionMode.Name), "should need :__vttransactionMode") assert.Equal(tc.workload, result.NeedsSysVar(sysvars.Workload.Name), "should need :__vtworkload") + assert.Equal(tc.ddlStrategy, result.NeedsSysVar(sysvars.DDLStrategy.Name), "should need ddlStrategy") assert.Equal(tc.rawGTID, result.NeedsSysVar(sysvars.ReadAfterWriteGTID.Name), "should need rawGTID") assert.Equal(tc.rawTimeout, result.NeedsSysVar(sysvars.ReadAfterWriteTimeOut.Name), "should need rawTimeout") assert.Equal(tc.sessTrackGTID, result.NeedsSysVar(sysvars.SessionTrackGTIDs.Name), "should need sessTrackGTID") diff --git a/go/vt/sysvars/sysvars.go b/go/vt/sysvars/sysvars.go index 88543366db9..2fa219fa2f6 100644 --- a/go/vt/sysvars/sysvars.go +++ b/go/vt/sysvars/sysvars.go @@ -53,6 +53,8 @@ var ( Workload = SystemVariable{Name: "workload", IdentifierAsString: true} Charset = SystemVariable{Name: "charset", Default: utf8, IdentifierAsString: true} Names = SystemVariable{Name: "names", Default: utf8, IdentifierAsString: true} + // Online DDL + DDLStrategy = SystemVariable{Name: "ddl_strategy", IdentifierAsString: true} // Read After Write settings ReadAfterWriteGTID = SystemVariable{Name: "read_after_write_gtid"} @@ -67,6 +69,7 @@ var ( TransactionReadOnly, SQLSelectLimit, TransactionMode, + DDLStrategy, Workload, Charset, Names, diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index bf6e699400e..cea216e3310 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -57,6 +57,10 @@ type noopVCursor struct { ctx context.Context } +func (t noopVCursor) SetDDLStrategy(strategy sqlparser.DDLStrategy) { + panic("implement me") +} + func (t noopVCursor) SetReadAfterWriteGTID(s string) { panic("implement me") } diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index c95965ebe59..8577632fef0 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -126,6 +126,8 @@ type ( SetWorkload(querypb.ExecuteOptions_Workload) SetFoundRows(uint64) + SetDDLStrategy(sqlparser.DDLStrategy) + // SetReadAfterWriteGTID sets the GTID that the user expects a replica to have caught up with before answering a query SetReadAfterWriteGTID(string) SetReadAfterWriteTimeout(float64) diff --git a/go/vt/vtgate/engine/set.go b/go/vt/vtgate/engine/set.go index 1bbea6a6a08..655f3f1ba43 100644 --- a/go/vt/vtgate/engine/set.go +++ b/go/vt/vtgate/engine/set.go @@ -36,6 +36,7 @@ import ( "vitess.io/vitess/go/vt/key" querypb "vitess.io/vitess/go/vt/proto/query" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/vindexes" ) @@ -398,6 +399,16 @@ func (svss *SysVarSetAware) Execute(vcursor VCursor, env evalengine.ExpressionEn return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid workload: %s", str) } vcursor.Session().SetWorkload(querypb.ExecuteOptions_Workload(out)) + case sysvars.DDLStrategy.Name: + str, err := svss.evalAsString(env) + if err != nil { + return err + } + strategy, err := schema.ValidateDDLStrategy(str) + if err != nil { + return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid DDL strategy: %s", str) + } + vcursor.Session().SetDDLStrategy(strategy) case sysvars.Charset.Name, sysvars.Names.Name: str, err := svss.evalAsString(env) if err != nil { diff --git a/go/vt/vtgate/safe_session.go b/go/vt/vtgate/safe_session.go index 0906c45e98b..7f76725c98f 100644 --- a/go/vt/vtgate/safe_session.go +++ b/go/vt/vtgate/safe_session.go @@ -22,6 +22,7 @@ import ( "time" "github.com/golang/protobuf/proto" + "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vterrors" querypb "vitess.io/vitess/go/vt/proto/query" @@ -453,6 +454,13 @@ func (session *SafeSession) ResetShard(tabletAlias *topodatapb.TabletAlias) erro return nil } +// SetDDLStrategy set the DDLStrategy setting. +func (session *SafeSession) SetDDLStrategy(strategy sqlparser.DDLStrategy) { + session.mu.Lock() + defer session.mu.Unlock() + // session.DDLStrategy = string(strategy) +} + // SetReadAfterWriteGTID set the ReadAfterWriteGtid setting. func (session *SafeSession) SetReadAfterWriteGTID(vtgtid string) { session.mu.Lock() diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index 0999c146cce..3d970dee2aa 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -585,6 +585,11 @@ func (vc *vcursorImpl) SetFoundRows(foundRows uint64) { vc.safeSession.foundRowsHandled = true } +// SetReadAfterWriteGTID implements the SessionActions interface +func (vc *vcursorImpl) SetDDLStrategy(strategy sqlparser.DDLStrategy) { + vc.safeSession.SetDDLStrategy(strategy) +} + // SetReadAfterWriteGTID implements the SessionActions interface func (vc *vcursorImpl) SetReadAfterWriteGTID(vtgtid string) { vc.safeSession.SetReadAfterWriteGTID(vtgtid) diff --git a/proto/vtgate.proto b/proto/vtgate.proto index 5dbc3665282..2e3318b51cf 100644 --- a/proto/vtgate.proto +++ b/proto/vtgate.proto @@ -137,6 +137,9 @@ message Session { // read_after_write tracks the ReadAfterWrite settings for this session. ReadAfterWrite read_after_write = 20; + + // DDL strategy + string DDLStrategy = 21; } // ReadAfterWrite contains information regarding gtid set and timeout From b64957396981db80a1ba4260192bf25d58612c32 Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Sun, 15 Nov 2020 15:40:47 +0200 Subject: [PATCH 2/5] vtgate protoc Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- go/vt/proto/vtgate/vtgate.pb.go | 181 +++++++++++++++++--------------- 1 file changed, 96 insertions(+), 85 deletions(-) diff --git a/go/vt/proto/vtgate/vtgate.pb.go b/go/vt/proto/vtgate/vtgate.pb.go index 1f576baffd8..c3c84d1cb51 100644 --- a/go/vt/proto/vtgate/vtgate.pb.go +++ b/go/vt/proto/vtgate/vtgate.pb.go @@ -152,10 +152,12 @@ type Session struct { // last_lock_heartbeat keep tracks of when last lock heartbeat was sent. LastLockHeartbeat int64 `protobuf:"varint,19,opt,name=last_lock_heartbeat,json=lastLockHeartbeat,proto3" json:"last_lock_heartbeat,omitempty"` // read_after_write tracks the ReadAfterWrite settings for this session. - ReadAfterWrite *ReadAfterWrite `protobuf:"bytes,20,opt,name=read_after_write,json=readAfterWrite,proto3" json:"read_after_write,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + ReadAfterWrite *ReadAfterWrite `protobuf:"bytes,20,opt,name=read_after_write,json=readAfterWrite,proto3" json:"read_after_write,omitempty"` + // DDL strategy + DDLStrategy string `protobuf:"bytes,21,opt,name=DDLStrategy,proto3" json:"DDLStrategy,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Session) Reset() { *m = Session{} } @@ -316,6 +318,13 @@ func (m *Session) GetReadAfterWrite() *ReadAfterWrite { return nil } +func (m *Session) GetDDLStrategy() string { + if m != nil { + return m.DDLStrategy + } + return "" +} + type Session_ShardSession struct { Target *query.Target `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` TransactionId int64 `protobuf:"varint,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` @@ -1083,88 +1092,90 @@ func init() { func init() { proto.RegisterFile("vtgate.proto", fileDescriptor_aab96496ceaf1ebb) } var fileDescriptor_aab96496ceaf1ebb = []byte{ - // 1328 bytes of a gzipped FileDescriptorProto + // 1346 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xdd, 0x6e, 0x1b, 0xb7, 0x12, 0xce, 0xea, 0x5f, 0xa3, 0xbf, 0x35, 0x6d, 0xe7, 0x6c, 0x7c, 0x72, 0xce, 0x11, 0x94, 0x04, 0x51, 0x72, 0x0a, 0xa9, 0x75, 0xd1, 0x36, 0x28, 0x5a, 0xb4, 0xb6, 0xac, 0xa4, 0x0a, 0xec, 0xc8, - 0xa5, 0x64, 0x1b, 0x28, 0x5a, 0x2c, 0xd6, 0x5a, 0x5a, 0x26, 0x2c, 0x2f, 0x15, 0x92, 0x92, 0xab, - 0xa7, 0xe8, 0x7d, 0x5f, 0xa0, 0x37, 0xbd, 0xef, 0x3b, 0xf4, 0xae, 0x57, 0x7d, 0x9d, 0x82, 0xe4, - 0xae, 0xb4, 0x52, 0xdc, 0xc6, 0x49, 0x90, 0x1b, 0x61, 0x39, 0xdf, 0x70, 0x38, 0x9c, 0xef, 0x1b, - 0x92, 0x82, 0xe2, 0x54, 0x0e, 0x3d, 0x49, 0x1a, 0x63, 0xce, 0x24, 0x43, 0x19, 0x33, 0xda, 0xb2, - 0x4f, 0x69, 0x30, 0x62, 0x43, 0xdf, 0x93, 0x9e, 0x41, 0xb6, 0x0a, 0x2f, 0x27, 0x84, 0xcf, 0xc2, - 0x41, 0x59, 0xb2, 0x31, 0x8b, 0x83, 0x53, 0xc9, 0xc7, 0x03, 0x33, 0xa8, 0xfd, 0x09, 0x90, 0xed, - 0x11, 0x21, 0x28, 0x0b, 0xd0, 0x03, 0x28, 0xd3, 0xc0, 0x95, 0xdc, 0x0b, 0x84, 0x37, 0x90, 0x94, - 0x05, 0x8e, 0x55, 0xb5, 0xea, 0x39, 0x5c, 0xa2, 0x41, 0x7f, 0x61, 0x44, 0x2d, 0x28, 0x8b, 0x73, - 0x8f, 0xfb, 0xae, 0x30, 0xf3, 0x84, 0x93, 0xa8, 0x26, 0xeb, 0x85, 0xed, 0xbb, 0x8d, 0x30, 0xbb, - 0x30, 0x5e, 0xa3, 0xa7, 0xbc, 0xc2, 0x01, 0x2e, 0x89, 0xd8, 0x48, 0xa0, 0xff, 0x02, 0x78, 0x13, - 0xc9, 0x06, 0xec, 0xf2, 0x92, 0x4a, 0x27, 0xa5, 0xd7, 0x89, 0x59, 0xd0, 0x3d, 0x28, 0x49, 0x8f, - 0x0f, 0x89, 0x74, 0x85, 0xe4, 0x34, 0x18, 0x3a, 0xe9, 0xaa, 0x55, 0xcf, 0xe3, 0xa2, 0x31, 0xf6, - 0xb4, 0x0d, 0x35, 0x21, 0xcb, 0xc6, 0x52, 0xa7, 0x90, 0xa9, 0x5a, 0xf5, 0xc2, 0xf6, 0x66, 0xc3, - 0x6c, 0xbc, 0xfd, 0x23, 0x19, 0x4c, 0x24, 0xe9, 0x1a, 0x10, 0x47, 0x5e, 0x68, 0x17, 0xec, 0xd8, - 0xf6, 0xdc, 0x4b, 0xe6, 0x13, 0x27, 0x5b, 0xb5, 0xea, 0xe5, 0xed, 0x7f, 0x45, 0xc9, 0xc7, 0x76, - 0x7a, 0xc0, 0x7c, 0x82, 0x2b, 0x72, 0xd9, 0x80, 0x9a, 0x90, 0xbb, 0xf2, 0x78, 0x40, 0x83, 0xa1, - 0x70, 0x72, 0x7a, 0xe3, 0xeb, 0xe1, 0xaa, 0xdf, 0xaa, 0xdf, 0x13, 0x83, 0xe1, 0xb9, 0x13, 0xfa, - 0x0a, 0x8a, 0x63, 0x4e, 0x16, 0xd5, 0xca, 0xdf, 0xa0, 0x5a, 0x85, 0x31, 0x27, 0xf3, 0x5a, 0xed, - 0x40, 0x69, 0xcc, 0x84, 0x5c, 0x44, 0x80, 0x1b, 0x44, 0x28, 0xaa, 0x29, 0xf3, 0x10, 0xf7, 0xa1, - 0x3c, 0xf2, 0x84, 0x74, 0x69, 0x20, 0x08, 0x97, 0x2e, 0xf5, 0x9d, 0x42, 0xd5, 0xaa, 0xa7, 0x70, - 0x51, 0x59, 0x3b, 0xda, 0xd8, 0xf1, 0xd1, 0x7f, 0x00, 0xce, 0xd8, 0x24, 0xf0, 0x5d, 0xce, 0xae, - 0x84, 0x53, 0xd4, 0x1e, 0x79, 0x6d, 0xc1, 0xec, 0x4a, 0x20, 0x17, 0x6e, 0x4f, 0x04, 0xe1, 0xae, - 0x4f, 0xce, 0x68, 0x40, 0x7c, 0x77, 0xea, 0x71, 0xea, 0x9d, 0x8e, 0x88, 0x70, 0x4a, 0x3a, 0xa1, - 0x47, 0xab, 0x09, 0x1d, 0x09, 0xc2, 0xf7, 0x8c, 0xf3, 0x71, 0xe4, 0xdb, 0x0e, 0x24, 0x9f, 0xe1, - 0x8d, 0xc9, 0x35, 0x10, 0xea, 0x82, 0x2d, 0x66, 0x42, 0x92, 0xcb, 0x58, 0xe8, 0xb2, 0x0e, 0x7d, - 0xff, 0x95, 0xbd, 0x6a, 0xbf, 0x95, 0xa8, 0x15, 0xb1, 0x6c, 0x45, 0xff, 0x86, 0x3c, 0x67, 0x57, - 0xee, 0x80, 0x4d, 0x02, 0xe9, 0x54, 0xaa, 0x56, 0x3d, 0x89, 0x73, 0x9c, 0x5d, 0xb5, 0xd4, 0x58, - 0x49, 0x50, 0x78, 0x53, 0x32, 0x66, 0x34, 0x90, 0xc2, 0xb1, 0xab, 0xc9, 0x7a, 0x1e, 0xc7, 0x2c, - 0xa8, 0x0e, 0x36, 0x0d, 0x5c, 0x4e, 0x04, 0xe1, 0x53, 0xe2, 0xbb, 0x03, 0x16, 0x04, 0xce, 0x9a, - 0x16, 0x6a, 0x99, 0x06, 0x38, 0x34, 0xb7, 0x58, 0x10, 0x28, 0x86, 0x47, 0x6c, 0x70, 0x11, 0x11, - 0xe4, 0x20, 0x2d, 0xc6, 0xd7, 0x30, 0xac, 0x66, 0x44, 0x9d, 0xd7, 0x80, 0x75, 0x4d, 0x8f, 0x8e, - 0x72, 0x4e, 0x3c, 0x2e, 0x4f, 0x89, 0x27, 0x9d, 0x75, 0x9d, 0xf1, 0x9a, 0x82, 0xf6, 0xd9, 0xe0, - 0xe2, 0x9b, 0x08, 0x40, 0x5f, 0x83, 0xcd, 0x89, 0xe7, 0xbb, 0xde, 0x99, 0x24, 0xdc, 0xbd, 0xe2, - 0x54, 0x12, 0x67, 0x43, 0x2f, 0x7a, 0x3b, 0x5a, 0x14, 0x13, 0xcf, 0xdf, 0x51, 0xf0, 0x89, 0x42, - 0x71, 0x99, 0x2f, 0x8d, 0xb7, 0x7e, 0xb3, 0xa0, 0x18, 0xcf, 0x07, 0x3d, 0x80, 0x8c, 0xe9, 0x2d, - 0xdd, 0xf4, 0x85, 0xed, 0x52, 0x28, 0xea, 0xbe, 0x36, 0xe2, 0x10, 0x54, 0x67, 0x44, 0xbc, 0x83, - 0xa8, 0xef, 0x24, 0x74, 0x92, 0xa5, 0x98, 0xb5, 0xe3, 0xa3, 0x27, 0x50, 0x94, 0x8a, 0x02, 0xe9, - 0x7a, 0x23, 0xea, 0x09, 0x27, 0x19, 0xb6, 0xe7, 0xfc, 0x28, 0xea, 0x6b, 0x74, 0x47, 0x81, 0xb8, - 0x20, 0x17, 0x03, 0xf4, 0x3f, 0x28, 0xcc, 0x4b, 0x4e, 0x7d, 0x7d, 0x32, 0x24, 0x31, 0x44, 0xa6, - 0x8e, 0xbf, 0xf5, 0x3d, 0xdc, 0xf9, 0x5b, 0x5d, 0x21, 0x1b, 0x92, 0x17, 0x64, 0xa6, 0xb7, 0x90, - 0xc7, 0xea, 0x13, 0x3d, 0x82, 0xf4, 0xd4, 0x1b, 0x4d, 0x88, 0xce, 0x73, 0xd1, 0xab, 0xbb, 0x34, - 0x98, 0xcf, 0xc5, 0xc6, 0xe3, 0xf3, 0xc4, 0x13, 0x6b, 0x6b, 0x17, 0x36, 0xae, 0x93, 0xd6, 0x35, - 0x81, 0x37, 0xe2, 0x81, 0xf3, 0xb1, 0x18, 0xcf, 0x53, 0xb9, 0xa4, 0x9d, 0xaa, 0xfd, 0x6a, 0x41, - 0x79, 0x99, 0x04, 0xf4, 0x11, 0x6c, 0xae, 0xd2, 0xe6, 0x0e, 0x25, 0xf5, 0xc3, 0xb0, 0x68, 0x99, - 0xa3, 0x67, 0x92, 0xfa, 0xe8, 0x33, 0x70, 0x5e, 0x99, 0x22, 0xe9, 0x25, 0x61, 0x13, 0xa9, 0x17, - 0xb6, 0xf0, 0xe6, 0xf2, 0xac, 0xbe, 0x01, 0x95, 0xa4, 0x42, 0x39, 0xaa, 0x13, 0x7d, 0x70, 0xa1, - 0x17, 0x32, 0x44, 0xe4, 0xf0, 0x5a, 0x08, 0xf5, 0x15, 0xa2, 0xd6, 0x11, 0xb5, 0x5f, 0x12, 0x50, - 0x0e, 0x8f, 0x4d, 0x4c, 0x5e, 0x4e, 0x88, 0x90, 0xe8, 0x03, 0xc8, 0x0f, 0xbc, 0xd1, 0x88, 0x70, - 0x37, 0x4c, 0xb1, 0xb0, 0x5d, 0x69, 0x98, 0xcb, 0xa3, 0xa5, 0xed, 0x9d, 0x3d, 0x9c, 0x33, 0x1e, - 0x1d, 0x1f, 0x3d, 0x82, 0x6c, 0xa4, 0xff, 0xc4, 0xdc, 0x37, 0xae, 0x7f, 0x1c, 0xe1, 0xe8, 0x21, - 0xa4, 0x35, 0x0b, 0xa1, 0x2c, 0xd6, 0x22, 0x4e, 0xd4, 0x49, 0xa3, 0x0f, 0x51, 0x6c, 0x70, 0xf4, - 0x09, 0x84, 0xda, 0x70, 0xe5, 0x6c, 0x4c, 0xb4, 0x18, 0xca, 0xdb, 0x1b, 0xab, 0x2a, 0xea, 0xcf, - 0xc6, 0x04, 0x83, 0x9c, 0x7f, 0x2b, 0x91, 0x5e, 0x90, 0x99, 0x18, 0x7b, 0x03, 0xe2, 0xea, 0x6b, - 0x47, 0x5f, 0x0f, 0x79, 0x5c, 0x8a, 0xac, 0x5a, 0xf9, 0xf1, 0xeb, 0x23, 0x7b, 0x93, 0xeb, 0xe3, - 0x79, 0x2a, 0x97, 0xb6, 0x33, 0xb5, 0x9f, 0x2c, 0xa8, 0xcc, 0x2b, 0x25, 0xc6, 0x2c, 0x10, 0x6a, - 0xc5, 0x34, 0xe1, 0x9c, 0xf1, 0x95, 0x32, 0xe1, 0xc3, 0x56, 0x5b, 0x99, 0xb1, 0x41, 0xdf, 0xa4, - 0x46, 0x8f, 0x21, 0xc3, 0x89, 0x98, 0x8c, 0x64, 0x58, 0x24, 0x14, 0xbf, 0x64, 0xb0, 0x46, 0x70, - 0xe8, 0x51, 0xfb, 0x23, 0x01, 0xeb, 0x61, 0x46, 0xbb, 0x9e, 0x1c, 0x9c, 0xbf, 0x77, 0x02, 0xff, - 0x0f, 0x59, 0x95, 0x0d, 0x25, 0x4a, 0x50, 0xc9, 0xeb, 0x29, 0x8c, 0x3c, 0xde, 0x81, 0x44, 0x4f, - 0x2c, 0xbd, 0x46, 0xd2, 0xe6, 0x35, 0xe2, 0x89, 0xf8, 0x6b, 0xe4, 0x3d, 0x71, 0x5d, 0xfb, 0xd9, - 0x82, 0x8d, 0xe5, 0x9a, 0xbe, 0x37, 0xaa, 0x3f, 0x84, 0xac, 0x21, 0x32, 0xaa, 0xe6, 0xed, 0x30, - 0x37, 0x43, 0xf3, 0x09, 0x95, 0xe7, 0x26, 0x74, 0xe4, 0xa6, 0x9a, 0x75, 0xa3, 0x27, 0x39, 0xf1, - 0x2e, 0xdf, 0xa9, 0x65, 0xe7, 0x7d, 0x98, 0x78, 0xb3, 0x3e, 0x4c, 0xbe, 0x75, 0x1f, 0xa6, 0x5e, - 0xc3, 0x4d, 0xfa, 0x46, 0xcf, 0xb8, 0x58, 0x6d, 0x33, 0xff, 0x5c, 0xdb, 0x5a, 0x0b, 0x36, 0x57, - 0x0a, 0x15, 0xd2, 0xb8, 0xe8, 0x2f, 0xeb, 0xb5, 0xfd, 0xf5, 0x03, 0xdc, 0xc1, 0x44, 0xb0, 0xd1, - 0x94, 0xc4, 0x94, 0xf7, 0x76, 0x25, 0x47, 0x90, 0xf2, 0x65, 0x78, 0x6b, 0xe6, 0xb1, 0xfe, 0xae, - 0xdd, 0x85, 0xad, 0xeb, 0xc2, 0x9b, 0x44, 0x6b, 0xbf, 0x5b, 0x50, 0x3e, 0x36, 0x7b, 0x78, 0xbb, - 0x25, 0x57, 0xc8, 0x4b, 0xdc, 0x90, 0xbc, 0x87, 0x90, 0x9e, 0xea, 0xcb, 0x29, 0x3a, 0xa4, 0x63, - 0xff, 0x32, 0x8e, 0xd5, 0x9d, 0x81, 0x0d, 0xae, 0x2a, 0x79, 0x46, 0x47, 0x92, 0x70, 0xcd, 0xae, - 0xaa, 0x64, 0xcc, 0xf3, 0xa9, 0x46, 0x70, 0xe8, 0x51, 0xfb, 0x12, 0x2a, 0xf3, 0xbd, 0x2c, 0x88, - 0x20, 0x53, 0xa2, 0x9e, 0x60, 0x96, 0x16, 0xff, 0xd2, 0xf4, 0xe3, 0xb6, 0x82, 0x70, 0xe8, 0xf1, - 0x78, 0x0f, 0x2a, 0x2b, 0xef, 0x73, 0x54, 0x81, 0xc2, 0xd1, 0x8b, 0xde, 0x61, 0xbb, 0xd5, 0x79, - 0xda, 0x69, 0xef, 0xd9, 0xb7, 0x10, 0x40, 0xa6, 0xd7, 0x79, 0xf1, 0x6c, 0xbf, 0x6d, 0x5b, 0x28, - 0x0f, 0xe9, 0x83, 0xa3, 0xfd, 0x7e, 0xc7, 0x4e, 0xa8, 0xcf, 0xfe, 0x49, 0xf7, 0xb0, 0x65, 0x27, - 0x1f, 0x7f, 0x01, 0x85, 0x96, 0xfe, 0x97, 0xd1, 0xe5, 0x3e, 0xe1, 0x6a, 0xc2, 0x8b, 0x2e, 0x3e, - 0xd8, 0xd9, 0xb7, 0x6f, 0xa1, 0x2c, 0x24, 0x0f, 0xb1, 0x9a, 0x99, 0x83, 0xd4, 0x61, 0xb7, 0xd7, - 0xb7, 0x13, 0xa8, 0x0c, 0xb0, 0x73, 0xd4, 0xef, 0xb6, 0xba, 0x07, 0x07, 0x9d, 0xbe, 0x9d, 0xdc, - 0xfd, 0x14, 0x2a, 0x94, 0x35, 0xa6, 0x54, 0x12, 0x21, 0xcc, 0x9f, 0xa8, 0xef, 0xee, 0x85, 0x23, - 0xca, 0x9a, 0xe6, 0xab, 0x39, 0x64, 0xcd, 0xa9, 0x6c, 0x6a, 0xb4, 0x69, 0xa4, 0x79, 0x9a, 0xd1, - 0xa3, 0x8f, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0x34, 0x51, 0xbb, 0x1e, 0xc4, 0x0d, 0x00, 0x00, + 0xa5, 0x64, 0x1b, 0x28, 0x5a, 0x2c, 0x68, 0x2d, 0x2d, 0x13, 0x96, 0x97, 0x0a, 0x49, 0xc9, 0xd5, + 0x53, 0xf4, 0xbe, 0x2f, 0xd0, 0x9b, 0xde, 0xf7, 0x1d, 0x7a, 0xd7, 0xc7, 0xe9, 0x5d, 0x41, 0xee, + 0xae, 0xb4, 0x52, 0xdc, 0xc6, 0x49, 0x90, 0x1b, 0x61, 0x67, 0xbe, 0xe1, 0x70, 0x38, 0xdf, 0x0c, + 0x87, 0x82, 0xe2, 0x54, 0x0d, 0x89, 0xa2, 0x8d, 0xb1, 0xe0, 0x8a, 0xa3, 0x4c, 0x20, 0x6d, 0xd9, + 0xa7, 0xcc, 0x1f, 0xf1, 0xa1, 0x47, 0x14, 0x09, 0x90, 0xad, 0xc2, 0xcb, 0x09, 0x15, 0xb3, 0x50, + 0x28, 0x2b, 0x3e, 0xe6, 0x71, 0x70, 0xaa, 0xc4, 0x78, 0x10, 0x08, 0xb5, 0x3f, 0x01, 0xb2, 0x3d, + 0x2a, 0x25, 0xe3, 0x3e, 0x7a, 0x00, 0x65, 0xe6, 0xbb, 0x4a, 0x10, 0x5f, 0x92, 0x81, 0x62, 0xdc, + 0x77, 0xac, 0xaa, 0x55, 0xcf, 0xe1, 0x12, 0xf3, 0xfb, 0x0b, 0x25, 0x6a, 0x41, 0x59, 0x9e, 0x13, + 0xe1, 0xb9, 0x32, 0x58, 0x27, 0x9d, 0x44, 0x35, 0x59, 0x2f, 0x6c, 0xdf, 0x6d, 0x84, 0xd1, 0x85, + 0xfe, 0x1a, 0x3d, 0x6d, 0x15, 0x0a, 0xb8, 0x24, 0x63, 0x92, 0x44, 0xff, 0x05, 0x20, 0x13, 0xc5, + 0x07, 0xfc, 0xf2, 0x92, 0x29, 0x27, 0x65, 0xf6, 0x89, 0x69, 0xd0, 0x3d, 0x28, 0x29, 0x22, 0x86, + 0x54, 0xb9, 0x52, 0x09, 0xe6, 0x0f, 0x9d, 0x74, 0xd5, 0xaa, 0xe7, 0x71, 0x31, 0x50, 0xf6, 0x8c, + 0x0e, 0x35, 0x21, 0xcb, 0xc7, 0xca, 0x84, 0x90, 0xa9, 0x5a, 0xf5, 0xc2, 0xf6, 0x66, 0x23, 0x38, + 0x78, 0xfb, 0x47, 0x3a, 0x98, 0x28, 0xda, 0x0d, 0x40, 0x1c, 0x59, 0xa1, 0x5d, 0xb0, 0x63, 0xc7, + 0x73, 0x2f, 0xb9, 0x47, 0x9d, 0x6c, 0xd5, 0xaa, 0x97, 0xb7, 0xff, 0x15, 0x05, 0x1f, 0x3b, 0xe9, + 0x01, 0xf7, 0x28, 0xae, 0xa8, 0x65, 0x05, 0x6a, 0x42, 0xee, 0x8a, 0x08, 0x9f, 0xf9, 0x43, 0xe9, + 0xe4, 0xcc, 0xc1, 0xd7, 0xc3, 0x5d, 0xbf, 0xd5, 0xbf, 0x27, 0x01, 0x86, 0xe7, 0x46, 0xe8, 0x2b, + 0x28, 0x8e, 0x05, 0x5d, 0x64, 0x2b, 0x7f, 0x83, 0x6c, 0x15, 0xc6, 0x82, 0xce, 0x73, 0xb5, 0x03, + 0xa5, 0x31, 0x97, 0x6a, 0xe1, 0x01, 0x6e, 0xe0, 0xa1, 0xa8, 0x97, 0xcc, 0x5d, 0xdc, 0x87, 0xf2, + 0x88, 0x48, 0xe5, 0x32, 0x5f, 0x52, 0xa1, 0x5c, 0xe6, 0x39, 0x85, 0xaa, 0x55, 0x4f, 0xe1, 0xa2, + 0xd6, 0x76, 0x8c, 0xb2, 0xe3, 0xa1, 0xff, 0x00, 0x9c, 0xf1, 0x89, 0xef, 0xb9, 0x82, 0x5f, 0x49, + 0xa7, 0x68, 0x2c, 0xf2, 0x46, 0x83, 0xf9, 0x95, 0x44, 0x2e, 0xdc, 0x9e, 0x48, 0x2a, 0x5c, 0x8f, + 0x9e, 0x31, 0x9f, 0x7a, 0xee, 0x94, 0x08, 0x46, 0x4e, 0x47, 0x54, 0x3a, 0x25, 0x13, 0xd0, 0xa3, + 0xd5, 0x80, 0x8e, 0x24, 0x15, 0x7b, 0x81, 0xf1, 0x71, 0x64, 0xdb, 0xf6, 0x95, 0x98, 0xe1, 0x8d, + 0xc9, 0x35, 0x10, 0xea, 0x82, 0x2d, 0x67, 0x52, 0xd1, 0xcb, 0x98, 0xeb, 0xb2, 0x71, 0x7d, 0xff, + 0x95, 0xb3, 0x1a, 0xbb, 0x15, 0xaf, 0x15, 0xb9, 0xac, 0x45, 0xff, 0x86, 0xbc, 0xe0, 0x57, 0xee, + 0x80, 0x4f, 0x7c, 0xe5, 0x54, 0xaa, 0x56, 0x3d, 0x89, 0x73, 0x82, 0x5f, 0xb5, 0xb4, 0xac, 0x4b, + 0x50, 0x92, 0x29, 0x1d, 0x73, 0xe6, 0x2b, 0xe9, 0xd8, 0xd5, 0x64, 0x3d, 0x8f, 0x63, 0x1a, 0x54, + 0x07, 0x9b, 0xf9, 0xae, 0xa0, 0x92, 0x8a, 0x29, 0xf5, 0xdc, 0x01, 0xf7, 0x7d, 0x67, 0xcd, 0x14, + 0x6a, 0x99, 0xf9, 0x38, 0x54, 0xb7, 0xb8, 0xef, 0x6b, 0x86, 0x47, 0x7c, 0x70, 0x11, 0x11, 0xe4, + 0x20, 0x53, 0x8c, 0xaf, 0x61, 0x58, 0xaf, 0x88, 0x3a, 0xaf, 0x01, 0xeb, 0x86, 0x1e, 0xe3, 0xe5, + 0x9c, 0x12, 0xa1, 0x4e, 0x29, 0x51, 0xce, 0xba, 0x89, 0x78, 0x4d, 0x43, 0xfb, 0x7c, 0x70, 0xf1, + 0x4d, 0x04, 0xa0, 0xaf, 0xc1, 0x16, 0x94, 0x78, 0x2e, 0x39, 0x53, 0x54, 0xb8, 0x57, 0x82, 0x29, + 0xea, 0x6c, 0x98, 0x4d, 0x6f, 0x47, 0x9b, 0x62, 0x4a, 0xbc, 0x1d, 0x0d, 0x9f, 0x68, 0x14, 0x97, + 0xc5, 0x92, 0x8c, 0xaa, 0x50, 0xd8, 0xdb, 0xdb, 0xef, 0x29, 0x41, 0x14, 0x1d, 0xce, 0x9c, 0x4d, + 0xd3, 0x5d, 0x71, 0xd5, 0xd6, 0x6f, 0x16, 0x14, 0xe3, 0x11, 0xa3, 0x07, 0x90, 0x09, 0xba, 0xcf, + 0x5c, 0x0b, 0x85, 0xed, 0x52, 0x58, 0xf6, 0x7d, 0xa3, 0xc4, 0x21, 0xa8, 0x6f, 0x91, 0x78, 0x8f, + 0x31, 0xcf, 0x49, 0x98, 0x63, 0x94, 0x62, 0xda, 0x8e, 0x87, 0x9e, 0x40, 0x51, 0x69, 0x92, 0x94, + 0x4b, 0x46, 0x8c, 0x48, 0x27, 0x19, 0x36, 0xf0, 0xfc, 0xb2, 0xea, 0x1b, 0x74, 0x47, 0x83, 0xb8, + 0xa0, 0x16, 0x02, 0xfa, 0x1f, 0x14, 0xe6, 0xa4, 0x30, 0xcf, 0xdc, 0x1d, 0x49, 0x0c, 0x91, 0xaa, + 0xe3, 0x6d, 0x7d, 0x0f, 0x77, 0xfe, 0xb6, 0xf2, 0x90, 0x0d, 0xc9, 0x0b, 0x3a, 0x33, 0x47, 0xc8, + 0x63, 0xfd, 0x89, 0x1e, 0x41, 0x7a, 0x4a, 0x46, 0x13, 0x6a, 0xe2, 0x5c, 0x74, 0xf3, 0x2e, 0xf3, + 0xe7, 0x6b, 0x71, 0x60, 0xf1, 0x79, 0xe2, 0x89, 0xb5, 0xb5, 0x0b, 0x1b, 0xd7, 0x15, 0xdf, 0x35, + 0x8e, 0x37, 0xe2, 0x8e, 0xf3, 0x31, 0x1f, 0xcf, 0x53, 0xb9, 0xa4, 0x9d, 0xaa, 0xfd, 0x6a, 0x41, + 0x79, 0x99, 0x26, 0xf4, 0x11, 0x6c, 0xae, 0x12, 0xeb, 0x0e, 0x15, 0xf3, 0x42, 0xb7, 0x68, 0x99, + 0xc5, 0x67, 0x8a, 0x79, 0xe8, 0x33, 0x70, 0x5e, 0x59, 0xa2, 0xd8, 0x25, 0xe5, 0x13, 0x65, 0x36, + 0xb6, 0xf0, 0xe6, 0xf2, 0xaa, 0x7e, 0x00, 0xea, 0xa2, 0x0b, 0x0b, 0x56, 0xdf, 0xf9, 0x83, 0x0b, + 0xb3, 0x51, 0x40, 0x44, 0x0e, 0xaf, 0x85, 0x50, 0x5f, 0x23, 0x7a, 0x1f, 0x59, 0xfb, 0x25, 0x01, + 0xe5, 0xf0, 0x62, 0xc5, 0xf4, 0xe5, 0x84, 0x4a, 0x85, 0x3e, 0x80, 0xfc, 0x80, 0x8c, 0x46, 0x54, + 0xb8, 0x61, 0x88, 0x85, 0xed, 0x4a, 0x23, 0x18, 0x2f, 0x2d, 0xa3, 0xef, 0xec, 0xe1, 0x5c, 0x60, + 0xd1, 0xf1, 0xd0, 0x23, 0xc8, 0x46, 0x1d, 0x92, 0x98, 0xdb, 0xc6, 0x3b, 0x04, 0x47, 0x38, 0x7a, + 0x08, 0x69, 0xc3, 0x42, 0x58, 0x16, 0x6b, 0x11, 0x27, 0xfa, 0x2e, 0x32, 0xd7, 0x2c, 0x0e, 0x70, + 0xf4, 0x09, 0x84, 0xb5, 0xe1, 0xaa, 0xd9, 0x98, 0x9a, 0x62, 0x28, 0x6f, 0x6f, 0xac, 0x56, 0x51, + 0x7f, 0x36, 0xa6, 0x18, 0xd4, 0xfc, 0x5b, 0x17, 0xe9, 0x05, 0x9d, 0xc9, 0x31, 0x19, 0x50, 0xd7, + 0x0c, 0x26, 0x33, 0x40, 0xf2, 0xb8, 0x14, 0x69, 0x4d, 0xe5, 0xc7, 0x07, 0x4c, 0xf6, 0x26, 0x03, + 0xe6, 0x79, 0x2a, 0x97, 0xb6, 0x33, 0xb5, 0x9f, 0x2c, 0xa8, 0xcc, 0x33, 0x25, 0xc7, 0xdc, 0x97, + 0x7a, 0xc7, 0x34, 0x15, 0x82, 0x8b, 0x95, 0x34, 0xe1, 0xc3, 0x56, 0x5b, 0xab, 0x71, 0x80, 0xbe, + 0x49, 0x8e, 0x1e, 0x43, 0x46, 0x50, 0x39, 0x19, 0xa9, 0x30, 0x49, 0x28, 0x3e, 0x86, 0xb0, 0x41, + 0x70, 0x68, 0x51, 0xfb, 0x23, 0x01, 0xeb, 0x61, 0x44, 0xbb, 0x44, 0x0d, 0xce, 0xdf, 0x3b, 0x81, + 0xff, 0x87, 0xac, 0x8e, 0x86, 0x51, 0x5d, 0x50, 0xc9, 0xeb, 0x29, 0x8c, 0x2c, 0xde, 0x81, 0x44, + 0x22, 0x97, 0xde, 0x2b, 0xe9, 0xe0, 0xbd, 0x42, 0x64, 0xfc, 0xbd, 0xf2, 0x9e, 0xb8, 0xae, 0xfd, + 0x6c, 0xc1, 0xc6, 0x72, 0x4e, 0xdf, 0x1b, 0xd5, 0x1f, 0x42, 0x36, 0x20, 0x32, 0xca, 0xe6, 0xed, + 0x30, 0xb6, 0x80, 0xe6, 0x13, 0xa6, 0xce, 0x03, 0xd7, 0x91, 0x99, 0x6e, 0xd6, 0x8d, 0x9e, 0x12, + 0x94, 0x5c, 0xbe, 0x53, 0xcb, 0xce, 0xfb, 0x30, 0xf1, 0x66, 0x7d, 0x98, 0x7c, 0xeb, 0x3e, 0x4c, + 0xbd, 0x86, 0x9b, 0xf4, 0x8d, 0x1e, 0x7a, 0xb1, 0xdc, 0x66, 0xfe, 0x39, 0xb7, 0xb5, 0x16, 0x6c, + 0xae, 0x24, 0x2a, 0xa4, 0x71, 0xd1, 0x5f, 0xd6, 0x6b, 0xfb, 0xeb, 0x07, 0xb8, 0x83, 0xa9, 0xe4, + 0xa3, 0x29, 0x8d, 0x55, 0xde, 0xdb, 0xa5, 0x1c, 0x41, 0xca, 0x53, 0xe1, 0xd4, 0xcc, 0x63, 0xf3, + 0x5d, 0xbb, 0x0b, 0x5b, 0xd7, 0xb9, 0x0f, 0x02, 0xad, 0xfd, 0x6e, 0x41, 0xf9, 0x38, 0x38, 0xc3, + 0xdb, 0x6d, 0xb9, 0x42, 0x5e, 0xe2, 0x86, 0xe4, 0x3d, 0x84, 0xf4, 0xd4, 0x0c, 0xa7, 0xe8, 0x92, + 0x8e, 0xfd, 0x0f, 0x39, 0xd6, 0x33, 0x03, 0x07, 0xb8, 0xce, 0xe4, 0x19, 0x1b, 0x29, 0x2a, 0x0c, + 0xbb, 0x3a, 0x93, 0x31, 0xcb, 0xa7, 0x06, 0xc1, 0xa1, 0x45, 0xed, 0x4b, 0xa8, 0xcc, 0xcf, 0xb2, + 0x20, 0x82, 0x4e, 0xa9, 0x7e, 0xa4, 0x59, 0xa6, 0xf8, 0x97, 0x96, 0x1f, 0xb7, 0x35, 0x84, 0x43, + 0x8b, 0xc7, 0x7b, 0x50, 0x59, 0x79, 0xc1, 0xa3, 0x0a, 0x14, 0x8e, 0x5e, 0xf4, 0x0e, 0xdb, 0xad, + 0xce, 0xd3, 0x4e, 0x7b, 0xcf, 0xbe, 0x85, 0x00, 0x32, 0xbd, 0xce, 0x8b, 0x67, 0xfb, 0x6d, 0xdb, + 0x42, 0x79, 0x48, 0x1f, 0x1c, 0xed, 0xf7, 0x3b, 0x76, 0x42, 0x7f, 0xf6, 0x4f, 0xba, 0x87, 0x2d, + 0x3b, 0xf9, 0xf8, 0x0b, 0x28, 0xb4, 0xcc, 0xff, 0x90, 0xae, 0xf0, 0xa8, 0xd0, 0x0b, 0x5e, 0x74, + 0xf1, 0xc1, 0xce, 0xbe, 0x7d, 0x0b, 0x65, 0x21, 0x79, 0x88, 0xf5, 0xca, 0x1c, 0xa4, 0x0e, 0xbb, + 0xbd, 0xbe, 0x9d, 0x40, 0x65, 0x80, 0x9d, 0xa3, 0x7e, 0xb7, 0xd5, 0x3d, 0x38, 0xe8, 0xf4, 0xed, + 0xe4, 0xee, 0xa7, 0x50, 0x61, 0xbc, 0x31, 0x65, 0x8a, 0x4a, 0x19, 0xfc, 0xcd, 0xfa, 0xee, 0x5e, + 0x28, 0x31, 0xde, 0x0c, 0xbe, 0x9a, 0x43, 0xde, 0x9c, 0xaa, 0xa6, 0x41, 0x9b, 0x41, 0x69, 0x9e, + 0x66, 0x8c, 0xf4, 0xf1, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x70, 0xa7, 0x77, 0x23, 0xe6, 0x0d, + 0x00, 0x00, } From ad264f509856ba135e64e304e709a3499eca16e3 Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Sun, 15 Nov 2020 16:12:43 +0200 Subject: [PATCH 3/5] session now knows the new ddl_strategy variable Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- go/mysql/endtoend/client_test.go | 17 +++++++++++++++++ go/vt/vtgate/executor.go | 2 ++ go/vt/vtgate/executor_select_test.go | 5 ++++- go/vt/vtgate/safe_session.go | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/go/mysql/endtoend/client_test.go b/go/mysql/endtoend/client_test.go index c19f302b195..fbaaddbc5b4 100644 --- a/go/mysql/endtoend/client_test.go +++ b/go/mysql/endtoend/client_test.go @@ -339,3 +339,20 @@ func TestSessionTrackGTIDs(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, qr.SessionStateChanges) } + +func TestDDLStrategy(t *testing.T) { + ctx := context.Background() + params := connParams + params.Flags |= mysql.CapabilityClientSessionTrack + conn, err := mysql.Connect(ctx, ¶ms) + require.NoError(t, err) + + _, err = conn.ExecuteFetch(`set session ddl_strategy='gh-ost'`, 1000, false) + require.NoError(t, err) + _, err = conn.ExecuteFetch(`set session ddl_strategy='pot-osc'`, 1000, false) + require.NoError(t, err) + _, err = conn.ExecuteFetch(`set session ddl_strategy=''`, 1000, false) + require.NoError(t, err) + _, err = conn.ExecuteFetch(`set session ddl_strategy='other'`, 1000, false) + require.Error(t, err) +} diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 736ff01adc4..fa82862ea9f 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -290,6 +290,8 @@ func (e *Executor) addNeededBindVars(bindVarNeeds *sqlparser.BindVarNeeds, bindV v = options.GetWorkload().String() }) bindVars[key] = sqltypes.StringBindVariable(v) + case sysvars.DDLStrategy.Name: + bindVars[key] = sqltypes.StringBindVariable(session.DDLStrategy) case sysvars.ReadAfterWriteGTID.Name: var v string ifReadAfterWriteExist(session, func(raw *vtgatepb.ReadAfterWrite) { diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index c5b4c0c071d..bcf200b4322 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -328,7 +328,8 @@ func TestSelectSystemVariables(t *testing.T) { sql := "select @@autocommit, @@client_found_rows, @@skip_query_plan_cache, " + "@@sql_select_limit, @@transaction_mode, @@workload, @@read_after_write_gtid, " + - "@@read_after_write_timeout, @@session_track_gtids" + "@@read_after_write_timeout, @@session_track_gtids" + + "@@ddl_strategy" result, err := executorExec(executor, sql, map[string]*querypb.BindVariable{}) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ @@ -341,6 +342,7 @@ func TestSelectSystemVariables(t *testing.T) { {Name: "@@read_after_write_gtid", Type: sqltypes.VarBinary}, {Name: "@@read_after_write_timeout", Type: sqltypes.Float64}, {Name: "@@session_track_gtids", Type: sqltypes.VarBinary}, + {Name: "@@ddl_strategy", Type: sqltypes.VarBinary}, }, RowsAffected: 1, Rows: [][]sqltypes.Value{{ @@ -355,6 +357,7 @@ func TestSelectSystemVariables(t *testing.T) { sqltypes.NewVarBinary("a fine gtid"), sqltypes.NewFloat64(13), sqltypes.NewVarBinary("own_gtid"), + sqltypes.NewVarBinary(""), }}, } require.NoError(t, err) diff --git a/go/vt/vtgate/safe_session.go b/go/vt/vtgate/safe_session.go index 7f76725c98f..a5ef0ebb032 100644 --- a/go/vt/vtgate/safe_session.go +++ b/go/vt/vtgate/safe_session.go @@ -458,7 +458,7 @@ func (session *SafeSession) ResetShard(tabletAlias *topodatapb.TabletAlias) erro func (session *SafeSession) SetDDLStrategy(strategy sqlparser.DDLStrategy) { session.mu.Lock() defer session.mu.Unlock() - // session.DDLStrategy = string(strategy) + session.DDLStrategy = string(strategy) } // SetReadAfterWriteGTID set the ReadAfterWriteGtid setting. From c6fb4e0a1bc405288f622529ada4b1b0bced76cc Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Sun, 15 Nov 2020 19:51:01 +0200 Subject: [PATCH 4/5] fix unit test Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- go/vt/vtgate/executor_select_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index bcf200b4322..95a2357d671 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -328,8 +328,8 @@ func TestSelectSystemVariables(t *testing.T) { sql := "select @@autocommit, @@client_found_rows, @@skip_query_plan_cache, " + "@@sql_select_limit, @@transaction_mode, @@workload, @@read_after_write_gtid, " + - "@@read_after_write_timeout, @@session_track_gtids" + - "@@ddl_strategy" + "@@read_after_write_timeout, @@session_track_gtids, @@ddl_strategy" + result, err := executorExec(executor, sql, map[string]*querypb.BindVariable{}) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ From b1dfc291a2fdf1b9af4cd5f6d9a371a55258a5a2 Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Sun, 15 Nov 2020 19:58:05 +0200 Subject: [PATCH 5/5] removed TestDDLStrategy. It was misplaced Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- go/mysql/endtoend/client_test.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/go/mysql/endtoend/client_test.go b/go/mysql/endtoend/client_test.go index fbaaddbc5b4..c19f302b195 100644 --- a/go/mysql/endtoend/client_test.go +++ b/go/mysql/endtoend/client_test.go @@ -339,20 +339,3 @@ func TestSessionTrackGTIDs(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, qr.SessionStateChanges) } - -func TestDDLStrategy(t *testing.T) { - ctx := context.Background() - params := connParams - params.Flags |= mysql.CapabilityClientSessionTrack - conn, err := mysql.Connect(ctx, ¶ms) - require.NoError(t, err) - - _, err = conn.ExecuteFetch(`set session ddl_strategy='gh-ost'`, 1000, false) - require.NoError(t, err) - _, err = conn.ExecuteFetch(`set session ddl_strategy='pot-osc'`, 1000, false) - require.NoError(t, err) - _, err = conn.ExecuteFetch(`set session ddl_strategy=''`, 1000, false) - require.NoError(t, err) - _, err = conn.ExecuteFetch(`set session ddl_strategy='other'`, 1000, false) - require.Error(t, err) -}