From 1fca5bdc70b42a319c483cdf2bdd68d18f31c865 Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Mon, 20 Jul 2026 10:57:16 +0800 Subject: [PATCH 01/10] fix: preserve prepared binary params across retries --- pkg/container/vector/vector.go | 30 + pkg/container/vector/vector_test.go | 18 + pkg/frontend/back_exec.go | 1 + pkg/frontend/compiler_context.go | 42 +- pkg/frontend/computation_wrapper.go | 53 +- pkg/frontend/computation_wrapper_test.go | 157 +++- pkg/frontend/mysql_cmd_executor.go | 7 +- pkg/frontend/session.go | 6 +- pkg/frontend/util.go | 8 +- pkg/frontend/variables.go | 1 + pkg/pb/pipeline/pipeline.pb.go | 883 ++++++++++-------- pkg/sql/colexec/evalExpression.go | 16 + pkg/sql/colexec/evalExpression_test.go | 60 ++ pkg/sql/compile/compile2.go | 9 +- pkg/sql/compile/compile_test.go | 19 + pkg/sql/compile/remoterunServer.go | 37 +- pkg/sql/compile/remoterunServer_test.go | 58 +- pkg/sql/plan/deepcopy.go | 3 +- pkg/sql/plan/utils.go | 24 +- pkg/sql/plan/utils_test.go | 57 ++ pkg/vm/process/process.go | 52 ++ pkg/vm/process/process2.go | 1 + pkg/vm/process/process2_test.go | 62 ++ pkg/vm/process/process_codec.go | 11 +- pkg/vm/process/process_codec_test.go | 12 +- pkg/vm/process/types.go | 41 +- proto/pipeline.proto | 1 + .../cases/prepare/prepare_binary_param.result | 50 + .../cases/prepare/prepare_binary_param.sql | 51 + 29 files changed, 1302 insertions(+), 468 deletions(-) create mode 100644 test/distributed/cases/prepare/prepare_binary_param.result create mode 100644 test/distributed/cases/prepare/prepare_binary_param.sql diff --git a/pkg/container/vector/vector.go b/pkg/container/vector/vector.go index e4aa8bd7bf517..f97cd33688cc5 100644 --- a/pkg/container/vector/vector.go +++ b/pkg/container/vector/vector.go @@ -502,6 +502,36 @@ func NewVecWithData( return vec } +// NewVecWithDataCopy copies external backing data into allocations owned by mp. +func NewVecWithDataCopy( + typ types.Type, + length int, + data []byte, + area []byte, + mp *mpool.MPool, +) (*Vector, error) { + vec := NewVec(typ) + vec.length = length + var err error + if len(data) > 0 { + vec.data, err = mp.Alloc(len(data), false) + if err != nil { + vec.Free(mp) + return nil, err + } + copy(vec.data, data) + } + if len(area) > 0 { + vec.area, err = mp.Alloc(len(area), false) + if err != nil { + vec.Free(mp) + return nil, err + } + copy(vec.area, area) + } + return vec, nil +} + func NewConstNull(typ types.Type, length int, mp *mpool.MPool) *Vector { vec := NewVecFromReuse() vec.typ = typ diff --git a/pkg/container/vector/vector_test.go b/pkg/container/vector/vector_test.go index 968df6b2c05e2..9db72e2cb6197 100644 --- a/pkg/container/vector/vector_test.go +++ b/pkg/container/vector/vector_test.go @@ -441,6 +441,24 @@ func TestDup(t *testing.T) { require.Equal(t, int64(0), mp.CurrNB()) } +func TestNewVecWithDataCopyOwnsBackingData(t *testing.T) { + mp := mpool.MustNewZero() + data := []byte("external-data") + area := []byte("external-area") + vec, err := NewVecWithDataCopy(types.T_text.ToType(), 1, data, area, mp) + require.NoError(t, err) + require.Equal(t, data, vec.GetData()) + require.Equal(t, area, vec.GetArea()) + + data[0] = 'X' + area[0] = 'Y' + require.Equal(t, byte('e'), vec.GetData()[0]) + require.Equal(t, byte('e'), vec.GetArea()[0]) + require.NotPanics(t, func() { vec.Free(mp) }) + require.Nil(t, vec.GetData()) + require.Nil(t, vec.GetArea()) +} + func TestShrink(t *testing.T) { mp := mpool.MustNewZero() { // Array Float32 diff --git a/pkg/frontend/back_exec.go b/pkg/frontend/back_exec.go index 2028a71eb4fac..8059be8637191 100644 --- a/pkg/frontend/back_exec.go +++ b/pkg/frontend/back_exec.go @@ -380,6 +380,7 @@ func doComQueryInBack( } proc.SetStmtProfile(&backSes.stmtProfile) proc.SetResolveVariableFunc(backSes.txnCompileCtx.ResolveVariable) + proc.SetResolveVariableIsBinFunc(backSes.txnCompileCtx.ResolveVariableIsBin) // Frontend back-exec — session-bound resolver. backSession is a // frontend session without a client connection (NOT a system // background task); all callers go through ses.GetBackgroundExec(...) diff --git a/pkg/frontend/compiler_context.go b/pkg/frontend/compiler_context.go index d3cdf8298cf5e..4254bc677f423 100644 --- a/pkg/frontend/compiler_context.go +++ b/pkg/frontend/compiler_context.go @@ -765,14 +765,8 @@ func (tcc *TxnCompilerContext) ResolveVariable(varName string, isSystemVar, isGl ctx := tcc.execCtx.reqCtx - if ctx.Value(defines.InSp{}) != nil && ctx.Value(defines.InSp{}).(bool) { - tmpScope := ctx.Value(defines.VarScopeKey{}).(*[]map[string]interface{}) - for i := len(*tmpScope) - 1; i >= 0; i-- { - curScope := (*tmpScope)[i] - if val, ok := curScope[strings.ToLower(varName)]; ok { - return val, nil - } - } + if val, ok := resolveStoredProcedureVariable(ctx, varName); ok { + return val, nil } if isSystemVar { @@ -797,6 +791,38 @@ func (tcc *TxnCompilerContext) ResolveVariable(varName string, isSystemVar, isGl return } +func (tcc *TxnCompilerContext) ResolveVariableIsBin(varName string, isSystemVar, _ bool) (bool, error) { + if _, ok := resolveStoredProcedureVariable(tcc.execCtx.reqCtx, varName); ok { + return false, nil + } + if isSystemVar { + return false, nil + } + udVar, err := tcc.GetSession().GetUserDefinedVar(varName) + if err != nil { + return false, err + } + return udVar.IsBin, nil +} + +func resolveStoredProcedureVariable(ctx context.Context, varName string) (interface{}, bool) { + inSp, _ := ctx.Value(defines.InSp{}).(bool) + if !inSp { + return nil, false + } + tmpScope, ok := ctx.Value(defines.VarScopeKey{}).(*[]map[string]interface{}) + if !ok { + return nil, false + } + name := strings.ToLower(varName) + for i := len(*tmpScope) - 1; i >= 0; i-- { + if val, ok := (*tmpScope)[i][name]; ok { + return val, true + } + } + return nil, false +} + func (tcc *TxnCompilerContext) ResolveAccountIds(accountNames []string) (accountIds []uint32, err error) { var sql string var erArray []ExecResult diff --git a/pkg/frontend/computation_wrapper.go b/pkg/frontend/computation_wrapper.go index 8437de20903c3..39c9b21d6e4e1 100644 --- a/pkg/frontend/computation_wrapper.go +++ b/pkg/frontend/computation_wrapper.go @@ -602,21 +602,11 @@ func initExecuteStmtParam(execCtx *ExecCtx, ses *Session, cwft *TxnComputationWr if len(execPlan.Args) != numParams { return nil, nil, nil, originSQL, moerr.NewInvalidInput(reqCtx, "Incorrect arguments to EXECUTE") } - params := vector.NewVec(types.T_text.ToType()) - paramVals := make([]any, numParams) - for i, arg := range execPlan.Args { - exprImpl := arg.Expr.(*plan.Expr_V) - param, err := cwft.proc.GetResolveVariableFunc()(exprImpl.V.Name, exprImpl.V.System, exprImpl.V.Global) - if err != nil { - return nil, nil, nil, originSQL, err - } - err = util.AppendAnyToStringVector(cwft.proc, param, params) - if err != nil { - return nil, nil, nil, originSQL, err - } - paramVals[i] = param + params, paramVals, paramIsBin, err := buildExecuteUserParams(cwft.proc, execPlan.Args) + if err != nil { + return nil, nil, nil, originSQL, err } - cwft.proc.SetPrepareParams(params) + cwft.proc.SetOwnedPrepareParamsWithIsBin(params, paramIsBin) cwft.paramVals = paramVals } else { if numParams > 0 { @@ -626,6 +616,41 @@ func initExecuteStmtParam(execCtx *ExecCtx, ses *Session, cwft *TxnComputationWr return prepareStmt.compile, preparePlan.Plan, prepareStmt.PrepareStmt, originSQL, nil } +func buildExecuteUserParams( + proc *process.Process, + args []*plan.Expr, +) (params *vector.Vector, paramVals []any, paramIsBin []bool, err error) { + params = vector.NewVec(types.T_text.ToType()) + defer func() { + if err != nil { + params.Free(proc.Mp()) + } + }() + paramVals = make([]any, len(args)) + paramIsBin = make([]bool, len(args)) + for i, arg := range args { + exprImpl := arg.Expr.(*plan.Expr_V) + var param any + param, err = proc.GetResolveVariableFunc()(exprImpl.V.Name, exprImpl.V.System, exprImpl.V.Global) + if err != nil { + return + } + err = util.AppendAnyToStringVector(proc, param, params) + if err != nil { + return + } + resolveIsBin := proc.GetResolveVariableIsBinFunc() + if resolveIsBin != nil { + paramIsBin[i], err = resolveIsBin(exprImpl.V.Name, exprImpl.V.System, exprImpl.V.Global) + if err != nil { + return + } + } + paramVals[i] = plan2.ParamValue{Value: param, IsBin: paramIsBin[i]} + } + return +} + func shouldCachePrepareCompile(p *plan.Plan) bool { if p == nil { return true diff --git a/pkg/frontend/computation_wrapper_test.go b/pkg/frontend/computation_wrapper_test.go index 9c365f842f15f..683169f10a49c 100644 --- a/pkg/frontend/computation_wrapper_test.go +++ b/pkg/frontend/computation_wrapper_test.go @@ -21,6 +21,9 @@ import ( "time" "github.com/matrixorigin/matrixone/pkg/config" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/defines" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/sql/compile" "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" @@ -104,6 +107,10 @@ func TestTxnComputationWrapper_Run_Error(t *testing.T) { // computation wrapper that executes it through the binary protocol, so tests // can drive cw.Compile through initExecuteStmtParam. func newPreparedExecuteEnv(t *testing.T, stmtID uint32) (*Session, *PrepareStmt, *TxnComputationWrapper, *ExecCtx) { + return newPreparedExecuteEnvForSQL(t, stmtID, "select 1") +} + +func newPreparedExecuteEnvForSQL(t *testing.T, stmtID uint32, sql string) (*Session, *PrepareStmt, *TxnComputationWrapper, *ExecCtx) { ctx := statistic.ContextWithStatsInfo(context.Background(), statistic.NewStatsInfo()) setPu("", config.NewParameterUnit(&config.FrontendParameters{}, nil, nil, nil)) @@ -113,7 +120,7 @@ func newPreparedExecuteEnv(t *testing.T, stmtID uint32) (*Session, *PrepareStmt, proc.Base.SessionInfo.StorageEngine = &disttae.Engine{} stmtName := getPrepareStmtName(stmtID) - prepareString := tree.NewPrepareString(tree.Identifier(stmtName), "select 1") + prepareString := tree.NewPrepareString(tree.Identifier(stmtName), sql) stmts, err := mysql.Parse(ctx, prepareString.Sql, 1) require.NoError(t, err) preparePlan, err := buildPlan(ctx, nil, plan2.NewEmptyCompilerContext(), prepareString) @@ -132,14 +139,162 @@ func newPreparedExecuteEnv(t *testing.T, stmtID uint32) (*Session, *PrepareStmt, cw.plan = preparePlan.GetDcl().GetPrepare().Plan execCtx := &ExecCtx{ reqCtx: ctx, + ses: ses, + proc: proc, input: &UserInput{ stmtName: stmtName, isBinaryProtExecute: true, }, } + ses.txnCompileCtx.execCtx = execCtx + proc.SetResolveVariableFunc(ses.txnCompileCtx.ResolveVariable) + proc.SetResolveVariableIsBinFunc(ses.txnCompileCtx.ResolveVariableIsBin) return ses, prepareStmt, cw, execCtx } +func TestInitExecuteStmtParamPreservesBinaryFlagPerUserVariable(t *testing.T) { + ses, prepareStmt, cw, execCtx := newPreparedExecuteEnvForSQL(t, 102, "select ?, ?") + defer prepareStmt.Close() + + require.NoError(t, ses.setUserDefinedVar("binary_param", "AB\x00\x00", "", true)) + require.NoError(t, ses.SetUserDefinedVar("text_param", "text", "")) + isBin, err := ses.txnCompileCtx.ResolveVariableIsBin("binary_param", false, false) + require.NoError(t, err) + require.True(t, isBin) + isBin, err = ses.txnCompileCtx.ResolveVariableIsBin("text_param", false, false) + require.NoError(t, err) + require.False(t, isBin) + isBin, err = ses.txnCompileCtx.ResolveVariableIsBin("system_var", true, false) + require.NoError(t, err) + require.False(t, isBin) + _, err = ses.txnCompileCtx.ResolveVariableIsBin("missing", false, false) + require.Error(t, err) + cw.proc.SetResolveVariableFunc(func(name string, _, _ bool) (interface{}, error) { + variable, err := ses.GetUserDefinedVar(name) + if err != nil { + return nil, err + } + return variable.Value, nil + }) + execPlan := &plan.Execute{ + Name: prepareStmt.Name, + Args: []*plan.Expr{ + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "binary_param"}}}, + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "text_param"}}}, + }, + } + + _, _, _, _, err = initExecuteStmtParam(execCtx, ses, cw, execPlan, "") + require.NoError(t, err) + require.True(t, cw.proc.GetPrepareParamIsBin(0)) + require.False(t, cw.proc.GetPrepareParamIsBin(1)) + require.Equal(t, plan2.ParamValue{Value: "AB\x00\x00", IsBin: true}, cw.paramVals[0]) + require.Equal(t, plan2.ParamValue{Value: "text", IsBin: false}, cw.paramVals[1]) + + params := cw.proc.GetPrepareParams() + require.NoError(t, ses.SetUserDefinedVar("binary_param", "now-text", "")) + _, _, _, _, err = initExecuteStmtParam(execCtx, ses, cw, execPlan, "") + require.NoError(t, err) + require.Zero(t, params.Length(), "the previous owned params must be released on successful replacement") + require.Nil(t, params.GetData()) + require.False(t, cw.proc.GetPrepareParamIsBin(0)) + require.Equal(t, "now-text", cw.proc.GetPrepareParams().GetStringAt(0)) + + current := cw.proc.GetPrepareParams() + cw.proc.SetPrepareParams(vector.NewVec(types.T_text.ToType())) + require.Zero(t, current.Length()) + require.Nil(t, current.GetData()) + require.False(t, cw.proc.GetPrepareParamIsBin(0), "binary metadata must not leak into the next execution") + cw.proc.GetPrepareParams().Free(cw.proc.Mp()) + cw.proc.SetPrepareParams(nil) +} + +func TestInitExecuteStmtParamFreesParamsOnResolveError(t *testing.T) { + ses, prepareStmt, cw, _ := newPreparedExecuteEnvForSQL(t, 103, "select ?, ?") + defer prepareStmt.Close() + require.NoError(t, ses.SetUserDefinedVar("first", "allocated", "")) + cw.proc.SetResolveVariableFunc(func(name string, _, _ bool) (interface{}, error) { + if name == "second" { + return nil, assert.AnError + } + variable, err := ses.GetUserDefinedVar(name) + if err != nil { + return nil, err + } + return variable.Value, nil + }) + execPlan := &plan.Execute{ + Name: prepareStmt.Name, + Args: []*plan.Expr{ + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "first"}}}, + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "second"}}}, + }, + } + params, _, _, err := buildExecuteUserParams(cw.proc, execPlan.Args) + require.ErrorIs(t, err, assert.AnError) + require.Zero(t, params.Length()) + require.Nil(t, params.GetData()) + require.Nil(t, params.GetArea()) +} + +func TestResolveVariableIsBinHonorsStoredProcedureScope(t *testing.T) { + ses, prepareStmt, _, execCtx := newPreparedExecuteEnv(t, 104) + defer prepareStmt.Close() + require.NoError(t, ses.setUserDefinedVar("v1", "session-binary", "", true)) + require.NoError(t, ses.setUserDefinedVar("session_only", "session-binary", "", true)) + scopes := []map[string]interface{}{ + {"v1": int64(10)}, + {"v1": int64(20), "inner": int64(30)}, + } + execCtx.reqCtx = context.WithValue(execCtx.reqCtx, defines.VarScopeKey{}, &scopes) + execCtx.reqCtx = context.WithValue(execCtx.reqCtx, defines.InSp{}, true) + + value, err := ses.txnCompileCtx.ResolveVariable("V1", false, false) + require.NoError(t, err) + require.Equal(t, int64(20), value) + isBin, err := ses.txnCompileCtx.ResolveVariableIsBin("V1", false, false) + require.NoError(t, err) + require.False(t, isBin) + + value, err = ses.txnCompileCtx.ResolveVariable("session_only", false, false) + require.NoError(t, err) + require.Equal(t, "session-binary", value) + isBin, err = ses.txnCompileCtx.ResolveVariableIsBin("session_only", false, false) + require.NoError(t, err) + require.True(t, isBin) +} + +func TestBuildExecuteUserParamsHonorsStoredProcedureScope(t *testing.T) { + ses, prepareStmt, cw, execCtx := newPreparedExecuteEnv(t, 105) + defer prepareStmt.Close() + require.NoError(t, ses.setUserDefinedVar("local_shadow", "session-binary", "", true)) + require.NoError(t, ses.setUserDefinedVar("session_only", "session-binary", "", true)) + scopes := []map[string]interface{}{ + {"local_only": int64(10), "local_shadow": int64(20)}, + } + execCtx.reqCtx = context.WithValue(execCtx.reqCtx, defines.VarScopeKey{}, &scopes) + execCtx.reqCtx = context.WithValue(execCtx.reqCtx, defines.InSp{}, true) + + args := []*plan.Expr{ + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "local_only"}}}, + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "local_shadow"}}}, + {Expr: &plan.Expr_V{V: &plan.VarRef{Name: "session_only"}}}, + } + params, paramVals, paramIsBin, err := buildExecuteUserParams(cw.proc, args) + require.NoError(t, err) + defer params.Free(cw.proc.Mp()) + + require.Equal(t, []bool{false, false, true}, paramIsBin) + require.Equal(t, []any{ + plan2.ParamValue{Value: int64(10), IsBin: false}, + plan2.ParamValue{Value: int64(20), IsBin: false}, + plan2.ParamValue{Value: "session-binary", IsBin: true}, + }, paramVals) + require.Equal(t, "10", params.GetStringAt(0)) + require.Equal(t, "20", params.GetStringAt(1)) + require.Equal(t, "session-binary", params.GetStringAt(2)) +} + // A nil cached compile means the statement was rejected for prepare-time // compile (e.g. AP query hitting ErrCantCompileForPrepare). Execute must not // retry that doomed compile on every run; the cache stays nil and the regular diff --git a/pkg/frontend/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index 3e553ed9fbe27..ed78b89043a4e 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -829,6 +829,7 @@ func handleCmdFieldList(ses FeSession, execCtx *ExecCtx, icfl *InternalCmdFieldL func doSetVar(ses *Session, execCtx *ExecCtx, sv *tree.SetVar, sql string) error { var err error = nil var ok bool + var userVarIsBin bool setVarFunc := func(system, global bool, name string, value interface{}, sql string) error { var oldValueRaw interface{} if system { @@ -865,7 +866,7 @@ func doSetVar(ses *Session, execCtx *ExecCtx, sv *tree.SetVar, sql string) error } } } else { - err = ses.SetUserDefinedVar(name, value, sql) + err = ses.setUserDefinedVar(name, value, sql, userVarIsBin) if err != nil { return err } @@ -876,8 +877,9 @@ func doSetVar(ses *Session, execCtx *ExecCtx, sv *tree.SetVar, sql string) error for _, assign := range sv.Assignments { name := assign.Name var value interface{} + userVarIsBin = false - value, err = getExprValue(assign.Value, ses, execCtx) + value, err = getExprValue(assign.Value, ses, execCtx, &userVarIsBin) if err != nil { return err } @@ -3943,6 +3945,7 @@ func doComQuery(ses *Session, execCtx *ExecCtx, input *UserInput) (retErr error) // ROW_COUNT() builtin can read it. proc.SetAffectedRows(ses.GetLastAffectedRows()) proc.SetResolveVariableFunc(ses.txnCompileCtx.ResolveVariable) + proc.SetResolveVariableIsBinFunc(ses.txnCompileCtx.ResolveVariableIsBin) // Frontend client SQL — session-bound resolver. Procs constructed // via pkg/sql/compile/sql_executor.go's NewTopProcess inherit // IsFrontend from opts.IsFrontend() (default false → background); diff --git a/pkg/frontend/session.go b/pkg/frontend/session.go index 1a280db64973a..b0cd23de30747 100644 --- a/pkg/frontend/session.go +++ b/pkg/frontend/session.go @@ -334,9 +334,13 @@ func (ses *Session) getNextProcessId() string { // SetUserDefinedVar sets the user defined variable to the value in session func (ses *Session) SetUserDefinedVar(name string, value interface{}, sql string) error { + return ses.setUserDefinedVar(name, value, sql, false) +} + +func (ses *Session) setUserDefinedVar(name string, value interface{}, sql string, isBin bool) error { ses.mu.Lock() defer ses.mu.Unlock() - ses.userDefinedVars[strings.ToLower(name)] = &UserDefinedVar{Value: value, Sql: sql} + ses.userDefinedVars[strings.ToLower(name)] = &UserDefinedVar{Value: value, Sql: sql, IsBin: isBin} return nil } diff --git a/pkg/frontend/util.go b/pkg/frontend/util.go index 998bfa1d42be7..25914dbd8fa0e 100644 --- a/pkg/frontend/util.go +++ b/pkg/frontend/util.go @@ -183,7 +183,7 @@ func WildcardMatch(pattern, target string) bool { } // getExprValue executes the expression and returns the value. -func getExprValue(e tree.Expr, ses *Session, execCtx *ExecCtx) (interface{}, error) { +func getExprValue(e tree.Expr, ses *Session, execCtx *ExecCtx, isBin ...*bool) (interface{}, error) { /* CORNER CASE: SET character_set_results = utf8; // e = tree.UnresolvedName{'utf8'}. @@ -193,6 +193,9 @@ func getExprValue(e tree.Expr, ses *Session, execCtx *ExecCtx) (interface{}, err switch v := e.(type) { case *tree.UnresolvedName: // set @a = on, type of a is bool. + if len(isBin) > 0 { + *isBin[0] = false + } return v.ColName(), nil } @@ -280,6 +283,9 @@ func getExprValue(e tree.Expr, ses *Session, execCtx *ExecCtx) (interface{}, err } } + if len(isBin) > 0 { + *isBin[0] = resultVec.GetIsBin() + } return getValueFromVector(execCtx.reqCtx, resultVec, ses, planExpr) } diff --git a/pkg/frontend/variables.go b/pkg/frontend/variables.go index 5e548ffacc974..3481403e8d8dc 100644 --- a/pkg/frontend/variables.go +++ b/pkg/frontend/variables.go @@ -4195,6 +4195,7 @@ func valueIsBoolTrue(value interface{}) (bool, error) { type UserDefinedVar struct { Value interface{} Sql string + IsBin bool } func autocommitValue(ses FeSession) (bool, error) { diff --git a/pkg/pb/pipeline/pipeline.pb.go b/pkg/pb/pipeline/pipeline.pb.go index 1656a8724996d..cb837a4193b75 100644 --- a/pkg/pb/pipeline/pipeline.pb.go +++ b/pkg/pb/pipeline/pipeline.pb.go @@ -4641,6 +4641,7 @@ type PrepareParamInfo struct { Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Area []byte `protobuf:"bytes,3,opt,name=area,proto3" json:"area,omitempty"` Nulls []bool `protobuf:"varint,4,rep,packed,name=nulls,proto3" json:"nulls,omitempty"` + IsBin []bool `protobuf:"varint,5,rep,packed,name=is_bin,json=isBin,proto3" json:"is_bin,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -4707,6 +4708,13 @@ func (m *PrepareParamInfo) GetNulls() []bool { return nil } +func (m *PrepareParamInfo) GetIsBin() []bool { + if m != nil { + return m.IsBin + } + return nil +} + type ProcessInfo struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Sql string `protobuf:"bytes,2,opt,name=sql,proto3" json:"sql,omitempty"` @@ -5423,400 +5431,401 @@ func init() { func init() { proto.RegisterFile("pipeline.proto", fileDescriptor_7ac67a7adf3df9c7) } var fileDescriptor_7ac67a7adf3df9c7 = []byte{ - // 6280 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7c, 0x4b, 0x6f, 0x1c, 0x49, - 0x72, 0xf0, 0xf4, 0xbb, 0x3a, 0xfa, 0xc1, 0x66, 0xea, 0xd5, 0x23, 0xcd, 0x83, 0x53, 0x2b, 0x69, - 0xb8, 0x9a, 0x19, 0x6a, 0x86, 0x33, 0xda, 0x9d, 0x7d, 0x2f, 0x45, 0x4a, 0x3b, 0xdc, 0x25, 0x29, - 0x7e, 0x45, 0xea, 0x1b, 0x60, 0x0e, 0x5f, 0xa1, 0x58, 0x95, 0xdd, 0xac, 0x61, 0x75, 0x65, 0xa9, - 0x2a, 0x4b, 0x22, 0x75, 0xfa, 0x3e, 0x7c, 0x3e, 0xf9, 0x0f, 0x18, 0xf0, 0x69, 0x61, 0x18, 0xf0, - 0x0b, 0xc6, 0x1e, 0x0c, 0xfb, 0x1f, 0x18, 0x58, 0xf8, 0x60, 0xf8, 0xe4, 0x83, 0x0f, 0x86, 0xb1, - 0x7b, 0x34, 0xe0, 0x9b, 0x81, 0xbd, 0x18, 0x30, 0x22, 0x32, 0xb3, 0xaa, 0xba, 0x49, 0x69, 0x1e, - 0x36, 0xf6, 0xe2, 0x3d, 0x31, 0x33, 0x22, 0x32, 0x3b, 0x2b, 0x32, 0x32, 0x9e, 0x99, 0x84, 0x61, - 0x12, 0x26, 0x3c, 0x0a, 0x63, 0xbe, 0x96, 0xa4, 0x42, 0x0a, 0x66, 0x99, 0xfe, 0xf5, 0xf7, 0xa6, - 0xa1, 0x3c, 0xce, 0x8f, 0xd6, 0x7c, 0x31, 0xbb, 0x3b, 0x15, 0x53, 0x71, 0x97, 0x08, 0x8e, 0xf2, - 0x09, 0xf5, 0xa8, 0x43, 0x2d, 0x35, 0xf0, 0x3a, 0x44, 0xc2, 0x3f, 0x31, 0xed, 0x24, 0xf2, 0x62, - 0xdd, 0x5e, 0x92, 0xe1, 0x8c, 0x67, 0xd2, 0x9b, 0x25, 0x1a, 0xd0, 0x95, 0xa7, 0x1a, 0x67, 0xff, - 0x6d, 0x03, 0x3a, 0xbb, 0x3c, 0xcb, 0xbc, 0x29, 0x67, 0x36, 0x34, 0xb2, 0x30, 0x18, 0xd7, 0x56, - 0x6a, 0xab, 0xc3, 0xf5, 0xd1, 0x5a, 0xb1, 0xac, 0x03, 0xe9, 0xc9, 0x3c, 0x73, 0x10, 0x89, 0x34, - 0xfe, 0x2c, 0x18, 0xd7, 0x17, 0x69, 0x76, 0xb9, 0x3c, 0x16, 0x81, 0x83, 0x48, 0x36, 0x82, 0x06, - 0x4f, 0xd3, 0x71, 0x63, 0xa5, 0xb6, 0xda, 0x77, 0xb0, 0xc9, 0x18, 0x34, 0x03, 0x4f, 0x7a, 0xe3, - 0x26, 0x81, 0xa8, 0xcd, 0x6e, 0xc2, 0x30, 0x49, 0x85, 0xef, 0x86, 0xf1, 0x44, 0xb8, 0x84, 0x6d, - 0x11, 0xb6, 0x8f, 0xd0, 0xed, 0x78, 0x22, 0xb6, 0x90, 0x6a, 0x0c, 0x1d, 0x2f, 0xf6, 0xa2, 0xb3, - 0x8c, 0x8f, 0xdb, 0x84, 0x36, 0x5d, 0x36, 0x84, 0x7a, 0x18, 0x8c, 0x3b, 0x2b, 0xb5, 0xd5, 0xa6, - 0x53, 0x0f, 0x03, 0xfc, 0x8d, 0x3c, 0x0f, 0x83, 0xb1, 0xa5, 0x7e, 0x03, 0xdb, 0xcc, 0x86, 0x7e, - 0xcc, 0x79, 0xb0, 0x27, 0xa4, 0xc3, 0x93, 0xe8, 0x6c, 0xdc, 0x5d, 0xa9, 0xad, 0x5a, 0xce, 0x1c, - 0x8c, 0x5d, 0x07, 0x2b, 0xe0, 0x47, 0xf9, 0x74, 0x37, 0x9b, 0x8e, 0x61, 0xa5, 0xb6, 0xda, 0x75, - 0x8a, 0x3e, 0x3b, 0x84, 0x6b, 0x29, 0x7f, 0x92, 0xf3, 0x4c, 0xf2, 0xc0, 0x95, 0xdc, 0x4b, 0x03, - 0xf1, 0x2c, 0x76, 0x67, 0x22, 0xe0, 0xe3, 0x1e, 0x71, 0xe0, 0xb5, 0x2a, 0x97, 0x52, 0xee, 0xcd, - 0x0e, 0x35, 0xd1, 0xae, 0x08, 0xb8, 0x73, 0xa5, 0x18, 0x5c, 0x05, 0x33, 0x07, 0xae, 0x7a, 0xbe, - 0xcf, 0x93, 0xf3, 0x93, 0xf6, 0xbf, 0xc4, 0xa4, 0x97, 0xcd, 0xd8, 0x2a, 0xd4, 0x7e, 0x0c, 0xdd, - 0x4d, 0x11, 0xc7, 0xdc, 0x97, 0x22, 0x65, 0x6f, 0x42, 0xcf, 0xcc, 0xe0, 0xea, 0x0d, 0x6d, 0x39, - 0x60, 0x40, 0xdb, 0x01, 0x7b, 0x1b, 0x96, 0x7c, 0x43, 0xed, 0x86, 0x71, 0xc0, 0x4f, 0x69, 0x47, - 0x5b, 0xce, 0xb0, 0x00, 0x6f, 0x23, 0xd4, 0xfe, 0xc3, 0x06, 0x74, 0x0e, 0x8e, 0xf3, 0xc9, 0x24, - 0xe2, 0xec, 0x26, 0x0c, 0x74, 0x73, 0x53, 0x44, 0xdb, 0xc1, 0xa9, 0x9e, 0x77, 0x1e, 0xc8, 0x56, - 0xa0, 0xa7, 0x01, 0x87, 0x67, 0x09, 0xd7, 0xd3, 0x56, 0x41, 0xf3, 0xf3, 0xec, 0x86, 0x31, 0x09, - 0x4a, 0xc3, 0x99, 0x07, 0x2e, 0x50, 0x79, 0xa7, 0x24, 0x3b, 0xf3, 0x54, 0x1e, 0xfd, 0xda, 0x46, - 0x14, 0x3e, 0xe5, 0x0e, 0x9f, 0x6e, 0xc6, 0x92, 0x24, 0xa8, 0xe5, 0x54, 0x41, 0x6c, 0x1d, 0xae, - 0x64, 0x6a, 0x88, 0x9b, 0x7a, 0xf1, 0x94, 0x67, 0x6e, 0x1e, 0xc6, 0xf2, 0x5b, 0x1f, 0x8d, 0xdb, - 0x2b, 0x8d, 0xd5, 0xa6, 0x73, 0x49, 0x23, 0x1d, 0xc2, 0x3d, 0x26, 0x14, 0x7b, 0x1f, 0x2e, 0x2f, - 0x8c, 0x51, 0x43, 0x3a, 0x2b, 0x8d, 0xd5, 0x86, 0xc3, 0xe6, 0x86, 0x6c, 0xd3, 0x88, 0x07, 0xb0, - 0x9c, 0xe6, 0x31, 0x9e, 0xb3, 0x87, 0x61, 0x24, 0x79, 0x7a, 0x90, 0x70, 0x9f, 0x24, 0xb1, 0xb7, - 0x7e, 0x6d, 0x8d, 0x8e, 0xa2, 0xb3, 0x88, 0x76, 0xce, 0x8f, 0x60, 0xef, 0x16, 0xcc, 0x7b, 0x70, - 0x9a, 0xa4, 0x24, 0xae, 0xbd, 0x75, 0x50, 0x13, 0x20, 0xc4, 0xa9, 0xa2, 0xed, 0xdf, 0xd4, 0xc1, - 0xda, 0x0a, 0xb3, 0xc4, 0x93, 0xfe, 0x31, 0xbb, 0x06, 0x9d, 0x49, 0x1e, 0xfb, 0xe5, 0x7e, 0xb7, - 0xb1, 0xbb, 0x1d, 0xb0, 0xef, 0xc3, 0x52, 0x24, 0x7c, 0x2f, 0x72, 0x8b, 0xad, 0x1d, 0xd7, 0x57, - 0x1a, 0xab, 0xbd, 0xf5, 0x4b, 0xa5, 0x98, 0x15, 0xa2, 0xe3, 0x0c, 0x89, 0xb6, 0x14, 0xa5, 0x1f, - 0xc0, 0x28, 0xe5, 0x33, 0x21, 0x79, 0x65, 0x78, 0x83, 0x86, 0xb3, 0x72, 0xf8, 0xa7, 0xa9, 0x97, - 0xec, 0xa1, 0x6c, 0x2e, 0x29, 0xda, 0x72, 0xf8, 0x07, 0x15, 0xee, 0xf3, 0xa9, 0x1b, 0x06, 0xa7, - 0x2e, 0xfd, 0xc0, 0xb8, 0xb9, 0xd2, 0x58, 0x6d, 0x95, 0xac, 0xe4, 0xd3, 0xed, 0xe0, 0x74, 0x07, - 0x31, 0xec, 0x43, 0xb8, 0xba, 0x38, 0x44, 0xcd, 0x3a, 0x6e, 0xd1, 0x98, 0x4b, 0x73, 0x63, 0x1c, - 0x42, 0xb1, 0xb7, 0xa0, 0x6f, 0x06, 0x49, 0x14, 0xbb, 0xb6, 0x12, 0x84, 0xac, 0x22, 0x76, 0xd7, - 0xa0, 0x13, 0x66, 0x6e, 0x16, 0xc6, 0x27, 0xa4, 0x34, 0x2c, 0xa7, 0x1d, 0x66, 0x07, 0x61, 0x7c, - 0xc2, 0x5e, 0x05, 0x2b, 0xe5, 0xbe, 0xc2, 0x58, 0x84, 0xe9, 0xa4, 0xdc, 0x27, 0xd4, 0x35, 0xc0, - 0xa6, 0xeb, 0x4b, 0xae, 0x55, 0x47, 0x3b, 0xe5, 0xfe, 0xa6, 0xe4, 0x76, 0x06, 0xad, 0x5d, 0x9e, - 0x4e, 0x39, 0x6a, 0x0f, 0x1c, 0x78, 0xe0, 0x7b, 0x31, 0xf1, 0xdd, 0x72, 0x8a, 0x3e, 0xea, 0xae, - 0xc4, 0x4b, 0x65, 0xe8, 0x45, 0x74, 0x0c, 0x2c, 0xc7, 0x74, 0xd9, 0x0d, 0xe8, 0x66, 0xd2, 0x4b, - 0x25, 0x7e, 0x1d, 0x89, 0x7f, 0xcb, 0xb1, 0x08, 0x80, 0x27, 0xe8, 0x1a, 0x74, 0x78, 0x1c, 0x10, - 0xaa, 0xa9, 0x76, 0x92, 0xc7, 0xc1, 0x76, 0x70, 0x6a, 0xff, 0x55, 0x0d, 0x06, 0xbb, 0x79, 0x24, - 0xc3, 0x8d, 0x74, 0x9a, 0xf3, 0x59, 0x2c, 0x51, 0xe7, 0x6d, 0x85, 0x99, 0xd4, 0xbf, 0x4c, 0x6d, - 0xb6, 0x0a, 0xdd, 0x9f, 0xa4, 0x22, 0x4f, 0x48, 0x82, 0xd4, 0x4e, 0x57, 0x25, 0xa8, 0x44, 0xa2, - 0xb4, 0x3d, 0x4a, 0x03, 0x9e, 0xde, 0x3f, 0x23, 0xda, 0xc6, 0x39, 0xda, 0x2a, 0x9a, 0xbd, 0x06, - 0xdd, 0x03, 0x9e, 0x78, 0xa9, 0x87, 0x22, 0xd0, 0x24, 0x45, 0x59, 0x02, 0xf0, 0x5b, 0x89, 0x78, - 0x3b, 0xd0, 0x87, 0xd0, 0x74, 0xed, 0x29, 0x74, 0x37, 0xa6, 0xd3, 0x94, 0x4f, 0x3d, 0x49, 0x4a, - 0x5b, 0x24, 0xb4, 0xdc, 0x86, 0x53, 0x17, 0x09, 0x19, 0x06, 0xfc, 0x00, 0xc5, 0x1f, 0x6a, 0xb3, - 0x37, 0xa0, 0xc9, 0x2f, 0x5e, 0x0f, 0xc1, 0xd9, 0x55, 0x68, 0xfb, 0x22, 0x9e, 0x84, 0x53, 0x6d, - 0x4e, 0x74, 0xcf, 0xfe, 0xf3, 0x06, 0xb4, 0xe8, 0xe3, 0x90, 0xbd, 0xa8, 0xe2, 0x5d, 0xfe, 0xd4, - 0x8b, 0xcc, 0xae, 0x20, 0xe0, 0xc1, 0x53, 0x2f, 0x62, 0x2b, 0xd0, 0xc2, 0x69, 0xb2, 0x0b, 0x78, - 0xa3, 0x10, 0xec, 0x36, 0xb4, 0x50, 0x88, 0xb2, 0xf9, 0x15, 0xa0, 0x10, 0xdd, 0x6f, 0xfe, 0xf2, - 0x9f, 0xdf, 0x7c, 0xc5, 0x51, 0x68, 0xf6, 0x36, 0x34, 0xbd, 0xe9, 0x34, 0x23, 0x59, 0x9e, 0x3b, - 0x4e, 0xc5, 0xf7, 0x3a, 0x44, 0xc0, 0xee, 0x41, 0x57, 0xed, 0x1b, 0x52, 0xb7, 0x88, 0xfa, 0x5a, - 0xc5, 0x74, 0x56, 0xb7, 0xd4, 0x29, 0x29, 0x91, 0xe3, 0x61, 0xa6, 0x0f, 0x3c, 0x49, 0xb4, 0xe5, - 0x94, 0x00, 0xb4, 0x6d, 0x49, 0xca, 0x37, 0xa2, 0x48, 0xf8, 0x07, 0xe1, 0x73, 0xae, 0x2d, 0xe1, - 0x1c, 0x8c, 0xdd, 0x86, 0xe1, 0xbe, 0x12, 0x39, 0x87, 0x67, 0x79, 0x24, 0x33, 0x6d, 0x1d, 0x17, - 0xa0, 0x6c, 0x0d, 0xd8, 0x1c, 0xe4, 0x90, 0x3e, 0xbf, 0xbb, 0xd2, 0x58, 0x1d, 0x38, 0x17, 0x60, - 0xd8, 0x37, 0x60, 0x30, 0x45, 0x4e, 0x87, 0xf1, 0xd4, 0x9d, 0x44, 0x1e, 0x1a, 0xce, 0x06, 0x1a, - 0x56, 0x03, 0x7c, 0x18, 0x79, 0x53, 0x12, 0xf2, 0x24, 0x8c, 0x22, 0x77, 0xc6, 0x67, 0x64, 0x2e, - 0x1b, 0x8e, 0x45, 0x80, 0x5d, 0x3e, 0xb3, 0xff, 0xa2, 0x09, 0xed, 0xed, 0x38, 0xe3, 0xa9, 0xc4, - 0x23, 0xe4, 0x4d, 0x26, 0xdc, 0x97, 0x5c, 0xa9, 0xae, 0xa6, 0x53, 0xf4, 0x91, 0x05, 0x87, 0xe2, - 0xd3, 0x34, 0x94, 0xfc, 0xe0, 0x43, 0x2d, 0x24, 0x25, 0x80, 0xdd, 0x81, 0x65, 0x2f, 0x08, 0x5c, - 0x43, 0xed, 0xa6, 0xe2, 0x59, 0x46, 0xc7, 0xc9, 0x72, 0x96, 0xbc, 0x20, 0xd8, 0xd0, 0x70, 0x47, - 0x3c, 0xcb, 0xd8, 0x5b, 0xd0, 0x48, 0xf9, 0x84, 0x44, 0xa6, 0xb7, 0xbe, 0xa4, 0xb6, 0xf4, 0xd1, - 0xd1, 0xe7, 0xdc, 0x97, 0x0e, 0x9f, 0x38, 0x88, 0x63, 0x97, 0xa1, 0xe5, 0x49, 0x99, 0xaa, 0x2d, - 0xea, 0x3a, 0xaa, 0xc3, 0xd6, 0xe0, 0x12, 0x1d, 0x5b, 0x19, 0x8a, 0xd8, 0x95, 0xde, 0x51, 0x84, - 0x36, 0x35, 0xd3, 0xe6, 0x63, 0xb9, 0x40, 0x1d, 0x22, 0x66, 0x3b, 0xc8, 0xd0, 0xe0, 0x2c, 0xd2, - 0xc7, 0xde, 0x8c, 0x67, 0x64, 0x3d, 0xba, 0xce, 0xa5, 0xf9, 0x11, 0x7b, 0x88, 0x42, 0x7e, 0x96, - 0x63, 0xf0, 0xe0, 0x5b, 0x74, 0x86, 0xfa, 0x05, 0x10, 0xf5, 0xc2, 0x15, 0x68, 0x87, 0x99, 0xcb, - 0xe3, 0x40, 0xeb, 0xa2, 0x56, 0x98, 0x3d, 0x88, 0x03, 0xf6, 0x0e, 0x74, 0xd5, 0xaf, 0x04, 0x7c, - 0x42, 0x0e, 0x4c, 0x6f, 0x7d, 0xa8, 0x25, 0x16, 0xc1, 0x5b, 0x7c, 0xe2, 0x58, 0x52, 0xb7, 0xd0, - 0x33, 0x90, 0xc2, 0xe5, 0xa7, 0x92, 0xa7, 0xb1, 0x17, 0xd1, 0xae, 0x58, 0x0e, 0x48, 0xf1, 0x40, - 0x43, 0xd8, 0x3d, 0xb8, 0x66, 0xb0, 0x6e, 0x26, 0x67, 0xd2, 0xcd, 0xe3, 0xf0, 0xd4, 0x8d, 0xbd, - 0x58, 0x90, 0x73, 0xd2, 0x70, 0x2e, 0x1b, 0xf4, 0x81, 0x9c, 0xc9, 0xc7, 0x71, 0x78, 0xba, 0xe7, - 0xc5, 0x82, 0xad, 0xc2, 0xa8, 0x18, 0x26, 0x9f, 0xd3, 0x07, 0x8f, 0x07, 0xa4, 0x23, 0x86, 0x06, - 0x7e, 0xf8, 0x1c, 0xbf, 0x15, 0xd5, 0x7b, 0x95, 0x52, 0x4c, 0x26, 0x19, 0x97, 0x6e, 0xc6, 0xfd, - 0xf1, 0x90, 0xbe, 0xf9, 0x52, 0x49, 0xff, 0x88, 0x70, 0x07, 0xdc, 0xb7, 0xff, 0x7f, 0x0d, 0x7a, - 0x74, 0x2e, 0x1e, 0x27, 0x01, 0xaa, 0x91, 0x6f, 0xc0, 0x60, 0x7e, 0xd3, 0x95, 0xdc, 0xf4, 0xbd, - 0xea, 0x8e, 0x5f, 0x85, 0xf6, 0x86, 0x8f, 0xcc, 0x23, 0xc1, 0x19, 0x38, 0xba, 0xc7, 0xbe, 0x0d, - 0x4b, 0x39, 0x4d, 0xe3, 0xfa, 0xf2, 0xd4, 0x8d, 0x50, 0xfd, 0xa8, 0x83, 0xae, 0xa5, 0x42, 0xfd, - 0xc6, 0xa6, 0x3c, 0x75, 0x06, 0xb9, 0x69, 0xee, 0x84, 0x99, 0xb4, 0x5f, 0x87, 0xd6, 0x46, 0x9a, - 0x7a, 0x67, 0x24, 0x28, 0xd8, 0x18, 0xd7, 0xc8, 0x22, 0xa9, 0x8e, 0xed, 0x43, 0x63, 0xd7, 0x4b, - 0xd8, 0x2d, 0xa8, 0xcf, 0x12, 0xc2, 0xf4, 0xd6, 0xaf, 0x54, 0x4e, 0xb9, 0x97, 0xac, 0xed, 0x26, - 0x0f, 0x62, 0x99, 0x9e, 0x39, 0xf5, 0x59, 0x72, 0xfd, 0x1e, 0x74, 0x74, 0x17, 0xfd, 0xe5, 0x13, - 0x7e, 0x46, 0xdf, 0xd0, 0x75, 0xb0, 0x89, 0x3f, 0xf0, 0xd4, 0x8b, 0x72, 0xe3, 0x3e, 0xa9, 0xce, - 0x77, 0xeb, 0x1f, 0xd7, 0xec, 0x7f, 0x6f, 0x82, 0xb5, 0xc5, 0x23, 0x4e, 0x5f, 0x62, 0x43, 0xbf, - 0x2a, 0xe3, 0x86, 0x0b, 0x73, 0x72, 0x6f, 0x43, 0x5f, 0xd9, 0x48, 0x1a, 0xc5, 0xf5, 0x21, 0x9a, - 0x83, 0xa1, 0xf2, 0xde, 0xbe, 0x9f, 0xfb, 0x27, 0x5c, 0xd2, 0xe9, 0x19, 0x38, 0xa6, 0x8b, 0x98, - 0x3d, 0x8d, 0x69, 0x2a, 0x8c, 0xee, 0xb2, 0xd7, 0x00, 0x52, 0xf1, 0xcc, 0x0d, 0x95, 0xa1, 0x52, - 0x3a, 0xdf, 0x4a, 0xc5, 0xb3, 0x6d, 0x34, 0x55, 0xbf, 0x95, 0x43, 0xf3, 0x6d, 0x18, 0x57, 0x0e, - 0x0d, 0xba, 0xab, 0x6e, 0x18, 0xbb, 0x47, 0xe8, 0x0d, 0xe9, 0xf3, 0x53, 0xce, 0x49, 0xde, 0xec, - 0x76, 0x7c, 0x9f, 0x5c, 0x25, 0xad, 0x0a, 0xba, 0x2f, 0x51, 0x05, 0x17, 0x6a, 0x16, 0xb8, 0x58, - 0xb3, 0xdc, 0x07, 0x38, 0xe0, 0xd3, 0x19, 0x8f, 0xe5, 0xae, 0x97, 0x8c, 0x7b, 0xb4, 0xf1, 0x76, - 0xb9, 0xf1, 0x66, 0xb7, 0xd6, 0x4a, 0x22, 0x25, 0x05, 0x95, 0x51, 0xe8, 0xbf, 0xf8, 0x5e, 0xec, - 0xca, 0x34, 0x8f, 0x7d, 0x4f, 0xaa, 0x40, 0xc0, 0x72, 0x7a, 0xbe, 0x17, 0x1f, 0x6a, 0x50, 0xe5, - 0xf8, 0x0f, 0xaa, 0xc7, 0xff, 0x36, 0x2c, 0x25, 0x69, 0x38, 0xf3, 0xd2, 0x33, 0xf7, 0x84, 0x9f, - 0xd1, 0x66, 0xa8, 0x83, 0x34, 0xd0, 0xe0, 0x9f, 0xf1, 0xb3, 0xed, 0xe0, 0xf4, 0xfa, 0x0f, 0x60, - 0x69, 0x61, 0x01, 0x5f, 0x49, 0xee, 0x7e, 0xde, 0x80, 0xee, 0x7e, 0xca, 0xb5, 0xca, 0x7e, 0x13, - 0x7a, 0x99, 0x7f, 0xcc, 0x67, 0x9e, 0x3a, 0xe9, 0x6a, 0x06, 0x50, 0x20, 0x3a, 0xe5, 0x73, 0x4a, - 0xa9, 0xfe, 0x05, 0x4a, 0x69, 0x04, 0x0d, 0xe5, 0x07, 0xe1, 0x61, 0xc2, 0x66, 0xa9, 0x89, 0x9b, - 0x55, 0x4d, 0xbc, 0x02, 0xfd, 0x63, 0x2f, 0x73, 0xbd, 0x5c, 0x0a, 0xd7, 0x17, 0x11, 0x09, 0x9d, - 0xe5, 0xc0, 0xb1, 0x97, 0x6d, 0xe4, 0x52, 0x6c, 0x8a, 0x88, 0xbd, 0x0e, 0xe0, 0x8b, 0x48, 0x2b, - 0x15, 0xed, 0x04, 0x76, 0x7d, 0x11, 0x29, 0x4d, 0x82, 0x52, 0xc9, 0x33, 0x19, 0xce, 0x3c, 0xbd, - 0xa5, 0xae, 0x2f, 0xf2, 0x58, 0x92, 0xe5, 0x6c, 0x38, 0xcb, 0x05, 0xca, 0x11, 0xcf, 0x36, 0x11, - 0xc1, 0xde, 0x87, 0xa1, 0x2f, 0x66, 0x89, 0x9b, 0x20, 0x67, 0xc9, 0x27, 0xb1, 0xce, 0x79, 0xe4, - 0x7d, 0xa4, 0xd8, 0x3f, 0xe1, 0xca, 0x49, 0x5a, 0x87, 0x25, 0x3f, 0xca, 0x33, 0xc9, 0x53, 0xf7, - 0x48, 0x0f, 0x39, 0xef, 0xc4, 0x0f, 0x34, 0x89, 0x76, 0xac, 0x6c, 0x18, 0x84, 0x99, 0x2b, 0xa2, - 0xc0, 0x55, 0xea, 0x46, 0xcb, 0x59, 0x2f, 0xcc, 0x1e, 0x45, 0x81, 0x56, 0x78, 0x8a, 0x26, 0xe6, - 0xcf, 0x0c, 0x4d, 0xcf, 0xd0, 0xec, 0xf1, 0x67, 0x8a, 0xc6, 0xfe, 0xc7, 0x3a, 0x74, 0xf6, 0x45, - 0x26, 0xb7, 0x66, 0x91, 0x11, 0xf1, 0xda, 0x57, 0x15, 0xf1, 0xfa, 0xc5, 0x22, 0x7e, 0x81, 0x90, - 0x35, 0x2e, 0x10, 0x32, 0x34, 0x03, 0x55, 0x3a, 0x12, 0x0e, 0xe5, 0x2a, 0x0e, 0x4b, 0x42, 0x12, - 0x90, 0x1b, 0xe8, 0xdb, 0xb8, 0x81, 0xd2, 0x49, 0x6a, 0x23, 0xad, 0x30, 0xd3, 0xfa, 0x48, 0x21, - 0x43, 0x92, 0x35, 0xed, 0xf8, 0x58, 0x61, 0xa6, 0x65, 0xef, 0x3b, 0xf0, 0x6a, 0x31, 0xd2, 0x7d, - 0x16, 0xca, 0x63, 0x91, 0x4b, 0x77, 0x42, 0x31, 0x54, 0xa6, 0x3d, 0xfb, 0xab, 0x66, 0xa6, 0x4f, - 0x15, 0x5a, 0x45, 0x58, 0xe4, 0x87, 0x4d, 0xf2, 0x28, 0x72, 0x25, 0x3f, 0x95, 0x7a, 0x2b, 0xc7, - 0x8a, 0x37, 0x9a, 0x6f, 0x0f, 0xf3, 0x28, 0x3a, 0xe4, 0xa7, 0x12, 0x95, 0xbf, 0x35, 0xd1, 0x1d, - 0xfb, 0x0f, 0x9a, 0x00, 0x3b, 0xc2, 0x3f, 0x39, 0xf4, 0xd2, 0x29, 0x97, 0x18, 0x2f, 0x18, 0x8d, - 0xa6, 0x35, 0x6e, 0x47, 0x2a, 0x3d, 0xc6, 0xd6, 0xe1, 0xaa, 0xf9, 0x7e, 0x94, 0x43, 0x8c, 0x5d, - 0x94, 0x4a, 0xd2, 0x07, 0x8a, 0x69, 0xac, 0x8a, 0x95, 0x49, 0x1f, 0xb1, 0x8f, 0x4b, 0xde, 0xe2, - 0x18, 0x79, 0x96, 0x10, 0x6f, 0x2f, 0xf2, 0x3b, 0x07, 0xe5, 0xf0, 0xc3, 0xb3, 0x84, 0xbd, 0x0f, - 0x57, 0x52, 0x3e, 0x49, 0x79, 0x76, 0xec, 0xca, 0xac, 0xfa, 0x63, 0x2a, 0x6c, 0x58, 0xd6, 0xc8, - 0xc3, 0xac, 0xf8, 0xad, 0xf7, 0xe1, 0x8a, 0xe2, 0xd4, 0xe2, 0xf2, 0x94, 0xfe, 0x5e, 0x56, 0xc8, - 0xea, 0xea, 0x5e, 0x07, 0xca, 0x2a, 0x29, 0x9d, 0x6c, 0x9c, 0xd0, 0x88, 0x98, 0x71, 0x14, 0x71, - 0xf4, 0xcf, 0x36, 0x8f, 0x31, 0x0e, 0xde, 0xe2, 0x13, 0xcd, 0xfc, 0x12, 0xc0, 0x6c, 0x68, 0xee, - 0x8a, 0x80, 0x13, 0xab, 0x87, 0xeb, 0xc3, 0x35, 0xca, 0x4f, 0x21, 0x27, 0x29, 0x91, 0x41, 0x38, - 0xf6, 0x36, 0xd0, 0x74, 0x4a, 0xfc, 0xce, 0x9f, 0x15, 0x0b, 0x91, 0x24, 0x83, 0xef, 0xc3, 0x95, - 0x72, 0x25, 0xae, 0x27, 0x5d, 0x79, 0xcc, 0x49, 0x1d, 0xaa, 0xe3, 0xb2, 0x5c, 0x2c, 0x6a, 0x43, - 0x1e, 0x1e, 0x73, 0x54, 0x8d, 0xab, 0xd0, 0x11, 0x47, 0x9f, 0xbb, 0x78, 0x10, 0x7a, 0x17, 0x1f, - 0x84, 0xb6, 0x38, 0xfa, 0xdc, 0xe1, 0x13, 0xf6, 0xad, 0xaa, 0x29, 0x59, 0x60, 0x4d, 0x9f, 0x58, - 0x73, 0xb9, 0xc0, 0x57, 0xb8, 0x63, 0x7f, 0x0c, 0x6d, 0xfc, 0x9c, 0x47, 0x09, 0x5b, 0x83, 0x8e, - 0x24, 0xf1, 0xc8, 0xb4, 0xe9, 0xbf, 0x5c, 0x5a, 0x80, 0x52, 0x76, 0x1c, 0x43, 0x64, 0x3b, 0xb0, - 0x54, 0xa8, 0xd3, 0xc7, 0x71, 0xf8, 0x24, 0xe7, 0xec, 0x47, 0xb0, 0x9c, 0xa4, 0x5c, 0x8b, 0xbd, - 0x9b, 0x9f, 0xa0, 0x7b, 0xa2, 0x4f, 0xf0, 0x65, 0x2d, 0xa5, 0xc5, 0x88, 0x13, 0x94, 0xd0, 0x61, - 0x32, 0xd7, 0xb7, 0x3f, 0x83, 0x6b, 0x05, 0xc5, 0x01, 0xf7, 0x45, 0x1c, 0x78, 0xe9, 0x19, 0x59, - 0xbe, 0x85, 0xb9, 0xb3, 0xaf, 0x32, 0xf7, 0x01, 0xcd, 0xfd, 0x27, 0x35, 0xe8, 0x3d, 0xcc, 0x9f, - 0x3f, 0x3f, 0x53, 0x67, 0x89, 0xf5, 0xa1, 0xb6, 0x47, 0x13, 0xd4, 0x9d, 0xda, 0x1e, 0xba, 0x5a, - 0xfb, 0x27, 0x78, 0xae, 0x49, 0xce, 0xbb, 0x8e, 0xee, 0x61, 0x24, 0xb5, 0x7f, 0x72, 0xf8, 0x12, - 0x89, 0x56, 0x68, 0x0c, 0x01, 0xee, 0xe7, 0x61, 0x84, 0xae, 0x83, 0x16, 0xde, 0xa2, 0x8f, 0xb1, - 0xc9, 0xf6, 0x44, 0x2d, 0xe5, 0x61, 0x2a, 0x66, 0x8a, 0x59, 0x5a, 0x65, 0x5c, 0x80, 0xb1, 0x7f, - 0xd3, 0x04, 0xeb, 0x13, 0x2f, 0x3b, 0xfe, 0xa9, 0x08, 0x63, 0xf6, 0x3e, 0x74, 0x3f, 0x17, 0x61, - 0xac, 0x92, 0x02, 0x2a, 0xb1, 0x79, 0x49, 0x2d, 0x62, 0x4f, 0x04, 0x7c, 0x0d, 0x69, 0x70, 0x35, - 0x8e, 0xf5, 0xb9, 0x6e, 0x69, 0x4d, 0x9b, 0x86, 0xd3, 0x63, 0xe9, 0x22, 0x50, 0xab, 0xc4, 0x5e, - 0x98, 0x39, 0x08, 0xa3, 0x59, 0x5f, 0x03, 0x34, 0x3a, 0xc7, 0xae, 0x88, 0xdd, 0xe4, 0x44, 0x07, - 0x1c, 0x16, 0x42, 0x1e, 0xc5, 0xfb, 0x27, 0x78, 0x64, 0xc2, 0xcc, 0xd5, 0xa9, 0x07, 0xfa, 0x9c, - 0xb9, 0xb8, 0xed, 0x26, 0x0c, 0xd1, 0xd4, 0x67, 0x27, 0x61, 0xe2, 0x26, 0xa9, 0x38, 0x32, 0xdf, - 0x82, 0x0e, 0xc0, 0xc1, 0x49, 0x98, 0xec, 0x23, 0x8c, 0x2c, 0xac, 0x4e, 0x68, 0xa0, 0xb6, 0x55, - 0xa6, 0x0c, 0x34, 0x08, 0xd9, 0x42, 0x59, 0x8b, 0x48, 0xb9, 0xaf, 0x1d, 0xb2, 0x9c, 0x9d, 0x94, - 0x47, 0xe8, 0xa7, 0x22, 0x0a, 0x65, 0x98, 0x50, 0x96, 0x42, 0xf9, 0x42, 0xa1, 0xbe, 0x09, 0x10, - 0xf1, 0x89, 0x74, 0x51, 0x38, 0x54, 0x80, 0xb7, 0x90, 0x1d, 0x40, 0xec, 0x26, 0x22, 0xd9, 0x3b, - 0xd0, 0x53, 0x5c, 0x50, 0xb4, 0x70, 0x8e, 0x16, 0x08, 0xad, 0x88, 0xef, 0x40, 0x2f, 0x16, 0xb1, - 0xcb, 0x9f, 0x10, 0xb5, 0x3e, 0x6e, 0x73, 0x13, 0xc7, 0x22, 0x7e, 0xf0, 0x04, 0x89, 0xd9, 0x5d, - 0xbd, 0x06, 0x15, 0x63, 0xf7, 0x5f, 0x10, 0x63, 0xd3, 0x4a, 0x54, 0xb4, 0xf9, 0x81, 0x59, 0x89, - 0x1a, 0x31, 0x78, 0xc1, 0x08, 0xb5, 0x1e, 0x35, 0x64, 0x05, 0xfa, 0xb4, 0xef, 0x33, 0x2f, 0x71, - 0xa5, 0x37, 0xd5, 0x2e, 0x11, 0x20, 0x6c, 0xd7, 0x4b, 0x0e, 0xbd, 0x29, 0x73, 0xe0, 0x55, 0x9d, - 0x7f, 0xd3, 0xc6, 0xc3, 0x3d, 0x42, 0x89, 0x53, 0x5c, 0x5b, 0x32, 0x31, 0xfa, 0xc5, 0x99, 0xbb, - 0xab, 0x73, 0x99, 0x3b, 0x92, 0x54, 0x0a, 0x10, 0xfe, 0xb8, 0x0e, 0xd6, 0x8e, 0x10, 0xc9, 0xd7, - 0x14, 0xbd, 0xea, 0x96, 0xd6, 0x5f, 0xbc, 0xa5, 0x8d, 0xf9, 0x2d, 0x5d, 0x60, 0x7d, 0xf3, 0xcb, - 0xb3, 0xbe, 0xf5, 0x95, 0x59, 0xdf, 0xfe, 0x1a, 0xac, 0xef, 0x2c, 0xb2, 0xde, 0xee, 0x40, 0xeb, - 0x80, 0xcb, 0x47, 0x89, 0xfd, 0x0b, 0x0b, 0xba, 0x5b, 0x3c, 0xc8, 0x15, 0xc3, 0xaa, 0x9f, 0x5f, - 0x7b, 0xf1, 0xe7, 0xd7, 0xe7, 0x3f, 0x1f, 0xed, 0x87, 0x91, 0xe8, 0x0b, 0x52, 0x46, 0x96, 0x11, - 0x68, 0x14, 0xfd, 0x52, 0x9e, 0x75, 0xce, 0x66, 0x8e, 0x4d, 0x85, 0x38, 0xbf, 0x5c, 0x36, 0x5a, - 0x5f, 0x4b, 0x36, 0x16, 0xb4, 0xc2, 0xb9, 0x6c, 0xce, 0x17, 0x72, 0x6d, 0x51, 0x23, 0x58, 0xe7, - 0x34, 0xc2, 0x0e, 0x5c, 0x12, 0xb1, 0x1b, 0xe4, 0x49, 0x14, 0x62, 0xc0, 0xe0, 0x7a, 0x2a, 0xf8, - 0xed, 0x9a, 0x9a, 0x42, 0x21, 0x7a, 0x8f, 0xe2, 0x2d, 0x43, 0xa4, 0x42, 0x62, 0x67, 0x59, 0x2c, - 0x82, 0x50, 0x4d, 0x05, 0xb8, 0x35, 0x64, 0x0e, 0xc9, 0x91, 0x53, 0xc5, 0x91, 0x3e, 0x41, 0x37, - 0x45, 0x44, 0x0a, 0xfe, 0x63, 0x58, 0x2a, 0xa9, 0x94, 0x8c, 0xf4, 0x5e, 0x20, 0x23, 0x03, 0x33, - 0x50, 0x89, 0xc9, 0x6f, 0x43, 0x0b, 0xbc, 0x07, 0x97, 0x4c, 0xa4, 0xaf, 0x6d, 0x3a, 0xed, 0xe0, - 0x90, 0x24, 0x68, 0xa4, 0x83, 0x7b, 0x32, 0xe7, 0xb4, 0x45, 0xdf, 0x83, 0xcb, 0x15, 0x72, 0x74, - 0xde, 0xab, 0xda, 0xa0, 0x2a, 0x2b, 0xcb, 0xc5, 0x58, 0xec, 0xee, 0xa8, 0xac, 0x65, 0x2f, 0xe0, - 0x91, 0xf9, 0xa1, 0xf1, 0x48, 0xc5, 0x1e, 0x01, 0x8f, 0x74, 0x5d, 0x64, 0x17, 0x6e, 0xa2, 0x8b, - 0x8f, 0x78, 0xdf, 0x4b, 0x64, 0x9e, 0x72, 0x37, 0x89, 0x3c, 0x9f, 0x1f, 0x8b, 0x28, 0xe0, 0x69, - 0xb9, 0xb8, 0x65, 0x5a, 0xdc, 0x9b, 0x22, 0x0a, 0x36, 0x45, 0xb4, 0xa9, 0x28, 0xf7, 0x4b, 0x42, - 0xb3, 0xd6, 0x0d, 0x78, 0xe3, 0xdc, 0x74, 0x68, 0x38, 0xca, 0x89, 0x18, 0x4d, 0xf4, 0xea, 0xfc, - 0x44, 0x48, 0x62, 0xa6, 0xf8, 0x00, 0xae, 0xa8, 0xbd, 0x53, 0xc2, 0x7d, 0xc2, 0x79, 0xe2, 0x46, - 0x5e, 0x26, 0xc7, 0x97, 0x94, 0x6d, 0x25, 0x24, 0x09, 0xf0, 0xcf, 0x38, 0x4f, 0x76, 0x3c, 0xf5, - 0xab, 0x6a, 0x88, 0x76, 0xbf, 0x69, 0xcc, 0x1c, 0x6f, 0x2f, 0xab, 0x5f, 0x25, 0x2a, 0xe5, 0x83, - 0xe3, 0xe0, 0x0a, 0x93, 0xbf, 0x0f, 0x37, 0xe6, 0xa6, 0x98, 0x79, 0xe9, 0x49, 0xe9, 0x8f, 0x8e, - 0xaf, 0x10, 0xdf, 0xae, 0x55, 0xc6, 0xef, 0x12, 0x81, 0x9a, 0xc1, 0xfe, 0xb7, 0x16, 0x0c, 0xc9, - 0x0e, 0xff, 0x4e, 0x6d, 0xfc, 0x4e, 0x6d, 0xfc, 0x0f, 0x50, 0x1b, 0xf6, 0xff, 0xad, 0x41, 0x67, - 0x3f, 0x15, 0x41, 0xee, 0xcb, 0xaf, 0x29, 0xe9, 0xf3, 0x12, 0xd4, 0xf8, 0x22, 0x09, 0x6a, 0x9e, - 0x33, 0xd7, 0x7f, 0x56, 0x83, 0xae, 0x5e, 0xc2, 0xce, 0xfa, 0xd7, 0x5c, 0x44, 0x59, 0xd3, 0xa9, - 0x5d, 0x58, 0xd3, 0xf9, 0xc2, 0x55, 0xa0, 0x60, 0x3d, 0x55, 0xf5, 0x6a, 0x91, 0x28, 0x9f, 0xaa, - 0xa5, 0x04, 0x4b, 0x41, 0x1f, 0x25, 0xb8, 0x77, 0xf6, 0x33, 0xe8, 0x52, 0xc0, 0x43, 0x9a, 0xe1, - 0x2a, 0xb4, 0x53, 0x2a, 0x5a, 0xe8, 0x85, 0xea, 0xde, 0xcb, 0xcf, 0x69, 0xfd, 0xeb, 0xb9, 0x7e, - 0x7f, 0x57, 0x87, 0x01, 0x45, 0x9f, 0x0f, 0xf3, 0x58, 0x9d, 0x84, 0x22, 0x87, 0x55, 0x9b, 0xcf, - 0x61, 0x35, 0x53, 0x0c, 0x12, 0xd5, 0xcf, 0xf4, 0xd5, 0xcf, 0x6c, 0x8a, 0x68, 0x8b, 0x4f, 0x1c, - 0xc2, 0x20, 0xab, 0xbc, 0x74, 0x9a, 0x5d, 0x54, 0xfe, 0x42, 0x38, 0x7e, 0x55, 0xe2, 0xa5, 0xde, - 0x2c, 0x33, 0xe5, 0x2f, 0xd5, 0x63, 0x0c, 0x9a, 0x74, 0xde, 0x14, 0x5b, 0xa8, 0xad, 0x13, 0x29, - 0x59, 0x18, 0x4f, 0x0b, 0xe5, 0x61, 0x51, 0xd5, 0x73, 0x1a, 0x71, 0xb6, 0x05, 0x4c, 0x65, 0x4d, - 0x53, 0xee, 0xa1, 0x09, 0xa2, 0x79, 0x48, 0x83, 0xf4, 0xd6, 0xaf, 0xaa, 0x9f, 0x25, 0x5e, 0x3a, - 0x84, 0xde, 0x47, 0xac, 0x33, 0x0a, 0x17, 0x20, 0x17, 0x30, 0x53, 0xd9, 0xa1, 0x22, 0xfa, 0xf8, - 0xd2, 0xcc, 0x24, 0xe3, 0x44, 0xcc, 0xdc, 0x80, 0x2b, 0xa6, 0x20, 0x81, 0xea, 0x62, 0x1d, 0xcf, - 0x02, 0x85, 0xb1, 0xe6, 0x1b, 0x6b, 0x95, 0x6f, 0xbc, 0x0c, 0xad, 0xea, 0x0d, 0x06, 0xd5, 0xb1, - 0x6f, 0x41, 0x6f, 0x12, 0x46, 0x5c, 0xa7, 0x02, 0x91, 0x69, 0x3a, 0x29, 0x58, 0xa3, 0x1a, 0xbe, - 0xee, 0xd9, 0x7f, 0x5d, 0x83, 0x6b, 0x89, 0x97, 0x3e, 0xc9, 0xb9, 0xa4, 0x84, 0x20, 0x15, 0xb0, - 0xdc, 0xec, 0xd8, 0x4b, 0x03, 0x3c, 0x38, 0x34, 0x85, 0x9a, 0x5d, 0x15, 0xd5, 0xbb, 0x08, 0x51, - 0x6b, 0xb9, 0x0d, 0x4b, 0x95, 0x11, 0xd2, 0x4b, 0x4d, 0x92, 0x67, 0x90, 0x8a, 0x67, 0x54, 0x87, - 0x3c, 0x40, 0x20, 0x06, 0x94, 0x25, 0x1d, 0x27, 0x6b, 0x43, 0xb5, 0x69, 0x43, 0xf5, 0x20, 0x0e, - 0xf0, 0xe4, 0xc4, 0xf9, 0x4c, 0xe5, 0x40, 0xd4, 0x3d, 0x87, 0x4e, 0x9c, 0xcf, 0x28, 0xed, 0x71, - 0x19, 0x5a, 0x47, 0x67, 0x92, 0xbc, 0x75, 0x84, 0xab, 0x8e, 0xfd, 0x4f, 0x4d, 0xe8, 0x1b, 0x16, - 0x51, 0xad, 0xf9, 0xdd, 0xaa, 0xb4, 0xf5, 0xd6, 0x47, 0x46, 0x6c, 0x90, 0x64, 0x43, 0xca, 0xd4, - 0xc4, 0xdb, 0x4a, 0x0a, 0x6f, 0x00, 0x7d, 0x88, 0x9b, 0x85, 0xcf, 0x39, 0x89, 0x62, 0xc3, 0xb1, - 0x10, 0x40, 0x45, 0xc3, 0x0d, 0x58, 0xae, 0xb0, 0xce, 0x95, 0x42, 0x7a, 0x91, 0x96, 0xc6, 0x4a, - 0x3d, 0xa3, 0x42, 0xe2, 0x2c, 0x61, 0x47, 0xe5, 0x58, 0x0f, 0x91, 0x1a, 0xa5, 0xdc, 0x17, 0x91, - 0xa9, 0x8c, 0x2e, 0x48, 0x39, 0x62, 0x28, 0x53, 0x9b, 0x72, 0x54, 0x9a, 0xd9, 0x93, 0x48, 0xcb, - 0x6c, 0x57, 0x41, 0x0e, 0x9e, 0x44, 0xc5, 0x02, 0x49, 0x8a, 0xda, 0x74, 0x80, 0x68, 0x81, 0xa4, - 0x4c, 0xde, 0x83, 0x9e, 0x48, 0xc3, 0x69, 0x48, 0xa9, 0x1a, 0x55, 0x22, 0x58, 0xfc, 0x11, 0x50, - 0x04, 0x9b, 0xf8, 0x53, 0x36, 0xb4, 0x95, 0x64, 0x5e, 0x90, 0xbd, 0xd5, 0x18, 0xdc, 0xcc, 0x4c, - 0xa6, 0xa1, 0x2f, 0x71, 0x39, 0xea, 0x2e, 0x8e, 0x2a, 0xb2, 0x0d, 0x14, 0xf8, 0xe0, 0x49, 0x44, - 0xd9, 0xaa, 0xdb, 0xb0, 0xe4, 0x8b, 0x28, 0x9f, 0xc5, 0xb4, 0x32, 0x37, 0xe2, 0x31, 0xd9, 0xb7, - 0x96, 0x33, 0x50, 0x60, 0x5c, 0xdf, 0x0e, 0x8f, 0x75, 0x41, 0xcf, 0x8b, 0x22, 0x54, 0x95, 0xc2, - 0x0b, 0x74, 0xbe, 0xb6, 0x6f, 0x80, 0x3b, 0xc2, 0x0b, 0xd8, 0x77, 0xe1, 0x3a, 0xe2, 0x5c, 0x3e, - 0x4b, 0xe4, 0x99, 0x1b, 0xe7, 0x33, 0x9e, 0x86, 0xbe, 0xeb, 0x65, 0xee, 0x73, 0x9e, 0x0a, 0x5d, - 0x02, 0xb8, 0x8a, 0x14, 0x0f, 0x90, 0x60, 0x4f, 0xe1, 0x37, 0xb2, 0xcf, 0x78, 0x2a, 0xd8, 0x67, - 0x94, 0xb1, 0xba, 0x48, 0x6e, 0x8d, 0x8d, 0x7b, 0xab, 0xdc, 0xab, 0x17, 0x50, 0x52, 0x7d, 0x04, - 0x11, 0x8e, 0x11, 0x58, 0x1a, 0x6f, 0xfb, 0x00, 0xea, 0xde, 0x11, 0x49, 0xd6, 0xdb, 0xd0, 0x91, - 0x47, 0x11, 0x25, 0xf2, 0x6b, 0x17, 0x26, 0xf2, 0xdb, 0xf2, 0x08, 0x79, 0x5e, 0x39, 0x63, 0x75, - 0x12, 0x55, 0xdd, 0x43, 0x09, 0x8e, 0xc2, 0x59, 0x28, 0xf5, 0x3d, 0x1f, 0xd5, 0xb1, 0x8f, 0xa0, - 0x4b, 0x33, 0xd0, 0x6f, 0x14, 0x15, 0xf7, 0xda, 0xcb, 0x2b, 0xee, 0xef, 0x41, 0x5f, 0x2b, 0x99, - 0x17, 0x95, 0xf0, 0x7b, 0x0a, 0x8f, 0xed, 0xcc, 0x7e, 0x17, 0xba, 0xff, 0xdb, 0x8b, 0x72, 0xf5, - 0x1b, 0x6f, 0x42, 0x8f, 0x6a, 0x43, 0xee, 0x51, 0x24, 0xfc, 0x13, 0x53, 0xb3, 0x20, 0xd0, 0x7d, - 0x84, 0xd8, 0x00, 0xd6, 0xe3, 0x38, 0x14, 0xf1, 0x46, 0x14, 0xd9, 0xbf, 0x6e, 0x43, 0xf7, 0x13, - 0x2f, 0x3b, 0x26, 0x05, 0x8f, 0x47, 0x98, 0xee, 0x13, 0x50, 0xd2, 0x67, 0xe6, 0x25, 0xfa, 0x4e, - 0x41, 0x0f, 0x81, 0x48, 0xb5, 0xeb, 0x25, 0x0b, 0x39, 0xa1, 0xfa, 0x42, 0x4e, 0xe8, 0x2d, 0x75, - 0x11, 0x4d, 0x55, 0xa7, 0xb8, 0x29, 0x52, 0xd3, 0x04, 0xf7, 0x15, 0x88, 0xbd, 0x0b, 0x8c, 0x48, - 0xbc, 0x28, 0x12, 0xe4, 0x88, 0x65, 0x3c, 0xca, 0x74, 0xfa, 0x68, 0x84, 0x98, 0x0d, 0x8d, 0x38, - 0xe0, 0xea, 0xfc, 0x54, 0xac, 0x7a, 0x6b, 0xd1, 0xaa, 0xdf, 0x01, 0x40, 0x7f, 0x95, 0x12, 0x96, - 0x0b, 0x61, 0xbb, 0xca, 0xdd, 0x94, 0xd8, 0x2f, 0xe1, 0x43, 0xbe, 0x0d, 0xa3, 0x82, 0x22, 0xe5, - 0x13, 0xd7, 0x8f, 0xa5, 0x76, 0x24, 0x07, 0x9a, 0xca, 0xe1, 0x93, 0xcd, 0x58, 0x2e, 0x3a, 0x9b, - 0xdd, 0x73, 0xce, 0xe6, 0x4f, 0xe0, 0xd2, 0x82, 0xb5, 0xc8, 0x12, 0xee, 0xeb, 0xb2, 0xf5, 0x57, - 0xb9, 0x29, 0xf5, 0x2a, 0x58, 0x54, 0x05, 0x08, 0xf2, 0x44, 0x9f, 0xad, 0x4e, 0x98, 0x51, 0x50, - 0xf0, 0x22, 0x87, 0xb6, 0xff, 0xdf, 0xe5, 0xd0, 0x0e, 0xbe, 0x9c, 0x43, 0x3b, 0xfc, 0x72, 0x0e, - 0xed, 0x82, 0x03, 0xb8, 0xb4, 0x18, 0x37, 0xbe, 0x30, 0x4a, 0x1b, 0xbd, 0x30, 0x4a, 0xfb, 0x82, - 0x10, 0x6b, 0xf9, 0xa5, 0x21, 0xd6, 0x97, 0x88, 0xf1, 0xd8, 0x17, 0xc5, 0x78, 0xb7, 0x61, 0x49, - 0xa6, 0x9e, 0x7f, 0xe2, 0xc6, 0x79, 0x14, 0xb9, 0x27, 0xfc, 0x2c, 0xd3, 0x31, 0xe5, 0x80, 0xc0, - 0x7b, 0x79, 0x14, 0xfd, 0x8c, 0x9f, 0x65, 0xf6, 0x63, 0x00, 0xb2, 0xa5, 0xf4, 0x69, 0x2f, 0x92, - 0x8d, 0xda, 0x57, 0x95, 0x0d, 0xfb, 0x3f, 0x6a, 0x00, 0x07, 0xde, 0x2c, 0x51, 0xce, 0x18, 0xfb, - 0x31, 0xf4, 0x32, 0xea, 0x55, 0x53, 0x71, 0x6f, 0x56, 0xee, 0x58, 0x16, 0xa4, 0xba, 0x49, 0x69, - 0x39, 0xc8, 0x8a, 0x36, 0x89, 0xb5, 0x9a, 0xa1, 0x28, 0x92, 0xb5, 0x0c, 0x01, 0x19, 0xe9, 0x5b, - 0x30, 0xd4, 0x04, 0x09, 0x4f, 0x7d, 0x1e, 0x2b, 0x5d, 0x57, 0x73, 0x06, 0x0a, 0xba, 0xaf, 0x80, - 0xec, 0x83, 0x82, 0x4c, 0x59, 0x8b, 0xec, 0x82, 0x78, 0x52, 0x0f, 0xd9, 0x54, 0x04, 0xf6, 0xba, - 0xf9, 0x14, 0x5a, 0x88, 0x05, 0x4d, 0xfc, 0xbd, 0xd1, 0x2b, 0xac, 0x07, 0x1d, 0x3d, 0xeb, 0xa8, - 0xc6, 0x06, 0xd0, 0xa5, 0xdb, 0x68, 0x84, 0xab, 0xdb, 0xff, 0x6f, 0x19, 0x7a, 0xdb, 0x71, 0x26, - 0xd3, 0x5c, 0x89, 0x70, 0x79, 0xe9, 0xaa, 0x45, 0x97, 0xae, 0x74, 0xbd, 0x55, 0x7d, 0x06, 0xd5, - 0x5b, 0xdf, 0x83, 0x8e, 0xbe, 0xde, 0xa7, 0x3d, 0xf4, 0x0b, 0xef, 0x06, 0x1a, 0x1a, 0xb6, 0x06, - 0x56, 0xa0, 0xef, 0x1d, 0xea, 0x7c, 0x63, 0xe5, 0x32, 0xa0, 0xb9, 0x91, 0xe8, 0x14, 0x34, 0xec, - 0x2d, 0x68, 0x78, 0xd3, 0x29, 0x69, 0x29, 0x2a, 0xc2, 0x18, 0x52, 0x32, 0x3a, 0x0e, 0xe2, 0xd8, - 0x5d, 0xe8, 0x92, 0xfa, 0xa4, 0x94, 0x7b, 0x7b, 0x71, 0x4e, 0x93, 0xcf, 0x57, 0x1a, 0x95, 0x9c, - 0xfb, 0xbb, 0xd0, 0x8d, 0x84, 0x48, 0xd4, 0x80, 0xce, 0xe2, 0x00, 0x93, 0x85, 0x75, 0xac, 0xc8, - 0xe4, 0x63, 0x6f, 0x43, 0x1b, 0xdd, 0x19, 0x91, 0x68, 0x37, 0xa0, 0xb2, 0x0e, 0xca, 0x46, 0x3a, - 0xad, 0x0c, 0xff, 0xb0, 0x75, 0x00, 0x25, 0xff, 0x34, 0x73, 0x77, 0x91, 0x1d, 0x45, 0xe2, 0x01, - 0x0f, 0xa9, 0xc9, 0x41, 0xdc, 0x87, 0x91, 0x0a, 0x32, 0x2b, 0x23, 0xc1, 0xd4, 0x17, 0xcd, 0xc8, - 0xf9, 0xbc, 0x85, 0x33, 0x4c, 0xe7, 0xf3, 0x18, 0xef, 0x40, 0x27, 0x51, 0x51, 0x16, 0x69, 0x98, - 0xde, 0xfa, 0x72, 0x39, 0x54, 0x87, 0x5f, 0x8e, 0xa1, 0x60, 0x3f, 0x84, 0xa1, 0xaa, 0x83, 0x4d, - 0x74, 0xb8, 0x41, 0x19, 0xee, 0xb9, 0x6b, 0x65, 0x73, 0xd1, 0x88, 0x33, 0x90, 0x73, 0xc1, 0xc9, - 0xf7, 0x60, 0x50, 0x5e, 0xf3, 0xf1, 0xbd, 0x98, 0xf4, 0x0e, 0xb9, 0xfd, 0x66, 0x78, 0xd5, 0xbb, - 0x74, 0xfa, 0xbc, 0xea, 0x6b, 0xae, 0x42, 0x5b, 0xd7, 0x66, 0x47, 0x34, 0xaa, 0x72, 0x0d, 0x5c, - 0x55, 0x63, 0x1c, 0x8d, 0x47, 0x5e, 0x96, 0x65, 0xa7, 0x31, 0x5b, 0xe4, 0x65, 0x51, 0x73, 0x72, - 0xba, 0x45, 0xb9, 0x89, 0x3d, 0x98, 0x2f, 0x83, 0xa9, 0x72, 0xcf, 0x25, 0x1a, 0xfa, 0xea, 0x05, - 0x43, 0x55, 0xd5, 0xc7, 0x59, 0x4a, 0x16, 0xaa, 0x69, 0xef, 0x82, 0x25, 0xd2, 0x80, 0xea, 0xf0, - 0x94, 0x94, 0x22, 0x7e, 0x52, 0xf5, 0x4f, 0xdd, 0x69, 0x24, 0xe5, 0xd1, 0x11, 0xaa, 0x83, 0x8e, - 0x45, 0x92, 0x8a, 0xcf, 0xb9, 0x2f, 0x95, 0x8a, 0xbb, 0x72, 0xde, 0xb1, 0xd0, 0x78, 0x52, 0x70, - 0x37, 0xa1, 0x63, 0x2a, 0xce, 0x57, 0xcf, 0x51, 0x1a, 0x14, 0xfb, 0x10, 0x96, 0xe6, 0x15, 0x5a, - 0x36, 0xbe, 0x76, 0x8e, 0x7a, 0x38, 0xa7, 0xbf, 0xd0, 0x1a, 0x6b, 0x6f, 0x69, 0x7c, 0xce, 0x59, - 0x55, 0x08, 0xf4, 0x67, 0xb5, 0x9f, 0xf5, 0xea, 0x79, 0x7f, 0x56, 0xfb, 0x5c, 0x63, 0xe8, 0x84, - 0xd9, 0xc3, 0x30, 0xcd, 0xe4, 0xf8, 0xba, 0xb1, 0x8e, 0xd4, 0x45, 0x2f, 0x2d, 0xcc, 0xd0, 0x4c, - 0x8c, 0x6f, 0x98, 0x5b, 0xb0, 0x64, 0x34, 0xee, 0x40, 0x5b, 0x57, 0xe3, 0x57, 0xce, 0x9d, 0x68, - 0x7d, 0x83, 0xc5, 0xd1, 0x14, 0xec, 0x9b, 0xd0, 0xa1, 0x52, 0xac, 0x48, 0xc6, 0x6f, 0x2d, 0x4a, - 0x80, 0xaa, 0x87, 0x3a, 0xed, 0x48, 0xd5, 0x45, 0xdf, 0x81, 0x8e, 0x71, 0x52, 0xec, 0x45, 0xa9, - 0xd6, 0xce, 0x8a, 0x63, 0x28, 0xd8, 0x2d, 0x68, 0xcd, 0x50, 0x8f, 0x8d, 0xbf, 0xb1, 0x78, 0x42, - 0x95, 0x7a, 0x53, 0x58, 0x76, 0x0f, 0x7a, 0x19, 0xf9, 0xa7, 0x4a, 0x74, 0x6f, 0x9a, 0x32, 0xe6, - 0xfc, 0xa5, 0x79, 0x12, 0x5c, 0xc8, 0x4a, 0x47, 0xf6, 0xff, 0xc0, 0xf5, 0x6a, 0x0d, 0xd4, 0x14, - 0x48, 0x75, 0x7c, 0x77, 0x8b, 0x66, 0x79, 0xeb, 0x02, 0x09, 0x9b, 0x2f, 0xa5, 0x3a, 0xd7, 0x92, - 0x17, 0xd4, 0x58, 0xef, 0x15, 0x56, 0x02, 0x0f, 0xe5, 0xf8, 0xf6, 0xb9, 0x65, 0x15, 0x76, 0xc6, - 0xd8, 0x0e, 0x32, 0x4f, 0x1f, 0x43, 0x7f, 0x92, 0x3f, 0x7f, 0x7e, 0xa6, 0x65, 0x64, 0xfc, 0x36, - 0x8d, 0xab, 0x44, 0x5a, 0x95, 0xb2, 0xab, 0xd3, 0x9b, 0x54, 0x6a, 0xb0, 0xd7, 0xa0, 0xe3, 0xc7, - 0xae, 0x17, 0x04, 0xe9, 0x78, 0x55, 0x95, 0x5d, 0xfd, 0x78, 0x23, 0x08, 0xe8, 0xfe, 0xbf, 0x48, - 0x38, 0x5d, 0xcc, 0x75, 0xc3, 0x60, 0xfc, 0x4d, 0x65, 0xaf, 0x0c, 0x68, 0x3b, 0xa0, 0x07, 0x02, - 0x26, 0x3c, 0x09, 0x83, 0xf1, 0x1d, 0xfd, 0x40, 0x40, 0x83, 0xb6, 0x03, 0xf4, 0x57, 0x67, 0xde, - 0xa9, 0x6b, 0x20, 0xe3, 0x77, 0x54, 0xcc, 0x3a, 0xf3, 0x4e, 0xf7, 0x35, 0x08, 0xcf, 0xb6, 0x4a, - 0x1f, 0x90, 0xb6, 0x7b, 0x77, 0xf1, 0x6c, 0x17, 0x69, 0x18, 0xa7, 0x1b, 0x16, 0x19, 0x19, 0xd2, - 0x07, 0xa4, 0xc1, 0xdc, 0x68, 0x7d, 0xfc, 0xde, 0x79, 0x7d, 0xa0, 0xb3, 0x4c, 0xa8, 0x0f, 0x4c, - 0xc2, 0x69, 0x1d, 0x40, 0xa9, 0x3a, 0xda, 0xec, 0xb5, 0xc5, 0x31, 0x45, 0x10, 0xe1, 0xa8, 0x1b, - 0x47, 0xb4, 0xd5, 0xeb, 0x00, 0x74, 0x75, 0x49, 0x8d, 0xb9, 0xbb, 0x38, 0xa6, 0x08, 0x0a, 0x9c, - 0xee, 0xd3, 0x22, 0x3e, 0xb8, 0x0b, 0xdd, 0x1c, 0xdd, 0x7f, 0x74, 0xc0, 0xc7, 0xef, 0x2f, 0x9e, - 0x01, 0x13, 0x19, 0x38, 0x56, 0xae, 0x5b, 0xf8, 0x23, 0x64, 0xb2, 0xc8, 0x7b, 0x19, 0x7f, 0xb0, - 0xf8, 0x23, 0x45, 0xf8, 0xe0, 0x90, 0x65, 0x53, 0x91, 0xc4, 0x3d, 0xe8, 0x29, 0xa6, 0xa9, 0x41, - 0xeb, 0x8b, 0x32, 0x52, 0xba, 0x43, 0x8e, 0xe2, 0xae, 0x1a, 0x76, 0x0b, 0x5a, 0x5e, 0x92, 0x44, - 0x67, 0xe3, 0x0f, 0x17, 0x0f, 0xc6, 0x06, 0x82, 0x1d, 0x85, 0x45, 0x51, 0x9a, 0xe5, 0x91, 0x0c, - 0xcd, 0x25, 0xa1, 0x8f, 0x16, 0x45, 0xa9, 0x72, 0x87, 0xd2, 0xe9, 0xcd, 0x2a, 0x17, 0x2a, 0xdf, - 0x05, 0x2b, 0x11, 0x99, 0x74, 0x83, 0x59, 0x34, 0xbe, 0x77, 0xce, 0xfa, 0xa8, 0xcb, 0x31, 0x4e, - 0x27, 0xd1, 0xb7, 0x8b, 0xe6, 0x6e, 0xf6, 0x7e, 0x6b, 0xfe, 0x66, 0xef, 0x4f, 0x9b, 0xd6, 0xf2, - 0x88, 0xd9, 0xf7, 0xa0, 0xbf, 0x41, 0x0f, 0x75, 0xc2, 0x8c, 0x34, 0xe6, 0x2d, 0x68, 0x16, 0x29, - 0xc3, 0x42, 0x15, 0x13, 0xc5, 0x73, 0xbe, 0x1d, 0x4f, 0x84, 0x43, 0x68, 0xfb, 0x6f, 0x9a, 0xd0, - 0x3e, 0x10, 0x79, 0xea, 0xf3, 0x2f, 0xbe, 0x63, 0xf6, 0xba, 0x11, 0x8c, 0xb8, 0xbc, 0x78, 0xa0, - 0x64, 0x80, 0xd0, 0x8b, 0x25, 0xd3, 0x6e, 0x99, 0x8d, 0xbc, 0x0c, 0x2d, 0x15, 0x04, 0xaa, 0xbb, - 0x49, 0xaa, 0x43, 0x87, 0x22, 0xcf, 0x8e, 0xe9, 0x35, 0x4e, 0xa8, 0xae, 0xb1, 0x37, 0x1d, 0x30, - 0xa0, 0xed, 0x80, 0x82, 0x7a, 0x43, 0x40, 0xa7, 0xae, 0xad, 0x22, 0x01, 0x03, 0xa4, 0xb3, 0x67, - 0x32, 0x9d, 0x9d, 0x17, 0x64, 0x3a, 0xdf, 0x80, 0x66, 0x6c, 0xee, 0xc4, 0x14, 0x78, 0x7a, 0x3c, - 0x41, 0x70, 0x76, 0x07, 0x8a, 0x8b, 0x71, 0xda, 0xf9, 0x78, 0xf1, 0xc5, 0xb9, 0x75, 0xe8, 0x16, - 0x4f, 0xbb, 0xb4, 0xbf, 0x71, 0x79, 0xad, 0x7c, 0xec, 0x75, 0x68, 0x5a, 0x4e, 0x49, 0xf6, 0xf2, - 0x7c, 0x5d, 0xef, 0x6b, 0xe5, 0xeb, 0x74, 0x30, 0xe6, 0x8b, 0x38, 0x93, 0x3a, 0x6d, 0xd1, 0x09, - 0xb3, 0x4d, 0xec, 0xb2, 0xef, 0xc0, 0x20, 0xe5, 0xfe, 0x53, 0x77, 0x96, 0x4d, 0xd5, 0x4f, 0x0c, - 0xaa, 0x57, 0x6d, 0x67, 0xd9, 0xf4, 0x13, 0xca, 0x25, 0xea, 0xd8, 0xa8, 0x87, 0xb4, 0xbb, 0xd9, - 0x94, 0x66, 0x7d, 0x07, 0x96, 0x67, 0x7c, 0x76, 0xc4, 0xd3, 0xec, 0x38, 0x4c, 0x8c, 0x76, 0x1c, - 0x52, 0xce, 0x73, 0x54, 0x22, 0xd4, 0x5a, 0xec, 0xdf, 0xaf, 0x81, 0x85, 0x5c, 0x44, 0x59, 0x62, - 0x0c, 0x9a, 0x33, 0x3f, 0xc9, 0xb5, 0xcb, 0x4b, 0x6d, 0xfd, 0x5c, 0x4c, 0x49, 0x89, 0x7e, 0x2e, - 0x46, 0x7b, 0xd8, 0x50, 0xa9, 0x44, 0x6c, 0xab, 0x07, 0x1b, 0x67, 0x94, 0xaf, 0x51, 0x92, 0x61, - 0xba, 0xec, 0x0a, 0xb4, 0xfd, 0x98, 0xe2, 0x5e, 0x75, 0x53, 0xaa, 0xe5, 0xc7, 0x18, 0xef, 0x2a, - 0x70, 0x79, 0x41, 0xa3, 0xe5, 0xc7, 0xdb, 0xc1, 0xa9, 0xfd, 0x97, 0x35, 0x58, 0xde, 0x4f, 0x85, - 0xcf, 0xb3, 0x6c, 0x07, 0x4d, 0xb6, 0x47, 0x3e, 0x17, 0x83, 0x26, 0xe5, 0xdb, 0xd4, 0xeb, 0x07, - 0x6a, 0xa3, 0x0c, 0xab, 0xa4, 0x44, 0x11, 0x58, 0x34, 0x9c, 0x2e, 0x41, 0x28, 0xae, 0x28, 0xd0, - 0x34, 0xb0, 0x51, 0x41, 0x53, 0xa6, 0xee, 0x16, 0x0c, 0xcb, 0x6b, 0x4b, 0x95, 0xe4, 0x61, 0x79, - 0x99, 0x9c, 0x66, 0x79, 0x13, 0x7a, 0x3a, 0xc5, 0x4b, 0xd3, 0xa8, 0x44, 0x22, 0x28, 0x10, 0xce, - 0x63, 0x1f, 0xc3, 0x68, 0x3f, 0xe5, 0x89, 0x97, 0x72, 0xca, 0xe9, 0x12, 0x0f, 0xaf, 0x42, 0x3b, - 0xe2, 0xf1, 0x54, 0x1e, 0xeb, 0xf5, 0xea, 0x5e, 0xf1, 0x94, 0xaf, 0x5e, 0x79, 0xca, 0x87, 0xbc, - 0x4c, 0xb9, 0xa7, 0x5f, 0xfc, 0x51, 0x1b, 0xcf, 0x18, 0x46, 0x7f, 0x2a, 0xc4, 0xb1, 0x1c, 0xd5, - 0xb1, 0xff, 0xbe, 0x01, 0x3d, 0xcd, 0x19, 0xfa, 0x15, 0xb5, 0x2b, 0xb5, 0x62, 0x57, 0x46, 0xd0, - 0xc8, 0x9e, 0x44, 0x7a, 0x9b, 0xb0, 0xc9, 0x3e, 0x84, 0x46, 0x14, 0xce, 0x74, 0x58, 0x72, 0x63, - 0xce, 0x56, 0xcc, 0xf3, 0x57, 0x8b, 0x10, 0x52, 0xa3, 0x82, 0xa2, 0x7b, 0xeb, 0x28, 0xac, 0x9a, - 0x27, 0xa8, 0xb7, 0x4f, 0xf1, 0x44, 0x20, 0x53, 0x3d, 0x9f, 0x6e, 0x7e, 0x9a, 0x63, 0x3e, 0x70, - 0xba, 0x1a, 0xb2, 0x1d, 0xb0, 0x8f, 0xc0, 0xca, 0x62, 0x2f, 0xc9, 0x8e, 0x85, 0x2c, 0x02, 0x11, - 0x79, 0x1a, 0xaf, 0x6d, 0xee, 0x1d, 0x9e, 0xc6, 0x07, 0x1a, 0xa3, 0x7f, 0xac, 0xa0, 0x64, 0x3f, - 0x84, 0x7e, 0xc6, 0xb3, 0x4c, 0x5d, 0x45, 0x9e, 0x08, 0x7d, 0xfc, 0xaf, 0x54, 0x63, 0x0c, 0xc2, - 0xe2, 0x57, 0x1b, 0x61, 0xcf, 0x4a, 0x10, 0xfb, 0x04, 0x86, 0x66, 0x7c, 0x24, 0xa6, 0xd3, 0x22, - 0x59, 0x79, 0xe3, 0xdc, 0x0c, 0x3b, 0x84, 0xae, 0xcc, 0x33, 0xc8, 0xaa, 0x08, 0xf6, 0x13, 0x18, - 0x26, 0x6a, 0x33, 0x5d, 0x5d, 0x27, 0x50, 0x6a, 0xe4, 0xfa, 0x9c, 0x6b, 0x33, 0xb7, 0xd9, 0xe5, - 0xf5, 0xc2, 0x12, 0x9e, 0x9d, 0xbf, 0x64, 0x0f, 0xc4, 0xc8, 0xb9, 0x4b, 0xf6, 0xf6, 0x1f, 0xd5, - 0xa1, 0x57, 0xf9, 0x34, 0x7a, 0x85, 0x99, 0xf1, 0xd4, 0x64, 0xe8, 0xb1, 0x8d, 0xb0, 0x63, 0xa1, - 0x1f, 0xf9, 0x74, 0x1d, 0x6a, 0x23, 0x2c, 0x15, 0xba, 0x1e, 0xd5, 0x75, 0xa8, 0x8d, 0x3f, 0xa8, - 0x23, 0x4c, 0xf5, 0x0c, 0x82, 0x76, 0xae, 0xe9, 0xf4, 0x4b, 0xe0, 0x76, 0x40, 0xcf, 0x35, 0x3d, - 0xe9, 0x1d, 0x79, 0x99, 0x29, 0x75, 0x14, 0x7d, 0x3c, 0xbf, 0x4f, 0x79, 0x8a, 0x6b, 0xd1, 0xaa, - 0xd9, 0x74, 0x51, 0x20, 0x48, 0xe5, 0x3d, 0x17, 0xb1, 0x7a, 0x29, 0xd3, 0x77, 0x2c, 0x04, 0x7c, - 0x26, 0x62, 0x1a, 0xa6, 0xb7, 0x9f, 0x98, 0xde, 0x75, 0x4c, 0x17, 0x15, 0xdb, 0x93, 0x9c, 0xa3, - 0x8f, 0x18, 0xd0, 0x65, 0xa9, 0xae, 0xd3, 0xa1, 0xfe, 0x76, 0xc0, 0xee, 0x00, 0xdd, 0x38, 0x74, - 0x9f, 0x79, 0xa1, 0x24, 0x39, 0x13, 0xb9, 0xd4, 0x1c, 0x5a, 0x42, 0xc4, 0xa7, 0x5e, 0x28, 0x0f, - 0x15, 0xd8, 0xfe, 0xd7, 0x1a, 0x2c, 0x9f, 0xdb, 0x3d, 0x74, 0xdf, 0x70, 0xe7, 0xcc, 0x35, 0xd2, - 0xbe, 0xd3, 0xc6, 0xee, 0x76, 0x40, 0x08, 0x39, 0x23, 0xe9, 0xac, 0x6b, 0x84, 0x9c, 0xa1, 0x68, - 0x5e, 0x81, 0xb6, 0x3c, 0x25, 0xce, 0xa8, 0x93, 0xd6, 0x92, 0xa7, 0xc8, 0x92, 0x0d, 0x0c, 0x85, - 0xa7, 0x6e, 0xc4, 0x9f, 0xf2, 0x88, 0x78, 0x36, 0x5c, 0xbf, 0xf9, 0x12, 0xb1, 0x59, 0xdb, 0x11, - 0xd3, 0x1d, 0xa4, 0xc5, 0xe0, 0x58, 0xb5, 0xec, 0x9f, 0x82, 0x65, 0xa0, 0xac, 0x0b, 0xad, 0x2d, - 0x7e, 0x94, 0x4f, 0x47, 0xaf, 0x30, 0x0b, 0x9a, 0x38, 0x62, 0x54, 0xc3, 0xd6, 0xa7, 0x5e, 0x1a, - 0x8f, 0xea, 0x88, 0x7e, 0x90, 0xa6, 0x22, 0x1d, 0x35, 0xb0, 0xb9, 0xef, 0xc5, 0xa1, 0x3f, 0x6a, - 0x62, 0xf3, 0xa1, 0x27, 0xbd, 0x68, 0xd4, 0xb2, 0x7f, 0xd1, 0x02, 0x6b, 0x5f, 0xff, 0x3a, 0xdb, - 0x82, 0x41, 0xf1, 0x14, 0xf5, 0xe2, 0xf4, 0xcb, 0xfe, 0x62, 0x83, 0xd2, 0x2f, 0xfd, 0xa4, 0xd2, - 0x5b, 0x7c, 0xd0, 0x5a, 0x3f, 0xf7, 0xa0, 0xf5, 0x35, 0x68, 0x3c, 0x49, 0xcf, 0xe6, 0xcb, 0x8b, - 0xfb, 0x91, 0x17, 0x3b, 0x08, 0x66, 0x1f, 0x40, 0x0f, 0x65, 0xc4, 0xcd, 0xc8, 0xb3, 0xd0, 0x29, - 0x8b, 0xea, 0x03, 0x67, 0x82, 0x3b, 0x80, 0x44, 0xda, 0xfb, 0x58, 0x03, 0xcb, 0x3f, 0x0e, 0xa3, - 0x20, 0xe5, 0xb1, 0x2e, 0xdd, 0xb3, 0xf3, 0x4b, 0x76, 0x0a, 0x1a, 0xf6, 0x63, 0x18, 0x85, 0x65, - 0xca, 0xa5, 0xac, 0x5b, 0xcc, 0xe9, 0x80, 0x4a, 0x52, 0xc6, 0x59, 0xaa, 0x90, 0x93, 0xb9, 0x2b, - 0xef, 0xf7, 0x77, 0xaa, 0xf7, 0xfb, 0xd5, 0xb3, 0x45, 0xb2, 0x49, 0x56, 0x11, 0xb0, 0xa1, 0x49, - 0xba, 0xad, 0x1d, 0x89, 0xee, 0xa2, 0xab, 0x6a, 0xcc, 0xa0, 0x76, 0x28, 0x6e, 0xc2, 0x10, 0x1d, - 0x14, 0x57, 0xf9, 0x35, 0xa8, 0x9b, 0x40, 0x3f, 0x2e, 0xca, 0xb3, 0xe3, 0x2d, 0xf4, 0x6c, 0x50, - 0x18, 0x6f, 0xc1, 0xd0, 0x7c, 0x8b, 0xbe, 0x15, 0xdf, 0xd3, 0x75, 0x0d, 0x0d, 0x55, 0x37, 0xe2, - 0xd7, 0xe0, 0x92, 0x7f, 0xec, 0xc5, 0x31, 0x8f, 0xdc, 0xa3, 0x7c, 0x32, 0x31, 0x26, 0xa5, 0x4f, - 0x19, 0xc1, 0x65, 0x8d, 0xba, 0x4f, 0x18, 0xb2, 0x50, 0x36, 0x0c, 0xe2, 0x30, 0x52, 0x69, 0x6f, - 0x32, 0x9f, 0x03, 0xa2, 0xec, 0xc5, 0x61, 0x44, 0x79, 0x6f, 0x34, 0xa2, 0x3f, 0x82, 0x51, 0x9e, - 0x87, 0x41, 0xe6, 0x4a, 0x61, 0x5e, 0x7c, 0xea, 0xe4, 0x69, 0x25, 0x1d, 0xf1, 0x38, 0x0f, 0x83, - 0x43, 0xa1, 0xdf, 0x7c, 0x0e, 0x88, 0xde, 0x74, 0xed, 0x1f, 0x41, 0xbf, 0x2a, 0x3b, 0x28, 0x8b, - 0x14, 0x2f, 0x8e, 0x5e, 0x61, 0x00, 0xed, 0x3d, 0x91, 0xce, 0xbc, 0x68, 0x54, 0xc3, 0xb6, 0x7a, - 0xf5, 0x32, 0xaa, 0xb3, 0x3e, 0x58, 0x26, 0x90, 0x19, 0x35, 0xec, 0xef, 0x81, 0x65, 0x9e, 0xb0, - 0xd2, 0xdb, 0x41, 0x11, 0x70, 0xe5, 0xe0, 0x29, 0x2d, 0x66, 0x21, 0x80, 0x9c, 0x3b, 0xf3, 0xc6, - 0xbc, 0x5e, 0xbe, 0x31, 0xb7, 0xff, 0x17, 0xf4, 0xab, 0x8b, 0x33, 0xd9, 0xb5, 0x5a, 0x99, 0x5d, - 0xbb, 0x60, 0x14, 0x15, 0xb8, 0x52, 0x31, 0x73, 0x2b, 0x3e, 0x88, 0x85, 0x00, 0xfc, 0x19, 0xfb, - 0xf7, 0x6a, 0xd0, 0x22, 0xc7, 0x9e, 0x6c, 0x15, 0x36, 0xca, 0xb3, 0xd3, 0x72, 0xba, 0x04, 0xf9, - 0x2f, 0xdc, 0x18, 0x2c, 0xaa, 0x2d, 0xcd, 0x97, 0x56, 0x5b, 0xee, 0xfc, 0x69, 0x0d, 0xda, 0xea, - 0x5d, 0x3f, 0x5b, 0x86, 0xc1, 0xe3, 0xf8, 0x24, 0x16, 0xcf, 0x62, 0x05, 0x18, 0xbd, 0xc2, 0x2e, - 0xc1, 0x92, 0xe1, 0xba, 0xfe, 0x07, 0x02, 0xa3, 0x1a, 0x1b, 0x41, 0x9f, 0xf6, 0xd5, 0x40, 0xea, - 0xec, 0x35, 0x18, 0x6b, 0x73, 0xb3, 0x25, 0x62, 0xbe, 0x27, 0x64, 0x38, 0x39, 0x33, 0xd8, 0x06, - 0x5b, 0x82, 0xde, 0x81, 0x14, 0xc9, 0x01, 0x8f, 0x83, 0x30, 0x9e, 0x8e, 0x9a, 0x6c, 0x0c, 0x97, - 0xcd, 0xac, 0x2a, 0x8c, 0x7f, 0x18, 0xc6, 0x61, 0x76, 0x3c, 0x6a, 0xb1, 0x1b, 0x70, 0xed, 0x22, - 0xcc, 0x86, 0x7f, 0x32, 0x6a, 0xdf, 0xf9, 0x08, 0xd8, 0xf9, 0xa7, 0xf2, 0x38, 0xfb, 0x0e, 0x9f, - 0x7a, 0xfe, 0xd9, 0x66, 0x24, 0x32, 0x14, 0x87, 0x01, 0x74, 0xcb, 0x51, 0xb5, 0x3b, 0x0f, 0xa1, - 0xad, 0xfe, 0xb7, 0x41, 0xe5, 0xfb, 0x14, 0x60, 0xf4, 0x0a, 0x0e, 0x46, 0x1d, 0x1e, 0xc6, 0xd3, - 0x3d, 0x7e, 0x2a, 0x95, 0x0a, 0xdc, 0xf1, 0x32, 0x39, 0xaa, 0xb3, 0x21, 0x80, 0xfe, 0x84, 0x07, - 0x71, 0x30, 0x6a, 0xdc, 0xdf, 0xfc, 0xe5, 0xaf, 0xde, 0xa8, 0xfd, 0xc3, 0xaf, 0xde, 0xa8, 0xfd, - 0xcb, 0xaf, 0xde, 0x78, 0xe5, 0xe7, 0xbf, 0x7e, 0xa3, 0xf6, 0xd9, 0x07, 0x95, 0xff, 0xdc, 0x30, - 0xf3, 0x64, 0x1a, 0x9e, 0xaa, 0x82, 0xa4, 0xe9, 0xc4, 0xfc, 0x6e, 0x72, 0x32, 0xbd, 0x9b, 0x1c, - 0xdd, 0x35, 0x12, 0x7e, 0xd4, 0xa6, 0x7f, 0xc8, 0xf0, 0xe1, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, - 0xe5, 0x4a, 0x8e, 0x5e, 0x0f, 0x42, 0x00, 0x00, + // 6295 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7c, 0xcb, 0x6e, 0x1c, 0x49, + 0x76, 0x68, 0xd7, 0x3b, 0xeb, 0xd4, 0x83, 0xc5, 0xd0, 0xab, 0x5a, 0xea, 0x07, 0x3b, 0x47, 0x52, + 0x73, 0xd4, 0xdd, 0x54, 0x37, 0xbb, 0x35, 0xd3, 0xf3, 0x1e, 0x8a, 0x94, 0xa6, 0x39, 0x43, 0x52, + 0xbc, 0x49, 0xea, 0x36, 0xd0, 0x8b, 0x9b, 0x48, 0x66, 0x46, 0x15, 0xb3, 0x99, 0x95, 0x91, 0xca, + 0x8c, 0x94, 0x48, 0x6d, 0xee, 0xbd, 0xb8, 0x77, 0xe5, 0x1f, 0x30, 0xe0, 0xd5, 0xc0, 0x30, 0xe0, + 0x17, 0x8c, 0x59, 0x18, 0xf6, 0x1f, 0x18, 0x18, 0x78, 0x61, 0x78, 0xe5, 0x85, 0x17, 0x86, 0x31, + 0xb3, 0x34, 0xe0, 0x9d, 0x81, 0xd9, 0x18, 0x30, 0xce, 0x89, 0x88, 0xcc, 0xac, 0x22, 0xa5, 0x7e, + 0xd8, 0x98, 0x8d, 0x67, 0xc5, 0x88, 0x73, 0x4e, 0x44, 0x45, 0x9e, 0x38, 0x71, 0x9e, 0x11, 0x84, + 0x61, 0x12, 0x26, 0x3c, 0x0a, 0x63, 0xbe, 0x96, 0xa4, 0x42, 0x0a, 0x66, 0x99, 0xfe, 0xf5, 0xf7, + 0xa6, 0xa1, 0x3c, 0xce, 0x8f, 0xd6, 0x7c, 0x31, 0xbb, 0x3b, 0x15, 0x53, 0x71, 0x97, 0x08, 0x8e, + 0xf2, 0x09, 0xf5, 0xa8, 0x43, 0x2d, 0x35, 0xf0, 0x3a, 0x44, 0xc2, 0x3f, 0x31, 0xed, 0x24, 0xf2, + 0x62, 0xdd, 0x5e, 0x92, 0xe1, 0x8c, 0x67, 0xd2, 0x9b, 0x25, 0x1a, 0xd0, 0x95, 0xa7, 0x1a, 0x67, + 0xff, 0x4d, 0x03, 0x3a, 0xbb, 0x3c, 0xcb, 0xbc, 0x29, 0x67, 0x36, 0x34, 0xb2, 0x30, 0x18, 0xd7, + 0x56, 0x6a, 0xab, 0xc3, 0xf5, 0xd1, 0x5a, 0xb1, 0xac, 0x03, 0xe9, 0xc9, 0x3c, 0x73, 0x10, 0x89, + 0x34, 0xfe, 0x2c, 0x18, 0xd7, 0x17, 0x69, 0x76, 0xb9, 0x3c, 0x16, 0x81, 0x83, 0x48, 0x36, 0x82, + 0x06, 0x4f, 0xd3, 0x71, 0x63, 0xa5, 0xb6, 0xda, 0x77, 0xb0, 0xc9, 0x18, 0x34, 0x03, 0x4f, 0x7a, + 0xe3, 0x26, 0x81, 0xa8, 0xcd, 0x6e, 0xc2, 0x30, 0x49, 0x85, 0xef, 0x86, 0xf1, 0x44, 0xb8, 0x84, + 0x6d, 0x11, 0xb6, 0x8f, 0xd0, 0xed, 0x78, 0x22, 0xb6, 0x90, 0x6a, 0x0c, 0x1d, 0x2f, 0xf6, 0xa2, + 0xb3, 0x8c, 0x8f, 0xdb, 0x84, 0x36, 0x5d, 0x36, 0x84, 0x7a, 0x18, 0x8c, 0x3b, 0x2b, 0xb5, 0xd5, + 0xa6, 0x53, 0x0f, 0x03, 0xfc, 0x8d, 0x3c, 0x0f, 0x83, 0xb1, 0xa5, 0x7e, 0x03, 0xdb, 0xcc, 0x86, + 0x7e, 0xcc, 0x79, 0xb0, 0x27, 0xa4, 0xc3, 0x93, 0xe8, 0x6c, 0xdc, 0x5d, 0xa9, 0xad, 0x5a, 0xce, + 0x1c, 0x8c, 0x5d, 0x07, 0x2b, 0xe0, 0x47, 0xf9, 0x74, 0x37, 0x9b, 0x8e, 0x61, 0xa5, 0xb6, 0xda, + 0x75, 0x8a, 0x3e, 0x3b, 0x84, 0x6b, 0x29, 0x7f, 0x92, 0xf3, 0x4c, 0xf2, 0xc0, 0x95, 0xdc, 0x4b, + 0x03, 0xf1, 0x2c, 0x76, 0x67, 0x22, 0xe0, 0xe3, 0x1e, 0x71, 0xe0, 0xb5, 0x2a, 0x97, 0x52, 0xee, + 0xcd, 0x0e, 0x35, 0xd1, 0xae, 0x08, 0xb8, 0x73, 0xa5, 0x18, 0x5c, 0x05, 0x33, 0x07, 0xae, 0x7a, + 0xbe, 0xcf, 0x93, 0xf3, 0x93, 0xf6, 0xbf, 0xc4, 0xa4, 0x97, 0xcd, 0xd8, 0x2a, 0xd4, 0x7e, 0x0c, + 0xdd, 0x4d, 0x11, 0xc7, 0xdc, 0x97, 0x22, 0x65, 0x6f, 0x42, 0xcf, 0xcc, 0xe0, 0xea, 0x0d, 0x6d, + 0x39, 0x60, 0x40, 0xdb, 0x01, 0x7b, 0x1b, 0x96, 0x7c, 0x43, 0xed, 0x86, 0x71, 0xc0, 0x4f, 0x69, + 0x47, 0x5b, 0xce, 0xb0, 0x00, 0x6f, 0x23, 0xd4, 0xfe, 0x83, 0x06, 0x74, 0x0e, 0x8e, 0xf3, 0xc9, + 0x24, 0xe2, 0xec, 0x26, 0x0c, 0x74, 0x73, 0x53, 0x44, 0xdb, 0xc1, 0xa9, 0x9e, 0x77, 0x1e, 0xc8, + 0x56, 0xa0, 0xa7, 0x01, 0x87, 0x67, 0x09, 0xd7, 0xd3, 0x56, 0x41, 0xf3, 0xf3, 0xec, 0x86, 0x31, + 0x09, 0x4a, 0xc3, 0x99, 0x07, 0x2e, 0x50, 0x79, 0xa7, 0x24, 0x3b, 0xf3, 0x54, 0x1e, 0xfd, 0xda, + 0x46, 0x14, 0x3e, 0xe5, 0x0e, 0x9f, 0x6e, 0xc6, 0x92, 0x24, 0xa8, 0xe5, 0x54, 0x41, 0x6c, 0x1d, + 0xae, 0x64, 0x6a, 0x88, 0x9b, 0x7a, 0xf1, 0x94, 0x67, 0x6e, 0x1e, 0xc6, 0xf2, 0x5b, 0x1f, 0x8d, + 0xdb, 0x2b, 0x8d, 0xd5, 0xa6, 0x73, 0x49, 0x23, 0x1d, 0xc2, 0x3d, 0x26, 0x14, 0x7b, 0x1f, 0x2e, + 0x2f, 0x8c, 0x51, 0x43, 0x3a, 0x2b, 0x8d, 0xd5, 0x86, 0xc3, 0xe6, 0x86, 0x6c, 0xd3, 0x88, 0x07, + 0xb0, 0x9c, 0xe6, 0x31, 0x9e, 0xb3, 0x87, 0x61, 0x24, 0x79, 0x7a, 0x90, 0x70, 0x9f, 0x24, 0xb1, + 0xb7, 0x7e, 0x6d, 0x8d, 0x8e, 0xa2, 0xb3, 0x88, 0x76, 0xce, 0x8f, 0x60, 0xef, 0x16, 0xcc, 0x7b, + 0x70, 0x9a, 0xa4, 0x24, 0xae, 0xbd, 0x75, 0x50, 0x13, 0x20, 0xc4, 0xa9, 0xa2, 0xed, 0xdf, 0xd4, + 0xc1, 0xda, 0x0a, 0xb3, 0xc4, 0x93, 0xfe, 0x31, 0xbb, 0x06, 0x9d, 0x49, 0x1e, 0xfb, 0xe5, 0x7e, + 0xb7, 0xb1, 0xbb, 0x1d, 0xb0, 0xef, 0xc3, 0x52, 0x24, 0x7c, 0x2f, 0x72, 0x8b, 0xad, 0x1d, 0xd7, + 0x57, 0x1a, 0xab, 0xbd, 0xf5, 0x4b, 0xa5, 0x98, 0x15, 0xa2, 0xe3, 0x0c, 0x89, 0xb6, 0x14, 0xa5, + 0x1f, 0xc0, 0x28, 0xe5, 0x33, 0x21, 0x79, 0x65, 0x78, 0x83, 0x86, 0xb3, 0x72, 0xf8, 0xa7, 0xa9, + 0x97, 0xec, 0xa1, 0x6c, 0x2e, 0x29, 0xda, 0x72, 0xf8, 0x07, 0x15, 0xee, 0xf3, 0xa9, 0x1b, 0x06, + 0xa7, 0x2e, 0xfd, 0xc0, 0xb8, 0xb9, 0xd2, 0x58, 0x6d, 0x95, 0xac, 0xe4, 0xd3, 0xed, 0xe0, 0x74, + 0x07, 0x31, 0xec, 0x43, 0xb8, 0xba, 0x38, 0x44, 0xcd, 0x3a, 0x6e, 0xd1, 0x98, 0x4b, 0x73, 0x63, + 0x1c, 0x42, 0xb1, 0xb7, 0xa0, 0x6f, 0x06, 0x49, 0x14, 0xbb, 0xb6, 0x12, 0x84, 0xac, 0x22, 0x76, + 0xd7, 0xa0, 0x13, 0x66, 0x6e, 0x16, 0xc6, 0x27, 0xa4, 0x34, 0x2c, 0xa7, 0x1d, 0x66, 0x07, 0x61, + 0x7c, 0xc2, 0x5e, 0x05, 0x2b, 0xe5, 0xbe, 0xc2, 0x58, 0x84, 0xe9, 0xa4, 0xdc, 0x27, 0xd4, 0x35, + 0xc0, 0xa6, 0xeb, 0x4b, 0xae, 0x55, 0x47, 0x3b, 0xe5, 0xfe, 0xa6, 0xe4, 0x76, 0x06, 0xad, 0x5d, + 0x9e, 0x4e, 0x39, 0x6a, 0x0f, 0x1c, 0x78, 0xe0, 0x7b, 0x31, 0xf1, 0xdd, 0x72, 0x8a, 0x3e, 0xea, + 0xae, 0xc4, 0x4b, 0x65, 0xe8, 0x45, 0x74, 0x0c, 0x2c, 0xc7, 0x74, 0xd9, 0x0d, 0xe8, 0x66, 0xd2, + 0x4b, 0x25, 0x7e, 0x1d, 0x89, 0x7f, 0xcb, 0xb1, 0x08, 0x80, 0x27, 0xe8, 0x1a, 0x74, 0x78, 0x1c, + 0x10, 0xaa, 0xa9, 0x76, 0x92, 0xc7, 0xc1, 0x76, 0x70, 0x6a, 0xff, 0x65, 0x0d, 0x06, 0xbb, 0x79, + 0x24, 0xc3, 0x8d, 0x74, 0x9a, 0xf3, 0x59, 0x2c, 0x51, 0xe7, 0x6d, 0x85, 0x99, 0xd4, 0xbf, 0x4c, + 0x6d, 0xb6, 0x0a, 0xdd, 0x9f, 0xa4, 0x22, 0x4f, 0x48, 0x82, 0xd4, 0x4e, 0x57, 0x25, 0xa8, 0x44, + 0xa2, 0xb4, 0x3d, 0x4a, 0x03, 0x9e, 0xde, 0x3f, 0x23, 0xda, 0xc6, 0x39, 0xda, 0x2a, 0x9a, 0xbd, + 0x06, 0xdd, 0x03, 0x9e, 0x78, 0xa9, 0x87, 0x22, 0xd0, 0x24, 0x45, 0x59, 0x02, 0xf0, 0x5b, 0x89, + 0x78, 0x3b, 0xd0, 0x87, 0xd0, 0x74, 0xed, 0x29, 0x74, 0x37, 0xa6, 0xd3, 0x94, 0x4f, 0x3d, 0x49, + 0x4a, 0x5b, 0x24, 0xb4, 0xdc, 0x86, 0x53, 0x17, 0x09, 0x19, 0x06, 0xfc, 0x00, 0xc5, 0x1f, 0x6a, + 0xb3, 0x37, 0xa0, 0xc9, 0x2f, 0x5e, 0x0f, 0xc1, 0xd9, 0x55, 0x68, 0xfb, 0x22, 0x9e, 0x84, 0x53, + 0x6d, 0x4e, 0x74, 0xcf, 0xfe, 0xb3, 0x06, 0xb4, 0xe8, 0xe3, 0x90, 0xbd, 0xa8, 0xe2, 0x5d, 0xfe, + 0xd4, 0x8b, 0xcc, 0xae, 0x20, 0xe0, 0xc1, 0x53, 0x2f, 0x62, 0x2b, 0xd0, 0xc2, 0x69, 0xb2, 0x0b, + 0x78, 0xa3, 0x10, 0xec, 0x36, 0xb4, 0x50, 0x88, 0xb2, 0xf9, 0x15, 0xa0, 0x10, 0xdd, 0x6f, 0xfe, + 0xf2, 0x9f, 0xde, 0x7c, 0xc5, 0x51, 0x68, 0xf6, 0x36, 0x34, 0xbd, 0xe9, 0x34, 0x23, 0x59, 0x9e, + 0x3b, 0x4e, 0xc5, 0xf7, 0x3a, 0x44, 0xc0, 0xee, 0x41, 0x57, 0xed, 0x1b, 0x52, 0xb7, 0x88, 0xfa, + 0x5a, 0xc5, 0x74, 0x56, 0xb7, 0xd4, 0x29, 0x29, 0x91, 0xe3, 0x61, 0xa6, 0x0f, 0x3c, 0x49, 0xb4, + 0xe5, 0x94, 0x00, 0xb4, 0x6d, 0x49, 0xca, 0x37, 0xa2, 0x48, 0xf8, 0x07, 0xe1, 0x73, 0xae, 0x2d, + 0xe1, 0x1c, 0x8c, 0xdd, 0x86, 0xe1, 0xbe, 0x12, 0x39, 0x87, 0x67, 0x79, 0x24, 0x33, 0x6d, 0x1d, + 0x17, 0xa0, 0x6c, 0x0d, 0xd8, 0x1c, 0xe4, 0x90, 0x3e, 0xbf, 0xbb, 0xd2, 0x58, 0x1d, 0x38, 0x17, + 0x60, 0xd8, 0x37, 0x60, 0x30, 0x45, 0x4e, 0x87, 0xf1, 0xd4, 0x9d, 0x44, 0x1e, 0x1a, 0xce, 0x06, + 0x1a, 0x56, 0x03, 0x7c, 0x18, 0x79, 0x53, 0x12, 0xf2, 0x24, 0x8c, 0x22, 0x77, 0xc6, 0x67, 0x64, + 0x2e, 0x1b, 0x8e, 0x45, 0x80, 0x5d, 0x3e, 0xb3, 0xff, 0xbc, 0x09, 0xed, 0xed, 0x38, 0xe3, 0xa9, + 0xc4, 0x23, 0xe4, 0x4d, 0x26, 0xdc, 0x97, 0x5c, 0xa9, 0xae, 0xa6, 0x53, 0xf4, 0x91, 0x05, 0x87, + 0xe2, 0xd3, 0x34, 0x94, 0xfc, 0xe0, 0x43, 0x2d, 0x24, 0x25, 0x80, 0xdd, 0x81, 0x65, 0x2f, 0x08, + 0x5c, 0x43, 0xed, 0xa6, 0xe2, 0x59, 0x46, 0xc7, 0xc9, 0x72, 0x96, 0xbc, 0x20, 0xd8, 0xd0, 0x70, + 0x47, 0x3c, 0xcb, 0xd8, 0x5b, 0xd0, 0x48, 0xf9, 0x84, 0x44, 0xa6, 0xb7, 0xbe, 0xa4, 0xb6, 0xf4, + 0xd1, 0xd1, 0xe7, 0xdc, 0x97, 0x0e, 0x9f, 0x38, 0x88, 0x63, 0x97, 0xa1, 0xe5, 0x49, 0x99, 0xaa, + 0x2d, 0xea, 0x3a, 0xaa, 0xc3, 0xd6, 0xe0, 0x12, 0x1d, 0x5b, 0x19, 0x8a, 0xd8, 0x95, 0xde, 0x51, + 0x84, 0x36, 0x35, 0xd3, 0xe6, 0x63, 0xb9, 0x40, 0x1d, 0x22, 0x66, 0x3b, 0xc8, 0xd0, 0xe0, 0x2c, + 0xd2, 0xc7, 0xde, 0x8c, 0x67, 0x64, 0x3d, 0xba, 0xce, 0xa5, 0xf9, 0x11, 0x7b, 0x88, 0x42, 0x7e, + 0x96, 0x63, 0xf0, 0xe0, 0x5b, 0x74, 0x86, 0xfa, 0x05, 0x10, 0xf5, 0xc2, 0x15, 0x68, 0x87, 0x99, + 0xcb, 0xe3, 0x40, 0xeb, 0xa2, 0x56, 0x98, 0x3d, 0x88, 0x03, 0xf6, 0x0e, 0x74, 0xd5, 0xaf, 0x04, + 0x7c, 0x42, 0x0e, 0x4c, 0x6f, 0x7d, 0xa8, 0x25, 0x16, 0xc1, 0x5b, 0x7c, 0xe2, 0x58, 0x52, 0xb7, + 0xd0, 0x33, 0x90, 0xc2, 0xe5, 0xa7, 0x92, 0xa7, 0xb1, 0x17, 0xd1, 0xae, 0x58, 0x0e, 0x48, 0xf1, + 0x40, 0x43, 0xd8, 0x3d, 0xb8, 0x66, 0xb0, 0x6e, 0x26, 0x67, 0xd2, 0xcd, 0xe3, 0xf0, 0xd4, 0x8d, + 0xbd, 0x58, 0x90, 0x73, 0xd2, 0x70, 0x2e, 0x1b, 0xf4, 0x81, 0x9c, 0xc9, 0xc7, 0x71, 0x78, 0xba, + 0xe7, 0xc5, 0x82, 0xad, 0xc2, 0xa8, 0x18, 0x26, 0x9f, 0xd3, 0x07, 0x8f, 0x07, 0xa4, 0x23, 0x86, + 0x06, 0x7e, 0xf8, 0x1c, 0xbf, 0x15, 0xd5, 0x7b, 0x95, 0x52, 0x4c, 0x26, 0x19, 0x97, 0x6e, 0xc6, + 0xfd, 0xf1, 0x90, 0xbe, 0xf9, 0x52, 0x49, 0xff, 0x88, 0x70, 0x07, 0xdc, 0xb7, 0xff, 0x5f, 0x0d, + 0x7a, 0x74, 0x2e, 0x1e, 0x27, 0x01, 0xaa, 0x91, 0x6f, 0xc0, 0x60, 0x7e, 0xd3, 0x95, 0xdc, 0xf4, + 0xbd, 0xea, 0x8e, 0x5f, 0x85, 0xf6, 0x86, 0x8f, 0xcc, 0x23, 0xc1, 0x19, 0x38, 0xba, 0xc7, 0xbe, + 0x0d, 0x4b, 0x39, 0x4d, 0xe3, 0xfa, 0xf2, 0xd4, 0x8d, 0x50, 0xfd, 0xa8, 0x83, 0xae, 0xa5, 0x42, + 0xfd, 0xc6, 0xa6, 0x3c, 0x75, 0x06, 0xb9, 0x69, 0xee, 0x84, 0x99, 0xb4, 0x5f, 0x87, 0xd6, 0x46, + 0x9a, 0x7a, 0x67, 0x24, 0x28, 0xd8, 0x18, 0xd7, 0xc8, 0x22, 0xa9, 0x8e, 0xed, 0x43, 0x63, 0xd7, + 0x4b, 0xd8, 0x2d, 0xa8, 0xcf, 0x12, 0xc2, 0xf4, 0xd6, 0xaf, 0x54, 0x4e, 0xb9, 0x97, 0xac, 0xed, + 0x26, 0x0f, 0x62, 0x99, 0x9e, 0x39, 0xf5, 0x59, 0x72, 0xfd, 0x1e, 0x74, 0x74, 0x17, 0xfd, 0xe5, + 0x13, 0x7e, 0x46, 0xdf, 0xd0, 0x75, 0xb0, 0x89, 0x3f, 0xf0, 0xd4, 0x8b, 0x72, 0xe3, 0x3e, 0xa9, + 0xce, 0x77, 0xeb, 0x1f, 0xd7, 0xec, 0x7f, 0x6b, 0x82, 0xb5, 0xc5, 0x23, 0x4e, 0x5f, 0x62, 0x43, + 0xbf, 0x2a, 0xe3, 0x86, 0x0b, 0x73, 0x72, 0x6f, 0x43, 0x5f, 0xd9, 0x48, 0x1a, 0xc5, 0xf5, 0x21, + 0x9a, 0x83, 0xa1, 0xf2, 0xde, 0xbe, 0x9f, 0xfb, 0x27, 0x5c, 0xd2, 0xe9, 0x19, 0x38, 0xa6, 0x8b, + 0x98, 0x3d, 0x8d, 0x69, 0x2a, 0x8c, 0xee, 0xb2, 0xd7, 0x00, 0x52, 0xf1, 0xcc, 0x0d, 0x95, 0xa1, + 0x52, 0x3a, 0xdf, 0x4a, 0xc5, 0xb3, 0x6d, 0x34, 0x55, 0xbf, 0x95, 0x43, 0xf3, 0x6d, 0x18, 0x57, + 0x0e, 0x0d, 0xba, 0xab, 0x6e, 0x18, 0xbb, 0x47, 0xe8, 0x0d, 0xe9, 0xf3, 0x53, 0xce, 0x49, 0xde, + 0xec, 0x76, 0x7c, 0x9f, 0x5c, 0x25, 0xad, 0x0a, 0xba, 0x2f, 0x51, 0x05, 0x17, 0x6a, 0x16, 0xb8, + 0x58, 0xb3, 0xdc, 0x07, 0x38, 0xe0, 0xd3, 0x19, 0x8f, 0xe5, 0xae, 0x97, 0x8c, 0x7b, 0xb4, 0xf1, + 0x76, 0xb9, 0xf1, 0x66, 0xb7, 0xd6, 0x4a, 0x22, 0x25, 0x05, 0x95, 0x51, 0xe8, 0xbf, 0xf8, 0x5e, + 0xec, 0xca, 0x34, 0x8f, 0x7d, 0x4f, 0xaa, 0x40, 0xc0, 0x72, 0x7a, 0xbe, 0x17, 0x1f, 0x6a, 0x50, + 0xe5, 0xf8, 0x0f, 0xaa, 0xc7, 0xff, 0x36, 0x2c, 0x25, 0x69, 0x38, 0xf3, 0xd2, 0x33, 0xf7, 0x84, + 0x9f, 0xd1, 0x66, 0xa8, 0x83, 0x34, 0xd0, 0xe0, 0x9f, 0xf1, 0xb3, 0xed, 0xe0, 0xf4, 0xfa, 0x0f, + 0x60, 0x69, 0x61, 0x01, 0x5f, 0x49, 0xee, 0x7e, 0xde, 0x80, 0xee, 0x7e, 0xca, 0xb5, 0xca, 0x7e, + 0x13, 0x7a, 0x99, 0x7f, 0xcc, 0x67, 0x9e, 0x3a, 0xe9, 0x6a, 0x06, 0x50, 0x20, 0x3a, 0xe5, 0x73, + 0x4a, 0xa9, 0xfe, 0x05, 0x4a, 0x69, 0x04, 0x0d, 0xe5, 0x07, 0xe1, 0x61, 0xc2, 0x66, 0xa9, 0x89, + 0x9b, 0x55, 0x4d, 0xbc, 0x02, 0xfd, 0x63, 0x2f, 0x73, 0xbd, 0x5c, 0x0a, 0xd7, 0x17, 0x11, 0x09, + 0x9d, 0xe5, 0xc0, 0xb1, 0x97, 0x6d, 0xe4, 0x52, 0x6c, 0x8a, 0x88, 0xbd, 0x0e, 0xe0, 0x8b, 0x48, + 0x2b, 0x15, 0xed, 0x04, 0x76, 0x7d, 0x11, 0x29, 0x4d, 0x82, 0x52, 0xc9, 0x33, 0x19, 0xce, 0x3c, + 0xbd, 0xa5, 0xae, 0x2f, 0xf2, 0x58, 0x92, 0xe5, 0x6c, 0x38, 0xcb, 0x05, 0xca, 0x11, 0xcf, 0x36, + 0x11, 0xc1, 0xde, 0x87, 0xa1, 0x2f, 0x66, 0x89, 0x9b, 0x20, 0x67, 0xc9, 0x27, 0xb1, 0xce, 0x79, + 0xe4, 0x7d, 0xa4, 0xd8, 0x3f, 0xe1, 0xca, 0x49, 0x5a, 0x87, 0x25, 0x3f, 0xca, 0x33, 0xc9, 0x53, + 0xf7, 0x48, 0x0f, 0x39, 0xef, 0xc4, 0x0f, 0x34, 0x89, 0x76, 0xac, 0x6c, 0x18, 0x84, 0x99, 0x2b, + 0xa2, 0xc0, 0x55, 0xea, 0x46, 0xcb, 0x59, 0x2f, 0xcc, 0x1e, 0x45, 0x81, 0x56, 0x78, 0x8a, 0x26, + 0xe6, 0xcf, 0x0c, 0x4d, 0xcf, 0xd0, 0xec, 0xf1, 0x67, 0x8a, 0xc6, 0xfe, 0x87, 0x3a, 0x74, 0xf6, + 0x45, 0x26, 0xb7, 0x66, 0x91, 0x11, 0xf1, 0xda, 0x57, 0x15, 0xf1, 0xfa, 0xc5, 0x22, 0x7e, 0x81, + 0x90, 0x35, 0x2e, 0x10, 0x32, 0x34, 0x03, 0x55, 0x3a, 0x12, 0x0e, 0xe5, 0x2a, 0x0e, 0x4b, 0x42, + 0x12, 0x90, 0x1b, 0xe8, 0xdb, 0xb8, 0x81, 0xd2, 0x49, 0x6a, 0x23, 0xad, 0x30, 0xd3, 0xfa, 0x48, + 0x21, 0x43, 0x92, 0x35, 0xed, 0xf8, 0x58, 0x61, 0xa6, 0x65, 0xef, 0x3b, 0xf0, 0x6a, 0x31, 0xd2, + 0x7d, 0x16, 0xca, 0x63, 0x91, 0x4b, 0x77, 0x42, 0x31, 0x54, 0xa6, 0x3d, 0xfb, 0xab, 0x66, 0xa6, + 0x4f, 0x15, 0x5a, 0x45, 0x58, 0xe4, 0x87, 0x4d, 0xf2, 0x28, 0x72, 0x25, 0x3f, 0x95, 0x7a, 0x2b, + 0xc7, 0x8a, 0x37, 0x9a, 0x6f, 0x0f, 0xf3, 0x28, 0x3a, 0xe4, 0xa7, 0x12, 0x95, 0xbf, 0x35, 0xd1, + 0x1d, 0xfb, 0xf7, 0x9b, 0x00, 0x3b, 0xc2, 0x3f, 0x39, 0xf4, 0xd2, 0x29, 0x97, 0x18, 0x2f, 0x18, + 0x8d, 0xa6, 0x35, 0x6e, 0x47, 0x2a, 0x3d, 0xc6, 0xd6, 0xe1, 0xaa, 0xf9, 0x7e, 0x94, 0x43, 0x8c, + 0x5d, 0x94, 0x4a, 0xd2, 0x07, 0x8a, 0x69, 0xac, 0x8a, 0x95, 0x49, 0x1f, 0xb1, 0x8f, 0x4b, 0xde, + 0xe2, 0x18, 0x79, 0x96, 0x10, 0x6f, 0x2f, 0xf2, 0x3b, 0x07, 0xe5, 0xf0, 0xc3, 0xb3, 0x84, 0xbd, + 0x0f, 0x57, 0x52, 0x3e, 0x49, 0x79, 0x76, 0xec, 0xca, 0xac, 0xfa, 0x63, 0x2a, 0x6c, 0x58, 0xd6, + 0xc8, 0xc3, 0xac, 0xf8, 0xad, 0xf7, 0xe1, 0x8a, 0xe2, 0xd4, 0xe2, 0xf2, 0x94, 0xfe, 0x5e, 0x56, + 0xc8, 0xea, 0xea, 0x5e, 0x07, 0xca, 0x2a, 0x29, 0x9d, 0x6c, 0x9c, 0xd0, 0x88, 0x98, 0x71, 0x14, + 0x71, 0xf4, 0xcf, 0x36, 0x8f, 0x31, 0x0e, 0xde, 0xe2, 0x13, 0xcd, 0xfc, 0x12, 0xc0, 0x6c, 0x68, + 0xee, 0x8a, 0x80, 0x13, 0xab, 0x87, 0xeb, 0xc3, 0x35, 0xca, 0x4f, 0x21, 0x27, 0x29, 0x91, 0x41, + 0x38, 0xf6, 0x36, 0xd0, 0x74, 0x4a, 0xfc, 0xce, 0x9f, 0x15, 0x0b, 0x91, 0x24, 0x83, 0xef, 0xc3, + 0x95, 0x72, 0x25, 0xae, 0x27, 0x5d, 0x79, 0xcc, 0x49, 0x1d, 0xaa, 0xe3, 0xb2, 0x5c, 0x2c, 0x6a, + 0x43, 0x1e, 0x1e, 0x73, 0x54, 0x8d, 0xab, 0xd0, 0x11, 0x47, 0x9f, 0xbb, 0x78, 0x10, 0x7a, 0x17, + 0x1f, 0x84, 0xb6, 0x38, 0xfa, 0xdc, 0xe1, 0x13, 0xf6, 0xad, 0xaa, 0x29, 0x59, 0x60, 0x4d, 0x9f, + 0x58, 0x73, 0xb9, 0xc0, 0x57, 0xb8, 0x63, 0x7f, 0x0c, 0x6d, 0xfc, 0x9c, 0x47, 0x09, 0x5b, 0x83, + 0x8e, 0x24, 0xf1, 0xc8, 0xb4, 0xe9, 0xbf, 0x5c, 0x5a, 0x80, 0x52, 0x76, 0x1c, 0x43, 0x64, 0x3b, + 0xb0, 0x54, 0xa8, 0xd3, 0xc7, 0x71, 0xf8, 0x24, 0xe7, 0xec, 0x47, 0xb0, 0x9c, 0xa4, 0x5c, 0x8b, + 0xbd, 0x9b, 0x9f, 0xa0, 0x7b, 0xa2, 0x4f, 0xf0, 0x65, 0x2d, 0xa5, 0xc5, 0x88, 0x13, 0x94, 0xd0, + 0x61, 0x32, 0xd7, 0xb7, 0x3f, 0x83, 0x6b, 0x05, 0xc5, 0x01, 0xf7, 0x45, 0x1c, 0x78, 0xe9, 0x19, + 0x59, 0xbe, 0x85, 0xb9, 0xb3, 0xaf, 0x32, 0xf7, 0x01, 0xcd, 0xfd, 0xc7, 0x35, 0xe8, 0x3d, 0xcc, + 0x9f, 0x3f, 0x3f, 0x53, 0x67, 0x89, 0xf5, 0xa1, 0xb6, 0x47, 0x13, 0xd4, 0x9d, 0xda, 0x1e, 0xba, + 0x5a, 0xfb, 0x27, 0x78, 0xae, 0x49, 0xce, 0xbb, 0x8e, 0xee, 0x61, 0x24, 0xb5, 0x7f, 0x72, 0xf8, + 0x12, 0x89, 0x56, 0x68, 0x0c, 0x01, 0xee, 0xe7, 0x61, 0x84, 0xae, 0x83, 0x16, 0xde, 0xa2, 0x8f, + 0xb1, 0xc9, 0xf6, 0x44, 0x2d, 0xe5, 0x61, 0x2a, 0x66, 0x8a, 0x59, 0x5a, 0x65, 0x5c, 0x80, 0xb1, + 0x7f, 0xd3, 0x04, 0xeb, 0x13, 0x2f, 0x3b, 0xfe, 0xa9, 0x08, 0x63, 0xf6, 0x3e, 0x74, 0x3f, 0x17, + 0x61, 0xac, 0x92, 0x02, 0x2a, 0xb1, 0x79, 0x49, 0x2d, 0x62, 0x4f, 0x04, 0x7c, 0x0d, 0x69, 0x70, + 0x35, 0x8e, 0xf5, 0xb9, 0x6e, 0x69, 0x4d, 0x9b, 0x86, 0xd3, 0x63, 0xe9, 0x22, 0x50, 0xab, 0xc4, + 0x5e, 0x98, 0x39, 0x08, 0xa3, 0x59, 0x5f, 0x03, 0x34, 0x3a, 0xc7, 0xae, 0x88, 0xdd, 0xe4, 0x44, + 0x07, 0x1c, 0x16, 0x42, 0x1e, 0xc5, 0xfb, 0x27, 0x78, 0x64, 0xc2, 0xcc, 0xd5, 0xa9, 0x07, 0xfa, + 0x9c, 0xb9, 0xb8, 0xed, 0x26, 0x0c, 0xd1, 0xd4, 0x67, 0x27, 0x61, 0xe2, 0x26, 0xa9, 0x38, 0x32, + 0xdf, 0x82, 0x0e, 0xc0, 0xc1, 0x49, 0x98, 0xec, 0x23, 0x8c, 0x2c, 0xac, 0x4e, 0x68, 0xa0, 0xb6, + 0x55, 0xa6, 0x0c, 0x34, 0x08, 0xd9, 0x42, 0x59, 0x8b, 0x48, 0xb9, 0xaf, 0x1d, 0xb2, 0x9c, 0x9d, + 0x94, 0x47, 0xe8, 0xa7, 0x22, 0x0a, 0x65, 0x98, 0x50, 0x96, 0x42, 0xf9, 0x42, 0xa1, 0xbe, 0x09, + 0x10, 0xf1, 0x89, 0x74, 0x51, 0x38, 0x54, 0x80, 0xb7, 0x90, 0x1d, 0x40, 0xec, 0x26, 0x22, 0xd9, + 0x3b, 0xd0, 0x53, 0x5c, 0x50, 0xb4, 0x70, 0x8e, 0x16, 0x08, 0xad, 0x88, 0xef, 0x40, 0x2f, 0x16, + 0xb1, 0xcb, 0x9f, 0x10, 0xb5, 0x3e, 0x6e, 0x73, 0x13, 0xc7, 0x22, 0x7e, 0xf0, 0x04, 0x89, 0xd9, + 0x5d, 0xbd, 0x06, 0x15, 0x63, 0xf7, 0x5f, 0x10, 0x63, 0xd3, 0x4a, 0x54, 0xb4, 0xf9, 0x81, 0x59, + 0x89, 0x1a, 0x31, 0x78, 0xc1, 0x08, 0xb5, 0x1e, 0x35, 0x64, 0x05, 0xfa, 0xb4, 0xef, 0x33, 0x2f, + 0x71, 0xa5, 0x37, 0xd5, 0x2e, 0x11, 0x20, 0x6c, 0xd7, 0x4b, 0x0e, 0xbd, 0x29, 0x73, 0xe0, 0x55, + 0x9d, 0x7f, 0xd3, 0xc6, 0xc3, 0x3d, 0x42, 0x89, 0x53, 0x5c, 0x5b, 0x32, 0x31, 0xfa, 0xc5, 0x99, + 0xbb, 0xab, 0x73, 0x99, 0x3b, 0x92, 0x54, 0x0a, 0x10, 0xfe, 0xa8, 0x0e, 0xd6, 0x8e, 0x10, 0xc9, + 0xd7, 0x14, 0xbd, 0xea, 0x96, 0xd6, 0x5f, 0xbc, 0xa5, 0x8d, 0xf9, 0x2d, 0x5d, 0x60, 0x7d, 0xf3, + 0xcb, 0xb3, 0xbe, 0xf5, 0x95, 0x59, 0xdf, 0xfe, 0x1a, 0xac, 0xef, 0x2c, 0xb2, 0xde, 0xee, 0x40, + 0xeb, 0x80, 0xcb, 0x47, 0x89, 0xfd, 0x0b, 0x0b, 0xba, 0x5b, 0x3c, 0xc8, 0x15, 0xc3, 0xaa, 0x9f, + 0x5f, 0x7b, 0xf1, 0xe7, 0xd7, 0xe7, 0x3f, 0x1f, 0xed, 0x87, 0x91, 0xe8, 0x0b, 0x52, 0x46, 0x96, + 0x11, 0x68, 0x14, 0xfd, 0x52, 0x9e, 0x75, 0xce, 0x66, 0x8e, 0x4d, 0x85, 0x38, 0xbf, 0x5c, 0x36, + 0x5a, 0x5f, 0x4b, 0x36, 0x16, 0xb4, 0xc2, 0xb9, 0x6c, 0xce, 0x17, 0x72, 0x6d, 0x51, 0x23, 0x58, + 0xe7, 0x34, 0xc2, 0x0e, 0x5c, 0x12, 0xb1, 0x1b, 0xe4, 0x49, 0x14, 0x62, 0xc0, 0xe0, 0x7a, 0x2a, + 0xf8, 0xed, 0x9a, 0x9a, 0x42, 0x21, 0x7a, 0x8f, 0xe2, 0x2d, 0x43, 0xa4, 0x42, 0x62, 0x67, 0x59, + 0x2c, 0x82, 0x50, 0x4d, 0x05, 0xb8, 0x35, 0x64, 0x0e, 0xc9, 0x91, 0x53, 0xc5, 0x91, 0x3e, 0x41, + 0x37, 0x45, 0x44, 0x0a, 0xfe, 0x63, 0x58, 0x2a, 0xa9, 0x94, 0x8c, 0xf4, 0x5e, 0x20, 0x23, 0x03, + 0x33, 0x50, 0x89, 0xc9, 0x6f, 0x43, 0x0b, 0xbc, 0x07, 0x97, 0x4c, 0xa4, 0xaf, 0x6d, 0x3a, 0xed, + 0xe0, 0x90, 0x24, 0x68, 0xa4, 0x83, 0x7b, 0x32, 0xe7, 0xb4, 0x45, 0xdf, 0x83, 0xcb, 0x15, 0x72, + 0x74, 0xde, 0xab, 0xda, 0xa0, 0x2a, 0x2b, 0xcb, 0xc5, 0x58, 0xec, 0xee, 0xa8, 0xac, 0x65, 0x2f, + 0xe0, 0x91, 0xf9, 0xa1, 0xf1, 0x48, 0xc5, 0x1e, 0x01, 0x8f, 0x74, 0x5d, 0x64, 0x17, 0x6e, 0xa2, + 0x8b, 0x8f, 0x78, 0xdf, 0x4b, 0x64, 0x9e, 0x72, 0x37, 0x89, 0x3c, 0x9f, 0x1f, 0x8b, 0x28, 0xe0, + 0x69, 0xb9, 0xb8, 0x65, 0x5a, 0xdc, 0x9b, 0x22, 0x0a, 0x36, 0x45, 0xb4, 0xa9, 0x28, 0xf7, 0x4b, + 0x42, 0xb3, 0xd6, 0x0d, 0x78, 0xe3, 0xdc, 0x74, 0x68, 0x38, 0xca, 0x89, 0x18, 0x4d, 0xf4, 0xea, + 0xfc, 0x44, 0x48, 0x62, 0xa6, 0xf8, 0x00, 0xae, 0xa8, 0xbd, 0x53, 0xc2, 0x7d, 0xc2, 0x79, 0xe2, + 0x46, 0x5e, 0x26, 0xc7, 0x97, 0x94, 0x6d, 0x25, 0x24, 0x09, 0xf0, 0xcf, 0x38, 0x4f, 0x76, 0x3c, + 0xf5, 0xab, 0x6a, 0x88, 0x76, 0xbf, 0x69, 0xcc, 0x1c, 0x6f, 0x2f, 0xab, 0x5f, 0x25, 0x2a, 0xe5, + 0x83, 0xe3, 0xe0, 0x0a, 0x93, 0xbf, 0x0f, 0x37, 0xe6, 0xa6, 0x98, 0x79, 0xe9, 0x49, 0xe9, 0x8f, + 0x8e, 0xaf, 0x10, 0xdf, 0xae, 0x55, 0xc6, 0xef, 0x12, 0x81, 0x9a, 0xc1, 0xfe, 0xd7, 0x16, 0x0c, + 0xc9, 0x0e, 0xff, 0x4e, 0x6d, 0xfc, 0x4e, 0x6d, 0xfc, 0x37, 0x50, 0x1b, 0xf6, 0xff, 0xa9, 0x41, + 0x67, 0x3f, 0x15, 0x41, 0xee, 0xcb, 0xaf, 0x29, 0xe9, 0xf3, 0x12, 0xd4, 0xf8, 0x22, 0x09, 0x6a, + 0x9e, 0x33, 0xd7, 0x7f, 0x5a, 0x83, 0xae, 0x5e, 0xc2, 0xce, 0xfa, 0xd7, 0x5c, 0x44, 0x59, 0xd3, + 0xa9, 0x5d, 0x58, 0xd3, 0xf9, 0xc2, 0x55, 0xa0, 0x60, 0x3d, 0x55, 0xf5, 0x6a, 0x91, 0x28, 0x9f, + 0xaa, 0xa5, 0x04, 0x4b, 0x41, 0x1f, 0x25, 0xb8, 0x77, 0xf6, 0x33, 0xe8, 0x52, 0xc0, 0x43, 0x9a, + 0xe1, 0x2a, 0xb4, 0x53, 0x2a, 0x5a, 0xe8, 0x85, 0xea, 0xde, 0xcb, 0xcf, 0x69, 0xfd, 0xeb, 0xb9, + 0x7e, 0x7f, 0x5b, 0x87, 0x01, 0x45, 0x9f, 0x0f, 0xf3, 0x58, 0x9d, 0x84, 0x22, 0x87, 0x55, 0x9b, + 0xcf, 0x61, 0x35, 0x53, 0x0c, 0x12, 0xd5, 0xcf, 0xf4, 0xd5, 0xcf, 0x6c, 0x8a, 0x68, 0x8b, 0x4f, + 0x1c, 0xc2, 0x20, 0xab, 0xbc, 0x74, 0x9a, 0x5d, 0x54, 0xfe, 0x42, 0x38, 0x7e, 0x55, 0xe2, 0xa5, + 0xde, 0x2c, 0x33, 0xe5, 0x2f, 0xd5, 0x63, 0x0c, 0x9a, 0x74, 0xde, 0x14, 0x5b, 0xa8, 0xad, 0x13, + 0x29, 0x59, 0x18, 0x4f, 0x0b, 0xe5, 0x61, 0x51, 0xd5, 0x73, 0x1a, 0x71, 0xb6, 0x05, 0x4c, 0x65, + 0x4d, 0x53, 0xee, 0xa1, 0x09, 0xa2, 0x79, 0x48, 0x83, 0xf4, 0xd6, 0xaf, 0xaa, 0x9f, 0x25, 0x5e, + 0x3a, 0x84, 0xde, 0x47, 0xac, 0x33, 0x0a, 0x17, 0x20, 0x17, 0x30, 0x53, 0xd9, 0xa1, 0x22, 0xfa, + 0xf8, 0xd2, 0xcc, 0x24, 0xe3, 0x44, 0xcc, 0xdc, 0x80, 0x2b, 0xa6, 0x20, 0x81, 0xea, 0x62, 0x1d, + 0xcf, 0x02, 0x85, 0xb1, 0xe6, 0x1b, 0x6b, 0x95, 0x6f, 0xbc, 0x0c, 0xad, 0xea, 0x0d, 0x06, 0xd5, + 0xb1, 0x6f, 0x41, 0x6f, 0x12, 0x46, 0x5c, 0xa7, 0x02, 0x91, 0x69, 0x3a, 0x29, 0x58, 0xa3, 0x1a, + 0xbe, 0xee, 0xd9, 0x7f, 0x55, 0x83, 0x6b, 0x89, 0x97, 0x3e, 0xc9, 0xb9, 0xa4, 0x84, 0x20, 0x15, + 0xb0, 0xdc, 0xec, 0xd8, 0x4b, 0x03, 0x3c, 0x38, 0x34, 0x85, 0x9a, 0x5d, 0x15, 0xd5, 0xbb, 0x08, + 0x51, 0x6b, 0xb9, 0x0d, 0x4b, 0x95, 0x11, 0xd2, 0x4b, 0x4d, 0x92, 0x67, 0x90, 0x8a, 0x67, 0x54, + 0x87, 0x3c, 0x40, 0x20, 0x06, 0x94, 0x25, 0x1d, 0x27, 0x6b, 0x43, 0xb5, 0x69, 0x43, 0xf5, 0x20, + 0x0e, 0xf0, 0xe4, 0xc4, 0xf9, 0x4c, 0xe5, 0x40, 0xd4, 0x3d, 0x87, 0x4e, 0x9c, 0xcf, 0x28, 0xed, + 0x71, 0x19, 0x5a, 0x47, 0x67, 0x92, 0xbc, 0x75, 0x84, 0xab, 0x8e, 0xfd, 0x8f, 0x4d, 0xe8, 0x1b, + 0x16, 0x51, 0xad, 0xf9, 0xdd, 0xaa, 0xb4, 0xf5, 0xd6, 0x47, 0x46, 0x6c, 0x90, 0x64, 0x43, 0xca, + 0xd4, 0xc4, 0xdb, 0x4a, 0x0a, 0x6f, 0x00, 0x7d, 0x88, 0x9b, 0x85, 0xcf, 0x39, 0x89, 0x62, 0xc3, + 0xb1, 0x10, 0x40, 0x45, 0xc3, 0x0d, 0x58, 0xae, 0xb0, 0xce, 0x95, 0x42, 0x7a, 0x91, 0x96, 0xc6, + 0x4a, 0x3d, 0xa3, 0x42, 0xe2, 0x2c, 0x61, 0x47, 0xe5, 0x58, 0x0f, 0x91, 0x1a, 0xa5, 0xdc, 0x17, + 0x91, 0xa9, 0x8c, 0x2e, 0x48, 0x39, 0x62, 0x28, 0x53, 0x9b, 0x72, 0x54, 0x9a, 0xd9, 0x93, 0x48, + 0xcb, 0x6c, 0x57, 0x41, 0x0e, 0x9e, 0x44, 0xc5, 0x02, 0x49, 0x8a, 0xda, 0x74, 0x80, 0x68, 0x81, + 0xa4, 0x4c, 0xde, 0x83, 0x9e, 0x48, 0xc3, 0x69, 0x48, 0xa9, 0x1a, 0x55, 0x22, 0x58, 0xfc, 0x11, + 0x50, 0x04, 0x9b, 0xf8, 0x53, 0x36, 0xb4, 0x95, 0x64, 0x5e, 0x90, 0xbd, 0xd5, 0x18, 0xdc, 0xcc, + 0x4c, 0xa6, 0xa1, 0x2f, 0x71, 0x39, 0xea, 0x2e, 0x8e, 0x2a, 0xb2, 0x0d, 0x14, 0xf8, 0xe0, 0x49, + 0x44, 0xd9, 0xaa, 0xdb, 0xb0, 0xe4, 0x8b, 0x28, 0x9f, 0xc5, 0xb4, 0x32, 0x37, 0xe2, 0x31, 0xd9, + 0xb7, 0x96, 0x33, 0x50, 0x60, 0x5c, 0xdf, 0x0e, 0x8f, 0x75, 0x41, 0xcf, 0x8b, 0x22, 0x54, 0x95, + 0xc2, 0x0b, 0x74, 0xbe, 0xb6, 0x6f, 0x80, 0x3b, 0xc2, 0x0b, 0xd8, 0x77, 0xe1, 0x3a, 0xe2, 0x5c, + 0x3e, 0x4b, 0xe4, 0x99, 0x1b, 0xe7, 0x33, 0x9e, 0x86, 0xbe, 0xeb, 0x65, 0xee, 0x73, 0x9e, 0x0a, + 0x5d, 0x02, 0xb8, 0x8a, 0x14, 0x0f, 0x90, 0x60, 0x4f, 0xe1, 0x37, 0xb2, 0xcf, 0x78, 0x2a, 0xd8, + 0x67, 0x94, 0xb1, 0xba, 0x48, 0x6e, 0x8d, 0x8d, 0x7b, 0xab, 0xdc, 0xab, 0x17, 0x50, 0x52, 0x7d, + 0x04, 0x11, 0x8e, 0x11, 0x58, 0x1a, 0x6f, 0xfb, 0x00, 0xea, 0xde, 0x11, 0x49, 0xd6, 0xdb, 0xd0, + 0x91, 0x47, 0x11, 0x25, 0xf2, 0x6b, 0x17, 0x26, 0xf2, 0xdb, 0xf2, 0x08, 0x79, 0x5e, 0x39, 0x63, + 0x75, 0x12, 0x55, 0xdd, 0x43, 0x09, 0x8e, 0xc2, 0x59, 0x28, 0xf5, 0x3d, 0x1f, 0xd5, 0xb1, 0x8f, + 0xa0, 0x4b, 0x33, 0xd0, 0x6f, 0x14, 0x15, 0xf7, 0xda, 0xcb, 0x2b, 0xee, 0xef, 0x41, 0x5f, 0x2b, + 0x99, 0x17, 0x95, 0xf0, 0x7b, 0x0a, 0x8f, 0xed, 0xcc, 0x7e, 0x17, 0xba, 0xff, 0xd3, 0x8b, 0x72, + 0xf5, 0x1b, 0x6f, 0x42, 0x8f, 0x6a, 0x43, 0xee, 0x51, 0x24, 0xfc, 0x13, 0x53, 0xb3, 0x20, 0xd0, + 0x7d, 0x84, 0xd8, 0x00, 0xd6, 0xe3, 0x38, 0x14, 0xf1, 0x46, 0x14, 0xd9, 0xbf, 0x6e, 0x43, 0xf7, + 0x13, 0x2f, 0x3b, 0x26, 0x05, 0x8f, 0x47, 0x98, 0xee, 0x13, 0x50, 0xd2, 0x67, 0xe6, 0x25, 0xfa, + 0x4e, 0x41, 0x0f, 0x81, 0x48, 0xb5, 0xeb, 0x25, 0x0b, 0x39, 0xa1, 0xfa, 0x42, 0x4e, 0xe8, 0x2d, + 0x75, 0x11, 0x4d, 0x55, 0xa7, 0xb8, 0x29, 0x52, 0xd3, 0x04, 0xf7, 0x15, 0x88, 0xbd, 0x0b, 0x8c, + 0x48, 0xbc, 0x28, 0x12, 0xe4, 0x88, 0x65, 0x3c, 0xca, 0x74, 0xfa, 0x68, 0x84, 0x98, 0x0d, 0x8d, + 0x38, 0xe0, 0xea, 0xfc, 0x54, 0xac, 0x7a, 0x6b, 0xd1, 0xaa, 0xdf, 0x01, 0x40, 0x7f, 0x95, 0x12, + 0x96, 0x0b, 0x61, 0xbb, 0xca, 0xdd, 0x94, 0xd8, 0x2f, 0xe1, 0x43, 0xbe, 0x0d, 0xa3, 0x82, 0x22, + 0xe5, 0x13, 0xd7, 0x8f, 0xa5, 0x76, 0x24, 0x07, 0x9a, 0xca, 0xe1, 0x93, 0xcd, 0x58, 0x2e, 0x3a, + 0x9b, 0xdd, 0x73, 0xce, 0xe6, 0x4f, 0xe0, 0xd2, 0x82, 0xb5, 0xc8, 0x12, 0xee, 0xeb, 0xb2, 0xf5, + 0x57, 0xb9, 0x29, 0xf5, 0x2a, 0x58, 0x54, 0x05, 0x08, 0xf2, 0x44, 0x9f, 0xad, 0x4e, 0x98, 0x51, + 0x50, 0xf0, 0x22, 0x87, 0xb6, 0xff, 0x5f, 0xe5, 0xd0, 0x0e, 0xbe, 0x9c, 0x43, 0x3b, 0xfc, 0x72, + 0x0e, 0xed, 0x82, 0x03, 0xb8, 0xb4, 0x18, 0x37, 0xbe, 0x30, 0x4a, 0x1b, 0xbd, 0x30, 0x4a, 0xfb, + 0x82, 0x10, 0x6b, 0xf9, 0xa5, 0x21, 0xd6, 0x97, 0x88, 0xf1, 0xd8, 0x17, 0xc5, 0x78, 0xb7, 0x61, + 0x49, 0xa6, 0x9e, 0x7f, 0xe2, 0xc6, 0x79, 0x14, 0xb9, 0x27, 0xfc, 0x2c, 0xd3, 0x31, 0xe5, 0x80, + 0xc0, 0x7b, 0x79, 0x14, 0xfd, 0x8c, 0x9f, 0x65, 0xf6, 0x63, 0x00, 0xb2, 0xa5, 0xf4, 0x69, 0x2f, + 0x92, 0x8d, 0xda, 0x57, 0x95, 0x0d, 0xfb, 0xdf, 0x6b, 0x00, 0x07, 0xde, 0x2c, 0x51, 0xce, 0x18, + 0xfb, 0x31, 0xf4, 0x32, 0xea, 0x55, 0x53, 0x71, 0x6f, 0x56, 0xee, 0x58, 0x16, 0xa4, 0xba, 0x49, + 0x69, 0x39, 0xc8, 0x8a, 0x36, 0x89, 0xb5, 0x9a, 0xa1, 0x28, 0x92, 0xb5, 0x0c, 0x01, 0x19, 0xe9, + 0x5b, 0x30, 0xd4, 0x04, 0x09, 0x4f, 0x7d, 0x1e, 0x2b, 0x5d, 0x57, 0x73, 0x06, 0x0a, 0xba, 0xaf, + 0x80, 0xec, 0x83, 0x82, 0x4c, 0x59, 0x8b, 0xec, 0x82, 0x78, 0x52, 0x0f, 0xd9, 0x54, 0x04, 0xf6, + 0xba, 0xf9, 0x14, 0x5a, 0x88, 0x05, 0x4d, 0xfc, 0xbd, 0xd1, 0x2b, 0xac, 0x07, 0x1d, 0x3d, 0xeb, + 0xa8, 0xc6, 0x06, 0xd0, 0xa5, 0xdb, 0x68, 0x84, 0xab, 0xdb, 0xff, 0x77, 0x19, 0x7a, 0xdb, 0x71, + 0x26, 0xd3, 0x5c, 0x89, 0x70, 0x79, 0xe9, 0xaa, 0x45, 0x97, 0xae, 0x74, 0xbd, 0x55, 0x7d, 0x06, + 0xd5, 0x5b, 0xdf, 0x83, 0x8e, 0xbe, 0xde, 0xa7, 0x3d, 0xf4, 0x0b, 0xef, 0x06, 0x1a, 0x1a, 0xb6, + 0x06, 0x56, 0xa0, 0xef, 0x1d, 0xea, 0x7c, 0x63, 0xe5, 0x32, 0xa0, 0xb9, 0x91, 0xe8, 0x14, 0x34, + 0xec, 0x2d, 0x68, 0x78, 0xd3, 0x29, 0x69, 0x29, 0x2a, 0xc2, 0x18, 0x52, 0x32, 0x3a, 0x0e, 0xe2, + 0xd8, 0x5d, 0xe8, 0x92, 0xfa, 0xa4, 0x94, 0x7b, 0x7b, 0x71, 0x4e, 0x93, 0xcf, 0x57, 0x1a, 0x95, + 0x9c, 0xfb, 0xbb, 0xd0, 0x8d, 0x84, 0x48, 0xd4, 0x80, 0xce, 0xe2, 0x00, 0x93, 0x85, 0x75, 0xac, + 0xc8, 0xe4, 0x63, 0x6f, 0x43, 0x1b, 0xdd, 0x19, 0x91, 0x68, 0x37, 0xa0, 0xb2, 0x0e, 0xca, 0x46, + 0x3a, 0xad, 0x0c, 0xff, 0xb0, 0x75, 0x00, 0x25, 0xff, 0x34, 0x73, 0x77, 0x91, 0x1d, 0x45, 0xe2, + 0x01, 0x0f, 0xa9, 0xc9, 0x41, 0xdc, 0x87, 0x91, 0x0a, 0x32, 0x2b, 0x23, 0xc1, 0xd4, 0x17, 0xcd, + 0xc8, 0xf9, 0xbc, 0x85, 0x33, 0x4c, 0xe7, 0xf3, 0x18, 0xef, 0x40, 0x27, 0x51, 0x51, 0x16, 0x69, + 0x98, 0xde, 0xfa, 0x72, 0x39, 0x54, 0x87, 0x5f, 0x8e, 0xa1, 0x60, 0x3f, 0x84, 0xa1, 0xaa, 0x83, + 0x4d, 0x74, 0xb8, 0x41, 0x19, 0xee, 0xb9, 0x6b, 0x65, 0x73, 0xd1, 0x88, 0x33, 0x90, 0x73, 0xc1, + 0xc9, 0xf7, 0x60, 0x50, 0x5e, 0xf3, 0xf1, 0xbd, 0x98, 0xf4, 0x0e, 0xb9, 0xfd, 0x66, 0x78, 0xd5, + 0xbb, 0x74, 0xfa, 0xbc, 0xea, 0x6b, 0xae, 0x42, 0x5b, 0xd7, 0x66, 0x47, 0x34, 0xaa, 0x72, 0x0d, + 0x5c, 0x55, 0x63, 0x1c, 0x8d, 0x47, 0x5e, 0x96, 0x65, 0xa7, 0x31, 0x5b, 0xe4, 0x65, 0x51, 0x73, + 0x72, 0xba, 0x45, 0xb9, 0x89, 0x3d, 0x98, 0x2f, 0x83, 0xa9, 0x72, 0xcf, 0x25, 0x1a, 0xfa, 0xea, + 0x05, 0x43, 0x55, 0xd5, 0xc7, 0x59, 0x4a, 0x16, 0xaa, 0x69, 0xef, 0x82, 0x25, 0xd2, 0x80, 0xea, + 0xf0, 0x94, 0x94, 0x22, 0x7e, 0x52, 0xf5, 0x4f, 0xdd, 0x69, 0x24, 0xe5, 0xd1, 0x11, 0xaa, 0x83, + 0x8e, 0x45, 0x92, 0x8a, 0xcf, 0xb9, 0x2f, 0x95, 0x8a, 0xbb, 0x72, 0xde, 0xb1, 0xd0, 0x78, 0x52, + 0x70, 0x37, 0xa1, 0x63, 0x2a, 0xce, 0x57, 0xcf, 0x51, 0x1a, 0x14, 0xfb, 0x10, 0x96, 0xe6, 0x15, + 0x5a, 0x36, 0xbe, 0x76, 0x8e, 0x7a, 0x38, 0xa7, 0xbf, 0xd0, 0x1a, 0x6b, 0x6f, 0x69, 0x7c, 0xce, + 0x59, 0x55, 0x08, 0xf4, 0x67, 0xb5, 0x9f, 0xf5, 0xea, 0x79, 0x7f, 0x56, 0xfb, 0x5c, 0x63, 0xe8, + 0x84, 0xd9, 0xc3, 0x30, 0xcd, 0xe4, 0xf8, 0xba, 0xb1, 0x8e, 0xd4, 0x45, 0x2f, 0x2d, 0xcc, 0xd0, + 0x4c, 0x8c, 0x6f, 0x98, 0x5b, 0xb0, 0x64, 0x34, 0xee, 0x40, 0x5b, 0x57, 0xe3, 0x57, 0xce, 0x9d, + 0x68, 0x7d, 0x83, 0xc5, 0xd1, 0x14, 0xec, 0x9b, 0xd0, 0xa1, 0x52, 0xac, 0x48, 0xc6, 0x6f, 0x2d, + 0x4a, 0x80, 0xaa, 0x87, 0x3a, 0xed, 0x48, 0xd5, 0x45, 0xdf, 0x81, 0x8e, 0x71, 0x52, 0xec, 0x45, + 0xa9, 0xd6, 0xce, 0x8a, 0x63, 0x28, 0xd8, 0x2d, 0x68, 0xcd, 0x50, 0x8f, 0x8d, 0xbf, 0xb1, 0x78, + 0x42, 0x95, 0x7a, 0x53, 0x58, 0x76, 0x0f, 0x7a, 0x19, 0xf9, 0xa7, 0x4a, 0x74, 0x6f, 0x9a, 0x32, + 0xe6, 0xfc, 0xa5, 0x79, 0x12, 0x5c, 0xc8, 0x4a, 0x47, 0xf6, 0x7f, 0xc1, 0xf5, 0x6a, 0x0d, 0xd4, + 0x14, 0x48, 0x75, 0x7c, 0x77, 0x8b, 0x66, 0x79, 0xeb, 0x02, 0x09, 0x9b, 0x2f, 0xa5, 0x3a, 0xd7, + 0x92, 0x17, 0xd4, 0x58, 0xef, 0x15, 0x56, 0x02, 0x0f, 0xe5, 0xf8, 0xf6, 0xb9, 0x65, 0x15, 0x76, + 0xc6, 0xd8, 0x0e, 0x32, 0x4f, 0x1f, 0x43, 0x7f, 0x92, 0x3f, 0x7f, 0x7e, 0xa6, 0x65, 0x64, 0xfc, + 0x36, 0x8d, 0xab, 0x44, 0x5a, 0x95, 0xb2, 0xab, 0xd3, 0x9b, 0x54, 0x6a, 0xb0, 0xd7, 0xa0, 0xe3, + 0xc7, 0xae, 0x17, 0x04, 0xe9, 0x78, 0x55, 0x95, 0x5d, 0xfd, 0x78, 0x23, 0x08, 0xe8, 0xfe, 0xbf, + 0x48, 0x38, 0x5d, 0xcc, 0x75, 0xc3, 0x60, 0xfc, 0x4d, 0x65, 0xaf, 0x0c, 0x68, 0x3b, 0xa0, 0x07, + 0x02, 0x26, 0x3c, 0x09, 0x83, 0xf1, 0x1d, 0xfd, 0x40, 0x40, 0x83, 0xb6, 0x03, 0xf4, 0x57, 0x67, + 0xde, 0xa9, 0x6b, 0x20, 0xe3, 0x77, 0x54, 0xcc, 0x3a, 0xf3, 0x4e, 0xf7, 0x35, 0x08, 0xcf, 0xb6, + 0x4a, 0x1f, 0x90, 0xb6, 0x7b, 0x77, 0xf1, 0x6c, 0x17, 0x69, 0x18, 0xa7, 0x1b, 0x16, 0x19, 0x19, + 0xd2, 0x07, 0xa4, 0xc1, 0xdc, 0x68, 0x7d, 0xfc, 0xde, 0x79, 0x7d, 0xa0, 0xb3, 0x4c, 0xa8, 0x0f, + 0x4c, 0xc2, 0x69, 0x1d, 0x40, 0xa9, 0x3a, 0xda, 0xec, 0xb5, 0xc5, 0x31, 0x45, 0x10, 0xe1, 0xa8, + 0x1b, 0x47, 0xb4, 0xd5, 0xeb, 0x00, 0x74, 0x75, 0x49, 0x8d, 0xb9, 0xbb, 0x38, 0xa6, 0x08, 0x0a, + 0x9c, 0xee, 0xd3, 0x22, 0x3e, 0xb8, 0x0b, 0xdd, 0x1c, 0xdd, 0x7f, 0x74, 0xc0, 0xc7, 0xef, 0x2f, + 0x9e, 0x01, 0x13, 0x19, 0x38, 0x56, 0xae, 0x5b, 0xf8, 0x23, 0x64, 0xb2, 0xc8, 0x7b, 0x19, 0x7f, + 0xb0, 0xf8, 0x23, 0x45, 0xf8, 0xe0, 0x90, 0x65, 0x53, 0x91, 0xc4, 0x3d, 0xe8, 0x29, 0xa6, 0xa9, + 0x41, 0xeb, 0x8b, 0x32, 0x52, 0xba, 0x43, 0x8e, 0xe2, 0xae, 0x1a, 0x76, 0x0b, 0x5a, 0x5e, 0x92, + 0x44, 0x67, 0xe3, 0x0f, 0x17, 0x0f, 0xc6, 0x06, 0x82, 0x1d, 0x85, 0x45, 0x51, 0x9a, 0xe5, 0x91, + 0x0c, 0xcd, 0x25, 0xa1, 0x8f, 0x16, 0x45, 0xa9, 0x72, 0x87, 0xd2, 0xe9, 0xcd, 0x2a, 0x17, 0x2a, + 0xdf, 0x05, 0x2b, 0x11, 0x99, 0x74, 0x83, 0x59, 0x34, 0xbe, 0x77, 0xce, 0xfa, 0xa8, 0xcb, 0x31, + 0x4e, 0x27, 0xd1, 0xb7, 0x8b, 0xe6, 0x6e, 0xf6, 0x7e, 0x6b, 0xfe, 0x66, 0xef, 0x4f, 0x9b, 0xd6, + 0xf2, 0x88, 0xd9, 0xf7, 0xa0, 0xbf, 0x41, 0x0f, 0x75, 0xc2, 0x8c, 0x34, 0xe6, 0x2d, 0x68, 0x16, + 0x29, 0xc3, 0x42, 0x15, 0x13, 0xc5, 0x73, 0xbe, 0x1d, 0x4f, 0x84, 0x43, 0x68, 0xfb, 0xaf, 0x9b, + 0xd0, 0x3e, 0x10, 0x79, 0xea, 0xf3, 0x2f, 0xbe, 0x63, 0xf6, 0xba, 0x11, 0x8c, 0xb8, 0xbc, 0x78, + 0xa0, 0x64, 0x80, 0xd0, 0x8b, 0x25, 0xd3, 0x6e, 0x99, 0x8d, 0xbc, 0x0c, 0x2d, 0x15, 0x04, 0xaa, + 0xbb, 0x49, 0xaa, 0x43, 0x87, 0x22, 0xcf, 0x8e, 0xe9, 0x35, 0x4e, 0xa8, 0xae, 0xb1, 0x37, 0x1d, + 0x30, 0xa0, 0xed, 0x80, 0x82, 0x7a, 0x43, 0x40, 0xa7, 0xae, 0xad, 0x22, 0x01, 0x03, 0xa4, 0xb3, + 0x67, 0x32, 0x9d, 0x9d, 0x17, 0x64, 0x3a, 0xdf, 0x80, 0x66, 0x6c, 0xee, 0xc4, 0x14, 0x78, 0x7a, + 0x3c, 0x41, 0x70, 0x76, 0x07, 0x8a, 0x8b, 0x71, 0xda, 0xf9, 0x78, 0xf1, 0xc5, 0xb9, 0x75, 0xe8, + 0x16, 0x4f, 0xbb, 0xb4, 0xbf, 0x71, 0x79, 0xad, 0x7c, 0xec, 0x75, 0x68, 0x5a, 0x4e, 0x49, 0xf6, + 0xf2, 0x7c, 0x5d, 0xef, 0x6b, 0xe5, 0xeb, 0x74, 0x30, 0xe6, 0x8b, 0x38, 0x93, 0x3a, 0x6d, 0xd1, + 0x09, 0xb3, 0x4d, 0xec, 0xb2, 0xef, 0xc0, 0x20, 0xe5, 0xfe, 0x53, 0x77, 0x96, 0x4d, 0xd5, 0x4f, + 0x0c, 0xaa, 0x57, 0x6d, 0x67, 0xd9, 0xf4, 0x13, 0xca, 0x25, 0xea, 0xd8, 0xa8, 0x87, 0xb4, 0xbb, + 0xd9, 0x94, 0x66, 0x7d, 0x07, 0x96, 0x67, 0x7c, 0x76, 0xc4, 0xd3, 0xec, 0x38, 0x4c, 0x8c, 0x76, + 0x1c, 0x52, 0xce, 0x73, 0x54, 0x22, 0xd4, 0x5a, 0xec, 0xdf, 0xab, 0x81, 0x85, 0x5c, 0x44, 0x59, + 0x62, 0x0c, 0x9a, 0x33, 0x3f, 0xc9, 0xb5, 0xcb, 0x4b, 0x6d, 0xfd, 0x5c, 0x4c, 0x49, 0x89, 0x7e, + 0x2e, 0x46, 0x7b, 0xd8, 0x50, 0xa9, 0x44, 0x6c, 0xab, 0x07, 0x1b, 0x67, 0x94, 0xaf, 0x51, 0x92, + 0x61, 0xba, 0xec, 0x0a, 0xb4, 0xfd, 0x98, 0xe2, 0x5e, 0x75, 0x53, 0xaa, 0xe5, 0xc7, 0x18, 0xef, + 0x2a, 0x70, 0x79, 0x41, 0xa3, 0xe5, 0xc7, 0xdb, 0xc1, 0xa9, 0xfd, 0x17, 0x35, 0x58, 0xde, 0x4f, + 0x85, 0xcf, 0xb3, 0x6c, 0x07, 0x4d, 0xb6, 0x47, 0x3e, 0x17, 0x83, 0x26, 0xe5, 0xdb, 0xd4, 0xeb, + 0x07, 0x6a, 0xa3, 0x0c, 0xab, 0xa4, 0x44, 0x11, 0x58, 0x34, 0x9c, 0x2e, 0x41, 0x28, 0xae, 0x28, + 0xd0, 0x34, 0xb0, 0x51, 0x41, 0x53, 0xa6, 0xee, 0x16, 0x0c, 0xcb, 0x6b, 0x4b, 0x95, 0xe4, 0x61, + 0x79, 0x99, 0x9c, 0x66, 0x79, 0x13, 0x7a, 0x3a, 0xc5, 0x4b, 0xd3, 0xa8, 0x44, 0x22, 0x28, 0x10, + 0xce, 0x63, 0xff, 0x6f, 0x18, 0xed, 0xa7, 0x3c, 0xf1, 0x52, 0x4e, 0x39, 0x5d, 0xe2, 0xe1, 0x55, + 0x68, 0x47, 0x3c, 0x9e, 0xca, 0x63, 0xbd, 0x5e, 0xdd, 0x2b, 0x9e, 0xf2, 0xd5, 0x2b, 0x4f, 0xf9, + 0x90, 0x97, 0x29, 0xf7, 0xf4, 0x8b, 0x3f, 0x6a, 0xe3, 0x19, 0xc3, 0xe8, 0x4f, 0x85, 0x38, 0x96, + 0xa3, 0x3a, 0xfa, 0x12, 0xeb, 0x51, 0x18, 0x53, 0x3d, 0x8c, 0x2e, 0xb1, 0xde, 0x0f, 0x63, 0xfb, + 0xef, 0x1a, 0xd0, 0xd3, 0x0c, 0xa3, 0x1f, 0x57, 0x9b, 0x55, 0x2b, 0x36, 0x6b, 0x04, 0x8d, 0xec, + 0x49, 0xa4, 0x77, 0x0f, 0x9b, 0xec, 0x43, 0x68, 0x44, 0xe1, 0x4c, 0x47, 0x2b, 0x37, 0xe6, 0x4c, + 0xc8, 0x3c, 0xdb, 0xb5, 0x64, 0x21, 0x35, 0xea, 0x2d, 0xba, 0xce, 0x8e, 0x32, 0xac, 0x59, 0x85, + 0xea, 0xfc, 0x14, 0x0f, 0x0a, 0xf2, 0xda, 0xf3, 0xe9, 0x42, 0xa8, 0x39, 0xfd, 0x03, 0xa7, 0xab, + 0x21, 0xdb, 0x01, 0xfb, 0x08, 0xac, 0x2c, 0xf6, 0x92, 0xec, 0x58, 0xc8, 0x22, 0x3e, 0x91, 0xa7, + 0xf1, 0xda, 0xe6, 0xde, 0xe1, 0x69, 0x7c, 0xa0, 0x31, 0xfa, 0xc7, 0x0a, 0x4a, 0xf6, 0x43, 0xe8, + 0x67, 0x3c, 0xcb, 0xd4, 0x0d, 0xe5, 0x89, 0xd0, 0x5a, 0xe1, 0x4a, 0x35, 0xf4, 0x20, 0x2c, 0x7e, + 0xb5, 0x39, 0x03, 0x59, 0x09, 0x62, 0x9f, 0xc0, 0xd0, 0x8c, 0x8f, 0xc4, 0x74, 0x5a, 0xe4, 0x30, + 0x6f, 0x9c, 0x9b, 0x61, 0x87, 0xd0, 0x95, 0x79, 0x06, 0x59, 0x15, 0xc1, 0x7e, 0x02, 0xc3, 0x44, + 0xed, 0xb1, 0xab, 0xcb, 0x07, 0x4a, 0xbb, 0x5c, 0x9f, 0xf3, 0x78, 0xe6, 0x64, 0xa0, 0xbc, 0x75, + 0x58, 0xc2, 0xb3, 0xf3, 0x77, 0xef, 0x81, 0x18, 0x39, 0x77, 0xf7, 0xde, 0xfe, 0xc3, 0x3a, 0xf4, + 0x2a, 0x9f, 0x46, 0x8f, 0x33, 0x33, 0x9e, 0x9a, 0xc4, 0x3d, 0xb6, 0x11, 0x76, 0x2c, 0xf4, 0xdb, + 0x9f, 0xae, 0x43, 0x6d, 0x84, 0xa5, 0x42, 0x97, 0xa9, 0xba, 0x0e, 0xb5, 0xf1, 0x07, 0x75, 0xe0, + 0xa9, 0x5e, 0x47, 0xd0, 0xce, 0x35, 0x9d, 0x7e, 0x09, 0xdc, 0x0e, 0xe8, 0x15, 0xa7, 0x27, 0xbd, + 0x23, 0x2f, 0x33, 0x15, 0x90, 0xa2, 0x8f, 0xc7, 0xfa, 0x29, 0x4f, 0x71, 0x2d, 0x5a, 0x63, 0x9b, + 0x2e, 0x0a, 0x04, 0x69, 0xc2, 0xe7, 0x22, 0x56, 0x0f, 0x68, 0xfa, 0x8e, 0x85, 0x80, 0xcf, 0x44, + 0x4c, 0xc3, 0xf4, 0xf6, 0x13, 0xd3, 0xbb, 0x8e, 0xe9, 0xa2, 0xbe, 0x7b, 0x92, 0x73, 0x74, 0x1d, + 0x03, 0xba, 0x43, 0xd5, 0x75, 0x3a, 0xd4, 0xdf, 0x0e, 0xd8, 0x1d, 0xa0, 0x8b, 0x88, 0xee, 0x33, + 0x2f, 0x94, 0x24, 0x67, 0x22, 0x97, 0x9a, 0x43, 0x4b, 0x88, 0xf8, 0xd4, 0x0b, 0xe5, 0xa1, 0x02, + 0xdb, 0xff, 0x52, 0x83, 0xe5, 0x73, 0xbb, 0x87, 0x5e, 0x1d, 0xee, 0x9c, 0xb9, 0x5d, 0xda, 0x77, + 0xda, 0xd8, 0xdd, 0x0e, 0x08, 0x21, 0x67, 0x24, 0x9d, 0x75, 0x8d, 0x90, 0x33, 0x14, 0xcd, 0x2b, + 0xd0, 0x96, 0xa7, 0xc4, 0x19, 0x75, 0x00, 0x5b, 0xf2, 0x14, 0x59, 0xb2, 0x81, 0x11, 0xf2, 0xd4, + 0x8d, 0xf8, 0x53, 0x1e, 0x11, 0xcf, 0x86, 0xeb, 0x37, 0x5f, 0x22, 0x36, 0x6b, 0x3b, 0x62, 0xba, + 0x83, 0xb4, 0x18, 0x33, 0xab, 0x96, 0xfd, 0x53, 0xb0, 0x0c, 0x94, 0x75, 0xa1, 0xb5, 0xc5, 0x8f, + 0xf2, 0xe9, 0xe8, 0x15, 0x66, 0x41, 0x13, 0x47, 0x8c, 0x6a, 0xd8, 0xfa, 0xd4, 0x4b, 0xe3, 0x51, + 0x1d, 0xd1, 0x0f, 0xd2, 0x54, 0xa4, 0xa3, 0x06, 0x36, 0xf7, 0xbd, 0x38, 0xf4, 0x47, 0x4d, 0x6c, + 0x3e, 0xf4, 0xa4, 0x17, 0x8d, 0x5a, 0xf6, 0x2f, 0x5a, 0x60, 0xed, 0xeb, 0x5f, 0x67, 0x5b, 0x30, + 0x28, 0x5e, 0xa8, 0x5e, 0x9c, 0x95, 0xd9, 0x5f, 0x6c, 0x50, 0x56, 0xa6, 0x9f, 0x54, 0x7a, 0x8b, + 0xef, 0x5c, 0xeb, 0xe7, 0xde, 0xb9, 0xbe, 0x06, 0x8d, 0x27, 0xe9, 0xd9, 0x7c, 0xd5, 0x71, 0x3f, + 0xf2, 0x62, 0x07, 0xc1, 0xec, 0x03, 0xe8, 0xa1, 0x8c, 0xb8, 0x19, 0x39, 0x1c, 0x3a, 0x93, 0x51, + 0x7d, 0xf7, 0x4c, 0x70, 0x07, 0x90, 0x48, 0x3b, 0x25, 0x6b, 0x60, 0xf9, 0xc7, 0x61, 0x14, 0xa4, + 0x3c, 0xd6, 0x15, 0x7d, 0x76, 0x7e, 0xc9, 0x4e, 0x41, 0xc3, 0x7e, 0x0c, 0xa3, 0xb0, 0xcc, 0xc4, + 0x94, 0xe5, 0x8c, 0x39, 0x1d, 0x50, 0xc9, 0xd5, 0x38, 0x4b, 0x15, 0x72, 0xb2, 0x82, 0xe5, 0xb5, + 0xff, 0x4e, 0xf5, 0xda, 0xbf, 0x7a, 0xcd, 0x48, 0xa6, 0xca, 0x2a, 0xe2, 0x38, 0xb4, 0x54, 0xb7, + 0xb5, 0x7f, 0xd1, 0x5d, 0xf4, 0x60, 0x8d, 0x75, 0xd4, 0x7e, 0xc6, 0x4d, 0x18, 0xa2, 0xdf, 0xe2, + 0x2a, 0x77, 0x07, 0x75, 0x13, 0xe8, 0x37, 0x47, 0x79, 0x76, 0xbc, 0x85, 0x0e, 0x0f, 0x0a, 0xe3, + 0x2d, 0x18, 0x9a, 0x6f, 0xd1, 0x97, 0xe5, 0x7b, 0xba, 0xdc, 0xa1, 0xa1, 0xea, 0xa2, 0xfc, 0x1a, + 0x5c, 0xf2, 0x8f, 0xbd, 0x38, 0xe6, 0x91, 0x7b, 0x94, 0x4f, 0x26, 0xc6, 0xd2, 0xf4, 0x29, 0x51, + 0xb8, 0xac, 0x51, 0xf7, 0x09, 0x43, 0x86, 0xcb, 0x86, 0x41, 0x1c, 0x46, 0x2a, 0x1b, 0x4e, 0x56, + 0x75, 0x40, 0x94, 0xbd, 0x38, 0x8c, 0x28, 0x1d, 0x8e, 0xb6, 0xf5, 0x47, 0x30, 0xca, 0xf3, 0x30, + 0xc8, 0x5c, 0x29, 0xcc, 0x43, 0x50, 0x9d, 0x53, 0xad, 0x64, 0x29, 0x1e, 0xe7, 0x61, 0x70, 0x28, + 0xf4, 0x53, 0xd0, 0x01, 0xd1, 0x9b, 0xae, 0xfd, 0x23, 0xe8, 0x57, 0x65, 0x07, 0x65, 0x91, 0xc2, + 0xc8, 0xd1, 0x2b, 0x0c, 0xa0, 0xbd, 0x27, 0xd2, 0x99, 0x17, 0x8d, 0x6a, 0xd8, 0x56, 0x8f, 0x61, + 0x46, 0x75, 0xd6, 0x07, 0xcb, 0xc4, 0x37, 0xa3, 0x86, 0xfd, 0x3d, 0xb0, 0xcc, 0xcb, 0x56, 0x7a, + 0x52, 0x28, 0x02, 0xae, 0xfc, 0x3e, 0xa5, 0xc5, 0x2c, 0x04, 0x90, 0xcf, 0x67, 0x9e, 0x9e, 0xd7, + 0xcb, 0xa7, 0xe7, 0xf6, 0xff, 0x80, 0x7e, 0x75, 0x71, 0x26, 0xe9, 0x56, 0x2b, 0x93, 0x6e, 0x17, + 0x8c, 0xa2, 0xba, 0x57, 0x2a, 0x66, 0x6e, 0xc5, 0x35, 0xb1, 0x10, 0x80, 0x3f, 0x63, 0xff, 0xff, + 0x1a, 0xb4, 0xc8, 0xdf, 0x27, 0x5b, 0x85, 0x8d, 0xf2, 0xec, 0xb4, 0x9c, 0x2e, 0x41, 0xfe, 0x13, + 0x17, 0x09, 0x8b, 0x22, 0x4c, 0xf3, 0xa5, 0x45, 0x98, 0x3b, 0x7f, 0x52, 0x83, 0xb6, 0x7a, 0xee, + 0xcf, 0x96, 0x61, 0xf0, 0x38, 0x3e, 0x89, 0xc5, 0xb3, 0x58, 0x01, 0x46, 0xaf, 0xb0, 0x4b, 0xb0, + 0x64, 0xb8, 0xae, 0xff, 0xaf, 0xc0, 0xa8, 0xc6, 0x46, 0xd0, 0xa7, 0x7d, 0x35, 0x90, 0x3a, 0x7b, + 0x0d, 0xc6, 0xda, 0xdc, 0x6c, 0x89, 0x98, 0xef, 0x09, 0x19, 0x4e, 0xce, 0x0c, 0xb6, 0xc1, 0x96, + 0xa0, 0x77, 0x20, 0x45, 0x72, 0xc0, 0xe3, 0x20, 0x8c, 0xa7, 0xa3, 0x26, 0x1b, 0xc3, 0x65, 0x33, + 0xab, 0x8a, 0xee, 0x1f, 0x86, 0x71, 0x98, 0x1d, 0x8f, 0x5a, 0xec, 0x06, 0x5c, 0xbb, 0x08, 0xb3, + 0xe1, 0x9f, 0x8c, 0xda, 0x77, 0x3e, 0x02, 0x76, 0xfe, 0x05, 0x3d, 0xce, 0xbe, 0xc3, 0xa7, 0x9e, + 0x7f, 0xb6, 0x19, 0x89, 0x0c, 0xc5, 0x61, 0x00, 0xdd, 0x72, 0x54, 0xed, 0xce, 0x43, 0x68, 0xab, + 0x7f, 0x79, 0x50, 0xf9, 0x3e, 0x05, 0x18, 0xbd, 0x82, 0x83, 0x51, 0x87, 0x87, 0xf1, 0x74, 0x8f, + 0x9f, 0x4a, 0xa5, 0x02, 0x77, 0xbc, 0x4c, 0x8e, 0xea, 0x6c, 0x08, 0xa0, 0x3f, 0xe1, 0x41, 0x1c, + 0x8c, 0x1a, 0xf7, 0x37, 0x7f, 0xf9, 0xab, 0x37, 0x6a, 0x7f, 0xff, 0xab, 0x37, 0x6a, 0xff, 0xfc, + 0xab, 0x37, 0x5e, 0xf9, 0xf9, 0xaf, 0xdf, 0xa8, 0x7d, 0xf6, 0x41, 0xe5, 0x1f, 0x3a, 0xcc, 0x3c, + 0x99, 0x86, 0xa7, 0xaa, 0x4e, 0x69, 0x3a, 0x31, 0xbf, 0x9b, 0x9c, 0x4c, 0xef, 0x26, 0x47, 0x77, + 0x8d, 0x84, 0x1f, 0xb5, 0xe9, 0xff, 0x34, 0x7c, 0xf8, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf6, + 0x52, 0xf0, 0x25, 0x26, 0x42, 0x00, 0x00, } func (m *Message) Marshal() (dAtA []byte, err error) { @@ -10505,6 +10514,19 @@ func (m *PrepareParamInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.IsBin) > 0 { + for iNdEx := len(m.IsBin) - 1; iNdEx >= 0; iNdEx-- { + i-- + if m.IsBin[iNdEx] { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + } + i = encodeVarintPipeline(dAtA, i, uint64(len(m.IsBin))) + i-- + dAtA[i] = 0x2a + } if len(m.Nulls) > 0 { for iNdEx := len(m.Nulls) - 1; iNdEx >= 0; iNdEx-- { i-- @@ -13108,6 +13130,9 @@ func (m *PrepareParamInfo) ProtoSize() (n int) { if len(m.Nulls) > 0 { n += 1 + sovPipeline(uint64(len(m.Nulls))) + len(m.Nulls)*1 } + if len(m.IsBin) > 0 { + n += 1 + sovPipeline(uint64(len(m.IsBin))) + len(m.IsBin)*1 + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -26481,6 +26506,76 @@ func (m *PrepareParamInfo) Unmarshal(dAtA []byte) error { } else { return fmt.Errorf("proto: wrong wireType = %d for field Nulls", wireType) } + case 5: + if wireType == 0 { + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPipeline + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsBin = append(m.IsBin, bool(v != 0)) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPipeline + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthPipeline + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthPipeline + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + elementCount = packedLen + if elementCount != 0 && len(m.IsBin) == 0 { + m.IsBin = make([]bool, 0, elementCount) + } + for iNdEx < postIndex { + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPipeline + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsBin = append(m.IsBin, bool(v != 0)) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field IsBin", wireType) + } default: iNdEx = preIndex skippy, err := skipPipeline(dAtA[iNdEx:]) diff --git a/pkg/sql/colexec/evalExpression.go b/pkg/sql/colexec/evalExpression.go index bbaa366e253e6..54afd602039a7 100644 --- a/pkg/sql/colexec/evalExpression.go +++ b/pkg/sql/colexec/evalExpression.go @@ -302,6 +302,9 @@ func (expr *ParamExpressionExecutor) Eval(proc *process.Process, _ []*batch.Batc } else { err = vector.SetConstBytes(expr.vec, val, 1, proc.GetMPool()) } + if err == nil { + expr.vec.SetIsBin(proc.GetPrepareParamIsBin(expr.pos)) + } return expr.vec, err } @@ -358,11 +361,21 @@ func (expr *VarExpressionExecutor) Eval(proc *process.Process, batches []*batch. if err != nil { return nil, err } + isBin := false + if resolveIsBin := proc.GetResolveVariableIsBinFunc(); resolveIsBin != nil { + isBin, err = resolveIsBin(expr.name, expr.system, expr.global) + if err != nil { + return nil, err + } + } if val == nil { if expr.null == nil { expr.null, err = util.GenVectorByVarValue(proc, expr.typ, nil) } + if err == nil { + expr.null.SetIsBin(isBin) + } return expr.null, err } @@ -378,6 +391,9 @@ func (expr *VarExpressionExecutor) Eval(proc *process.Process, batches []*batch. err = vector.SetConstBytes(expr.vec, util2.UnsafeStringToBytes(fmt.Sprintf("%v", v)), 1, proc.GetMPool()) } } + if err == nil { + expr.vec.SetIsBin(isBin) + } return expr.vec, err } diff --git a/pkg/sql/colexec/evalExpression_test.go b/pkg/sql/colexec/evalExpression_test.go index 913037c24186c..2e4ec304ab39b 100644 --- a/pkg/sql/colexec/evalExpression_test.go +++ b/pkg/sql/colexec/evalExpression_test.go @@ -93,6 +93,30 @@ func TestListExpressionExecutor(t *testing.T) { require.Equal(t, curr, proc.Mp().CurrNB()) } +func TestParamExpressionExecutorPreservesBinaryFlagPerParameter(t *testing.T) { + proc := testutil.NewProcess(t) + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, []byte("AB\x00\x00"), false, proc.Mp())) + require.NoError(t, vector.AppendBytes(params, []byte("text"), false, proc.Mp())) + proc.SetPrepareParamsWithIsBin(params, []bool{true, false}) + t.Cleanup(func() { params.Free(proc.Mp()) }) + + binaryExpr := NewParamExpressionExecutor(proc.Mp(), 0, types.T_text.ToType()) + textExpr := NewParamExpressionExecutor(proc.Mp(), 1, types.T_text.ToType()) + t.Cleanup(binaryExpr.Free) + t.Cleanup(textExpr.Free) + + binaryVec, err := binaryExpr.Eval(proc, nil, nil) + require.NoError(t, err) + require.True(t, binaryVec.GetIsBin()) + require.Equal(t, "AB\x00\x00", binaryVec.GetStringAt(0)) + + textVec, err := textExpr.Eval(proc, nil, nil) + require.NoError(t, err) + require.False(t, textVec.GetIsBin()) + require.Equal(t, "text", textVec.GetStringAt(0)) +} + func TestFixedExpressionExecutor(t *testing.T) { proc := testutil.NewProcess(t) @@ -242,6 +266,42 @@ func TestVarExpressionExecutor(t *testing.T) { // require.Equal(t, int64(0), proc.Mp().CurrNB()) } +func TestVarExpressionExecutorPreservesBinaryFlagOnReuse(t *testing.T) { + proc := testutil.NewProcess(t) + value := "AB\x00\x00" + isBin := true + proc.SetResolveVariableFunc(func(string, bool, bool) (interface{}, error) { + return value, nil + }) + proc.SetResolveVariableIsBinFunc(func(string, bool, bool) (bool, error) { + return isBin, nil + }) + expr := &plan.Expr{ + Expr: &plan.Expr_V{V: &plan.VarRef{Name: "copied_var"}}, + Typ: plan.Type{Id: int32(types.T_text)}, + } + executor, err := NewExpressionExecutor(proc, expr) + require.NoError(t, err) + t.Cleanup(executor.Free) + + vec, err := executor.Eval(proc, nil, nil) + require.NoError(t, err) + require.True(t, vec.GetIsBin()) + require.Equal(t, "AB\x00\x00", vec.GetStringAt(0)) + + value, isBin = "text", false + vec, err = executor.Eval(proc, nil, nil) + require.NoError(t, err) + require.False(t, vec.GetIsBin()) + require.Equal(t, "text", vec.GetStringAt(0)) + + value, isBin = "CD\x00\x00", true + vec, err = executor.Eval(proc, nil, nil) + require.NoError(t, err) + require.True(t, vec.GetIsBin()) + require.Equal(t, "CD\x00\x00", vec.GetStringAt(0)) +} + func TestVarExpressionExecutorWithoutResolveVariableFunc(t *testing.T) { proc := testutil.NewProcess(t) varExpr := &plan.Expr{ diff --git a/pkg/sql/compile/compile2.go b/pkg/sql/compile/compile2.go index 5f0bc98e5c47e..5850a71f0660a 100644 --- a/pkg/sql/compile/compile2.go +++ b/pkg/sql/compile/compile2.go @@ -292,7 +292,7 @@ func (c *Compile) Run(_ uint64) (queryResult *util2.RunResult, err error) { retryTimes++ if runC != c { - runC.Release() + releaseRetryCompile(runC) } c.retryTimes = retryTimes defChanged := moerr.IsMoErrCode(err, moerr.ErrTxnNeedRetryWithDefChanged) @@ -351,6 +351,13 @@ func (c *Compile) Run(_ uint64) (queryResult *util2.RunResult, err error) { return queryResult, err } +func releaseRetryCompile(c *Compile) { + proc := c.proc + prepareParams := proc.DetachPrepareParams() + defer proc.RestorePrepareParams(prepareParams) + c.Release() +} + // rewriteAutoModeToPre recursively traverses the AST and rewrites 'mode=auto' to 'mode=pre' // in the RankOption of vector search queries. // NOTE: RankOption is configured at the top-level SQL, so deep traversal here is defensive. diff --git a/pkg/sql/compile/compile_test.go b/pkg/sql/compile/compile_test.go index c3c8509f2fc6e..71ed3afc8c31f 100644 --- a/pkg/sql/compile/compile_test.go +++ b/pkg/sql/compile/compile_test.go @@ -70,6 +70,25 @@ type compileTestCase struct { txnClient client.TxnClient // Store txnClient for truncating table with real transaction } +func TestReleaseRetryCompilePreservesPrepareParams(t *testing.T) { + proc := testutil.NewProcess(t) + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, []byte("binary"), false, proc.Mp())) + proc.SetOwnedPrepareParamsWithIsBin(params, []bool{true}) + + for range 2 { + retryCompile := NewCompile("", "", "", "", "", nil, proc, nil, false, nil, time.Time{}) + releaseRetryCompile(retryCompile) + require.Same(t, params, proc.GetPrepareParams()) + require.True(t, proc.GetPrepareParamIsBin(0)) + require.Equal(t, 1, params.Length()) + } + + proc.Free() + require.Zero(t, params.Length()) + require.Nil(t, params.GetData()) +} + func testPrint(_ *batch.Batch, crs *perfcounter.CounterSet) error { return nil } diff --git a/pkg/sql/compile/remoterunServer.go b/pkg/sql/compile/remoterunServer.go index 469232b2003cc..d65b01c98b1de 100644 --- a/pkg/sql/compile/remoterunServer.go +++ b/pkg/sql/compile/remoterunServer.go @@ -499,7 +499,7 @@ type processHelper struct { sessionInfo process.SessionInfo //analysisNodeList []int32 StmtId uuid.UUID - prepareParams *vector.Vector + prepareParams pipeline.PrepareParamInfo affectedRows int64 } @@ -645,7 +645,26 @@ func (receiver *messageReceiverOnServer) newCompile() (*Compile, error) { proc.Base.Lim = pHelper.lim proc.Base.SessionInfo = pHelper.sessionInfo proc.Base.SessionInfo.StorageEngine = cnInfo.storeEngine - proc.SetPrepareParams(pHelper.prepareParams) + if pHelper.prepareParams.Length > 0 { + prepareParams, err := vector.NewVecWithDataCopy( + types.T_text.ToType(), + int(pHelper.prepareParams.Length), + pHelper.prepareParams.Data, + pHelper.prepareParams.Area, + proc.Mp(), + ) + if err != nil { + proc.Free() + mpool.DeleteMPool(mp) + return nil, err + } + for i := range pHelper.prepareParams.Nulls { + if pHelper.prepareParams.Nulls[i] { + prepareParams.GetNulls().Add(uint64(i)) + } + } + proc.SetOwnedPrepareParamsWithIsBin(prepareParams, append([]bool(nil), pHelper.prepareParams.IsBin...)) + } // Carry ROW_COUNT() state so row_count() pushed down to this remote CN reads // the previous statement's affected rows instead of the default 0. proc.SetAffectedRows(pHelper.affectedRows) @@ -768,19 +787,6 @@ func generateProcessHelper(ctx context.Context, data []byte, cli client.TxnClien txnClient: cli, affectedRows: procInfo.AffectedRows, } - if procInfo.PrepareParams.Length > 0 { - result.prepareParams = vector.NewVecWithData( - types.T_text.ToType(), - int(procInfo.PrepareParams.Length), - procInfo.PrepareParams.Data, - procInfo.PrepareParams.Area, - ) - for i := range procInfo.PrepareParams.Nulls { - if procInfo.PrepareParams.Nulls[i] { - result.prepareParams.GetNulls().Add(uint64(i)) - } - } - } result.txnOperator, err = cli.NewWithSnapshot(ctx, procInfo.Snapshot) if err != nil { return processHelper{}, err @@ -789,6 +795,7 @@ func generateProcessHelper(ctx context.Context, data []byte, cli client.TxnClien if err != nil { return processHelper{}, err } + result.prepareParams = procInfo.PrepareParams if sessLogger := procInfo.SessionLogger; len(sessLogger.SessId) > 0 { copy(result.sessionInfo.SessionId[:], sessLogger.SessId) copy(result.StmtId[:], sessLogger.StmtId) diff --git a/pkg/sql/compile/remoterunServer_test.go b/pkg/sql/compile/remoterunServer_test.go index 282836e07315a..abcee4144ecea 100644 --- a/pkg/sql/compile/remoterunServer_test.go +++ b/pkg/sql/compile/remoterunServer_test.go @@ -28,6 +28,8 @@ import ( "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/morpc" mock_morpc "github.com/matrixorigin/matrixone/pkg/common/morpc/mock_morpc" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/defines" mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" "github.com/matrixorigin/matrixone/pkg/pb/pipeline" @@ -197,6 +199,11 @@ func TestNewCompile_CreatesCorrectStructure(t *testing.T) { txnOperator.EXPECT().Status().Return(txn.TxnStatus_Active).AnyTimes() txnClient := mock_frontend.NewMockTxnClient(ctrl) txnClient.EXPECT().New(gomock.Any(), gomock.Any()).Return(txnOperator, nil).AnyTimes() + sourceProc := testutil.NewProcess(t) + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, []byte("AB\x00\x00"), false, sourceProc.Mp())) + require.NoError(t, vector.AppendBytes(params, []byte("text"), false, sourceProc.Mp())) + t.Cleanup(func() { params.Free(sourceProc.Mp()) }) receiver := &messageReceiverOnServer{ colexecServer: colexec.GetServer(""), @@ -207,11 +214,19 @@ func TestNewCompile_CreatesCorrectStructure(t *testing.T) { storeEngine: mockEngine, }, procBuildHelper: processHelper{ - id: "test-proc-id", - accountId: catalog.System_Account, - unixTime: time.Now().Unix(), - txnClient: txnClient, - txnOperator: txnOperator, + id: "test-proc-id", + accountId: catalog.System_Account, + unixTime: time.Now().Unix(), + affectedRows: 42, + txnClient: txnClient, + txnOperator: txnOperator, + prepareParams: pipeline.PrepareParamInfo{ + Length: 2, + Data: append([]byte(nil), params.GetData()...), + Area: append([]byte(nil), params.GetArea()...), + Nulls: []bool{false, false}, + IsBin: []bool{true, false}, + }, }, messageAcquirer: func() morpc.Message { return &pipeline.Message{} @@ -224,7 +239,16 @@ func TestNewCompile_CreatesCorrectStructure(t *testing.T) { require.Equal(t, "test-addr", compile.addr) require.Equal(t, mockEngine, compile.e) require.NotNil(t, compile.proc) + require.Equal(t, "AB\x00\x00", compile.proc.GetPrepareParams().GetStringAt(0)) + require.Equal(t, "text", compile.proc.GetPrepareParams().GetStringAt(1)) + require.True(t, compile.proc.GetPrepareParamIsBin(0)) + require.False(t, compile.proc.GetPrepareParamIsBin(1)) + require.Equal(t, int64(42), compile.proc.GetAffectedRows()) require.NotNil(t, compile.fill, "fill callback should be set") + remoteParams := compile.proc.GetPrepareParams() + require.NotPanics(t, compile.Release) + require.Nil(t, remoteParams.GetData()) + require.Nil(t, remoteParams.GetArea()) } func TestHandlePipelineMessage_ReleasesCompileOnDecodeError(t *testing.T) { @@ -290,15 +314,29 @@ func TestGenerateProcessHelper_WithSnapshot(t *testing.T) { txnClient.EXPECT().NewWithSnapshot(gomock.Any(), gomock.Any()).Return(txnOperator, nil).Times(1) // Create a valid ProcessInfo + proc := testutil.NewProcess(t) + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, []byte("AB\x00\x00"), false, proc.Mp())) + require.NoError(t, vector.AppendBytes(params, []byte("text"), false, proc.Mp())) + t.Cleanup(func() { params.Free(proc.Mp()) }) + procInfo := &pipeline.ProcessInfo{ - Id: "test-proc-id", - AccountId: catalog.System_Account, - UnixTime: time.Now().Unix(), + Id: "test-proc-id", + AccountId: catalog.System_Account, + UnixTime: time.Now().Unix(), + AffectedRows: 42, Snapshot: txn.CNTxnSnapshot{ Txn: txn.TxnMeta{ ID: []byte("test-txn-id"), }, }, + PrepareParams: pipeline.PrepareParamInfo{ + Length: 2, + Data: append([]byte(nil), params.GetData()...), + Area: append([]byte(nil), params.GetArea()...), + Nulls: []bool{false, false}, + IsBin: []bool{true, false}, + }, } data, err := procInfo.Marshal() @@ -308,6 +346,10 @@ func TestGenerateProcessHelper_WithSnapshot(t *testing.T) { require.NoError(t, err) require.Equal(t, "test-proc-id", helper.id) require.Equal(t, catalog.System_Account, helper.accountId) + require.Equal(t, []bool{true, false}, helper.prepareParams.IsBin) + require.Equal(t, procInfo.PrepareParams.Data, helper.prepareParams.Data) + require.Equal(t, procInfo.PrepareParams.Area, helper.prepareParams.Area) + require.Equal(t, int64(42), helper.affectedRows) require.NotNil(t, helper.txnOperator, "txnOperator should be created from snapshot") // Verify that rebuilt txnOperator has nil workspace (key point for remote run) require.Nil(t, helper.txnOperator.GetWorkspace(), "rebuilt txnOperator should have nil workspace initially") diff --git a/pkg/sql/plan/deepcopy.go b/pkg/sql/plan/deepcopy.go index 6584eeacddc97..62e0d1a99bac8 100644 --- a/pkg/sql/plan/deepcopy.go +++ b/pkg/sql/plan/deepcopy.go @@ -847,7 +847,8 @@ func DeepCopyExpr(expr *Expr) *Expr { case *plan.Expr_Lit: pc := &plan.Literal{ Isnull: item.Lit.GetIsnull(), - Src: item.Lit.Src, + IsBin: item.Lit.GetIsBin(), + Src: DeepCopyExpr(item.Lit.Src), } switch c := item.Lit.Value.(type) { diff --git a/pkg/sql/plan/utils.go b/pkg/sql/plan/utils.go index ddceacba06f8b..90de31cf396da 100644 --- a/pkg/sql/plan/utils.go +++ b/pkg/sql/plan/utils.go @@ -3015,22 +3015,24 @@ func MakeInExpr(ctx context.Context, left *Expr, length int32, data []byte, matc // FillValuesOfParamsInPlan replaces the params by their values func FillValuesOfParamsInPlan(ctx context.Context, preparePlan *Plan, paramVals []any) (*Plan, error) { - copied := preparePlan - - switch pp := copied.Plan.(type) { + switch preparePlan.Plan.(type) { case *plan.Plan_Tcl, *plan.Plan_Dcl: return nil, moerr.NewInvalidInput(ctx, "cannot prepare TCL and DCL statement") + } + + copied := DeepCopyPlan(preparePlan) + switch pp := copied.Plan.(type) { case *plan.Plan_Ddl: if pp.Ddl.Query != nil { - err := replaceParamVals(ctx, preparePlan, paramVals) + err := replaceParamVals(ctx, copied, paramVals) if err != nil { return nil, err } } case *plan.Plan_Query: - err := replaceParamVals(ctx, preparePlan, paramVals) + err := replaceParamVals(ctx, copied, paramVals) if err != nil { return nil, err } @@ -3038,9 +3040,19 @@ func FillValuesOfParamsInPlan(ctx context.Context, preparePlan *Plan, paramVals return copied, nil } +type ParamValue struct { + Value any + IsBin bool +} + func replaceParamVals(ctx context.Context, plan0 *Plan, paramVals []any) error { params := make([]*Expr, len(paramVals)) for i, val := range paramVals { + isBin := false + if param, ok := val.(ParamValue); ok { + val = param.Value + isBin = param.IsBin + } if val == nil { pc := &plan.Literal{ Isnull: true, @@ -3052,7 +3064,7 @@ func replaceParamVals(ctx context.Context, plan0 *Plan, paramVals []any) error { }, } } else { - pc := &plan.Literal{} + pc := &plan.Literal{IsBin: isBin} pc.Value = &plan.Literal_Sval{Sval: fmt.Sprintf("%v", val)} params[i] = &plan.Expr{ Expr: &plan.Expr_Lit{ diff --git a/pkg/sql/plan/utils_test.go b/pkg/sql/plan/utils_test.go index 81c7b84c94e7c..dc10cc0c1ff84 100644 --- a/pkg/sql/plan/utils_test.go +++ b/pkg/sql/plan/utils_test.go @@ -135,6 +135,63 @@ func TestHasTrailingZeros(t *testing.T) { } } +func TestFillValuesOfParamsInPlanDoesNotMutatePreparedPlan(t *testing.T) { + source := &plan.Expr{Expr: &plan.Expr_P{P: &plan.ParamRef{Pos: 1}}} + binaryLiteral := &plan.Expr{Expr: &plan.Expr_Lit{Lit: &plan.Literal{ + Value: &plan.Literal_Sval{Sval: "AB\x00\x00"}, + IsBin: true, + Src: source, + }}} + queryPlan := &plan.Plan{ + Plan: &plan.Plan_Query{Query: &plan.Query{ + Steps: []int32{0}, + Nodes: []*plan.Node{{ + NodeType: plan.Node_VALUE_SCAN, + Limit: &plan.Expr{Expr: &plan.Expr_P{P: &plan.ParamRef{Pos: 0}}}, + Offset: binaryLiteral, + }}, + }}, + } + + tests := []struct { + value string + isBin bool + }{ + {value: "AB\x00\x00", isBin: true}, + {value: "text", isBin: false}, + {value: "CD\x00\x00", isBin: true}, + } + for _, test := range tests { + filled, err := FillValuesOfParamsInPlan(context.Background(), queryPlan, []any{ + ParamValue{Value: test.value, IsBin: test.isBin}, + }) + require.NoError(t, err) + literal := filled.GetQuery().Nodes[0].Limit.GetLit() + require.NotNil(t, literal) + require.Equal(t, test.isBin, literal.GetIsBin()) + require.Equal(t, test.value, literal.GetSval()) + require.NotSame(t, queryPlan, filled) + require.NotNil(t, queryPlan.GetQuery().Nodes[0].Limit.GetP()) + copiedLiteral := filled.GetQuery().Nodes[0].Offset.GetLit() + require.True(t, copiedLiteral.GetIsBin()) + require.Equal(t, "AB\x00\x00", copiedLiteral.GetSval()) + require.NotSame(t, source, copiedLiteral.GetSrc()) + require.NotNil(t, binaryLiteral.GetLit().GetSrc().GetP()) + } +} + +func TestFillValuesOfParamsInPlanRejectsControlStatements(t *testing.T) { + _, err := FillValuesOfParamsInPlan(context.Background(), &plan.Plan{ + Plan: &plan.Plan_Tcl{Tcl: &plan.TransationControl{}}, + }, nil) + require.Error(t, err) + + _, err = FillValuesOfParamsInPlan(context.Background(), &plan.Plan{ + Plan: &plan.Plan_Dcl{Dcl: &plan.DataControl{}}, + }, nil) + require.Error(t, err) +} + func TestCheckNoNeedCastWithTrailingZeros(t *testing.T) { tests := []struct { name string diff --git a/pkg/vm/process/process.go b/pkg/vm/process/process.go index 3e2ff08a8d77e..65f83c90ff6d7 100644 --- a/pkg/vm/process/process.go +++ b/pkg/vm/process/process.go @@ -151,8 +151,60 @@ func (proc *Process) GetPrepareParams() *vector.Vector { return proc.Base.prepareParams } +// SetPrepareParams borrows prepareParams. The caller remains responsible for releasing it. func (proc *Process) SetPrepareParams(prepareParams *vector.Vector) { + proc.setPrepareParams(prepareParams, nil, false) +} + +// SetPrepareParamsWithIsBin borrows prepareParams. The caller remains responsible for releasing it. +func (proc *Process) SetPrepareParamsWithIsBin(prepareParams *vector.Vector, isBin []bool) { + proc.setPrepareParams(prepareParams, isBin, false) +} + +// SetOwnedPrepareParamsWithIsBin transfers prepareParams to proc. Replacing or freeing proc releases it. +func (proc *Process) SetOwnedPrepareParamsWithIsBin(prepareParams *vector.Vector, isBin []bool) { + proc.setPrepareParams(prepareParams, isBin, true) +} + +func (proc *Process) setPrepareParams(prepareParams *vector.Vector, isBin []bool, owned bool) { + if proc.Base.prepareParams == prepareParams && proc.Base.prepareParamsOwned { + owned = true + } + if proc.Base.prepareParamsOwned && proc.Base.prepareParams != nil && proc.Base.prepareParams != prepareParams { + proc.Base.prepareParams.Free(proc.Mp()) + } proc.Base.prepareParams = prepareParams + proc.Base.prepareParamsIsBin = isBin + proc.Base.prepareParamsOwned = owned && prepareParams != nil +} + +// PrepareParamsState keeps the complete prepare-parameter state while a +// Compile that shares the Process is being released. +type PrepareParamsState struct { + prepareParams *vector.Vector + isBin []bool + owned bool +} + +// DetachPrepareParams removes the prepare-parameter state without releasing +// the owned vector. The caller must restore the returned state so a later +// Process.Free can release it. +func (proc *Process) DetachPrepareParams() PrepareParamsState { + state := PrepareParamsState{ + prepareParams: proc.Base.prepareParams, + isBin: proc.Base.prepareParamsIsBin, + owned: proc.Base.prepareParamsOwned, + } + proc.Base.prepareParams = nil + proc.Base.prepareParamsIsBin = nil + proc.Base.prepareParamsOwned = false + return state +} + +// RestorePrepareParams restores state previously returned by +// DetachPrepareParams. +func (proc *Process) RestorePrepareParams(state PrepareParamsState) { + proc.setPrepareParams(state.prepareParams, state.isBin, state.owned) } func (proc *Process) OperatorOutofMemory(size int64) bool { diff --git a/pkg/vm/process/process2.go b/pkg/vm/process/process2.go index 3d8b3a19df7bb..33b7d95226328 100644 --- a/pkg/vm/process/process2.go +++ b/pkg/vm/process/process2.go @@ -240,6 +240,7 @@ func (proc *Process) Free() { proc.Base.messageBoard.Reset() proc.Base.messageBoard = nil } + proc.setPrepareParams(nil, nil, false) } type QueryBaseContext struct { diff --git a/pkg/vm/process/process2_test.go b/pkg/vm/process/process2_test.go index 64a1da1fa315b..ca56b3c0db5dc 100644 --- a/pkg/vm/process/process2_test.go +++ b/pkg/vm/process/process2_test.go @@ -18,9 +18,13 @@ import ( "context" "testing" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/defines" "github.com/matrixorigin/matrixone/pkg/fileservice" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestBuildPipelineContext(t *testing.T) { @@ -126,3 +130,61 @@ func TestGetSpillFileServiceError(t *testing.T) { _, err = proc.GetSpillFileService() assert.NotNil(t, err) } + +func TestOwnedPrepareParamsLifecycle(t *testing.T) { + proc := &Process{Base: &BaseProcess{mp: mpool.MustNewZero()}} + newParams := func(value string) *vector.Vector { + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, []byte(value), false, proc.Mp())) + return params + } + + first := newParams("first") + proc.SetOwnedPrepareParamsWithIsBin(first, []bool{true}) + proc.SetPrepareParamsWithIsBin(first, []bool{false}) + require.Equal(t, 1, first.Length(), "setting the same pointer must not release it") + require.True(t, proc.Base.prepareParamsOwned, "setting the same pointer must preserve ownership") + + borrowed := newParams("borrowed") + proc.SetPrepareParams(borrowed) + require.Zero(t, first.Length()) + require.Nil(t, first.GetData()) + require.Equal(t, 1, borrowed.Length()) + require.False(t, proc.Base.prepareParamsOwned) + require.Nil(t, proc.Base.prepareParamsIsBin) + + second := newParams("second") + proc.SetOwnedPrepareParamsWithIsBin(second, []bool{true}) + proc.Free() + require.Zero(t, second.Length()) + require.Nil(t, second.GetData()) + require.Nil(t, proc.GetPrepareParams()) + require.Nil(t, proc.Base.prepareParamsIsBin) + require.False(t, proc.Base.prepareParamsOwned) + require.Equal(t, 1, borrowed.Length(), "Process must not release borrowed params") + borrowed.Free(proc.Mp()) +} + +func TestDetachAndRestorePrepareParams(t *testing.T) { + proc := &Process{Base: &BaseProcess{mp: mpool.MustNewZero()}} + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, []byte("binary"), false, proc.Mp())) + proc.SetOwnedPrepareParamsWithIsBin(params, []bool{true}) + + state := proc.DetachPrepareParams() + require.Nil(t, proc.GetPrepareParams()) + require.False(t, proc.GetPrepareParamIsBin(0)) + require.Equal(t, 1, params.Length(), "detach must not release owned params") + + proc.Free() + require.Equal(t, 1, params.Length(), "transient Process.Free must not release detached params") + + proc.RestorePrepareParams(state) + require.Same(t, params, proc.GetPrepareParams()) + require.True(t, proc.GetPrepareParamIsBin(0)) + require.True(t, proc.Base.prepareParamsOwned) + + proc.Free() + require.Zero(t, params.Length()) + require.Nil(t, params.GetData()) +} diff --git a/pkg/vm/process/process_codec.go b/pkg/vm/process/process_codec.go index 026c897044f27..557699262b174 100644 --- a/pkg/vm/process/process_codec.go +++ b/pkg/vm/process/process_codec.go @@ -80,6 +80,7 @@ func (proc *Process) BuildProcessInfo( for i := range procInfo.PrepareParams.Nulls { procInfo.PrepareParams.Nulls[i] = vec.GetNulls().Contains(uint64(i)) } + procInfo.PrepareParams.IsBin = append(procInfo.PrepareParams.IsBin, proc.Base.prepareParamsIsBin...) } } { // session info @@ -223,17 +224,23 @@ func (c *codecService) Decode( proc.Base.SessionInfo.StorageEngine = c.engine proc.SetAffectedRows(value.AffectedRows) if value.PrepareParams.Length > 0 { - proc.Base.prepareParams = vector.NewVecWithData( + prepareParams, err := vector.NewVecWithDataCopy( types.T_text.ToType(), int(value.PrepareParams.Length), value.PrepareParams.Data, value.PrepareParams.Area, + proc.Mp(), ) + if err != nil { + proc.Free() + return nil, err + } for i := range value.PrepareParams.Nulls { if value.PrepareParams.Nulls[i] { - proc.Base.prepareParams.GetNulls().Add(uint64(i)) + prepareParams.GetNulls().Add(uint64(i)) } } + proc.SetOwnedPrepareParamsWithIsBin(prepareParams, append([]bool(nil), value.PrepareParams.IsBin...)) } return proc, nil } diff --git a/pkg/vm/process/process_codec_test.go b/pkg/vm/process/process_codec_test.go index 505bcf80caffd..a87f83b5bb08c 100644 --- a/pkg/vm/process/process_codec_test.go +++ b/pkg/vm/process/process_codec_test.go @@ -97,7 +97,8 @@ func newCodecTestProcess(t *testing.T) (*Process, client.TxnOperator) { vec := vector.NewVec(types.T_text.ToType()) require.NoError(t, vector.AppendBytes(vec, []byte("a"), false, proc.Mp())) require.NoError(t, vector.AppendBytes(vec, []byte("b"), true, proc.Mp())) - proc.SetPrepareParams(vec) + proc.SetPrepareParamsWithIsBin(vec, []bool{true, false}) + proc.SetAffectedRows(42) return proc, txnOp } @@ -178,6 +179,8 @@ func TestBuildProcessInfoAndMockProcessInfoWithPro(t *testing.T) { require.Equal(t, uint32(42), info.AccountId) require.Equal(t, int64(2), info.PrepareParams.Length) require.Equal(t, []bool{false, true}, info.PrepareParams.Nulls) + require.Equal(t, []bool{true, false}, info.PrepareParams.IsBin) + require.Equal(t, int64(42), info.AffectedRows) require.Equal(t, uint64(99), info.SessionInfo.ConnectionId) require.Equal(t, int64(7), info.SessionInfo.LockWaitTimeout) require.Equal(t, pipeline.SessionLoggerInfo_Warn, info.SessionLogger.LogLevel) @@ -213,6 +216,13 @@ func TestCodecServiceEncodeDecodeAndLookup(t *testing.T) { require.NotNil(t, decodedProc.GetPrepareParams()) require.Equal(t, 2, decodedProc.GetPrepareParams().Length()) require.True(t, decodedProc.GetPrepareParams().GetNulls().Contains(1)) + require.True(t, decodedProc.GetPrepareParamIsBin(0)) + require.False(t, decodedProc.GetPrepareParamIsBin(1)) + require.Equal(t, int64(42), decodedProc.GetAffectedRows()) + decodedParams := decodedProc.GetPrepareParams() + require.NotPanics(t, decodedProc.Free) + require.Nil(t, decodedParams.GetData()) + require.Nil(t, decodedParams.GetArea()) rtSvc := "codec-test-svc" runtime := rt.DefaultRuntime() diff --git a/pkg/vm/process/types.go b/pkg/vm/process/types.go index b808998ebf483..92594b2e38e35 100644 --- a/pkg/vm/process/types.go +++ b/pkg/vm/process/types.go @@ -328,19 +328,22 @@ type BaseProcess struct { // statement in the same session, used by the ROW_COUNT() builtin. // It follows MySQL semantics: -1 after a result-set statement (e.g. SELECT), // 0 after DDL, and the affected row count after DML. - AffectedRows *int64 - LoadLocalReader *io.PipeReader - Aicm *defines.AutoIncrCacheManager - resolveVariableFunc func(varName string, isSystemVar, isGlobalVar bool) (interface{}, error) - prepareParams *vector.Vector - QueryClient qclient.QueryClient - Hakeeper logservice.CNHAKeeperClient - UdfService udf.Service - WaitPolicy lock.WaitPolicy - messageBoard *message.MessageBoard - logger *log.MOLogger - TxnOperator client.TxnOperator - CloneTxnOperator client.TxnOperator + AffectedRows *int64 + LoadLocalReader *io.PipeReader + Aicm *defines.AutoIncrCacheManager + resolveVariableFunc func(varName string, isSystemVar, isGlobalVar bool) (interface{}, error) + resolveVariableIsBinFunc func(varName string, isSystemVar, isGlobalVar bool) (bool, error) + prepareParams *vector.Vector + prepareParamsIsBin []bool + prepareParamsOwned bool + QueryClient qclient.QueryClient + Hakeeper logservice.CNHAKeeperClient + UdfService udf.Service + WaitPolicy lock.WaitPolicy + messageBoard *message.MessageBoard + logger *log.MOLogger + TxnOperator client.TxnOperator + CloneTxnOperator client.TxnOperator // incrStatementDisabled marks a process that executes internal SQL on a // caller-owned transaction without opening a statement of its own // (executor.Options.WithDisableIncrStatement). Compiles on such a process @@ -467,6 +470,10 @@ func (proc *Process) GetPrepareParamsAt(i int) ([]byte, error) { } } +func (proc *Process) GetPrepareParamIsBin(i int) bool { + return i >= 0 && i < len(proc.Base.prepareParamsIsBin) && proc.Base.prepareParamsIsBin[i] +} + // SetIncrStatementDisabled marks this process (and every child process // sharing its BaseProcess) as running internal SQL that must not advance the // workspace snapshot write offset. See BaseProcess.incrStatementDisabled. @@ -488,6 +495,14 @@ func (proc *Process) GetResolveVariableFunc() func(varName string, isSystemVar, return proc.Base.resolveVariableFunc } +func (proc *Process) SetResolveVariableIsBinFunc(f func(varName string, isSystemVar, isGlobalVar bool) (bool, error)) { + proc.Base.resolveVariableIsBinFunc = f +} + +func (proc *Process) GetResolveVariableIsBinFunc() func(varName string, isSystemVar, isGlobalVar bool) (bool, error) { + return proc.Base.resolveVariableIsBinFunc +} + func (proc *Process) SetLastInsertID(num uint64) { if proc.Base.LastInsertID != nil { atomic.StoreUint64(proc.Base.LastInsertID, num) diff --git a/proto/pipeline.proto b/proto/pipeline.proto index 8477f86e9d3e9..870ae32ae454b 100644 --- a/proto/pipeline.proto +++ b/proto/pipeline.proto @@ -550,6 +550,7 @@ message PrepareParamInfo { bytes data = 2; bytes area = 3; repeated bool nulls = 4; + repeated bool is_bin = 5; } message ProcessInfo { diff --git a/test/distributed/cases/prepare/prepare_binary_param.result b/test/distributed/cases/prepare/prepare_binary_param.result new file mode 100644 index 0000000000000..f228464055dda --- /dev/null +++ b/test/distributed/cases/prepare/prepare_binary_param.result @@ -0,0 +1,50 @@ +drop database if exists prepare_binary_param; +create database prepare_binary_param; +use prepare_binary_param; +create table indexed_values ( +id int primary key, +b binary(4), +label varchar(20), +key idx_b (b) +); +create table scanned_values ( +id int primary key, +b binary(4), +label varchar(20) +); +insert into indexed_values values (1, 0x41420000, 'indexed'), (2, 0x43440000, 'other'); +insert into scanned_values values (1, 0x41420000, 'scanned'), (2, 0x43440000, 'other'); +prepare indexed_lookup from 'select id, hex(b), label from indexed_values where b = ? and label = ?'; +prepare scanned_lookup from 'select id, hex(b), label from scanned_values where b = ? and label = ?'; +set @binary_source = (0x41420000); +set @binary_value = @binary_source; +set @indexed_label = 'indexed'; +set @scanned_label = 'scanned'; +execute indexed_lookup using @binary_value, @indexed_label; +➤ id[4,32,0] ¦ hex(b)[12,-1,0] ¦ label[12,-1,0] 𝄀 +1 ¦ 41420000 ¦ indexed +execute scanned_lookup using @binary_value, @scanned_label; +➤ id[4,32,0] ¦ hex(b)[12,-1,0] ¦ label[12,-1,0] 𝄀 +1 ¦ 41420000 ¦ scanned +set @text_source = 'AB'; +set @binary_value = @text_source; +execute indexed_lookup using @binary_value, @indexed_label; +➤ id[4,32,0] ¦ hex(b)[12,-1,0] ¦ label[12,-1,0] +execute scanned_lookup using @binary_value, @scanned_label; +➤ id[4,32,0] ¦ hex(b)[12,-1,0] ¦ label[12,-1,0] +set @binary_value = 0x41420000; +execute indexed_lookup using @binary_value, @indexed_label; +➤ id[4,32,0] ¦ hex(b)[12,-1,0] ¦ label[12,-1,0] 𝄀 +1 ¦ 41420000 ¦ indexed +execute scanned_lookup using @binary_value, @scanned_label; +➤ id[4,32,0] ¦ hex(b)[12,-1,0] ¦ label[12,-1,0] 𝄀 +1 ¦ 41420000 ¦ scanned +deallocate prepare indexed_lookup; +deallocate prepare scanned_lookup; +set @v1 = 0x41420000; +create procedure local_scope_binary_shadow() 'begin declare v1 int default 10; if v1 > 5 then set v1 = v1 + 1; end if; select v1; end'; +call local_scope_binary_shadow(); +➤ v1[12,0,0] 𝄀 +11 +drop procedure local_scope_binary_shadow; +drop database prepare_binary_param; diff --git a/test/distributed/cases/prepare/prepare_binary_param.sql b/test/distributed/cases/prepare/prepare_binary_param.sql new file mode 100644 index 0000000000000..38fb1b5d92c5c --- /dev/null +++ b/test/distributed/cases/prepare/prepare_binary_param.sql @@ -0,0 +1,51 @@ +-- @suit + +-- @case +-- @desc: Prepared user variables preserve binary literal semantics. +-- @label:bvt +drop database if exists prepare_binary_param; +create database prepare_binary_param; +use prepare_binary_param; + +create table indexed_values ( + id int primary key, + b binary(4), + label varchar(20), + key idx_b (b) +); +create table scanned_values ( + id int primary key, + b binary(4), + label varchar(20) +); +insert into indexed_values values (1, 0x41420000, 'indexed'), (2, 0x43440000, 'other'); +insert into scanned_values values (1, 0x41420000, 'scanned'), (2, 0x43440000, 'other'); + +prepare indexed_lookup from 'select id, hex(b), label from indexed_values where b = ? and label = ?'; +prepare scanned_lookup from 'select id, hex(b), label from scanned_values where b = ? and label = ?'; + +set @binary_source = (0x41420000); +set @binary_value = @binary_source; +set @indexed_label = 'indexed'; +set @scanned_label = 'scanned'; +execute indexed_lookup using @binary_value, @indexed_label; +execute scanned_lookup using @binary_value, @scanned_label; + +set @text_source = 'AB'; +set @binary_value = @text_source; +execute indexed_lookup using @binary_value, @indexed_label; +execute scanned_lookup using @binary_value, @scanned_label; + +set @binary_value = 0x41420000; +execute indexed_lookup using @binary_value, @indexed_label; +execute scanned_lookup using @binary_value, @scanned_label; + +deallocate prepare indexed_lookup; +deallocate prepare scanned_lookup; + +set @v1 = 0x41420000; +create procedure local_scope_binary_shadow() 'begin declare v1 int default 10; if v1 > 5 then set v1 = v1 + 1; end if; select v1; end'; +call local_scope_binary_shadow(); +drop procedure local_scope_binary_shadow; + +drop database prepare_binary_param; From 3d22ec23a7107e4ec018e1076fd5dcc53113fb07 Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Mon, 20 Jul 2026 11:57:31 +0800 Subject: [PATCH 02/10] test: cover prepared binary retry and version boundary --- pkg/sql/compile/compile_test.go | 75 ++++++++++++++++++++++------ pkg/vm/engine/disttae/engine_test.go | 34 +++++++++++++ pkg/vm/process/process_codec_test.go | 22 ++++++++ 3 files changed, 117 insertions(+), 14 deletions(-) diff --git a/pkg/sql/compile/compile_test.go b/pkg/sql/compile/compile_test.go index 71ed3afc8c31f..10a1dfc6462ae 100644 --- a/pkg/sql/compile/compile_test.go +++ b/pkg/sql/compile/compile_test.go @@ -70,23 +70,49 @@ type compileTestCase struct { txnClient client.TxnClient // Store txnClient for truncating table with real transaction } -func TestReleaseRetryCompilePreservesPrepareParams(t *testing.T) { - proc := testutil.NewProcess(t) +func TestCompileRunPreservesBinaryPrepareParamAcrossRetries(t *testing.T) { + tc := newTestCaseWithPrepare("select ?", true, t) + ctrl := gomock.NewController(t) + txnCli, txnOp := newTestTxnClientAndOpWithIsolation(ctrl, txn.TxnIsolation_RC) + ctx := defines.AttachAccountId(context.Background(), catalog.System_Account) + tc.proc.Base.TxnClient = txnCli + tc.proc.Base.TxnOperator = txnOp + tc.proc.Ctx = ctx + tc.proc.ReplaceTopCtx(ctx) + + want := []byte{'A', 'B', 0, 0} params := vector.NewVec(types.T_text.ToType()) - require.NoError(t, vector.AppendBytes(params, []byte("binary"), false, proc.Mp())) - proc.SetOwnedPrepareParamsWithIsBin(params, []bool{true}) - - for range 2 { - retryCompile := NewCompile("", "", "", "", "", nil, proc, nil, false, nil, time.Time{}) - releaseRetryCompile(retryCompile) - require.Same(t, params, proc.GetPrepareParams()) - require.True(t, proc.GetPrepareParamIsBin(0)) - require.Equal(t, 1, params.Length()) + require.NoError(t, vector.AppendBytes(params, want, false, tc.proc.Mp())) + tc.proc.SetOwnedPrepareParamsWithIsBin(params, []bool{true}) + + evaluations := 0 + fill := func(bat *batch.Batch, _ *perfcounter.CounterSet) error { + if bat == nil { + return nil + } + require.Len(t, bat.Vecs, 1) + require.True(t, bat.Vecs[0].GetIsBin(), "binary semantics were lost on evaluation %d", evaluations+1) + require.Equal(t, want, bat.Vecs[0].GetBytesAt(0)) + evaluations++ + if evaluations <= 2 { + return moerr.NewTxnNeedRetryNoCtx() + } + return nil } - proc.Free() + c := NewCompile("test", "test", tc.sql, "", "", tc.e, tc.proc, tc.stmt, false, nil, time.Now()) + require.NoError(t, c.Compile(ctx, tc.pn, fill)) + _, err := c.Run(0) + require.NoError(t, err) + require.Equal(t, 3, evaluations) + require.Equal(t, 2, c.retryTimes) require.Zero(t, params.Length()) require.Nil(t, params.GetData()) + require.Nil(t, params.GetArea()) + + c.Release() + tc.proc.Free() + tc.proc.GetSessionInfo().Buf.Free() } func testPrint(_ *batch.Batch, crs *perfcounter.CounterSet) error { @@ -406,11 +432,18 @@ func TestCompileWithFaults(t *testing.T) { } func newTestTxnClientAndOp(ctrl *gomock.Controller) (client.TxnClient, client.TxnOperator) { + return newTestTxnClientAndOpWithIsolation(ctrl, txn.TxnIsolation_SI) +} + +func newTestTxnClientAndOpWithIsolation( + ctrl *gomock.Controller, + isolation txn.TxnIsolation, +) (client.TxnClient, client.TxnOperator) { txnOperator := mock_frontend.NewMockTxnOperator(ctrl) txnOperator.EXPECT().Commit(gomock.Any()).Return(nil).AnyTimes() txnOperator.EXPECT().Rollback(gomock.Any()).Return(nil).AnyTimes() txnOperator.EXPECT().GetWorkspace().Return(&Ws{}).AnyTimes() - txnOperator.EXPECT().Txn().Return(txn.TxnMeta{}).AnyTimes() + txnOperator.EXPECT().Txn().Return(txn.TxnMeta{Isolation: isolation}).AnyTimes() txnOperator.EXPECT().TxnOptions().Return(txn.TxnOptions{}).AnyTimes() txnOperator.EXPECT().NextSequence().Return(uint64(0)).AnyTimes() txnOperator.EXPECT().TryEnterRunSqlWithTokenAndSQL(gomock.Any(), gomock.Any()).Return(uint64(1), nil).AnyTimes() @@ -484,6 +517,10 @@ func newTestTxnClientAndOpWithPessimistic(ctrl *gomock.Controller) (client.TxnCl } func newTestCase(sql string, t *testing.T) compileTestCase { + return newTestCaseWithPrepare(sql, false, t) +} + +func newTestCaseWithPrepare(sql string, isPrepare bool, t *testing.T) compileTestCase { proc := testutil.NewProcess(t) proc.GetSessionInfo().Buf = buffer.New() proc.SetResolveVariableFunc(func(varName string, isSystemVar, isGlobalVar bool) (interface{}, error) { @@ -493,7 +530,17 @@ func newTestCase(sql string, t *testing.T) compileTestCase { e, txnClient, compilerCtx := testengine.New(defines.AttachAccountId(context.Background(), catalog.System_Account)) stmts, err := mysql.Parse(compilerCtx.GetContext(), sql, 1) require.NoError(t, err) - pn, err := plan2.BuildPlan(compilerCtx, stmts[0], false) + var pn *plan.Plan + if isPrepare { + query, optimizeErr := plan2.NewPrepareOptimizer(compilerCtx).Optimize(stmts[0], true) + err = optimizeErr + pn = &plan.Plan{Plan: &plan.Plan_Query{Query: query}, IsPrepare: true} + if err == nil { + _, _, err = plan2.ResetPreparePlan(compilerCtx, pn) + } + } else { + pn, err = plan2.BuildPlan(compilerCtx, stmts[0], false) + } if err != nil { panic(err) } diff --git a/pkg/vm/engine/disttae/engine_test.go b/pkg/vm/engine/disttae/engine_test.go index 162b6cbf4c94c..c7122e1d21304 100644 --- a/pkg/vm/engine/disttae/engine_test.go +++ b/pkg/vm/engine/disttae/engine_test.go @@ -370,6 +370,40 @@ func TestEngineCandidateDiscoveryExcludesIncompatibleCNBeforePoolFallback(t *tes require.True(t, nodes[0].HasMixedCommit) } +func TestPreparedBinarySchedulingExcludesMixedVersionCN(t *testing.T) { + for _, tc := range []struct { + name string + peerCommit string + }{ + {name: "peer is older", peerCommit: "older-than-" + version.CommitID}, + {name: "peer is newer", peerCommit: "newer-than-" + version.CommitID}, + } { + t.Run(tc.name, func(t *testing.T) { + e := newEngineWithClusterDetails(t, logpb.ClusterDetails{CNStores: []logpb.CNStore{ + newEngineNodesCNStore("compatible-cn", "compatible:6001", nil, metadata.WorkState_Working, version.CommitID), + newEngineNodesCNStore("mixed-version-cn", "mixed-version:6001", nil, metadata.WorkState_Working, tc.peerCommit), + }}) + + // Prepared parameters are encoded only after scheduling has selected a + // query worker. Keep this boundary ahead of ProcessInfo serialization so + // a peer that does not understand PrepareParamInfo.is_bin cannot silently + // reinterpret a binary parameter. + candidates, err := e.DiscoverQueryCandidates(context.Background()) + require.NoError(t, err) + require.Len(t, candidates, 1) + require.Equal(t, "compatible-cn", candidates[0].Service.ServiceID) + require.Equal(t, version.CommitID, candidates[0].Service.CommitID) + require.True(t, candidates[0].HasMixedCommit) + + nodes, err := e.ResolveQueryCandidatePool( + context.Background(), candidates, engine.QueryCandidatePoolRequest{}) + require.NoError(t, err) + require.Equal(t, []string{"compatible:6001"}, nodeAddresses(nodes)) + require.True(t, nodes[0].HasMixedCommit) + }) + } +} + func TestEngineCandidateDiscoveryMarksOldCommitOutsideWorkingSet(t *testing.T) { for _, state := range []metadata.WorkState{ metadata.WorkState_Draining, diff --git a/pkg/vm/process/process_codec_test.go b/pkg/vm/process/process_codec_test.go index a87f83b5bb08c..34696119ae221 100644 --- a/pkg/vm/process/process_codec_test.go +++ b/pkg/vm/process/process_codec_test.go @@ -231,6 +231,28 @@ func TestCodecServiceEncodeDecodeAndLookup(t *testing.T) { require.Same(t, svc, GetCodecService(rtSvc)) } +func TestCodecServiceDecodesLegacyPrepareParamsWithoutBinaryFlags(t *testing.T) { + proc, _ := newCodecTestProcess(t) + info, err := proc.BuildProcessInfo("select ?") + require.NoError(t, err) + info.PrepareParams.IsBin = nil + + payload, err := info.Marshal() + require.NoError(t, err) + legacyInfo := pipeline.ProcessInfo{} + require.NoError(t, legacyInfo.Unmarshal(payload)) + require.Empty(t, legacyInfo.PrepareParams.IsBin) + + svc := NewCodecService(fakeCodecTxnClient{op: fakeCodecTxnOperator{}}, nil, nil, nil, nil, nil, nil, nil) + decodedProc, err := svc.Decode(context.Background(), legacyInfo) + require.NoError(t, err) + require.NotNil(t, decodedProc.GetPrepareParams()) + require.Equal(t, 2, decodedProc.GetPrepareParams().Length()) + require.False(t, decodedProc.GetPrepareParamIsBin(0)) + require.False(t, decodedProc.GetPrepareParamIsBin(1)) + decodedProc.Free() +} + func TestGetCodecServicePanicsWhenMissing(t *testing.T) { rtSvc := "codec-missing-svc" runtime := rt.NewRuntime(metadata.ServiceType_CN, rtSvc, nil) From 910cf1ca4c1a92794ad8a17a6d2ad498ac282f8b Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Mon, 20 Jul 2026 17:40:32 +0800 Subject: [PATCH 03/10] test: prove mixed-version binary dispatch boundary --- pkg/vm/engine/disttae/engine_test.go | 53 +++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/pkg/vm/engine/disttae/engine_test.go b/pkg/vm/engine/disttae/engine_test.go index c7122e1d21304..3e43a8af1b0d9 100644 --- a/pkg/vm/engine/disttae/engine_test.go +++ b/pkg/vm/engine/disttae/engine_test.go @@ -182,10 +182,15 @@ import ( "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/clusterservice" moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/defines" mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" logpb "github.com/matrixorigin/matrixone/pkg/pb/logservice" "github.com/matrixorigin/matrixone/pkg/pb/metadata" + "github.com/matrixorigin/matrixone/pkg/pb/pipeline" txnpb "github.com/matrixorigin/matrixone/pkg/pb/txn" + "github.com/matrixorigin/matrixone/pkg/testutil" "github.com/matrixorigin/matrixone/pkg/version" "github.com/matrixorigin/matrixone/pkg/vm/engine" "github.com/stretchr/testify/require" @@ -379,15 +384,25 @@ func TestPreparedBinarySchedulingExcludesMixedVersionCN(t *testing.T) { {name: "peer is newer", peerCommit: "newer-than-" + version.CommitID}, } { t.Run(tc.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + txnOp := mock_frontend.NewMockTxnOperator(ctrl) + txnOp.EXPECT().Snapshot().Return(txnpb.CNTxnSnapshot{}, nil) + proc := testutil.NewProcess(t) + ctx := defines.AttachAccountId(context.Background(), catalog.System_Account) + proc.Ctx = ctx + proc.ReplaceTopCtx(ctx) + proc.Base.TxnOperator = txnOp + binaryValue := []byte{'A', 'B', 0, 0} + params := vector.NewVec(types.T_text.ToType()) + require.NoError(t, vector.AppendBytes(params, binaryValue, false, proc.Mp())) + proc.SetOwnedPrepareParamsWithIsBin(params, []bool{true}) + t.Cleanup(proc.Free) + e := newEngineWithClusterDetails(t, logpb.ClusterDetails{CNStores: []logpb.CNStore{ newEngineNodesCNStore("compatible-cn", "compatible:6001", nil, metadata.WorkState_Working, version.CommitID), newEngineNodesCNStore("mixed-version-cn", "mixed-version:6001", nil, metadata.WorkState_Working, tc.peerCommit), }}) - // Prepared parameters are encoded only after scheduling has selected a - // query worker. Keep this boundary ahead of ProcessInfo serialization so - // a peer that does not understand PrepareParamInfo.is_bin cannot silently - // reinterpret a binary parameter. candidates, err := e.DiscoverQueryCandidates(context.Background()) require.NoError(t, err) require.Len(t, candidates, 1) @@ -400,6 +415,36 @@ func TestPreparedBinarySchedulingExcludesMixedVersionCN(t *testing.T) { require.NoError(t, err) require.Equal(t, []string{"compatible:6001"}, nodeAddresses(nodes)) require.True(t, nodes[0].HasMixedCommit) + + // Remote ProcessInfo is built only for the workers that survived + // discovery and pool resolution. This models the coordinator send + // boundary and proves that an incompatible worker never receives an + // is_bin field it might silently ignore. + deliveries := make(map[string]pipeline.ProcessInfo, len(nodes)) + for _, node := range nodes { + info, buildErr := proc.BuildProcessInfo("select ?") + require.NoError(t, buildErr) + payload, marshalErr := info.Marshal() + require.NoError(t, marshalErr) + decoded := pipeline.ProcessInfo{} + require.NoError(t, decoded.Unmarshal(payload)) + deliveries[node.Addr] = decoded + } + require.NotContains(t, deliveries, "mixed-version:6001") + delivered, ok := deliveries["compatible:6001"] + require.True(t, ok) + require.Equal(t, []bool{true}, delivered.PrepareParams.IsBin) + + decodedParams, err := vector.NewVecWithDataCopy( + types.T_text.ToType(), + int(delivered.PrepareParams.Length), + delivered.PrepareParams.Data, + delivered.PrepareParams.Area, + proc.Mp(), + ) + require.NoError(t, err) + require.Equal(t, binaryValue, decodedParams.GetRawBytesAt(0)) + decodedParams.Free(proc.Mp()) }) } } From de8df523b87b9691780dfb2a0b274d20094951ee Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Tue, 21 Jul 2026 18:54:13 +0800 Subject: [PATCH 04/10] fix: guard binary params in shard reads --- pkg/shardservice/service_read.go | 51 +++++++ pkg/shardservice/service_read_test.go | 30 ++++ .../disttae/txn_table_sharding_handle.go | 134 +++++++++++++----- .../disttae/txn_table_sharding_handle_test.go | 111 +++++++++++++++ 4 files changed, 290 insertions(+), 36 deletions(-) create mode 100644 pkg/vm/engine/disttae/txn_table_sharding_handle_test.go diff --git a/pkg/shardservice/service_read.go b/pkg/shardservice/service_read.go index 0459502eb6b79..da17855cda416 100644 --- a/pkg/shardservice/service_read.go +++ b/pkg/shardservice/service_read.go @@ -18,12 +18,60 @@ import ( "context" "errors" + "github.com/matrixorigin/matrixone/pkg/clusterservice" + "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/morpc" + "github.com/matrixorigin/matrixone/pkg/pb/metadata" pb "github.com/matrixorigin/matrixone/pkg/pb/shard" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" + "github.com/matrixorigin/matrixone/pkg/version" ) +func hasBinaryPrepareParam(param pb.ReadParam) bool { + for _, isBin := range param.Process.PrepareParams.IsBin { + if isBin { + return true + } + } + return false +} + +func (s *service) validateRemoteReadCompatibility( + ctx context.Context, + shard pb.TableShard, + param pb.ReadParam, +) error { + if !hasBinaryPrepareParam(param) { + return nil + } + + target := shard.Replicas[0].CN + found := false + compatible := false + err := clusterservice.GetCNServiceWithoutWorkingStateWithContext( + ctx, + s.remote.cluster, + clusterservice.NewServiceIDSelector(target), + func(cn metadata.CNService) bool { + found = true + compatible = cn.CommitID == version.CommitID + return false + }, + ) + if err != nil { + return err + } + if found && compatible { + return nil + } + return moerr.NewInternalErrorf( + ctx, + "cannot send binary prepared parameters to shard replica %s with an incompatible or unknown commit", + target, + ) +} + func (s *service) Read( ctx context.Context, req ReadRequest, @@ -93,6 +141,9 @@ func (s *service) Read( if opts.adjust != nil { opts.adjust(&shard) } + if e := s.validateRemoteReadCompatibility(ctx, shard, req.Param); e != nil { + return false, e + } f, e := s.remote.client.AsyncSend( ctx, s.newReadRequest( diff --git a/pkg/shardservice/service_read_test.go b/pkg/shardservice/service_read_test.go index 4dabe62966e2b..d8ca87f103afc 100644 --- a/pkg/shardservice/service_read_test.go +++ b/pkg/shardservice/service_read_test.go @@ -20,13 +20,43 @@ import ( "testing" "time" + "github.com/matrixorigin/matrixone/pkg/clusterservice" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/pb/metadata" + "github.com/matrixorigin/matrixone/pkg/pb/pipeline" "github.com/matrixorigin/matrixone/pkg/pb/shard" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" + "github.com/matrixorigin/matrixone/pkg/version" "github.com/stretchr/testify/require" ) +func TestValidateRemoteReadCompatibility(t *testing.T) { + cns, _ := initTestCluster("target") + cluster := clusterservice.GetMOCluster(sid) + s := &service{} + s.remote.cluster = cluster + target := shard.TableShard{Replicas: []shard.ShardReplica{{CN: "target"}}} + binaryParam := shard.ReadParam{Process: pipeline.ProcessInfo{ + PrepareParams: pipeline.PrepareParamInfo{IsBin: []bool{false, true}}, + }} + + cns[0].CommitID = version.CommitID + cluster.UpdateCN(cns[0]) + require.NoError(t, s.validateRemoteReadCompatibility(t.Context(), target, binaryParam)) + + cns[0].CommitID = "older-commit" + cluster.UpdateCN(cns[0]) + require.Error(t, s.validateRemoteReadCompatibility(t.Context(), target, binaryParam)) + + textParam := binaryParam + textParam.Process.PrepareParams.IsBin = []bool{false, false} + require.NoError(t, s.validateRemoteReadCompatibility(t.Context(), target, textParam)) + + unknown := target + unknown.Replicas[0].CN = "unknown" + require.Error(t, s.validateRemoteReadCompatibility(t.Context(), unknown, binaryParam)) +} + func TestRead(t *testing.T) { runServicesTest( t, diff --git a/pkg/vm/engine/disttae/txn_table_sharding_handle.go b/pkg/vm/engine/disttae/txn_table_sharding_handle.go index 85cf7bb3c87de..d2773a4ef44a5 100644 --- a/pkg/vm/engine/disttae/txn_table_sharding_handle.go +++ b/pkg/vm/engine/disttae/txn_table_sharding_handle.go @@ -39,10 +39,26 @@ import ( const StreamReaderLease = time.Minute * 2 type shardingRemoteReader struct { - streamID types.Uuid - rd engine.Reader - colTypes []types.Type - deadline time.Time + streamID types.Uuid + rd engine.Reader + colTypes []types.Type + deadline time.Time + release func() + mu sync.Mutex + closed bool + closeOnce sync.Once +} + +func (sr *shardingRemoteReader) close() { + sr.closeOnce.Do(func() { + sr.mu.Lock() + defer sr.mu.Unlock() + sr.closed = true + sr.rd.Close() + if sr.release != nil { + sr.release() + } + }) } func (sr *shardingRemoteReader) updateCols(cols []string, tblDef *plan.TableDef) { @@ -67,25 +83,34 @@ func (sr *shardingRemoteReader) updateCols(cols []string, tblDef *plan.TableDef) type streamHandle struct { sync.Mutex - streamReaders map[types.Uuid]shardingRemoteReader + streamReaders map[types.Uuid]*shardingRemoteReader gcJob *tasks.CancelableJob } var streamHandler streamHandle +func closeExpiredStreamReaders(now time.Time) { + streamHandler.Lock() + var expired []*shardingRemoteReader + for id, sr := range streamHandler.streamReaders { + if now.After(sr.deadline) { + delete(streamHandler.streamReaders, id) + expired = append(expired, sr) + } + } + streamHandler.Unlock() + for _, sr := range expired { + sr.close() + } +} + func init() { - streamHandler.streamReaders = make(map[types.Uuid]shardingRemoteReader) + streamHandler.streamReaders = make(map[types.Uuid]*shardingRemoteReader) streamHandler.gcJob = tasks.NewCancelableCronJob( "streamReaderGC", StreamReaderLease, func(ctx context.Context) { - streamHandler.Lock() - defer streamHandler.Unlock() - for id, sr := range streamHandler.streamReaders { - if time.Now().After(sr.deadline) { - delete(streamHandler.streamReaders, id) - } - } + closeExpiredStreamReaders(time.Now()) }, true, 1, @@ -102,7 +127,7 @@ func HandleShardingReadRows( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -110,6 +135,7 @@ func HandleShardingReadRows( if err != nil { return nil, err } + defer release() rows, err := tbl.Rows(ctx) if err != nil { @@ -127,7 +153,7 @@ func HandleShardingReadSize( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -135,6 +161,7 @@ func HandleShardingReadSize( if err != nil { return nil, err } + defer release() rows, err := tbl.Size( ctx, @@ -155,7 +182,7 @@ func HandleShardingReadStatus( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -163,6 +190,7 @@ func HandleShardingReadStatus( if err != nil { return nil, err } + defer release() info, err := tbl.Stats( ctx, @@ -191,7 +219,7 @@ func HandleShardingReadApproxObjectsNum( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -199,6 +227,7 @@ func HandleShardingReadApproxObjectsNum( if err != nil { return nil, err } + defer release() num := tbl.ApproxObjectsNum( ctx, @@ -215,7 +244,7 @@ func HandleShardingReadRanges( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, eng, @@ -223,6 +252,7 @@ func HandleShardingReadRanges( if err != nil { return nil, err } + defer release() rangesParam := engine.RangesParam{ BlockFilters: param.RangesParam.Exprs, PreAllocBlocks: int(param.RangesParam.PreAllocSize), @@ -251,7 +281,7 @@ func HandleShardingReadBuildReader( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, e, @@ -259,6 +289,16 @@ func HandleShardingReadBuildReader( if err != nil { return nil, err } + transferred := false + var rd engine.Reader + defer func() { + if !transferred { + if rd != nil { + rd.Close() + } + release() + } + }() relData, err := readutil.UnmarshalRelationData(param.ReaderBuildParam.RelData) if err != nil { @@ -276,7 +316,7 @@ func HandleShardingReadBuildReader( return nil, err } - rd, err := readutil.NewReader( + rd, err = readutil.NewReader( ctx, tbl.proc.Load().Mp(), e.(*Engine).packerPool, @@ -298,11 +338,13 @@ func HandleShardingReadBuildReader( } streamHandler.Lock() defer streamHandler.Unlock() - streamHandler.streamReaders[uuid] = shardingRemoteReader{ + streamHandler.streamReaders[uuid] = &shardingRemoteReader{ streamID: uuid, rd: rd, deadline: time.Now().Add(StreamReaderLease), + release: release, } + transferred = true return buffer.EncodeBytes(types.EncodeUuid(&uuid)), nil } @@ -316,7 +358,7 @@ func HandleShardingReadNext( buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -324,6 +366,7 @@ func HandleShardingReadNext( if err != nil { return nil, err } + defer release() mp := tbl.proc.Load().Mp() streamID := types.DecodeUuid(param.ReadNextParam.Uuid) @@ -335,8 +378,14 @@ func HandleShardingReadNext( streamHandler.Unlock() return nil, moerr.NewInternalErrorNoCtx("stream reader not found, may be expired") } - streamHandler.Unlock() sr.deadline = time.Now().Add(StreamReaderLease) + streamHandler.Unlock() + + sr.mu.Lock() + defer sr.mu.Unlock() + if sr.closed { + return nil, moerr.NewInternalErrorNoCtx("stream reader is closed") + } sr.updateCols(cols, tbl.tableDef) @@ -398,13 +447,14 @@ func HandleShardingReadClose( streamID := types.DecodeUuid(param.ReadCloseParam.Uuid) //find reader by streamID streamHandler.Lock() - defer streamHandler.Unlock() sr, ok := streamHandler.streamReaders[streamID] if !ok { + streamHandler.Unlock() return nil, moerr.NewInternalErrorNoCtx("stream reader not found, may be expired") } - sr.rd.Close() delete(streamHandler.streamReaders, sr.streamID) + streamHandler.Unlock() + sr.close() return nil, nil } @@ -416,7 +466,7 @@ func HandleShardingReadCollectTombstones( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, eng, @@ -424,6 +474,7 @@ func HandleShardingReadCollectTombstones( if err != nil { return nil, err } + defer release() tombstones, err := tbl.CollectTombstones( ctx, @@ -451,7 +502,7 @@ func HandleShardingReadGetColumMetadataScanInfo( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -459,6 +510,7 @@ func HandleShardingReadGetColumMetadataScanInfo( if err != nil { return nil, err } + defer release() infos, err := tbl.GetColumMetadataScanInfo( ctx, @@ -488,7 +540,7 @@ func HandleShardingReadPrimaryKeysMayBeModified( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -496,6 +548,7 @@ func HandleShardingReadPrimaryKeysMayBeModified( if err != nil { return nil, err } + defer release() var from, to types.TS err = from.Unmarshal(param.PrimaryKeysMayBeModifiedParam.From) @@ -542,7 +595,7 @@ func HandleShardingReadPrimaryKeysMayBeUpserted( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -550,6 +603,7 @@ func HandleShardingReadPrimaryKeysMayBeUpserted( if err != nil { return nil, err } + defer release() var from, to types.TS err = from.Unmarshal(param.PrimaryKeysMayBeModifiedParam.From) @@ -596,7 +650,7 @@ func HandleShardingReadMergeObjects( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -604,6 +658,7 @@ func HandleShardingReadMergeObjects( if err != nil { return nil, err } + defer release() objstats := make([]objectio.ObjectStats, len(param.MergeObjectsParam.Objstats)) for i, o := range param.MergeObjectsParam.Objstats { @@ -634,7 +689,7 @@ func HandleShardingReadVisibleObjectStats( ts timestamp.Timestamp, buffer *morpc.Buffer, ) ([]byte, error) { - tbl, err := getTxnTable( + tbl, release, err := getTxnTable( ctx, param, engine, @@ -642,6 +697,7 @@ func HandleShardingReadVisibleObjectStats( if err != nil { return nil, err } + defer release() stats, err := tbl.GetNonAppendableObjectStats(ctx) if err != nil { @@ -662,14 +718,18 @@ func getTxnTable( ctx context.Context, param shard.ReadParam, engine engine.Engine, -) (*txnTable, error) { +) (*txnTable, func(), error) { // TODO: reduce mem allocate proc, err := process.GetCodecService(engine.GetService()).Decode( ctx, param.Process, ) if err != nil { - return nil, err + return nil, nil, err + } + var releaseOnce sync.Once + release := func() { + releaseOnce.Do(proc.Free) } ws := NewTxnWorkSpace(engine.(*Engine), proc) proc.GetTxnOperator().AddWorkspace(ws) @@ -688,10 +748,12 @@ func getTxnTable( engine.(*Engine), ) if err != nil { - return nil, err + release() + return nil, nil, err } if item == nil { - return nil, moerr.NewParseErrorf(ctx, "table %q does not exist", param.TxnTable.TableName) + release() + return nil, nil, moerr.NewParseErrorf(ctx, "table %q does not exist", param.TxnTable.TableName) } tbl := newTxnTableWithItem( @@ -702,5 +764,5 @@ func getTxnTable( ) tbl.remoteWorkspace = true tbl.createdInTxn = param.TxnTable.CreatedInTxn - return tbl, nil + return tbl, release, nil } diff --git a/pkg/vm/engine/disttae/txn_table_sharding_handle_test.go b/pkg/vm/engine/disttae/txn_table_sharding_handle_test.go new file mode 100644 index 0000000000000..b79afbc94a645 --- /dev/null +++ b/pkg/vm/engine/disttae/txn_table_sharding_handle_test.go @@ -0,0 +1,111 @@ +// Copyright 2021-2026 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package disttae + +import ( + "context" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/objectio" + "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/stretchr/testify/require" +) + +type countingShardingReader struct { + closes atomic.Int32 +} + +func (r *countingShardingReader) Close() error { + r.closes.Add(1) + return nil +} + +func (r *countingShardingReader) Read( + context.Context, + []string, + *plan.Expr, + *mpool.MPool, + *batch.Batch, +) (bool, error) { + return false, nil +} + +func (r *countingShardingReader) SetOrderBy([]*plan.OrderBySpec) {} +func (r *countingShardingReader) GetOrderBy() []*plan.OrderBySpec { return nil } +func (r *countingShardingReader) SetIndexParam(*plan.IndexReaderParam) {} +func (r *countingShardingReader) SetFilterZM(objectio.ZoneMap) {} + +func TestShardingRemoteReaderCloseIsIdempotent(t *testing.T) { + reader := &countingShardingReader{} + var releases atomic.Int32 + sr := &shardingRemoteReader{ + rd: reader, + release: func() { + releases.Add(1) + }, + } + + var wg sync.WaitGroup + for range 8 { + wg.Add(1) + go func() { + defer wg.Done() + sr.close() + }() + } + wg.Wait() + + require.Equal(t, int32(1), reader.closes.Load()) + require.Equal(t, int32(1), releases.Load()) +} + +func TestCloseExpiredStreamReadersReleasesOwnedProcess(t *testing.T) { + reader := &countingShardingReader{} + var releases atomic.Int32 + id := types.Uuid{1} + sr := &shardingRemoteReader{ + streamID: id, + rd: reader, + deadline: time.Now().Add(-time.Second), + release: func() { + releases.Add(1) + }, + } + + streamHandler.Lock() + streamHandler.streamReaders[id] = sr + streamHandler.Unlock() + t.Cleanup(func() { + streamHandler.Lock() + delete(streamHandler.streamReaders, id) + streamHandler.Unlock() + }) + + closeExpiredStreamReaders(time.Now()) + sr.close() + + streamHandler.Lock() + _, ok := streamHandler.streamReaders[id] + streamHandler.Unlock() + require.False(t, ok) + require.Equal(t, int32(1), reader.closes.Load()) + require.Equal(t, int32(1), releases.Load()) +} From 77b367e3714425a2c3c5717ee743a6d9468a288a Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Tue, 21 Jul 2026 22:44:47 +0800 Subject: [PATCH 05/10] fix: validate shard targets before remote reads --- pkg/shardservice/service_read.go | 13 ++++- pkg/shardservice/service_read_test.go | 84 +++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/pkg/shardservice/service_read.go b/pkg/shardservice/service_read.go index da17855cda416..37a26b3c1a8ba 100644 --- a/pkg/shardservice/service_read.go +++ b/pkg/shardservice/service_read.go @@ -130,7 +130,8 @@ func (s *service) Read( local := 0 remote := 0 - for i, shard := range selected.values { + for i := range selected.values { + shard := &selected.values[i] if s.isLocalReplica(shard.Replicas[0]) { selected.local = append(selected.local, i) local++ @@ -139,11 +140,17 @@ func (s *service) Read( remote++ if opts.adjust != nil { - opts.adjust(&shard) + opts.adjust(shard) } - if e := s.validateRemoteReadCompatibility(ctx, shard, req.Param); e != nil { + if e := s.validateRemoteReadCompatibility(ctx, *shard, req.Param); e != nil { return false, e } + } + + for i, shard := range selected.values { + if s.isLocalReplica(shard.Replicas[0]) { + continue + } f, e := s.remote.client.AsyncSend( ctx, s.newReadRequest( diff --git a/pkg/shardservice/service_read_test.go b/pkg/shardservice/service_read_test.go index d8ca87f103afc..349303b35d7fd 100644 --- a/pkg/shardservice/service_read_test.go +++ b/pkg/shardservice/service_read_test.go @@ -17,11 +17,13 @@ package shardservice import ( "context" "sort" + "sync/atomic" "testing" "time" "github.com/matrixorigin/matrixone/pkg/clusterservice" "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/common/morpc" "github.com/matrixorigin/matrixone/pkg/pb/metadata" "github.com/matrixorigin/matrixone/pkg/pb/pipeline" "github.com/matrixorigin/matrixone/pkg/pb/shard" @@ -30,6 +32,19 @@ import ( "github.com/stretchr/testify/require" ) +type countingMethodBasedClient struct { + morpc.MethodBasedClient[*shard.Request, *shard.Response] + asyncCalls atomic.Int32 +} + +func (c *countingMethodBasedClient) AsyncSend( + ctx context.Context, + req *shard.Request, +) (*morpc.Future, error) { + c.asyncCalls.Add(1) + return c.MethodBasedClient.AsyncSend(ctx, req) +} + func TestValidateRemoteReadCompatibility(t *testing.T) { cns, _ := initTestCluster("target") cluster := clusterservice.GetMOCluster(sid) @@ -57,6 +72,75 @@ func TestValidateRemoteReadCompatibility(t *testing.T) { require.Error(t, s.validateRemoteReadCompatibility(t.Context(), unknown, binaryParam)) } +func TestReadValidatesAllRemoteShardsBeforeSending(t *testing.T) { + runServicesTest( + t, + "cn1,cn2,cn3", + func(ctx context.Context, _ *server, services []*service) { + s := services[0] + table := uint64(1) + mustAddTestShards(t, ctx, s, table, 3, 1, services[1:]...) + for _, service := range services { + waitReplicaCount(table, service, 1) + } + + cache, err := s.getShards(table) + require.NoError(t, err) + var remoteTargets []string + cache.selectReplicas( + table, + func(_ shard.ShardsMetadata, _ shard.TableShard, replica shard.ShardReplica) bool { + if !s.isLocalReplica(replica) { + remoteTargets = append(remoteTargets, replica.CN) + } + return true + }, + ) + require.GreaterOrEqual(t, len(remoteTargets), 2) + + cns := make(map[string]metadata.CNService) + s.remote.cluster.GetCNServiceWithoutWorkingState( + clusterservice.NewSelector(), + func(cn metadata.CNService) bool { + cns[cn.ServiceID] = cn + return true + }, + ) + for _, target := range remoteTargets { + cn := cns[target] + cn.CommitID = version.CommitID + s.remote.cluster.UpdateCN(cn) + } + incompatible := cns[remoteTargets[len(remoteTargets)-1]] + incompatible.CommitID = "older-commit" + s.remote.cluster.UpdateCN(incompatible) + + client := &countingMethodBasedClient{MethodBasedClient: s.remote.client} + s.remote.client = client + adjustCalls := make(map[uint64]int) + err = s.Read( + ctx, + ReadRequest{ + TableID: table, + Param: shard.ReadParam{Process: pipeline.ProcessInfo{ + PrepareParams: pipeline.PrepareParamInfo{IsBin: []bool{true}}, + }}, + }, + DefaultOptions.Adjust(func(target *shard.TableShard) { + adjustCalls[target.ShardID]++ + }), + ) + require.Error(t, err) + require.Zero(t, client.asyncCalls.Load()) + require.Len(t, adjustCalls, len(remoteTargets)) + for _, calls := range adjustCalls { + require.Equal(t, 1, calls) + } + }, + nil, + ) +} + func TestRead(t *testing.T) { runServicesTest( t, From fa7e7b3f42e6d96de23a3bb67686328d6a8ef487 Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Tue, 21 Jul 2026 22:52:38 +0800 Subject: [PATCH 06/10] test: serialize shard read client instrumentation --- pkg/shardservice/service_read_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/shardservice/service_read_test.go b/pkg/shardservice/service_read_test.go index 349303b35d7fd..b49ab612bc557 100644 --- a/pkg/shardservice/service_read_test.go +++ b/pkg/shardservice/service_read_test.go @@ -115,6 +115,9 @@ func TestReadValidatesAllRemoteShardsBeforeSending(t *testing.T) { incompatible.CommitID = "older-commit" s.remote.cluster.UpdateCN(incompatible) + // Stop the heartbeat loop before replacing the client so the test does + // not race with background RPCs unrelated to the read under test. + s.stopper.Stop() client := &countingMethodBasedClient{MethodBasedClient: s.remote.client} s.remote.client = client adjustCalls := make(map[uint64]int) From 9e3f0466ae02c047adcdced8176a5b7c6afd960f Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Tue, 21 Jul 2026 22:58:23 +0800 Subject: [PATCH 07/10] fix: preserve remote shard selection after validation --- pkg/shardservice/service_read.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/shardservice/service_read.go b/pkg/shardservice/service_read.go index 37a26b3c1a8ba..abd85ceff13e0 100644 --- a/pkg/shardservice/service_read.go +++ b/pkg/shardservice/service_read.go @@ -130,6 +130,7 @@ func (s *service) Read( local := 0 remote := 0 + remoteShards := make([]int, 0, len(selected.values)) for i := range selected.values { shard := &selected.values[i] if s.isLocalReplica(shard.Replicas[0]) { @@ -139,6 +140,7 @@ func (s *service) Read( } remote++ + remoteShards = append(remoteShards, i) if opts.adjust != nil { opts.adjust(shard) } @@ -147,10 +149,8 @@ func (s *service) Read( } } - for i, shard := range selected.values { - if s.isLocalReplica(shard.Replicas[0]) { - continue - } + for _, i := range remoteShards { + shard := selected.values[i] f, e := s.remote.client.AsyncSend( ctx, s.newReadRequest( From e1e7d7ecc992f07e81d8a48146075235f68aa4c6 Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Tue, 21 Jul 2026 23:29:06 +0800 Subject: [PATCH 08/10] fix: version binary shard read RPCs --- pkg/pb/shard/shard.pb.go | 233 +++++++++++++------------- pkg/shardservice/service_read_test.go | 76 +++++++++ pkg/shardservice/service_remote.go | 14 ++ proto/shard.proto | 1 + 4 files changed, 209 insertions(+), 115 deletions(-) diff --git a/pkg/pb/shard/shard.pb.go b/pkg/pb/shard/shard.pb.go index 1368ad2db413a..7180a45d2c997 100644 --- a/pkg/pb/shard/shard.pb.go +++ b/pkg/pb/shard/shard.pb.go @@ -175,6 +175,7 @@ const ( Method_ShardRead Method = 4 Method_PauseCN Method = 5 Method_GetCNReplicas Method = 6 + Method_ShardReadV2 Method = 7 ) var Method_name = map[int32]string{ @@ -185,6 +186,7 @@ var Method_name = map[int32]string{ 4: "ShardRead", 5: "PauseCN", 6: "GetCNReplicas", + 7: "ShardReadV2", } var Method_value = map[string]int32{ @@ -195,6 +197,7 @@ var Method_value = map[string]int32{ "ShardRead": 4, "PauseCN": 5, "GetCNReplicas": 6, + "ShardReadV2": 7, } func (x Method) String() string { @@ -2408,123 +2411,123 @@ func init() { func init() { proto.RegisterFile("shard.proto", fileDescriptor_319ea41e44cdc364) } var fileDescriptor_319ea41e44cdc364 = []byte{ - // 1842 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x4f, 0x6f, 0xdb, 0xc8, - 0x15, 0x37, 0x65, 0x4a, 0x96, 0x9e, 0x24, 0x9b, 0x9a, 0x38, 0x5e, 0xc1, 0xcd, 0xba, 0x2a, 0x91, - 0xdd, 0xba, 0xce, 0xc6, 0x46, 0x9d, 0x6e, 0x17, 0x68, 0xd3, 0x3f, 0x8e, 0x14, 0x24, 0x46, 0xea, - 0x3f, 0xa0, 0x9d, 0x3d, 0x74, 0x81, 0x02, 0x23, 0x69, 0xac, 0x30, 0x4b, 0x91, 0x2c, 0x39, 0x6a, - 0xa5, 0x9e, 0xda, 0x4f, 0xd1, 0x63, 0xfb, 0x09, 0x7a, 0x6a, 0x81, 0x7e, 0x84, 0x05, 0x7a, 0xd9, - 0x5b, 0x6f, 0x45, 0x9b, 0x7e, 0x91, 0xc5, 0xfc, 0xe5, 0x0c, 0xa5, 0x38, 0x7b, 0xc8, 0x8d, 0xef, - 0xff, 0x9b, 0x37, 0xbf, 0x79, 0x6f, 0x86, 0xd0, 0xcc, 0x5f, 0xe1, 0x6c, 0x7c, 0x98, 0x66, 0x09, - 0x4d, 0x50, 0x95, 0x13, 0xbb, 0x0f, 0x27, 0x21, 0x7d, 0x35, 0x1b, 0x1e, 0x8e, 0x92, 0xe9, 0xd1, - 0x24, 0x99, 0x24, 0x47, 0x5c, 0x3a, 0x9c, 0xdd, 0x70, 0x8a, 0x13, 0xfc, 0x4b, 0x58, 0xed, 0x6e, - 0xd1, 0x70, 0x4a, 0x72, 0x8a, 0xa7, 0xa9, 0x64, 0x6c, 0xa6, 0x61, 0x4a, 0xa2, 0x30, 0x26, 0x92, - 0x86, 0x34, 0xc2, 0xb1, 0xf8, 0xf6, 0xff, 0xed, 0xc0, 0xe6, 0x15, 0x8b, 0x92, 0x9f, 0x11, 0x8a, - 0xc7, 0x98, 0x62, 0xf4, 0x11, 0xd4, 0x2e, 0x93, 0x28, 0x1c, 0x2d, 0xba, 0x4e, 0xcf, 0xd9, 0xdf, - 0x3c, 0x6e, 0x1f, 0x8a, 0x9c, 0x04, 0x33, 0x90, 0x42, 0xd4, 0x83, 0xa6, 0x30, 0xec, 0x27, 0xb3, - 0x98, 0x76, 0x2b, 0x3d, 0x67, 0xbf, 0x1d, 0x98, 0x2c, 0xd4, 0x85, 0x8d, 0xcf, 0x49, 0x96, 0x87, - 0x49, 0xdc, 0x5d, 0xe7, 0x52, 0x45, 0xa2, 0x7b, 0xd0, 0x38, 0x19, 0x8d, 0x98, 0xd2, 0xe9, 0xa0, - 0xeb, 0xf6, 0x9c, 0x7d, 0x37, 0x28, 0x18, 0x68, 0x1f, 0xb6, 0xce, 0xf0, 0x3c, 0x20, 0x69, 0x14, - 0x8e, 0xb0, 0xf0, 0x5e, 0xe5, 0xf6, 0x65, 0x36, 0xda, 0x85, 0x3a, 0x0f, 0x78, 0x3a, 0xc8, 0xbb, - 0xb5, 0xde, 0xfa, 0xbe, 0x1b, 0x68, 0xda, 0xff, 0xa7, 0x03, 0x70, 0x8d, 0x87, 0x11, 0xe1, 0x1c, - 0x96, 0x0c, 0xa7, 0x4e, 0x07, 0x7c, 0x59, 0x6e, 0xa0, 0x48, 0x26, 0x91, 0x46, 0x7c, 0x11, 0x6e, - 0xa0, 0x48, 0xa3, 0x12, 0xeb, 0xb7, 0x55, 0xc2, 0x58, 0xa7, 0x6b, 0xaf, 0xf3, 0x53, 0xa8, 0xcb, - 0x7c, 0xf3, 0x6e, 0xb5, 0xb7, 0xbe, 0xdf, 0x3c, 0xbe, 0x23, 0x5d, 0xf0, 0x10, 0x52, 0xf6, 0xc4, - 0xfd, 0xea, 0x3f, 0xdf, 0x5d, 0x0b, 0xb4, 0xaa, 0xff, 0x27, 0x07, 0x5a, 0xa6, 0x02, 0xab, 0x97, - 0xfc, 0xd4, 0xe9, 0x17, 0x0c, 0xf4, 0x03, 0xa8, 0x5e, 0x51, 0x4c, 0x09, 0x4f, 0x7f, 0x53, 0x87, - 0x90, 0x0a, 0x5c, 0x14, 0x08, 0x0d, 0xb4, 0x09, 0x95, 0xfe, 0x39, 0x5f, 0x4d, 0x23, 0xa8, 0xf4, - 0xcf, 0xcb, 0xa9, 0xbb, 0x3a, 0x75, 0xff, 0xcf, 0x2e, 0x6c, 0x04, 0xe4, 0xb7, 0x33, 0x92, 0x53, - 0x11, 0x9e, 0x7f, 0x9a, 0xe1, 0x25, 0x03, 0x3d, 0x80, 0x46, 0x70, 0xd9, 0x3f, 0x23, 0xf4, 0x55, - 0x32, 0x96, 0x29, 0xa8, 0x42, 0x09, 0x66, 0x50, 0xc8, 0xd1, 0x00, 0x5a, 0xfd, 0x8c, 0x60, 0x2a, - 0x76, 0x25, 0xe7, 0xa9, 0x34, 0x8f, 0x77, 0xa5, 0xbe, 0x29, 0x92, 0x01, 0x64, 0x71, 0x2c, 0x2b, - 0xe6, 0x65, 0x40, 0x22, 0xa2, 0xbd, 0xb8, 0x96, 0x17, 0x53, 0x54, 0xf2, 0x62, 0x8a, 0xd0, 0x4f, - 0xa1, 0xf1, 0x9c, 0xe0, 0x8c, 0x0e, 0x09, 0x16, 0x08, 0x6b, 0x1e, 0x7f, 0x20, 0x5d, 0x68, 0xbe, - 0x6d, 0x5f, 0xe8, 0x33, 0xe3, 0x67, 0x84, 0xca, 0xf8, 0x35, 0xcb, 0x58, 0xf3, 0x4b, 0xc6, 0x9a, - 0xcf, 0x8c, 0xe5, 0xfe, 0xe2, 0x71, 0x77, 0xc3, 0x32, 0xd6, 0xfc, 0x92, 0xb1, 0xe6, 0xa3, 0x4f, - 0x61, 0xe3, 0x12, 0xcf, 0x72, 0xd2, 0x3f, 0xef, 0xd6, 0xb9, 0xe9, 0x5d, 0x05, 0x4b, 0xc1, 0xb5, - 0x0d, 0x95, 0x2e, 0x7a, 0x06, 0xed, 0x67, 0x84, 0x32, 0xb1, 0x04, 0x64, 0x83, 0x1b, 0x7f, 0xa7, - 0x48, 0xba, 0x90, 0xd9, 0x2e, 0x6c, 0x3b, 0xff, 0x1f, 0x2e, 0x43, 0x75, 0x9e, 0x26, 0x71, 0x4e, - 0xde, 0x27, 0x34, 0xb6, 0xa1, 0xfa, 0x34, 0xcb, 0x92, 0x8c, 0x63, 0xa2, 0x15, 0x08, 0x02, 0x3d, - 0x2d, 0x01, 0xc6, 0xb5, 0xb2, 0xb6, 0x01, 0x23, 0x72, 0x5a, 0x89, 0x98, 0xa7, 0x25, 0xc4, 0x54, - 0x2d, 0x37, 0x36, 0x62, 0x6c, 0x37, 0x16, 0x64, 0x1e, 0x9b, 0x90, 0x11, 0xbb, 0xde, 0x5d, 0x86, - 0x8c, 0xe5, 0xc0, 0xc0, 0xcc, 0x63, 0x13, 0x33, 0x1b, 0x96, 0xb5, 0x81, 0x19, 0xdb, 0xba, 0x00, - 0xcd, 0x63, 0x13, 0x34, 0x75, 0xcb, 0xda, 0x00, 0x8d, 0x6d, 0x5d, 0xa0, 0xe6, 0xc7, 0x05, 0x6a, - 0xc4, 0xc6, 0xef, 0x94, 0x51, 0x63, 0x59, 0x6a, 0xd8, 0x3c, 0x2f, 0xc3, 0x06, 0xb8, 0xf5, 0xbd, - 0xd5, 0xb0, 0xb1, 0x7c, 0x94, 0x71, 0xe3, 0x40, 0xfd, 0x22, 0x25, 0x19, 0xa6, 0x49, 0x86, 0xbe, - 0x07, 0xee, 0xf5, 0x22, 0x25, 0xa5, 0x11, 0x73, 0x91, 0x32, 0x66, 0xc0, 0x45, 0xe8, 0x33, 0xb3, - 0x7f, 0x73, 0xf4, 0x34, 0x8f, 0x3b, 0x52, 0xb1, 0x10, 0xc8, 0x58, 0x66, 0xab, 0x7f, 0xc4, 0x3a, + // 1852 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xcd, 0x73, 0x1b, 0x49, + 0x15, 0xf7, 0xc8, 0xa3, 0xaf, 0x27, 0xc9, 0x1e, 0x75, 0x1c, 0xaf, 0xca, 0x64, 0x8d, 0x98, 0xca, + 0x2e, 0xc6, 0xd9, 0xd8, 0x85, 0xc3, 0xb2, 0x55, 0x10, 0x3e, 0x1c, 0x29, 0x95, 0xb8, 0x82, 0x3f, + 0x6a, 0xec, 0xe4, 0xc0, 0x56, 0x51, 0xd5, 0x92, 0xda, 0xca, 0x64, 0x47, 0x33, 0xc3, 0x4c, 0x0b, + 0x2c, 0x4e, 0x70, 0xe5, 0x1f, 0xe0, 0x08, 0x7f, 0x01, 0x27, 0xa8, 0xe2, 0x4f, 0xd8, 0x2a, 0x2e, + 0x7b, 0xe3, 0x46, 0x41, 0xf8, 0x47, 0xa8, 0xfe, 0x9c, 0xee, 0x91, 0xe2, 0xec, 0x61, 0x6f, 0xf3, + 0xbe, 0x5f, 0xbf, 0xfe, 0xf5, 0x7b, 0xdd, 0x03, 0xad, 0xfc, 0x35, 0xce, 0x26, 0x07, 0x69, 0x96, + 0xd0, 0x04, 0x55, 0x39, 0xb1, 0xf3, 0x70, 0x1a, 0xd2, 0xd7, 0xf3, 0xd1, 0xc1, 0x38, 0x99, 0x1d, + 0x4e, 0x93, 0x69, 0x72, 0xc8, 0xa5, 0xa3, 0xf9, 0x35, 0xa7, 0x38, 0xc1, 0xbf, 0x84, 0xd5, 0xce, + 0x26, 0x0d, 0x67, 0x24, 0xa7, 0x78, 0x96, 0x4a, 0xc6, 0x46, 0x1a, 0xa6, 0x24, 0x0a, 0x63, 0x22, + 0x69, 0x48, 0x23, 0x1c, 0x8b, 0x6f, 0xff, 0x5f, 0x0e, 0x6c, 0x5c, 0xb2, 0x28, 0xf9, 0x29, 0xa1, + 0x78, 0x82, 0x29, 0x46, 0x1f, 0x41, 0xed, 0x22, 0x89, 0xc2, 0xf1, 0xa2, 0xe7, 0xf4, 0x9d, 0xbd, + 0x8d, 0xa3, 0xce, 0x81, 0xc8, 0x49, 0x30, 0x03, 0x29, 0x44, 0x7d, 0x68, 0x09, 0xc3, 0x41, 0x32, + 0x8f, 0x69, 0xaf, 0xd2, 0x77, 0xf6, 0x3a, 0x81, 0xc9, 0x42, 0x3d, 0xa8, 0xbf, 0x22, 0x59, 0x1e, + 0x26, 0x71, 0x6f, 0x9d, 0x4b, 0x15, 0x89, 0xee, 0x41, 0xf3, 0x78, 0x3c, 0x66, 0x4a, 0x27, 0xc3, + 0x9e, 0xdb, 0x77, 0xf6, 0xdc, 0xa0, 0x60, 0xa0, 0x3d, 0xd8, 0x3c, 0xc5, 0x37, 0x01, 0x49, 0xa3, + 0x70, 0x8c, 0x85, 0xf7, 0x2a, 0xb7, 0x2f, 0xb3, 0xd1, 0x0e, 0x34, 0x78, 0xc0, 0x93, 0x61, 0xde, + 0xab, 0xf5, 0xd7, 0xf7, 0xdc, 0x40, 0xd3, 0xfe, 0x3f, 0x1c, 0x80, 0x2b, 0x3c, 0x8a, 0x08, 0xe7, + 0xb0, 0x64, 0x38, 0x75, 0x32, 0xe4, 0xcb, 0x72, 0x03, 0x45, 0x32, 0x89, 0x34, 0xe2, 0x8b, 0x70, + 0x03, 0x45, 0x1a, 0x95, 0x58, 0xbf, 0xad, 0x12, 0xc6, 0x3a, 0x5d, 0x7b, 0x9d, 0x9f, 0x42, 0x43, + 0xe6, 0x9b, 0xf7, 0xaa, 0xfd, 0xf5, 0xbd, 0xd6, 0xd1, 0x1d, 0xe9, 0x82, 0x87, 0x90, 0xb2, 0x27, + 0xee, 0x97, 0xff, 0xfe, 0xf6, 0x5a, 0xa0, 0x55, 0xfd, 0x3f, 0x38, 0xd0, 0x36, 0x15, 0x58, 0xbd, + 0xe4, 0xa7, 0x4e, 0xbf, 0x60, 0xa0, 0xef, 0x41, 0xf5, 0x92, 0x62, 0x4a, 0x78, 0xfa, 0x1b, 0x3a, + 0x84, 0x54, 0xe0, 0xa2, 0x40, 0x68, 0xa0, 0x0d, 0xa8, 0x0c, 0xce, 0xf8, 0x6a, 0x9a, 0x41, 0x65, + 0x70, 0x56, 0x4e, 0xdd, 0xd5, 0xa9, 0xfb, 0x7f, 0x72, 0xa1, 0x1e, 0x90, 0x5f, 0xcf, 0x49, 0x4e, + 0x45, 0x78, 0xfe, 0x69, 0x86, 0x97, 0x0c, 0xf4, 0x00, 0x9a, 0xc1, 0xc5, 0xe0, 0x94, 0xd0, 0xd7, + 0xc9, 0x44, 0xa6, 0xa0, 0x0a, 0x25, 0x98, 0x41, 0x21, 0x47, 0x43, 0x68, 0x0f, 0x32, 0x82, 0xa9, + 0xd8, 0x95, 0x9c, 0xa7, 0xd2, 0x3a, 0xda, 0x91, 0xfa, 0xa6, 0x48, 0x06, 0x90, 0xc5, 0xb1, 0xac, + 0x98, 0x97, 0x21, 0x89, 0x88, 0xf6, 0xe2, 0x5a, 0x5e, 0x4c, 0x51, 0xc9, 0x8b, 0x29, 0x42, 0x3f, + 0x86, 0xe6, 0x73, 0x82, 0x33, 0x3a, 0x22, 0x58, 0x20, 0xac, 0x75, 0xf4, 0x81, 0x74, 0xa1, 0xf9, + 0xb6, 0x7d, 0xa1, 0xcf, 0x8c, 0x9f, 0x11, 0x2a, 0xe3, 0xd7, 0x2c, 0x63, 0xcd, 0x2f, 0x19, 0x6b, + 0x3e, 0x33, 0x96, 0xfb, 0x8b, 0x27, 0xbd, 0xba, 0x65, 0xac, 0xf9, 0x25, 0x63, 0xcd, 0x47, 0x9f, + 0x42, 0xfd, 0x02, 0xcf, 0x73, 0x32, 0x38, 0xeb, 0x35, 0xb8, 0xe9, 0x5d, 0x05, 0x4b, 0xc1, 0xb5, + 0x0d, 0x95, 0x2e, 0x7a, 0x06, 0x9d, 0x67, 0x84, 0x32, 0xb1, 0x04, 0x64, 0x93, 0x1b, 0x7f, 0xab, + 0x48, 0xba, 0x90, 0xd9, 0x2e, 0x6c, 0x3b, 0xff, 0xef, 0x2e, 0x43, 0x75, 0x9e, 0x26, 0x71, 0x4e, + 0xbe, 0x49, 0x68, 0x6c, 0x41, 0xf5, 0x69, 0x96, 0x25, 0x19, 0xc7, 0x44, 0x3b, 0x10, 0x04, 0x7a, + 0x5a, 0x02, 0x8c, 0x6b, 0x65, 0x6d, 0x03, 0x46, 0xe4, 0xb4, 0x12, 0x31, 0x4f, 0x4b, 0x88, 0xa9, + 0x5a, 0x6e, 0x6c, 0xc4, 0xd8, 0x6e, 0x2c, 0xc8, 0x3c, 0x36, 0x21, 0x23, 0x76, 0xbd, 0xb7, 0x0c, + 0x19, 0xcb, 0x81, 0x81, 0x99, 0xc7, 0x26, 0x66, 0xea, 0x96, 0xb5, 0x81, 0x19, 0xdb, 0xba, 0x00, + 0xcd, 0x63, 0x13, 0x34, 0x0d, 0xcb, 0xda, 0x00, 0x8d, 0x6d, 0x5d, 0xa0, 0xe6, 0x87, 0x05, 0x6a, + 0xc4, 0xc6, 0x6f, 0x97, 0x51, 0x63, 0x59, 0x6a, 0xd8, 0x3c, 0x2f, 0xc3, 0x06, 0xb8, 0xf5, 0xbd, + 0xd5, 0xb0, 0xb1, 0x7c, 0x94, 0x71, 0xe3, 0x40, 0xe3, 0x3c, 0x25, 0x19, 0xa6, 0x49, 0x86, 0xbe, + 0x03, 0xee, 0xd5, 0x22, 0x25, 0xa5, 0x11, 0x73, 0x9e, 0x32, 0x66, 0xc0, 0x45, 0xe8, 0x33, 0xb3, + 0x7f, 0x73, 0xf4, 0xb4, 0x8e, 0xba, 0x52, 0xb1, 0x10, 0xc8, 0x58, 0x66, 0xab, 0x7f, 0xc4, 0x3a, 0x17, 0x0f, 0x2a, 0xdb, 0xcb, 0x2d, 0x4d, 0x57, 0x69, 0x9a, 0xf3, 0xc1, 0xb5, 0xe6, 0x83, 0xff, - 0x1b, 0xb8, 0xb3, 0xa2, 0x2f, 0xb1, 0x56, 0xaa, 0x21, 0x5f, 0x39, 0x1d, 0xa0, 0xcf, 0xa0, 0xae, - 0x46, 0xa8, 0x4c, 0xf6, 0xae, 0x19, 0x56, 0xcf, 0x57, 0xd5, 0xed, 0x15, 0xed, 0xef, 0xc0, 0xf6, + 0x2b, 0xb8, 0xb3, 0xa2, 0x2f, 0xb1, 0x56, 0xaa, 0x21, 0x5f, 0x39, 0x19, 0xa2, 0xcf, 0xa0, 0xa1, + 0x46, 0xa8, 0x4c, 0xf6, 0xae, 0x19, 0x56, 0xcf, 0x57, 0xd5, 0xed, 0x15, 0xed, 0x6f, 0xc3, 0xd6, 0x2a, 0x18, 0xfb, 0x1f, 0xc1, 0x9d, 0x15, 0x9d, 0xac, 0x1c, 0x97, 0x99, 0xaf, 0x82, 0xaf, 0x7f, - 0x05, 0x5e, 0xb9, 0x8b, 0xc9, 0xf6, 0xef, 0xe8, 0xf6, 0x7f, 0x04, 0x35, 0x89, 0xc6, 0x0a, 0x9f, - 0x4e, 0x6f, 0x2d, 0xaf, 0x54, 0xf3, 0x9f, 0x43, 0x67, 0x09, 0xe7, 0xe8, 0x11, 0x34, 0xd4, 0xbe, - 0xe6, 0x5d, 0x87, 0x3b, 0xda, 0xd2, 0x1b, 0x2a, 0xf8, 0x0a, 0x8f, 0x5a, 0xcf, 0xff, 0x02, 0xbc, - 0x72, 0x9f, 0x7c, 0x7f, 0x25, 0x1d, 0x40, 0x67, 0xe9, 0x40, 0x19, 0x8b, 0x75, 0xbe, 0xdd, 0x62, - 0xff, 0xe5, 0x80, 0x57, 0x6e, 0xc7, 0xe8, 0x21, 0x54, 0x05, 0x20, 0x9d, 0xdb, 0x01, 0x29, 0xb4, - 0x64, 0xc5, 0x2b, 0xba, 0xe2, 0x3b, 0x50, 0x93, 0xed, 0x50, 0x5c, 0x89, 0x24, 0x85, 0x3e, 0x81, - 0xea, 0x25, 0xce, 0xf0, 0x54, 0xf6, 0x37, 0x4f, 0xcf, 0x70, 0x3c, 0xe6, 0x7c, 0xe5, 0x95, 0x13, - 0xe8, 0x18, 0x6a, 0x4c, 0x72, 0xa2, 0xc6, 0xd6, 0xf6, 0x61, 0x71, 0xe7, 0xbb, 0x56, 0x5f, 0x6a, - 0x35, 0x42, 0xd3, 0x7f, 0x08, 0x9d, 0xa5, 0x36, 0xc1, 0x50, 0x7f, 0x89, 0x17, 0x51, 0x82, 0xc5, - 0x7a, 0x5a, 0x81, 0x22, 0xfd, 0x1e, 0x6c, 0xda, 0xf3, 0xc4, 0xd8, 0x9d, 0x06, 0x07, 0x5e, 0x07, - 0xb6, 0x4a, 0xbd, 0xc3, 0xff, 0x18, 0xb6, 0x57, 0xcd, 0x91, 0x25, 0xd3, 0x73, 0xb8, 0xbb, 0xb2, - 0x71, 0x58, 0x17, 0x26, 0xe7, 0xdb, 0x5f, 0x98, 0xfe, 0xbe, 0xc1, 0xc6, 0x90, 0x2c, 0x15, 0x1f, - 0x90, 0x59, 0x32, 0x22, 0x79, 0x2e, 0x37, 0xe9, 0xee, 0xa1, 0xbe, 0x01, 0x4b, 0xc1, 0x69, 0x7c, - 0x93, 0xe8, 0x4e, 0x27, 0x58, 0xe8, 0x87, 0x50, 0xbf, 0x9e, 0xc7, 0x7c, 0x23, 0x25, 0xda, 0x14, - 0x8a, 0x15, 0x5b, 0xc5, 0x55, 0x34, 0x6b, 0x51, 0xec, 0x5e, 0x95, 0x8b, 0xad, 0x5b, 0xb7, 0x10, - 0x51, 0x08, 0x54, 0x8b, 0x2a, 0x38, 0xe8, 0x47, 0xd0, 0xb8, 0x0a, 0xff, 0x40, 0x56, 0x6d, 0xb9, - 0xe6, 0xeb, 0x1e, 0xae, 0x18, 0xe8, 0x27, 0xd0, 0x0c, 0x70, 0x3c, 0x21, 0x32, 0x9e, 0xd8, 0x7b, - 0xa4, 0xa0, 0x52, 0x48, 0xa4, 0xa5, 0xa9, 0x8c, 0x52, 0xf8, 0x90, 0x95, 0x3c, 0x89, 0x66, 0x53, - 0x75, 0x4c, 0xae, 0x46, 0x38, 0x66, 0x85, 0x10, 0xde, 0xc4, 0x34, 0xbb, 0x6f, 0xf4, 0xf5, 0xb7, - 0xea, 0x4a, 0xff, 0xb7, 0x3b, 0x44, 0xbf, 0x82, 0xce, 0x19, 0xc9, 0x26, 0xe4, 0x62, 0xf8, 0x9a, - 0x8c, 0x54, 0x8d, 0xec, 0xa9, 0xb7, 0x24, 0x97, 0x9e, 0x97, 0x0d, 0xd9, 0xee, 0xbc, 0x20, 0x0b, - 0xe1, 0xa4, 0x6e, 0xed, 0x8e, 0x62, 0xab, 0xdd, 0x51, 0x34, 0x3a, 0x05, 0x8f, 0x81, 0x82, 0x64, - 0x4f, 0x66, 0x61, 0x24, 0xb0, 0x21, 0x67, 0xdf, 0x07, 0xc6, 0xf1, 0x32, 0xc5, 0xd2, 0xc5, 0x92, - 0x19, 0xab, 0xde, 0x65, 0x16, 0x4e, 0x71, 0xb6, 0x78, 0x41, 0x16, 0xf9, 0x19, 0x5e, 0x3c, 0x21, - 0x67, 0xc9, 0x38, 0xbc, 0x09, 0x89, 0xf4, 0x0b, 0x56, 0xf5, 0x6e, 0xd5, 0x55, 0xd5, 0xbb, 0x55, - 0x09, 0xfd, 0x12, 0xda, 0x2c, 0x8b, 0x73, 0x32, 0xa7, 0x22, 0x42, 0x53, 0x9e, 0xf4, 0x22, 0x73, - 0x2d, 0x53, 0xf3, 0xd6, 0x62, 0xa2, 0x3e, 0x6c, 0x32, 0x46, 0x3f, 0x4a, 0x72, 0x09, 0xb4, 0x96, - 0xd5, 0x43, 0x6d, 0xa1, 0xf4, 0x51, 0x32, 0x41, 0x5f, 0xc0, 0x4e, 0x3f, 0x89, 0x22, 0x32, 0xa2, - 0xd7, 0xc9, 0x74, 0x98, 0xd3, 0x24, 0x56, 0xe8, 0x6b, 0x73, 0x67, 0x1f, 0xaa, 0x8b, 0xd8, 0x4a, - 0x25, 0xe9, 0xf4, 0x2d, 0x2e, 0xfc, 0xbf, 0x39, 0xc5, 0x91, 0xb3, 0xdf, 0x84, 0x4e, 0xf9, 0x4d, - 0xb8, 0x07, 0x30, 0xc0, 0x14, 0x0f, 0x71, 0x4e, 0xf4, 0x3b, 0xcd, 0xe0, 0x20, 0x1f, 0x5a, 0x8a, - 0x3a, 0xc7, 0x53, 0x22, 0x9f, 0x38, 0x16, 0x8f, 0x45, 0xe0, 0xa1, 0xb8, 0x82, 0xcb, 0x15, 0x0a, - 0x06, 0xf3, 0x20, 0xc6, 0xf0, 0xf8, 0x34, 0xbe, 0x9e, 0xc7, 0xfc, 0x74, 0xd5, 0x03, 0x8b, 0xe7, - 0xf7, 0xcc, 0xf3, 0x8e, 0x10, 0xb8, 0xf9, 0x22, 0x1e, 0xf1, 0x64, 0xeb, 0x01, 0xff, 0xf6, 0x1f, - 0x18, 0x07, 0x9b, 0x25, 0x3d, 0x62, 0xe7, 0x23, 0xe6, 0x11, 0x45, 0xfb, 0x33, 0x38, 0xfe, 0x5f, - 0x1c, 0xeb, 0x40, 0xa3, 0x1e, 0x54, 0x9f, 0xce, 0x53, 0x3d, 0x44, 0xe1, 0x90, 0x3f, 0xd4, 0x19, - 0x2b, 0x10, 0x02, 0x96, 0x64, 0x9a, 0x91, 0x93, 0x28, 0x4a, 0x46, 0x2c, 0x8c, 0x7c, 0x75, 0x5b, - 0x3c, 0xf4, 0x09, 0x74, 0xd8, 0x61, 0x94, 0x35, 0x37, 0x1e, 0xb0, 0xed, 0x60, 0x59, 0xc0, 0x8a, - 0x42, 0xe7, 0xf1, 0xc5, 0xcd, 0x4d, 0x4e, 0xa8, 0x7c, 0xbe, 0x16, 0x0c, 0xff, 0xe7, 0x6f, 0xdb, - 0x7e, 0x74, 0x1f, 0xda, 0x23, 0x2b, 0x82, 0xd8, 0x32, 0x9b, 0xe9, 0xff, 0xe2, 0x1d, 0x5d, 0xe7, - 0x9d, 0x25, 0xba, 0x57, 0x1c, 0x7b, 0xe4, 0xc1, 0xfa, 0x0b, 0xb2, 0x90, 0x83, 0x8a, 0x7d, 0xfa, - 0x7f, 0x74, 0x96, 0x8f, 0x38, 0x9b, 0x69, 0x19, 0x89, 0xd8, 0xce, 0xab, 0x99, 0x26, 0x49, 0xb4, - 0x07, 0x2e, 0x99, 0xa7, 0x99, 0xec, 0xee, 0x66, 0x79, 0x39, 0x1f, 0x1d, 0xc3, 0x36, 0x55, 0xcb, - 0x3c, 0x49, 0xd3, 0x68, 0x61, 0x14, 0xaf, 0x1a, 0xac, 0x94, 0xf9, 0xdf, 0x87, 0x8e, 0x91, 0x41, - 0x40, 0xf2, 0x59, 0x44, 0x19, 0x32, 0x66, 0xb3, 0x50, 0xcd, 0x54, 0xfe, 0xed, 0xff, 0xac, 0x74, - 0xa0, 0x57, 0x29, 0xb1, 0xdc, 0xc5, 0xe2, 0xc5, 0x8d, 0xac, 0x11, 0x28, 0xd2, 0xdf, 0x17, 0xa7, - 0x99, 0x99, 0xcb, 0x20, 0x3b, 0x50, 0xcb, 0xf8, 0x97, 0xf4, 0x20, 0x29, 0xff, 0x7e, 0xf9, 0xdc, - 0xaf, 0x4c, 0x07, 0xbf, 0xa3, 0xa3, 0x31, 0xa3, 0x9b, 0x2c, 0x99, 0x2a, 0x23, 0xf6, 0xcd, 0xe6, - 0x38, 0x4d, 0x78, 0xf9, 0x5a, 0x41, 0x85, 0x26, 0x0c, 0x3c, 0x5f, 0x92, 0xc5, 0xe7, 0x64, 0x44, - 0xf5, 0xb3, 0xad, 0x60, 0xf8, 0x2f, 0x57, 0x0c, 0x00, 0xb4, 0x0b, 0xf5, 0x64, 0xf8, 0x3a, 0x67, - 0xa7, 0x88, 0xc3, 0xbc, 0x15, 0x68, 0x9a, 0x61, 0x8a, 0xe2, 0x6c, 0x42, 0xe8, 0xc5, 0xf0, 0x35, - 0x87, 0xb7, 0x40, 0xad, 0xcd, 0x3c, 0x78, 0xa0, 0xfe, 0xca, 0xa0, 0x3a, 0xb8, 0xe7, 0x49, 0x4c, - 0xbc, 0x35, 0xd4, 0x86, 0xc6, 0x25, 0xce, 0x68, 0x48, 0xc3, 0x24, 0xf6, 0x1c, 0x26, 0x78, 0x8e, - 0xf3, 0x57, 0x5e, 0xe5, 0xe0, 0x05, 0xd4, 0xc4, 0xa3, 0x02, 0x6d, 0x02, 0x9c, 0x8c, 0xd5, 0x0d, - 0xc2, 0x5b, 0x43, 0x1d, 0x68, 0x8b, 0x7b, 0xb3, 0x62, 0x39, 0xcc, 0x8b, 0x60, 0x9d, 0x44, 0x91, - 0x57, 0x41, 0x5b, 0xd0, 0x14, 0xa7, 0x9f, 0x37, 0x09, 0x6f, 0xfd, 0xe0, 0x63, 0xd8, 0xe8, 0x9f, - 0x8b, 0x1f, 0x29, 0x35, 0xa8, 0xbc, 0x4c, 0xbd, 0x35, 0xd4, 0x60, 0xf7, 0xb6, 0x59, 0x4e, 0x44, - 0xd0, 0x41, 0xf2, 0xfb, 0xd8, 0xab, 0x1c, 0xbc, 0x84, 0x96, 0xf9, 0xf3, 0x85, 0x87, 0x66, 0xc7, - 0x13, 0xd3, 0x30, 0x9e, 0x88, 0x6c, 0x25, 0x4d, 0xc6, 0x9e, 0x83, 0x9a, 0xb0, 0x11, 0xcc, 0xe2, - 0x98, 0xc9, 0x2a, 0x08, 0xa0, 0x76, 0x96, 0xfc, 0x8e, 0x7d, 0xaf, 0x33, 0x3d, 0x7d, 0xec, 0x3c, - 0xf7, 0x60, 0xa1, 0xee, 0x8e, 0x4c, 0xa0, 0xaf, 0xe1, 0xde, 0x1a, 0xf2, 0xec, 0x37, 0xb2, 0xe7, - 0x30, 0x8e, 0xf9, 0x28, 0xf0, 0x2a, 0xcc, 0x44, 0x5f, 0x89, 0x85, 0x6b, 0x7d, 0x1b, 0xf4, 0x5c, - 0x96, 0x82, 0xbc, 0xcb, 0x79, 0x55, 0x56, 0x19, 0xeb, 0x76, 0xe6, 0xd5, 0x9e, 0x0c, 0xbe, 0xfe, - 0xdf, 0x9e, 0xf3, 0xd5, 0x9b, 0x3d, 0xe7, 0xeb, 0x37, 0x7b, 0xce, 0x7f, 0xdf, 0xec, 0xad, 0xfd, - 0xf5, 0xff, 0x7b, 0xce, 0xaf, 0x0f, 0x8d, 0x1f, 0x93, 0x53, 0x4c, 0xb3, 0x70, 0x9e, 0x64, 0xe1, - 0x24, 0x8c, 0x15, 0x11, 0x93, 0xa3, 0xf4, 0xcb, 0xc9, 0x51, 0x3a, 0x3c, 0xe2, 0x43, 0x62, 0x58, - 0xe3, 0xff, 0x1c, 0x1f, 0x7d, 0x13, 0x00, 0x00, 0xff, 0xff, 0x10, 0xeb, 0x9f, 0x51, 0xe5, 0x14, - 0x00, 0x00, + 0x09, 0x5e, 0xb9, 0x8b, 0xc9, 0xf6, 0xef, 0xe8, 0xf6, 0x7f, 0x08, 0x35, 0x89, 0xc6, 0x0a, 0x9f, + 0x4e, 0xef, 0x2c, 0xaf, 0x54, 0xf3, 0x9f, 0x43, 0x77, 0x09, 0xe7, 0xe8, 0x11, 0x34, 0xd5, 0xbe, + 0xe6, 0x3d, 0x87, 0x3b, 0xda, 0xd4, 0x1b, 0x2a, 0xf8, 0x0a, 0x8f, 0x5a, 0xcf, 0xff, 0x1c, 0xbc, + 0x72, 0x9f, 0xfc, 0xe6, 0x4a, 0x3a, 0x84, 0xee, 0xd2, 0x81, 0x32, 0x16, 0xeb, 0x7c, 0xbd, 0xc5, + 0xfe, 0xd3, 0x01, 0xaf, 0xdc, 0x8e, 0xd1, 0x43, 0xa8, 0x0a, 0x40, 0x3a, 0xb7, 0x03, 0x52, 0x68, + 0xc9, 0x8a, 0x57, 0x74, 0xc5, 0xb7, 0xa1, 0x26, 0xdb, 0xa1, 0xb8, 0x12, 0x49, 0x0a, 0x7d, 0x02, + 0xd5, 0x0b, 0x9c, 0xe1, 0x99, 0xec, 0x6f, 0x9e, 0x9e, 0xe1, 0x78, 0xc2, 0xf9, 0xca, 0x2b, 0x27, + 0xd0, 0x11, 0xd4, 0x98, 0xe4, 0x58, 0x8d, 0xad, 0xad, 0x83, 0xe2, 0xce, 0x77, 0xa5, 0xbe, 0xd4, + 0x6a, 0x84, 0xa6, 0xff, 0x10, 0xba, 0x4b, 0x6d, 0x82, 0xa1, 0xfe, 0x02, 0x2f, 0xa2, 0x04, 0x8b, + 0xf5, 0xb4, 0x03, 0x45, 0xfa, 0x7d, 0xd8, 0xb0, 0xe7, 0x89, 0xb1, 0x3b, 0x4d, 0x0e, 0xbc, 0x2e, + 0x6c, 0x96, 0x7a, 0x87, 0xff, 0x31, 0x6c, 0xad, 0x9a, 0x23, 0x4b, 0xa6, 0x67, 0x70, 0x77, 0x65, + 0xe3, 0xb0, 0x2e, 0x4c, 0xce, 0xd7, 0xbf, 0x30, 0xfd, 0xad, 0xce, 0xc6, 0x90, 0x2c, 0x15, 0x1f, + 0x90, 0x59, 0x32, 0x26, 0x79, 0x2e, 0x37, 0xe9, 0xee, 0x81, 0xbe, 0x01, 0x4b, 0xc1, 0x49, 0x7c, + 0x9d, 0xe8, 0x4e, 0x27, 0x58, 0xe8, 0xfb, 0xd0, 0xb8, 0xba, 0x89, 0xf9, 0x46, 0x4a, 0xb4, 0x29, + 0x14, 0x2b, 0xb6, 0x8a, 0xab, 0x68, 0xd6, 0xa2, 0xd8, 0xbd, 0x2a, 0x17, 0x5b, 0xb7, 0x6e, 0x21, + 0xa2, 0x10, 0xa8, 0x16, 0x55, 0x70, 0xd0, 0x0f, 0xa0, 0x79, 0x19, 0xfe, 0x8e, 0xac, 0xda, 0x72, + 0xcd, 0xd7, 0x3d, 0x5c, 0x31, 0xd0, 0x8f, 0xa0, 0x15, 0xe0, 0x78, 0x4a, 0x64, 0x3c, 0xb1, 0xf7, + 0x48, 0x41, 0xa5, 0x90, 0x48, 0x4b, 0x53, 0x19, 0xa5, 0xf0, 0x21, 0x2b, 0x79, 0x12, 0xcd, 0x67, + 0xea, 0x98, 0x5c, 0x8e, 0x71, 0xcc, 0x0a, 0x21, 0xbc, 0x89, 0x69, 0x76, 0xdf, 0xe8, 0xeb, 0xef, + 0xd4, 0x95, 0xfe, 0x6f, 0x77, 0x88, 0x7e, 0x01, 0xdd, 0x53, 0x92, 0x4d, 0xc9, 0xf9, 0xe8, 0x0d, + 0x19, 0xab, 0x1a, 0xd9, 0x53, 0x6f, 0x49, 0x2e, 0x3d, 0x2f, 0x1b, 0xb2, 0xdd, 0x79, 0x41, 0x16, + 0xc2, 0x49, 0xc3, 0xda, 0x1d, 0xc5, 0x56, 0xbb, 0xa3, 0x68, 0x74, 0x02, 0x1e, 0x03, 0x05, 0xc9, + 0x9e, 0xcc, 0xc3, 0x48, 0x60, 0x43, 0xce, 0xbe, 0x0f, 0x8c, 0xe3, 0x65, 0x8a, 0xa5, 0x8b, 0x25, + 0x33, 0x56, 0xbd, 0x8b, 0x2c, 0x9c, 0xe1, 0x6c, 0xf1, 0x82, 0x2c, 0xf2, 0x53, 0xbc, 0x78, 0x42, + 0x4e, 0x93, 0x49, 0x78, 0x1d, 0x12, 0xe9, 0x17, 0xac, 0xea, 0xdd, 0xaa, 0xab, 0xaa, 0x77, 0xab, + 0x12, 0xfa, 0x39, 0x74, 0x58, 0x16, 0x67, 0xe4, 0x86, 0x8a, 0x08, 0x2d, 0x79, 0xd2, 0x8b, 0xcc, + 0xb5, 0x4c, 0xcd, 0x5b, 0x8b, 0x89, 0x06, 0xb0, 0xc1, 0x18, 0x83, 0x28, 0xc9, 0x25, 0xd0, 0xda, + 0x56, 0x0f, 0xb5, 0x85, 0xd2, 0x47, 0xc9, 0x04, 0x7d, 0x0e, 0xdb, 0x83, 0x24, 0x8a, 0xc8, 0x98, + 0x5e, 0x25, 0xb3, 0x51, 0x4e, 0x93, 0x58, 0xa1, 0xaf, 0xc3, 0x9d, 0x7d, 0xa8, 0x2e, 0x62, 0x2b, + 0x95, 0xa4, 0xd3, 0x77, 0xb8, 0xf0, 0xff, 0xea, 0x14, 0x47, 0xce, 0x7e, 0x13, 0x3a, 0xe5, 0x37, + 0xe1, 0x2e, 0xc0, 0x10, 0x53, 0x3c, 0xc2, 0x39, 0xd1, 0xef, 0x34, 0x83, 0x83, 0x7c, 0x68, 0x2b, + 0xea, 0x0c, 0xcf, 0x88, 0x7c, 0xe2, 0x58, 0x3c, 0x16, 0x81, 0x87, 0xe2, 0x0a, 0x2e, 0x57, 0x28, + 0x18, 0xcc, 0x83, 0x18, 0xc3, 0x93, 0x93, 0xf8, 0xea, 0x26, 0xe6, 0xa7, 0xab, 0x11, 0x58, 0x3c, + 0xbf, 0x6f, 0x9e, 0x77, 0x84, 0xc0, 0xcd, 0x17, 0xf1, 0x98, 0x27, 0xdb, 0x08, 0xf8, 0xb7, 0xff, + 0xc0, 0x38, 0xd8, 0x2c, 0xe9, 0x31, 0x3b, 0x1f, 0x31, 0x8f, 0x28, 0xda, 0x9f, 0xc1, 0xf1, 0xff, + 0xec, 0x58, 0x07, 0x1a, 0xf5, 0xa1, 0xfa, 0xf4, 0x26, 0xd5, 0x43, 0x14, 0x0e, 0xf8, 0x43, 0x9d, + 0xb1, 0x02, 0x21, 0x60, 0x49, 0xa6, 0x19, 0x39, 0x8e, 0xa2, 0x64, 0xcc, 0xc2, 0xc8, 0x57, 0xb7, + 0xc5, 0x43, 0x9f, 0x40, 0x97, 0x1d, 0x46, 0x59, 0x73, 0xe3, 0x01, 0xdb, 0x09, 0x96, 0x05, 0xac, + 0x28, 0xf4, 0x26, 0x3e, 0xbf, 0xbe, 0xce, 0x09, 0x95, 0xcf, 0xd7, 0x82, 0xe1, 0xff, 0xf4, 0x5d, + 0xdb, 0x8f, 0xee, 0x43, 0x67, 0x6c, 0x45, 0x10, 0x5b, 0x66, 0x33, 0xfd, 0x9f, 0xbd, 0xa7, 0xeb, + 0xbc, 0xb7, 0x44, 0xf7, 0x8a, 0x63, 0x8f, 0x3c, 0x58, 0x7f, 0x41, 0x16, 0x72, 0x50, 0xb1, 0x4f, + 0xff, 0xf7, 0xce, 0xf2, 0x11, 0x67, 0x33, 0x2d, 0x23, 0x11, 0xdb, 0x79, 0x35, 0xd3, 0x24, 0x89, + 0x76, 0xc1, 0x25, 0x37, 0x69, 0x26, 0xbb, 0xbb, 0x59, 0x5e, 0xce, 0x47, 0x47, 0xb0, 0x45, 0xd5, + 0x32, 0x8f, 0xd3, 0x34, 0x5a, 0x18, 0xc5, 0xab, 0x06, 0x2b, 0x65, 0xfe, 0x77, 0xa1, 0x6b, 0x64, + 0x10, 0x90, 0x7c, 0x1e, 0x51, 0x86, 0x8c, 0xf9, 0x3c, 0x54, 0x33, 0x95, 0x7f, 0xfb, 0x3f, 0x29, + 0x1d, 0xe8, 0x55, 0x4a, 0x2c, 0x77, 0xb1, 0x78, 0x71, 0x23, 0x6b, 0x06, 0x8a, 0xf4, 0xf7, 0xc4, + 0x69, 0x66, 0xe6, 0x32, 0xc8, 0x36, 0xd4, 0x32, 0xfe, 0x25, 0x3d, 0x48, 0xca, 0xbf, 0x5f, 0x3e, + 0xf7, 0x2b, 0xd3, 0xc1, 0xef, 0xe9, 0x68, 0xcc, 0xe8, 0x3a, 0x4b, 0x66, 0xca, 0x88, 0x7d, 0xb3, + 0x39, 0x4e, 0x13, 0x5e, 0xbe, 0x76, 0x50, 0xa1, 0x09, 0x03, 0xcf, 0x17, 0x64, 0xf1, 0x8a, 0x8c, + 0xa9, 0x7e, 0xb6, 0x15, 0x0c, 0xff, 0xe5, 0x8a, 0x01, 0x80, 0x76, 0xa0, 0x91, 0x8c, 0xde, 0xe4, + 0xec, 0x14, 0x71, 0x98, 0xb7, 0x03, 0x4d, 0x33, 0x4c, 0x51, 0x9c, 0x4d, 0x09, 0x3d, 0x1f, 0xbd, + 0xe1, 0xf0, 0x16, 0xa8, 0xb5, 0x99, 0xfb, 0x0f, 0xd4, 0x5f, 0x19, 0xd4, 0x00, 0xf7, 0x2c, 0x89, + 0x89, 0xb7, 0x86, 0x3a, 0xd0, 0xbc, 0xc0, 0x19, 0x0d, 0x69, 0x98, 0xc4, 0x9e, 0xc3, 0x04, 0xcf, + 0x71, 0xfe, 0xda, 0xab, 0xec, 0xbf, 0x80, 0x9a, 0x78, 0x54, 0xa0, 0x0d, 0x80, 0xe3, 0x89, 0xba, + 0x41, 0x78, 0x6b, 0xa8, 0x0b, 0x1d, 0x71, 0x6f, 0x56, 0x2c, 0x87, 0x79, 0x11, 0xac, 0xe3, 0x28, + 0xf2, 0x2a, 0x68, 0x13, 0x5a, 0xe2, 0xf4, 0xf3, 0x26, 0xe1, 0xad, 0xef, 0x7f, 0x0c, 0xf5, 0xc1, + 0x99, 0xf8, 0x91, 0x52, 0x83, 0xca, 0xcb, 0xd4, 0x5b, 0x43, 0x4d, 0x76, 0x6f, 0x9b, 0xe7, 0x44, + 0x04, 0x1d, 0x26, 0xbf, 0x8d, 0xbd, 0xca, 0xfe, 0x4b, 0x68, 0x9b, 0x3f, 0x5f, 0x78, 0x68, 0x76, + 0x3c, 0x31, 0x0d, 0xe3, 0xa9, 0xc8, 0x56, 0xd2, 0x64, 0xe2, 0x39, 0xa8, 0x05, 0xf5, 0x60, 0x1e, + 0xc7, 0x4c, 0x56, 0x41, 0x00, 0xb5, 0xd3, 0xe4, 0x37, 0xec, 0x7b, 0x9d, 0xe9, 0xe9, 0x63, 0xe7, + 0xb9, 0xfb, 0x7f, 0x74, 0xd4, 0xe5, 0x91, 0x49, 0xf4, 0x3d, 0xdc, 0x5b, 0x43, 0x9e, 0xfd, 0x48, + 0xf6, 0x1c, 0xc6, 0x31, 0x5f, 0x05, 0x5e, 0x85, 0x99, 0xe8, 0x3b, 0xb1, 0xf0, 0xad, 0xaf, 0x83, + 0x9e, 0xcb, 0x72, 0x90, 0x97, 0x39, 0xaf, 0xca, 0x4a, 0x63, 0x5d, 0xcf, 0xbc, 0x1a, 0xab, 0x85, + 0x56, 0x7f, 0x75, 0xe4, 0xd5, 0x9f, 0x0c, 0xbf, 0xfa, 0xef, 0xae, 0xf3, 0xe5, 0xdb, 0x5d, 0xe7, + 0xab, 0xb7, 0xbb, 0xce, 0x7f, 0xde, 0xee, 0xae, 0xfd, 0xe5, 0x7f, 0xbb, 0xce, 0x2f, 0x0f, 0x8c, + 0x5f, 0x95, 0x33, 0x4c, 0xb3, 0xf0, 0x26, 0xc9, 0xc2, 0x69, 0x18, 0x2b, 0x22, 0x26, 0x87, 0xe9, + 0x17, 0xd3, 0xc3, 0x74, 0x74, 0xc8, 0xc7, 0xc6, 0xa8, 0xc6, 0xff, 0x42, 0x3e, 0xfa, 0x7f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xbf, 0x90, 0x9c, 0xfb, 0xf7, 0x14, 0x00, 0x00, } func (m *ShardsMetadata) Marshal() (dAtA []byte, err error) { diff --git a/pkg/shardservice/service_read_test.go b/pkg/shardservice/service_read_test.go index b49ab612bc557..2df1df4584c50 100644 --- a/pkg/shardservice/service_read_test.go +++ b/pkg/shardservice/service_read_test.go @@ -16,6 +16,8 @@ package shardservice import ( "context" + "fmt" + "os" "sort" "sync/atomic" "testing" @@ -72,6 +74,80 @@ func TestValidateRemoteReadCompatibility(t *testing.T) { require.Error(t, s.validateRemoteReadCompatibility(t.Context(), unknown, binaryParam)) } +func TestNewReadRequestUsesVersionedMethodForBinaryParams(t *testing.T) { + s := &service{} + s.remote.pool = morpc.NewMessagePool( + func() *shard.Request { return &shard.Request{} }, + func() *shard.Response { return &shard.Response{} }, + ) + target := shard.TableShard{Replicas: []shard.ShardReplica{{CN: "target"}}} + + textReq := s.newReadRequest(target, ReadRows, shard.ReadParam{}, timestamp.Timestamp{}) + require.Equal(t, shard.Method_ShardRead, textReq.RPCMethod) + s.remote.pool.ReleaseRequest(textReq) + + binaryReq := s.newReadRequest( + target, + ReadRows, + shard.ReadParam{Process: pipeline.ProcessInfo{ + PrepareParams: pipeline.PrepareParamInfo{IsBin: []bool{true}}, + }}, + timestamp.Timestamp{}, + ) + require.Equal(t, shard.Method_ShardReadV2, binaryReq.RPCMethod) + s.remote.pool.ReleaseRequest(binaryReq) +} + +func TestOldReceiverRejectsVersionedShardReadBeforeHandler(t *testing.T) { + initTestCluster("cn1") + address := fmt.Sprintf("unix:///tmp/shard-read-v2-%d.sock", time.Now().UnixNano()) + require.NoError(t, os.RemoveAll(address[7:])) + + pool := morpc.NewMessagePool( + func() *shard.Request { return &shard.Request{} }, + func() *shard.Response { return &shard.Response{} }, + ) + server, err := morpc.NewMessageHandler( + sid, + "old-shard-service", + address, + morpc.Config{}, + pool, + ) + require.NoError(t, err) + var handlerCalls atomic.Int32 + server.RegisterMethod( + uint32(shard.Method_ShardRead), + func(context.Context, *shard.Request, *shard.Response, *morpc.Buffer) error { + handlerCalls.Add(1) + return nil + }, + false, + ) + require.NoError(t, server.Start()) + t.Cleanup(func() { require.NoError(t, server.Close()) }) + + client, err := morpc.NewMethodBasedClient( + sid, + "new-shard-client", + morpc.Config{ClientOptions: []morpc.ClientOption{morpc.WithClientEnableAutoCreateBackend()}}, + pool, + ) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, client.Close()) }) + client.RegisterMethod( + uint32(shard.Method_ShardReadV2), + func(*shard.Request) (string, error) { return address, nil }, + ) + + ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) + defer cancel() + _, err = client.Send(ctx, &shard.Request{RPCMethod: shard.Method_ShardReadV2}) + require.Error(t, err) + require.True(t, moerr.IsMoErrCode(err, moerr.ErrNotSupported)) + require.Zero(t, handlerCalls.Load()) +} + func TestReadValidatesAllRemoteShardsBeforeSending(t *testing.T) { runServicesTest( t, diff --git a/pkg/shardservice/service_remote.go b/pkg/shardservice/service_remote.go index 9305823e79e17..f2a8f1759e9ec 100644 --- a/pkg/shardservice/service_remote.go +++ b/pkg/shardservice/service_remote.go @@ -54,6 +54,11 @@ func (s *service) initRemote() { s.handleRemoteRead, true, ) + s.remote.server.RegisterMethod( + uint32(pb.Method_ShardReadV2), + s.handleRemoteRead, + true, + ) if err := s.remote.server.Start(); err != nil { panic(err) @@ -104,6 +109,12 @@ func (s *service) initRemoteClient() { return getCNAddress(r.ShardRead.CN, s.remote.cluster), nil }, ) + s.remote.client.RegisterMethod( + uint32(pb.Method_ShardReadV2), + func(r *pb.Request) (string, error) { + return getCNAddress(r.ShardRead.CN, s.remote.cluster), nil + }, + ) } func (s *service) handleRemoteRead( @@ -191,6 +202,9 @@ func (s *service) newReadRequest( ) *pb.Request { req := s.remote.pool.AcquireRequest() req.RPCMethod = pb.Method_ShardRead + if hasBinaryPrepareParam(param) { + req.RPCMethod = pb.Method_ShardReadV2 + } req.ShardRead.Shard = shard req.ShardRead.Method = uint32(method) req.ShardRead.Param = param diff --git a/proto/shard.proto b/proto/shard.proto index a4f82bb96c68f..8e4e44e404a7d 100644 --- a/proto/shard.proto +++ b/proto/shard.proto @@ -120,6 +120,7 @@ enum Method { ShardRead = 4; PauseCN = 5; GetCNReplicas = 6; + ShardReadV2 = 7; } message Request { From e0e549d7c9e8f4be306b802dd9869465ec5e7700 Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Tue, 21 Jul 2026 23:30:31 +0800 Subject: [PATCH 09/10] test: cover versioned shard read receivers --- pkg/shardservice/service_read_test.go | 56 +++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/pkg/shardservice/service_read_test.go b/pkg/shardservice/service_read_test.go index 2df1df4584c50..bf792768bd19b 100644 --- a/pkg/shardservice/service_read_test.go +++ b/pkg/shardservice/service_read_test.go @@ -148,6 +148,62 @@ func TestOldReceiverRejectsVersionedShardReadBeforeHandler(t *testing.T) { require.Zero(t, handlerCalls.Load()) } +func TestBinaryReadUsesVersionedRemoteHandler(t *testing.T) { + runServicesTest( + t, + "cn1,cn2", + func(ctx context.Context, _ *server, services []*service) { + s1 := services[0] + s2 := services[1] + table := uint64(1) + mustAddTestShards(t, ctx, s1, table, 2, 1, s2) + waitReplicaCount(table, s1, 1) + waitReplicaCount(table, s2, 1) + + var cns []metadata.CNService + s1.remote.cluster.GetCNServiceWithoutWorkingState( + clusterservice.NewSelector(), + func(cn metadata.CNService) bool { + cns = append(cns, cn) + return true + }, + ) + for _, cn := range cns { + cn.CommitID = version.CommitID + s1.remote.cluster.UpdateCN(cn) + } + + key := []byte("key") + value := []byte("value") + store := s2.storage.(*MemShardStorage) + store.set(key, value, newTestTimestamp(1)) + store.waiter.NotifyLatestCommitTS(newTestTimestamp(2)) + remoteShard := s2.getAllocatedShards()[0].ShardID + applied := false + err := s1.Read( + ctx, + ReadRequest{ + TableID: table, + Param: shard.ReadParam{ + KeyParam: shard.KeyParam{Key: key}, + Process: pipeline.ProcessInfo{ + PrepareParams: pipeline.PrepareParamInfo{IsBin: []bool{true}}, + }, + }, + Apply: func(actual []byte) { + applied = true + require.Equal(t, value, actual) + }, + }, + DefaultOptions.ReadAt(newTestTimestamp(2)).Shard(remoteShard), + ) + require.NoError(t, err) + require.True(t, applied) + }, + nil, + ) +} + func TestReadValidatesAllRemoteShardsBeforeSending(t *testing.T) { runServicesTest( t, From daed24135d5818a5842faa06b5b705dd7090d253 Mon Sep 17 00:00:00 2001 From: Cao Kai Date: Wed, 22 Jul 2026 11:23:25 +0800 Subject: [PATCH 10/10] fix: cancel rejected method RPC contexts --- pkg/common/morpc/method_based.go | 1 + pkg/common/morpc/method_based_test.go | 89 +++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/pkg/common/morpc/method_based.go b/pkg/common/morpc/method_based.go index eae1052f42654..b5c7bdd96b058 100644 --- a/pkg/common/morpc/method_based.go +++ b/pkg/common/morpc/method_based.go @@ -194,6 +194,7 @@ func (s *methodBasedServer[REQ, RESP]) onMessage( resp := s.pool.AcquireResponse() handlerCtx, ok := s.getHandleFunc(ctx, req, resp) if !ok { + defer request.Cancel() s.pool.ReleaseRequest(req) return cs.Write(ctx, resp) } diff --git a/pkg/common/morpc/method_based_test.go b/pkg/common/morpc/method_based_test.go index 632ef7fa3ae46..0b790d7565f2c 100644 --- a/pkg/common/morpc/method_based_test.go +++ b/pkg/common/morpc/method_based_test.go @@ -17,6 +17,7 @@ package morpc import ( "context" "fmt" + "io" "os" "testing" "time" @@ -29,6 +30,94 @@ import ( "github.com/stretchr/testify/require" ) +type testMethodBasedClientSession struct { + write func(context.Context, Message) error +} + +func (s *testMethodBasedClientSession) Close() error { + return nil +} + +func (s *testMethodBasedClientSession) SessionCtx() context.Context { + return context.Background() +} + +func (s *testMethodBasedClientSession) Write(ctx context.Context, message Message) error { + return s.write(ctx, message) +} + +func (s *testMethodBasedClientSession) AsyncWrite(Message) error { + panic("not implemented") +} + +func (s *testMethodBasedClientSession) CreateCache(context.Context, uint64) (MessageCache, error) { + panic("not implemented") +} + +func (s *testMethodBasedClientSession) DeleteCache(uint64) { + panic("not implemented") +} + +func (s *testMethodBasedClientSession) GetCache(uint64) (MessageCache, error) { + panic("not implemented") +} + +func (s *testMethodBasedClientSession) RemoteAddress() string { + return "" +} + +func TestMethodBasedServerCancelsRejectedRequest(t *testing.T) { + writeErr := io.ErrClosedPipe + for _, tc := range []struct { + name string + writeErr error + }{ + {name: "write succeeds"}, + {name: "write fails", writeErr: writeErr}, + } { + t.Run(tc.name, func(t *testing.T) { + pool := NewMessagePool( + func() *testMethodBasedMessage { return &testMethodBasedMessage{} }, + func() *testMethodBasedMessage { return &testMethodBasedMessage{} }, + ) + s := &methodBasedServer[*testMethodBasedMessage, *testMethodBasedMessage]{ + logger: getLogger(""), + pool: pool, + handlers: make(map[uint32]handleFuncCtx[*testMethodBasedMessage, *testMethodBasedMessage]), + } + + cancelCalls := 0 + writeCalls := 0 + cs := &testMethodBasedClientSession{ + write: func(_ context.Context, message Message) error { + writeCalls++ + require.Zero(t, cancelCalls) + require.True(t, moerr.IsMoErrCode( + message.(*testMethodBasedMessage).UnwrapError(), + moerr.ErrNotSupported, + )) + return tc.writeErr + }, + } + request := RPCMessage{ + Message: &testMethodBasedMessage{method: 100}, + Cancel: func() { + cancelCalls++ + }, + } + + err := s.onMessage(t.Context(), request, 0, cs) + if tc.writeErr == nil { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.writeErr) + } + require.Equal(t, 1, writeCalls) + require.Equal(t, 1, cancelCalls) + }) + } +} + func TestRPCSend(t *testing.T) { runRPCTests( t,