diff --git a/vendor/github.com/StackExchange/wmi/LICENSE b/vendor/github.com/StackExchange/wmi/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..ae80b67209e2a745b9cc950d15503c6ec1178485 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Stack Exchange + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/StackExchange/wmi/README.md b/vendor/github.com/StackExchange/wmi/README.md new file mode 100644 index 0000000000000000000000000000000000000000..426d1a46b4aa93b44023409fdd5838270a67406f --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/README.md @@ -0,0 +1,6 @@ +wmi +=== + +Package wmi provides a WQL interface to Windows WMI. + +Note: It interfaces with WMI on the local machine, therefore it only runs on Windows. diff --git a/vendor/github.com/StackExchange/wmi/swbemservices.go b/vendor/github.com/StackExchange/wmi/swbemservices.go new file mode 100644 index 0000000000000000000000000000000000000000..3ff8756303784b8c1a8d4c7c8be1bbec977d69cb --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/swbemservices.go @@ -0,0 +1,260 @@ +// +build windows + +package wmi + +import ( + "fmt" + "reflect" + "runtime" + "sync" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +// SWbemServices is used to access wmi. See https://msdn.microsoft.com/en-us/library/aa393719(v=vs.85).aspx +type SWbemServices struct { + //TODO: track namespace. Not sure if we can re connect to a different namespace using the same instance + cWMIClient *Client //This could also be an embedded struct, but then we would need to branch on Client vs SWbemServices in the Query method + sWbemLocatorIUnknown *ole.IUnknown + sWbemLocatorIDispatch *ole.IDispatch + queries chan *queryRequest + closeError chan error + lQueryorClose sync.Mutex +} + +type queryRequest struct { + query string + dst interface{} + args []interface{} + finished chan error +} + +// InitializeSWbemServices will return a new SWbemServices object that can be used to query WMI +func InitializeSWbemServices(c *Client, connectServerArgs ...interface{}) (*SWbemServices, error) { + //fmt.Println("InitializeSWbemServices: Starting") + //TODO: implement connectServerArgs as optional argument for init with connectServer call + s := new(SWbemServices) + s.cWMIClient = c + s.queries = make(chan *queryRequest) + initError := make(chan error) + go s.process(initError) + + err, ok := <-initError + if ok { + return nil, err //Send error to caller + } + //fmt.Println("InitializeSWbemServices: Finished") + return s, nil +} + +// Close will clear and release all of the SWbemServices resources +func (s *SWbemServices) Close() error { + s.lQueryorClose.Lock() + if s == nil || s.sWbemLocatorIDispatch == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices is not Initialized") + } + if s.queries == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices has been closed") + } + //fmt.Println("Close: sending close request") + var result error + ce := make(chan error) + s.closeError = ce //Race condition if multiple callers to close. May need to lock here + close(s.queries) //Tell background to shut things down + s.lQueryorClose.Unlock() + err, ok := <-ce + if ok { + result = err + } + //fmt.Println("Close: finished") + return result +} + +func (s *SWbemServices) process(initError chan error) { + //fmt.Println("process: starting background thread initialization") + //All OLE/WMI calls must happen on the same initialized thead, so lock this goroutine + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { + initError <- fmt.Errorf("ole.CoInitializeEx error: %v", err) + return + } + } + defer ole.CoUninitialize() + + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + initError <- fmt.Errorf("CreateObject SWbemLocator error: %v", err) + return + } else if unknown == nil { + initError <- ErrNilCreateObject + return + } + defer unknown.Release() + s.sWbemLocatorIUnknown = unknown + + dispatch, err := s.sWbemLocatorIUnknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + initError <- fmt.Errorf("SWbemLocator QueryInterface error: %v", err) + return + } + defer dispatch.Release() + s.sWbemLocatorIDispatch = dispatch + + // we can't do the ConnectServer call outside the loop unless we find a way to track and re-init the connectServerArgs + //fmt.Println("process: initialized. closing initError") + close(initError) + //fmt.Println("process: waiting for queries") + for q := range s.queries { + //fmt.Printf("process: new query: len(query)=%d\n", len(q.query)) + errQuery := s.queryBackground(q) + //fmt.Println("process: s.queryBackground finished") + if errQuery != nil { + q.finished <- errQuery + } + close(q.finished) + } + //fmt.Println("process: queries channel closed") + s.queries = nil //set channel to nil so we know it is closed + //TODO: I think the Release/Clear calls can panic if things are in a bad state. + //TODO: May need to recover from panics and send error to method caller instead. + close(s.closeError) +} + +// Query runs the WQL query using a SWbemServices instance and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + s.lQueryorClose.Lock() + if s == nil || s.sWbemLocatorIDispatch == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices is not Initialized") + } + if s.queries == nil { + s.lQueryorClose.Unlock() + return fmt.Errorf("SWbemServices has been closed") + } + + //fmt.Println("Query: Sending query request") + qr := queryRequest{ + query: query, + dst: dst, + args: connectServerArgs, + finished: make(chan error), + } + s.queries <- &qr + s.lQueryorClose.Unlock() + err, ok := <-qr.finished + if ok { + //fmt.Println("Query: Finished with error") + return err //Send error to caller + } + //fmt.Println("Query: Finished") + return nil +} + +func (s *SWbemServices) queryBackground(q *queryRequest) error { + if s == nil || s.sWbemLocatorIDispatch == nil { + return fmt.Errorf("SWbemServices is not Initialized") + } + wmi := s.sWbemLocatorIDispatch //Should just rename in the code, but this will help as we break things apart + //fmt.Println("queryBackground: Starting") + + dv := reflect.ValueOf(q.dst) + if dv.Kind() != reflect.Ptr || dv.IsNil() { + return ErrInvalidEntityType + } + dv = dv.Elem() + mat, elemType := checkMultiArg(dv) + if mat == multiArgTypeInvalid { + return ErrInvalidEntityType + } + + // service is a SWbemServices + serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", q.args...) + if err != nil { + return err + } + service := serviceRaw.ToIDispatch() + defer serviceRaw.Clear() + + // result is a SWBemObjectSet + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", q.query) + if err != nil { + return err + } + result := resultRaw.ToIDispatch() + defer resultRaw.Clear() + + count, err := oleInt64(result, "Count") + if err != nil { + return err + } + + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + defer enum.Release() + + // Initialize a slice with Count capacity + dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) + + var errFieldMismatch error + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + + err := func() error { + // item is a SWbemObject, but really a Win32_Process + item := itemRaw.ToIDispatch() + defer item.Release() + + ev := reflect.New(elemType) + if err = s.cWMIClient.loadEntity(ev.Interface(), item); err != nil { + if _, ok := err.(*ErrFieldMismatch); ok { + // We continue loading entities even in the face of field mismatch errors. + // If we encounter any other error, that other error is returned. Otherwise, + // an ErrFieldMismatch is returned. + errFieldMismatch = err + } else { + return err + } + } + if mat != multiArgTypeStructPtr { + ev = ev.Elem() + } + dv.Set(reflect.Append(dv, ev)) + return nil + }() + if err != nil { + return err + } + } + //fmt.Println("queryBackground: Finished") + return errFieldMismatch +} diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go new file mode 100644 index 0000000000000000000000000000000000000000..f32fb200b133acd696ea27bf83cfef3e880bfff3 --- /dev/null +++ b/vendor/github.com/StackExchange/wmi/wmi.go @@ -0,0 +1,490 @@ +// +build windows + +/* +Package wmi provides a WQL interface for WMI on Windows. + +Example code to print names of running processes: + + type Win32_Process struct { + Name string + } + + func main() { + var dst []Win32_Process + q := wmi.CreateQuery(&dst, "") + err := wmi.Query(q, &dst) + if err != nil { + log.Fatal(err) + } + for i, v := range dst { + println(i, v.Name) + } + } + +*/ +package wmi + +import ( + "bytes" + "errors" + "fmt" + "log" + "os" + "reflect" + "runtime" + "strconv" + "strings" + "sync" + "time" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" +) + +var l = log.New(os.Stdout, "", log.LstdFlags) + +var ( + ErrInvalidEntityType = errors.New("wmi: invalid entity type") + // ErrNilCreateObject is the error returned if CreateObject returns nil even + // if the error was nil. + ErrNilCreateObject = errors.New("wmi: create object returned nil") + lock sync.Mutex +) + +// S_FALSE is returned by CoInitializeEx if it was already called on this thread. +const S_FALSE = 0x00000001 + +// QueryNamespace invokes Query with the given namespace on the local machine. +func QueryNamespace(query string, dst interface{}, namespace string) error { + return Query(query, dst, nil, namespace) +} + +// Query runs the WQL query and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +// +// Query is a wrapper around DefaultClient.Query. +func Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + if DefaultClient.SWbemServicesClient == nil { + return DefaultClient.Query(query, dst, connectServerArgs...) + } + return DefaultClient.SWbemServicesClient.Query(query, dst, connectServerArgs...) +} + +// A Client is an WMI query client. +// +// Its zero value (DefaultClient) is a usable client. +type Client struct { + // NonePtrZero specifies if nil values for fields which aren't pointers + // should be returned as the field types zero value. + // + // Setting this to true allows stucts without pointer fields to be used + // without the risk failure should a nil value returned from WMI. + NonePtrZero bool + + // PtrNil specifies if nil values for pointer fields should be returned + // as nil. + // + // Setting this to true will set pointer fields to nil where WMI + // returned nil, otherwise the types zero value will be returned. + PtrNil bool + + // AllowMissingFields specifies that struct fields not present in the + // query result should not result in an error. + // + // Setting this to true allows custom queries to be used with full + // struct definitions instead of having to define multiple structs. + AllowMissingFields bool + + // SWbemServiceClient is an optional SWbemServices object that can be + // initialized and then reused across multiple queries. If it is null + // then the method will initialize a new temporary client each time. + SWbemServicesClient *SWbemServices +} + +// DefaultClient is the default Client and is used by Query, QueryNamespace +var DefaultClient = &Client{} + +// Query runs the WQL query and appends the values to dst. +// +// dst must have type *[]S or *[]*S, for some struct type S. Fields selected in +// the query must have the same name in dst. Supported types are all signed and +// unsigned integers, time.Time, string, bool, or a pointer to one of those. +// Array types are not supported. +// +// By default, the local machine and default namespace are used. These can be +// changed using connectServerArgs. See +// http://msdn.microsoft.com/en-us/library/aa393720.aspx for details. +func (c *Client) Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + dv := reflect.ValueOf(dst) + if dv.Kind() != reflect.Ptr || dv.IsNil() { + return ErrInvalidEntityType + } + dv = dv.Elem() + mat, elemType := checkMultiArg(dv) + if mat == multiArgTypeInvalid { + return ErrInvalidEntityType + } + + lock.Lock() + defer lock.Unlock() + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { + return err + } + } + defer ole.CoUninitialize() + + unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + return err + } else if unknown == nil { + return ErrNilCreateObject + } + defer unknown.Release() + + wmi, err := unknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + return err + } + defer wmi.Release() + + // service is a SWbemServices + serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer", connectServerArgs...) + if err != nil { + return err + } + service := serviceRaw.ToIDispatch() + defer serviceRaw.Clear() + + // result is a SWBemObjectSet + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", query) + if err != nil { + return err + } + result := resultRaw.ToIDispatch() + defer resultRaw.Clear() + + count, err := oleInt64(result, "Count") + if err != nil { + return err + } + + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + defer enum.Release() + + // Initialize a slice with Count capacity + dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) + + var errFieldMismatch error + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + + err := func() error { + // item is a SWbemObject, but really a Win32_Process + item := itemRaw.ToIDispatch() + defer item.Release() + + ev := reflect.New(elemType) + if err = c.loadEntity(ev.Interface(), item); err != nil { + if _, ok := err.(*ErrFieldMismatch); ok { + // We continue loading entities even in the face of field mismatch errors. + // If we encounter any other error, that other error is returned. Otherwise, + // an ErrFieldMismatch is returned. + errFieldMismatch = err + } else { + return err + } + } + if mat != multiArgTypeStructPtr { + ev = ev.Elem() + } + dv.Set(reflect.Append(dv, ev)) + return nil + }() + if err != nil { + return err + } + } + return errFieldMismatch +} + +// ErrFieldMismatch is returned when a field is to be loaded into a different +// type than the one it was stored from, or when a field is missing or +// unexported in the destination struct. +// StructType is the type of the struct pointed to by the destination argument. +type ErrFieldMismatch struct { + StructType reflect.Type + FieldName string + Reason string +} + +func (e *ErrFieldMismatch) Error() string { + return fmt.Sprintf("wmi: cannot load field %q into a %q: %s", + e.FieldName, e.StructType, e.Reason) +} + +var timeType = reflect.TypeOf(time.Time{}) + +// loadEntity loads a SWbemObject into a struct pointer. +func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) { + v := reflect.ValueOf(dst).Elem() + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + of := f + isPtr := f.Kind() == reflect.Ptr + if isPtr { + ptr := reflect.New(f.Type().Elem()) + f.Set(ptr) + f = f.Elem() + } + n := v.Type().Field(i).Name + if !f.CanSet() { + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "CanSet() is false", + } + } + prop, err := oleutil.GetProperty(src, n) + if err != nil { + if !c.AllowMissingFields { + errFieldMismatch = &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "no such struct field", + } + } + continue + } + defer prop.Clear() + + if prop.Value() == nil { + continue + } + + switch val := prop.Value().(type) { + case int8, int16, int32, int64, int: + v := reflect.ValueOf(val).Int() + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + f.SetInt(v) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.SetUint(uint64(v)) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not an integer class", + } + } + case uint8, uint16, uint32, uint64: + v := reflect.ValueOf(val).Uint() + switch f.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + f.SetInt(int64(v)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.SetUint(v) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not an integer class", + } + } + case string: + switch f.Kind() { + case reflect.String: + f.SetString(val) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + iv, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return err + } + f.SetInt(iv) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uv, err := strconv.ParseUint(val, 10, 64) + if err != nil { + return err + } + f.SetUint(uv) + case reflect.Struct: + switch f.Type() { + case timeType: + if len(val) == 25 { + mins, err := strconv.Atoi(val[22:]) + if err != nil { + return err + } + val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60) + } + t, err := time.Parse("20060102150405.000000-0700", val) + if err != nil { + return err + } + f.Set(reflect.ValueOf(t)) + } + } + case bool: + switch f.Kind() { + case reflect.Bool: + f.SetBool(val) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not a bool", + } + } + case float32: + switch f.Kind() { + case reflect.Float32: + f.SetFloat(float64(val)) + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: "not a Float32", + } + } + default: + if f.Kind() == reflect.Slice { + switch f.Type().Elem().Kind() { + case reflect.String: + safeArray := prop.ToArray() + if safeArray != nil { + arr := safeArray.ToValueArray() + fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) + for i, v := range arr { + s := fArr.Index(i) + s.SetString(v.(string)) + } + f.Set(fArr) + } + case reflect.Uint8: + safeArray := prop.ToArray() + if safeArray != nil { + arr := safeArray.ToValueArray() + fArr := reflect.MakeSlice(f.Type(), len(arr), len(arr)) + for i, v := range arr { + s := fArr.Index(i) + s.SetUint(reflect.ValueOf(v).Uint()) + } + f.Set(fArr) + } + default: + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: fmt.Sprintf("unsupported slice type (%T)", val), + } + } + } else { + typeof := reflect.TypeOf(val) + if typeof == nil && (isPtr || c.NonePtrZero) { + if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) { + of.Set(reflect.Zero(of.Type())) + } + break + } + return &ErrFieldMismatch{ + StructType: of.Type(), + FieldName: n, + Reason: fmt.Sprintf("unsupported type (%T)", val), + } + } + } + } + return errFieldMismatch +} + +type multiArgType int + +const ( + multiArgTypeInvalid multiArgType = iota + multiArgTypeStruct + multiArgTypeStructPtr +) + +// checkMultiArg checks that v has type []S, []*S for some struct type S. +// +// It returns what category the slice's elements are, and the reflect.Type +// that represents S. +func checkMultiArg(v reflect.Value) (m multiArgType, elemType reflect.Type) { + if v.Kind() != reflect.Slice { + return multiArgTypeInvalid, nil + } + elemType = v.Type().Elem() + switch elemType.Kind() { + case reflect.Struct: + return multiArgTypeStruct, elemType + case reflect.Ptr: + elemType = elemType.Elem() + if elemType.Kind() == reflect.Struct { + return multiArgTypeStructPtr, elemType + } + } + return multiArgTypeInvalid, nil +} + +func oleInt64(item *ole.IDispatch, prop string) (int64, error) { + v, err := oleutil.GetProperty(item, prop) + if err != nil { + return 0, err + } + defer v.Clear() + + i := int64(v.Val) + return i, nil +} + +// CreateQuery returns a WQL query string that queries all columns of src. where +// is an optional string that is appended to the query, to be used with WHERE +// clauses. In such a case, the "WHERE" string should appear at the beginning. +func CreateQuery(src interface{}, where string) string { + var b bytes.Buffer + b.WriteString("SELECT ") + s := reflect.Indirect(reflect.ValueOf(src)) + t := s.Type() + if s.Kind() == reflect.Slice { + t = t.Elem() + } + if t.Kind() != reflect.Struct { + return "" + } + var fields []string + for i := 0; i < t.NumField(); i++ { + fields = append(fields, t.Field(i).Name) + } + b.WriteString(strings.Join(fields, ", ")) + b.WriteString(" FROM ") + b.WriteString(t.Name()) + b.WriteString(" " + where) + return b.String() +} diff --git a/vendor/github.com/XiaoMi/soar/CHANGES.md b/vendor/github.com/XiaoMi/soar/CHANGES.md new file mode 100644 index 0000000000000000000000000000000000000000..b2ca8181cdca11bb0bcbdf031e343d7ab8dd3e5a --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/CHANGES.md @@ -0,0 +1,82 @@ +# CHANGELOG + +## 2018-11 +- DOING: english translation +- add -cleanup-test-database command-line arg +- fix -config arg load file error +- fix #87 RuleImplicitConversion value type mistach check bug +- fix #38 always true where condition check +- abandon stdin terminal interactive mod, which may seems like hangup + +## 2018-10 +- Fix SplitStatement mulitstatement eof bug #66 +- Fix pretty func hangup issue #47 +- Fix some foolish code spell error +- Use travis for CI +- Fix Go 1.8 defapth GOPATH compatible issue BUG #5 +- 2018-10-20 开源先锋日(OSCAR)对外正式开源发布代码 + +## 2018-09 +- 修复多个启发式建议不准确BUG,优化部分建议文案使得建议更清晰 +- 基于TiDB Parser完善多个DDL类型语句的建议 +- 新增lint report-type类型,支持Vim Plugin优化建议输出 +- 更新整理项目文档,开源准备 +- 2018-09-21 Gdevops SOAR首次对外进行技术分享宣传 + +## 2018-08 +- 利用docker临时容器进行daily测试 +- 添加main_test全功能回归测试 +- 修复在测试中发现的问题 +- mymysql合并MySQL8.0相关PR,修改vendor依赖 +- 改善HeuristicRule中的文案 +- 持续集成Vitess Parser的改进 +- NewQuery4Audit结构体中引入TiDB Parser +- 通过TiAST完成大量与 DDL 相关的TODO +- 修改heuristic rules检查的返回值,提升拓展性 +- 建议中引入Position,用于表示建议产生于SQL的位置 +- 新增多个HeuristicRule +- Makefile中添加依赖检查,优化Makefile中逻辑,添加新功能 +- 优化gometalinter性能,引入新的代码质量检测工具,提升代码质量 +- 引入 retool 用于管理依赖的工具 +- 优化 doc 文档 + +## 2018-07 +- 补充文档,添加项目LOGO +- 改善代码质量提升测试覆盖度 +- mymysql升级,支持MySQL 8.0 +- 提供remove-comment小工具 +- 提供索引重复检查小工具 +- HeuristicRule新增RuleSpaceAfterDot +- 支持字符集和Collation不相同时的隐式数据类型转换的检查 + +## 2018-06 +- 支持更多的SQL Rewrite规则 +- 添加SQL执行超时限制 +- 索引优化建议支持对约束的检查 +- 修复数据采样中null值处理不正确的问题 +- Explain支持last_query_cost + +## 2018-05 +- 添加数据采样功能 +- 添加语句执行安全检查 +- 支持DDL语法检查 +- 支持DDL在测试环境的执行 +- 支持隐式数据类型转换检查 +- 支持索引去重 +- 索引优化建议支持前缀索引 +- 支持SQL Pretty输出 + +## 2018-04 +- 支持语法检查 +- 支持测试环境 +- 支持MySQL原数据的获取 +- 支持基于数据库环境信息给予索引优化建议 +- 支持不依赖数据库原信息的简单索引优化建议 +- 添加日志模块 +- 引入配置文件 + +## 2018-03 +- 基本架构设计 +- 添加大量底层函数用于处理AST +- 添加Insert、Delete、Update转写成Select的基本函数 +- 支持MySQL Explain信息输出 diff --git a/vendor/github.com/XiaoMi/soar/CODE_OF_CONDUCT.md b/vendor/github.com/XiaoMi/soar/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000000000000000000000000000000..220407cb82b4687529ea465e7162acbabf94f025 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at zhangliang3@xiaomi.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/XiaoMi/soar/CONTRIBUTING.md b/vendor/github.com/XiaoMi/soar/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..0346f4eb778bb6d91465d2282cf20b054d6386b9 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/CONTRIBUTING.md @@ -0,0 +1,3 @@ +Ask questions at [Gitter](https://gitter.im/xiaomi-dba/soar). + +[Open an issue](https://github.com/xiaomi/soar/issues/new) to discuss your plans before doing any work on SOAR. diff --git a/vendor/github.com/XiaoMi/soar/LICENSE b/vendor/github.com/XiaoMi/soar/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/XiaoMi/soar/Makefile b/vendor/github.com/XiaoMi/soar/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a89aabca1524d5646db4adfce80fdbc1f200d16b --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/Makefile @@ -0,0 +1,221 @@ +# This how we want to name the binary output +# +# use checkmake linter https://github.com/mrtazz/checkmake +# $ checkmake Makefile +# +BINARY=soar +GOPATH ?= $(shell go env GOPATH) +# Ensure GOPATH is set before running build process. +ifeq "$(GOPATH)" "" + $(error Please set the environment variable GOPATH before running `make`) +endif +PATH := ${GOPATH}/bin:$(PATH) +GCFLAGS=-gcflags "all=-trimpath=${GOPATH}" +LDFLAGS=-ldflags="-s -w" + +# These are the values we want to pass for VERSION and BUILD +BUILD_TIME=`date +%Y%m%d%H%M` +COMMIT_VERSION=`git rev-parse HEAD` + +# Add mysql version for testing `MYSQL_RELEASE=percona MYSQL_VERSION=5.7 make docker` +# MYSQL_RELEASE: mysql, percona, mariadb ... +# MYSQL_VERSION: latest, 8.0, 5.7, 5.6, 5.5 ... +# use mysql:latest as default +MYSQL_RELEASE := $(or ${MYSQL_RELEASE}, ${MYSQL_RELEASE}, mysql) +MYSQL_VERSION := $(or ${MYSQL_VERSION}, ${MYSQL_VERSION}, latest) + +.PHONY: all +all: | fmt build + +.PHONY: go_version_check +GO_VERSION_MIN=1.10 +# Parse out the x.y or x.y.z version and output a single value x*10000+y*100+z (e.g., 1.9 is 10900) +# that allows the three components to be checked in a single comparison. +VER_TO_INT:=awk '{split(substr($$0, match ($$0, /[0-9\.]+/)), a, "."); print a[1]*10000+a[2]*100+a[3]}' +go_version_check: + @echo "\033[92mGo version check\033[0m" + @if test $(shell go version | $(VER_TO_INT) ) -lt \ + $(shell echo "$(GO_VERSION_MIN)" | $(VER_TO_INT)); \ + then printf "go version $(GO_VERSION_MIN)+ required, found: "; go version; exit 1; \ + else echo "go version check pass"; fi + +# Dependency check +.PHONY: deps +deps: + @echo "\033[92mDependency check\033[0m" + @bash ./deps.sh + # The retool tools.json is setup from retool-install.sh + retool sync + retool do gometalinter.v2 intall + +# Code format +.PHONY: fmt +fmt: go_version_check + @echo "\033[92mRun gofmt on all source files ...\033[0m" + @echo "gofmt -l -s -w ..." + @ret=0 && for d in $$(go list -f '{{.Dir}}' ./... | grep -v /vendor/); do \ + gofmt -l -s -w $$d/*.go || ret=$$? ; \ + done ; exit $$ret + +# Run golang test cases +.PHONY: test +test: + @echo "\033[92mRun all test cases ...\033[0m" + go test ./... + @echo "test Success!" + +# Code Coverage +# colorful coverage numerical >=90% GREEN, <80% RED, Other YELLOW +.PHONY: cover +cover: test + @echo "\033[92mRun test cover check ...\033[0m" + go test -coverpkg=./... -coverprofile=coverage.data ./... | column -t + go tool cover -html=coverage.data -o coverage.html + go tool cover -func=coverage.data -o coverage.txt + @tail -n 1 coverage.txt | awk '{sub(/%/, "", $$NF); \ + if($$NF < 80) \ + {print "\033[91m"$$0"%\033[0m"} \ + else if ($$NF >= 90) \ + {print "\033[92m"$$0"%\033[0m"} \ + else \ + {print "\033[93m"$$0"%\033[0m"}}' + +# Builds the project +build: fmt + @echo "\033[92mBuilding ...\033[0m" + @mkdir -p bin + @bash ./genver.sh + @ret=0 && for d in $$(go list -f '{{if (eq .Name "main")}}{{.ImportPath}}{{end}}' ./...); do \ + b=$$(basename $${d}) ; \ + go build ${GCFLAGS} -o bin/$${b} $$d || ret=$$? ; \ + done ; exit $$ret + @echo "build Success!" + +# Installs our project: copies binaries +install: build + @echo "\033[92mInstall ...\033[0m" + go install ./... + @echo "install Success!" + +# Generate doc use -list* command +.PHONY: doc +doc: build + @echo "\033[92mAuto generate doc ...\033[0m" + ./bin/soar -list-heuristic-rules > doc/heuristic.md + ./bin/soar -list-rewrite-rules > doc/rewrite.md + ./bin/soar -list-report-types > doc/report_type.md + +# Add or change a heuristic rule +.PHONY: heuristic +heuristic: doc docker + @echo "\033[92mUpdate Heuristic rule golden files ...\033[0m" + go test github.com/XiaoMi/soar/advisor -v -update -run TestListHeuristicRules + go test github.com/XiaoMi/soar/advisor -v -update -run TestMergeConflictHeuristicRules + docker stop soar-mysql 2>/dev/null || true + +# Update vitess vendor +.PHONY: vitess +vitess: + @echo "\033[92mUpdate vitess deps ...\033[0m" + govendor fetch -v vitess.io/vitess/... + +# Update tidb vendor +.PHONY: tidb +tidb: + @echo "\033[92mUpdate tidb deps ...\033[0m" + govendor fetch -v github.com/pingcap/tidb/... + +# make pingcap parser +.PHONY: pingcap-parser +pingcap-parser: tidb + @echo "\033[92mimporting pingcap parser ...\033[0m" + govendor fetch -v github.com/pingcap/parser/... + +# Update all vendor +.PHONY: vendor +vendor: vitess pingcap-parser +# gometalinter +# 如果有不想改的lint问题可以使用metalinter.sh加黑名单 +#@bash doc/example/metalinter.sh +.PHONY: lint +lint: build + @echo "\033[92mRun linter check ...\033[0m" + CGO_ENABLED=0 retool do gometalinter.v2 -j 1 --config doc/example/metalinter.json ./... + retool do revive -formatter friendly --exclude vendor/... -config doc/example/revive.toml ./... + retool do golangci-lint --tests=false run + @echo "gometalinter check your code is pretty good" + +.PHONY: release +release: deps build + @echo "\033[92mCross platform building for release ...\033[0m" + @mkdir -p release + @for GOOS in darwin linux windows; do \ + for GOARCH in amd64; do \ + for d in $$(go list -f '{{if (eq .Name "main")}}{{.ImportPath}}{{end}}' ./...); do \ + b=$$(basename $${d}) ; \ + echo "Building $${b}.$${GOOS}-$${GOARCH} ..."; \ + GOOS=$${GOOS} GOARCH=$${GOARCH} go build ${GCFLAGS} ${LDFLAGS} -v -o release/$${b}.$${GOOS}-$${GOARCH} $$d 2>/dev/null ; \ + done ; \ + done ;\ + done + +.PHONY: docker +docker: + @echo "\033[92mBuild mysql test enviorment\033[0m" + @docker stop soar-mysql 2>/dev/null || true + @echo "docker run --name soar-mysql $(MYSQL_RELEASE):$(MYSQL_VERSION)" + @docker run --name soar-mysql --rm -d \ + -e MYSQL_ROOT_PASSWORD=1tIsB1g3rt \ + -e MYSQL_DATABASE=sakila \ + -p 3306:3306 \ + -v `pwd`/doc/example/sakila.sql.gz:/docker-entrypoint-initdb.d/sakila.sql.gz \ + $(MYSQL_RELEASE):$(MYSQL_VERSION) + + @echo -n "waiting for sakila database initializing " + @while ! mysql -h 127.0.0.1 -u root sakila -p1tIsB1g3rt -NBe "do 1;" 2>/dev/null; do \ + printf '.' ; \ + sleep 1 ; \ + done ; \ + echo '.' + @echo "mysql test enviorment is ready!" + +.PHONY: connect +connect: + mysql -h 127.0.0.1 -u root -p1tIsB1g3rt -c + +.PHONY: main_test +main_test: install + @echo "\033[92mrunning main_test\033[0m" + @echo "soar -list-test-sqls | soar" + @./doc/example/main_test.sh + @echo "main_test Success!" + +.PHONY: daily +daily: | deps fmt vendor docker cover doc lint release install main_test clean logo + @echo "\033[92mdaily build finished\033[0m" + +# vendor, docker will cost long time, if all those are ready, daily-quick will much more fast. +.PHONY: daily-quick +daily-quick: | deps fmt cover doc lint logo + @echo "\033[92mdaily-quick build finished\033[0m" + +.PHONY: logo +logo: + @echo "\033[93m" + @cat doc/images/logo.ascii + @echo "\033[m" + +# Cleans our projects: deletes binaries +.PHONY: clean +clean: + @echo "\033[92mCleanup ...\033[0m" + go clean + @for GOOS in darwin linux windows; do \ + for GOARCH in 386 amd64; do \ + rm -f ${BINARY}.$${GOOS}-$${GOARCH} ;\ + done ;\ + done + rm -f ${BINARY} coverage.* + find . -name "*.log" -delete + git clean -fi + docker stop soar-mysql 2>/dev/null || true diff --git a/vendor/github.com/XiaoMi/soar/NOTICE.txt b/vendor/github.com/XiaoMi/soar/NOTICE.txt new file mode 100644 index 0000000000000000000000000000000000000000..84fbfb3af4f676a661480834208e30f71f0e2ce7 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/NOTICE.txt @@ -0,0 +1,8 @@ + +Copyright 2018 Xiaomi, Inc. All Rights Reserved. +This product includes software developed by Xiaomi, Inc. +(http://www.mi.com/). +This product is licensed to you under the Apache License, Version 2.0 +(the "License"). You may not use this product except in compliance with +the License. + diff --git a/vendor/github.com/XiaoMi/soar/README.md b/vendor/github.com/XiaoMi/soar/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5f23326544c7374043dc8fab3ecac5e34f8a31c3 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/README.md @@ -0,0 +1,45 @@ +# ![SOAR](https://raw.githubusercontent.com/XiaoMi/soar/master/doc/images/logo.png) + +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/xiaomi-dba/soar) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://github.com/XiaoMi/soar/blob/master/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/XiaoMi/soar)](https://goreportcard.com/report/github.com/XiaoMi/soar) +[![Build Status](https://travis-ci.org/XiaoMi/soar.svg?branch=master)](https://travis-ci.org/XiaoMi/soar) +[![GoDoc](https://godoc.org/github.com/XiaoMi/soar?status.svg)](https://godoc.org/github.com/XiaoMi/soar) + +[文档](http://github.com/XiaoMi/soar/tree/master/doc) | [FAQ](http://github.com/XiaoMi/soar/blob/master/doc/FAQ.md) | [变更记录](http://github.com/XiaoMi/soar/blob/master/CHANGES.md) | [路线图](http://github.com/XiaoMi/soar/blob/master/doc/roadmap.md) | [English](http://github.com/XiaoMi/soar/blob/master/README_EN.md) + +## SOAR + +SOAR(SQL Optimizer And Rewriter)是一个对SQL进行优化和改写的自动化工具。 由小米人工智能与云平台的数据库团队开发与维护。 + +## 功能特点 + +* 跨平台支持(支持Linux, Mac环境,Windows环境理论上也支持,不过未全面测试) +* 目前只支持 MySQL 语法族协议的SQL优化 +* 支持基于启发式算法的语句优化 +* 支持复杂查询的多列索引优化(UPDATE, INSERT, DELETE, SELECT) +* 支持EXPLAIN信息丰富解读 +* 支持SQL指纹、压缩和美化 +* 支持同一张表多条ALTER请求合并 +* 支持自定义规则的SQL改写 + +## 快速入门 + +* [安装使用](http://github.com/XiaoMi/soar/blob/master/doc/install.md) +* [体系架构](http://github.com/XiaoMi/soar/blob/master/doc/structure.md) +* [配置文件](http://github.com/XiaoMi/soar/blob/master/doc/config.md) +* [常用命令](http://github.com/XiaoMi/soar/blob/master/doc/cheatsheet.md) +* [产品对比](http://github.com/XiaoMi/soar/blob/master/doc/comparison.md) +* [路线图](http://github.com/XiaoMi/soar/blob/master/doc/roadmap.md) + +## 交流与反馈 + +* 欢迎通过Github Issues提交问题报告与建议 +* QQ群: 779359816(满) 758940447(新) +* [Gitter](https://gitter.im/xiaomi-dba/soar) 推荐 + + ![xiaomi_sa](https://raw.githubusercontent.com/XiaoMi/soar/master/doc/images/xiaomi_sa.png) + +## License + +[Apache License 2.0](https://github.com/XiaoMi/soar/blob/master/LICENSE). diff --git a/vendor/github.com/XiaoMi/soar/README_EN.md b/vendor/github.com/XiaoMi/soar/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..fc7b7be6a13e1a898f3b7cffc0b7535ec356efd8 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/README_EN.md @@ -0,0 +1,40 @@ +# ![SOAR](https://raw.githubusercontent.com/XiaoMi/soar/master/doc/images/logo.png) + +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/xiaomi-dba/soar) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://github.com/XiaoMi/soar/blob/master/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/XiaoMi/soar)](https://goreportcard.com/report/github.com/XiaoMi/soar) +[![Build Status](https://travis-ci.org/XiaoMi/soar.svg?branch=master)](https://travis-ci.org/XiaoMi/soar) +[![GoDoc](https://godoc.org/github.com/XiaoMi/soar?status.svg)](https://godoc.org/github.com/XiaoMi/soar) + +[Docs](http://github.com/XiaoMi/soar/tree/master/doc) | [FAQ](http://github.com/XiaoMi/soar/blob/master/doc/FAQ_en.md) | [中文](http://github.com/XiaoMi/soar/blob/master/README.md) + +## SOAR + +SOAR (SQL Optimizer And Rewriter) is a tool, which can help SQL optimization and rewrite. It's developed and maintained by the DBA Team of Xiaomi AI&Cloud. + +## Features + +* Cross-platform support, such as Linux, Mac, and Windows +* Support Heuristic Rules Suggestion +* Support Complicate SQL Indexing Optimize +* Support EXPLAIN analyze for query plan +* Support SQL fingerprint, compress and built-in pretty print +* Support merge multi ALTER query into one SQL +* Support self-config rewrite rules from SQL Rewrite +* Suggestions were written in Chinese. But SOAR also gives many tools, which can be used without understanding Chinese. + +## QuickStart + +* [Install](http://github.com/XiaoMi/soar/blob/master/doc/install_en.md) +* [CheatSheet](http://github.com/XiaoMi/soar/blob/master/doc/cheatsheet_en.md) +* [Related works](http://github.com/XiaoMi/soar/blob/master/doc/comparison_en.md) + +## Communication + +* GitHub issues: bug reports, usage issues, feature requests +* [Gitter](https://gitter.im/xiaomi-dba/soar) +* IM QQ Group: 779359816 + +## License + +[Apache License 2.0](https://github.com/XiaoMi/soar/blob/master/LICENSE). diff --git a/vendor/github.com/XiaoMi/soar/VERSION b/vendor/github.com/XiaoMi/soar/VERSION new file mode 100644 index 0000000000000000000000000000000000000000..ac39a106c48515b621e90c028ed94c6f71bc03fa --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/VERSION @@ -0,0 +1 @@ +0.9.0 diff --git a/vendor/github.com/XiaoMi/soar/advisor/doc.go b/vendor/github.com/XiaoMi/soar/advisor/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..e435db2bba36c26da77c336dd10a52ae5cbe10ff --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/doc.go @@ -0,0 +1,18 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor contain heuristic rules, index rules and explain translator. +package advisor diff --git a/vendor/github.com/XiaoMi/soar/advisor/explainer.go b/vendor/github.com/XiaoMi/soar/advisor/explainer.go new file mode 100644 index 0000000000000000000000000000000000000000..c8b7c5f26f7699f7fac3e5d6a71b7c72c2aa7687 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/explainer.go @@ -0,0 +1,285 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "fmt" + "strings" + + "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/database" +) + +var explainRuleID int + +// [EXP.XXX]Rule +var explainRules map[string]Rule + +// [table_name]"suggest text" +var tablesSuggests map[string][]string + +/* +var explainIgnoreTables = []string{ + "dual", + "", +} +*/ + +// explain建议的形式 +// Item: EXP.XXX +// Severity: L[0-8] +// Summary: full table scan, not use index, full index scan... +// Content: XX TABLE xxx + +// +func checkExplainSelectType(exp *database.ExplainInfo) { + // 判断是否跳过不检查 + if len(common.Config.ExplainWarnSelectType) == 1 { + if common.Config.ExplainWarnSelectType[0] == "" { + return + } + } else if len(common.Config.ExplainWarnSelectType) < 1 { + return + } + + if exp.ExplainFormat == database.JSONFormatExplain { + // TODO + // JSON 形式遍历分析不方便,转成 Row 格式也没有 SelectType 暂不处理 + return + } + for _, v := range common.Config.ExplainWarnSelectType { + for _, row := range exp.ExplainRows { + if row.SelectType == v && v != "" { + tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("SelectType:%s", row.SelectType)) + } + } + } +} + +// 用户可以设置AccessType的建议级别,匹配到的查询会给出建议 +func checkExplainAccessType(exp *database.ExplainInfo) { + // 判断是否跳过不检查 + if len(common.Config.ExplainWarnAccessType) == 1 { + if common.Config.ExplainWarnAccessType[0] == "" { + return + } + } else if len(common.Config.ExplainWarnAccessType) < 1 { + return + } + + rows := exp.ExplainRows + if exp.ExplainFormat == database.JSONFormatExplain { + // JSON形式遍历分析不方便,转成Row格式统一处理 + rows = database.ConvertExplainJSON2Row(exp.ExplainJSON) + } + for _, v := range common.Config.ExplainWarnAccessType { + for _, row := range rows { + if row.AccessType == v && v != "" { + tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("Scalability:%s", row.Scalability)) + } + } + } +} + +// TODO: +/* +func checkExplainPossibleKeys(exp *database.ExplainInfo) { + // 判断是否跳过不检查 + if common.Config.ExplainMinPossibleKeys == 0 { + return + } + + rows := exp.ExplainRows + if exp.ExplainFormat == database.JSONFormatExplain { + // JSON形式遍历分析不方便,转成Row格式统一处理 + rows = database.ConvertExplainJSON2Row(exp.ExplainJSON) + } + for _, row := range rows { + if len(row.PossibleKeys) < common.Config.ExplainMinPossibleKeys { + tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("PossibleKeys:%d < %d", + len(row.PossibleKeys), common.Config.ExplainMinPossibleKeys)) + } + } +} +*/ + +// TODO: +/* +func checkExplainKeyLen(exp *database.ExplainInfo) { +} +*/ + +// TODO: +/* +func checkExplainKey(exp *database.ExplainInfo) { + // 小于最小使用试用key数量 + //return intval($explainResult) < intval($userCond); + //explain-min-keys int +} +*/ + +func checkExplainRef(exp *database.ExplainInfo) { + rows := exp.ExplainRows + if exp.ExplainFormat == database.JSONFormatExplain { + // JSON形式遍历分析不方便,转成Row格式统一处理 + rows = database.ConvertExplainJSON2Row(exp.ExplainJSON) + } + for i, row := range rows { + if strings.Join(row.Ref, "") == "NULL" || strings.Join(row.Ref, "") == "" { + if i == 0 && len(rows) > 1 { + continue + } + tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("Ref:null")) + } + } +} + +func checkExplainRows(exp *database.ExplainInfo) { + // 判断是否跳过不检查 + if common.Config.ExplainMaxRows <= 0 { + return + } + + rows := exp.ExplainRows + if exp.ExplainFormat == database.JSONFormatExplain { + // JSON形式遍历分析不方便,转成Row格式统一处理 + rows = database.ConvertExplainJSON2Row(exp.ExplainJSON) + } + + for _, row := range rows { + if row.Rows >= common.Config.ExplainMaxRows { + tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("Rows:%d", row.Rows)) + } + } +} + +// TODO: +/* +func checkExplainExtra(exp *database.ExplainInfo) { + // 包含用户配置的逗号分隔关键词之一则提醒 + // return self::contains($explainResult, $userCond); + // explain-warn-extra []string +} +*/ + +func checkExplainFiltered(exp *database.ExplainInfo) { + // 判断是否跳过不检查 + if common.Config.ExplainMaxFiltered <= 0.001 { + return + } + + rows := exp.ExplainRows + if exp.ExplainFormat == database.JSONFormatExplain { + // JSON形式遍历分析不方便,转成Row格式统一处理 + rows = database.ConvertExplainJSON2Row(exp.ExplainJSON) + } + for i, row := range rows { + if i == 0 && len(rows) > 1 { + continue + } + if row.Filtered >= common.Config.ExplainMaxFiltered { + tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("Filtered:%.2f%s", row.Filtered, "%")) + } + } +} + +// ExplainAdvisor 基于explain信息给出建议 +func ExplainAdvisor(exp *database.ExplainInfo) map[string]Rule { + common.Log.Debug("ExplainAdvisor SQL: %v", exp.SQL) + explainRuleID = 0 + explainRules = make(map[string]Rule) + tablesSuggests = make(map[string][]string) + + checkExplainSelectType(exp) + checkExplainAccessType(exp) + checkExplainFiltered(exp) + checkExplainRef(exp) + checkExplainRows(exp) + + // 打印explain table + content := database.PrintMarkdownExplainTable(exp) + + if common.Config.ShowWarnings { + content += "\n" + database.MySQLExplainWarnings(exp) + } + + // 对explain table中各项难于理解的值做解释 + cases := database.ExplainInfoTranslator(exp) + + // 添加last_query_cost + if common.Config.ShowLastQueryCost { + content += "\n" + database.MySQLExplainQueryCost(exp) + } + + if content != "" { + explainRules["EXP.000"] = Rule{ + Item: "EXP.000", + Severity: "L0", + Summary: "Explain信息", + Content: content, + Case: cases, + Func: (*Query4Audit).RuleOK, + } + } + /* + for t, s := range tablesSuggests { + // 检查explain对应的表是否需要跳过,如dual,空表等 + ig := false + for _, ti := range explainIgnoreTables { + if ti == t { + ig = true + } + } + if ig { + continue + } + ruleId := fmt.Sprintf("EXP.%03d", explainRuleId+1) + explainRuleId = explainRuleId + 1 + explainRules[ruleId] = Rule{ + Item: ruleId, + Severity: "L0", + Summary: fmt.Sprintf("表 `%s` 查询效率不高", t), + Content: fmt.Sprint("原因:", strings.Join(s, ",")), + Case: "", + Func: (*Query4Audit).RuleOK, + } + } + */ + return explainRules +} + +// DigestExplainText 分析用户输入的EXPLAIN信息 +func DigestExplainText(text string) { + // explain信息就不要显示完美了,美不美自己看吧。 + common.Config.IgnoreRules = append(common.Config.IgnoreRules, "OK") + + if !IsIgnoreRule("EXP.") { + explainInfo, err := database.ParseExplainText(text) + if err != nil { + common.Log.Error("main ParseExplainText Error: %v", err) + return + } + expSuggest := ExplainAdvisor(explainInfo) + _, output := FormatSuggest("", common.Config.ReportType, expSuggest) + if common.Config.ReportType == "html" { + fmt.Println(common.MarkdownHTMLHeader()) + fmt.Println(common.Markdown2HTML(output)) + } else { + fmt.Println(output) + } + } +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/explainer_test.go b/vendor/github.com/XiaoMi/soar/advisor/explainer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0fc8a86a4ff0af53ece1b61bca74afb78998123f --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/explainer_test.go @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "testing" + + "github.com/XiaoMi/soar/common" +) + +func TestDigestExplainText(t *testing.T) { + var text = `+----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+ +| 1 | SIMPLE | country | index | PRIMARY,country_id | country | 152 | NULL | 109 | Using index | +| 1 | SIMPLE | city | ref | idx_fk_country_id,idx_country_id_city,idx_all,idx_other | idx_fk_country_id | 2 | sakila.country.country_id | 2 | Using index | ++----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+` + common.Config.ReportType = "explain-digest" + err := common.GoldenDiff(func() { DigestExplainText(text) }, t.Name(), update) + if nil != err { + t.Fatal(err) + } +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/heuristic.go b/vendor/github.com/XiaoMi/soar/advisor/heuristic.go new file mode 100644 index 0000000000000000000000000000000000000000..c35682f6b6d4f5ecfbe9dc5f79a5564d04b3d5b0 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/heuristic.go @@ -0,0 +1,3408 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "bytes" + "fmt" + "regexp" + "strconv" + "strings" + "unicode/utf8" + + "github.com/XiaoMi/soar/ast" + "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/database" + "github.com/gedex/inflector" + "github.com/percona/go-mysql/query" + tidb "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/mysql" + "vitess.io/vitess/go/vt/sqlparser" +) + +// RuleOK OK +func (q *Query4Audit) RuleOK() Rule { + return HeuristicRules["OK"] +} + +// RuleImplicitAlias ALI.001 +func (q *Query4Audit) RuleImplicitAlias() Rule { + var rule = q.RuleOK() + tkns := ast.Tokenizer(q.Query) + if len(tkns) == 0 { + return rule + } + if tkns[0].Type != sqlparser.SELECT { + return rule + } + for i, tkn := range tkns { + if tkn.Type == sqlparser.ID && i+1 < len(tkns) && tkn.Type == tkns[i+1].Type { + rule = HeuristicRules["ALI.001"] + break + } + } + return rule +} + +// RuleStarAlias ALI.002 +func (q *Query4Audit) RuleStarAlias() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`(?i)(\*\s+as\b)`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["ALI.002"] + } + return rule +} + +// RuleSameAlias ALI.003 +func (q *Query4Audit) RuleSameAlias() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.AliasedExpr: + switch n := expr.Expr.(type) { + case *sqlparser.ColName: + if n.Name.String() == expr.As.String() { + rule = HeuristicRules["ALI.003"] + return false, nil + } + } + case *sqlparser.AliasedTableExpr: + switch n := expr.Expr.(type) { + case sqlparser.TableName: + if n.Name.String() == expr.As.String() { + rule = HeuristicRules["ALI.003"] + return false, nil + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RulePrefixLike ARG.001 +func (q *Query4Audit) RulePrefixLike() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.ComparisonExpr: + if expr.Operator == "like" { + switch sqlval := expr.Right.(type) { + case *sqlparser.SQLVal: + // prefix like with '%', '_' + if sqlval.Type == 0 && (sqlval.Val[0] == 0x25 || sqlval.Val[0] == 0x5f) { + rule = HeuristicRules["ARG.001"] + return false, nil + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleEqualLike ARG.002 +func (q *Query4Audit) RuleEqualLike() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.ComparisonExpr: + if expr.Operator == "like" { + switch sqlval := expr.Right.(type) { + case *sqlparser.SQLVal: + // not start with '%', '_' && not end with '%', '_' + if sqlval.Type == 0 { + if sqlval.Val[0] != 0x25 && + sqlval.Val[0] != 0x5f && + sqlval.Val[len(sqlval.Val)-1] != 0x5f && + sqlval.Val[len(sqlval.Val)-1] != 0x25 { + rule = HeuristicRules["ARG.002"] + return false, nil + } + } else { + rule = HeuristicRules["ARG.002"] + return false, nil + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleImplicitConversion ARG.003 +// 隐式类型转换检查:该项检查一定是在开启测试环境或线上环境情境下下进行的 +func (idxAdv *IndexAdvisor) RuleImplicitConversion() Rule { + /* + * 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换 + * 两个参数都是字符串,会按照字符串来比较,不做类型转换 + * 两个参数都是整数,按照整数来比较,不做类型转换 + * 十六进制的值和非数字做比较时,会被当做二进制串 + * 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp + * 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较 + * 所有其他情况下,两个参数都会被转换为浮点数再进行比较 + */ + rule := HeuristicRules["OK"] + // 未开启测试环境不进行检查 + if common.Config.TestDSN.Disable { + return rule + } + + var content string + conditions := ast.FindAllCondition(idxAdv.Ast) + for _, cond := range conditions { + var colList []*common.Column + var values []*sqlparser.SQLVal + + // condition 左右两侧有且只有如下几种可能: + // 1. 列与列比较,如: col1 = col2 + // 2. 列与值比较,如: col = val + // 3. 值与值比较,如: val1 = val2 暂不处理 + // 如果列包含在一个函数中,认为这个条件为值,如: col = func(col) 认定为 列与值比较 + switch node := cond.(type) { + case *sqlparser.ComparisonExpr: + // 获取 condition 左侧的信息 + switch nLeft := node.Left.(type) { + case *sqlparser.SQLVal, sqlparser.ValTuple: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch val := node.(type) { + case *sqlparser.SQLVal: + values = append(values, val) + } + return true, nil + }, nLeft) + common.LogIfError(err, "") + + case *sqlparser.ColName: + left := &common.Column{Name: nLeft.Name.String()} + if !nLeft.Qualifier.Name.IsEmpty() { + left.Table = nLeft.Qualifier.Name.String() + } + colList = append(colList, left) + } + + // 获取 condition 右侧的信息 + switch nRight := node.Right.(type) { + case *sqlparser.SQLVal, sqlparser.ValTuple: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch val := node.(type) { + case *sqlparser.SQLVal: + values = append(values, val) + } + return true, nil + }, nRight) + common.LogIfError(err, "") + + case *sqlparser.ColName: + right := &common.Column{Name: nRight.Name.String()} + if !nRight.Qualifier.Name.IsEmpty() { + right.Table = nRight.Qualifier.Name.String() + } + colList = append(colList, right) + } + + if len(colList) == 0 { + continue + } + + // 补全列信息 + colList = CompleteColumnsInfo(idxAdv.Ast, colList, idxAdv.vEnv) + + // 列与列比较 + if len(colList) == 2 { + // 列信息补全后如果依然没有表信息,说明在该数据库中不存在该列 + // 如果列信息获取异常,可能会存在无法获取到数据类型的情况,对于这种情况将不会给予建议。 + needBreak := false + for _, col := range colList { + if col.Table == "" { + common.Log.Warning("Column %s not exists", col.Name) + needBreak = true + } + + if col.DataType == "" { + common.Log.Warning("Can't get column %s data type", col.Name) + needBreak = true + } + + } + + if needBreak { + break + } + + // 检查数据类型不一致导致的隐式数据转换 + type1 := common.GetDataTypeBase(colList[0].DataType) + type2 := common.GetDataTypeBase(colList[1].DataType) + common.Log.Debug("DataType: `%s`.`%s` (%s) VS `%s`.`%s` (%s)", + colList[0].Table, colList[0].Name, type1, + colList[1].Table, colList[1].Name, type2) + if strings.ToLower(type1) != strings.ToLower(type2) { + content += fmt.Sprintf("`%s`.`%s` (%s) VS `%s`.`%s` (%s) datatype not match", + colList[0].Table, colList[0].Name, type1, + colList[1].Table, colList[1].Name, type2) + continue + } + + // 检查字符集不一致导致的隐式数据转换 + common.Log.Debug("Charset: `%s`.`%s` (%s) VS `%s`.`%s` (%s)", + colList[0].Table, colList[0].Name, colList[0].Character, + colList[1].Table, colList[1].Name, colList[1].Character) + if colList[0].Character != colList[1].Character { + content += fmt.Sprintf("`%s`.`%s` (%s) VS `%s`.`%s` (%s) charset not match", + colList[0].Table, colList[0].Name, colList[0].Character, + colList[1].Table, colList[1].Name, colList[1].Character) + continue + } + + // 检查排序排序不一致导致的隐式数据转换 + common.Log.Debug("Collation: `%s`.`%s` (%s) VS `%s`.`%s` (%s)", + colList[0].Table, colList[0].Name, colList[0].Collation, + colList[1].Table, colList[1].Name, colList[1].Collation) + if colList[0].Collation != colList[1].Collation { + content += fmt.Sprintf("`%s`.`%s` (%s) VS `%s`.`%s` (%s) collation not match", + colList[0].Table, colList[0].Name, colList[0].Collation, + colList[1].Table, colList[1].Name, colList[1].Collation) + continue + } + } + + typMap := map[sqlparser.ValType][]string{ + // date, time, datetime, timestamp, year + sqlparser.StrVal: { + "char", "varchar", "tinytext", "text", "mediumtext", "longtext", + "date", "time", "datetime", "timestamp", "year", + }, + sqlparser.IntVal: { + "tinyint", "smallint", "mediumint", "int", "integer", "bigint", "timestamp", "year", + }, + sqlparser.FloatVal: { + "float", "double", "real", "decimal", + }, + } + + typNameMap := map[sqlparser.ValType]string{ + sqlparser.StrVal: "string", + sqlparser.IntVal: "int", + sqlparser.FloatVal: "float", + } + + // 列与值比较 + for _, val := range values { + if colList[0].DataType == "" { + common.Log.Debug("Can't get %s data type", colList[0].Name) + break + } + + isCovered := true + if tps, ok := typMap[val.Type]; ok { + for _, tp := range tps { + if strings.HasPrefix(colList[0].DataType, tp) { + isCovered = false + } + } + } + + if isCovered { + if colList[0].Table == "" { + common.Log.Warning("Column %s not exists", colList[0].Name) + continue + } + + c := fmt.Sprintf("%s.%s definition is %s not %s", + colList[0].Table, colList[0].Name, colList[0].DataType, typNameMap[val.Type]) + + common.Log.Debug("Implicit data type conversion: %s", c) + content += c + } + } + + case *sqlparser.RangeCond: + // TODO + case *sqlparser.IsExpr: + // TODO + } + } + if content != "" { + rule = HeuristicRules["ARG.003"] + rule.Content = content + } + return rule +} + +// RuleNoWhere CLA.001 & CLA.014 & CLA.015 +func (q *Query4Audit) RuleNoWhere() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.Select: + if n.Where == nil && sqlparser.String(n.From) != "dual" { + rule = HeuristicRules["CLA.001"] + return false, nil + } + case *sqlparser.Delete: + if n.Where == nil { + rule = HeuristicRules["CLA.014"] + return false, nil + } + case *sqlparser.Update: + if n.Where == nil { + rule = HeuristicRules["CLA.015"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleOrderByRand CLA.002 +func (q *Query4Audit) RuleOrderByRand() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.OrderBy: + for _, order := range n { + switch expr := order.Expr.(type) { + case *sqlparser.FuncExpr: + if expr.Name.String() == "rand" { + rule = HeuristicRules["CLA.002"] + return false, nil + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleOffsetLimit CLA.003 +func (q *Query4Audit) RuleOffsetLimit() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.Limit: + if n != nil && n.Offset != nil { + switch v := n.Offset.(type) { + case *sqlparser.SQLVal: + offset, err := strconv.Atoi(string(v.Val)) + // 检查一下Offset阈值,太小了给这个建议也没什么用,阈值写死了没加配置 + if err == nil && offset > 1000 { + rule = HeuristicRules["CLA.003"] + return false, nil + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleGroupByConst CLA.004 +func (q *Query4Audit) RuleGroupByConst() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.GroupBy: + for _, group := range n { + switch group.(type) { + case *sqlparser.SQLVal: + rule = HeuristicRules["CLA.004"] + return false, nil + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleGroupByConst GRP.001 +func (idxAdv *IndexAdvisor) RuleGroupByConst() Rule { + rule := HeuristicRules["OK"] + + // 非GroupBy语句 + if len(idxAdv.groupBy) == 0 || len(idxAdv.whereEQ) == 0 { + return rule + } + + for _, groupByCols := range idxAdv.groupBy { + for _, whereEQCols := range idxAdv.whereEQ { + if (groupByCols.Name == whereEQCols.Name) && + (groupByCols.DB == whereEQCols.DB) && + (groupByCols.Table == whereEQCols.Table) { + rule = HeuristicRules["GRP.001"] + break + } + } + } + return rule +} + +// RuleOrderByConst CLA.005 +func (q *Query4Audit) RuleOrderByConst() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.OrderBy: + for _, order := range n { + switch order.Expr.(type) { + case *sqlparser.SQLVal: + rule = HeuristicRules["CLA.005"] + return false, nil + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleOrderByConst CLA.005 +// TODO: SELECT col FROM tbl WHERE col IN('NEWS') ORDER BY col; +func (idxAdv *IndexAdvisor) RuleOrderByConst() Rule { + rule := HeuristicRules["OK"] + + // 非GroupBy语句 + if len(idxAdv.orderBy) == 0 || len(idxAdv.whereEQ) == 0 { + return rule + } + + for _, groupbyCols := range idxAdv.orderBy { + for _, whereEQCols := range idxAdv.whereEQ { + if (groupbyCols.Name == whereEQCols.Name) && + (groupbyCols.DB == whereEQCols.DB) && + (groupbyCols.Table == whereEQCols.Table) { + rule = HeuristicRules["CLA.005"] + break + } + } + } + return rule +} + +// RuleDiffGroupByOrderBy CLA.006 +func (q *Query4Audit) RuleDiffGroupByOrderBy() Rule { + var rule = q.RuleOK() + var groupbyTbls []sqlparser.TableIdent + var orderbyTbls []sqlparser.TableIdent + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.GroupBy: + // 检查group by涉及到表的个数 + for _, group := range n { + switch g := group.(type) { + case *sqlparser.ColName: + tblExist := false + for _, t := range groupbyTbls { + if t.String() == g.Qualifier.Name.String() { + tblExist = true + } + } + if !tblExist { + groupbyTbls = append(groupbyTbls, g.Qualifier.Name) + if len(groupbyTbls) > 1 { + rule = HeuristicRules["CLA.006"] + return false, nil + } + } + } + } + case sqlparser.OrderBy: + // 检查order by涉及到表的个数 + for _, order := range n { + switch o := order.Expr.(type) { + case *sqlparser.ColName: + tblExist := false + for _, t := range orderbyTbls { + if t.String() == o.Qualifier.Name.String() { + tblExist = true + } + } + if !tblExist { + orderbyTbls = append(orderbyTbls, o.Qualifier.Name) + if len(orderbyTbls) > 1 { + rule = HeuristicRules["CLA.006"] + return false, nil + } + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + + if rule.Item == "OK" { + // 检查group by, order by涉及到表的个数 + for _, g := range groupbyTbls { + tblExist := false + for _, o := range orderbyTbls { + if g.String() == o.String() { + tblExist = true + } + } + if !tblExist && len(orderbyTbls) > 0 { + rule = HeuristicRules["CLA.006"] + return rule + } + } + } + + return rule +} + +// RuleMixOrderBy CLA.007 +func (q *Query4Audit) RuleMixOrderBy() Rule { + var rule = q.RuleOK() + var direction string + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.OrderBy: + for _, order := range n { + // 比较相邻两个order by列的方向 + if direction != "" && order.Direction != direction { + rule = HeuristicRules["CLA.007"] + return false, nil + } + direction = order.Direction + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleExplicitOrderBy CLA.008 +func (q *Query4Audit) RuleExplicitOrderBy() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.Select: + // 有group by,但没有order by + if n.GroupBy != nil && n.OrderBy == nil { + rule = HeuristicRules["CLA.008"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleOrderByExpr CLA.009 +func (q *Query4Audit) RuleOrderByExpr() Rule { + var rule = q.RuleOK() + var orderByCols []string + var selectCols []string + funcExp := regexp.MustCompile(`(?i)[a-z0-9]\(`) + allowExp := regexp.MustCompile("(?i)[a-z0-9_,.` ()]") + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.OrderBy: + orderBy := sqlparser.String(n) + // 函数名方式,如:from_unixtime(col) + if funcExp.MatchString(orderBy) { + rule = HeuristicRules["CLA.009"] + return false, nil + } + + // 运算符方式,如:colA - colB + trim := allowExp.ReplaceAllFunc([]byte(orderBy), func(s []byte) []byte { + return []byte("") + }) + if string(trim) != "" { + rule = HeuristicRules["CLA.009"] + return false, nil + } + + for _, o := range strings.Split(strings.TrimPrefix(orderBy, " order by "), ",") { + orderByCols = append(orderByCols, strings.TrimSpace(strings.Split(o, " ")[0])) + } + case *sqlparser.Select: + for _, s := range n.SelectExprs { + selectCols = append(selectCols, sqlparser.String(s)) + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + + // AS情况,如:SELECT colA-colB a FROM tbl ORDER BY a; + for _, o := range orderByCols { + if o == "" { + continue + } + for _, s := range selectCols { + if strings.HasSuffix(s, " as "+o) { + buf := strings.TrimSuffix(s, " as "+o) + // 运算符 + trim := allowExp.ReplaceAllFunc([]byte(buf), func(s []byte) []byte { + return []byte("") + }) + if string(trim) != "" { + rule = HeuristicRules["CLA.009"] + } + // 函数 + if funcExp.MatchString(s) { + rule = HeuristicRules["CLA.009"] + } + } + } + } + return rule +} + +// RuleGroupByExpr CLA.010 +func (q *Query4Audit) RuleGroupByExpr() Rule { + var rule = q.RuleOK() + var groupByCols []string + var selectCols []string + funcExp := regexp.MustCompile(`(?i)[a-z0-9]\(`) + allowExp := regexp.MustCompile("(?i)[a-z0-9_,.` ()]") + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.GroupBy: + groupBy := sqlparser.String(n) + // 函数名方式,如:from_unixtime(col) + if funcExp.MatchString(groupBy) { + rule = HeuristicRules["CLA.010"] + return false, nil + } + + // 运算符方式,如:colA - colB + trim := allowExp.ReplaceAllFunc([]byte(groupBy), func(s []byte) []byte { + return []byte("") + }) + if string(trim) != "" { + rule = HeuristicRules["CLA.010"] + return false, nil + } + + for _, o := range strings.Split(strings.TrimPrefix(groupBy, " group by "), ",") { + groupByCols = append(groupByCols, strings.TrimSpace(strings.Split(o, " ")[0])) + } + case *sqlparser.Select: + for _, s := range n.SelectExprs { + selectCols = append(selectCols, sqlparser.String(s)) + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + + // AS情况,如:SELECT colA-colB a FROM tbl GROUP BY a; + for _, g := range groupByCols { + if g == "" { + continue + } + for _, s := range selectCols { + if strings.HasSuffix(s, " as "+g) { + buf := strings.TrimSuffix(s, " as "+g) + // 运算符 + trim := allowExp.ReplaceAllFunc([]byte(buf), func(s []byte) []byte { + return []byte("") + }) + if string(trim) != "" { + rule = HeuristicRules["CLA.010"] + } + // 函数 + if funcExp.MatchString(s) { + rule = HeuristicRules["CLA.010"] + } + } + } + } + return rule +} + +// RuleTblCommentCheck CLA.011 +func (q *Query4Audit) RuleTblCommentCheck() Rule { + var rule = q.RuleOK() + switch node := q.Stmt.(type) { + case *sqlparser.DDL: + if node.Action != "create" { + return rule + } + if node.TableSpec == nil { + return rule + } + if options := node.TableSpec.Options; options == "" { + rule = HeuristicRules["CLA.011"] + + } else { + reg := regexp.MustCompile("(?i)comment") + if !reg.MatchString(options) { + rule = HeuristicRules["CLA.011"] + } + } + } + return rule +} + +// RuleSelectStar COL.001 +func (q *Query4Audit) RuleSelectStar() Rule { + var rule = q.RuleOK() + // 先把count(*)替换为count(1) + re := regexp.MustCompile(`(?i)count\s*\(\s*\*\s*\)`) + sql := re.ReplaceAllString(q.Query, "count(1)") + stmt, err := sqlparser.Parse(sql) + if err != nil { + common.Log.Debug("RuleSelectStar sqlparser.Parse Error: %v", err) + return rule + } + err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.StarExpr: + rule = HeuristicRules["COL.001"] + return false, nil + } + return true, nil + }, stmt) + common.LogIfError(err, "") + return rule +} + +// RuleInsertColDef COL.002 +func (q *Query4Audit) RuleInsertColDef() Rule { + var rule = q.RuleOK() + switch node := q.Stmt.(type) { + case *sqlparser.Insert: + if node.Columns == nil { + rule = HeuristicRules["COL.002"] + return rule + } + } + return rule +} + +// RuleAddDefaultValue COL.004 +func (q *Query4Audit) RuleAddDefaultValue() Rule { + var rule = q.RuleOK() + for _, node := range q.TiStmt { + switch n := node.(type) { + case *tidb.CreateTableStmt: + for _, c := range n.Cols { + colDefault := false + for _, o := range c.Options { + // 忽略AutoIncrement类型的默认值检查 + if o.Tp == tidb.ColumnOptionDefaultValue || o.Tp == tidb.ColumnOptionAutoIncrement { + colDefault = true + } + } + if !colDefault { + rule = HeuristicRules["COL.004"] + break + } + } + case *tidb.AlterTableStmt: + for _, s := range n.Specs { + switch s.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, tidb.AlterTableModifyColumn: + for _, c := range s.NewColumns { + colDefault := false + for _, o := range c.Options { + // 忽略AutoIncrement类型的默认值检查 + if o.Tp == tidb.ColumnOptionDefaultValue || o.Tp == tidb.ColumnOptionAutoIncrement { + colDefault = true + } + } + if !colDefault { + rule = HeuristicRules["COL.004"] + break + } + } + } + } + } + } + return rule +} + +// RuleColCommentCheck COL.005 +func (q *Query4Audit) RuleColCommentCheck() Rule { + var rule = q.RuleOK() + for _, node := range q.TiStmt { + switch n := node.(type) { + case *tidb.CreateTableStmt: + for _, c := range n.Cols { + colComment := false + for _, o := range c.Options { + if o.Tp == tidb.ColumnOptionComment { + colComment = true + } + } + if !colComment { + rule = HeuristicRules["COL.005"] + break + } + } + case *tidb.AlterTableStmt: + for _, s := range n.Specs { + switch s.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, tidb.AlterTableModifyColumn: + for _, c := range s.NewColumns { + colComment := false + for _, o := range c.Options { + if o.Tp == tidb.ColumnOptionComment { + colComment = true + } + } + if !colComment { + rule = HeuristicRules["COL.005"] + break + } + } + } + } + } + } + return rule +} + +// RuleIPString LIT.001 +func (q *Query4Audit) RuleIPString() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`['"]\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["LIT.001"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleDataNotQuote LIT.002 +func (q *Query4Audit) RuleDataNotQuote() Rule { + var rule = q.RuleOK() + // 2010-01-01 + re := regexp.MustCompile(`.\d{4}\s*-\s*\d{1,2}\s*-\s*\d{1,2}\b`) + sqls := re.FindAllString(q.Query, -1) + for _, sql := range sqls { + re = regexp.MustCompile(`^['"\w-].*`) + if re.FindString(sql) == "" { + rule = HeuristicRules["LIT.002"] + } + } + + // 10-01-01 + re = regexp.MustCompile(`.\d{2}\s*-\s*\d{1,2}\s*-\s*\d{1,2}\b`) + sqls = re.FindAllString(q.Query, -1) + for _, sql := range sqls { + re = regexp.MustCompile(`^['"\w-].*`) + if re.FindString(sql) == "" { + rule = HeuristicRules["LIT.002"] + } + } + + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + return rule +} + +// RuleSQLCalcFoundRows KWR.001 +func (q *Query4Audit) RuleSQLCalcFoundRows() Rule { + var rule = q.RuleOK() + tkns := ast.Tokenizer(q.Query) + for _, tkn := range tkns { + if tkn.Val == "sql_calc_found_rows" { + rule = HeuristicRules["KWR.001"] + break + } + } + return rule +} + +// RuleCommaAnsiJoin JOI.001 +func (q *Query4Audit) RuleCommaAnsiJoin() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.Select: + ansiJoin := false + commaJoin := false + for _, f := range n.From { + switch f.(type) { + case *sqlparser.JoinTableExpr: + ansiJoin = true + case *sqlparser.AliasedTableExpr: + commaJoin = true + } + } + if ansiJoin && commaJoin { + rule = HeuristicRules["JOI.001"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleDupJoin JOI.002 +func (q *Query4Audit) RuleDupJoin() Rule { + var rule = q.RuleOK() + var tables []string + switch q.Stmt.(type) { + // TODO: 这里未检查UNION SELECT + case *sqlparser.Union: + return rule + default: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.AliasedTableExpr: + switch table := n.Expr.(type) { + case sqlparser.TableName: + for _, t := range tables { + if t == table.Name.String() { + rule = HeuristicRules["JOI.002"] + return false, nil + } + } + tables = append(tables, table.Name.String()) + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + } + return rule +} + +// RuleImpossibleOuterJoin JOI.003 +// TODO: 未实现完 +func (idxAdv *IndexAdvisor) RuleImpossibleOuterJoin() Rule { + rule := HeuristicRules["OK"] + + var joinTables []string // JOIN相关表名 + var whereEQTables []string // WHERE等值判断条件表名 + var joinNotWhereTables []string // 是JOIN相关表,但未出现在WHERE等值判断条件中的表名 + + // 非JOIN语句 + if len(idxAdv.joinCond) == 0 || len(idxAdv.whereEQ) == 0 { + return rule + } + + for _, l1 := range idxAdv.joinCond { + for _, l2 := range l1 { + if l2.Table != "" && l2.Table != "dual" { + joinTables = append(joinTables, l2.Table) + } + } + } + + for _, w := range idxAdv.whereEQ { + whereEQTables = append(whereEQTables, w.Table) + } + + for _, j := range joinTables { + found := false + for _, w := range whereEQTables { + if j == w { + found = true + } + } + if !found { + joinNotWhereTables = append(joinNotWhereTables, j) + } + } + + // TODO: + fmt.Println(joinNotWhereTables) + /* + if len(joinNotWhereTables) == 0 { + rule = HeuristicRules["JOI.003"] + } + */ + rule = HeuristicRules["JOI.003"] + return rule +} + +// TODO: JOI.004 + +// RuleNoDeterministicGroupby RES.001 +func (q *Query4Audit) RuleNoDeterministicGroupby() Rule { + var rule = q.RuleOK() + var groupbyCols []*common.Column + var selectCols []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.Select: + // 过滤select列 + selectCols = ast.FindColumn(n.SelectExprs) + // 过滤group by列 + groupbyCols = ast.FindColumn(n.GroupBy) + // `select *`, but not `select count(*)` + if strings.Contains(sqlparser.String(n), " * ") && len(groupbyCols) > 0 { + rule = HeuristicRules["RES.001"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + + // TODO:暂时只检查了列名,未对库表名进行检查,也未处理AS + for _, s := range selectCols { + // 无group by退出 + if len(groupbyCols) == 0 { + break + } + found := false + for _, g := range groupbyCols { + if g.Name == s.Name { + found = true + } + } + if !found { + rule = HeuristicRules["RES.001"] + break + } + } + return rule +} + +// RuleNoDeterministicLimit RES.002 +func (q *Query4Audit) RuleNoDeterministicLimit() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.Select: + if n.Limit != nil && n.OrderBy == nil { + rule = HeuristicRules["RES.002"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleUpdateDeleteWithLimit RES.003 +func (q *Query4Audit) RuleUpdateDeleteWithLimit() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.Update: + if s.Limit != nil { + rule = HeuristicRules["RES.003"] + } + } + return rule +} + +// RuleUpdateDeleteWithOrderby RES.004 +func (q *Query4Audit) RuleUpdateDeleteWithOrderby() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.Update: + if s.OrderBy != nil { + rule = HeuristicRules["RES.004"] + } + } + return rule +} + +// RuleUpdateSetAnd RES.005 +func (q *Query4Audit) RuleUpdateSetAnd() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.Update: + if strings.Contains(sqlparser.String(s.Exprs), " and ") { + rule = HeuristicRules["RES.005"] + } + } + return rule +} + +// RuleImpossibleWhere RES.006 +func (q *Query4Audit) RuleImpossibleWhere() Rule { + var rule = q.RuleOK() + // BETWEEN 10 AND 5 + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.RangeCond: + if n.Operator == "between" { + from := 0 + to := 0 + switch s := n.From.(type) { + case *sqlparser.SQLVal: + from, _ = strconv.Atoi(string(s.Val)) + } + switch s := n.To.(type) { + case *sqlparser.SQLVal: + to, _ = strconv.Atoi(string(s.Val)) + } + if from > to { + rule = HeuristicRules["RES.006"] + return false, nil + } + } + case *sqlparser.ComparisonExpr: + factor := false + switch n.Operator { + case "!=", "<>": + case "=", "<=>": + factor = true + default: + return true, nil + } + + var left []byte + var right []byte + + // left + switch l := n.Left.(type) { + case *sqlparser.SQLVal: + left = l.Val + default: + return true, nil + } + + // right + switch r := n.Right.(type) { + case *sqlparser.SQLVal: + right = r.Val + default: + return true, nil + } + + // compare + if (!bytes.Equal(left, right) && factor) || (bytes.Equal(left, right) && !factor) { + rule = HeuristicRules["RES.006"] + } + return false, nil + } + + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleMeaninglessWhere RES.007 +func (q *Query4Audit) RuleMeaninglessWhere() Rule { + var rule = q.RuleOK() + // SELECT * FROM tb WHERE 1 + switch n := q.Stmt.(type) { + case *sqlparser.Select: + if n.Where != nil { + switch n.Where.Expr.(type) { + case *sqlparser.SQLVal: + rule = HeuristicRules["RES.007"] + return rule + } + } + } + // 1=1, 0=0 + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.ComparisonExpr: + factor := false + switch n.Operator { + case "!=", "<>": + factor = true + case "=", "<=>": + default: + return true, nil + } + + var left []byte + var right []byte + + // left + switch l := n.Left.(type) { + case *sqlparser.SQLVal: + left = l.Val + default: + return true, nil + } + + // right + switch r := n.Right.(type) { + case *sqlparser.SQLVal: + right = r.Val + default: + return true, nil + } + + // compare + if (bytes.Equal(left, right) && !factor) || (!bytes.Equal(left, right) && factor) { + rule = HeuristicRules["RES.007"] + } + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleLoadFile RES.008 +func (q *Query4Audit) RuleLoadFile() Rule { + var rule = q.RuleOK() + // 去除注释 + sql := database.RemoveSQLComments(q.Query) + // 去除多余的空格和回车 + sql = strings.Join(strings.Fields(sql), " ") + tks := ast.Tokenize(sql) + for i, tk := range tks { + // 注意:每个关键字token的结尾是带空格的,这里偷懒没trimspace直接加空格比较 + // LOAD DATA... + if strings.ToLower(tk.Val) == "load " && i+1 < len(tks) && + strings.ToLower(tks[i+1].Val) == "data " { + rule = HeuristicRules["RES.008"] + break + } + + // SELECT ... INTO OUTFILE + if strings.ToLower(tk.Val) == "into " && i+1 < len(tks) && + (strings.ToLower(tks[i+1].Val) == "outfile " || strings.ToLower(tks[i+1].Val) == "dumpfile ") { + rule = HeuristicRules["RES.008"] + break + } + } + return rule +} + +// RuleStandardINEQ STA.001 +func (q *Query4Audit) RuleStandardINEQ() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`(!=)`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["STA.001"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleUseKeyWord KWR.002 +func (q *Query4Audit) RuleUseKeyWord() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + if q.TiStmt == nil { + common.Log.Error("TiStmt is nil, SQL: %s", q.Query) + return rule + } + + for _, tiStmtNode := range q.TiStmt { + switch stmt := tiStmtNode.(type) { + case *tidb.AlterTableStmt: + // alter + for _, spec := range stmt.Specs { + for _, column := range spec.NewColumns { + if ast.IsMysqlKeyword(column.Name.String()) { + return HeuristicRules["KWR.002"] + } + } + } + + case *tidb.CreateTableStmt: + // create + if ast.IsMysqlKeyword(stmt.Table.Name.String()) { + return HeuristicRules["KWR.002"] + } + + for _, col := range stmt.Cols { + if ast.IsMysqlKeyword(col.Name.String()) { + return HeuristicRules["KWR.002"] + } + } + } + + } + } + + return rule +} + +// RulePluralWord KWR.003 +// Reference: https://en.wikipedia.org/wiki/English_plurals +func (q *Query4Audit) RulePluralWord() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + if q.TiStmt == nil { + common.Log.Error("TiStmt is nil, SQL: %s", q.Query) + return rule + } + + for _, tiStmtNode := range q.TiStmt { + switch stmt := tiStmtNode.(type) { + case *tidb.AlterTableStmt: + // alter + for _, spec := range stmt.Specs { + for _, column := range spec.NewColumns { + if inflector.Singularize(column.Name.String()) != column.Name.String() { + return HeuristicRules["KWR.003"] + } + } + } + + case *tidb.CreateTableStmt: + // create + if inflector.Singularize(stmt.Table.Name.String()) != stmt.Table.Name.String() { + return HeuristicRules["KWR.003"] + } + + for _, col := range stmt.Cols { + if inflector.Singularize(col.Name.String()) != col.Name.String() { + return HeuristicRules["KWR.003"] + } + } + } + + } + + } + return rule +} + +// RuleMultiBytesWord KWR.004 +func (q *Query4Audit) RuleMultiBytesWord() Rule { + // TODO: 目前使用 utf8 字符集检查,其他字符集输入可能会有问题 + var rule = q.RuleOK() + for _, tk := range ast.Tokenize(q.Query) { + switch tk.Type { + case ast.TokenTypeBacktickQuote, ast.TokenTypeWord: + if utf8.RuneCountInString(tk.Val) != len(tk.Val) { + rule = HeuristicRules["KWR.004"] + } + default: + } + } + return rule +} + +// RuleInsertSelect LCK.001 +func (q *Query4Audit) RuleInsertSelect() Rule { + var rule = q.RuleOK() + switch n := q.Stmt.(type) { + case *sqlparser.Insert: + switch n.Rows.(type) { + case *sqlparser.Select: + rule = HeuristicRules["LCK.001"] + } + } + return rule +} + +// RuleInsertOnDup LCK.002 +func (q *Query4Audit) RuleInsertOnDup() Rule { + var rule = q.RuleOK() + switch n := q.Stmt.(type) { + case *sqlparser.Insert: + if n.OnDup != nil { + rule = HeuristicRules["LCK.002"] + return rule + } + } + return rule +} + +// RuleInSubquery SUB.001 +func (q *Query4Audit) RuleInSubquery() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.Subquery: + rule = HeuristicRules["SUB.001"] + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleSubqueryDepth SUB.004 +func (q *Query4Audit) RuleSubqueryDepth() Rule { + var rule = q.RuleOK() + if depth := ast.GetSubqueryDepth(q.Stmt); depth > common.Config.MaxSubqueryDepth { + rule = HeuristicRules["SUB.004"] + } + return rule +} + +// RuleSubQueryLimit SUB.005 +// 只有 IN 的 SUBQUERY 限制了 LIMIT, FROM 子句中的 SUBQUERY 并未限制 LIMIT +func (q *Query4Audit) RuleSubQueryLimit() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.ComparisonExpr: + if n.Operator == "in" { + switch r := n.Right.(type) { + case *sqlparser.Subquery: + switch s := r.Select.(type) { + case *sqlparser.Select: + if s.Limit != nil { + rule = HeuristicRules["SUB.005"] + return false, nil + } + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleSubQueryFunctions SUB.006 +func (q *Query4Audit) RuleSubQueryFunctions() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.Subquery: + err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.FuncExpr: + rule = HeuristicRules["SUB.006"] + return false, nil + } + return true, nil + }, node) + common.LogIfError(err, "") + } + + if rule.Item == "OK" { + return true, nil + } + return false, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleMultiValueAttribute LIT.003 +func (q *Query4Audit) RuleMultiValueAttribute() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`(?i)(id\s+varchar)|(id\s+text)|(id\s+regexp)`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["LIT.003"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleAddDelimiter LIT.004 +func (q *Query4Audit) RuleAddDelimiter() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`(?i)(^use\s+[0-9a-z_-]*)|(^show\s+databases)`) + if re.FindString(q.Query) != "" && !strings.HasSuffix(q.Query, common.Config.Delimiter) { + rule = HeuristicRules["LIT.004"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleRecursiveDependency KEY.003 +func (q *Query4Audit) RuleRecursiveDependency() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + // create statement + for _, ref := range node.Constraints { + if ref != nil && ref.Tp == tidb.ConstraintForeignKey { + rule = HeuristicRules["KEY.003"] + } + } + + case *tidb.AlterTableStmt: + // alter table statement + for _, spec := range node.Specs { + if spec.Constraint != nil && spec.Constraint.Tp == tidb.ConstraintForeignKey { + rule = HeuristicRules["KEY.003"] + } + } + } + } + } + + if rule.Item == "KEY.003" { + re := regexp.MustCompile(`(?i)(\s+references\s+)`) + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + + return rule +} + +// RuleImpreciseDataType COL.009 +func (q *Query4Audit) RuleImpreciseDataType() Rule { + var rule = q.RuleOK() + if q.TiStmt != nil { + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + // Create table statement + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeFloat, mysql.TypeDouble, mysql.TypeDecimal, mysql.TypeNewDecimal: + rule = HeuristicRules["COL.009"] + } + } + + case *tidb.AlterTableStmt: + // Alter table statement + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, tidb.AlterTableModifyColumn: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeFloat, mysql.TypeDouble, + mysql.TypeDecimal, mysql.TypeNewDecimal: + rule = HeuristicRules["COL.009"] + } + } + } + } + + case *tidb.InsertStmt: + // Insert statement + for _, values := range node.Lists { + for _, value := range values { + switch value.GetType().Tp { + case mysql.TypeNewDecimal, mysql.TypeFloat: + rule = HeuristicRules["COL.009"] + } + } + } + + case *tidb.SelectStmt: + // Select statement + switch where := node.Where.(type) { + case *tidb.BinaryOperationExpr: + switch where.R.GetType().Tp { + case mysql.TypeNewDecimal, mysql.TypeFloat: + rule = HeuristicRules["COL.009"] + } + } + } + } + } + + return rule +} + +// RuleValuesInDefinition COL.010 +func (q *Query4Audit) RuleValuesInDefinition() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeSet, mysql.TypeEnum, mysql.TypeBit: + rule = HeuristicRules["COL.010"] + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, tidb.AlterTableModifyColumn: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeSet, mysql.TypeEnum, mysql.TypeBit: + rule = HeuristicRules["COL.010"] + } + } + } + } + } + } + } + return rule +} + +// RuleIndexAttributeOrder KEY.004 +func (q *Query4Audit) RuleIndexAttributeOrder() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateIndexStmt: + if len(node.IndexColNames) > 1 { + rule = HeuristicRules["KEY.004"] + break + } + case *tidb.CreateTableStmt: + for _, constraint := range node.Constraints { + // 当一条索引中包含多个列的时候给予建议 + if len(constraint.Keys) > 1 { + rule = HeuristicRules["KEY.004"] + break + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + if spec.Tp == tidb.AlterTableAddConstraint && len(spec.Constraint.Keys) > 1 { + rule = HeuristicRules["KEY.004"] + break + } + } + } + } + } + return rule +} + +// RuleNullUsage COL.011 +func (q *Query4Audit) RuleNullUsage() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`(?i)(\s+null\s+)`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["COL.011"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleStringConcatenation FUN.003 +func (q *Query4Audit) RuleStringConcatenation() Rule { + var rule = q.RuleOK() + re := regexp.MustCompile(`(?i)(\|\|)`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["FUN.003"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleSysdate FUN.004 +func (q *Query4Audit) RuleSysdate() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.FuncExpr: + if n.Name.String() == "sysdate" { + rule = HeuristicRules["FUN.004"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleCountConst FUN.005 +func (q *Query4Audit) RuleCountConst() Rule { + var rule = q.RuleOK() + fingerprint := query.Fingerprint(q.Query) + countReg := regexp.MustCompile(`(?i)count\(\s*[0-9a-z?]*\s*\)`) + if countReg.MatchString(fingerprint) { + rule = HeuristicRules["FUN.005"] + if position := countReg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleSumNPE FUN.006 +func (q *Query4Audit) RuleSumNPE() Rule { + var rule = q.RuleOK() + fingerprint := query.Fingerprint(q.Query) + sumReg := regexp.MustCompile(`(?i)sum\(\s*[0-9a-z?]*\s*\)`) + isnullReg := regexp.MustCompile(`(?i)isnull\(sum\(\s*[0-9a-z?]*\s*\)\)`) + if sumReg.MatchString(fingerprint) && !isnullReg.MatchString(fingerprint) { + rule = HeuristicRules["FUN.006"] + if position := isnullReg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + return rule +} + +// RuleForbiddenTrigger FUN.007 +func (q *Query4Audit) RuleForbiddenTrigger() Rule { + var rule = q.RuleOK() + + // 由于vitess对某些语法的支持不完善,使得如创建临时表等语句无法通过语法检查 + // 所以这里使用正则对触发器、临时表、存储过程等进行匹配 + // 但是目前支持的也不是非常全面,有待完善匹配规则 + // TODO TiDB 目前还不支持触发器、存储过程、自定义函数、外键 + + forbidden := []*regexp.Regexp{ + regexp.MustCompile(`(?i)CREATE\s+TRIGGER\s+`), + } + + for _, reg := range forbidden { + if reg.MatchString(q.Query) { + rule = HeuristicRules["FUN.007"] + if position := reg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + break + } + } + return rule +} + +// RuleForbiddenProcedure FUN.008 +func (q *Query4Audit) RuleForbiddenProcedure() Rule { + var rule = q.RuleOK() + + // 由于vitess对某些语法的支持不完善,使得如创建临时表等语句无法通过语法检查 + // 所以这里使用正则对触发器、临时表、存储过程等进行匹配 + // 但是目前支持的也不是非常全面,有待完善匹配规则 + // TODO TiDB 目前还不支持触发器、存储过程、自定义函数、外键 + + forbidden := []*regexp.Regexp{ + regexp.MustCompile(`(?i)CREATE\s+PROCEDURE\s+`), + } + + for _, reg := range forbidden { + if reg.MatchString(q.Query) { + rule = HeuristicRules["FUN.008"] + if position := reg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + break + } + } + return rule +} + +// RuleForbiddenFunction FUN.009 +func (q *Query4Audit) RuleForbiddenFunction() Rule { + var rule = q.RuleOK() + + // 由于vitess对某些语法的支持不完善,使得如创建临时表等语句无法通过语法检查 + // 所以这里使用正则对触发器、临时表、存储过程等进行匹配 + // 但是目前支持的也不是非常全面,有待完善匹配规则 + // TODO TiDB 目前还不支持触发器、存储过程、自定义函数、外键 + + forbidden := []*regexp.Regexp{ + regexp.MustCompile(`(?i)CREATE\s+FUNCTION\s+`), + } + + for _, reg := range forbidden { + if reg.MatchString(q.Query) { + rule = HeuristicRules["FUN.009"] + if position := reg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + break + } + } + return rule +} + +// RulePatternMatchingUsage ARG.007 +func (q *Query4Audit) RulePatternMatchingUsage() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.Select: + re := regexp.MustCompile(`(?i)(\bregexp\b)|(\bsimilar to\b)`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["ARG.007"] + } + } + return rule +} + +// RuleSpaghettiQueryAlert CLA.012 +func (q *Query4Audit) RuleSpaghettiQueryAlert() Rule { + var rule = q.RuleOK() + if len(query.Fingerprint(q.Query)) > common.Config.SpaghettiQueryLength { + rule = HeuristicRules["CLA.012"] + } + return rule +} + +// RuleReduceNumberOfJoin JOI.005 +func (q *Query4Audit) RuleReduceNumberOfJoin() Rule { + var rule = q.RuleOK() + var tables []string + switch q.Stmt.(type) { + // TODO: UNION有可能有多张表,这里未检查UNION SELECT + case *sqlparser.Union: + return rule + default: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.AliasedTableExpr: + switch table := n.Expr.(type) { + case sqlparser.TableName: + exist := false + for _, t := range tables { + if t == table.Name.String() { + exist = true + break + } + } + if !exist { + tables = append(tables, table.Name.String()) + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + } + if len(tables) > common.Config.MaxJoinTableCount { + rule = HeuristicRules["JOI.005"] + } + return rule +} + +// RuleDistinctUsage DIS.001 +func (q *Query4Audit) RuleDistinctUsage() Rule { + // Distinct + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.Select: + re := regexp.MustCompile(`(?i)(\bdistinct\b)`) + if len(re.FindAllString(q.Query, -1)) > common.Config.MaxDistinctCount { + rule = HeuristicRules["DIS.001"] + } + } + return rule +} + +// RuleCountDistinctMultiCol DIS.002 +func (q *Query4Audit) RuleCountDistinctMultiCol() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.FuncExpr: + str := strings.ToLower(sqlparser.String(n)) + if strings.HasPrefix(str, "count") && strings.Contains(str, ",") { + rule = HeuristicRules["DIS.002"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleDistinctStar DIS.003 +func (q *Query4Audit) RuleDistinctStar() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.Select: + meta := ast.GetMeta(q.Stmt, nil) + for _, m := range meta { + if len(m.Table) == 1 { + // distinct tbl.* from tbl和 distinct * + re := regexp.MustCompile(`(?i)((\s+distinct\s*\*)|(\s+distinct\s+[0-9a-z_` + "`" + `]*\.\*))`) + if re.MatchString(q.Query) { + rule = HeuristicRules["DIS.003"] + } + } + break + } + } + return rule +} + +// RuleHavingClause CLA.013 +func (q *Query4Audit) RuleHavingClause() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.Select: + if expr.Having != nil { + rule = HeuristicRules["CLA.013"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleUpdatePrimaryKey CLA.016 +func (idxAdv *IndexAdvisor) RuleUpdatePrimaryKey() Rule { + rule := HeuristicRules["OK"] + switch node := idxAdv.Ast.(type) { + case *sqlparser.Update: + var setColumns []*common.Column + + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.UpdateExpr: + // 获取 set 操作的全部 column + setColumns = append(setColumns, ast.FindAllCols(node)...) + } + return true, nil + }, node) + common.LogIfError(err, "") + setColumns = idxAdv.calcCardinality(CompleteColumnsInfo(idxAdv.Ast, setColumns, idxAdv.vEnv)) + for _, col := range setColumns { + idxMeta := idxAdv.IndexMeta[idxAdv.vEnv.DBHash(col.DB)][col.Table] + if idxMeta == nil { + return rule + } + for _, idx := range idxMeta.IdxRows { + if idx.KeyName == "PRIMARY" { + if col.Name == idx.ColumnName { + rule = HeuristicRules["CLA.016"] + return rule + } + continue + } + } + } + } + + return rule +} + +// RuleNestedSubQueries JOI.006 +func (q *Query4Audit) RuleNestedSubQueries() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.Subquery: + rule = HeuristicRules["JOI.006"] + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleMultiDeleteUpdate JOI.007 +func (q *Query4Audit) RuleMultiDeleteUpdate() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.Delete, *sqlparser.Update: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.JoinTableExpr: + rule = HeuristicRules["JOI.007"] + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + } + return rule +} + +// RuleMultiDBJoin JOI.008 +func (q *Query4Audit) RuleMultiDBJoin() Rule { + var rule = q.RuleOK() + meta := ast.GetMeta(q.Stmt, nil) + dbCount := 0 + for range meta { + dbCount++ + } + + if dbCount > 1 { + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.JoinTableExpr: + rule = HeuristicRules["JOI.008"] + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + } + return rule +} + +// RuleORUsage ARG.008 +func (q *Query4Audit) RuleORUsage() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.Select: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.OrExpr: + rule = HeuristicRules["ARG.008"] + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + } + return rule +} + +// RuleSpaceWithQuote ARG.009 +func (q *Query4Audit) RuleSpaceWithQuote() Rule { + var rule = q.RuleOK() + for _, tk := range ast.Tokenize(q.Query) { + if tk.Type == ast.TokenTypeQuote { + // 序列化的Val是带引号,所以要取第2个最倒数第二个,这样也就不用担心len<2了。 + switch tk.Val[1] { + case ' ': + rule = HeuristicRules["ARG.009"] + } + switch tk.Val[len(tk.Val)-2] { + case ' ': + rule = HeuristicRules["ARG.009"] + } + } + } + return rule +} + +// RuleHint ARG.010 +// TODO: sql_no_cache, straight join +func (q *Query4Audit) RuleHint() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.IndexHints: + if n != nil { + rule = HeuristicRules["ARG.010"] + } + return false, nil + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleNot ARG.011 +func (q *Query4Audit) RuleNot() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.ComparisonExpr: + if strings.HasPrefix(n.Operator, "not") { + rule = HeuristicRules["ARG.011"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleInsertValues ARG.012 +func (q *Query4Audit) RuleInsertValues() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.Insert: + switch val := s.Rows.(type) { + case sqlparser.Values: + if len(val) > common.Config.MaxValueCount { + rule = HeuristicRules["ARG.012"] + } + } + } + return rule +} + +// RuleUNIONUsage SUB.002 +func (q *Query4Audit) RuleUNIONUsage() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.Union: + if s.Type == "union" { + rule = HeuristicRules["SUB.002"] + } + } + return rule +} + +// RuleDistinctJoinUsage SUB.003 +func (q *Query4Audit) RuleDistinctJoinUsage() Rule { + var rule = q.RuleOK() + switch expr := q.Stmt.(type) { + case *sqlparser.Select: + if expr.Distinct != "" { + if expr.From != nil { + if len(expr.From) > 1 { + rule = HeuristicRules["SUB.003"] + } + } + } + } + return rule +} + +// RuleReadablePasswords SEC.002 +func (q *Query4Audit) RuleReadablePasswords() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + re := regexp.MustCompile(`(?i)(password)|(password)|(pwd)`) + for _, tiStmt := range q.TiStmt { + // create table stmt + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString, + mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob: + if re.FindString(q.Query) != "" { + return HeuristicRules["SEC.002"] + } + } + } + + case *tidb.AlterTableStmt: + // alter table stmt + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableModifyColumn, tidb.AlterTableChangeColumn, tidb.AlterTableAddColumns: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString, + mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob: + if re.FindString(q.Query) != "" { + return HeuristicRules["SEC.002"] + } + } + } + } + } + } + } + } + return rule +} + +// RuleDataDrop SEC.003 +func (q *Query4Audit) RuleDataDrop() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.DBDDL: + if s.Action == "drop" { + rule = HeuristicRules["SEC.003"] + } + case *sqlparser.DDL: + if s.Action == "drop" || s.Action == "truncate" { + rule = HeuristicRules["SEC.003"] + } + case *sqlparser.Delete: + rule = HeuristicRules["SEC.003"] + } + return rule +} + +// RuleCompareWithFunction FUN.001 +func (q *Query4Audit) RuleCompareWithFunction() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + // Vitess 中有些函数进行了单独定义不在 FuncExpr 中,如: substring。所以不能直接用 FuncExpr 判断。 + switch n := node.(type) { + case *sqlparser.ComparisonExpr: + switch n.Left.(type) { + case *sqlparser.SQLVal, *sqlparser.ColName: + default: + rule = HeuristicRules["FUN.001"] + return false, nil + } + /* + // func always has bracket + if strings.HasSuffix(sqlparser.String(n.Left), ")") { + rule = HeuristicRules["FUN.001"] + return false, nil + } + */ + + case *sqlparser.RangeCond: + // func(a) between func(c) and func(d) + switch n.Left.(type) { + case *sqlparser.SQLVal, *sqlparser.ColName: + default: + rule = HeuristicRules["FUN.001"] + return false, nil + } + switch n.From.(type) { + case *sqlparser.SQLVal, *sqlparser.ColName: + default: + rule = HeuristicRules["FUN.001"] + return false, nil + } + switch n.To.(type) { + case *sqlparser.SQLVal, *sqlparser.ColName: + default: + rule = HeuristicRules["FUN.001"] + return false, nil + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleCountStar FUN.002 +func (q *Query4Audit) RuleCountStar() Rule { + var rule = q.RuleOK() + switch n := q.Stmt.(type) { + case *sqlparser.Select: + // count(N), count(col), count(*) + re := regexp.MustCompile(`(?i)(count\(\s*[*0-9a-z_` + "`" + `]*\s*\))`) + if re.FindString(q.Query) != "" && n.Where != nil { + rule = HeuristicRules["FUN.002"] + } + } + return rule +} + +// RuleTruncateTable SEC.001 +func (q *Query4Audit) RuleTruncateTable() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.DDL: + if s.Action == "truncate" { + rule = HeuristicRules["SEC.001"] + } + } + return rule +} + +// RuleIn ARG.005 && ARG.004 +func (q *Query4Audit) RuleIn() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case *sqlparser.ComparisonExpr: + switch n.Operator { + case "in": + switch r := n.Right.(type) { + case sqlparser.ValTuple: + // IN (NULL) + for _, v := range r { + switch v.(type) { + case *sqlparser.NullVal: + rule = HeuristicRules["ARG.004"] + return false, nil + } + } + if len(r) > common.Config.MaxInCount { + rule = HeuristicRules["ARG.005"] + return false, nil + } + } + case "not in": + switch r := n.Right.(type) { + case sqlparser.ValTuple: + // NOT IN (NULL) + for _, v := range r { + switch v.(type) { + case *sqlparser.NullVal: + rule = HeuristicRules["ARG.004"] + return false, nil + } + } + } + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleIsNullIsNotNull ARG.006 +func (q *Query4Audit) RuleIsNullIsNotNull() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.Select: + re := regexp.MustCompile(`(?i)is\s*(not)?\s+null\b`) + if re.FindString(q.Query) != "" { + rule = HeuristicRules["ARG.006"] + } + } + return rule +} + +// RuleVarcharVSChar COL.008 +func (q *Query4Audit) RuleVarcharVSChar() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + // 在 TiDB 的 AST 中,char 和 binary 的 type 都是 mysql.TypeString + // 只是 binary 数据类型的 character 和 collate 是 binary + case mysql.TypeString: + rule = HeuristicRules["COL.008"] + } + } + + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, tidb.AlterTableModifyColumn: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeString: + rule = HeuristicRules["COL.008"] + } + } + } + } + } + } + } + return rule +} + +// RuleCreateDualTable TBL.003 +func (q *Query4Audit) RuleCreateDualTable() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.DDL: + if s.Table.Name.String() == "dual" { + rule = HeuristicRules["TBL.003"] + + } + } + return rule +} + +// RuleAlterCharset ALT.001 +func (q *Query4Audit) RuleAlterCharset() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableOption: + for _, option := range spec.Options { + if option.Tp == tidb.TableOptionCharset || + option.Tp == tidb.TableOptionCollate { + rule = HeuristicRules["ALT.001"] + break + } + } + } + + if rule.Item == "ALT.001" { + break + } + } + } + } + } + return rule +} + +// RuleAlterDropColumn ALT.003 +func (q *Query4Audit) RuleAlterDropColumn() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableDropColumn: + rule = HeuristicRules["ALT.003"] + } + } + } + } + + if rule.Item == "ALT.003" { + re := regexp.MustCompile(`(?i)(drop\s+column)`) + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + } + } + return rule +} + +// RuleAlterDropKey ALT.004 +func (q *Query4Audit) RuleAlterDropKey() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableDropPrimaryKey, + tidb.AlterTableDropIndex, + tidb.AlterTableDropForeignKey: + rule = HeuristicRules["ALT.004"] + } + } + } + } + } + return rule +} + +// RuleCantBeNull COL.012 +func (q *Query4Audit) RuleCantBeNull() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: + if !mysql.HasNotNullFlag(col.Tp.Flag) { + rule = HeuristicRules["COL.012"] + } + } + } + + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableModifyColumn, tidb.AlterTableChangeColumn: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: + if !mysql.HasNotNullFlag(col.Tp.Flag) { + rule = HeuristicRules["COL.012"] + } + } + } + } + } + } + } + } + + return rule +} + +// RuleTooManyKeys KEY.005 +func (q *Query4Audit) RuleTooManyKeys() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + if len(node.Constraints) > common.Config.MaxIdxCount { + rule = HeuristicRules["KEY.005"] + } + } + } + } + return rule +} + +// RuleTooManyKeyParts KEY.006 +func (q *Query4Audit) RuleTooManyKeyParts() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, constraint := range node.Constraints { + if len(constraint.Keys) > common.Config.MaxIdxColsCount { + return HeuristicRules["KEY.006"] + } + + if constraint.Refer != nil && len(constraint.Refer.IndexColNames) > common.Config.MaxIdxColsCount { + return HeuristicRules["KEY.006"] + } + } + + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddConstraint: + if spec.Constraint != nil { + if len(spec.Constraint.Keys) > common.Config.MaxIdxColsCount { + return HeuristicRules["KEY.006"] + } + + if spec.Constraint.Refer != nil { + if len(spec.Constraint.Refer.IndexColNames) > common.Config.MaxIdxColsCount { + return HeuristicRules["KEY.006"] + } + } + } + } + } + } + } + } + + return rule +} + +// RulePKNotInt KEY.007 && KEY.001 +func (q *Query4Audit) RulePKNotInt() Rule { + var rule = q.RuleOK() + var pk sqlparser.ColIdent + switch s := q.Stmt.(type) { + case *sqlparser.DDL: + if s.Action == "create" { + if s.TableSpec == nil { + return rule + } + for _, idx := range s.TableSpec.Indexes { + if idx.Info.Type == "primary key" { + if len(idx.Columns) == 1 { + pk = idx.Columns[0].Column + break + } + } + } + + // 未指定主键 + if pk.String() == "" { + rule = HeuristicRules["KEY.007"] + return rule + } + + // 主键非int, bigint类型 + for _, col := range s.TableSpec.Columns { + if pk.String() == col.Name.String() { + switch col.Type.Type { + case "int", "bigint", "integer": + if !col.Type.Unsigned { + rule = HeuristicRules["KEY.007"] + } + if !col.Type.Autoincrement { + rule = HeuristicRules["KEY.001"] + } + default: + rule = HeuristicRules["KEY.007"] + } + } + } + } + } + return rule +} + +// RuleOrderByMultiDirection KEY.008 +func (q *Query4Audit) RuleOrderByMultiDirection() Rule { + var rule = q.RuleOK() + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch n := node.(type) { + case sqlparser.OrderBy: + order := "" + for _, col := range strings.Split(sqlparser.String(n), ",") { + orders := strings.Split(col, " ") + if order != "" && order != orders[len(orders)-1] { + rule = HeuristicRules["KEY.008"] + return false, nil + } + order = orders[len(orders)-1] + } + } + return true, nil + }, q.Stmt) + common.LogIfError(err, "") + return rule +} + +// RuleUniqueKeyDup KEY.009 +// TODO: 目前只是给建议,期望能够实现自动检查 +func (q *Query4Audit) RuleUniqueKeyDup() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateIndexStmt: + // create index + if node.Unique { + re := regexp.MustCompile(`(?i)(create\s+(unique)\s)`) + rule = HeuristicRules["KEY.009"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + return rule + } + + case *tidb.AlterTableStmt: + // alter table add constraint + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddConstraint: + if spec.Constraint == nil { + continue + } + switch spec.Constraint.Tp { + case tidb.ConstraintPrimaryKey, tidb.ConstraintUniq, tidb.ConstraintUniqKey, tidb.ConstraintUniqIndex: + re := regexp.MustCompile(`(?i)(add\s+(unique)\s)`) + rule = HeuristicRules["KEY.009"] + if position := re.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + return rule + } + } + } + } + } + } + return rule +} + +// RuleTimestampDefault COL.013 +func (q *Query4Audit) RuleTimestampDefault() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + if col.Tp.Tp == mysql.TypeTimestamp { + hasDefault := false + for _, option := range col.Options { + if option.Tp == tidb.ColumnOptionDefaultValue { + hasDefault = true + } + } + if !hasDefault { + rule = HeuristicRules["COL.013"] + break + } + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, + tidb.AlterTableModifyColumn, + tidb.AlterTableChangeColumn, + tidb.AlterTableAlterColumn: + for _, col := range spec.NewColumns { + if col.Tp.Tp == mysql.TypeTimestamp { + hasDefault := false + for _, option := range col.Options { + if option.Tp == tidb.ColumnOptionDefaultValue { + hasDefault = true + } + } + if !hasDefault { + rule = HeuristicRules["COL.013"] + break + } + } + } + } + } + } + } + } + return rule +} + +// RuleAutoIncrementInitNotZero TBL.004 +func (q *Query4Audit) RuleAutoIncrementInitNotZero() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, opt := range node.Options { + if opt.Tp == tidb.TableOptionAutoIncrement && opt.UintValue > 1 { + rule = HeuristicRules["TBL.004"] + } + } + + } + } + } + return rule +} + +// RuleColumnWithCharset COL.014 +func (q *Query4Audit) RuleColumnWithCharset() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + if col.Tp.Charset != "" || col.Tp.Collate != "" { + rule = HeuristicRules["COL.014"] + break + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAlterColumn, tidb.AlterTableChangeColumn, + tidb.AlterTableModifyColumn, tidb.AlterTableAddColumns: + for _, col := range spec.NewColumns { + if col.Tp.Charset != "" || col.Tp.Collate != "" { + rule = HeuristicRules["COL.014"] + break + } + } + } + + } + } + } + } + return rule +} + +// RuleTableCharsetCheck TBL.005 +func (q *Query4Audit) RuleTableCharsetCheck() Rule { + var rule = q.RuleOK() + + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + var allow bool + var hasCharset bool + for _, opt := range node.Options { + if opt.Tp == tidb.TableOptionCharset { + hasCharset = true + for _, ch := range common.Config.TableAllowCharsets { + if strings.TrimSpace(strings.ToLower(ch)) == strings.TrimSpace(strings.ToLower(opt.StrValue)) { + allow = true + break + } + } + } + } + + // 未指定字符集使用MySQL默认配置字符集,我们认为MySQL的配置是被优化过的。 + if hasCharset && !allow { + rule = HeuristicRules["TBL.005"] + break + } + + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + var allow bool + var hasCharset bool + switch spec.Tp { + case tidb.AlterTableOption: + for _, opt := range spec.Options { + if opt.Tp == tidb.TableOptionCharset { + hasCharset = true + for _, ch := range common.Config.TableAllowCharsets { + if strings.TrimSpace(strings.ToLower(ch)) == strings.TrimSpace(strings.ToLower(opt.StrValue)) { + allow = true + break + } + } + } + } + // 未指定字符集使用MySQL默认配置字符集,我们认为MySQL的配置是被优化过的。 + if hasCharset && !allow { + rule = HeuristicRules["TBL.005"] + break + } + } + } + } + } + } + return rule +} + +// RuleForbiddenView TBL.006 +func (q *Query4Audit) RuleForbiddenView() Rule { + var rule = q.RuleOK() + + // 由于vitess对某些语法的支持不完善,使得如创建临时表等语句无法通过语法检查 + // 所以这里使用正则对触发器、临时表、存储过程等进行匹配 + // 但是目前支持的也不是非常全面,有待完善匹配规则 + // TODO TiDB 目前还不支持触发器、存储过程、自定义函数、外键 + + forbidden := []*regexp.Regexp{ + regexp.MustCompile(`(?i)CREATE\s+VIEW\s+`), + regexp.MustCompile(`(?i)REPLACE\s+VIEW\s+`), + } + + for _, reg := range forbidden { + if reg.MatchString(q.Query) { + rule = HeuristicRules["TBL.006"] + if position := reg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + break + } + } + return rule +} + +// RuleForbiddenTempTable TBL.007 +func (q *Query4Audit) RuleForbiddenTempTable() Rule { + var rule = q.RuleOK() + + // 由于vitess对某些语法的支持不完善,使得如创建临时表等语句无法通过语法检查 + // 所以这里使用正则对触发器、临时表、存储过程等进行匹配 + // 但是目前支持的也不是非常全面,有待完善匹配规则 + // TODO TiDB 目前还不支持触发器、存储过程、自定义函数、外键 + + forbidden := []*regexp.Regexp{ + regexp.MustCompile(`(?i)CREATE\s+TEMPORARY\s+TABLE\s+`), + } + + for _, reg := range forbidden { + if reg.MatchString(q.Query) { + rule = HeuristicRules["TBL.007"] + if position := reg.FindIndex([]byte(q.Query)); len(position) > 0 { + rule.Position = position[0] + } + break + } + } + return rule +} + +// RuleBlobDefaultValue COL.015 +func (q *Query4Audit) RuleBlobDefaultValue() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeLongBlob: + for _, opt := range col.Options { + if opt.Tp == tidb.ColumnOptionDefaultValue && opt.Expr.GetType().Tp != mysql.TypeNull { + rule = HeuristicRules["COL.015"] + break + } + } + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableModifyColumn, tidb.AlterTableAlterColumn, + tidb.AlterTableChangeColumn, tidb.AlterTableAddColumns: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeLongBlob: + for _, opt := range col.Options { + if opt.Tp == tidb.ColumnOptionDefaultValue && opt.Expr.GetType().Tp != mysql.TypeNull { + rule = HeuristicRules["COL.015"] + break + } + } + } + } + } + } + } + } + } + return rule +} + +// RuleIntPrecision COL.016 +func (q *Query4Audit) RuleIntPrecision() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeLong: + if (col.Tp.Flen < 10 || col.Tp.Flen > 11) && col.Tp.Flen > 0 { + // 有些语言 ORM 框架会生成 int(11),有些语言的框架生成 int(10) + rule = HeuristicRules["COL.016"] + break + } + case mysql.TypeLonglong: + if (col.Tp.Flen != 20) && col.Tp.Flen > 0 { + rule = HeuristicRules["COL.016"] + break + } + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, + tidb.AlterTableAlterColumn, tidb.AlterTableModifyColumn: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeLong: + if (col.Tp.Flen < 10 || col.Tp.Flen > 11) && col.Tp.Flen > 0 { + // 有些语言 ORM 框架会生成 int(11),有些语言的框架生成 int(10) + rule = HeuristicRules["COL.016"] + break + } + case mysql.TypeLonglong: + if col.Tp.Flen != 20 && col.Tp.Flen > 0 { + rule = HeuristicRules["COL.016"] + break + } + } + } + } + } + } + } + } + return rule +} + +// RuleVarcharLength COL.017 +func (q *Query4Audit) RuleVarcharLength() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + switch col.Tp.Tp { + case mysql.TypeVarchar, mysql.TypeVarString: + if col.Tp.Flen > common.Config.MaxVarcharLength { + rule = HeuristicRules["COL.017"] + break + } + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableAddColumns, tidb.AlterTableChangeColumn, + tidb.AlterTableAlterColumn, tidb.AlterTableModifyColumn: + for _, col := range spec.NewColumns { + switch col.Tp.Tp { + case mysql.TypeVarchar, mysql.TypeVarString: + if col.Tp.Flen > common.Config.MaxVarcharLength { + rule = HeuristicRules["COL.017"] + break + } + } + } + } + } + } + } + } + return rule +} + +// RuleNoOSCKey KEY.002 +func (q *Query4Audit) RuleNoOSCKey() Rule { + var rule = q.RuleOK() + switch s := q.Stmt.(type) { + case *sqlparser.DDL: + if s.Action == "create" { + pkReg := regexp.MustCompile(`(?i)(primary\s+key)`) + if !pkReg.MatchString(q.Query) { + ukReg := regexp.MustCompile(`(?i)(unique\s+((key)|(index)))`) + if !ukReg.MatchString(q.Query) { + rule = HeuristicRules["KEY.002"] + } + } + } + } + return rule +} + +// RuleTooManyFields COL.006 +func (q *Query4Audit) RuleTooManyFields() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + if len(node.Cols) > common.Config.MaxColCount { + rule = HeuristicRules["COL.006"] + } + } + } + } + return rule +} + +// RuleAllowEngine TBL.002 +func (q *Query4Audit) RuleAllowEngine() Rule { + var rule = q.RuleOK() + var hasDefaultEngine bool + var allowedEngine bool + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, opt := range node.Options { + if opt.Tp == tidb.TableOptionEngine { + hasDefaultEngine = true + // 使用了非推荐的存储引擎 + for _, engine := range common.Config.TableAllowEngines { + if strings.EqualFold(opt.StrValue, engine) { + allowedEngine = true + } + } + // common.Config.TableAllowEngines 为空时不给予建议 + if !allowedEngine && len(common.Config.TableAllowEngines) > 0 { + rule = HeuristicRules["TBL.002"] + break + } + } + } + // 建表语句未指定表的存储引擎 + if !hasDefaultEngine { + rule = HeuristicRules["TBL.002"] + break + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableOption: + for _, opt := range spec.Options { + if opt.Tp == tidb.TableOptionEngine { + // 使用了非推荐的存储引擎 + for _, engine := range common.Config.TableAllowEngines { + if strings.EqualFold(opt.StrValue, engine) { + allowedEngine = true + } + } + // common.Config.TableAllowEngines 为空时不给予建议 + if !allowedEngine && len(common.Config.TableAllowEngines) > 0 { + rule = HeuristicRules["TBL.002"] + break + } + } + } + } + } + } + } + } + return rule +} + +// RulePartitionNotAllowed TBL.001 +func (q *Query4Audit) RulePartitionNotAllowed() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + if node.Partition != nil { + rule = HeuristicRules["TBL.001"] + break + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + if len(spec.PartDefinitions) > 0 { + rule = HeuristicRules["TBL.001"] + break + } + } + } + } + } + return rule +} + +// RuleAutoIncUnsigned COL.003: +func (q *Query4Audit) RuleAutoIncUnsigned() Rule { + var rule = q.RuleOK() + switch q.Stmt.(type) { + case *sqlparser.DDL: + for _, tiStmt := range q.TiStmt { + switch node := tiStmt.(type) { + case *tidb.CreateTableStmt: + for _, col := range node.Cols { + for _, opt := range col.Options { + if opt.Tp == tidb.ColumnOptionAutoIncrement { + if !mysql.HasUnsignedFlag(col.Tp.Flag) { + rule = HeuristicRules["COL.003"] + break + } + } + + if rule.Item == "COL.003" { + break + } + } + } + case *tidb.AlterTableStmt: + for _, spec := range node.Specs { + switch spec.Tp { + case tidb.AlterTableChangeColumn, tidb.AlterTableAlterColumn, + tidb.AlterTableModifyColumn, tidb.AlterTableAddColumns: + for _, col := range spec.NewColumns { + for _, opt := range col.Options { + if opt.Tp == tidb.ColumnOptionAutoIncrement { + if !mysql.HasUnsignedFlag(col.Tp.Flag) { + rule = HeuristicRules["COL.003"] + break + } + } + + if rule.Item == "COL.003" { + break + } + } + } + } + } + } + } + } + return rule +} + +// RuleSpaceAfterDot STA.002 +func (q *Query4Audit) RuleSpaceAfterDot() Rule { + var rule = q.RuleOK() + tks := ast.Tokenize(q.Query) + for i, tk := range tks { + switch tk.Type { + + // SELECT * FROM db. tbl + // SELECT tbl. col FROM tbl + case ast.TokenTypeWord: + if len(tks) > i+1 && + tks[i+1].Type == ast.TokenTypeWhitespace && + strings.HasSuffix(tk.Val, ".") { + common.Log.Debug("RuleSpaceAfterDot: ", tk.Val, tks[i+1].Val) + rule = HeuristicRules["STA.002"] + return rule + } + default: + } + } + return rule +} + +// RuleIdxPrefix STA.003 +func (q *Query4Audit) RuleIdxPrefix() Rule { + var rule = q.RuleOK() + for _, node := range q.TiStmt { + switch n := node.(type) { + case *tidb.CreateTableStmt: + for _, c := range n.Constraints { + switch c.Tp { + case tidb.ConstraintIndex, tidb.ConstraintKey: + if !strings.HasPrefix(c.Name, common.Config.IdxPrefix) { + rule = HeuristicRules["STA.003"] + } + case tidb.ConstraintUniq, tidb.ConstraintUniqKey, tidb.ConstraintUniqIndex: + if !strings.HasPrefix(c.Name, common.Config.UkPrefix) { + rule = HeuristicRules["STA.003"] + } + } + } + case *tidb.AlterTableStmt: + for _, s := range n.Specs { + switch s.Tp { + case tidb.AlterTableAddConstraint: + switch s.Constraint.Tp { + case tidb.ConstraintIndex, tidb.ConstraintKey: + if !strings.HasPrefix(s.Constraint.Name, common.Config.IdxPrefix) { + rule = HeuristicRules["STA.003"] + } + case tidb.ConstraintUniq, tidb.ConstraintUniqKey, tidb.ConstraintUniqIndex: + if !strings.HasPrefix(s.Constraint.Name, common.Config.UkPrefix) { + rule = HeuristicRules["STA.003"] + } + } + } + } + } + } + return rule +} + +// RuleStandardName STA.004 +func (q *Query4Audit) RuleStandardName() Rule { + var rule = q.RuleOK() + allowReg := regexp.MustCompile(`(?i)[a-z0-9_` + "`" + `]`) + for _, tk := range ast.Tokenize(q.Query) { + if tk.Val == "``" { + rule = HeuristicRules["STA.004"] + } + + switch tk.Type { + // 反引号中可能有乱七八糟的东西 + case ast.TokenTypeBacktickQuote: + // 特殊字符,连续下划线 + if allowReg.ReplaceAllString(tk.Val, "") != "" || strings.Contains(tk.Val, "__") { + rule = HeuristicRules["STA.004"] + } + // 统一大小写 + if !(strings.ToLower(tk.Val) == tk.Val || strings.ToUpper(tk.Val) == tk.Val) { + rule = HeuristicRules["STA.004"] + } + case ast.TokenTypeWord: + // TOKEN_TYPE_WORD 中处理连续下划线的情况,其他情况容易误伤 + if strings.Contains(tk.Val, "__") { + rule = HeuristicRules["STA.004"] + } + default: + } + } + return rule +} + +// MergeConflictHeuristicRules merge conflict rules +func MergeConflictHeuristicRules(rules map[string]Rule) map[string]Rule { + // KWR.001 VS ERR.000 + // select sql_calc_found_rows * from film + if _, ok := rules["KWR.001"]; ok { + delete(rules, "ERR.000") + } + + // SUB.001 VS OWN.004 VS JOI.006 + if _, ok := rules["SUB.001"]; ok { + delete(rules, "ARG.005") + delete(rules, "JOI.006") + } + + // SUB.004 VS SUB.001 + if _, ok := rules["SUB.004"]; ok { + delete(rules, "SUB.001") + } + + // KEY.007 VS KEY.002 + if _, ok := rules["KEY.007"]; ok { + delete(rules, "KEY.002") + } + + // JOI.002 VS JOI.006 + if _, ok := rules["JOI.002"]; ok { + delete(rules, "JOI.006") + } + + // JOI.008 VS JOI.007 + if _, ok := rules["JOI.008"]; ok { + delete(rules, "JOI.007") + } + return rules +} + +// RuleMySQLError ERR.XXX +func RuleMySQLError(item string, err error) Rule { + + type MySQLError struct { + ErrCode string + ErrString string + } + + // tidb parser 语法检查出错返回的是ERR.000 + switch item { + case "ERR.000": + return Rule{ + Item: item, + Summary: "No available MySQL environment, build-in sql parse failed: " + err.Error(), + Severity: "L8", + Content: err.Error(), + } + } + + // Received #1146 error from MySQL server: "table xxx doesn't exist" + errReg := regexp.MustCompile(`(?i)Received #([0-9]+) error from MySQL server: ['"](.*)['"]`) + errStr := err.Error() + msg := errReg.FindStringSubmatch(errStr) + var mysqlError MySQLError + + if len(msg) == 3 { + if msg[1] != "" && msg[2] != "" { + mysqlError = MySQLError{ + ErrCode: msg[1], + ErrString: msg[2], + } + } + } else { + var errcode string + if strings.HasPrefix(err.Error(), "syntax error at position") { + errcode = "1064" + } + mysqlError = MySQLError{ + ErrCode: errcode, + ErrString: err.Error(), + } + } + switch mysqlError.ErrCode { + // 1146 ER_NO_SUCH_TABLE + case "", "1146": + return Rule{ + Item: item, + Summary: "MySQL execute failed: ", + Severity: "L0", + Content: "", + } + default: + return Rule{ + Item: item, + Summary: "MySQL execute failed: " + mysqlError.ErrString, + Severity: "L8", + Content: mysqlError.ErrString, + } + } +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/heuristic_test.go b/vendor/github.com/XiaoMi/soar/advisor/heuristic_test.go new file mode 100644 index 0000000000000000000000000000000000000000..de57328c13ee88ff90d84da51e5ff6739e96ec54 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/heuristic_test.go @@ -0,0 +1,3183 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "errors" + "sort" + "testing" + + "github.com/XiaoMi/soar/common" + + "github.com/kr/pretty" +) + +// ALI.001 +func TestRuleImplicitAlias(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "select col c from tbl where id < 1000", + "select col from tbl tb where id < 1000", + }, + { + "do 1", + }, + } + for _, sql := range sqls[0] { + q, _ := NewQuery4Audit(sql) + rule := q.RuleImplicitAlias() + if rule.Item != "ALI.001" { + t.Error("Rule not match:", rule.Item, "Expect : ALI.001") + } + } + for _, sql := range sqls[1] { + q, _ := NewQuery4Audit(sql) + rule := q.RuleImplicitAlias() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ALI.002 +func TestRuleStarAlias(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select tbl.* as c1,c2,c3 from tbl where id < 1000", + } + for _, sql := range sqls { + q, _ := NewQuery4Audit(sql) + rule := q.RuleStarAlias() + if rule.Item != "ALI.002" { + t.Error("Rule not match:", rule.Item, "Expect : ALI.002") + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ALI.003 +func TestRuleSameAlias(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col as col from tbl where id < 1000", + "select col from tbl as tbl where id < 1000", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSameAlias() + if rule.Item != "ALI.003" { + t.Error("Rule not match:", rule.Item, "Expect : ALI.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.001 +func TestRulePrefixLike(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col from tbl where id like '%abc'", + "select col from tbl where id like '_abc'", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePrefixLike() + if rule.Item != "ARG.001" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.002 +func TestRuleEqualLike(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col from tbl where id like 'abc'", + "select col from tbl where id like 1", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleEqualLike() + if rule.Item != "ARG.002" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.001 +func TestRuleNoWhere(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + {"select col from tbl", + "delete from tbl", + "update tbl set col=1", + "insert into city (country_id) select country_id from country", + }, + { + `select 1;`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoWhere() + if rule.Item != "CLA.001" && rule.Item != "CLA.014" && rule.Item != "CLA.015" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.001/CLA.014/CLA.015") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoWhere() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.002 +func TestRuleOrderByRand(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col from tbl where id = 1 order by rand()", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOrderByRand() + if rule.Item != "CLA.002" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.003 +func TestRuleOffsetLimit(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select c1,c2 from tbl where name=xx order by number limit 1 offset 2000", + "select c1,c2 from tbl where name=xx order by number limit 2000,1", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOffsetLimit() + if rule.Item != "CLA.003" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.004 +func TestRuleGroupByConst(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col1,col2 from tbl where col1='abc' group by 1", + "select col1,col2 from tbl group by 1", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleGroupByConst() + if rule.Item != "CLA.004" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.005 +func TestRuleOrderByConst(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + // "select id from test where id=1 order by id", + "select id from test where id=1 order by 1", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOrderByConst() + if rule.Item != "CLA.005" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.006 +func TestRuleDiffGroupByOrderBy(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select tb1.col, tb2.col from tb1, tb2 where id=1 group by tb1.col, tb2.col", + "select tb1.col, tb2.col from tb1, tb2 where id=1 order by tb1.col, tb2.col", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDiffGroupByOrderBy() + if rule.Item != "CLA.006" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.007 +func TestRuleMixOrderBy(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMixOrderBy() + if rule.Item != "CLA.007" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.007") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.008 +func TestRuleExplicitOrderBy(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select c1,c2,c3 from t1 where c1='foo' group by c2", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleExplicitOrderBy() + if rule.Item != "CLA.008" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.008") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.009 +func TestRuleOrderByExpr(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "SELECT col FROM tbl order by cola - cl;", // order by 列运算 + "SELECT cola - cl col FROM tbl order by col;", // 别名为列运算 + "SELECT cola FROM tbl order by from_unixtime(col);", // order by 函数运算 + "SELECT from_unixtime(col) cola FROM tbl order by cola;", // 别名为函数运算 + }, + { + `SELECT tbl.col FROM tbl ORDER BY col`, + "SELECT sum(col) AS col FROM tbl ORDER BY dt", + "SELECT tbl.col FROM tb, tbl WHERE tbl.tag_id = tb.id ORDER BY tbl.col", + "SELECT col FROM tbl order by `timestamp`;", // 列名为关键字 + "select col from tb where cl = 1 order by APPLY_TIME", // issue #104 case sensitive + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOrderByExpr() + if rule.Item != "CLA.009" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.009") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOrderByExpr() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.010 +func TestRuleGroupByExpr(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "SELECT col FROM tbl GROUP by cola - col;", + "SELECT cola - col col FROM tbl GROUP by col;", + "SELECT cola FROM tbl GROUP by from_unixtime(col);", + "SELECT from_unixtime(col) cola FROM tbl GROUP by cola;", + + // 反面例子 + // `SELECT tbl.col FROM tbl GROUP BY col`, + // "SELECT dt, sum(col) AS col FROM tbl GROUP BY dt", + // "SELECT tbl.col FROM tb, tbl WHERE tbl.tag_id = tb.id GROUP BY tbl.col", + // "SELECT col FROM tbl GROUP by `timestamp`;", // 列名为关键字 + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleGroupByExpr() + if rule.Item != "CLA.010" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.010") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.011 +func TestRuleTblCommentCheck(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "CREATE TABLE `test1`( `ID` bigint(20) NOT NULL AUTO_INCREMENT," + + " `c1` varchar(128) DEFAULT NULL, `c2` varchar(300) DEFAULT NULL," + + " `c3` varchar(32) DEFAULT NULL, `c4` int(11) NOT NULL, `c5` double NOT NULL," + + " `c6` text NOT NULL, PRIMARY KEY (`ID`), KEY `idx_c3_c2_c4_c5_c6` " + + "(`c3`,`c2`(255),`c4`,`c5`,`c6`(255)), KEY `idx_c3_c2_c4` (`c3`,`c2`,`c4`)) " + + "ENGINE = InnoDB DEFAULT CHARSET=utf8", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTblCommentCheck() + if rule.Item != "CLA.011" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.011") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.001 +func TestRuleSelectStar(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select * from tbl where id=1", + "select col, * from tbl where id=1", + // 反面例子 + // "select count(*) from film where id=1", + // `select count(* ) from film where id=1`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSelectStar() + if rule.Item != "COL.001" { + t.Error("Rule not match:", rule.Item, "Expect : COL.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.002 +func TestRuleInsertColDef(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "insert into tbl values(1,'name')", + "replace into tbl values(1,'name')", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleInsertColDef() + if rule.Item != "COL.002" { + t.Error("Rule not match:", rule.Item, "Expect : COL.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.004 +func TestRuleAddDefaultValue(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "create table test(id int)", + `ALTER TABLE test change id id varchar(10);`, + `ALTER TABLE test modify id varchar(10);`, + }, + { + `ALTER TABLE test modify id varchar(10) DEFAULT '';`, + `ALTER TABLE test CHANGE id id varchar(10) DEFAULT '';`, + "create table test(id int not null default 0 comment '用户id')", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAddDefaultValue() + if rule.Item != "COL.004" { + t.Error("Rule not match:", rule.Item, "Expect : COL.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAddDefaultValue() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.005 +func TestRuleColCommentCheck(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "create table test(id int not null default 0)", + `alter table test add column a int`, + `ALTER TABLE t1 CHANGE b b INT NOT NULL;`, + }, + { + "create table test(id int not null default 0 comment '用户id')", + `alter table test add column a int comment 'test'`, + `ALTER TABLE t1 AUTO_INCREMENT = 13;`, + `ALTER TABLE t1 CHANGE b b INT NOT NULL COMMENT 'test';`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleColCommentCheck() + if rule.Item != "COL.005" { + t.Error("Rule not match:", rule.Item, "Expect : COL.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleColCommentCheck() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// LIT.001 +func TestRuleIPString(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "insert into tbl (IP,name) values('10.20.306.122','test')", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIPString() + if rule.Item != "LIT.001" { + t.Error("Rule not match:", rule.Item, "Expect : LIT.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// LIT.002 +func TestRuleDataNotQuote(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col1,col2 from tbl where time < 2018-01-10", + "select col1,col2 from tbl where time < 18-01-10", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDataNotQuote() + if rule.Item != "LIT.002" { + t.Error("Rule not match:", rule.Item, "Expect : LIT.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KWR.001 +func TestRuleSQLCalcFoundRows(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select SQL_CALC_FOUND_ROWS col from tbl where id>1000", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSQLCalcFoundRows() + if rule.Item != "KWR.001" { + t.Error("Rule not match:", rule.Item, "Expect : KWR.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// JOI.001 +func TestRuleCommaAnsiJoin(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select c1,c2,c3 from t1,t2 join t3 on t1.c1=t2.c1 and t1.c3=t3.c1 where id>1000;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCommaAnsiJoin() + if rule.Item != "JOI.001" { + t.Error("Rule not match:", rule.Item, "Expect : JOI.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// JOI.002 +func TestRuleDupJoin(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select tb1.col from (tb1, tb2) join tb2 on tb1.id=tb.id where tb1.id=1;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDupJoin() + if rule.Item != "JOI.002" { + t.Error("Rule not match:", rule.Item, "Expect : JOI.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.001 +func TestRuleNoDeterministicGroupby(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + // 正面CASE + { + "select c1,c2,c3 from t1 where c2='foo' group by c2", + "select col, col2, sum(col1) from tb group by col", + "select col, col1 from tb group by col,sum(col1)", + "select * from tb group by col", + }, + + // 反面CASE + { + "select id from film", + "select col, sum(col1) from tb group by col", + "select * from file", + "SELECT COUNT(*) AS cnt, language_id FROM film GROUP BY language_id;", + "SELECT COUNT(*) AS cnt FROM film GROUP BY language_id;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoDeterministicGroupby() + if rule.Item != "RES.001" { + t.Error("Rule not match:", rule.Item, "Expect : RES.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoDeterministicGroupby() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.002 +func TestRuleNoDeterministicLimit(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col1,col2 from tbl where name='tony' limit 10", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoDeterministicLimit() + if rule.Item != "RES.002" { + t.Error("Rule not match:", rule.Item, "Expect : RES.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.003 +func TestRuleUpdateDeleteWithLimit(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "UPDATE film SET length = 120 WHERE title = 'abc' LIMIT 1;", + }, + { + "UPDATE film SET length = 120 WHERE title = 'abc';", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUpdateDeleteWithLimit() + if rule.Item != "RES.003" { + t.Error("Rule not match:", rule.Item, "Expect : RES.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUpdateDeleteWithLimit() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.004 +func TestRuleUpdateDeleteWithOrderby(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "UPDATE film SET length = 120 WHERE title = 'abc' ORDER BY title;", + }, + { + "UPDATE film SET length = 120 WHERE title = 'abc';", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUpdateDeleteWithOrderby() + if rule.Item != "RES.004" { + t.Error("Rule not match:", rule.Item, "Expect : RES.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUpdateDeleteWithOrderby() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.005 +func TestRuleUpdateSetAnd(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "update tbl set col = 1 and cl = 2 where col=3;", + }, + { + "update tbl set col = 1 ,cl = 2 where col=3;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUpdateSetAnd() + if rule.Item != "RES.005" { + t.Error("Rule not match:", rule.Item, "Expect : RES.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUpdateSetAnd() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.006 +func TestRuleImpossibleWhere(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "select * from tbl where 1 != 1;", + "select * from tbl where 'a' != 'a';", + "select * from tbl where col between 10 AND 5;", + }, + { + "select * from tbl where 1 = 1;", + "select * from tbl where 'a' != 1;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleImpossibleWhere() + if rule.Item != "RES.006" { + t.Error("Rule not match:", rule.Item, "Expect : RES.006, SQL: ", sql) + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleImpossibleWhere() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK, SQL: ", sql) + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.007 +func TestRuleMeaninglessWhere(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "select * from tbl where 1 = 1;", + "select * from tbl where 'a' = 'a';", + "select * from tbl where 'a' != 1;", + "select * from tbl where 'a';", + "select * from tbl where 'a' limit 1;", + "select * from tbl where 1;", + "select * from tbl where 1 limit 1;", + }, + { + "select * from tbl where 2 = 1;", + "select * from tbl where 'b' = 'a';", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMeaninglessWhere() + if rule.Item != "RES.007" { + t.Error("Rule not match:", rule.Item, "Expect : RES.007, SQL: ", sql) + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMeaninglessWhere() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK, SQL: ", sql) + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// RES.008 +func TestRuleLoadFile(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;", + "LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;", + "LOAD /*COMMENT*/DATA INFILE 'data.txt' INTO TABLE db2.my_table;", + `SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table;`, + }, + { + "SELECT id, data INTO @x, @y FROM test.t1 LIMIT 1;", + }, + } + for _, sql := range sqls[0] { + q := &Query4Audit{Query: sql} + rule := q.RuleLoadFile() + if rule.Item != "RES.008" { + t.Error("Rule not match:", rule.Item, "Expect : RES.008, SQL: ", sql) + } + } + + for _, sql := range sqls[1] { + q := &Query4Audit{Query: sql} + rule := q.RuleLoadFile() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK, SQL: ", sql) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// STA.001 +func TestRuleStandardINEQ(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col1,col2 from tbl where type!=0", + // "select col1,col2 from tbl where type<>0", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleStandardINEQ() + if rule.Item != "STA.001" { + t.Error("Rule not match:", rule.Item, "Expect : STA.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KWR.002 +func TestRuleUseKeyWord(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE tbl (`select` int)", + "CREATE TABLE `select` (a int)", + "ALTER TABLE tbl ADD COLUMN `select` varchar(10)", + }, + { + "CREATE TABLE tbl (a int)", + "ALTER TABLE tbl ADD COLUMN col varchar(10)", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUseKeyWord() + if rule.Item != "KWR.002" { + t.Error("Rule not match:", rule.Item, "Expect : KWR.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUseKeyWord() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KWR.003 +func TestRulePluralWord(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE tbl (`people` int)", + "CREATE TABLE people (a int)", + "ALTER TABLE tbl ADD COLUMN people varchar(10)", + }, + { + "CREATE TABLE tbl (`person` int)", + "ALTER TABLE tbl ADD COLUMN person varchar(10)", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePluralWord() + if rule.Item != "KWR.003" { + t.Error("Rule not match:", rule.Item, "Expect : KWR.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePluralWord() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KWR.004 +func TestRuleMultiBytesWord(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "select col as 列 from tb", + "select col as `列` from tb", + }, + { + "select col as c from tb", + "select '列'", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMultiBytesWord() + if rule.Item != "KWR.004" { + t.Error("Rule not match:", rule.Item, "Expect : KWR.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMultiBytesWord() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// LCK.001 +func TestRuleInsertSelect(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `INSERT INTO tbl SELECT * FROM tbl2;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleInsertSelect() + if rule.Item != "LCK.001" { + t.Error("Rule not match:", rule.Item, "Expect : LCK.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// LCK.002 +func TestRuleInsertOnDup(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `INSERT INTO t1(a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleInsertOnDup() + if rule.Item != "LCK.002" { + t.Error("Rule not match:", rule.Item, "Expect : LCK.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SUB.001 +func TestRuleInSubquery(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select col1,col2,col3 from table1 where col2 in(select col from table2)", + "SELECT col1,col2,col3 from table1 where col2 =(SELECT col2 FROM `table1` limit 1)", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleInSubquery() + if rule.Item != "SUB.001" { + t.Error("Rule not match:", rule.Item, "Expect : SUB.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// LIT.003 +func TestRuleMultiValueAttribute(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "select c1,c2,c3,c4 from tab1 where col_id REGEXP '[[:<:]]12[[:>:]]'", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMultiValueAttribute() + if rule.Item != "LIT.003" { + t.Error("Rule not match:", rule.Item, "Expect : LIT.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// LIT.003 +func TestRuleAddDelimiter(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `use sakila + select * from film`, + `use sakila`, + `show databases`, + }, + { + `use sakila;`, + }, + } + for _, sql := range sqls[0] { + q, _ := NewQuery4Audit(sql) + + rule := q.RuleAddDelimiter() + if rule.Item != "LIT.004" { + t.Error("Rule not match:", rule.Item, "Expect : LIT.004") + } + } + for _, sql := range sqls[1] { + q, _ := NewQuery4Audit(sql) + + rule := q.RuleAddDelimiter() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.003 +func TestRuleRecursiveDependency(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `CREATE TABLE tab2 ( + p_id BIGINT UNSIGNED NOT NULL, + a_id BIGINT UNSIGNED NOT NULL, + PRIMARY KEY (p_id, a_id), + FOREIGN KEY (p_id) REFERENCES tab1(p_id), + FOREIGN KEY (a_id) REFERENCES tab3(a_id) + );`, + `ALTER TABLE tbl2 add FOREIGN KEY (p_id) REFERENCES tab1(p_id);`, + }, + { + `ALTER TABLE tbl2 ADD KEY p_id (p_id);`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleRecursiveDependency() + if rule.Item != "KEY.003" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleRecursiveDependency() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.009 +func TestRuleImpreciseDataType(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `CREATE TABLE tab2 ( + p_id BIGINT UNSIGNED NOT NULL, + a_id BIGINT UNSIGNED NOT NULL, + hours float NOT null, + PRIMARY KEY (p_id, a_id) + );`, + `alter table tbl add column c float not null;`, + `insert into tb (col) values (0.00001);`, + `select * from tb where col = 0.00001;`, + }, + { + "REPLACE INTO `storage` (`hostname`,`storagehost`, `filename`, `starttime`, `binlogstarttime`, `uploadname`, `binlogsize`, `filesize`, `md5`, `status`) VALUES (1, 1, 1, 1, 1, 1, ?, ?);", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleImpreciseDataType() + if rule.Item != "COL.009" { + t.Error("Rule not match:", rule.Item, "Expect : COL.009") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleImpreciseDataType() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.010 +func TestRuleValuesInDefinition(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `create table tab1(status ENUM('new', 'in progress', 'fixed'))`, + `alter table tab1 add column status ENUM('new', 'in progress', 'fixed')`, + } + + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleValuesInDefinition() + if rule.Item != "COL.010" { + t.Error("Rule not match:", rule.Item, "Expect : COL.010") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.004 +func TestRuleIndexAttributeOrder(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `create index idx1 on tab(last_name,first_name);`, + `alter table tab add index idx1 (last_name,first_name);`, + `CREATE TABLE test (id int,blob_col BLOB, INDEX(blob_col(10),id));`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIndexAttributeOrder() + if rule.Item != "KEY.004" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.011 +func TestRuleNullUsage(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select c1,c2,c3 from tab where c4 is null or c4 <> 1;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNullUsage() + if rule.Item != "COL.011" { + t.Error("Rule not match:", rule.Item, "Expect : COL.011") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.003 +func TestRuleStringConcatenation(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select c1 || coalesce(' ' || c2 || ' ', ' ') || c3 as c from tab;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleStringConcatenation() + if rule.Item != "FUN.003" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.004 +func TestRuleSysdate(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select sysdate();`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSysdate() + if rule.Item != "FUN.004" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.005 +func TestRuleCountConst(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `select count(1) from tbl;`, + `select count(col) from tbl;`, + }, + { + `select count(*) from tbl`, + `select count(DISTINCT col) from tbl`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCountConst() + if rule.Item != "FUN.005" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCountConst() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.006 +func TestRuleSumNPE(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `select sum(1) from tbl;`, + `select sum(col) from tbl;`, + }, + { + `SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSumNPE() + if rule.Item != "FUN.006" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSumNPE() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.007 +func TestRulePatternMatchingUsage(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select c1,c2,c3,c4 from tab1 where col_id REGEXP '[[:<:]]12[[:>:]]';`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePatternMatchingUsage() + if rule.Item != "ARG.007" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.007") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.012 +func TestRuleSpaghettiQueryAlert(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select 1`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + common.Config.SpaghettiQueryLength = 1 + rule := q.RuleSpaghettiQueryAlert() + if rule.Item != "CLA.012" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.012") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// JOI.005 +func TestRuleReduceNumberOfJoin(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select bp1.p_id, b1.d_d as l, b1.b_id from b1 join bp1 on (b1.b_id = bp1.b_id) left outer join (b1 as b2 join bp2 on (b2.b_id = bp2.b_id)) on (bp1.p_id = bp2.p_id ) join bp21 on (b1.b_id = bp1.b_id) join bp31 on (b1.b_id = bp1.b_id) join bp41 on (b1.b_id = bp1.b_id) where b2.b_id = 0; `, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleReduceNumberOfJoin() + if rule.Item != "JOI.005" { + t.Error("Rule not match:", rule.Item, "Expect : JOI.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// DIS.001 +func TestRuleDistinctUsage(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT DISTINCT c.c_id,count(DISTINCT c.c_name),count(DISTINCT c.c_e),count(DISTINCT c.c_n),count(DISTINCT c.c_me),c.c_d FROM (select distinct id, name from B) as e WHERE e.country_id = c.country_id;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDistinctUsage() + if rule.Item != "DIS.001" { + t.Error("Rule not match:", rule.Item, "Expect : DIS.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// DIS.002 +func TestRuleCountDistinctMultiCol(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "SELECT COUNT(DISTINCT col, col2) FROM tbl;", + }, + { + "SELECT COUNT(DISTINCT col) FROM tbl;", + `SELECT JSON_OBJECT( "key", p.id, "title", p.name, "manufacturer", p.manufacturer, "price", p.price, "specifications", JSON_OBJECTAGG(a.name, v.value)) as product FROM product as p JOIN value as v ON p.id = v.prod_id JOIN attribute as a ON a.id = v.attribute_id GROUP BY v.prod_id`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCountDistinctMultiCol() + if rule.Item != "DIS.002" { + t.Error("Rule not match:", rule.Item, "Expect : DIS.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCountDistinctMultiCol() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// DIS.003 +// RuleDistinctStar +func TestRuleDistinctStar(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "SELECT DISTINCT * FROM film;", + "SELECT DISTINCT film.* FROM film;", + }, + { + "SELECT DISTINCT col FROM film;", + "SELECT DISTINCT film.* FROM film, tbl;", + "SELECT DISTINCT * FROM film, tbl;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDistinctStar() + if rule.Item != "DIS.003" { + t.Error("Rule not match:", rule.Item, "Expect : DIS.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDistinctStar() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.013 +func TestRuleHavingClause(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT s.c_id,count(s.c_id) FROM s where c = test GROUP BY s.c_id HAVING s.c_id <> '1660' AND s.c_id <> '2' order by s.c_id;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleHavingClause() + if rule.Item != "CLA.013" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.013") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.007 +func TestRuleForbiddenTrigger(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `CREATE TRIGGER t1 AFTER INSERT ON work FOR EACH ROW INSERT INTO time VALUES(NOW());`, + } + for _, sql := range sqls { + q, _ := NewQuery4Audit(sql) + rule := q.RuleForbiddenTrigger() + if rule.Item != "FUN.007" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.007") + } + + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.008 +func TestRuleForbiddenProcedure(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `CREATE PROCEDURE simpleproc (OUT param1 INT)`, + } + for _, sql := range sqls { + q, _ := NewQuery4Audit(sql) + rule := q.RuleForbiddenProcedure() + if rule.Item != "FUN.008" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.008") + } + + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.009 +func TestRuleForbiddenFunction(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `CREATE FUNCTION hello (s CHAR(20));`, + } + for _, sql := range sqls { + q, _ := NewQuery4Audit(sql) + rule := q.RuleForbiddenFunction() + if rule.Item != "FUN.009" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.009") + } + + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.006 +func TestRuleForbiddenView(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `create view v_today (today) AS SELECT CURRENT_DATE;`, + `CREATE VIEW v (col) AS SELECT 'abc';`, + } + for _, sql := range sqls { + q, _ := NewQuery4Audit(sql) + rule := q.RuleForbiddenView() + if rule.Item != "TBL.006" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.006") + } + + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.007 +func TestRuleForbiddenTempTable(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "CREATE TEMPORARY TABLE `work` (`time` time DEFAULT NULL) ENGINE=InnoDB;", + } + for _, sql := range sqls { + q, _ := NewQuery4Audit(sql) + rule := q.RuleForbiddenTempTable() + if rule.Item != "TBL.007" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.007") + } + + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// JOI.006 +func TestRuleNestedSubQueries(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT s,p,d FROM tab WHERE p.p_id = (SELECT s.p_id FROM tab WHERE s.c_id = 100996 AND s.q = 1 );`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNestedSubQueries() + if rule.Item != "JOI.006" { + t.Error("Rule not match:", rule.Item, "Expect : JOI.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// JOI.007 +func TestRuleMultiDeleteUpdate(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `DELETE u FROM users u LEFT JOIN hobby tna ON u.id = tna.uid WHERE tna.hobby = 'piano'; `, + `UPDATE users u LEFT JOIN hobby h ON u.id = h.uid SET u.name = 'pianoboy' WHERE h.hobby = 'piano';`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMultiDeleteUpdate() + if rule.Item != "JOI.007" { + t.Error("Rule not match:", rule.Item, "Expect : JOI.007") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// JOI.008 +func TestRuleMultiDBJoin(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT s,p,d FROM db1.tb1 join db2.tb2 on db1.tb1.a = db2.tb2.a where db1.tb1.a > 10;`, + `SELECT s,p,d FROM db1.tb1 join tb2 on db1.tb1.a = tb2.a where db1.tb1.a > 10;`, + // `SELECT s,p,d FROM db1.tb1 join db1.tb2 on db1.tb1.a = db1.tb2.a where db1.tb1.a > 10;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleMultiDBJoin() + if rule.Item != "JOI.008" { + t.Error("Rule not match:", rule.Item, "Expect : JOI.008") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.008 +func TestRuleORUsage(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT c1,c2,c3 FROM tab WHERE c1 = 14 OR c2 = 17;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleORUsage() + if rule.Item != "ARG.008" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.008") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.009 +func TestRuleSpaceWithQuote(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `SELECT 'a ';`, + `SELECT ' a';`, + `SELECT "a ";`, + `SELECT " a";`, + }, + { + `select ''`, + `select 'a'`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSpaceWithQuote() + if rule.Item != "ARG.009" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.009") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSpaceWithQuote() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.010 +func TestRuleHint(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `SELECT * FROM t1 USE INDEX (i1) ORDER BY a;`, + `SELECT * FROM t1 IGNORE INDEX (i1) ORDER BY (i2);`, + // TODO: vitess syntax not support now + // `SELECT * FROM t1 USE INDEX (i1,i2) IGNORE INDEX (i2);`, + // `SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) USE INDEX (i2);`, + }, + { + `select ''`, + `select 'a'`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleHint() + if rule.Item != "ARG.010" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.010") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleHint() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.011 +func TestRuleNot(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `select id from t where num not in(1,2,3);`, + `select id from t where num not like "a%"`, + }, + { + `select id from t where num in(1,2,3);`, + `select id from t where num like "a%"`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNot() + if rule.Item != "ARG.011" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.011") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNot() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.012 +func TestRuleInsertValues(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `INSERT INTO tb VALUES (1), (2)`, + `REPLACE INTO tb VALUES (1), (2)`, + }, + { + `INSERT INTO tb VALUES (1)`, + }, + } + oldMaxValueCount := common.Config.MaxValueCount + common.Config.MaxValueCount = 1 + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleInsertValues() + if rule.Item != "ARG.012" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.012") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleInsertValues() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Config.MaxValueCount = oldMaxValueCount + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SUB.002 +func TestRuleUNIONUsage(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select teacher_id as id,people_name as name from t1,t2 where t1.teacher_id=t2.people_id union select student_id as id,people_name as name from t1,t2 where t1.student_id=t2.people_id;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUNIONUsage() + if rule.Item != "SUB.002" { + t.Error("Rule not match:", rule.Item, "Expect : SUB.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SUB.003 +func TestRuleDistinctJoinUsage(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT DISTINCT c.c_id, c.c_name FROM c,e WHERE e.c_id = c.c_id;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDistinctJoinUsage() + if rule.Item != "SUB.003" { + t.Error("Rule not match:", rule.Item, "Expect : SUB.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SUB.005 +func TestRuleSubQueryLimit(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `SELECT * FROM staff WHERE name IN (SELECT NAME FROM customer ORDER BY name LIMIT 1)`, + }, + { + `select * from (select id from tbl limit 3) as foo`, + `select * from tbl where id in (select t.id from (select * from tbl limit 3)as t)`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSubQueryLimit() + if rule.Item != "SUB.005" { + t.Error("Rule not match:", rule.Item, "Expect : SUB.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSubQueryLimit() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SUB.006 +func TestRuleSubQueryFunctions(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `SELECT * FROM staff WHERE name IN (SELECT max(NAME) FROM customer)`, + }, + { + `select * from (select id from tbl limit 3) as foo`, + `select * from tbl where id in (select t.id from (select * from tbl limit 3)as t)`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSubQueryFunctions() + if rule.Item != "SUB.006" { + t.Error("Rule not match:", rule.Item, "Expect : SUB.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSubQueryFunctions() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SEC.002 +func TestRuleReadablePasswords(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `create table test(id int,name varchar(20) not null,password varchar(200)not null);`, + `alter table test add column password varchar(200) not null;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleReadablePasswords() + if rule.Item != "SEC.002" { + t.Error("Rule not match:", rule.Item, "Expect : SEC.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SEC.003 +func TestRuleDataDrop(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `delete from tb where a = b;`, + `truncate table tb;`, + `drop table tb;`, + `drop database db;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleDataDrop() + if rule.Item != "SEC.003" { + t.Error("Rule not match:", rule.Item, "Expect : SEC.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.001 +func TestCompareWithFunction(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `select id from t where substring(name,1,3)='abc';`, + `SELECT * FROM tbl WHERE UNIX_TIMESTAMP(loginTime) BETWEEN UNIX_TIMESTAMP('2018-11-16 09:46:00 +0800 CST') AND UNIX_TIMESTAMP('2018-11-22 00:00:00 +0800 CST')`, + }, + // TODO: 右侧使用函数比较 + { + `select id from t where 'abc'=substring(name,1,3);`, + `select id from t where col = (select 1)`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCompareWithFunction() + if rule.Item != "FUN.001" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCompareWithFunction() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// FUN.002 +func TestRuleCountStar(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `SELECT c3, COUNT(*) AS accounts FROM tab where c2 < 10000 GROUP BY c3 ORDER BY num;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCountStar() + if rule.Item != "FUN.002" { + t.Error("Rule not match:", rule.Item, "Expect : FUN.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// SEC.001 +func TestRuleTruncateTable(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `TRUNCATE TABLE tbl_name;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTruncateTable() + if rule.Item != "SEC.001" { + t.Error("Rule not match:", rule.Item, "Expect : SEC.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.005 +func TestRuleIn(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select id from t where num in(1,2,3);`, + `SELECT * FROM tbl WHERE col IN (NULL)`, + `SELECT * FROM tbl WHERE col NOT IN (NULL)`, + } + common.Config.MaxInCount = 0 + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIn() + if rule.Item != "ARG.005" && rule.Item != "ARG.004" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.005 OR ARG.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ARG.006 +func TestRuleIsNullIsNotNull(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select id from t where num is null;`, + `select id from t where num is not null;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIsNullIsNotNull() + if rule.Item != "ARG.006" { + t.Error("Rule not match:", rule.Item, "Expect : ARG.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.008 +func TestRuleVarcharVSChar(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `create table t1(id int,name char(20),last_time date);`, + `create table t1(id int,name binary(20),last_time date);`, + `alter table t1 add column id int, add column name binary(20), add column last_time date;`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleVarcharVSChar() + if rule.Item != "COL.008" { + t.Error("Rule not match:", rule.Item, "Expect : COL.008") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.003 +func TestRuleCreateDualTable(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "create table `dual`(id int, primary key (id));", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCreateDualTable() + if rule.Item != "TBL.003" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ALT.001 +func TestRuleAlterCharset(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `alter table tbl default character set 'utf8';`, + `alter table tbl default character set='utf8';`, + `ALTER TABLE t1 CHANGE a b BIGINT NOT NULL, default character set utf8`, + `ALTER TABLE t1 CHANGE a b BIGINT NOT NULL,default character set utf8`, + `ALTER TABLE tbl_name CHARACTER SET charset_name;`, + `ALTER TABLE t1 CHANGE a b BIGINT NOT NULL, character set utf8`, + `ALTER TABLE t1 CHANGE a b BIGINT NOT NULL,character set utf8`, + `alter table t1 convert to character set utf8 collate utf8_unicode_ci;`, + `alter table t1 default collate = utf8_unicode_ci;`, + }, + { + // 反面的例子 + `ALTER TABLE t MODIFY latin1_text_col TEXT CHARACTER SET utf8`, + `ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAlterCharset() + if rule.Item != "ALT.001" { + t.Error(sql, " Rule not match:", rule.Item, "Expect : ALT.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAlterCharset() + if rule.Item != "OK" { + t.Error(sql, " Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ALT.003 +func TestRuleAlterDropColumn(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `alter table film drop column title;`, + }, + { + // 反面的例子 + `ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAlterDropColumn() + if rule.Item != "ALT.003" { + t.Error(sql, " Rule not match:", rule.Item, "Expect : ALT.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAlterDropColumn() + if rule.Item != "OK" { + t.Error(sql, " Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// ALT.004 +func TestRuleAlterDropKey(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `alter table film drop primary key`, + `alter table film drop foreign key fk_film_language`, + }, + { + // 反面的例子 + `ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAlterDropKey() + if rule.Item != "ALT.004" { + t.Error(sql, " Rule not match:", rule.Item, "Expect : ALT.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAlterDropKey() + if rule.Item != "OK" { + t.Error(sql, " Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.012 +func TestRuleCantBeNull(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "CREATE TABLE `tbl` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` longblob, PRIMARY KEY (`id`));", + "alter TABLE `tbl` add column `c` longblob;", + "alter TABLE `tbl` add column `c` text;", + "alter TABLE `tbl` add column `c` blob;", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleCantBeNull() + if rule.Item != "COL.012" { + t.Error("Rule not match:", rule.Item, "Expect : COL.012") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.006 +func TestRuleTooManyKeyParts(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` longblob NOT NULL DEFAULT '', PRIMARY KEY (`id`));", + "alter TABLE `tb` add index idx_idx (`id`);", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + common.Config.MaxIdxColsCount = 0 + rule := q.RuleTooManyKeyParts() + if rule.Item != "KEY.006" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.005 +func TestRuleTooManyKeys(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "create table tbl ( a char(10), b int, primary key (`a`)) engine=InnoDB;", + "create table tbl ( a varchar(64) not null, b int, PRIMARY KEY (`a`), key `idx_a_b` (`a`,`b`)) engine=InnoDB", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + common.Config.MaxIdxCount = 0 + rule := q.RuleTooManyKeys() + if rule.Item != "KEY.005" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.007 +func TestRulePKNotInt(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "create table tbl ( a char(10), b int, primary key (`a`)) engine=InnoDB;", + "create table tbl ( a int, b int, primary key (`a`)) engine=InnoDB;", + "create table tbl ( a bigint, b int, primary key (`a`)) engine=InnoDB;", + "create table tbl ( a int unsigned, b int, primary key (`a`)) engine=InnoDB;", + "create table tbl ( a bigint unsigned, b int, primary key (`a`)) engine=InnoDB;", + }, + { + "CREATE TABLE tbl (a int unsigned auto_increment, b int, primary key(`a`)) engine=InnoDB;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePKNotInt() + if rule.Item != "KEY.007" && rule.Item != "KEY.001" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.007 OR KEY.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePKNotInt() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.008 +func TestRuleOrderByMultiDirection(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `SELECT col FROM tbl order by col desc, col2 asc`, + }, + { + `SELECT col FROM tbl order by col, col2`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOrderByMultiDirection() + if rule.Item != "KEY.008" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.008") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleOrderByMultiDirection() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.009 +func TestRuleUniqueKeyDup(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `ALTER TABLE customer ADD UNIQUE INDEX part_of_name (name(10));`, + `CREATE UNIQUE INDEX part_of_name ON customer (name(10));`, + }, + { + `ALTER TABLE tbl add INDEX idx_col (col);`, + `CREATE INDEX part_of_name ON customer (name(10));`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUniqueKeyDup() + if rule.Item != "KEY.009" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.009") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleUniqueKeyDup() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.013 +func TestRuleTimestampDefault(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE tbl( `id` bigint not null, `create_time` timestamp) ENGINE=InnoDB DEFAULT CHARSET=utf8;", + "ALTER TABLE t1 MODIFY b timestamp NOT NULL;", + }, + { + "CREATE TABLE tbl (`id` bigint not null, `update_time` timestamp default current_timestamp)", + "ALTER TABLE t1 MODIFY b timestamp NOT NULL default current_timestamp;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTimestampDefault() + if rule.Item != "COL.013" { + t.Error("Rule not match:", rule.Item, "Expect : COL.013") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTimestampDefault() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.004 +func TestRuleAutoIncrementInitNotZero(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + // 正面的例子 + { + "CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=13", + }, + // 反面的例子 + { + "CREATE TABLE `test1` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`))", + "CREATE TABLE `test1` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`)) auto_increment = 1", + "CREATE TABLE `test1` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`)) auto_increment = 1 DEFAULT CHARSET=latin1", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAutoIncrementInitNotZero() + if rule.Item != "TBL.004" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAutoIncrementInitNotZero() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.014 +func TestRuleColumnWithCharset(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + // 正面的例子 + { + "CREATE TABLE `tb2` ( `id` int(11) DEFAULT NULL, `col` char(10) CHARACTER SET utf8 DEFAULT NULL)", + "alter table tb2 change col col char(10) CHARACTER SET utf8 DEFAULT NULL;", + }, + // 反面的例子 + { + "CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` char(120) NOT NULL DEFAULT '', PRIMARY KEY (`id`))", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleColumnWithCharset() + if rule.Item != "COL.014" { + t.Error("Rule not match:", rule.Item, "Expect : COL.014") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleColumnWithCharset() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.005 +func TestRuleTableCharsetCheck(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "create table tbl (a int) DEFAULT CHARSET=latin1;", + "ALTER TABLE tbl CONVERT TO CHARACTER SET latin1;", + }, + { + "create table tlb (a int);", + "ALTER TABLE `tbl` add column a int, add column b int ;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTableCharsetCheck() + if rule.Item != "TBL.005" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.005") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTableCharsetCheck() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.015 +func TestRuleBlobDefaultValue(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` blob NOT NULL DEFAULT '', PRIMARY KEY (`id`));", + "alter table `tb` add column `c` blob NOT NULL DEFAULT '';", + }, + { + "CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` blob NOT NULL, PRIMARY KEY (`id`));", + "alter table `tb` add column `c` blob NOT NULL DEFAULT NULL;", + }, + } + + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleBlobDefaultValue() + if rule.Item != "COL.015" { + t.Error("Rule not match:", rule.Item, "Expect : COL.015") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleBlobDefaultValue() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.016 +func TestRuleIntPrecision(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE `tb` ( `id` int(1) );", + "CREATE TABLE `tb` ( `id` bigint(1) );", + "alter TABLE `tb` add column `id` bigint(1);", + "alter TABLE `tb` add column `id` int(1);", + }, + { + "CREATE TABLE `tb` ( `id` int(10));", + "CREATE TABLE `tb` ( `id` bigint(20));", + "alter TABLE `tb` add column `id` bigint(20);", + "alter TABLE `tb` add column `id` int(10);", + "CREATE TABLE `tb` ( `id` int);", + "alter TABLE `tb` add column `id` bigint;", + }, + } + + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIntPrecision() + if rule.Item != "COL.016" { + t.Error("Rule not match:", rule.Item, "Expect : COL.016") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIntPrecision() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.017 +func TestRuleVarcharLength(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE `tb` ( `id` varchar(4000) );", + "CREATE TABLE `tb` ( `id` varchar(3500) );", + "alter TABLE `tb` add column `id` varchar(3500);", + }, + { + "CREATE TABLE `tb` ( `id` varchar(1024));", + "CREATE TABLE `tb` ( `id` varchar(20));", + "alter TABLE `tb` add column `id` varchar(35);", + }, + } + + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleVarcharLength() + if rule.Item != "COL.017" { + t.Error("Rule not match:", rule.Item, "Expect : COL.017") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleVarcharLength() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// KEY.002 +func TestRuleNoOSCKey(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + // 正面的例子 + { + "CREATE TABLE tbl (a int, b int)", + }, + // 反面的例子 + { + "CREATE TABLE tbl (a int, primary key(`a`))", + "CREATE TABLE tbl (a int, unique key(`a`))", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoOSCKey() + if rule.Item != "KEY.002" { + t.Error("Rule not match:", rule.Item, "Expect : KEY.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleNoOSCKey() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.006 +func TestRuleTooManyFields(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "create table tbl (a int);", + } + + common.Config.MaxColCount = 0 + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleTooManyFields() + if rule.Item != "COL.006" { + t.Error("Rule not match:", rule.Item, "Expect : COL.006") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.002 +func TestRuleAllowEngine(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE tbl (a int) engine=MyISAM;", + "ALTER TABLE tbl engine=MyISAM;", + "CREATE TABLE tbl (a int);", + }, + { + "CREATE TABLE tbl (a int) engine = InnoDB;", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAllowEngine() + if rule.Item != "TBL.002" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAllowEngine() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// TBL.001 +func TestRulePartitionNotAllowed(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `CREATE TABLE trb3 (id INT, name VARCHAR(50), purchased DATE) PARTITION BY RANGE( YEAR(purchased) ) + ( + PARTITION p0 VALUES LESS THAN (1990), + PARTITION p1 VALUES LESS THAN (1995), + PARTITION p2 VALUES LESS THAN (2000), + PARTITION p3 VALUES LESS THAN (2005) + );`, + `ALTER TABLE t1 ADD PARTITION (PARTITION p3 VALUES LESS THAN (2002));`, + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RulePartitionNotAllowed() + if rule.Item != "TBL.001" { + t.Error("Rule not match:", rule.Item, "Expect : TBL.001") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// COL.003 +func TestRuleAutoIncUnsigned(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + "CREATE TABLE `tb` ( `id` int(10) NOT NULL AUTO_INCREMENT, `c` longblob, PRIMARY KEY (`id`));", + "ALTER TABLE `tbl` ADD COLUMN `id` int(10) NOT NULL AUTO_INCREMENT;", + } + for _, sql := range sqls { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleAutoIncUnsigned() + if rule.Item != "COL.003" { + t.Error("Rule not match:", rule.Item, "Expect : COL.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// STA.003 +func TestRuleIdxPrefix(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE tbl (a int, unique key `xx_a` (`a`));", + "CREATE TABLE tbl (a int, key `xx_a` (`a`));", + `ALTER TABLE tbl ADD INDEX xx_a (a)`, + `ALTER TABLE tbl ADD UNIQUE INDEX xx_a (a)`, + }, + { + `ALTER TABLE tbl ADD INDEX idx_a (a)`, + `ALTER TABLE tbl ADD UNIQUE INDEX uk_a (a)`, + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIdxPrefix() + if rule.Item != "STA.003" { + t.Error("Rule not match:", rule.Item, "Expect : STA.003") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleIdxPrefix() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// STA.004 +func TestRuleStandardName(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "CREATE TABLE `tbl-name` (a int);", + "CREATE TABLE `tbl `(a int)", + "CREATE TABLE t__bl (a int);", + }, + { + "CREATE TABLE tbl (a int)", + "CREATE TABLE `tbl`(a int)", + "CREATE TABLE `tbl` (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleStandardName() + if rule.Item != "STA.004" { + t.Error("Rule not match:", rule.Item, "Expect : STA.004") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleStandardName() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// STA.002 +func TestRuleSpaceAfterDot(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + "SELECT * FROM sakila. film", + "SELECT film. length FROM film", + }, + { + "SELECT * FROM sakila.film", + "SELECT film.length FROM film", + "SELECT * FROM t1, t2 WHERE t1.title = t2.title", + }, + } + for _, sql := range sqls[0] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSpaceAfterDot() + if rule.Item != "STA.002" { + t.Error("Rule not match:", rule.Item, "Expect : STA.002") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + + for _, sql := range sqls[1] { + q, err := NewQuery4Audit(sql) + if err == nil { + rule := q.RuleSpaceAfterDot() + if rule.Item != "OK" { + t.Error("Rule not match:", rule.Item, "Expect : OK") + } + } else { + t.Error("sqlparser.Parse Error:", err) + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +func TestRuleMySQLError(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + err := errors.New(`Received #1146 error from MySQL server: "can't xxxx"`) + if RuleMySQLError("ERR.002", err).Content != "" { + t.Error("Want: '', Bug get: ", err) + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +func TestMergeConflictHeuristicRules(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + tmpRules := make(map[string]Rule) + for item, val := range HeuristicRules { + tmpRules[item] = val + } + err := common.GoldenDiff(func() { + suggest := MergeConflictHeuristicRules(tmpRules) + var sortedSuggest []string + for item := range suggest { + sortedSuggest = append(sortedSuggest, item) + } + sort.Strings(sortedSuggest) + for _, item := range sortedSuggest { + pretty.Println(suggest[item]) + } + }, t.Name(), update) + if err != nil { + t.Error(err) + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/index.go b/vendor/github.com/XiaoMi/soar/advisor/index.go new file mode 100644 index 0000000000000000000000000000000000000000..0c00818eddc5ef96b2e0dc6018f028a4fc75a129 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/index.go @@ -0,0 +1,1130 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "fmt" + "strings" + + "github.com/XiaoMi/soar/ast" + "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/database" + "github.com/XiaoMi/soar/env" + + "github.com/dchest/uniuri" + "vitess.io/vitess/go/vt/sqlparser" +) + +const ( + // IndexNameMaxLength Ref. https://dev.mysql.com/doc/refman/8.0/en/identifiers.html + IndexNameMaxLength = 64 +) + +// IndexAdvisor 索引建议需要使用到的所有信息 +type IndexAdvisor struct { + vEnv *env.VirtualEnv // 线下虚拟测试环境(测试环境) + rEnv database.Connector // 线上真实环境 + Ast sqlparser.Statement // Vitess Parser生成的抽象语法树 + where []*common.Column // 所有where条件中用到的列 + whereEQ []*common.Column // where条件中可以加索引的等值条件列 + whereINEQ []*common.Column // where条件中可以加索引的非等值条件列 + groupBy []*common.Column // group by可以加索引列 + orderBy []*common.Column // order by可以加索引列 + joinCond [][]*common.Column // 由于join condition跨层级间索引不可共用,需要多一个维度用来维护层级关系 + IndexMeta map[string]map[string]*database.TableIndexInfo +} + +// IndexInfo 创建一条索引需要的信息 +type IndexInfo struct { + Name string `json:"name"` // 索引名称 + Database string `json:"database"` // 数据库名 + Table string `json:"table"` // 表名 + DDL string `json:"ddl"` // ALTER, CREATE 等类型的 DDL 语句 + ColumnDetails []*common.Column `json:"column_details"` // 列详情 +} + +// IndexAdvises IndexAdvises列表 +type IndexAdvises []IndexInfo + +// mergeAdvices 合并索引建议 +func mergeAdvices(dst []IndexInfo, src ...IndexInfo) IndexAdvises { + if len(src) == 0 { + return dst + } + + for _, newIdx := range src { + has := false + for _, idx := range dst { + if newIdx.DDL == idx.DDL { + common.Log.Debug("merge index %s and %s", idx.Name, newIdx.Name) + has = true + } + } + + if !has { + dst = append(dst, newIdx) + } + } + + return dst +} + +// NewAdvisor 构造一个 IndexAdvisor 的时候就会对其本身结构初始化 +// 获取 condition 中的等值条件、非等值条件,以及group by 、 order by信息 +func NewAdvisor(env *env.VirtualEnv, rEnv database.Connector, q Query4Audit) (*IndexAdvisor, error) { + common.Log.Debug("Enter: NewAdvisor(), Caller: %s", common.Caller()) + if common.Config.TestDSN.Disable { + return nil, fmt.Errorf("TestDSN is Disabled: %s", common.Config.TestDSN.Addr) + } + // DDL 检测 + switch stmt := q.Stmt.(type) { + case *sqlparser.DDL: + // 获取ast中用到的库表 + sqlMeta := ast.GetMeta(q.Stmt, nil) + for db := range sqlMeta { + dbRef := db + if db == "" { + dbRef = rEnv.Database + } + + // DDL 在 Env 初始化的时候已经执行过了 + if _, ok := env.TableMap[dbRef]; !ok { + env.TableMap[dbRef] = make(map[string]string) + } + + for _, tb := range sqlMeta[db].Table { + env.TableMap[dbRef][tb.TableName] = tb.TableName + } + } + + return nil, nil + + case *sqlparser.DBDDL: + // 忽略建库语句 + return nil, nil + + case *sqlparser.Use: + // 如果是use,切基础环境 + env.Database = env.DBHash(stmt.DBName.String()) + return nil, nil + } + + return &IndexAdvisor{ + vEnv: env, + rEnv: rEnv, + Ast: q.Stmt, + + // 所有的FindXXXXCols尽最大可能先排除不需要加索引的列,但由于元数据在此阶段尚未补齐,给出的列有可能也无法添加索引 + // 后续需要通过CompleteColumnsInfo + calcCardinality补全后再进一步判断 + joinCond: ast.FindJoinCols(q.Stmt), + whereEQ: ast.FindWhereEQ(q.Stmt), + whereINEQ: ast.FindWhereINEQ(q.Stmt), + groupBy: ast.FindGroupByCols(q.Stmt), + orderBy: ast.FindOrderByCols(q.Stmt), + where: ast.FindAllCols(q.Stmt, ast.WhereExpression), + IndexMeta: make(map[string]map[string]*database.TableIndexInfo), + }, nil +} + +/* + +关于如何添加索引: +在《Relational Database Index Design and the Optimizers》一书中,作者提出著名的的三星索引理论(Three-Star Index) + +To Qualify for the First Star: +Pick the columns from all equal predicates (WHERE COL = . . .). +Make these the first columns of the index—in any order. For CURSOR41, the three-star index will begin with +columns LNAME, CITY or CITY, LNAME. In both cases the index slice that must be scanned will be as thin as possible. + +To Qualify for the Second Star: +Add the ORDER BY columns. Do not change the order of these columns, but ignore columns that were already +picked in step 1. For example, if CURSOR41 had redundant columns in the ORDER BY, say ORDER BY LNAME, +FNAME or ORDER BY FNAME, CITY, only FNAME would be added in this step. When FNAME is the third index column, +the result table will be in the right order without sorting. The first FETCH call will return the row with +the smallest FNAME value. + +To Qualify for the Third Star: +Add all the remaining columns from the SELECT statement. The order of the columns added in this step +has no impact on the performance of the SELECT, but the cost of updates should be reduced by placing volatile +columns at the end. Now the index contains all the columns required for an index-only access path. + +索引添加算法正是以这个理想化索策略添为基础,尽可能的给予"三星"索引建议。 + +但又如《High Performance MySQL》一书中所说,索引并不总是最好的工具。只有当索引帮助存储引擎快速查找到记录带来的好处大于其 +带来的额外工作时,索引才是有效的。 + +因此,在三星索引理论的基础上引入启发式索引算法,在第二颗星的实现上做了部分改进,对于非等值条件只会添加散粒度最高的一列到索引中, +并基于总体列的使用情况作出判断,按需对order by、group by添加索引,由此来想`增强索引建议的通用性。 + +*/ + +// IndexAdvise 索引优化建议算法入口主函数 +// TODO 索引顺序该如何确定 +func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises { + // 支持不依赖DB的索引建议分析 + if common.Config.TestDSN.Disable { + // 未开启Env原数据依赖,信息不全的情况下可能会给予错误的索引建议,请人工进行核查。 + common.Log.Warn("TestDSN.Disable = true") + } + + // 检查否是否含有子查询 + subQueries := ast.FindSubquery(0, idxAdv.Ast) + var subQueryAdvises []IndexInfo + // 含有子查询对子查询进行单独评审,子查询评审建议报错忽略 + if len(subQueries) > 0 { + for _, subSQL := range subQueries { + stmt, err := sqlparser.Parse(subSQL) + if err != nil { + continue + } + q := Query4Audit{ + Query: subSQL, + Stmt: stmt, + } + subIdxAdv, _ := NewAdvisor(idxAdv.vEnv, idxAdv.rEnv, q) + subQueryAdvises = append(subQueryAdvises, subIdxAdv.IndexAdvise()...) + } + } + + // 变量初始化,用于存放索引信息,按照db.tb.[cols]组织 + indexList := make(map[string]map[string][]*common.Column) + + // 为用到的每一列填充库名,表名等信息 + var joinCond [][]*common.Column + for _, joinCols := range idxAdv.joinCond { + joinCond = append(joinCond, CompleteColumnsInfo(idxAdv.Ast, joinCols, idxAdv.vEnv)) + } + idxAdv.joinCond = joinCond + + idxAdv.where = CompleteColumnsInfo(idxAdv.Ast, idxAdv.where, idxAdv.vEnv) + idxAdv.whereEQ = CompleteColumnsInfo(idxAdv.Ast, idxAdv.whereEQ, idxAdv.vEnv) + idxAdv.whereINEQ = CompleteColumnsInfo(idxAdv.Ast, idxAdv.whereINEQ, idxAdv.vEnv) + idxAdv.groupBy = CompleteColumnsInfo(idxAdv.Ast, idxAdv.groupBy, idxAdv.vEnv) + idxAdv.orderBy = CompleteColumnsInfo(idxAdv.Ast, idxAdv.orderBy, idxAdv.vEnv) + + // 只要在开启使用env元数据的时候才会计算散粒度 + if !common.Config.TestDSN.Disable { + // 计算joinCond, whereEQ, whereINEQ用到的每一列的散粒度,并排序,方便后续添加复合索引 + // groupBy, orderBy列按书写顺序给索引建议,不需要按散粒度排序 + idxAdv.calcCardinality(idxAdv.whereEQ) + idxAdv.calcCardinality(idxAdv.whereINEQ) + idxAdv.calcCardinality(idxAdv.orderBy) + idxAdv.calcCardinality(idxAdv.groupBy) + + for i, joinCols := range idxAdv.joinCond { + idxAdv.calcCardinality(joinCols) + joinCols = common.ColumnSort(joinCols) + idxAdv.joinCond[i] = joinCols + } + + // 根据散粒度进行排序 + // 对所有列进行排序,按散粒度由大到小排序 + idxAdv.whereEQ = common.ColumnSort(idxAdv.whereEQ) + idxAdv.whereINEQ = common.ColumnSort(idxAdv.whereINEQ) + idxAdv.orderBy = common.ColumnSort(idxAdv.orderBy) + idxAdv.groupBy = common.ColumnSort(idxAdv.groupBy) + + } + + // 是否指定Where条件,打标签 + hasWhere := false + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch where := node.(type) { + case *sqlparser.Subquery: + return false, nil + case *sqlparser.Where: + if where != nil { + hasWhere = true + } + } + return true, nil + }, idxAdv.Ast) + common.LogIfError(err, "") + // 获取哪些列被忽略 + var ignore []*common.Column + usedCols := append(idxAdv.whereINEQ, idxAdv.whereEQ...) + + for _, whereCol := range idxAdv.where { + isUsed := false + for _, used := range usedCols { + if whereCol.Equal(used) { + isUsed = true + } + } + + if !isUsed { + common.Log.Debug("column %s in `%s`.`%s` will ignore when adding index", whereCol.DB, whereCol.Table, whereCol.Name) + ignore = append(ignore, whereCol) + } + + } + + // 索引优化算法入口,从这里开始放大招 + if hasWhere { + // 有Where条件的先分析 等值条件 + for _, index := range idxAdv.whereEQ { + // 对应列在前面已经按散粒度由大到小排序好了 + mergeIndex(indexList, index) + } + // 若存在非等值查询条件,可以给第一个非等值条件添加索引 + if len(idxAdv.whereINEQ) > 0 { + mergeIndex(indexList, idxAdv.whereINEQ[0]) + } + // 有WHERE条件,但 WHERE 条件未能给出索引建议就不能再加 GROUP BY 和 ORDER BY 建议了 + if len(ignore) == 0 { + // 没有非等值查询条件时可以再为 GroupBy 和 OrderBy 添加索引 + for _, index := range idxAdv.groupBy { + mergeIndex(indexList, index) + } + + // OrderBy + // 没有 GroupBy 时可以为 OrderBy 加索引 + if len(idxAdv.groupBy) == 0 { + for _, index := range idxAdv.orderBy { + mergeIndex(indexList, index) + } + } + } + } else { + // 未指定 Where 条件的,只需要 GroupBy 和 OrderBy 的索引建议 + for _, index := range idxAdv.groupBy { + mergeIndex(indexList, index) + } + + // OrderBy + // 没有GroupBy 时可以为 OrderBy 加索引 + // 没有 where 条件时 OrderBy 的索引仅能够在索引覆盖的情况下被使用 + + // if len(idxAdv.groupBy) == 0 { + // for _, index := range idxAdv.orderBy { + // mergeIndex(indexList, index) + // } + // } + } + + // 开始整合索引信息,添加索引 + var indexes []IndexInfo + + // 为join添加索引 + // 获取 join condition 中需要加索引的表有哪些 + defaultDB := "" + if !common.Config.TestDSN.Disable { + defaultDB = idxAdv.vEnv.RealDB(idxAdv.vEnv.Database) + } + if !common.Config.OnlineDSN.Disable { + defaultDB = idxAdv.rEnv.Database + } + + // 根据join table的信息给予优化建议 + joinTableMeta := ast.FindJoinTable(idxAdv.Ast, nil).SetDefault(idxAdv.rEnv.Database).SetDefault(defaultDB) + indexes = mergeAdvices(indexes, idxAdv.buildJoinIndex(joinTableMeta)...) + + if common.Config.TestDSN.Disable || common.Config.OnlineDSN.Disable { + // 无 env 环境下只提供单列索引,无法确定 table 时不给予优化建议 + // 仅有 table 信息时给出的建议不包含 DB 信息 + indexes = mergeAdvices(indexes, idxAdv.buildIndexWithNoEnv(indexList)...) + } else { + // 给出尽可能详细的索引建议 + indexes = mergeAdvices(indexes, idxAdv.buildIndex(indexList)...) + } + + indexes = mergeAdvices(indexes, subQueryAdvises...) + + // 在开启 env 的情况下,检查数据库版本,字段类型,索引总长度 + indexes = idxAdv.idxColsTypeCheck(indexes) + + // 在开启 env 的情况下,会对索引进行检查,对全索引进行过滤 + // 在前几步都不会对 idx 生成 DDL 语句,DDL语句在这里生成 + return idxAdv.mergeIndexes(indexes) +} + +// idxColsTypeCheck 对超长的字段添加前缀索引,剔除无法添索引字段的列 +// TODO: 暂不支持 fulltext 索引, +func (idxAdv *IndexAdvisor) idxColsTypeCheck(idxList []IndexInfo) []IndexInfo { + if common.Config.TestDSN.Disable { + return rmSelfDupIndex(idxList) + } + + var indexes []IndexInfo + + for _, idx := range idxList { + var newCols []*common.Column + var newColInfo []string + // 索引总长度 + idxBytesTotal := 0 + isOverFlow := false + for _, col := range idx.ColumnDetails { + // 获取字段 bytes + bytes := col.GetDataBytes(common.Config.OnlineDSN.Version) + tmpCol := col.Name + overFlow := 0 + // 加上该列后是否索引长度过长 + if bytes < 0 { + // bytes < 0 说明字段的长度是无法计算的 + common.Log.Warning("%s.%s data type not support %s, can't add index", + col.Table, col.Name, col.DataType) + continue + } + + // idx bytes over flow + if total := idxBytesTotal + bytes; total > common.Config.MaxIdxBytes { + + common.Log.Debug("bytes: %d, idxBytesTotal: %d, total: %d, common.Config.MaxIdxBytes: %d", + bytes, idxBytesTotal, total, common.Config.MaxIdxBytes) + + overFlow = total - common.Config.MaxIdxBytes + isOverFlow = true + + } else { + idxBytesTotal = total + } + + // common.Config.MaxIdxColBytes 默认大小 767 + if bytes > common.Config.MaxIdxBytesPerColumn || isOverFlow { + // In 5.6, you may not include a column that equates to + // bigger than 767 bytes: VARCHAR(255) CHARACTER SET utf8 or VARCHAR(191) CHARACTER SET utf8mb4. + // In 5.7 you may not include a column that equates to + // bigger than 3072 bytes. + + // v : 在 col.Character 字符集下每个字符占用 v bytes + v, ok := common.CharSets[strings.ToLower(col.Character)] + if !ok { + // 找不到对应字符集,不添加索引 + // 如果出现不认识的字符集,认为每个字符占用4个字节 + common.Log.Warning("%s.%s(%s) charset not support yet %s, use default 4 bytes length", + col.Table, col.Name, col.DataType, col.Character) + v = 4 + } + + // 保留两个字节的安全余量 + length := (common.Config.MaxIdxBytesPerColumn - 2) / v + if isOverFlow { + // 在索引中添加该列会导致索引长度过长,建议根据需求转换为合理的前缀索引 + // _OPR_SPLIT_ 是自定的用于后续处理的特殊分隔符 + common.Log.Warning("adding index '%s(%s)' to table '%s' causes the index to be too long, overflow is %d", + col.Name, col.DataType, col.Table, overFlow) + tmpCol += fmt.Sprintf("_OPR_SPLIT_(N)") + } else { + // 索引没有过长,可以加一个最长的前缀索引 + common.Log.Warning("index column too large: %s.%s --> %s.%s(%d), data type: %s", + col.Table, col.Name, col.Table, tmpCol, length, col.DataType) + tmpCol += fmt.Sprintf("_OPR_SPLIT_(%d)", length) + } + + } + + newCols = append(newCols, col) + newColInfo = append(newColInfo, tmpCol) + } + + // 为新索引重建索引语句 + idxName := "idx_" + idxCols := "" + for i, newCol := range newColInfo { + // 对名称和可能存在的长度进行拼接 + // 用等号进行分割 + tmp := strings.Split(newCol, "_OPR_SPLIT_") + idxName += tmp[0] + if len(tmp) > 1 { + idxCols += tmp[0] + "`" + tmp[1] + } else { + idxCols += tmp[0] + "`" + } + + if i+1 < len(newColInfo) { + idxName += "_" + idxCols += ",`" + } + } + + // 索引名称最大长度64 + if len(idxName) > IndexNameMaxLength { + common.Log.Warn("index '%s' name large than IndexNameMaxLength", idxName) + idxName = strings.TrimRight(idxName[:IndexNameMaxLength], "_") + } + + // 新的alter语句 + newDDL := fmt.Sprintf("alter table `%s`.`%s` add index `%s` (`%s)", idxAdv.vEnv.RealDB(idx.Database), + idx.Table, idxName, idxCols) + + // 将筛选改造后的索引信息信息加入到新的索引列表中 + idx.ColumnDetails = newCols + idx.DDL = newDDL + indexes = append(indexes, idx) + } + + return indexes +} + +// mergeIndexes 与线上环境对比,将给出的索引建议进行去重 +func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo { + // TODO 暂不支持前缀索引去重 + if common.Config.TestDSN.Disable { + return rmSelfDupIndex(idxList) + } + + var indexes []IndexInfo + for _, idx := range idxList { + // 将 DB 替换成 vEnv 中的数据库名称 + dbInVEnv := idx.Database + if _, ok := idxAdv.vEnv.DBRef[idx.Database]; ok { + dbInVEnv = idxAdv.vEnv.DBRef[idx.Database] + } + + // 检测索引添加的表是否是视图 + if idxAdv.vEnv.IsView(idx.Table) { + common.Log.Info("%s.%s is a view. no need indexed", idx.Database, idx.Table) + continue + } + + // 检测是否存在重复索引 + indexMeta := idxAdv.IndexMeta[dbInVEnv][idx.Table] + isExisted := false + + // 检测无索引列的情况 + if len(idx.ColumnDetails) < 1 { + continue + } + + if existedIndexes := indexMeta.FindIndex(database.IndexColumnName, idx.ColumnDetails[0].Name); len(existedIndexes) > 0 { + for _, existedIdx := range existedIndexes { + // flag: 用于标记已存在的索引是否是约束条件 + isConstraint := false + + var cols []string + var colsDetail []*common.Column + + // 把已经存在的 key 摘出来遍历一遍对比是否是包含关系 + for _, col := range indexMeta.FindIndex(database.IndexKeyName, existedIdx.KeyName) { + cols = append(cols, col.ColumnName) + colsDetail = append(colsDetail, &common.Column{ + Name: col.ColumnName, + Table: idx.Table, + DB: idx.ColumnDetails[0].DB, + }) + } + + // 判断已存在的索引是否属于约束条件(唯一索引、主键) + // 这里可以忽略是否含有外键的情况,因为索引已经重复了,添加了新索引后原先重复的索引是可以删除的。 + if existedIdx.NonUnique == 0 { + common.Log.Debug("%s.%s表%s为约束条件", dbInVEnv, idx.Table, existedIdx.KeyName) + isConstraint = true + } + + // 如果已存在的索引与索引建议存在重叠,则说明无需添加新索引或可能需要给出删除索引的建议 + if common.IsColsPart(colsDetail, idx.ColumnDetails) { + idxName := existedIdx.KeyName + // 如果已经存在的索引包含需要添加的索引,则无需添加 + if len(colsDetail) >= len(idx.ColumnDetails) { + common.Log.Info(" `%s`.`%s` %s already had a index `%s`", + idx.Database, idx.Table, strings.Join(cols, ","), idxName) + isExisted = true + continue + } + + // 库、表、列名需要用反撇转义 + // TODO: 关于外键索引去重的优雅解决方案 + if !isConstraint { + if common.Config.AllowDropIndex { + alterSQL := fmt.Sprintf("alter table `%s`.`%s` drop index `%s`", idx.Database, idx.Table, idxName) + indexes = append(indexes, IndexInfo{ + Name: idxName, + Database: idx.Database, + Table: idx.Table, + DDL: alterSQL, + ColumnDetails: colsDetail, + }) + } else { + common.Log.Warning("In table `%s`, the new index of column `%s` contains index `%s`,"+ + " maybe you could drop one of them.", existedIdx.Table, + strings.Join(cols, ","), idxName) + } + } + } + } + } + + if !isExisted { + // 检测索引名称是否重复? + if existedIndexes := indexMeta.FindIndex(database.IndexKeyName, idx.Name); len(existedIndexes) > 0 { + var newName string + idxSuffix := getRandomIndexSuffix() + if len(idx.Name) < IndexNameMaxLength-len(idxSuffix) { + newName = idx.Name + idxSuffix + } else { + newName = idx.Name[:IndexNameMaxLength-len(idxSuffix)] + idxSuffix + } + + common.Log.Warning("duplicate index name '%s', new name is '%s'", idx.Name, newName) + idx.DDL = strings.Replace(idx.DDL, idx.Name, newName, -1) + idx.Name = newName + } + + // 添加合并 + indexes = mergeAdvices(indexes, idx) + } + + } + + // 对索引进行去重 + return rmSelfDupIndex(indexes) +} + +// getRandomIndexSuffix format: _xxxx, length: 5 +func getRandomIndexSuffix() string { + return fmt.Sprintf("_%s", uniuri.New()[:4]) +} + +// rmSelfDupIndex 去重传入的[]IndexInfo中重复的索引 +func rmSelfDupIndex(indexes []IndexInfo) []IndexInfo { + var resultIndex []IndexInfo + tmpIndexList := indexes + for _, a := range indexes { + tmp := a + for i, b := range tmpIndexList { + if common.IsColsPart(tmp.ColumnDetails, b.ColumnDetails) && tmp.Name != b.Name { + if len(b.ColumnDetails) > len(tmp.ColumnDetails) { + common.Log.Debug("remove duplicate index: %s", tmp.Name) + tmp = b + } + + if i < len(tmpIndexList) { + tmpIndexList = append(tmpIndexList[:i], tmpIndexList[i+1:]...) + } else { + tmpIndexList = tmpIndexList[:i] + } + + } + } + resultIndex = mergeAdvices(resultIndex, tmp) + } + + return resultIndex +} + +// buildJoinIndex 检查Join中使用的库表是否需要添加索引并给予索引建议 +func (idxAdv *IndexAdvisor) buildJoinIndex(meta common.Meta) []IndexInfo { + var indexes []IndexInfo + for _, IndexCols := range idxAdv.joinCond { + // 如果该列的库表为join condition中需要添加索引的库表 + indexColsList := make(map[string]map[string][]*common.Column) + for _, col := range IndexCols { + mergeIndex(indexColsList, col) + + } + + if common.Config.TestDSN.Disable || common.Config.OnlineDSN.Disable { + indexes = mergeAdvices(indexes, idxAdv.buildIndexWithNoEnv(indexColsList)...) + continue + } + + indexes = mergeAdvices(indexes, idxAdv.buildIndex(indexColsList)...) + } + return indexes +} + +// buildIndex 尽可能的将 map[string]map[string][]*common.Column 转换成 []IndexInfo +// 此处不判断索引是否重复 +func (idxAdv *IndexAdvisor) buildIndex(idxList map[string]map[string][]*common.Column) []IndexInfo { + var indexes []IndexInfo + for db, tbs := range idxList { + for tb, cols := range tbs { + + // 单个索引中含有的列收 config 中参数限制 + if len(cols) > common.Config.MaxIdxColsCount { + cols = cols[:common.Config.MaxIdxColsCount] + } + + var colNames []string + for _, col := range cols { + if col.DB == "" || col.Table == "" { + common.Log.Warn("can not get the meta info of column '%s'", col.Name) + continue + } + colNames = append(colNames, col.Name) + } + + if len(colNames) == 0 { + continue + } + + idxName := "idx_" + strings.Join(colNames, "_") + + // 索引名称最大长度64 + if len(idxName) > IndexNameMaxLength { + common.Log.Warn("index '%s' name large than IndexNameMaxLength", idxName) + idxName = strings.TrimRight(idxName[:IndexNameMaxLength], "_") + } + + alterSQL := fmt.Sprintf("alter table `%s`.`%s` add index `%s` (`%s`)", idxAdv.vEnv.RealDB(db), tb, + idxName, strings.Join(colNames, "`,`")) + + indexes = append(indexes, IndexInfo{ + Name: idxName, + Database: idxAdv.vEnv.RealDB(db), + Table: tb, + DDL: alterSQL, + ColumnDetails: cols, + }) + } + } + return indexes +} + +// buildIndexWithNoEnv 忽略原数据,给予最基础的索引 +func (idxAdv *IndexAdvisor) buildIndexWithNoEnv(indexList map[string]map[string][]*common.Column) []IndexInfo { + // 如果不获取数据库原信息,则不去判断索引是否重复,且只给单列加索引 + var indexes []IndexInfo + for _, tableIndex := range indexList { + for _, indexCols := range tableIndex { + for _, col := range indexCols { + if col.Table == "" { + common.Log.Warn("can not get the meta info of column '%s'", col.Name) + continue + } + idxName := "idx_" + col.Name + // 库、表、列名需要用反撇转义 + alterSQL := fmt.Sprintf("alter table `%s`.`%s` add index `%s` (`%s`)", idxAdv.vEnv.RealDB(col.DB), col.Table, idxName, col.Name) + if col.DB == "" { + alterSQL = fmt.Sprintf("alter table `%s` add index `%s` (`%s`)", col.Table, idxName, col.Name) + } + + indexes = append(indexes, IndexInfo{ + Name: idxName, + Database: idxAdv.vEnv.RealDB(col.DB), + Table: col.Table, + DDL: alterSQL, + ColumnDetails: []*common.Column{col}, + }) + } + + } + } + return indexes +} + +// mergeIndex 将索引用到的列去重后合并到一起 +func mergeIndex(idxList map[string]map[string][]*common.Column, column *common.Column) { + db := column.DB + tb := column.Table + if idxList[db] == nil { + idxList[db] = make(map[string][]*common.Column) + } + if idxList[db][tb] == nil { + idxList[db][tb] = make([]*common.Column, 0) + } + + // 去除重复列Append + exist := false + for _, cl := range idxList[db][tb] { + if cl.Name == column.Name { + exist = true + } + } + if !exist { + idxList[db][tb] = append(idxList[db][tb], column) + } +} + +// CompleteColumnsInfo 补全索引可能会用到列的所属库名、表名等信息 +func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *env.VirtualEnv) []*common.Column { + // 如果传过来的列是空的,没必要跑逻辑 + if len(cols) == 0 { + return cols + } + + // 从 Ast 中拿到 DBStructure,包含所有表的相关信息 + dbs := ast.GetMeta(stmt, nil) + + // 此处生成的 meta 信息中不应该含有""db的信息,若 DB 为空则认为是已传入的 db 为默认 db 并进行信息补全 + // BUG Fix: + // 修补 dbs 中空 DB 的导致后续补全列信息时无法获取正确 table 名称的问题 + if _, ok := dbs[""]; ok { + dbs[env.Database] = dbs[""] + delete(dbs, "") + } + + tableCount := 0 + for db := range dbs { + for tb := range dbs[db].Table { + if tb != "" { + tableCount++ + } + } + } + + var noEnvTmp []*common.Column + for _, col := range cols { + for db := range dbs { + // 对每一列进行比对,将别名转换为正确的名称 + find := false + for _, tb := range dbs[db].Table { + for _, tbAlias := range tb.TableAliases { + if col.Table != "" && col.Table == tbAlias { + common.Log.Debug("column '%s' prefix change: %s --> %s", col.Name, col.Table, tb.TableName) + find = true + col.Table = tb.TableName + col.DB = db + break + } + } + if find { + break + } + + } + + // 如果不依赖env环境,利用ast中包含的信息推理列的库表信息 + if common.Config.TestDSN.Disable { + if tableCount == 1 { + for _, tb := range dbs[db].Table { + col.Table = tb.TableName + + // 因为tableMeta是按照库表组织的树状结构,db变量贯穿全局 + // 只有在最终赋值前才能根据逻辑变更补全 + if db == "" { + db = env.Database + } + col.DB = db + } + } + + // 如果SQL中含有的表大于一个,则使用的列中必须含有前缀,不然无法判断该列属于哪个表 + // 如果某一列未含有前缀信息,则认为两张表中都含有该列,需要由人去判断 + if tableCount > 1 { + if col.Table == "" { + for _, tb := range dbs[db].Table { + if tb.TableName == "" { + common.Log.Warn("can not get the meta info of column '%s'", col.Name) + } + + if db == "" { + db = env.RealDB(env.Database) + } + col.Table = tb.TableName + col.DB = db + + tmp := *col + tmp.Table = tb.TableName + tmp.DB = db + + noEnvTmp = append(noEnvTmp, &tmp) + } + } + + if col.DB == "" { + if db == "" { + db = env.Database + } + col.DB = db + } + } + + break + } + + // 将已经获取到正确表信息的列信息带入到env中,利用show columns where table 获取库表信息 + // 此出会传入之前从ast中,该 db 下获取的所有表来作为where限定条件, + // 防止与SQL无关的库表信息干扰准确性 + // 此处传入的是测试环境,DB 是经过变换的,所以在寻找列名的时候需要将 DB 名称转换成测试环境中经过 hash 的 DB 名称 + // 不然会找不到col的信息 + realCols, err := env.FindColumn(col.Name, env.DBHash(db), dbs.Tables(db)...) + if err != nil { + common.Log.Warn("%v", err) + continue + } + + // 对比 column 信息中的表名与从 env 中获取的库表名的一致性 + for _, realCol := range realCols { + if col.Name == realCol.Name { + // 如果查询到了列名一致,但从 ast 中获取的列的前缀与 env 中的表信息不符 + // 1.存在一个同名列,但不同表,该情况下忽略 + // 2.存在一个未正确转换的别名(如表名为),该情况下修正,大概率是正确的 + if col.Table != "" && col.Table != realCol.Table { + has, _ := env.FindColumn(col.Name, env.DBHash(db), col.Table) + if len(has) > 0 { + realCol = has[0] + } + } + + col.DataType = realCol.DataType + col.Table = realCol.Table + col.DB = env.RealDB(realCol.DB) + col.Character = realCol.Character + col.Collation = realCol.Collation + + } + } + } + + } + + // 如果不依赖env环境,将可能存在的列也加入到索引预处理列表中 + if common.Config.TestDSN.Disable { + cols = append(cols, noEnvTmp...) + } + + return cols +} + +// calcCardinality 计算每一列的散粒度 +// 这个函数需要在补全列的库表信息之后再调用,否则无法确定要计算列的归属 +func (idxAdv *IndexAdvisor) calcCardinality(cols []*common.Column) []*common.Column { + common.Log.Debug("Enter: calcCardinality(), Caller: %s", common.Caller()) + tmpDB := *idxAdv.vEnv + for _, col := range cols { + // 补全对应列的库->表->索引信息到IndexMeta + // 这将在后面用于判断某一列是否为主键或单列唯一索引,快速返回散粒度 + if col.DB == "" { + col.DB = idxAdv.vEnv.Database + } + realDB := idxAdv.vEnv.DBHash(col.DB) + if idxAdv.IndexMeta[realDB] == nil { + idxAdv.IndexMeta[realDB] = make(map[string]*database.TableIndexInfo) + } + + if idxAdv.IndexMeta[realDB][col.Table] == nil { + tmpDB.Database = realDB + indexInfo, err := tmpDB.ShowIndex(col.Table) + if err != nil { + // 如果是不存在的表就会报错,报错的可能性有三个: + // 1.数据库错误 2.表不存在 3.临时表 + // 而这三种错误都是不需要在这一层关注的,直接跳过 + common.Log.Debug("calcCardinality error: %v", err) + continue + } + + // 将获取的索引信息以db.tb 维度组织到 IndexMeta 中 + idxAdv.IndexMeta[realDB][col.Table] = indexInfo + } + + // 检查对应列是否为主键或单列唯一索引,如果满足直接返回1,不再重复计算,提高效率 + // 多列复合唯一索引不能跳过计算,单列普通索引不能跳过计算 + for _, index := range idxAdv.IndexMeta[realDB][col.Table].IdxRows { + // 根据索引的名称判断该索引包含的列数,列数大于1即为复合索引 + columnCount := len(idxAdv.IndexMeta[realDB][col.Table].FindIndex(database.IndexKeyName, index.KeyName)) + if col.Name == index.ColumnName { + // 主键、唯一键 无需计算散粒度 + if (index.KeyName == "PRIMARY" || index.NonUnique == 0) && columnCount == 1 { + common.Log.Debug("column '%s' is PK or UK, no need to calculate cardinality.", col.Name) + col.Cardinality = 1 + break + } + } + + } + + // 给非 PRIMARY、UNIQUE 的列计算散粒度 + if col.Cardinality != 1 { + col.Cardinality = idxAdv.vEnv.ColumnCardinality(col.Table, col.Name) + } + } + + return cols +} + +// Format 用于格式化输出索引建议 +func (idxAdvs IndexAdvises) Format() map[string]Rule { + rulesMap := make(map[string]Rule) + number := 1 + rules := make(map[string]*Rule) + sqls := make(map[string][]string) + + for _, advise := range idxAdvs { + advKey := advise.Database + advise.Table + + if _, ok := sqls[advKey]; !ok { + sqls[advKey] = make([]string, 0) + } + + sqls[advKey] = append(sqls[advKey], advise.DDL) + + if _, ok := rules[advKey]; !ok { + summary := fmt.Sprintf("为%s库的%s表添加索引", advise.Database, advise.Table) + if advise.Database == "" { + summary = fmt.Sprintf("为%s表添加索引", advise.Table) + } + + rules[advKey] = &Rule{ + Summary: summary, + Content: "", + Severity: "L2", + } + } + + for _, col := range advise.ColumnDetails { + // 为了更好地显示效果 + if common.Config.Sampling { + cardinal := fmt.Sprintf("%0.2f", col.Cardinality*100) + if cardinal != "0.00" { + rules[advKey].Content += fmt.Sprintf("为列%s添加索引,散粒度为: %s%%; ", + col.Name, cardinal) + } + } else { + rules[advKey].Content += fmt.Sprintf("为列%s添加索引;", col.Name) + } + } + // 清理多余的标点 + rules[advKey].Content = strings.Trim(rules[advKey].Content, common.Config.Delimiter) + } + + for adv := range rules { + key := fmt.Sprintf("IDX.%03d", number) + ddl := ast.MergeAlterTables(sqls[adv]...) + // 由于传入合并的SQL都是一张表的,所以一定只会输出一条ddl语句 + for _, v := range ddl { + rules[adv].Case = v + } + + // set item + rules[adv].Item = key + + rulesMap[key] = *rules[adv] + + number++ + } + + return rulesMap +} + +// HeuristicCheck 依赖数据字典的启发式检查 +// IndexAdvisor会构建测试环境和数据字典,所以放在这里实现 +func (idxAdv *IndexAdvisor) HeuristicCheck(q Query4Audit) map[string]Rule { + var rule Rule + heuristicSuggest := make(map[string]Rule) + if common.Config.OnlineDSN.Disable && common.Config.TestDSN.Disable { + return heuristicSuggest + } + + ruleFuncs := []func(*IndexAdvisor) Rule{ + (*IndexAdvisor).RuleImplicitConversion, // ARG.003 + // (*IndexAdvisor).RuleImpossibleOuterJoin, // TODO: JOI.003, JOI.004 + (*IndexAdvisor).RuleGroupByConst, // CLA.004 + (*IndexAdvisor).RuleOrderByConst, // CLA.005 + (*IndexAdvisor).RuleUpdatePrimaryKey, // CLA.016 + } + + for _, f := range ruleFuncs { + rule = f(idxAdv) + if rule.Item != "OK" { + heuristicSuggest[rule.Item] = rule + } + } + return heuristicSuggest +} + +// DuplicateKeyChecker 对所有用到的库表检查是否存在重复索引 +func DuplicateKeyChecker(conn *database.Connector, databases ...string) map[string]Rule { + common.Log.Debug("Enter: DuplicateKeyChecker, Caller: %s", common.Caller()) + // 复制一份online connector,防止环境切换影响其他功能的使用 + tmpOnline := *conn + ruleMap := make(map[string]Rule) + number := 1 + + // 错误处理,用于汇总所有的错误 + funcErrCheck := func(err error) { + if err != nil { + if sug, ok := ruleMap["ERR.003"]; ok { + sug.Content += fmt.Sprintf("; %s", err.Error()) + } else { + ruleMap["ERR.003"] = Rule{ + Item: "ERR.003", + Severity: "L8", + Content: err.Error(), + } + } + } + } + + // 不指定 DB 的时候检查 online dsn 中的 DB + if len(databases) == 0 { + databases = append(databases, tmpOnline.Database) + } + + for _, db := range databases { + // 获取所有的表 + tmpOnline.Database = db + tables, err := tmpOnline.ShowTables() + + if err != nil { + funcErrCheck(err) + if !common.Config.DryRun { + return ruleMap + } + } + + for _, tb := range tables { + // 获取表中所有的索引 + idxMap := make(map[string][]*common.Column) + idxInfo, err := tmpOnline.ShowIndex(tb) + if err != nil { + funcErrCheck(err) + if !common.Config.DryRun { + return ruleMap + } + } + + // 枚举所有的索引信息,提取用到的列 + for _, idx := range idxInfo.IdxRows { + if _, ok := idxMap[idx.KeyName]; !ok { + idxMap[idx.KeyName] = make([]*common.Column, 0) + for _, col := range idxInfo.FindIndex(database.IndexKeyName, idx.KeyName) { + idxMap[idx.KeyName] = append(idxMap[idx.KeyName], &common.Column{ + Name: col.ColumnName, + Table: tb, + DB: db, + }) + } + } + } + + // 对索引进行重复检查 + hasDup := false + content := "" + + for k1, cl1 := range idxMap { + for k2, cl2 := range idxMap { + if k1 != k2 && common.IsColsPart(cl1, cl2) { + hasDup = true + col1Str := common.JoinColumnsName(cl1, ", ") + col2Str := common.JoinColumnsName(cl2, ", ") + content += fmt.Sprintf("索引%s(%s)与%s(%s)重复;", k1, col1Str, k2, col2Str) + common.Log.Debug(" %s.%s has duplicate index %s(%s) <--> %s(%s)", db, tb, k1, col1Str, k2, col2Str) + } + } + delete(idxMap, k1) + } + + // TODO 重复索引检查添加对约束及索引的判断,提供重复索引的删除功能 + if hasDup { + tmpOnline.Database = db + ddl, _ := tmpOnline.ShowCreateTable(tb) + key := fmt.Sprintf("IDX.%03d", number) + ruleMap[key] = Rule{ + Item: key, + Severity: "L2", + Summary: fmt.Sprintf("%s.%s存在重复的索引", db, tb), + Content: content, + Case: ddl, + } + number++ + } + } + } + + return ruleMap +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/index_test.go b/vendor/github.com/XiaoMi/soar/advisor/index_test.go new file mode 100644 index 0000000000000000000000000000000000000000..314655f5ca0eb48de6e0c3cd30f3b85282c6717d --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/index_test.go @@ -0,0 +1,476 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/env" + + "github.com/kr/pretty" + "vitess.io/vitess/go/vt/sqlparser" +) + +func init() { + common.BaseDir = common.DevPath + err := common.ParseConfig("") + if err != nil { + fmt.Println(err.Error()) + } + vEnv, rEnv := env.BuildEnv() + if _, err = vEnv.Version(); err != nil { + fmt.Println(err.Error(), ", By pass all advisor test cases") + os.Exit(0) + } + + if _, err := rEnv.Version(); err != nil { + fmt.Println(err.Error(), ", By pass all advisor test cases") + os.Exit(0) + } +} + +// ARG.003 +func TestRuleImplicitConversion(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + dsn := common.Config.OnlineDSN + common.Config.OnlineDSN = common.Config.TestDSN + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + initSQLs := []string{ + `CREATE TABLE t1 (id int, title varchar(255) CHARSET utf8 COLLATE utf8_general_ci);`, + `CREATE TABLE t2 (id int, title varchar(255) CHARSET utf8mb4);`, + `CREATE TABLE t3 (id int, title varchar(255) CHARSET utf8 COLLATE utf8_bin);`, + } + for _, sql := range initSQLs { + vEnv.BuildVirtualEnv(rEnv, sql) + } + + sqls := []string{ + "SELECT * FROM t1 WHERE title >= 60;", + "SELECT * FROM t1, t2 WHERE t1.title = t2.title;", + "SELECT * FROM t1, t3 WHERE t1.title = t3.title;", + "SELECT * FROM t1 WHERE title in (60, '60');", + "SELECT * FROM t1 WHERE title in (60);", + } + for _, sql := range sqls { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleImplicitConversion() + if rule.Item != "ARG.003" { + t.Error("Rule not match:", rule, "Expect : ARG.003, SQL:", sql) + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) + common.Config.OnlineDSN = dsn +} + +// JOI.003 & JOI.004 +func TestRuleImpossibleOuterJoin(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select city_id, city, country from city left outer join country using(country_id) WHERE city.city_id=59 and country.country='Algeria'`, + `select city_id, city, country from city left outer join country using(country_id) WHERE country.country='Algeria'`, + `select city_id, city, country from city left outer join country on city.country_id=country.country_id WHERE city.city_id IS NULL`, + } + + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range sqls { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleImpossibleOuterJoin() + if rule.Item != "JOI.003" && rule.Item != "JOI.004" { + t.Error("Rule not match:", rule, "Expect : JOI.003 || JOI.004") + } + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// GRP.001 +func TestIndexAdvisorRuleGroupByConst(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `select film_id, title from film where release_year='2006' group by release_year`, + `select film_id, title from film where release_year in ('2006') group by release_year`, + }, + { + // 反面的例子 + `select film_id, title from film where release_year in ('2006', '2007') group by release_year`, + }, + } + + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range sqls[0] { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleGroupByConst() + if rule.Item != "GRP.001" { + t.Error("Rule not match:", rule, "Expect : GRP.001") + } + } + } + } + + for _, sql := range sqls[1] { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleGroupByConst() + if rule.Item != "OK" { + t.Error("Rule not match:", rule, "Expect : OK") + } + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.005 +func TestIndexAdvisorRuleOrderByConst(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `select film_id, title from film where release_year='2006' order by release_year;`, + `select film_id, title from film where release_year in ('2006') order by release_year;`, + }, + { + // 反面的例子 + `select film_id, title from film where release_year in ('2006', '2007') order by release_year;`, + }, + } + + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range sqls[0] { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleOrderByConst() + if rule.Item != "CLA.005" { + t.Error("Rule not match:", rule, "Expect : CLA.005") + } + } + } + } + + for _, sql := range sqls[1] { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleOrderByConst() + if rule.Item != "OK" { + t.Error("Rule not match:", rule, "Expect : OK") + } + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +// CLA.016 +func TestRuleUpdatePrimaryKey(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := [][]string{ + { + `update film set film_id = 1 where title='a';`, + }, + { + // 反面的例子 + `select film_id, title from film where release_year in ('2006', '2007') order by release_year;`, + }, + } + + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range sqls[0] { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleUpdatePrimaryKey() + if rule.Item != "CLA.016" { + t.Error("Rule not match:", rule.Item, "Expect : CLA.016") + } + } + } + } + + for _, sql := range sqls[1] { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleUpdatePrimaryKey() + if rule.Item != "OK" { + t.Error("Rule not match:", rule, "Expect : OK") + } + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +func TestIndexAdvise(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range common.TestSQLs { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.IndexAdvise().Format() + if len(rule) > 0 { + pretty.Println(rule) + } + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +func TestIndexAdviseNoEnv(t *testing.T) { + common.Config.OnlineDSN.Disable = true + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range common.TestSQLs { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.IndexAdvise().Format() + if len(rule) > 0 { + pretty.Println(rule) + } + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) +} + +func TestDuplicateKeyChecker(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + _, rEnv := env.BuildEnv() + rule := DuplicateKeyChecker(rEnv, "sakila") + if len(rule) != 0 { + t.Errorf("got rules: %s", pretty.Sprint(rule)) + } +} + +func TestMergeAdvices(t *testing.T) { + dst := []IndexInfo{ + { + Name: "test", + Database: "db", + Table: "tb", + ColumnDetails: []*common.Column{ + { + Name: "test", + }, + }, + }, + } + + src := dst[0] + + advise := mergeAdvices(dst, src) + if len(advise) != 1 { + t.Error(pretty.Sprint(advise)) + } +} + +func TestIdxColsTypeCheck(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + sqls := []string{ + `select city_id, city, country from city left outer join country using(country_id) WHERE city.city_id=59 and country.country='Algeria'`, + } + + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + + for _, sql := range sqls { + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + if vEnv.BuildVirtualEnv(rEnv, q.Query) { + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + idxList := []IndexInfo{ + { + Name: "idx_fk_country_id", + Database: "sakila", + Table: "city", + ColumnDetails: []*common.Column{ + { + Name: "country_id", + Character: "utf8", + DataType: "varchar(3000)", + }, + }, + }, + } + + if idxAdvisor != nil { + rule := idxAdvisor.idxColsTypeCheck(idxList) + if !(len(rule) > 0 && rule[0].DDL == "alter table `sakila`.`city` add index `idx_country_id` (`country_id`(N))") { + t.Error(pretty.Sprint(rule)) + } + } + } + } +} + +func TestGetRandomIndexSuffix(t *testing.T) { + for i := 0; i < 5; i++ { + r := getRandomIndexSuffix() + if !(strings.HasPrefix(r, "_") && len(r) == 5) { + t.Errorf("getRandomIndexSuffix should return a string with prefix `_` and 5 length, but got:%s", r) + } + } +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/rules.go b/vendor/github.com/XiaoMi/soar/advisor/rules.go new file mode 100644 index 0000000000000000000000000000000000000000..de925369aec6c10cce397f2486ffc60e5e356b52 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/rules.go @@ -0,0 +1,1426 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "encoding/json" + "fmt" + "regexp" + "sort" + "strconv" + "strings" + + "github.com/XiaoMi/soar/ast" + "github.com/XiaoMi/soar/common" + + "github.com/kr/pretty" + "github.com/percona/go-mysql/query" + tidb "github.com/pingcap/parser/ast" + "vitess.io/vitess/go/vt/sqlparser" +) + +// Query4Audit 待评审的SQL结构体,由原SQL和其对应的抽象语法树组成 +type Query4Audit struct { + Query string // 查询语句 + Stmt sqlparser.Statement // 通过Vitess解析出的抽象语法树 + TiStmt []tidb.StmtNode // 通过TiDB解析出的抽象语法树 +} + +// NewQuery4Audit return a struct for Query4Audit +func NewQuery4Audit(sql string, options ...string) (*Query4Audit, error) { + var err, vErr error + var charset string + var collation string + + if len(options) > 0 { + charset = options[0] + } + + if len(options) > 1 { + collation = options[1] + } + + q := &Query4Audit{Query: sql} + // vitess 语法解析不上报,以 tidb parser 为主 + q.Stmt, vErr = sqlparser.Parse(sql) + if vErr != nil { + common.Log.Warn("NewQuery4Audit vitess parse Error: %s", vErr.Error()) + } + + // TODO: charset, collation + // tdib parser 语法解析 + q.TiStmt, err = ast.TiParse(sql, charset, collation) + return q, err +} + +// Rule 评审规则元数据结构 +type Rule struct { + Item string `json:"Item"` // 规则代号 + Severity string `json:"Severity"` // 危险等级:L[0-8], 数字越大表示级别越高 + Summary string `json:"Summary"` // 规则摘要 + Content string `json:"Content"` // 规则解释 + Case string `json:"Case"` // SQL示例 + Position int `json:"Position"` // 建议所处SQL字符位置,默认0表示全局建议 + Func func(*Query4Audit) Rule `json:"-"` // 函数名 +} + +/* + +## Item单词缩写含义 + +* ALI Alias(AS) +* ALT Alter +* ARG Argument +* CLA Classic +* COL Column +* DIS Distinct +* ERR Error, 特指MySQL执行返回的报错信息, ERR.000为vitess语法错误,ERR.001为执行错误,ERR.002为EXPLAIN错误 +* EXP Explain, 由explain模块给 +* FUN Function +* IDX Index, 由index模块给 +* JOI Join +* KEY Key +* KWR Keyword +* LCK Lock +* LIT Literal +* PRO Profiling, 由profiling模块给 +* RES Result +* SEC Security +* STA Standard +* SUB Subquery +* TBL Table +* TRA Trace, 由trace模块给 + +*/ + +// HeuristicRules 启发式规则列表 +var HeuristicRules map[string]Rule + +func init() { + HeuristicRules = map[string]Rule{ + "OK": { + Item: "OK", + Severity: "L0", + Summary: "OK", + Content: `OK`, + Case: "OK", + Func: (*Query4Audit).RuleOK, + }, + "ALI.001": { + Item: "ALI.001", + Severity: "L0", + Summary: "建议使用 AS 关键字显示声明一个别名", + Content: `在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。`, + Case: "select name from tbl t1 where id < 1000", + Func: (*Query4Audit).RuleImplicitAlias, + }, + "ALI.002": { + Item: "ALI.002", + Severity: "L8", + Summary: "不建议给列通配符'*'设置别名", + Content: `例: "SELECT tbl.* col1, col2"上面这条 SQL 给列通配符设置了别名,这样的SQL可能存在逻辑错误。您可能意在查询 col1, 但是代替它的是重命名的是 tbl 的最后一列。`, + Case: "select tbl.* as c1,c2,c3 from tbl where id < 1000", + Func: (*Query4Audit).RuleStarAlias, + }, + "ALI.003": { + Item: "ALI.003", + Severity: "L1", + Summary: "别名不要与表或列的名字相同", + Content: `表或列的别名与其真实名称相同, 这样的别名会使得查询更难去分辨。`, + Case: "select name from tbl as tbl where id < 1000", + Func: (*Query4Audit).RuleSameAlias, + }, + "ALT.001": { + Item: "ALT.001", + Severity: "L4", + Summary: "修改表的默认字符集不会改表各个字段的字符集", + Content: `很多初学者会将 ALTER TABLE tbl_name [DEFAULT] CHARACTER SET 'UTF8' 误认为会修改所有字段的字符集,但实际上它只会影响后续新增的字段不会改表已有字段的字符集。如果想修改整张表所有字段的字符集建议使用 ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;`, + Case: "ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;", + Func: (*Query4Audit).RuleAlterCharset, + }, + "ALT.002": { + Item: "ALT.002", + Severity: "L2", + Summary: "同一张表的多条 ALTER 请求建议合为一条", + Content: `每次表结构变更对线上服务都会产生影响,即使是能够通过在线工具进行调整也请尽量通过合并 ALTER 请求的试减少操作次数。`, + Case: "ALTER TABLE tbl ADD COLUMN col int, ADD INDEX idx_col (`col`);", + Func: (*Query4Audit).RuleOK, // 该建议在indexAdvisor中给 + }, + "ALT.003": { + Item: "ALT.003", + Severity: "L0", + Summary: "删除列为高危操作,操作前请注意检查业务逻辑是否还有依赖", + Content: `如业务逻辑依赖未完全消除,列被删除后可能导致数据无法写入或无法查询到已删除列数据导致程序异常的情况。这种情况下即使通过备份数据回滚也会丢失用户请求写入的数据。`, + Case: "ALTER TABLE tbl DROP COLUMN col;", + Func: (*Query4Audit).RuleAlterDropColumn, + }, + "ALT.004": { + Item: "ALT.004", + Severity: "L0", + Summary: "删除主键和外键为高危操作,操作前请与 DBA 确认影响", + Content: `主键和外键为关系型数据库中两种重要约束,删除已有约束会打破已有业务逻辑,操作前请业务开发与 DBA 确认影响,三思而行。`, + Case: "ALTER TABLE tbl DROP PRIMARY KEY;", + Func: (*Query4Audit).RuleAlterDropKey, + }, + "ARG.001": { + Item: "ARG.001", + Severity: "L4", + Summary: "不建议使用前项通配符查找", + Content: `例如 "%foo",查询参数有一个前项通配符的情况无法使用已有索引。`, + Case: "select c1,c2,c3 from tbl where name like '%foo'", + Func: (*Query4Audit).RulePrefixLike, + }, + "ARG.002": { + Item: "ARG.002", + Severity: "L1", + Summary: "没有通配符的 LIKE 查询", + Content: `不包含通配符的 LIKE 查询可能存在逻辑错误,因为逻辑上它与等值查询相同。`, + Case: "select c1,c2,c3 from tbl where name like 'foo'", + Func: (*Query4Audit).RuleEqualLike, + }, + "ARG.003": { + Item: "ARG.003", + Severity: "L4", + Summary: "参数比较包含隐式转换,无法使用索引", + Content: "隐式类型转换有无法命中索引的风险,在高并发、大数据量的情况下,命不中索引带来的后果非常严重。", + Case: "SELECT * FROM sakila.film WHERE length >= '60';", + Func: (*Query4Audit).RuleOK, // 该建议在IndexAdvisor中给,RuleImplicitConversion + }, + "ARG.004": { + Item: "ARG.004", + Severity: "L4", + Summary: "IN (NULL)/NOT IN (NULL) 永远非真", + Content: "正确的作法是 col IN ('val1', 'val2', 'val3') OR col IS NULL", + Case: "SELECT * FROM tb WHERE col IN (NULL);", + Func: (*Query4Audit).RuleIn, + }, + "ARG.005": { + Item: "ARG.005", + Severity: "L1", + Summary: "IN 要慎用,元素过多会导致全表扫描", + Content: ` 如:select id from t where num in(1,2,3)对于连续的数值,能用 BETWEEN 就不要用 IN 了:select id from t where num between 1 and 3。而当 IN 值过多时 MySQL 也可能会进入全表扫描导致性能急剧下降。`, + Case: "select id from t where num in(1,2,3)", + Func: (*Query4Audit).RuleIn, + }, + "ARG.006": { + Item: "ARG.006", + Severity: "L1", + Summary: "应尽量避免在 WHERE 子句中对字段进行 NULL 值判断", + Content: `使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;`, + Case: "select id from t where num is null", + Func: (*Query4Audit).RuleIsNullIsNotNull, + }, + "ARG.007": { + Item: "ARG.007", + Severity: "L3", + Summary: "避免使用模式匹配", + Content: `性能问题是使用模式匹配操作符的最大缺点。使用 LIKE 或正则表达式进行模式匹配进行查询的另一个问题,是可能会返回意料之外的结果。最好的方案就是使用特殊的搜索引擎技术来替代 SQL,比如 Apache Lucene。另一个可选方案是将结果保存起来从而减少重复的搜索开销。如果一定要使用SQL,请考虑在 MySQL 中使用像 FULLTEXT 索引这样的第三方扩展。但更广泛地说,您不一定要使用SQL来解决所有问题。`, + Case: "select c_id,c2,c3 from tbl where c2 like 'test%'", + Func: (*Query4Audit).RulePatternMatchingUsage, + }, + "ARG.008": { + Item: "ARG.008", + Severity: "L1", + Summary: "OR 查询索引列时请尽量使用 IN 谓词", + Content: `IN-list 谓词可以用于索引检索,并且优化器可以对 IN-list 进行排序,以匹配索引的排序序列,从而获得更有效的检索。请注意,IN-list 必须只包含常量,或在查询块执行期间保持常量的值,例如外引用。`, + Case: "SELECT c1,c2,c3 FROM tbl WHERE c1 = 14 OR c1 = 17", + Func: (*Query4Audit).RuleORUsage, + }, + "ARG.009": { + Item: "ARG.009", + Severity: "L1", + Summary: "引号中的字符串开头或结尾包含空格", + Content: `如果 VARCHAR 列的前后存在空格将可能引起逻辑问题,如在 MySQL 5.5中 'a' 和 'a ' 可能会在查询中被认为是相同的值。`, + Case: "SELECT 'abc '", + Func: (*Query4Audit).RuleSpaceWithQuote, + }, + "ARG.010": { + Item: "ARG.010", + Severity: "L1", + Summary: "不要使用 hint,如:sql_no_cache, force index, ignore key, straight join等", + Content: `hint 是用来强制 SQL 按照某个执行计划来执行,但随着数据量变化我们无法保证自己当初的预判是正确的。`, + Case: "SELECT * FROM t1 USE INDEX (i1) ORDER BY a;", + Func: (*Query4Audit).RuleHint, + }, + "ARG.011": { + Item: "ARG.011", + Severity: "L3", + Summary: "不要使用负向查询,如:NOT IN/NOT LIKE", + Content: `请尽量不要使用负向查询,这将导致全表扫描,对查询性能影响较大。`, + Case: "select id from t where num not in(1,2,3);", + Func: (*Query4Audit).RuleNot, + }, + "ARG.012": { + Item: "ARG.012", + Severity: "L2", + Summary: "一次性 INSERT/REPLACE 的数据过多", + Content: "单条 INSERT/REPLACE 语句批量插入大量数据性能较差,甚至可能导致从库同步延迟。为了提升性能,减少批量写入数据对从库同步延时的影响,建议采用分批次插入的方法。", + Case: "INSERT INTO tb (a) VALUES (1), (2)", + Func: (*Query4Audit).RuleInsertValues, + }, + "CLA.001": { + Item: "CLA.001", + Severity: "L4", + Summary: "最外层 SELECT 未指定 WHERE 条件", + Content: `SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。`, + Case: "select id from tbl", + Func: (*Query4Audit).RuleNoWhere, + }, + "CLA.002": { + Item: "CLA.002", + Severity: "L3", + Summary: "不建议使用 ORDER BY RAND()", + Content: `ORDER BY RAND() 是从结果集中检索随机行的一种非常低效的方法,因为它会对整个结果进行排序并丢弃其大部分数据。`, + Case: "select name from tbl where id < 1000 order by rand(number)", + Func: (*Query4Audit).RuleOrderByRand, + }, + "CLA.003": { + Item: "CLA.003", + Severity: "L2", + Summary: "不建议使用带 OFFSET 的LIMIT 查询", + Content: `使用 LIMIT 和 OFFSET 对结果集分页的复杂度是 O(n^2),并且会随着数据增大而导致性能问题。采用“书签”扫描的方法实现分页效率更高。`, + Case: "select c1,c2 from tbl where name=xx order by number limit 1 offset 20", + Func: (*Query4Audit).RuleOffsetLimit, + }, + "CLA.004": { + Item: "CLA.004", + Severity: "L2", + Summary: "不建议对常量进行 GROUP BY", + Content: `GROUP BY 1 表示按第一列进行 GROUP BY。如果在 GROUP BY 子句中使用数字,而不是表达式或列名称,当查询列顺序改变时,可能会导致问题。`, + Case: "select col1,col2 from tbl group by 1", + Func: (*Query4Audit).RuleGroupByConst, + }, + "CLA.005": { + Item: "CLA.005", + Severity: "L2", + Summary: "ORDER BY 常数列没有任何意义", + Content: `SQL 逻辑上可能存在错误; 最多只是一个无用的操作,不会更改查询结果。`, + Case: "select id from test where id=1 order by id", + Func: (*Query4Audit).RuleOrderByConst, + }, + "CLA.006": { + Item: "CLA.006", + Severity: "L4", + Summary: "在不同的表中 GROUP BY 或 ORDER BY", + Content: `这将强制使用临时表和 filesort,可能产生巨大性能隐患,并且可能消耗大量内存和磁盘上的临时空间。`, + Case: "select tb1.col, tb2.col from tb1, tb2 where id=1 group by tb1.col, tb2.col", + Func: (*Query4Audit).RuleDiffGroupByOrderBy, + }, + "CLA.007": { + Item: "CLA.007", + Severity: "L2", + Summary: "ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引", + Content: `ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。`, + Case: "select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc", + Func: (*Query4Audit).RuleMixOrderBy, + }, + "CLA.008": { + Item: "CLA.008", + Severity: "L2", + Summary: "请为 GROUP BY 显示添加 ORDER BY 条件", + Content: `默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。`, + Case: "select c1,c2,c3 from t1 where c1='foo' group by c2", + Func: (*Query4Audit).RuleExplicitOrderBy, + }, + "CLA.009": { + Item: "CLA.009", + Severity: "L2", + Summary: "ORDER BY 的条件为表达式", + Content: `当 ORDER BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。`, + Case: "select description from film where title ='ACADEMY DINOSAUR' order by length-language_id;", + Func: (*Query4Audit).RuleOrderByExpr, + }, + "CLA.010": { + Item: "CLA.010", + Severity: "L2", + Summary: "GROUP BY 的条件为表达式", + Content: `当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。`, + Case: "select description from film where title ='ACADEMY DINOSAUR' GROUP BY length-language_id;", + Func: (*Query4Audit).RuleGroupByExpr, + }, + "CLA.011": { + Item: "CLA.011", + Severity: "L1", + Summary: "建议为表添加注释", + Content: `为表添加注释能够使得表的意义更明确,从而为日后的维护带来极大的便利。`, + Case: "CREATE TABLE `test1` (`ID` bigint(20) NOT NULL AUTO_INCREMENT,`c1` varchar(128) DEFAULT NULL,PRIMARY KEY (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=utf8", + Func: (*Query4Audit).RuleTblCommentCheck, + }, + "CLA.012": { + Item: "CLA.012", + Severity: "L2", + Summary: "将复杂的裹脚布式查询分解成几个简单的查询", + Content: `SQL是一门极具表现力的语言,您可以在单个SQL查询或者单条语句中完成很多事情。但这并不意味着必须强制只使用一行代码,或者认为使用一行代码就搞定每个任务是个好主意。通过一个查询来获得所有结果的常见后果是得到了一个笛卡儿积。当查询中的两张表之间没有条件限制它们的关系时,就会发生这种情况。没有对应的限制而直接使用两张表进行联结查询,就会得到第一张表中的每一行和第二张表中的每一行的一个组合。每一个这样的组合就会成为结果集中的一行,最终您就会得到一个行数很多的结果集。重要的是要考虑这些查询很难编写、难以修改和难以调试。数据库查询请求的日益增加应该是预料之中的事。经理们想要更复杂的报告以及在用户界面上添加更多的字段。如果您的设计很复杂,并且是一个单一查询,要扩展它们就会很费时费力。不论对您还是项目来说,时间花在这些事情上面不值得。将复杂的意大利面条式查询分解成几个简单的查询。当您拆分一个复杂的SQL查询时,得到的结果可能是很多类似的查询,可能仅仅在数据类型上有所不同。编写所有的这些查询是很乏味的,因此,最好能够有个程序自动生成这些代码。SQL代码生成是一个很好的应用。尽管SQL支持用一行代码解决复杂的问题,但也别做不切实际的事情。`, + Case: "这是一条很长很长的 SQL,案例略。", + Func: (*Query4Audit).RuleSpaghettiQueryAlert, + }, + /* + https://www.datacamp.com/community/tutorials/sql-tutorial-query + The HAVING Clause + The HAVING clause was originally added to SQL because the WHERE keyword could not be used with aggregate functions. HAVING is typically used with the GROUP BY clause to restrict the groups of returned rows to only those that meet certain conditions. However, if you use this clause in your query, the index is not used, which -as you already know- can result in a query that doesn't really perform all that well. + + If you’re looking for an alternative, consider using the WHERE clause. Consider the following queries: + + SELECT state, COUNT(*) + FROM Drivers + WHERE state IN ('GA', 'TX') + GROUP BY state + ORDER BY state + SELECT state, COUNT(*) + FROM Drivers + GROUP BY state + HAVING state IN ('GA', 'TX') + ORDER BY state + The first query uses the WHERE clause to restrict the number of rows that need to be summed, whereas the second query sums up all the rows in the table and then uses HAVING to throw away the sums it calculated. In these types of cases, the alternative with the WHERE clause is obviously the better one, as you don’t waste any resources. + + You see that this is not about limiting the result set, rather about limiting the intermediate number of records within a query. + + Note that the difference between these two clauses lies in the fact that the WHERE clause introduces a condition on individual rows, while the HAVING clause introduces a condition on aggregations or results of a selection where a single result, such as MIN, MAX, SUM,… has been produced from multiple rows. + */ + "CLA.013": { + Item: "CLA.013", + Severity: "L3", + Summary: "不建议使用 HAVING 子句", + Content: `将查询的 HAVING 子句改写为 WHERE 中的查询条件,可以在查询处理期间使用索引。`, + Case: "SELECT s.c_id,count(s.c_id) FROM s where c = test GROUP BY s.c_id HAVING s.c_id <> '1660' AND s.c_id <> '2' order by s.c_id", + Func: (*Query4Audit).RuleHavingClause, + }, + "CLA.014": { + Item: "CLA.014", + Severity: "L2", + Summary: "删除全表时建议使用 TRUNCATE 替代 DELETE", + Content: `删除全表时建议使用 TRUNCATE 替代 DELETE`, + Case: "delete from tbl", + Func: (*Query4Audit).RuleNoWhere, + }, + "CLA.015": { + Item: "CLA.015", + Severity: "L4", + Summary: "UPDATE 未指定 WHERE 条件", + Content: `UPDATE 不指定 WHERE 条件一般是致命的,请您三思后行`, + Case: "update tbl set col=1", + Func: (*Query4Audit).RuleNoWhere, + }, + "CLA.016": { + Item: "CLA.016", + Severity: "L2", + Summary: "不要 UPDATE 主键", + Content: `主键是数据表中记录的唯一标识符,不建议频繁更新主键列,这将影响元数据统计信息进而影响正常的查询。`, + Case: "update tbl set col=1", + Func: (*Query4Audit).RuleOK, // 该建议在indexAdvisor中给 + }, + "COL.001": { + Item: "COL.001", + Severity: "L1", + Summary: "不建议使用 SELECT * 类型查询", + Content: `当表结构变更时,使用 * 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。`, + Case: "select * from tbl where id=1", + Func: (*Query4Audit).RuleSelectStar, + }, + "COL.002": { + Item: "COL.002", + Severity: "L2", + Summary: "INSERT/REPLACE 未指定列名", + Content: `当表结构发生变更,如果 INSERT 或 REPLACE 请求不明确指定列名,请求的结果将会与预想的不同; 建议使用 “INSERT INTO tbl(col1,col2)VALUES ...” 代替。`, + Case: "insert into tbl values(1,'name')", + Func: (*Query4Audit).RuleInsertColDef, + }, + "COL.003": { + Item: "COL.003", + Severity: "L2", + Summary: "建议修改自增 ID 为无符号类型", + Content: `建议修改自增 ID 为无符号类型`, + Case: "create table test(`id` int(11) NOT NULL AUTO_INCREMENT)", + Func: (*Query4Audit).RuleAutoIncUnsigned, + }, + "COL.004": { + Item: "COL.004", + Severity: "L1", + Summary: "请为列添加默认值", + Content: `请为列添加默认值,如果是 ALTER 操作,请不要忘记将原字段的默认值写上。字段无默认值,当表较大时无法在线变更表结构。`, + Case: "CREATE TABLE tbl (col int) ENGINE=InnoDB;", + Func: (*Query4Audit).RuleAddDefaultValue, + }, + "COL.005": { + Item: "COL.005", + Severity: "L1", + Summary: "列未添加注释", + Content: `建议对表中每个列添加注释,来明确每个列在表中的含义及作用。`, + Case: "CREATE TABLE tbl (col int) ENGINE=InnoDB;", + Func: (*Query4Audit).RuleColCommentCheck, + }, + "COL.006": { + Item: "COL.006", + Severity: "L3", + Summary: "表中包含有太多的列", + Content: `表中包含有太多的列`, + Case: "CREATE TABLE tbl ( cols ....);", + Func: (*Query4Audit).RuleTooManyFields, + }, + "COL.008": { + Item: "COL.008", + Severity: "L1", + Summary: "可使用 VARCHAR 代替 CHAR, VARBINARY 代替 BINARY", + Content: `为首先变长字段存储空间小,可以节省存储空间。其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。`, + Case: "create table t1(id int,name char(20),last_time date)", + Func: (*Query4Audit).RuleVarcharVSChar, + }, + "COL.009": { + Item: "COL.009", + Severity: "L2", + Summary: "建议使用精确的数据类型", + Content: `实际上,任何使用 FLOAT, REAL 或 DOUBLE PRECISION 数据类型的设计都有可能是反模式。大多数应用程序使用的浮点数的取值范围并不需要达到IEEE 754标准所定义的最大/最小区间。在计算总量时,非精确浮点数所积累的影响是严重的。使用 SQL 中的 NUMERIC 或 DECIMAL 类型来代替 FLOAT 及其类似的数据类型进行固定精度的小数存储。这些数据类型精确地根据您定义这一列时指定的精度来存储数据。尽可能不要使用浮点数。`, + Case: "CREATE TABLE tab2 (p_id BIGINT UNSIGNED NOT NULL,a_id BIGINT UNSIGNED NOT NULL,hours float not null,PRIMARY KEY (p_id, a_id))", + Func: (*Query4Audit).RuleImpreciseDataType, + }, + "COL.010": { + Item: "COL.010", + Severity: "L2", + Summary: "不建议使用 ENUM 数据类型", + Content: `ENUM 定义了列中值的类型,使用字符串表示 ENUM 里的值时,实际存储在列中的数据是这些值在定义时的序数。因此,这列的数据是字节对齐的,当您进行一次排序查询时,结果是按照实际存储的序数值排序的,而不是按字符串值的字母顺序排序的。这可能不是您所希望的。没有什么语法支持从 ENUM 或者 check 约束中添加或删除一个值;您只能使用一个新的集合重新定义这一列。如果您打算废弃一个选项,您可能会为历史数据而烦恼。作为一种策略,改变元数据——也就是说,改变表和列的定义——应该是不常见的,并且要注意测试和质量保证。有一个更好的解决方案来约束一列中的可选值:创建一张检查表,每一行包含一个允许在列中出现的候选值;然后在引用新表的旧表上声明一个外键约束。`, + Case: "create table tab1(status ENUM('new','in progress','fixed'))", + Func: (*Query4Audit).RuleValuesInDefinition, + }, + // 这个建议从sqlcheck迁移来的,实际生产环境每条建表SQL都会给这条建议,看多了会不开心。 + "COL.011": { + Item: "COL.011", + Severity: "L0", + Summary: "当需要唯一约束时才使用 NULL,仅当列不能有缺失值时才使用 NOT NULL", + Content: `NULL 和0是不同的,10乘以 NULL 还是 NULL。NULL 和空字符串是不一样的。将一个字符串和标准 SQL 中的 NULL 联合起来的结果还是 NULL。NULL 和 FALSE 也是不同的。AND、OR 和 NOT 这三个布尔操作如果涉及 NULL,其结果也让很多人感到困惑。当您将一列声明为 NOT NULL 时,也就是说这列中的每一个值都必须存在且是有意义的。使用 NULL 来表示任意类型不存在的空值。 当您将一列声明为 NOT NULL 时,也就是说这列中的每一个值都必须存在且是有意义的。`, + Case: "select c1,c2,c3 from tbl where c4 is null or c4 <> 1", + Func: (*Query4Audit).RuleNullUsage, + }, + "COL.012": { + Item: "COL.012", + Severity: "L5", + Summary: "BLOB 和 TEXT 类型的字段不可设置为 NULL", + Content: `BLOB 和 TEXT 类型的字段不可设置为 NULL`, + Case: "CREATE TABLE `tbl` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` longblob, PRIMARY KEY (`id`));", + Func: (*Query4Audit).RuleCantBeNull, + }, + "COL.013": { + Item: "COL.013", + Severity: "L4", + Summary: "TIMESTAMP 类型未设置默认值", + Content: `TIMESTAMP 类型未设置默认值`, + Case: "CREATE TABLE tbl( `id` bigint not null, `create_time` timestamp);", + Func: (*Query4Audit).RuleTimestampDefault, + }, + "COL.014": { + Item: "COL.014", + Severity: "L5", + Summary: "为列指定了字符集", + Content: `建议列与表使用同一个字符集,不要单独指定列的字符集。`, + Case: "CREATE TABLE `tb2` ( `id` int(11) DEFAULT NULL, `col` char(10) CHARACTER SET utf8 DEFAULT NULL)", + Func: (*Query4Audit).RuleColumnWithCharset, + }, + "COL.015": { + Item: "COL.015", + Severity: "L4", + Summary: "BLOB 类型的字段不可指定默认值", + Content: `BLOB 类型的字段不可指定默认值`, + Case: "CREATE TABLE `tbl` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` blob NOT NULL DEFAULT '', PRIMARY KEY (`id`));", + Func: (*Query4Audit).RuleBlobDefaultValue, + }, + "COL.016": { + Item: "COL.016", + Severity: "L1", + Summary: "整型定义建议采用 INT(10) 或 BIGINT(20)", + Content: `INT(M) 在 integer 数据类型中,M 表示最大显示宽度。 在 INT(M) 中,M 的值跟 INT(M) 所占多少存储空间并无任何关系。 INT(3)、INT(4)、INT(8) 在磁盘上都是占用 4 bytes 的存储空间。`, + Case: "CREATE TABLE tab (a INT(1));", + Func: (*Query4Audit).RuleIntPrecision, + }, + "COL.017": { + Item: "COL.017", + Severity: "L2", + Summary: "VARCHAR 定义长度过长", + Content: fmt.Sprintf(`varchar 是可变长字符串,不预先分配存储空间,长度不要超过%d,如果存储长度过长 MySQL 将定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。`, common.Config.MaxVarcharLength), + Case: "CREATE TABLE tab (a varchar(3500));", + Func: (*Query4Audit).RuleVarcharLength, + }, + "DIS.001": { + Item: "DIS.001", + Severity: "L1", + Summary: "消除不必要的 DISTINCT 条件", + Content: `太多DISTINCT条件是复杂的裹脚布式查询的症状。考虑将复杂查询分解成许多简单的查询,并减少DISTINCT条件的数量。如果主键列是列的结果集的一部分,则DISTINCT条件可能没有影响。`, + Case: "SELECT DISTINCT c.c_id,count(DISTINCT c.c_name),count(DISTINCT c.c_e),count(DISTINCT c.c_n),count(DISTINCT c.c_me),c.c_d FROM (select distinct id, name from B) as e WHERE e.country_id = c.country_id", + Func: (*Query4Audit).RuleDistinctUsage, + }, + "DIS.002": { + Item: "DIS.002", + Severity: "L3", + Summary: "COUNT(DISTINCT) 多列时结果可能和你预想的不同", + Content: `COUNT(DISTINCT col) 计算该列除NULL之外的不重复行数,注意 COUNT(DISTINCT col, col2) 如果其中一列全为 NULL 那么即使另一列有不同的值,也返回0。`, + Case: "SELECT COUNT(DISTINCT col, col2) FROM tbl;", + Func: (*Query4Audit).RuleCountDistinctMultiCol, + }, + // DIS.003 灵感来源于如下链接 + // http://www.ijstr.org/final-print/oct2015/Query-Optimization-Techniques-Tips-For-Writing-Efficient-And-Faster-Sql-Queries.pdf + "DIS.003": { + Item: "DIS.003", + Severity: "L3", + Summary: "DISTINCT * 对有主键的表没有意义", + Content: `当表已经有主键时,对所有列进行 DISTINCT 的输出结果与不进行 DISTINCT 操作的结果相同,请不要画蛇添足。`, + Case: "SELECT DISTINCT * FROM film;", + Func: (*Query4Audit).RuleDistinctStar, + }, + "FUN.001": { + Item: "FUN.001", + Severity: "L2", + Summary: "避免在 WHERE 条件中使用函数或其他运算符", + Content: `虽然在 SQL 中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。也不建议在查询比较条件两侧书写多余的括号,这会对阅读产生比较大的困扰。`, + Case: "select id from t where substring(name,1,3)='abc'", + Func: (*Query4Audit).RuleCompareWithFunction, + }, + "FUN.002": { + Item: "FUN.002", + Severity: "L1", + Summary: "指定了 WHERE 条件或非 MyISAM 引擎时使用 COUNT(*) 操作性能不佳", + Content: `COUNT(*) 的作用是统计表行数,COUNT(COL) 的作用是统计指定列非 NULL 的行数。MyISAM 表对于 COUNT(*) 统计全表行数进行了特殊的优化,通常情况下非常快。但对于非 MyISAM 表或指定了某些 WHERE 条件,COUNT(*) 操作需要扫描大量的行才能获取精确的结果,性能也因此不佳。有时候某些业务场景并不需要完全精确的 COUNT 值,此时可以用近似值来代替。EXPLAIN 出来的优化器估算的行数就是一个不错的近似值,执行 EXPLAIN 并不需要真正去执行查询,所以成本很低。`, + Case: "SELECT c3, COUNT(*) AS accounts FROM tab where c2 < 10000 GROUP BY c3 ORDER BY num", + Func: (*Query4Audit).RuleCountStar, + }, + "FUN.003": { + Item: "FUN.003", + Severity: "L3", + Summary: "使用了合并为可空列的字符串连接", + Content: `在一些查询请求中,您需要强制让某一列或者某个表达式返回非 NULL 的值,从而让查询逻辑变得更简单,担忧不想将这个值存下来。使用 COALESCE() 函数来构造连接的表达式,这样即使是空值列也不会使整表达式变为 NULL。`, + Case: "select c1 || coalesce(' ' || c2 || ' ', ' ') || c3 as c from tbl", + Func: (*Query4Audit).RuleStringConcatenation, + }, + "FUN.004": { + Item: "FUN.004", + Severity: "L4", + Summary: "不建议使用 SYSDATE() 函数", + Content: `SYSDATE() 函数可能导致主从数据不一致,请使用 NOW() 函数替代 SYSDATE()。`, + Case: "SELECT SYSDATE();", + Func: (*Query4Audit).RuleSysdate, + }, + "FUN.005": { + Item: "FUN.005", + Severity: "L1", + Summary: "不建议使用 COUNT(col) 或 COUNT(常量)", + Content: `不要使用 COUNT(col) 或 COUNT(常量) 来替代 COUNT(*), COUNT(*) 是 SQL92 定义的标准统计行数的方法,跟数据无关,跟 NULL 和非 NULL 也无关。`, + Case: "SELECT COUNT(1) FROM tbl;", + Func: (*Query4Audit).RuleCountConst, + }, + "FUN.006": { + Item: "FUN.006", + Severity: "L1", + Summary: "使用 SUM(COL) 时需注意 NPE 问题", + Content: `当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl`, + Case: "SELECT SUM(COL) FROM tbl;", + Func: (*Query4Audit).RuleSumNPE, + }, + "FUN.007": { + Item: "FUN.007", + Severity: "L1", + Summary: "不建议使用触发器", + Content: `触发器的执行没有反馈和日志,隐藏了实际的执行步骤,当数据库出现问题是,不能通过慢日志分析触发器的具体执行情况,不易发现问题。在MySQL中,触发器不能临时关闭或打开,在数据迁移或数据恢复等场景下,需要临时drop触发器,可能影响到生产环境。`, + Case: "CREATE TRIGGER t1 AFTER INSERT ON work FOR EACH ROW INSERT INTO time VALUES(NOW());", + Func: (*Query4Audit).RuleForbiddenTrigger, + }, + "FUN.008": { + Item: "FUN.008", + Severity: "L1", + Summary: "不建议使用存储过程", + Content: `存储过程无版本控制,配合业务的存储过程升级很难做到业务无感知。存储过程在拓展和移植上也存在问题。`, + Case: "CREATE PROCEDURE simpleproc (OUT param1 INT);", + Func: (*Query4Audit).RuleForbiddenProcedure, + }, + "FUN.009": { + Item: "FUN.009", + Severity: "L1", + Summary: "不建议使用自定义函数", + Content: `不建议使用自定义函数`, + Case: "CREATE FUNCTION hello (s CHAR(20));", + Func: (*Query4Audit).RuleForbiddenFunction, + }, + "GRP.001": { + Item: "GRP.001", + Severity: "L2", + Summary: "不建议对等值查询列使用 GROUP BY", + Content: `GROUP BY 中的列在前面的 WHERE 条件中使用了等值查询,对这样的列进行 GROUP BY 意义不大。`, + Case: "select film_id, title from film where release_year='2006' group by release_year", + Func: (*Query4Audit).RuleOK, // 该建议在indexAdvisor中给 + }, + "JOI.001": { + Item: "JOI.001", + Severity: "L2", + Summary: "JOIN 语句混用逗号和 ANSI 模式", + Content: `表连接的时候混用逗号和 ANSI JOIN 不便于人类理解,并且MySQL不同版本的表连接行为和优先级均有所不同,当 MySQL 版本变化后可能会引入错误。`, + Case: "select c1,c2,c3 from t1,t2 join t3 on t1.c1=t2.c1,t1.c3=t3,c1 where id>1000", + Func: (*Query4Audit).RuleCommaAnsiJoin, + }, + "JOI.002": { + Item: "JOI.002", + Severity: "L4", + Summary: "同一张表被连接两次", + Content: `相同的表在 FROM 子句中至少出现两次,可以简化为对该表的单次访问。`, + Case: "select tb1.col from (tb1, tb2) join tb2 on tb1.id=tb.id where tb1.id=1", + Func: (*Query4Audit).RuleDupJoin, + }, + "JOI.003": { + Item: "JOI.003", + Severity: "L4", + Summary: "OUTER JOIN 失效", + Content: `由于 WHERE 条件错误使得 OUTER JOIN 的外部表无数据返回,这会将查询隐式转换为 INNER JOIN 。如:select c from L left join R using(c) where L.a=5 and R.b=10。这种 SQL 逻辑上可能存在错误或程序员对 OUTER JOIN 如何工作存在误解,因为 LEFT/RIGHT JOIN 是 LEFT/RIGHT OUTER JOIN 的缩写。`, + Case: "select c1,c2,c3 from t1 left outer join t2 using(c1) where t1.c2=2 and t2.c3=4", + Func: (*Query4Audit).RuleOK, // TODO + }, + "JOI.004": { + Item: "JOI.004", + Severity: "L4", + Summary: "不建议使用排它 JOIN", + Content: `只在右侧表为 NULL 的带 WHERE 子句的 LEFT OUTER JOIN 语句,有可能是在WHERE子句中使用错误的列,如:“... FROM l LEFT OUTER JOIN r ON l.l = r.r WHERE r.z IS NULL”,这个查询正确的逻辑可能是 WHERE r.r IS NULL。`, + Case: "select c1,c2,c3 from t1 left outer join t2 on t1.c1=t2.c1 where t2.c2 is null", + Func: (*Query4Audit).RuleOK, // TODO + }, + "JOI.005": { + Item: "JOI.005", + Severity: "L2", + Summary: "减少 JOIN 的数量", + Content: `太多的 JOIN 是复杂的裹脚布式查询的症状。考虑将复杂查询分解成许多简单的查询,并减少 JOIN 的数量。`, + Case: "select bp1.p_id, b1.d_d as l, b1.b_id from b1 join bp1 on (b1.b_id = bp1.b_id) left outer join (b1 as b2 join bp2 on (b2.b_id = bp2.b_id)) on (bp1.p_id = bp2.p_id ) join bp21 on (b1.b_id = bp1.b_id) join bp31 on (b1.b_id = bp1.b_id) join bp41 on (b1.b_id = bp1.b_id) where b2.b_id = 0", + Func: (*Query4Audit).RuleReduceNumberOfJoin, + }, + "JOI.006": { + Item: "JOI.006", + Severity: "L4", + Summary: "将嵌套查询重写为 JOIN 通常会导致更高效的执行和更有效的优化", + Content: `一般来说,非嵌套子查询总是用于关联子查询,最多是来自FROM子句中的一个表,这些子查询用于 ANY, ALL 和 EXISTS 的谓词。如果可以根据查询语义决定子查询最多返回一个行,那么一个不相关的子查询或来自FROM子句中的多个表的子查询就被压平了。`, + Case: "SELECT s,p,d FROM tbl WHERE p.p_id = (SELECT s.p_id FROM tbl WHERE s.c_id = 100996 AND s.q = 1 )", + Func: (*Query4Audit).RuleNestedSubQueries, + }, + "JOI.007": { + Item: "JOI.007", + Severity: "L4", + Summary: "不建议使用联表删除或更新", + Content: `当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。`, + Case: "UPDATE users u LEFT JOIN hobby h ON u.id = h.uid SET u.name = 'pianoboy' WHERE h.hobby = 'piano';", + Func: (*Query4Audit).RuleMultiDeleteUpdate, + }, + "JOI.008": { + Item: "JOI.008", + Severity: "L4", + Summary: "不要使用跨数据库的 JOIN 查询", + Content: `一般来说,跨数据库的 JOIN 查询意味着查询语句跨越了两个不同的子系统,这可能意味着系统耦合度过高或库表结构设计不合理。`, + Case: "SELECT s,p,d FROM tbl WHERE p.p_id = (SELECT s.p_id FROM tbl WHERE s.c_id = 100996 AND s.q = 1 )", + Func: (*Query4Audit).RuleMultiDBJoin, + }, + // TODO: 跨库事务的检查,目前SOAR未对事务做处理 + "KEY.001": { + Item: "KEY.001", + Severity: "L2", + Summary: "建议使用自增列作为主键,如使用联合自增主键时请将自增键作为第一列", + Content: `建议使用自增列作为主键,如使用联合自增主键时请将自增键作为第一列`, + Case: "create table test(`id` int(11) NOT NULL PRIMARY KEY (`id`))", + Func: (*Query4Audit).RulePKNotInt, + }, + "KEY.002": { + Item: "KEY.002", + Severity: "L4", + Summary: "无主键或唯一键,无法在线变更表结构", + Content: `无主键或唯一键,无法在线变更表结构`, + Case: "create table test(col varchar(5000))", + Func: (*Query4Audit).RuleNoOSCKey, + }, + "KEY.003": { + Item: "KEY.003", + Severity: "L4", + Summary: "避免外键等递归关系", + Content: `存在递归关系的数据很常见,数据常会像树或者以层级方式组织。然而,创建一个外键约束来强制执行同一表中两列之间的关系,会导致笨拙的查询。树的每一层对应着另一个连接。您将需要发出递归查询,以获得节点的所有后代或所有祖先。解决方案是构造一个附加的闭包表。它记录了树中所有节点间的关系,而不仅仅是那些具有直接的父子关系。您也可以比较不同层次的数据设计:闭包表,路径枚举,嵌套集。然后根据应用程序的需要选择一个。`, + Case: "CREATE TABLE tab2 (p_id BIGINT UNSIGNED NOT NULL,a_id BIGINT UNSIGNED NOT NULL,PRIMARY KEY (p_id, a_id),FOREIGN KEY (p_id) REFERENCES tab1(p_id),FOREIGN KEY (a_id) REFERENCES tab3(a_id))", + Func: (*Query4Audit).RuleRecursiveDependency, + }, + // TODO: 新增复合索引,字段按散粒度是否由大到小排序,区分度最高的在最左边 + "KEY.004": { + Item: "KEY.004", + Severity: "L0", + Summary: "提醒:请将索引属性顺序与查询对齐", + Content: `如果为列创建复合索引,请确保查询属性与索引属性的顺序相同,以便DBMS在处理查询时使用索引。如果查询和索引属性订单没有对齐,那么DBMS可能无法在查询处理期间使用索引。`, + Case: "create index idx1 on tbl (last_name,first_name)", + Func: (*Query4Audit).RuleIndexAttributeOrder, + }, + "KEY.005": { + Item: "KEY.005", + Severity: "L2", + Summary: "表建的索引过多", + Content: `表建的索引过多`, + Case: "CREATE TABLE tbl ( a int, b int, c int, KEY idx_a (`a`),KEY idx_b(`b`),KEY idx_c(`c`));", + Func: (*Query4Audit).RuleTooManyKeys, + }, + "KEY.006": { + Item: "KEY.006", + Severity: "L4", + Summary: "主键中的列过多", + Content: `主键中的列过多`, + Case: "CREATE TABLE tbl ( a int, b int, c int, PRIMARY KEY(`a`,`b`,`c`));", + Func: (*Query4Audit).RuleTooManyKeyParts, + }, + "KEY.007": { + Item: "KEY.007", + Severity: "L4", + Summary: "未指定主键或主键非 int 或 bigint", + Content: `未指定主键或主键非 int 或 bigint,建议将主键设置为 int unsigned 或 bigint unsigned。`, + Case: "CREATE TABLE tbl (a int);", + Func: (*Query4Audit).RulePKNotInt, + }, + "KEY.008": { + Item: "KEY.008", + Severity: "L4", + Summary: "ORDER BY 多个列但排序方向不同时可能无法使用索引", + Content: `在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。`, + Case: "SELECT * FROM tbl ORDER BY a DESC, b ASC;", + Func: (*Query4Audit).RuleOrderByMultiDirection, + }, + "KEY.009": { + Item: "KEY.009", + Severity: "L0", + Summary: "添加唯一索引前请注意检查数据唯一性", + Content: `请提前检查添加唯一索引列的数据唯一性,如果数据不唯一在线表结构调整时将有可能自动将重复列删除,这有可能导致数据丢失。`, + Case: "CREATE UNIQUE INDEX part_of_name ON customer (name(10));", + Func: (*Query4Audit).RuleUniqueKeyDup, + }, + "KWR.001": { + Item: "KWR.001", + Severity: "L2", + Summary: "SQL_CALC_FOUND_ROWS 效率低下", + Content: `因为 SQL_CALC_FOUND_ROWS 不能很好地扩展,所以可能导致性能问题; 建议业务使用其他策略来替代 SQL_CALC_FOUND_ROWS 提供的计数功能,比如:分页结果展示等。`, + Case: "select SQL_CALC_FOUND_ROWS col from tbl where id>1000", + Func: (*Query4Audit).RuleSQLCalcFoundRows, + }, + "KWR.002": { + Item: "KWR.002", + Severity: "L2", + Summary: "不建议使用 MySQL 关键字做列名或表名", + Content: `当使用关键字做为列名或表名时程序需要对列名和表名进行转义,如果疏忽被将导致请求无法执行。`, + Case: "CREATE TABLE tbl ( `select` int )", + Func: (*Query4Audit).RuleUseKeyWord, + }, + "KWR.003": { + Item: "KWR.003", + Severity: "L1", + Summary: "不建议使用复数做列名或表名", + Content: `表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯。`, + Case: "CREATE TABLE tbl ( `books` int )", + Func: (*Query4Audit).RulePluralWord, + }, + "KWR.004": { + Item: "KWR.004", + Severity: "L1", + Summary: "不建议使用使用多字节编码字符(中文)命名", + Content: `为库、表、列、别名命名时建议使用英文,数字,下划线等字符,不建议使用中文或其他多字节编码字符。`, + Case: "select col as 列 from tb", + Func: (*Query4Audit).RuleMultiBytesWord, + }, + "LCK.001": { + Item: "LCK.001", + Severity: "L3", + Summary: "INSERT INTO xx SELECT 加锁粒度较大请谨慎", + Content: `INSERT INTO xx SELECT 加锁粒度较大请谨慎`, + Case: "INSERT INTO tbl SELECT * FROM tbl2;", + Func: (*Query4Audit).RuleInsertSelect, + }, + "LCK.002": { + Item: "LCK.002", + Severity: "L3", + Summary: "请慎用 INSERT ON DUPLICATE KEY UPDATE", + Content: `当主键为自增键时使用 INSERT ON DUPLICATE KEY UPDATE 可能会导致主键出现大量不连续快速增长,导致主键快速溢出无法继续写入。极端情况下还有可能导致主从数据不一致。`, + Case: "INSERT INTO t1(a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;", + Func: (*Query4Audit).RuleInsertOnDup, + }, + "LIT.001": { + Item: "LIT.001", + Severity: "L2", + Summary: "用字符类型存储IP地址", + Content: `字符串字面上看起来像IP地址,但不是 INET_ATON() 的参数,表示数据被存储为字符而不是整数。将IP地址存储为整数更为有效。`, + Case: "insert into tbl (IP,name) values('10.20.306.122','test')", + Func: (*Query4Audit).RuleIPString, + }, + "LIT.002": { + Item: "LIT.002", + Severity: "L4", + Summary: "日期/时间未使用引号括起", + Content: `诸如“WHERE col <2010-02-12”之类的查询是有效的SQL,但可能是一个错误,因为它将被解释为“WHERE col <1996”; 日期/时间文字应该加引号。`, + Case: "select col1,col2 from tbl where time < 2018-01-10", + Func: (*Query4Audit).RuleDataNotQuote, + }, + "LIT.003": { + Item: "LIT.003", + Severity: "L3", + Summary: "一列中存储一系列相关数据的集合", + Content: `将 ID 存储为一个列表,作为 VARCHAR/TEXT 列,这样能导致性能和数据完整性问题。查询这样的列需要使用模式匹配的表达式。使用逗号分隔的列表来做多表联结查询定位一行数据是极不优雅和耗时的。这将使验证 ID 更加困难。考虑一下,列表最多支持存放多少数据呢?将 ID 存储在一张单独的表中,代替使用多值属性,从而每个单独的属性值都可以占据一行。这样交叉表实现了两张表之间的多对多关系。这将更好地简化查询,也更有效地验证ID。`, + Case: "select c1,c2,c3,c4 from tab1 where col_id REGEXP '[[:<:]]12[[:>:]]'", + Func: (*Query4Audit).RuleMultiValueAttribute, + }, + "LIT.004": { + Item: "LIT.004", + Severity: "L1", + Summary: "请使用分号或已设定的 DELIMITER 结尾", + Content: `USE database, SHOW DATABASES 等命令也需要使用使用分号或已设定的 DELIMITER 结尾。`, + Case: "USE db", + Func: (*Query4Audit).RuleOK, // TODO: RuleAddDelimiter + }, + "RES.001": { + Item: "RES.001", + Severity: "L4", + Summary: "非确定性的 GROUP BY", + Content: `SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。`, + Case: "select c1,c2,c3 from t1 where c2='foo' group by c2", + Func: (*Query4Audit).RuleNoDeterministicGroupby, + }, + "RES.002": { + Item: "RES.002", + Severity: "L4", + Summary: "未使用 ORDER BY 的 LIMIT 查询", + Content: `没有 ORDER BY 的 LIMIT 会导致非确定性的结果,这取决于查询执行计划。`, + Case: "select col1,col2 from tbl where name=xx limit 10", + Func: (*Query4Audit).RuleNoDeterministicLimit, + }, + "RES.003": { + Item: "RES.003", + Severity: "L4", + Summary: "UPDATE/DELETE 操作使用了 LIMIT 条件", + Content: `UPDATE/DELETE 操作使用 LIMIT 条件和不添加 WHERE 条件一样危险,它可将会导致主从数据不一致或从库同步中断。`, + Case: "UPDATE film SET length = 120 WHERE title = 'abc' LIMIT 1;", + Func: (*Query4Audit).RuleUpdateDeleteWithLimit, + }, + "RES.004": { + Item: "RES.004", + Severity: "L4", + Summary: "UPDATE/DELETE 操作指定了 ORDER BY 条件", + Content: `UPDATE/DELETE 操作不要指定 ORDER BY 条件。`, + Case: "UPDATE film SET length = 120 WHERE title = 'abc' ORDER BY title", + Func: (*Query4Audit).RuleUpdateDeleteWithOrderby, + }, + "RES.005": { + Item: "RES.005", + Severity: "L4", + Summary: "UPDATE 语句可能存在逻辑错误,导致数据损坏", + Content: "在一条 UPDATE 语句中,如果要更新多个字段,字段间不能使用 AND ,而应该用逗号分隔。", + Case: "update tbl set col = 1 and cl = 2 where col=3;", + Func: (*Query4Audit).RuleUpdateSetAnd, + }, + "RES.006": { + Item: "RES.006", + Severity: "L4", + Summary: "永远不真的比较条件", + Content: "查询条件永远非真,如果该条件出现在 where 中可能导致查询无匹配到的结果。", + Case: "select * from tbl where 1 != 1;", + Func: (*Query4Audit).RuleImpossibleWhere, + }, + "RES.007": { + Item: "RES.007", + Severity: "L4", + Summary: "永远为真的比较条件", + Content: "查询条件永远为真,可能导致 WHERE 条件失效进行全表查询。", + Case: "select * from tbl where 1 = 1;", + Func: (*Query4Audit).RuleMeaninglessWhere, + }, + "RES.008": { + Item: "RES.008", + Severity: "L2", + Summary: "不建议使用LOAD DATA/SELECT ... INTO OUTFILE", + Content: "SELECT INTO OUTFILE 需要授予 FILE 权限,这通过会引入安全问题。LOAD DATA 虽然可以提高数据导入速度,但同时也可能导致从库同步延迟过大。", + Case: "LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;", + Func: (*Query4Audit).RuleLoadFile, + }, + "SEC.001": { + Item: "SEC.001", + Severity: "L0", + Summary: "请谨慎使用TRUNCATE操作", + Content: `一般来说想清空一张表最快速的做法就是使用TRUNCATE TABLE tbl_name;语句。但TRUNCATE操作也并非是毫无代价的,TRUNCATE TABLE无法返回被删除的准确行数,如果需要返回被删除的行数建议使用DELETE语法。TRUNCATE 操作还会重置 AUTO_INCREMENT,如果不想重置该值建议使用 DELETE FROM tbl_name WHERE 1;替代。TRUNCATE 操作会对数据字典添加源数据锁(MDL),当一次需要 TRUNCATE 很多表时会影响整个实例的所有请求,因此如果要 TRUNCATE 多个表建议用 DROP+CREATE 的方式以减少锁时长。`, + Case: "TRUNCATE TABLE tbl_name", + Func: (*Query4Audit).RuleTruncateTable, + }, + "SEC.002": { + Item: "SEC.002", + Severity: "L0", + Summary: "不使用明文存储密码", + Content: `使用明文存储密码或者使用明文在网络上传递密码都是不安全的。如果攻击者能够截获您用来插入密码的SQL语句,他们就能直接读到密码。另外,将用户输入的字符串以明文的形式插入到纯SQL语句中,也会让攻击者发现它。如果您能够读取密码,黑客也可以。解决方案是使用单向哈希函数对原始密码进行加密编码。哈希是指将输入字符串转化成另一个新的、不可识别的字符串的函数。对密码加密表达式加点随机串来防御“字典攻击”。不要将明文密码输入到SQL查询语句中。在应用程序代码中计算哈希串,只在SQL查询中使用哈希串。`, + Case: "create table test(id int,name varchar(20) not null,password varchar(200)not null)", + Func: (*Query4Audit).RuleReadablePasswords, + }, + "SEC.003": { + Item: "SEC.003", + Severity: "L0", + Summary: "使用DELETE/DROP/TRUNCATE等操作时注意备份", + Content: `在执行高危操作之前对数据进行备份是十分有必要的。`, + Case: "delete from table where col = 'condition'", + Func: (*Query4Audit).RuleDataDrop, + }, + "STA.001": { + Item: "STA.001", + Severity: "L0", + Summary: "'!=' 运算符是非标准的", + Content: `"<>"才是标准SQL中的不等于运算符。`, + Case: "select col1,col2 from tbl where type!=0", + Func: (*Query4Audit).RuleStandardINEQ, + }, + "STA.002": { + Item: "STA.002", + Severity: "L1", + Summary: "库名或表名点后建议不要加空格", + Content: `当使用 db.table 或 table.column 格式访问表或字段时,请不要在点号后面添加空格,虽然这样语法正确。`, + Case: "select col from sakila. film", + Func: (*Query4Audit).RuleSpaceAfterDot, + }, + "STA.003": { + Item: "STA.003", + Severity: "L1", + Summary: "索引起名不规范", + Content: `建议普通二级索引以idx_为前缀,唯一索引以uk_为前缀。`, + Case: "select col from now where type!=0", + Func: (*Query4Audit).RuleIdxPrefix, + }, + "STA.004": { + Item: "STA.004", + Severity: "L1", + Summary: "起名时请不要使用字母、数字和下划线之外的字符", + Content: `以字母或下划线开头,名字只允许使用字母、数字和下划线。请统一大小写,不要使用驼峰命名法。不要在名字中出现连续下划线'__',这样很难辨认。`, + Case: "CREATE TABLE ` abc` (a int);", + Func: (*Query4Audit).RuleStandardName, + }, + "SUB.001": { + Item: "SUB.001", + Severity: "L4", + Summary: "MySQL 对子查询的优化效果不佳", + Content: `MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。`, + Case: "select col1,col2,col3 from table1 where col2 in(select col from table2)", + Func: (*Query4Audit).RuleInSubquery, + }, + "SUB.002": { + Item: "SUB.002", + Severity: "L2", + Summary: "如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION", + Content: `与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。`, + Case: "select teacher_id as id,people_name as name from t1,t2 where t1.teacher_id=t2.people_id union select student_id as id,people_name as name from t1,t2 where t1.student_id=t2.people_id", + Func: (*Query4Audit).RuleUNIONUsage, + }, + "SUB.003": { + Item: "SUB.003", + Severity: "L3", + Summary: "考虑使用 EXISTS 而不是 DISTINCT 子查询", + Content: `DISTINCT 关键字在对元组排序后删除重复。相反,考虑使用一个带有 EXISTS 关键字的子查询,您可以避免返回整个表。`, + Case: "SELECT DISTINCT c.c_id, c.c_name FROM c,e WHERE e.c_id = c.c_id", + Func: (*Query4Audit).RuleDistinctJoinUsage, + }, + // TODO: 5.6有了semi join 还要把 in 转成 exists 么? + // Use EXISTS instead of IN to check existence of data. + // http://www.winwire.com/25-tips-to-improve-sql-query-performance/ + "SUB.004": { + Item: "SUB.004", + Severity: "L3", + Summary: "执行计划中嵌套连接深度过深", + Content: `MySQL对子查询的优化效果不佳,MySQL将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。`, + Case: "SELECT * from tb where id in (select id from (select id from tb))", + Func: (*Query4Audit).RuleSubqueryDepth, + }, + // SUB.005灵感来自 https://blog.csdn.net/zhuocr/article/details/61192418 + "SUB.005": { + Item: "SUB.005", + Severity: "L8", + Summary: "子查询不支持LIMIT", + Content: `当前 MySQL 版本不支持在子查询中进行 'LIMIT & IN/ALL/ANY/SOME'。`, + Case: "SELECT * FROM staff WHERE name IN (SELECT NAME FROM customer ORDER BY name LIMIT 1)", + Func: (*Query4Audit).RuleSubQueryLimit, + }, + "SUB.006": { + Item: "SUB.006", + Severity: "L2", + Summary: "不建议在子查询中使用函数", + Content: `MySQL将外部查询中的每一行作为依赖子查询执行子查询,如果在子查询中使用函数,即使是semi-join也很难进行高效的查询。可以将子查询重写为OUTER JOIN语句并用连接条件对数据进行过滤。`, + Case: "SELECT * FROM staff WHERE name IN (SELECT max(NAME) FROM customer)", + Func: (*Query4Audit).RuleSubQueryFunctions, + }, + "TBL.001": { + Item: "TBL.001", + Severity: "L4", + Summary: "不建议使用分区表", + Content: `不建议使用分区表`, + Case: "CREATE TABLE trb3(id INT, name VARCHAR(50), purchased DATE) PARTITION BY RANGE(YEAR(purchased)) (PARTITION p0 VALUES LESS THAN (1990), PARTITION p1 VALUES LESS THAN (1995), PARTITION p2 VALUES LESS THAN (2000), PARTITION p3 VALUES LESS THAN (2005) );", + Func: (*Query4Audit).RulePartitionNotAllowed, + }, + "TBL.002": { + Item: "TBL.002", + Severity: "L4", + Summary: "请为表选择合适的存储引擎", + Content: `建表或修改表的存储引擎时建议使用推荐的存储引擎,如:` + strings.Join(common.Config.TableAllowEngines, ","), + Case: "create table test(`id` int(11) NOT NULL AUTO_INCREMENT)", + Func: (*Query4Audit).RuleAllowEngine, + }, + "TBL.003": { + Item: "TBL.003", + Severity: "L8", + Summary: "以DUAL命名的表在数据库中有特殊含义", + Content: `DUAL表为虚拟表,不需要创建即可使用,也不建议服务以DUAL命名表。`, + Case: "create table dual(id int, primary key (id));", + Func: (*Query4Audit).RuleCreateDualTable, + }, + "TBL.004": { + Item: "TBL.004", + Severity: "L2", + Summary: "表的初始AUTO_INCREMENT值不为0", + Content: `AUTO_INCREMENT不为0会导致数据空洞。`, + Case: "CREATE TABLE tbl (a int) AUTO_INCREMENT = 10;", + Func: (*Query4Audit).RuleAutoIncrementInitNotZero, + }, + "TBL.005": { + Item: "TBL.005", + Severity: "L4", + Summary: "请使用推荐的字符集", + Content: `表字符集只允许设置为` + strings.Join(common.Config.TableAllowCharsets, ","), + Case: "CREATE TABLE tbl (a int) DEFAULT CHARSET = latin1;", + Func: (*Query4Audit).RuleTableCharsetCheck, + }, + "TBL.006": { + Item: "TBL.006", + Severity: "L1", + Summary: "不建议使用视图", + Content: `不建议使用视图`, + Case: "create view v_today (today) AS SELECT CURRENT_DATE;", + Func: (*Query4Audit).RuleForbiddenView, + }, + "TBL.007": { + Item: "TBL.007", + Severity: "L1", + Summary: "不建议使用临时表", + Content: `不建议使用临时表`, + Case: "CREATE TEMPORARY TABLE `work` (`time` time DEFAULT NULL) ENGINE=InnoDB;", + Func: (*Query4Audit).RuleForbiddenTempTable, + }, + } +} + +// IsIgnoreRule 判断是否是过滤规则 +// 支持XXX*前缀匹配,OK规则不可设置过滤 +func IsIgnoreRule(item string) bool { + + for _, ir := range common.Config.IgnoreRules { + ir = strings.Trim(ir, "*") + if strings.HasPrefix(item, ir) && ir != "OK" && ir != "" { + common.Log.Debug("IsIgnoreRule: %s", item) + return true + } + } + return false +} + +// InBlackList 判断一条请求是否在黑名单列表中 +// 如果在返回true,表示不需要评审 +// 注意这里没有做指纹判断,是否用指纹在这个函数的外面处理 +func InBlackList(sql string) bool { + in := false + for _, r := range common.BlackList { + if sql == r { + in = true + break + } + re, err := regexp.Compile("(?i)" + r) + if err == nil { + if re.FindString(sql) != "" { + common.Log.Debug("InBlackList: true, regexp: %s, sql: %s", "(?i)"+r, sql) + in = true + break + } + common.Log.Debug("InBlackList: false, regexp: %s, sql: %s", "(?i)"+r, sql) + } + } + return in +} + +// FormatSuggest 格式化输出优化建议 +func FormatSuggest(sql string, format string, suggests ...map[string]Rule) (map[string]Rule, string) { + common.Log.Debug("FormatSuggest, Query: %s", sql) + var fingerprint, id string + var buf []string + var score = 100 + type Result struct { + ID string + Fingerprint string + Sample string + Suggest map[string]Rule + } + + // 生成指纹和ID + if sql != "" { + fingerprint = query.Fingerprint(sql) + id = query.Id(fingerprint) + } + + // 合并重复的建议 + suggest := make(map[string]Rule) + for _, s := range suggests { + for item, rule := range s { + suggest[item] = rule + } + } + suggest = MergeConflictHeuristicRules(suggest) + + // 是否忽略显示OK建议,测试的时候大家都喜欢看OK,线上跑起来的时候OK太多反而容易看花眼 + ignoreOK := false + for _, r := range common.Config.IgnoreRules { + if "OK" == r { + ignoreOK = true + } + } + + // 先保证suggest中有元素,然后再根据ignore配置删除不需要的项 + if len(suggest) < 1 { + suggest = map[string]Rule{"OK": HeuristicRules["OK"]} + } + if ignoreOK || len(suggest) > 1 { + delete(suggest, "OK") + } + for k := range suggest { + if IsIgnoreRule(k) { + delete(suggest, k) + } + } + common.Log.Debug("FormatSuggest, format: %s", format) + switch format { + case "json": + js, err := json.MarshalIndent(Result{ + ID: id, + Fingerprint: fingerprint, + Sample: sql, + Suggest: suggest, + }, "", " ") + if err == nil { + buf = append(buf, fmt.Sprintln(string(js))) + } else { + common.Log.Error("FormatSuggest json.Marshal Error: %v", err) + } + + case "text": + for item, rule := range suggest { + buf = append(buf, fmt.Sprintln("Query: ", sql)) + buf = append(buf, fmt.Sprintln("ID: ", id)) + buf = append(buf, fmt.Sprintln("Item: ", item)) + buf = append(buf, fmt.Sprintln("Severity: ", rule.Severity)) + buf = append(buf, fmt.Sprintln("Summary: ", rule.Summary)) + buf = append(buf, fmt.Sprintln("Content: ", rule.Content)) + } + case "lint": + for item, rule := range suggest { + // lint 中无需关注 OK 和 EXP + if item != "OK" && !strings.HasPrefix(item, "EXP") { + buf = append(buf, fmt.Sprintf("%s %s", item, rule.Summary)) + } + } + + case "markdown", "html", "explain-digest", "duplicate-key-checker": + if sql != "" && len(suggest) > 0 { + switch common.Config.ExplainSQLReportType { + case "fingerprint": + buf = append(buf, fmt.Sprintf("# Query: %s\n", id)) + buf = append(buf, fmt.Sprintf("```sql\n%s\n```\n", fingerprint)) + case "sample": + buf = append(buf, fmt.Sprintf("# Query: %s\n", id)) + buf = append(buf, fmt.Sprintf("```sql\n%s\n```\n", sql)) + default: + buf = append(buf, fmt.Sprintf("# Query: %s\n", id)) + buf = append(buf, fmt.Sprintf("```sql\n%s\n```\n", ast.Pretty(sql, format))) + } + } + // MySQL + common.Log.Debug("FormatSuggest, start of sortedMySQLSuggest") + var sortedMySQLSuggest []string + for item := range suggest { + if strings.HasPrefix(item, "ERR") { + if suggest[item].Content == "" { + delete(suggest, item) + } else { + sortedMySQLSuggest = append(sortedMySQLSuggest, item) + } + } + } + sort.Strings(sortedMySQLSuggest) + if len(sortedMySQLSuggest) > 0 { + buf = append(buf, "## MySQL execute failed\n") + } + for _, item := range sortedMySQLSuggest { + buf = append(buf, fmt.Sprintln(suggest[item].Content)) + score = 0 + delete(suggest, item) + } + + // Explain + common.Log.Debug("FormatSuggest, start of sortedExplainSuggest") + if suggest["EXP.000"].Item != "" { + buf = append(buf, fmt.Sprintln("## ", suggest["EXP.000"].Summary)) + buf = append(buf, fmt.Sprintln(suggest["EXP.000"].Content)) + buf = append(buf, fmt.Sprint(suggest["EXP.000"].Case, "\n")) + delete(suggest, "EXP.000") + } + var sortedExplainSuggest []string + for item := range suggest { + if strings.HasPrefix(item, "EXP") { + sortedExplainSuggest = append(sortedExplainSuggest, item) + } + } + sort.Strings(sortedExplainSuggest) + for _, item := range sortedExplainSuggest { + buf = append(buf, fmt.Sprintln("### ", suggest[item].Summary)) + buf = append(buf, fmt.Sprintln(suggest[item].Content)) + buf = append(buf, fmt.Sprint(suggest[item].Case, "\n")) + } + + // Profiling + common.Log.Debug("FormatSuggest, start of sortedProfilingSuggest") + var sortedProfilingSuggest []string + for item := range suggest { + if strings.HasPrefix(item, "PRO") { + sortedProfilingSuggest = append(sortedProfilingSuggest, item) + } + } + sort.Strings(sortedProfilingSuggest) + if len(sortedProfilingSuggest) > 0 { + buf = append(buf, "## Profiling信息\n") + } + for _, item := range sortedProfilingSuggest { + buf = append(buf, fmt.Sprintln(suggest[item].Content)) + delete(suggest, item) + } + + // Trace + common.Log.Debug("FormatSuggest, start of sortedTraceSuggest") + var sortedTraceSuggest []string + for item := range suggest { + if strings.HasPrefix(item, "TRA") { + sortedTraceSuggest = append(sortedTraceSuggest, item) + } + } + sort.Strings(sortedTraceSuggest) + if len(sortedTraceSuggest) > 0 { + buf = append(buf, "## Trace信息\n") + } + for _, item := range sortedTraceSuggest { + buf = append(buf, fmt.Sprintln(suggest[item].Content)) + delete(suggest, item) + } + + // Index + common.Log.Debug("FormatSuggest, start of sortedIdxSuggest") + var sortedIdxSuggest []string + for item := range suggest { + if strings.HasPrefix(item, "IDX") { + sortedIdxSuggest = append(sortedIdxSuggest, item) + } + } + sort.Strings(sortedIdxSuggest) + for _, item := range sortedIdxSuggest { + buf = append(buf, fmt.Sprintln("## ", common.MarkdownEscape(suggest[item].Summary))) + buf = append(buf, fmt.Sprintln("* **Item:** ", item)) + buf = append(buf, fmt.Sprintln("* **Severity:** ", suggest[item].Severity)) + minus, err := strconv.Atoi(strings.Trim(suggest[item].Severity, "L")) + if err == nil { + score = score - minus*5 + } else { + common.Log.Debug("FormatSuggest, sortedIdxSuggest, strconv.Atoi, Error: ", err) + score = 0 + } + buf = append(buf, fmt.Sprintln("* **Content:** ", common.MarkdownEscape(suggest[item].Content))) + + if format == "duplicate-key-checker" { + buf = append(buf, fmt.Sprintf("* **原建表语句:** \n```sql\n%s\n```\n", suggest[item].Case), "\n\n") + } else { + buf = append(buf, fmt.Sprint("* **Case:** ", common.MarkdownEscape(suggest[item].Case), "\n\n")) + } + } + + // Heuristic + common.Log.Debug("FormatSuggest, start of sortedHeuristicSuggest") + var sortedHeuristicSuggest []string + for item := range suggest { + if !strings.HasPrefix(item, "EXP") && + !strings.HasPrefix(item, "IDX") && + !strings.HasPrefix(item, "PRO") { + sortedHeuristicSuggest = append(sortedHeuristicSuggest, item) + } + } + sort.Strings(sortedHeuristicSuggest) + for _, item := range sortedHeuristicSuggest { + buf = append(buf, fmt.Sprintln("## ", suggest[item].Summary)) + if item == "OK" { + continue + } + buf = append(buf, fmt.Sprintln("* **Item:** ", item)) + buf = append(buf, fmt.Sprintln("* **Severity:** ", suggest[item].Severity)) + minus, err := strconv.Atoi(strings.Trim(suggest[item].Severity, "L")) + if err == nil { + score = score - minus*5 + } else { + common.Log.Debug("FormatSuggest, sortedHeuristicSuggest, strconv.Atoi, Error: ", err) + score = 0 + } + buf = append(buf, fmt.Sprintln("* **Content:** ", common.MarkdownEscape(suggest[item].Content))) + // buf = append(buf, fmt.Sprint("* **Case:** ", common.MarkdownEscape(suggest[item].Case), "\n\n")) + } + + default: + common.Log.Debug("report-type: %s", format) + buf = append(buf, fmt.Sprintln("Query: ", sql)) + for _, rule := range suggest { + buf = append(buf, pretty.Sprint(rule)) + } + } + + // 打分 + var str string + switch common.Config.ReportType { + case "markdown", "html": + if len(buf) > 1 { + str = buf[0] + "\n" + common.Score(score) + "\n\n" + strings.Join(buf[1:], "\n") + } + default: + str = strings.Join(buf, "\n") + } + + return suggest, str +} + +// ListHeuristicRules 打印支持的启发式规则,对应命令行参数-list-heuristic-rules +func ListHeuristicRules(rules ...map[string]Rule) { + switch common.Config.ReportType { + case "json": + js, err := json.MarshalIndent(rules, "", " ") + if err == nil { + fmt.Println(string(js)) + } + default: + fmt.Print("# 启发式规则建议\n\n[toc]\n\n") + for _, r := range rules { + delete(r, "OK") + for _, item := range common.SortedKey(r) { + fmt.Print("## ", common.MarkdownEscape(r[item].Summary), + "\n\n* **Item**:", r[item].Item, + "\n* **Severity**:", r[item].Severity, + "\n* **Content**:", common.MarkdownEscape(r[item].Content), + "\n* **Case**:\n\n```sql\n", r[item].Case, "\n```\n") + } + } + } +} + +// ListTestSQLs 打印测试用的SQL,方便测试,对应命令行参数-list-test-sqls +func ListTestSQLs() { + for _, sql := range common.TestSQLs { + fmt.Println(sql) + } +} diff --git a/vendor/github.com/XiaoMi/soar/advisor/rules_test.go b/vendor/github.com/XiaoMi/soar/advisor/rules_test.go new file mode 100644 index 0000000000000000000000000000000000000000..938a54601813c974ca9607aadd04ba141153e436 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/advisor/rules_test.go @@ -0,0 +1,54 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 advisor + +import ( + "flag" + "testing" + + "github.com/XiaoMi/soar/common" +) + +var update = flag.Bool("update", false, "update .golden files") + +func TestListTestSQLs(t *testing.T) { + err := common.GoldenDiff(func() { ListTestSQLs() }, t.Name(), update) + if nil != err { + t.Fatal(err) + } +} + +func TestListHeuristicRules(t *testing.T) { + err := common.GoldenDiff(func() { ListHeuristicRules(HeuristicRules) }, t.Name(), update) + if nil != err { + t.Fatal(err) + } +} + +func TestInBlackList(t *testing.T) { + common.BlackList = []string{"select"} + if !InBlackList("select 1") { + t.Error("should be true") + } +} + +func TestIsIgnoreRule(t *testing.T) { + common.Config.IgnoreRules = []string{"test"} + if !IsIgnoreRule("test") { + t.Error("should be true") + } +} diff --git a/vendor/github.com/XiaoMi/soar/ast/doc.go b/vendor/github.com/XiaoMi/soar/ast/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..43bbb74fcc7edf895a370077c6f91bf29ecc63f5 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/ast/doc.go @@ -0,0 +1,18 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 ast is an interface for Abstract Syntax Tree parser +package ast diff --git a/vendor/github.com/XiaoMi/soar/ast/meta.go b/vendor/github.com/XiaoMi/soar/ast/meta.go new file mode 100644 index 0000000000000000000000000000000000000000..48323ffd86c1c75c9adb8ea281aeb71770e91c77 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/ast/meta.go @@ -0,0 +1,779 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 ast + +import ( + "fmt" + "strings" + + "github.com/XiaoMi/soar/common" + "vitess.io/vitess/go/vt/sqlparser" +) + +// GetTableFromExprs 从sqlparser.Exprs中获取所有的库表 +func GetTableFromExprs(exprs sqlparser.TableExprs, metas ...common.Meta) common.Meta { + meta := make(map[string]*common.DB) + if len(metas) >= 1 { + meta = metas[0] + } + + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.AliasedTableExpr: + + switch table := expr.Expr.(type) { + case sqlparser.TableName: + db := table.Qualifier.String() + tb := table.Name.String() + + if meta[db] == nil { + meta[db] = common.NewDB(db) + } + + meta[db].Table[tb] = common.NewTable(tb) + + // alias去重 + aliasExist := false + for _, existedAlias := range meta[db].Table[tb].TableAliases { + if existedAlias == expr.As.String() { + aliasExist = true + } + } + + if !aliasExist { + meta[db].Table[tb].TableAliases = append(meta[db].Table[tb].TableAliases, expr.As.String()) + } + } + } + return true, nil + }, exprs) + common.LogIfWarn(err, "") + return meta +} + +// GetMeta 获取元数据信息,构建到db->table层级。 +// 从 SQL 或 Statement 中获取表信息,并返回。当 meta 不为 nil 时,返回值会将新老 meta 合并去重 +func GetMeta(stmt sqlparser.Statement, meta common.Meta) common.Meta { + // 初始化meta + if meta == nil { + meta = make(map[string]*common.DB) + } + + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.DDL: + // 如果 SQL 是一个 DDL,则不需要继续遍历语法树了 + for _, tb := range expr.FromTables { + appendTable(tb, "", meta) + } + + for _, tb := range expr.ToTables { + appendTable(tb, "", meta) + } + + appendTable(expr.Table, "", meta) + return false, nil + case *sqlparser.AliasedTableExpr: + // 非 DDL 情况下处理 TableExpr + // 在 sqlparser 中存在三种 TableExpr: AliasedTableExpr,ParenTableExpr 以及 JoinTableExpr。 + // 其中 AliasedTableExpr 是其他两种 TableExpr 的基础组成,SQL中的 表信息(别名、前缀)在这个结构体中。 + + switch table := expr.Expr.(type) { + + // 获取表名、别名与前缀名(数据库名) + // 表名存放在 AST 中 TableName 里,包含表名与表前缀名。 + // 当与 As 相对应的 Expr 为 TableName 的时候,别名才是一张实体表的别名,否则为结果集的别名。 + case sqlparser.TableName: + appendTable(table, expr.As.String(), meta) + default: + // 如果 AliasedTableExpr 中的 Expr 不是 TableName 结构体,则表示该表为一个查询结果集(子查询或临时表)。 + // 在这里记录一下别名,但将列名制空,用来保证在其他环节中判断列前缀的时候不会有遗漏 + // 最终结果为所有的子查询别名都会归于 ""(空) 数据库 ""(空) 表下,对于空数据库,空表后续在索引优化时直接PASS + if meta == nil { + meta = make(map[string]*common.DB) + } + + if meta[""] == nil { + meta[""] = common.NewDB("") + } + + meta[""].Table[""] = common.NewTable("") + meta[""].Table[""].TableAliases = append(meta[""].Table[""].TableAliases, expr.As.String()) + } + } + return true, nil + }, stmt) + common.LogIfWarn(err, "") + return meta +} + +// appendTable 将 sqlparser.TableName 中的库表信息提取后放到 meta 中 +// @tb 为 sqlparser.TableName 对象 +// @as 为该表的别名,无别名时为空 +// @meta 为信息集合 +func appendTable(tb sqlparser.TableName, as string, meta map[string]*common.DB) map[string]*common.DB { + if meta == nil { + return meta + } + + dbName := tb.Qualifier.String() + tbName := tb.Name.String() + if tbName == "" { + return meta + } + + if meta[dbName] == nil { + meta[dbName] = common.NewDB(dbName) + } + + meta[dbName].Table[tbName] = common.NewTable(tbName) + mergeAlias(dbName, tbName, as, meta) + + return meta +} + +// mergeAlias 将所有的表别名归并到一个表下 +func mergeAlias(db, tb, as string, meta map[string]*common.DB) { + if meta == nil || as == "" { + return + } + + aliasExist := false + for _, existedAlias := range meta[db].Table[tb].TableAliases { + if existedAlias == as { + aliasExist = true + } + } + + if !aliasExist { + meta[db].Table[tb].TableAliases = append(meta[db].Table[tb].TableAliases, as) + } +} + +// eqOperators 等值条件判断关键字 +var eqOperators = map[string]string{ + "=": "eq", + "<=>": "eq", + "is true": "eq", + "is false": "eq", + "is not true": "eq", + "is not false": "eq", + "is null": "eq", + "in": "eq", // 单值的in属于等值条件 +} + +// inEqOperators 非等值条件判断关键字 +var inEqOperators = map[string]string{ + "<": "inEq", + ">": "inEq", + "<=": "inEq", + ">=": "inEq", + "!=": "inEq", + "is not null": "inEq", + "like": "inEq", + "not like": "inEq", + "->": "inEq", + "->>": "inEq", + "between": "inEq", + "not between": "inEq", + "in": "inEq", // 多值in属于非等值条件 + + // 某些非等值条件无需添加索引,所以忽略即可 + // 比如"not in",比如"exists"、 "not exists"等 +} + +// FindColumn 从传入的 node 中获取所有可能加索引的的 column 信息 +func FindColumn(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindColumn, Caller: %s", common.Caller()) + var result []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch col := node.(type) { + case *sqlparser.FuncExpr: + // 忽略function + return false, nil + case *sqlparser.ColName: + result = common.MergeColumn(result, &common.Column{ + Name: col.Name.String(), + Table: col.Qualifier.Name.String(), + DB: col.Qualifier.Qualifier.String(), + Alias: make([]string, 0), + }) + } + + return true, nil + }, node) + common.LogIfWarn(err, "") + return result +} + +// inEqIndexAble 判断非等值查询条件是否可以复用到索引 +// Output: true 可以考虑添加索引, false 不需要添加索引 +func inEqIndexAble(node sqlparser.SQLNode) bool { + common.Log.Debug("Enter: inEqIndexAble(), Caller: %s", common.Caller()) + var indexAble bool + switch expr := node.(type) { + case *sqlparser.ComparisonExpr: + // like前百分号查询无法使用索引 + // TODO: date 类型的 like 属于隐式数据类型转换,会导致无法使用索引 + if expr.Operator == "like" || expr.Operator == "not like" { + switch right := expr.Right.(type) { + case *sqlparser.SQLVal: + return !(strings.HasPrefix(string(right.Val), "%")) + } + } + + // 如果是in查询,则需要判断in查询是否是多值查询 + if expr.Operator == "in" { + switch right := expr.Right.(type) { + case sqlparser.ValTuple: + // 若是单值查询则应该属于等值条件而非非等值条件 + return len(right) > 1 + } + } + + _, indexAble = inEqOperators[expr.Operator] + + case *sqlparser.IsExpr: + _, indexAble = inEqOperators[expr.Operator] + + case *sqlparser.RangeCond: + _, indexAble = inEqOperators[expr.Operator] + + default: + indexAble = false + } + return indexAble +} + +// FindWhereEQ 找到Where中的等值条件 +func FindWhereEQ(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindWhereEQ(), Caller: %s", common.Caller()) + return append(FindEQColsInWhere(node), FindEQColsInJoinCond(node)...) +} + +// FindWhereINEQ 找到Where条件中的非等值条件 +func FindWhereINEQ(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindWhereINEQ(), Caller: %s", common.Caller()) + return append(FindINEQColsInWhere(node), FindINEQColsInJoinCond(node)...) +} + +// FindEQColsInWhere 获取等值条件信息 +// 将所有值得加索引的condition条件信息进行过滤 +func FindEQColsInWhere(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindEQColsInWhere(), Caller: %s", common.Caller()) + var columns []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + // 对AST中所有节点进行扫描 + case *sqlparser.Subquery, *sqlparser.JoinTableExpr, *sqlparser.BinaryExpr, *sqlparser.OrExpr: + // 忽略子查询,join condition,数值计算,or condition + return false, nil + + case *sqlparser.ComparisonExpr: + var newCols []*common.Column + // ComparisonExpr中可能含有等值查询列条件 + switch node.Operator { + case "in": + // 对in进行特别判断,只有单值的in条件才算做是等值查询 + switch right := node.Right.(type) { + case sqlparser.ValTuple: + if len(right) == 1 { + newCols = FindColumn(node) + } + } + + default: + if _, ok := eqOperators[node.Operator]; ok { + newCols = FindColumn(node) + } + } + + // operator两边都为列的情况不提供索引建议 + // 如果该列位于function中则不予提供索引建议 + if len(newCols) == 1 { + columns = common.MergeColumn(columns, newCols[0]) + } + + case *sqlparser.IsExpr: + // IsExpr中可能含有等值查询列条件 + if _, ok := eqOperators[node.Operator]; ok { + newCols := FindColumn(node) + if len(newCols) == 1 { + columns = common.MergeColumn(columns, newCols[0]) + } + } + } + return true, nil + + }, node) + common.LogIfWarn(err, "") + return columns +} + +// FindINEQColsInWhere 获取非等值条件中可能需要加索引的列 +// 将所有值得加索引的condition条件信息进行过滤 +// TODO: 将 where 条件中隐含的 join 条件合并到 join condition中 +func FindINEQColsInWhere(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindINEQColsInWhere(), Caller: %s", common.Caller()) + var columns []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + // 对AST中所有节点进行扫描 + case *sqlparser.Subquery, *sqlparser.JoinTableExpr, *sqlparser.BinaryExpr, *sqlparser.OrExpr: + // 忽略子查询,join condition,数值计算,or condition + return false, nil + + case *sqlparser.ComparisonExpr: + // ComparisonExpr中可能含有非等值查询列条件 + if inEqIndexAble(node) { + newCols := FindColumn(node) + // operator两边都为列的情况不提供索引建议 + if len(newCols) == 1 { + columns = common.MergeColumn(columns, newCols[0]) + } + } + case *sqlparser.IsExpr: + // IsExpr中可能含有非等值查询列条件 + if inEqIndexAble(node) { + newCols := FindColumn(node) + if len(newCols) == 1 { + columns = common.MergeColumn(columns, newCols[0]) + } + } + + case *sqlparser.RangeCond: + // RangeCond中只存在非等值条件查询 + if inEqIndexAble(node) { + columns = common.MergeColumn(columns, FindColumn(node)...) + } + } + + return true, nil + + }, node) + common.LogIfWarn(err, "") + return columns +} + +// FindGroupByCols 获取groupBy中可能需要加索引的列信息 +func FindGroupByCols(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindGroupByCols(), Caller: %s", common.Caller()) + isIgnore := false + var columns []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case sqlparser.GroupBy: + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + case *sqlparser.BinaryExpr, *sqlparser.FuncExpr: + // 如果group by中出现数值计算、函数等 + isIgnore = true + return false, nil + default: + columns = common.MergeColumn(columns, FindColumn(node)...) + } + return true, nil + }, expr) + common.LogIfWarn(err, "") + case *sqlparser.Subquery, *sqlparser.JoinTableExpr, *sqlparser.BinaryExpr: + // 忽略子查询,join condition以及数值计算 + return false, nil + } + return true, nil + }, node) + common.LogIfWarn(err, "") + if isIgnore { + return []*common.Column{} + } + + return columns +} + +// FindOrderByCols 为索引优化获取orderBy中可能添加索引的列信息 +func FindOrderByCols(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindOrderByCols(), Caller: %s", common.Caller()) + var columns []*common.Column + lastDirection := "" + directionNotEq := false + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.Order: + // MySQL对于排序顺序不同的查询无法使用索引(8.0后支持) + if lastDirection != "" && expr.Direction != lastDirection { + directionNotEq = true + return false, nil + } + lastDirection = expr.Direction + columns = common.MergeColumn(columns, FindColumn(expr)...) + case *sqlparser.Subquery, *sqlparser.JoinTableExpr, *sqlparser.BinaryExpr: + // 忽略子查询,join condition以及数值计算 + return false, nil + } + return true, nil + }, node) + common.LogIfWarn(err, "") + if directionNotEq { + // 当发现Order by中排序顺序不同时,即放弃Oder by条件中的字段 + return []*common.Column{} + } + + return columns +} + +// FindJoinTable 获取 Join 中需要添加索引的表 +// join 优化添加索引分为三种类型:1. inner join, 2. left join, 3.right join +// 针对三种优化类型,需要三种不同的索引添加方案: +// 1. inner join 需要对 join 左右的表添加索引 +// 2. left join 由于左表为全表扫描,需要对右表的关联列添加索引。 +// 3. right join 与 left join 相反,需要对左表的关联列添加索引。 +// 以上添加索引的策略前提为join的表为实体表而非临时表。 +func FindJoinTable(node sqlparser.SQLNode, meta common.Meta) common.Meta { + common.Log.Debug("Enter: FindJoinTable(), Caller: %s", common.Caller()) + if meta == nil { + meta = make(common.Meta) + } + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.JoinTableExpr: + switch expr.Join { + case sqlparser.JoinStr, sqlparser.NaturalJoinStr: + // 两边表都需要 + findJoinTable(expr.LeftExpr, meta) + findJoinTable(expr.RightExpr, meta) + case sqlparser.LeftJoinStr, sqlparser.NaturalLeftJoinStr, sqlparser.StraightJoinStr: + // 只需要右表 + findJoinTable(expr.RightExpr, meta) + + case sqlparser.RightJoinStr, sqlparser.NaturalRightJoinStr: + // 只需要左表 + findJoinTable(expr.LeftExpr, meta) + } + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return meta +} + +// findJoinTable 获取join table +func findJoinTable(expr sqlparser.TableExpr, meta common.Meta) { + common.Log.Debug("Enter: findJoinTable(), Caller: %s", common.Caller()) + if meta == nil { + meta = make(common.Meta) + } + switch tableExpr := expr.(type) { + case *sqlparser.AliasedTableExpr: + switch table := tableExpr.Expr.(type) { + // 获取表名、别名与前缀名(数据库名) + // 表名存放在 AST 中 TableName 里,包含表名与表前缀名。 + // 当与 As 相对应的 Expr 为 TableName 的时候,别名才是一张实体表的别名,否则为结果集的别名。 + case sqlparser.TableName: + db := table.Qualifier.String() + tb := table.Name.String() + + if meta == nil { + meta = make(map[string]*common.DB) + } + + if meta[db] == nil { + meta[db] = common.NewDB(db) + } + + meta[db].Table[tb] = common.NewTable(tb) + + // alias去重 + aliasExist := false + for _, existedAlias := range meta[db].Table[tb].TableAliases { + if existedAlias == tableExpr.As.String() { + aliasExist = true + } + } + if !aliasExist { + meta[db].Table[tb].TableAliases = append(meta[db].Table[tb].TableAliases, tableExpr.As.String()) + } + } + case *sqlparser.ParenTableExpr: + // join 时可能会同时 join 多张表 + for _, tbExpr := range tableExpr.Exprs { + findJoinTable(tbExpr, meta) + } + default: + // 如果是如上两种类型都没有命中,说明join的表为临时表,递归调用 FindJoinTable 继续下探查找。 + // NOTE: 这里需要注意的是,如果不递归寻找,如果存在子查询结果集的join表,subquery也会把这个查询提取出。 + // 所以针对default这一段理论上可以忽略处理(待测试) + FindJoinTable(tableExpr, meta) + } +} + +// FindJoinCols 获取 join condition 中使用到的列(必须是 `列 operator 列` 的情况。 +// 如果列对应的值或是 function,则应该移到where condition中) +// 某些 where 条件隐含在 join 条件中(INNER JOIN) +func FindJoinCols(node sqlparser.SQLNode) [][]*common.Column { + common.Log.Debug("Enter: FindJoinCols(), Caller: %s", common.Caller()) + var columns [][]*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.JoinTableExpr: + // on + if on := expr.Condition.On; on != nil { + cols := FindColumn(expr.Condition.On) + if len(cols) > 1 { + columns = append(columns, cols) + } + } + + // using + if using := expr.Condition.Using; using != nil { + left := "" + right := "" + + switch tableExpr := expr.LeftExpr.(type) { + case *sqlparser.AliasedTableExpr: + switch table := tableExpr.Expr.(type) { + case sqlparser.TableName: + left = table.Name.String() + } + } + + switch tableExpr := expr.RightExpr.(type) { + case *sqlparser.AliasedTableExpr: + switch table := tableExpr.Expr.(type) { + case sqlparser.TableName: + right = table.Name.String() + } + } + + var cols []*common.Column + for _, col := range using { + if left != "" { + cols = append(cols, &common.Column{ + Name: col.String(), + Table: left, + Alias: make([]string, 0), + }) + } + + if right != "" { + cols = append(cols, &common.Column{ + Name: col.String(), + Table: right, + Alias: make([]string, 0), + }) + } + + } + columns = append(columns, cols) + + } + + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return columns +} + +// FindEQColsInJoinCond 获取 join condition 中应转为whereEQ条件的列 +func FindEQColsInJoinCond(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindEQColsInJoinCond(), Caller: %s", common.Caller()) + var columns []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case sqlparser.JoinCondition: + columns = append(columns, FindEQColsInWhere(expr)...) + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return columns +} + +// FindINEQColsInJoinCond 获取 join condition 中应转为whereINEQ条件的列 +func FindINEQColsInJoinCond(node sqlparser.SQLNode) []*common.Column { + common.Log.Debug("Enter: FindINEQColsInJoinCond(), Caller: %s", common.Caller()) + var columns []*common.Column + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case sqlparser.JoinCondition: + columns = append(columns, FindINEQColsInWhere(expr)...) + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return columns +} + +// FindSubquery 拆分subquery,获取最深层的subquery +// 为索引优化获取subquery中包含的列信息 +func FindSubquery(depth int, node sqlparser.SQLNode, queries ...string) []string { + common.Log.Debug("Enter: FindSubquery(), Caller: %s", common.Caller()) + if queries == nil { + queries = make([]string, 0) + } + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + // 查找SQL中的子查询 + case *sqlparser.Subquery: + noSub := true + // 查看子查询中是否还包含子查询,如果包含,递归找到最深层的子查询 + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch sub := node.(type) { + case *sqlparser.Subquery: + noSub = false + // 查找深度depth,超过最大深度后不再向下查找 + depth = depth + 1 + if depth < common.Config.MaxSubqueryDepth { + queries = append(queries, FindSubquery(depth, sub.Select)...) + } + } + return true, nil + }, expr.Select) + common.LogIfWarn(err, "") + + // 如果没有嵌套的子查询了,返回子查询的SQL + if noSub { + sql := sqlparser.String(expr) + // 去除SQL前后的括号 + queries = append(queries, sql[1:len(sql)-1]) + } + + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return queries +} + +// FindAllCondition 获取 AST 中所有的 condition 条件 +func FindAllCondition(node sqlparser.SQLNode) []interface{} { + common.Log.Debug("Enter: FindAllCondition(), Caller: %s", common.Caller()) + var conditions []interface{} + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + case *sqlparser.ComparisonExpr, *sqlparser.RangeCond, *sqlparser.IsExpr: + conditions = append(conditions, node) + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return conditions +} + +// Expression describe sql expression type +type Expression string + +const ( + // WhereExpression 用于标记 where + WhereExpression Expression = "where" + // JoinExpression 用于标记 join + JoinExpression Expression = "join" + // GroupByExpression 用于标记 group by + GroupByExpression Expression = "group by" + // OrderByExpression 用于标记 order by + OrderByExpression Expression = "order by" +) + +// FindAllCols 获取 AST 中某个节点下所有的 columns +func FindAllCols(node sqlparser.SQLNode, targets ...Expression) []*common.Column { + var result []*common.Column + // 获取节点内所有的列 + f := func(node sqlparser.SQLNode) { + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch col := node.(type) { + case *sqlparser.ColName: + result = common.MergeColumn(result, &common.Column{ + Name: col.Name.String(), + Table: col.Qualifier.Name.String(), + DB: col.Qualifier.Qualifier.String(), + Alias: make([]string, 0), + }) + } + return true, nil + }, node) + common.LogIfWarn(err, "") + } + + if len(targets) == 0 { + // 如果不指定具体节点类型,则获取全部的column + f(node) + } else { + // 根据target获取所有的节点 + for _, target := range targets { + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node := node.(type) { + case *sqlparser.Subquery: + // 忽略子查询 + case *sqlparser.JoinTableExpr: + if target == JoinExpression { + f(node) + } + case *sqlparser.Where: + if target == WhereExpression { + f(node) + } + case sqlparser.GroupBy: + if target == GroupByExpression { + f(node) + } + case sqlparser.OrderBy: + if target == OrderByExpression { + f(node) + } + } + return true, nil + }, node) + common.LogIfWarn(err, "") + } + } + + return result +} + +// GetSubqueryDepth 获取一条SQL的嵌套深度 +func GetSubqueryDepth(node sqlparser.SQLNode) int { + depth := 1 + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch node.(type) { + case *sqlparser.Subquery: + depth++ + } + return true, nil + }, node) + common.LogIfWarn(err, "") + return depth +} + +// getColumnName 获取 node 中 column 具体的定义以及名称 +func getColumnName(node sqlparser.SQLNode) (*sqlparser.ColName, string) { + var colName *sqlparser.ColName + str := "" + switch c := node.(type) { + case *sqlparser.ColName: + if c.Qualifier.Name.IsEmpty() { + str = fmt.Sprintf("`%s`", c.Name.String()) + } else { + if c.Qualifier.Qualifier.IsEmpty() { + str = fmt.Sprintf("`%s`.`%s`", c.Qualifier.Name.String(), c.Name.String()) + } else { + str = fmt.Sprintf("`%s`.`%s`.`%s`", + c.Qualifier.Qualifier.String(), c.Qualifier.Name.String(), c.Name.String()) + } + } + colName = c + } + return colName, str +} diff --git a/vendor/github.com/XiaoMi/soar/ast/meta_test.go b/vendor/github.com/XiaoMi/soar/ast/meta_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f072978ec88b4cc376b8f8e486bae1e98a15a964 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/ast/meta_test.go @@ -0,0 +1,370 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 ast + +import ( + "fmt" + "testing" + + "github.com/XiaoMi/soar/common" + + "github.com/kr/pretty" + "vitess.io/vitess/go/vt/sqlparser" +) + +func TestGetTableFromExprs(t *testing.T) { + tbExprs := sqlparser.TableExprs{ + &sqlparser.AliasedTableExpr{ + Expr: sqlparser.TableName{ + Name: sqlparser.NewTableIdent("table"), + Qualifier: sqlparser.NewTableIdent("db"), + }, + As: sqlparser.NewTableIdent("as"), + }, + } + meta := GetTableFromExprs(tbExprs) + if tb, ok := meta["db"]; !ok { + t.Errorf("no table qualifier, meta: %s", pretty.Sprint(tb)) + } +} + +func TestGetParseTableWithStmt(t *testing.T) { + for _, sql := range common.TestSQLs { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + if err != nil { + t.Errorf("SQL Parsed error: %v", err) + } + meta := GetMeta(stmt, nil) + pretty.Println(meta) + fmt.Println() + } +} + +func TestFindCondition(t *testing.T) { + for _, sql := range common.TestSQLs { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + eq := FindEQColsInWhere(stmt) + inEq := FindINEQColsInWhere(stmt) + fmt.Println("WhereEQ:") + pretty.Println(eq) + fmt.Println("WhereINEQ:") + pretty.Println(inEq) + fmt.Println() + } +} + +func TestFindGroupBy(t *testing.T) { + sqlList := []string{ + "select a from t group by c", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + if err != nil { + panic(err) + } + res := FindGroupByCols(stmt) + pretty.Println(res) + fmt.Println() + } +} + +func TestFindOrderBy(t *testing.T) { + sqlList := []string{ + "select a from t group by c order by d, c desc", + "select a from t group by c order by d desc", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + if err != nil { + panic(err) + } + res := FindOrderByCols(stmt) + pretty.Println(res) + fmt.Println() + } +} + +func TestFindSubquery(t *testing.T) { + sqlList := []string{ + "SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM (SELECT column1 FROM t2) a);", + "select column1 from t2", + "SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);", + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + if err != nil { + panic(err) + } + + subquery := FindSubquery(0, stmt) + fmt.Println(len(subquery)) + pretty.Println(subquery) + } + +} + +func TestFindJoinTable(t *testing.T) { + sqlList := []string{ + "SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + "SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT * FROM t1 RIGHT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT left_tbl.* FROM left_tbl RIGHT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + + joinMeta := FindJoinTable(stmt, nil) + pretty.Println(joinMeta) + } +} + +func TestFindJoinCols(t *testing.T) { + sqlList := []string{ + "SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "select t from a LEFT JOIN b USING (c1, c2, c3)", + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + "SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT * FROM t1 RIGHT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT left_tbl.* FROM left_tbl RIGHT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + + columns := FindJoinCols(stmt) + pretty.Println(columns) + } +} + +func TestFindJoinColBeWhereEQ(t *testing.T) { + sqlList := []string{ + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + "SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT * FROM t1 RIGHT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT left_tbl.* FROM left_tbl RIGHT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + + columns := FindEQColsInJoinCond(stmt) + pretty.Println(columns) + } +} + +func TestFindJoinColBeWhereINEQ(t *testing.T) { + sqlList := []string{ + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + "SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT * FROM t1 RIGHT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b > 'b' AND t4.c = t1.c)", + "SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT left_tbl.* FROM left_tbl RIGHT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + + columns := FindINEQColsInJoinCond(stmt) + pretty.Println(columns) + } +} + +func TestFindAllCondition(t *testing.T) { + sqlList := []string{ + "SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "select t from a LEFT JOIN b USING (c1, c2, c3)", + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + "SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT * FROM t1 RIGHT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT left_tbl.* FROM left_tbl RIGHT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT * FROM t1 where a in ('a','b')", + "SELECT * FROM t1 where a BETWEEN 'bar' AND 'foo'", + "SELECT * FROM t1 where a = sum(a,b)", + "SELECT distinct a FROM t1 where a = '2001-01-01 01:01:01'", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + + columns := FindAllCondition(stmt) + pretty.Println(columns) + } +} + +func TestFindColumn(t *testing.T) { + sqlList := []string{ + "select col, col2, sum(col1) from tb group by col", + "select col from tb group by col,sum(col1)", + "select col, sum(col1) from tb group by col", + } + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + // pretty.Println(stmt) + if err != nil { + panic(err) + } + + columns := FindColumn(stmt) + pretty.Println(columns) + } +} + +func TestFindAllCols(t *testing.T) { + sqlList := []string{ + "select * from tb where a = '1' order by c", + "select * from tb where a = '1' group by c", + "select * from tb where c = '1' group by a", + "select * from tb join tb2 on c = c where c = '1' group by a", + } + + targets := []Expression{ + OrderByExpression, + GroupByExpression, + WhereExpression, + JoinExpression, + } + + for i, sql := range sqlList { + stmt, err := sqlparser.Parse(sql) + if err != nil { + t.Error(err) + return + } + + columns := FindAllCols(stmt, targets[i]) + if columns[0].Name != "c" { + fmt.Println(sql) + t.Error(fmt.Errorf("want 'c' got %v", columns)) + } + } +} + +func TestGetSubqueryDepth(t *testing.T) { + sqlList := []string{ + "SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "select t from a LEFT JOIN b USING (c1, c2, c3)", + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + "SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT * FROM t1 RIGHT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)", + "SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT left_tbl.* FROM left_tbl RIGHT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;", + "SELECT * FROM t1 where a in ('a','b')", + "SELECT * FROM t1 where a BETWEEN 'bar' AND 'foo'", + "SELECT * FROM t1 where a = sum(a,b)", + "SELECT distinct a FROM t1 where a = '2001-01-01 01:01:01'", + } + + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + if err != nil { + t.Error("syntax check error.") + } + + dep := GetSubqueryDepth(stmt) + fmt.Println(dep) + } +} + +func TestAppendTable(t *testing.T) { + sqlList := []string{ + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + } + + meta := make(map[string]*common.DB) + for _, sql := range sqlList { + fmt.Println(sql) + stmt, err := sqlparser.Parse(sql) + if err != nil { + t.Error("syntax check error.") + } + + err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch expr := node.(type) { + case *sqlparser.AliasedTableExpr: + switch table := expr.Expr.(type) { + case sqlparser.TableName: + appendTable(table, expr.As.String(), meta) + default: + if meta == nil { + meta = make(map[string]*common.DB) + } + if meta[""] == nil { + meta[""] = common.NewDB("") + } + meta[""].Table[""] = common.NewTable("") + meta[""].Table[""].TableAliases = append(meta[""].Table[""].TableAliases, expr.As.String()) + } + } + return true, nil + }, stmt) + + if err != nil { + t.Error(err) + } + } + + // 仅对第一条测试SQL进行测试,验证别名正确性 + if meta[""].Table["customer_list"].TableAliases[0] != "l" || meta[""].Table["city"].TableAliases[0] != "c" { + t.Error("alias filed\n", pretty.Sprint(meta)) + } +} diff --git a/vendor/github.com/XiaoMi/soar/ast/node_array.go b/vendor/github.com/XiaoMi/soar/ast/node_array.go new file mode 100644 index 0000000000000000000000000000000000000000..e8f7952765da595c043d574b72daad29c021ed31 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/ast/node_array.go @@ -0,0 +1,123 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 ast + +import ( + "errors" + + "github.com/XiaoMi/soar/common" + "vitess.io/vitess/go/vt/sqlparser" +) + +// 该文件用于构造一个存储AST生成节点的链表 +// 以能够更好的对AST中的每个节点进行查询、跳转、重建等 + +// NodeItem 链表节点 +type NodeItem struct { + ID int // NodeItem 在 List 中的编号,与顺序有关 + Prev *NodeItem // 前一个节点 + Self sqlparser.SQLNode // 自身指向的AST Node + Next *NodeItem // 后一个节点 + Array *NodeList // 指针指向所在的链表,用于快速跳转node +} + +// NodeList 链表结构体 +type NodeList struct { + Length int + Head *NodeItem + NodeMap map[int]*NodeItem +} + +// NewNodeList 从抽象语法树中构造一个链表 +func NewNodeList(statement sqlparser.Statement) *NodeList { + // 将AST构造成链表 + l := &NodeList{NodeMap: make(map[int]*NodeItem)} + err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + l.Add(node) + return true, nil + }, statement) + common.LogIfWarn(err, "") + return l +} + +// Add 将会把一个sqlparser.SQLNode添加到节点中 +func (l *NodeList) Add(node sqlparser.SQLNode) *NodeItem { + if l.Length == 0 { + l.Head = &NodeItem{ + ID: 0, + Self: node, + Next: nil, + Prev: nil, + Array: l, + } + l.NodeMap[l.Length] = l.Head + } else { + if n, ok := l.NodeMap[l.Length-1]; ok { + n.Next = &NodeItem{ + ID: l.Length - 1, + Prev: n, + Self: node, + Next: nil, + Array: l, + } + l.NodeMap[l.Length] = n.Next + } + } + l.Length++ + + return l.NodeMap[l.Length-1] +} + +// Remove 从链表中移除一个节点 +func (l *NodeList) Remove(node *NodeItem) error { + var err error + defer func() { + err := recover() + if err != nil { + common.Log.Error("func (l *NodeList) Remove recovered: %v", err) + } + }() + + if node.Array != l { + return errors.New("node not belong to this array") + } + + if node.Prev == nil { + // 如果是头结点 + node.Next.Prev = nil + } else if node.Next == nil { + // 如果是尾节点 + node.Prev.Next = nil + } else { + // 删除节点,连接断开的链表 + node.Prev.Next = node.Next + node.Next.Prev = node.Prev + delete(l.NodeMap, node.ID) + } + + return err +} + +// First 返回链表头结点 +func (l *NodeList) First() *NodeItem { + return l.Head +} + +// Last 返回链表末尾节点 +func (l *NodeList) Last() *NodeItem { + return l.NodeMap[l.Length-1] +} diff --git a/vendor/github.com/XiaoMi/soar/ast/pretty.go b/vendor/github.com/XiaoMi/soar/ast/pretty.go new file mode 100644 index 0000000000000000000000000000000000000000..6e4862fb2f0f5afbdfc63d10b424a9b5a4cc34b3 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/ast/pretty.go @@ -0,0 +1,350 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 ast + +import ( + "container/list" + "regexp" + "strings" + + "github.com/XiaoMi/soar/common" + + "github.com/percona/go-mysql/query" +) + +// Pretty 格式化输出SQL +func Pretty(sql string, method string) (output string) { + common.Log.Debug("Pretty, Query: %s, method: %s", sql, method) + // 超出 Config.MaxPrettySQLLength 长度的 SQL 会对其指纹进行 pretty + if len(sql) > common.Config.MaxPrettySQLLength { + fingerprint := query.Fingerprint(sql) + // 超出 Config.MaxFpPrettySqlLength 长度的指纹不会进行pretty + if len(fingerprint) > common.Config.MaxPrettySQLLength { + return sql + } + sql = fingerprint + } + + switch method { + case "builtin", "markdown": + return format(sql) + default: + return sql + } +} + +// format the whitespace in a SQL string to make it easier to read. +// @param string $query The SQL string +// @return String The SQL string with HTML styles and formatting wrapped in a
 tag
+func format(query string) string {
+	// This variable will be populated with formatted html
+	result := ""
+	// Use an actual tab while formatting and then switch out with self::$tab at the end
+	tab := "  "
+	indentLevel := 0
+	var newline bool
+	var inlineParentheses bool
+	var increaseSpecialIndent bool
+	var increaseBlockIndent bool
+	var addedNewline bool
+	var inlineCount int
+	var inlineIndented bool
+	var clauseLimit bool
+	indentTypes := list.New()
+
+	// Tokenize String
+	originalTokens := Tokenize(query)
+
+	// Remove existing whitespace//
+	var tokens []Token
+	for i, token := range originalTokens {
+		if token.Type != TokenTypeWhitespace {
+			token.i = i
+			tokens = append(tokens, token)
+		}
+	}
+
+	for i, token := range tokens {
+		highlighted := token.Val
+
+		// If we are increasing the special indent level now
+		if increaseSpecialIndent {
+			indentLevel++
+			increaseSpecialIndent = false
+			indentTypes.PushFront("special")
+		}
+
+		// If we are increasing the block indent level now
+		if increaseBlockIndent {
+			indentLevel++
+			increaseBlockIndent = false
+			indentTypes.PushFront("block")
+		}
+
+		// If we need a new line before the token
+		if newline {
+			result += "\n" + strings.Repeat(tab, indentLevel)
+			newline = false
+			addedNewline = true
+		} else {
+			addedNewline = false
+		}
+
+		// Display comments directly where they appear in the source
+		if token.Type == TokenTypeComment || token.Type == TokenTypeBlockComment {
+			if token.Type == TokenTypeBlockComment {
+				indent := strings.Repeat(tab, indentLevel)
+				result += "\n" + indent
+				highlighted = strings.Replace(highlighted, "\n", "\n"+indent, -1)
+			}
+
+			result += highlighted
+			newline = true
+			continue
+		}
+
+		if inlineParentheses {
+			// End of inline parentheses
+			if token.Val == ")" {
+				result = strings.TrimRight(result, " ")
+
+				if inlineIndented {
+					indentTypes.Remove(indentTypes.Front())
+					if indentLevel > 0 {
+						indentLevel--
+					}
+					result += strings.Repeat(tab, indentLevel)
+				}
+
+				inlineParentheses = false
+
+				result += highlighted + " "
+				continue
+			}
+
+			if token.Val == "," {
+				if inlineCount >= 30 {
+					inlineCount = 0
+					newline = true
+				}
+			}
+
+			inlineCount += len(token.Val)
+		}
+
+		// Opening parentheses increase the block indent level and start a new line
+		if token.Val == "(" {
+			// First check if this should be an inline parentheses block
+			// Examples are "NOW()", "COUNT(*)", "int(10)", key(`somecolumn`), DECIMAL(7,2)
+			// Allow up to 3 non-whitespace tokens inside inline parentheses
+			length := 0
+			for j := 1; j <= 250; j++ {
+				// Reached end of string
+				if i+j >= len(tokens) {
+					break
+				}
+
+				next := tokens[i+j]
+
+				// Reached closing parentheses, able to inline it
+				if next.Val == ")" {
+					inlineParentheses = true
+					inlineCount = 0
+					inlineIndented = false
+					break
+				}
+
+				// Reached an invalid token for inline parentheses
+				if next.Val == ";" || next.Val == "(" {
+					break
+				}
+
+				// Reached an invalid token type for inline parentheses
+				if next.Type == TokenTypeReservedToplevel ||
+					next.Type == TokenTypeReservedNewline ||
+					next.Type == TokenTypeComment ||
+					next.Type == TokenTypeBlockComment {
+					break
+				}
+
+				length += len(next.Val)
+			}
+
+			if inlineParentheses && length > 30 {
+				increaseBlockIndent = true
+				inlineIndented = true
+				newline = true
+			}
+
+			// Take out the preceding space unless there was whitespace there in the original query
+			if token.i != 0 && (token.i-1) > len(originalTokens)-1 &&
+				originalTokens[token.i-1].Type != TokenTypeWhitespace {
+
+				result = strings.TrimRight(result, " ")
+			}
+
+			if inlineParentheses {
+				increaseBlockIndent = true
+				// Add a newline after the parentheses
+				newline = true
+			}
+
+		} else if token.Val == ")" {
+			// Closing parentheses decrease the block indent level
+			// Remove whitespace before the closing parentheses
+			result = strings.TrimRight(result, " ")
+
+			if indentLevel > 0 {
+				indentLevel--
+			}
+
+			// Reset indent level
+			for j := indentTypes.Front(); indentTypes.Len() > 0; indentTypes.Remove(j) {
+				if j.Value.(string) == "special" {
+					if indentLevel > 0 {
+						indentLevel--
+					} else {
+						break
+					}
+				} else {
+					break
+				}
+			}
+
+			if indentLevel < 0 {
+				// This is an error
+				indentLevel = 0
+			}
+
+			// Add a newline before the closing parentheses (if not already added)
+			if !addedNewline {
+				result += "\n" + strings.Repeat(tab, indentLevel)
+			}
+
+		} else if token.Type == TokenTypeReservedToplevel {
+			// Top level reserved words start a new line and increase the special indent level
+			increaseSpecialIndent = true
+
+			// If the last indent type was 'special', decrease the special indent for this round
+			if indentTypes.Len() > 0 && indentTypes.Front().Value.(string) == "special" {
+				if indentLevel > 0 {
+					indentLevel--
+				}
+				indentTypes.Remove(indentTypes.Front())
+			}
+
+			// Add a newline after the top level reserved word
+			newline = true
+			// Add a newline before the top level reserved word (if not already added)
+			if !addedNewline {
+				result += "\n" + strings.Repeat(tab, indentLevel)
+			} else {
+				// If we already added a newline, redo the indentation since it may be different now
+				result = strings.TrimSuffix(result, tab) + strings.Repeat(tab, indentLevel)
+			}
+
+			// If the token may have extra whitespace
+			if strings.Index(token.Val, " ") != 0 ||
+				strings.Index(token.Val, "\n") != 0 ||
+				strings.Index(token.Val, "\t") != 0 {
+
+				re, _ := regexp.Compile(`\s+`)
+				highlighted = re.ReplaceAllString(highlighted, " ")
+
+			}
+
+			//if SQL 'LIMIT' clause, start variable to reset newline
+			if token.Val == "LIMIT" && inlineParentheses {
+				clauseLimit = true
+			}
+
+		} else if clauseLimit && token.Val != "," &&
+			token.Type != TokenTypeNumber &&
+			token.Type != TokenTypeWhitespace {
+			// Checks if we are out of the limit clause
+
+			clauseLimit = false
+
+		} else if token.Val == "," && !inlineParentheses {
+			// Commas start a new line (unless within inline parentheses or SQL 'LIMIT' clause)
+			if clauseLimit {
+				newline = false
+				clauseLimit = false
+			} else {
+				// All other cases of commas
+				newline = true
+			}
+
+		} else if token.Type == TokenTypeReservedNewline {
+			// Newline reserved words start a new line
+			// Add a newline before the reserved word (if not already added)
+			if !addedNewline {
+				result += "\n" + strings.Repeat(tab, indentLevel)
+			}
+
+			// If the token may have extra whitespace
+			if strings.Index(token.Val, " ") != 0 ||
+				strings.Index(token.Val, "\n") != 0 ||
+				strings.Index(token.Val, "\t") != 0 {
+
+				re, _ := regexp.Compile(`\s+`)
+				highlighted = re.ReplaceAllString(highlighted, " ")
+			}
+
+		} else if token.Type == TokenTypeBoundary {
+			// Multiple boundary characters in a row should not have spaces between them (not including parentheses)
+			if i != 0 && i < len(tokens) &&
+				tokens[i-1].Type == TokenTypeBoundary {
+
+				if token.i != 0 && token.i < len(originalTokens) &&
+					originalTokens[token.i-1].Type != TokenTypeWhitespace {
+
+					result = strings.TrimRight(result, " ")
+				}
+			}
+		}
+
+		// If the token shouldn't have a space before it
+		if token.Val == "." || token.Val == "," || token.Val == ";" {
+			result = strings.TrimRight(result, " ")
+		}
+
+		result += highlighted + " "
+
+		// If the token shouldn't have a space after it
+		if token.Val == "(" || token.Val == "." {
+			result = strings.TrimRight(result, " ")
+		}
+
+		// If this is the "-" of a negative number, it shouldn't have a space after it
+		if token.Val == "-" && i+1 < len(tokens) && tokens[i+1].Type == TokenTypeNumber && i != 0 {
+			prev := tokens[i-1].Type
+			if prev != TokenTypeQuote &&
+				prev != TokenTypeBacktickQuote &&
+				prev != TokenTypeWord &&
+				prev != TokenTypeNumber {
+
+				result = strings.TrimRight(result, " ")
+			}
+		}
+	}
+
+	// Replace tab characters with the configuration tab character
+	result = strings.TrimRight(strings.Replace(result, "\t", tab, -1), " ")
+
+	return result
+}
diff --git a/vendor/github.com/XiaoMi/soar/ast/pretty_test.go b/vendor/github.com/XiaoMi/soar/ast/pretty_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..2046cad0ab005a8ce951ea1e553fdde9623a44e5
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/ast/pretty_test.go
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 ast
+
+import (
+	"flag"
+	"fmt"
+	"testing"
+
+	"github.com/XiaoMi/soar/common"
+
+	"vitess.io/vitess/go/vt/sqlparser"
+)
+
+var update = flag.Bool("update", false, "update .golden files")
+
+var TestSqlsPretty = []string{
+	"select sourcetable, if(f.lastcontent = ?, f.lastupdate, f.lastcontent) as lastactivity, f.totalcount as activity, type.class as type, (f.nodeoptions & ?) as nounsubscribe from node as f inner join contenttype as type on type.contenttypeid = f.contenttypeid inner join subscribed as sd on sd.did = f.nodeid and sd.userid = ? union all select f.name as title, f.userid as keyval, ? as sourcetable, ifnull(f.lastpost, f.joindate) as lastactivity, f.posts as activity, ? as type, ? as nounsubscribe from user as f inner join userlist as ul on ul.relationid = f.userid and ul.userid = ? where ul.type = ? and ul.aq = ? order by title limit ?",
+	"administrator command: Init DB",
+	"CALL foo(1, 2, 3)",
+	"### Channels ###\n\u0009\u0009\u0009\u0009\u0009SELECT sourcetable, IF(f.lastcontent = 0, f.lastupdate, f.lastcontent) AS lastactivity,\n\u0009\u0009\u0009\u0009\u0009f.totalcount AS activity, type.class AS type,\n\u0009\u0009\u0009\u0009\u0009(f.nodeoptions \u0026 512) AS noUnsubscribe\n\u0009\u0009\u0009\u0009\u0009FROM node AS f\n\u0009\u0009\u0009\u0009\u0009INNER JOIN contenttype AS type ON type.contenttypeid = f.contenttypeid \n\n\u0009\u0009\u0009\u0009\u0009INNER JOIN subscribed AS sd ON sd.did = f.nodeid AND sd.userid = 15965\n UNION  ALL \n\n\u0009\u0009\u0009\u0009\u0009### Users ###\n\u0009\u0009\u0009\u0009\u0009SELECT f.name AS title, f.userid AS keyval, 'user' AS sourcetable, IFNULL(f.lastpost, f.joindate) AS lastactivity,\n\u0009\u0009\u0009\u0009\u0009f.posts as activity, 'Member' AS type,\n\u0009\u0009\u0009\u0009\u00090 AS noUnsubscribe\n\u0009\u0009\u0009\u0009\u0009FROM user AS f\n\u0009\u0009\u0009\u0009\u0009INNER JOIN userlist AS ul ON ul.relationid = f.userid AND ul.userid = 15965\n\u0009\u0009\u0009\u0009\u0009WHERE ul.type = 'f' AND ul.aq = 'yes'\n ORDER BY title ASC LIMIT 100",
+	"CREATE DATABASE org235_percona345 COLLATE 'utf8_general_ci'",
+	"insert into abtemp.coxed select foo.bar from foo",
+	"insert into foo(a, b, c) value(2, 4, 5)",
+	"insert into foo(a, b, c) values(2, 4, 5)",
+	"insert into foo(a, b, c) values(2, 4, 5) , (2,4,5)",
+	"insert into foo values (1, '(2)', 'This is a trick: ). More values.', 4)",
+	"insert into tb values (1)",
+	"INSERT INTO t (ts) VALUES ('()', '\\(', '\\)')",
+	"INSERT INTO t (ts) VALUES (NOW())",
+	"INSERT INTO t () VALUES ()",
+	"insert into t values (1), (2), (3)\n\n\ton duplicate key update query_count=1",
+	"insert into t values (1) on duplicate key update query_count=COALESCE(query_count, 0) + VALUES(query_count)",
+	"LOAD DATA INFILE '/tmp/foo.txt' INTO db.tbl",
+	"select 0e0, +6e-30, -6.00 from foo where a = 5.5 or b=0.5 or c=.5",
+	"select 0x0, x'123', 0b1010, b'10101' from foo",
+	"select 123_foo from 123_foo",
+	"select 123foo from 123foo",
+	`SELECT 	1 AS one FROM calls USE INDEX(index_name)`,
+	"SELECT /*!40001 SQL_NO_CACHE */ * FROM `film`",
+	"SELECT 'a' 'b' 'c' 'd' FROM kamil",
+	"SELECT BENCHMARK(100000000, pow(rand(), rand())), 1 FROM `-hj-7d6-shdj5-7jd-kf-g988h-`.`-aaahj-7d6-shdj5-7&^%$jd-kf-g988h-9+4-5*6ab-`",
+	"SELECT c FROM org235.t WHERE id=0xdeadbeaf",
+	"select c from t where i=1 order by c asc",
+	"SELECT c FROM t WHERE id=0xdeadbeaf",
+	"SELECT c FROM t WHERE id=1",
+	"select `col` from `table-1` where `id` = 5",
+	"SELECT `db`.*, (CASE WHEN (`date_start` <=  '2014-09-10 09:17:59' AND `date_end` >=  '2014-09-10 09:17:59') THEN 'open' WHEN (`date_start` >  '2014-09-10 09:17:59' AND `date_end` >  '2014-09-10 09:17:59') THEN 'tbd' ELSE 'none' END) AS `status` FROM `foo` AS `db` WHERE (a_b in ('1', '10101'))",
+	"select field from `-master-db-1`.`-table-1-` order by id, ?;",
+	"select   foo",
+	"select foo_1 from foo_2_3",
+	"select foo -- bar\n",
+	"select foo-- bar\n,foo",
+	"select '\\\\' from foo",
+	"select * from foo limit 5",
+	"select * from foo limit 5, 10",
+	"select * from foo limit 5 offset 10",
+	"SELECT * from foo where a = 5",
+	"select * from foo where a in (5) and b in (5, 8,9 ,9 , 10)",
+	"SELECT '' '' '' FROM kamil",
+	" select  * from\nfoo where a = 5",
+	"SELECT * FROM prices.rt_5min where id=1",
+	"SELECT * FROM table WHERE field = 'value' /*arbitrary/31*/ ",
+	"SELECT * FROM table WHERE field = 'value' /*arbitrary31*/ ",
+	"SELECT *    FROM t WHERE 1=1 AND id=1",
+	"select * from t where (base.nid IN  ('1412', '1410', '1411'))",
+	`select * from t where i=1      order            by
+             a,  b          ASC, d    DESC,
+
+                                    e asc`,
+	"select * from t where i=1 order by a, b ASC, d DESC, e asc",
+	"select 'hello'\n",
+	"select 'hello', '\nhello\n', \"hello\", '\\'' from foo",
+	"SELECT ID, name, parent, type FROM posts WHERE _name IN ('perf','caching') AND (type = 'page' OR type = 'attachment')",
+	"SELECT name, value FROM variable",
+	"select \n-- bar\n foo",
+	"select null, 5.001, 5001. from foo",
+	"select sleep(2) from test.n",
+	"SELECT t FROM field WHERE  (entity_type = 'node') AND (entity_id IN  ('609')) AND (language IN  ('und')) AND (deleted = '0') ORDER BY delta ASC",
+	"select  t.table_schema,t.table_name,engine  from information_schema.tables t  inner join information_schema.columns c  on t.table_schema=c.table_schema and t.table_name=c.table_name group by t.table_schema,t.table_name having  sum(if(column_key in ('PRI','UNI'),1,0))=0",
+	"/* -- S++ SU ABORTABLE -- spd_user: rspadim */SELECT SQL_SMALL_RESULT SQL_CACHE DISTINCT centro_atividade FROM est_dia WHERE unidade_id=1001 AND item_id=67 AND item_id_red=573",
+	`UPDATE groups_search SET  charter = '   -------3\'\' XXXXXXXXX.\n    \n    -----------------------------------------------------', show_in_list = 'Y' WHERE group_id='aaaaaaaa'`,
+	"use `foo`",
+	"select sourcetable, if(f.lastcontent = ?, f.lastupdate, f.lastcontent) as lastactivity, f.totalcount as activity, type.class as type, (f.nodeoptions & ?) as nounsubscribe from node as f inner join contenttype as type on type.contenttypeid = f.contenttypeid inner join subscribed as sd on sd.did = f.nodeid and sd.userid = ? union all select f.name as title, f.userid as keyval, ? as sourcetable, ifnull(f.lastpost, f.joindate) as lastactivity, f.posts as activity, ? as type, ? as nounsubscribe from user as f inner join userlist as ul on ul.relationid = f.userid and ul.userid = ? where ul.type = ? and ul.aq = ? order by title limit ?",
+	"CREATE INDEX part_of_name ON customer (name(10));",
+	"alter table `sakila`.`t1` add index `idx_col`(`col`)",
+	"alter table `sakila`.`t1` add UNIQUE index `idx_col`(`col`)",
+	"alter table `sakila`.`t1` add index `idx_ID`(`ID`)",
+
+	// ADD|DROP COLUMN
+	"ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;",
+	"ALTER TABLE T2 ADD COLUMN C int;",
+	"ALTER TABLE T2 ADD COLUMN D int FIRST;",
+	"ALTER TABLE T2 ADD COLUMN E int AFTER D;",
+
+	// RENAME COLUMN
+	"ALTER TABLE t1 RENAME COLUMN a TO b",
+
+	// RENAME INDEX
+	"ALTER TABLE t1 RENAME INDEX idx_a TO idx_b",
+	"ALTER TABLE t1 RENAME KEY idx_a TO idx_b",
+
+	// RENAME TABLE
+	"ALTER TABLE db.old_table RENAME new_table;",
+	"ALTER TABLE old_table RENAME TO new_table;",
+	"ALTER TABLE old_table RENAME AS new_table;",
+
+	// MODIFY & CHANGE
+	"ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT 'my column';",
+	"ALTER TABLE t1 CHANGE b a INT NOT NULL;",
+
+	// COMMENT
+	"/*!40000 select 1*/;",
+}
+
+func TestPretty(t *testing.T) {
+	err := common.GoldenDiff(func() {
+		for _, sql := range append(TestSqlsPretty, common.TestSQLs...) {
+			fmt.Println(sql)
+			fmt.Println(Pretty(sql, "builtin"))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestIsKeyword(t *testing.T) {
+	tks := map[string]bool{
+		"AGAINST":        true,
+		"AUTO_INCREMENT": true,
+		"ADD":            true,
+		"BETWEEN":        true,
+		".":              false,
+		"actions":        false,
+		`"`:              false,
+		":":              false,
+	}
+	for tk, v := range tks {
+		if IsMysqlKeyword(tk) != v {
+			t.Error("isKeyword:", tk)
+		}
+	}
+}
+
+func TestRemoveComments(t *testing.T) {
+	for _, sql := range TestSqlsPretty {
+		stmt, _ := sqlparser.Parse(sql)
+		newSQL := sqlparser.String(stmt)
+		if newSQL != sql {
+			fmt.Print(newSQL)
+		}
+	}
+}
+
+func TestMysqlEscapeString(t *testing.T) {
+	var strs = []map[string]string{
+		{
+			"input":  "abc",
+			"output": "abc",
+		},
+		{
+			"input":  "'abc",
+			"output": "\\'abc",
+		},
+		{
+			"input": `
+abc`,
+			"output": `\
+abc`,
+		},
+		{
+			"input":  "\"abc",
+			"output": "\\\"abc",
+		},
+	}
+	for _, str := range strs {
+		output, err := MysqlEscapeString(str["input"])
+		if err != nil {
+			t.Error("TestMysqlEscapeString", err)
+		} else {
+			if output != str["output"] {
+				t.Error("TestMysqlEscapeString", output, str["output"])
+			}
+		}
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/ast/rewrite.go b/vendor/github.com/XiaoMi/soar/ast/rewrite.go
new file mode 100644
index 0000000000000000000000000000000000000000..cf4bab24f64359a3e11906c4b0165cb16cd44863
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/ast/rewrite.go
@@ -0,0 +1,1732 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 ast
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"regexp"
+	"strings"
+
+	"github.com/XiaoMi/soar/common"
+
+	"github.com/kr/pretty"
+	"vitess.io/vitess/go/vt/sqlparser"
+)
+
+// Rule SQL重写规则
+type Rule struct {
+	Name        string                  `json:"Name"`
+	Description string                  `json:"Description"`
+	Original    string                  `json:"Original"` // 错误示范。为空或"暂不支持"不会出现在list-rewrite-rules中
+	Suggest     string                  `json:"Suggest"`  // 正确示范。
+	Func        func(*Rewrite) *Rewrite `json:"-"`        // 如果不定义 Func 需要多条 SQL 联动改写
+}
+
+// RewriteRules SQL重写规则,注意这个规则是有序的,先后顺序不能乱
+var RewriteRules = []Rule{
+	{
+		Name:        "dml2select",
+		Description: "将数据库更新请求转换为只读查询请求,便于执行EXPLAIN",
+		Original:    "DELETE FROM film WHERE length > 100",
+		Suggest:     "select * from film where length > 100",
+		Func:        (*Rewrite).RewriteDML2Select,
+	},
+	{
+		Name:        "star2columns",
+		Description: "为SELECT *补全表的列信息",
+		Original:    "SELECT * FROM film",
+		Suggest:     "select film.film_id, film.title from film",
+		Func:        (*Rewrite).RewriteStar2Columns,
+	},
+	{
+		Name:        "insertcolumns",
+		Description: "为INSERT补全表的列信息",
+		Original:    "insert into film values(1,2,3,4,5)",
+		Suggest:     "insert into film(film_id, title, description, release_year, language_id) values (1, 2, 3, 4, 5)",
+		Func:        (*Rewrite).RewriteInsertColumns,
+	},
+	{
+		Name:        "having",
+		Description: "将查询的 HAVING 子句改写为 WHERE 中的查询条件",
+		Original:    "SELECT state, COUNT(*) FROM Drivers GROUP BY state HAVING state IN ('GA', 'TX') ORDER BY state",
+		Suggest:     "select state, COUNT(*) from Drivers where state in ('GA', 'TX') group by state order by state asc",
+		Func:        (*Rewrite).RewriteHaving,
+	},
+	{
+		Name:        "orderbynull",
+		Description: "如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 ORDER BY NULL",
+		Original:    "SELECT sum(col1) FROM tbl GROUP BY col",
+		Suggest:     "select sum(col1) from tbl group by col order by null",
+		Func:        (*Rewrite).RewriteAddOrderByNull,
+	},
+	{
+		Name:        "unionall",
+		Description: "可以接受重复的时间,使用 UNION ALL 替代 UNION 以提高查询效率",
+		Original:    "select country_id from city union select country_id from country",
+		Suggest:     "select country_id from city union all select country_id from country",
+		Func:        (*Rewrite).RewriteUnionAll,
+	},
+	{
+		Name:        "or2in",
+		Description: "将同一列不同条件的 OR 查询转写为 IN 查询",
+		Original:    "select country_id from city where col1 = 1 or (col2 = 1 or col2 = 2 ) or col1 = 3;",
+		Suggest:     "select country_id from city where (col2 in (1, 2)) or col1 in (1, 3);",
+		Func:        (*Rewrite).RewriteOr2In,
+	},
+	{
+		Name:        "innull",
+		Description: "如果 IN 条件中可能有 NULL 值而又想匹配 NULL 值时,建议添加OR col IS NULL",
+		Original:    "暂不支持",
+		Suggest:     "暂不支持",
+		Func:        (*Rewrite).RewriteInNull,
+	},
+	// 把所有跟 or 相关的重写完之后才进行 or 转 union 的重写
+	{
+		Name:        "or2union",
+		Description: "将不同列的 OR 查询转为 UNION 查询,建议结合 unionall 重写策略一起使用",
+		Original:    "暂不支持",
+		Suggest:     "暂不支持",
+		Func:        (*Rewrite).RewriteOr2Union,
+	},
+	{
+		Name:        "dmlorderby",
+		Description: "删除 DML 更新操作中无意义的 ORDER BY",
+		Original:    "DELETE FROM tbl WHERE col1=1 ORDER BY col",
+		Suggest:     "delete from tbl where col1 = 1",
+		Func:        (*Rewrite).RewriteRemoveDMLOrderBy,
+	},
+	/*
+		{
+			Name:        "groupbyconst",
+			Description: "删除无意义的GROUP BY常量",
+			Original:    "SELECT sum(col1) FROM tbl GROUP BY 1;",
+			Suggest:     "select sum(col1) from tbl",
+			Func:        (*Rewrite).RewriteGroupByConst,
+		},
+	*/
+	{
+		Name:        "sub2join",
+		Description: "将子查询转换为JOIN查询",
+		Original:    "暂不支持",
+		Suggest:     "暂不支持",
+		Func:        (*Rewrite).RewriteSubQuery2Join,
+	},
+	{
+		Name:        "join2sub",
+		Description: "将JOIN查询转换为子查询",
+		Original:    "暂不支持",
+		Suggest:     "暂不支持",
+		Func:        (*Rewrite).RewriteJoin2SubQuery,
+	},
+	{
+		Name:        "distinctstar",
+		Description: "DISTINCT *对有主键的表没有意义,可以将DISTINCT删掉",
+		Original:    "SELECT DISTINCT * FROM film;",
+		Suggest:     "SELECT * FROM film",
+		Func:        (*Rewrite).RewriteDistinctStar,
+	},
+	{
+		Name:        "standard",
+		Description: "SQL标准化,如:关键字转换为小写",
+		Original:    "SELECT sum(col1) FROM tbl GROUP BY 1;",
+		Suggest:     "select sum(col1) from tbl group by 1",
+		Func:        (*Rewrite).RewriteStandard,
+	},
+	{
+		Name:        "mergealter",
+		Description: "合并同一张表的多条ALTER语句",
+		Original:    "ALTER TABLE t2 DROP COLUMN c;ALTER TABLE t2 DROP COLUMN d;",
+		Suggest:     "ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;",
+	},
+	{
+		Name:        "alwaystrue",
+		Description: "删除无用的恒真判断条件",
+		Original:    "SELECT count(col) FROM tbl where 'a'= 'a' or ('b' = 'b' and a = 'b');",
+		Suggest:     "select count(col) from tbl where (a = 'b');",
+		Func:        (*Rewrite).RewriteAlwaysTrue,
+	},
+	{
+		Name:        "countstar",
+		Description: "不建议使用COUNT(col)或COUNT(常量),建议改写为COUNT(*)",
+		Original:    "SELECT count(col) FROM tbl GROUP BY 1;",
+		Suggest:     "SELECT count(*) FROM tbl GROUP BY 1;",
+		Func:        (*Rewrite).RewriteCountStar,
+	},
+	{
+		Name:        "innodb",
+		Description: "建表时建议使用InnoDB引擎,非 InnoDB 引擎表自动转 InnoDB",
+		Original:    "CREATE TABLE t1(id bigint(20) NOT NULL AUTO_INCREMENT);",
+		Suggest:     "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB;",
+		Func:        (*Rewrite).RewriteInnoDB,
+	},
+	{
+		Name:        "autoincrement",
+		Description: "将autoincrement初始化为1",
+		Original:    "CREATE TABLE t1(id bigint(20) NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=123802;",
+		Suggest:     "create table t1(id bigint(20) not null auto_increment) ENGINE=InnoDB auto_increment=1;",
+		Func:        (*Rewrite).RewriteAutoIncrement,
+	},
+	{
+		Name:        "intwidth",
+		Description: "整型数据类型修改默认显示宽度",
+		Original:    "create table t1 (id int(20) not null auto_increment) ENGINE=InnoDB;",
+		Suggest:     "create table t1 (id int(10) not null auto_increment) ENGINE=InnoDB;",
+		Func:        (*Rewrite).RewriteIntWidth,
+	},
+	{
+		Name:        "truncate",
+		Description: "不带 WHERE 条件的 DELETE 操作建议修改为 TRUNCATE",
+		Original:    "DELETE FROM tbl",
+		Suggest:     "truncate table tbl",
+		Func:        (*Rewrite).RewriteTruncate,
+	},
+	{
+		Name:        "rmparenthesis",
+		Description: "去除没有意义的括号",
+		Original:    "select col from table where (col = 1);",
+		Suggest:     "select col from table where col = 1;",
+		Func:        (*Rewrite).RewriteRmParenthesis,
+	},
+	// delimiter要放在最后,不然补不上
+	{
+		Name:        "delimiter",
+		Description: "补全DELIMITER",
+		Original:    "use sakila",
+		Suggest:     "use sakila;",
+		Func:        (*Rewrite).RewriteDelimiter,
+	},
+	// TODO in to exists
+	// TODO exists to in
+}
+
+// ListRewriteRules 打印SQL重写规则
+func ListRewriteRules(rules []Rule) {
+	switch common.Config.ReportType {
+	case "json":
+		js, err := json.MarshalIndent(rules, "", "  ")
+		if err == nil {
+			fmt.Println(string(js))
+		}
+	default:
+
+		fmt.Print("# 重写规则\n\n[toc]\n\n")
+		for _, r := range rules {
+			if !common.Config.Verbose && (r.Original == "" || r.Original == "暂不支持") {
+				continue
+			}
+
+			fmt.Print("## ", common.MarkdownEscape(r.Name),
+				"\n* **Description**:", r.Description+"\n",
+				"\n* **Original**:\n\n```sql\n", r.Original, "\n```\n",
+				"\n* **Suggest**:\n\n```sql\n", r.Suggest, "\n```\n")
+
+		}
+	}
+}
+
+// Rewrite 用于重写SQL
+type Rewrite struct {
+	SQL     string
+	NewSQL  string
+	Stmt    sqlparser.Statement
+	Columns common.TableColumns
+}
+
+// NewRewrite 返回一个*Rewrite对象,如果SQL无法被正常解析,将错误输出到日志中,返回一个nil
+func NewRewrite(sql string) *Rewrite {
+	stmt, err := sqlparser.Parse(sql)
+	if err != nil {
+		common.Log.Error(err.Error(), sql)
+		return nil
+	}
+
+	return &Rewrite{
+		SQL:  sql,
+		Stmt: stmt,
+	}
+}
+
+// Rewrite 入口函数
+func (rw *Rewrite) Rewrite() *Rewrite {
+	defer func() {
+		if err := recover(); err != nil {
+			common.Log.Error("Query rewrite Error: %s, maybe hit a bug.\nQuery: %s \nAST: %s",
+				err, rw.SQL, pretty.Sprint(rw.Stmt))
+			return
+		}
+	}()
+
+	for _, rule := range RewriteRules {
+		if RewriteRuleMatch(rule.Name) && rule.Func != nil {
+			rule.Func(rw)
+			common.Log.Debug("Rewrite Rule:%s Output NewSQL: %s", rule.Name, rw.NewSQL)
+		}
+	}
+	if rw.NewSQL == "" {
+		rw.NewSQL = rw.SQL
+	}
+	rw.Stmt, _ = sqlparser.Parse(rw.NewSQL)
+
+	// TODO: 重新前后返回结果一致性对比
+
+	// TODO: 前后SQL性能对比
+	return rw
+}
+
+// RewriteDelimiter delimiter: 补分号,可以指定不同的DELIMITER
+func (rw *Rewrite) RewriteDelimiter() *Rewrite {
+	if rw.NewSQL != "" {
+		rw.NewSQL = strings.TrimSuffix(rw.NewSQL, common.Config.Delimiter) + common.Config.Delimiter
+	} else {
+		rw.NewSQL = strings.TrimSuffix(rw.SQL, common.Config.Delimiter) + common.Config.Delimiter
+	}
+	return rw
+}
+
+// RewriteStandard standard: 使用 vitess 提供的 String 功能将抽象语法树转写回 SQL,注意:这可能转写失败。
+func (rw *Rewrite) RewriteStandard() *Rewrite {
+	if _, err := sqlparser.Parse(rw.SQL); err == nil {
+		rw.NewSQL = sqlparser.String(rw.Stmt)
+	}
+	return rw
+}
+
+// RewriteAlwaysTrue alwaystrue: 删除恒真条件
+func (rw *Rewrite) RewriteAlwaysTrue() (reWriter *Rewrite) {
+	array := NewNodeList(rw.Stmt)
+	tNode := array.Head
+	for {
+		omitAlwaysTrue(tNode)
+		tNode = tNode.Next
+		if tNode == nil {
+			break
+		}
+	}
+
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// isAlwaysTrue 用于判断ComparisonExpr是否是恒真
+func isAlwaysTrue(expr *sqlparser.ComparisonExpr) bool {
+	if expr == nil {
+		return true
+	}
+
+	var result bool
+	switch expr.Operator {
+	case "<>":
+		expr.Operator = "!="
+	case "<=>":
+		expr.Operator = "="
+	case ">=", "<=", "!=", "=":
+	default:
+		return false
+	}
+
+	var left []byte
+	var right []byte
+
+	// left
+	switch l := expr.Left.(type) {
+	case *sqlparser.SQLVal:
+		left = l.Val
+	default:
+		return false
+	}
+
+	// right
+	switch r := expr.Right.(type) {
+	case *sqlparser.SQLVal:
+		right = r.Val
+	default:
+		return false
+	}
+
+	switch expr.Operator {
+	case "=":
+		result = bytes.Equal(left, right)
+	case "!=":
+		result = !bytes.Equal(left, right)
+	case ">":
+		result = bytes.Compare(left, right) > 0
+	case ">=":
+		result = bytes.Compare(left, right) >= 0
+	case "<":
+		result = bytes.Compare(left, right) < 0
+	case "<=":
+		result = bytes.Compare(left, right) <= 0
+	default:
+		result = false
+	}
+
+	return result
+}
+
+// omitAlwaysTrue 移除AST中的恒真条件
+func omitAlwaysTrue(node *NodeItem) {
+	if node == nil {
+		return
+	}
+
+	switch self := node.Self.(type) {
+	case *sqlparser.Where:
+		if self != nil {
+			switch cond := self.Expr.(type) {
+			case *sqlparser.ComparisonExpr:
+				if isAlwaysTrue(cond) {
+					self.Expr = nil
+				}
+			case *sqlparser.ParenExpr:
+				if cond.Expr == nil {
+					self.Expr = nil
+				}
+			}
+		}
+	case *sqlparser.ParenExpr:
+		if self != nil {
+			switch cond := self.Expr.(type) {
+			case *sqlparser.ComparisonExpr:
+				if isAlwaysTrue(cond) {
+					self.Expr = nil
+				}
+			}
+		}
+	case *sqlparser.AndExpr:
+		if self != nil {
+			var tmp sqlparser.Expr
+			isRightTrue := false
+			isLeftTrue := false
+			tmp = nil
+
+			// 查看左树的情况
+			switch l := self.Left.(type) {
+			case *sqlparser.ComparisonExpr:
+				if isAlwaysTrue(l) {
+					self.Left = nil
+					isLeftTrue = true
+					tmp = self.Right
+				}
+			case *sqlparser.ParenExpr:
+				if l.Expr == nil {
+					self.Left = nil
+					isLeftTrue = true
+					tmp = self.Right
+				}
+			default:
+				if l == nil {
+					isLeftTrue = true
+					tmp = self.Right
+				}
+			}
+
+			// 查看右树的情况
+			switch r := self.Right.(type) {
+			case *sqlparser.ComparisonExpr:
+				if isAlwaysTrue(r) {
+					self.Right = nil
+					isRightTrue = true
+					tmp = self.Left
+				}
+			case *sqlparser.ParenExpr:
+				if r.Expr == nil {
+					self.Right = nil
+					isRightTrue = true
+					tmp = self.Left
+				}
+			default:
+				if r == nil {
+					isRightTrue = true
+					tmp = self.Left
+				}
+			}
+
+			if isRightTrue && isLeftTrue {
+				tmp = nil
+			} else if !isLeftTrue && !isRightTrue {
+				return
+			}
+
+			// 根据类型开始替换节点
+			switch l := node.Prev.Self.(type) {
+			case *sqlparser.Where:
+				l.Expr = tmp
+			case *sqlparser.ParenExpr:
+				l.Expr = tmp
+			case *sqlparser.AndExpr:
+				if l.Left == self {
+					l.Left = tmp
+				} else if l.Right == self {
+					l.Right = tmp
+				}
+			case *sqlparser.OrExpr:
+				if l.Left == self {
+					l.Left = tmp
+				} else if l.Right == self {
+					l.Right = tmp
+				}
+			default:
+				// 未匹配到对应数据类型则从链表中移除该节点
+				err := node.Array.Remove(node.Prev)
+				common.LogIfError(err, "")
+			}
+
+		}
+
+	case *sqlparser.OrExpr:
+		// 与AndExpr相同
+		if self != nil {
+			var tmp sqlparser.Expr
+			isRightTrue := false
+			isLeftTrue := false
+			tmp = nil
+
+			switch l := self.Left.(type) {
+			case *sqlparser.ComparisonExpr:
+				if isAlwaysTrue(l) {
+					self.Left = nil
+					isLeftTrue = true
+					tmp = self.Right
+				}
+			case *sqlparser.ParenExpr:
+				if l.Expr == nil {
+					self.Left = nil
+					isLeftTrue = true
+					tmp = self.Right
+				}
+			default:
+				if l == nil {
+					isLeftTrue = true
+					tmp = self.Right
+				}
+			}
+
+			switch r := self.Right.(type) {
+			case *sqlparser.ComparisonExpr:
+				if isAlwaysTrue(r) {
+					self.Right = nil
+					isRightTrue = true
+					tmp = self.Left
+				}
+			case *sqlparser.ParenExpr:
+				if r.Expr == nil {
+					self.Right = nil
+					isRightTrue = true
+					tmp = self.Left
+				}
+			default:
+				if r == nil {
+					isRightTrue = true
+					tmp = self.Left
+				}
+			}
+
+			if isRightTrue && isLeftTrue {
+				tmp = nil
+			} else if !isLeftTrue && !isRightTrue {
+				return
+			}
+
+			switch l := node.Prev.Self.(type) {
+			case *sqlparser.Where:
+				l.Expr = tmp
+			case *sqlparser.ParenExpr:
+				l.Expr = tmp
+			case *sqlparser.AndExpr:
+				if l.Left == self {
+					l.Left = tmp
+				} else if l.Right == self {
+					l.Right = tmp
+				}
+			case *sqlparser.OrExpr:
+				if l.Left == self {
+					l.Left = tmp
+				} else if l.Right == self {
+					l.Right = tmp
+				}
+			default:
+				err := node.Array.Remove(node.Prev)
+				common.LogIfError(err, "")
+			}
+		}
+	}
+
+	omitAlwaysTrue(node.Prev)
+}
+
+// RewriteCountStar countstar: 将COUNT(col)改写为COUNT(*)
+// COUNT(DISTINCT col)不能替换为COUNT(*)
+func (rw *Rewrite) RewriteCountStar() *Rewrite {
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch f := node.(type) {
+		case *sqlparser.FuncExpr:
+			if strings.ToLower(f.Name.String()) == "count" && len(f.Exprs) > 0 {
+				switch colExpr := f.Exprs[0].(type) {
+				case *sqlparser.AliasedExpr:
+					switch col := colExpr.Expr.(type) {
+					case *sqlparser.ColName:
+						f.Exprs[0] = &sqlparser.StarExpr{TableName: col.Qualifier}
+					}
+				}
+			}
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteInnoDB InnoDB: 为未指定 Engine 的表默认添加 InnoDB 引擎,将其他存储引擎转为 InnoDB
+func (rw *Rewrite) RewriteInnoDB() *Rewrite {
+	switch create := rw.Stmt.(type) {
+	case *sqlparser.DDL:
+		if create.Action != "create" {
+			return rw
+		}
+
+		if strings.Contains(strings.ToLower(create.TableSpec.Options), "engine=") {
+			reg := regexp.MustCompile(`(?i)engine=[a-z]+`)
+			create.TableSpec.Options = reg.ReplaceAllString(create.TableSpec.Options, "ENGINE=InnoDB ")
+		} else {
+			create.TableSpec.Options = " ENGINE=InnoDB " + create.TableSpec.Options
+		}
+
+	}
+
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteAutoIncrement autoincrement: 将auto_increment设置为1
+func (rw *Rewrite) RewriteAutoIncrement() *Rewrite {
+	switch create := rw.Stmt.(type) {
+	case *sqlparser.DDL:
+		if create.Action != "create" || create.TableSpec == nil {
+			return rw
+		}
+		if strings.Contains(strings.ToLower(create.TableSpec.Options), "auto_increment=") {
+			reg := regexp.MustCompile(`(?i)auto_increment=[0-9]+`)
+			create.TableSpec.Options = reg.ReplaceAllString(create.TableSpec.Options, "auto_increment=1 ")
+		}
+	}
+
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteIntWidth intwidth: int 类型转为 int(10),bigint 类型转为 bigint(20)
+func (rw *Rewrite) RewriteIntWidth() *Rewrite {
+	switch create := rw.Stmt.(type) {
+	case *sqlparser.DDL:
+		if create.Action != "create" || create.TableSpec == nil {
+			return rw
+		}
+		for _, col := range create.TableSpec.Columns {
+			switch col.Type.Type {
+			case "int", "integer":
+				if col.Type.Length != nil &&
+					(string(col.Type.Length.Val) != "10" && string(col.Type.Length.Val) != "11") {
+					col.Type.Length = sqlparser.NewIntVal([]byte("10"))
+				}
+			case "bigint":
+				if col.Type.Length != nil && string(col.Type.Length.Val) != "20" || col.Type.Length == nil {
+					col.Type.Length = sqlparser.NewIntVal([]byte("20"))
+				}
+			default:
+			}
+		}
+	}
+
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteStar2Columns star2columns: 对应COL.001,SELECT补全*指代的列名
+func (rw *Rewrite) RewriteStar2Columns() *Rewrite {
+	// 如果未配置mysql环境或从环境中获取失败,*不进行替换
+	if common.Config.TestDSN.Disable || len(rw.Columns) == 0 {
+		common.Log.Debug("(rw *Rewrite) RewriteStar2Columns(): Rewrite failed. TestDSN.Disable: %v, len(rw.Columns):%d",
+			common.Config.TestDSN.Disable, len(rw.Columns))
+		return rw
+	}
+
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch n := node.(type) {
+		case *sqlparser.Select:
+
+			// select * 可能出现的情况:
+			// 1. select * from tb;
+			// 2. select * from tb1,tb2;
+			// 3. select tb1.* from tb1;
+			// 4. select tb1.*,tb2.col from tb1,tb2;
+			// 5. select db.tb1.* from tb1;
+			// 6. select db.tb1.*,db.tb2.col from db.tb1,db.tb2;
+
+			newSelectExprs := make(sqlparser.SelectExprs, 0)
+			for _, expr := range n.SelectExprs {
+				switch e := expr.(type) {
+				case *sqlparser.StarExpr:
+					// 一般情况下最外层循环不会超过两层
+					for _, tables := range rw.Columns {
+						for _, cols := range tables {
+							for _, col := range cols {
+								newExpr := &sqlparser.AliasedExpr{
+									Expr: &sqlparser.ColName{
+										Metadata: nil,
+										Name:     sqlparser.NewColIdent(col.Name),
+										Qualifier: sqlparser.TableName{
+											Name: sqlparser.NewTableIdent(col.Table),
+											// 因为不建议跨DB的查询,所以这里的db前缀将不进行补齐
+											Qualifier: sqlparser.TableIdent{},
+										},
+									},
+									As: sqlparser.ColIdent{},
+								}
+
+								if e.TableName.Name.IsEmpty() {
+									// 情况1,2
+									newSelectExprs = append(newSelectExprs, newExpr)
+								} else {
+									// 其他情况下只有在匹配表名的时候才会进行替换
+									if e.TableName.Name.String() == col.Table {
+										newSelectExprs = append(newSelectExprs, newExpr)
+									}
+								}
+							}
+						}
+					}
+				default:
+					newSelectExprs = append(newSelectExprs, e)
+				}
+			}
+
+			n.SelectExprs = newSelectExprs
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteInsertColumns insertcolumns: 对应COL.002,INSERT补全列名
+func (rw *Rewrite) RewriteInsertColumns() *Rewrite {
+
+	switch insert := rw.Stmt.(type) {
+	case *sqlparser.Insert:
+		switch insert.Action {
+		case "insert", "replace":
+			if insert.Columns != nil {
+				return rw
+			}
+
+			newColumns := make(sqlparser.Columns, 0)
+			db := insert.Table.Qualifier.String()
+			table := insert.Table.Name.String()
+			// 支持INSERT/REPLACE INTO VALUES形式,支持INSERT/REPLACE INTO SELECT
+			colCount := 0
+			switch v := insert.Rows.(type) {
+			case sqlparser.Values:
+				if len(v) > 0 {
+					colCount = len(v[0])
+				}
+
+			case *sqlparser.Select:
+				if l := len(v.SelectExprs); l > 0 {
+					colCount = l
+				}
+			}
+
+			// 开始对ast进行替换,补全前N列
+			counter := 0
+			for dbName, tb := range rw.Columns {
+				for tbName, cols := range tb {
+					for _, col := range cols {
+						// 只有全部列补全完成的时候才会替换ast
+						if counter == colCount {
+							insert.Columns = newColumns
+							rw.NewSQL = sqlparser.String(rw.Stmt)
+							return rw
+						}
+
+						if db != "" {
+							// 指定了DB的时候,只能怼指定DB的列
+							if db == dbName && table == tbName {
+								newColumns = append(newColumns, sqlparser.NewColIdent(col.Name))
+								counter++
+							}
+						} else {
+							// 没有指定DB的时候,将column中的列按顺序往里怼
+							if table == tbName {
+								newColumns = append(newColumns, sqlparser.NewColIdent(col.Name))
+								counter++
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return rw
+}
+
+// RewriteHaving having: 对应CLA.013,使用 WHERE 过滤条件替代 HAVING
+func (rw *Rewrite) RewriteHaving() *Rewrite {
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch n := node.(type) {
+		case *sqlparser.Select:
+			if n.Having != nil {
+				if n.Where == nil {
+					// WHERE 条件为空直接用 HAVING 替代 WHERE 即可
+					n.Where = n.Having
+				} else {
+					// WHERE 条件不为空,需要对已有的条件进行括号保护,然后再 AND+HAVING
+					n.Where = &sqlparser.Where{
+						Expr: &sqlparser.AndExpr{
+							Left: &sqlparser.ParenExpr{
+								Expr: n.Where.Expr,
+							},
+							Right: n.Having.Expr,
+						},
+					}
+				}
+				// 别忘了重置 HAVING 和 Where.Type
+				n.Where.Type = "where"
+				n.Having = nil
+			}
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteAddOrderByNull orderbynull: 对应 CLA.008,GROUP BY 无排序要求时添加 ORDER BY NULL
+func (rw *Rewrite) RewriteAddOrderByNull() *Rewrite {
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch n := node.(type) {
+		case *sqlparser.Select:
+			if n.GroupBy != nil && n.OrderBy == nil {
+				n.OrderBy = sqlparser.OrderBy{
+					&sqlparser.Order{
+						Expr:      &sqlparser.NullVal{},
+						Direction: "asc",
+					},
+				}
+			}
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteOr2Union or2union: 将 OR 查询转写为 UNION ALL TODO: 暂无对应 HeuristicRules
+// https://sqlperformance.com/2014/09/sql-plan/rewriting-queries-improve-performance
+func (rw *Rewrite) RewriteOr2Union() *Rewrite {
+	return rw
+}
+
+// RewriteUnionAll unionall: 不介意重复数据的情况下使用 union all 替换 union
+func (rw *Rewrite) RewriteUnionAll() *Rewrite {
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch n := node.(type) {
+		case *sqlparser.Union:
+			n.Type = "union all"
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteOr2In or2in: 同一列的 OR 过滤条件使用 IN() 替代,如果值有相等的会进行合并
+func (rw *Rewrite) RewriteOr2In() *Rewrite {
+	// 通过 AST 生成 node 的双向链表,链表顺序为书写顺序
+	nodeList := NewNodeList(rw.Stmt)
+	tNode := nodeList.First()
+
+	for {
+		tNode.or2in()
+		if tNode.Next == nil {
+			break
+		}
+		tNode = tNode.Next
+	}
+
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// or2in 用于将 or 转换成 in
+func (node *NodeItem) or2in() {
+	if node == nil || node.Self == nil {
+		return
+	}
+
+	switch selfNode := node.Self.(type) {
+	case *sqlparser.OrExpr:
+		newExpr := mergeExprs(selfNode.Left, selfNode.Right)
+		if newExpr != nil {
+			// or 自身两个节点可以合并的情况下,将父节点中的 expr 替换成新的
+			switch pre := node.Prev.Self.(type) {
+			case *sqlparser.OrExpr:
+				if pre.Left == node.Self {
+					node.Self = newExpr
+					pre.Left = newExpr
+				} else if pre.Right == node.Self {
+					node.Self = newExpr
+					pre.Right = newExpr
+				}
+			case *sqlparser.AndExpr:
+				if pre.Left == node.Self {
+					node.Self = newExpr
+					pre.Left = newExpr
+				} else if pre.Right == node.Self {
+					node.Self = newExpr
+					pre.Right = newExpr
+				}
+			case *sqlparser.Where:
+				node.Self = newExpr
+				pre.Expr = newExpr
+			case *sqlparser.ParenExpr:
+				// 如果 SQL 书写中带了括号,暂不会进行跨括号的合并
+				// TODO: 无意义括号打平,加个 rewrite rule
+				node.Self = newExpr
+				pre.Expr = newExpr
+			}
+		} else {
+			// or 自身两个节点如不可以合并,则检测是否可以与父节点合并
+			// 与父节点的合并不能跨越and、括号等,可能会改变语义
+			// 检查自身左右节点是否能与上层节点中合并,or 只能与 or 合并
+			switch pre := node.Prev.Self.(type) {
+			case *sqlparser.OrExpr:
+				// AST 中如果出现复合条件,则一定在左树,所以只需要判断左边就可以
+				if pre.Left == selfNode {
+					switch n := pre.Right.(type) {
+					case *sqlparser.ComparisonExpr:
+						newLeftExpr := mergeExprs(selfNode.Left, n)
+						newRightExpr := mergeExprs(selfNode.Right, n)
+
+						// newLeftExpr 与 newRightExpr 一定有一个是 nil,
+						// 否则说明该 orExpr 下的两个节点可合并,可以通过最后的向前递归合并 pre 节点中的 expr
+						if newLeftExpr == nil || newRightExpr == nil {
+							if newLeftExpr != nil {
+								pre.Right = newLeftExpr
+								pre.Left = selfNode.Right
+								err := node.Array.Remove(node)
+								common.LogIfError(err, "")
+							}
+
+							if newRightExpr != nil {
+								pre.Right = newRightExpr
+								pre.Left = selfNode.Left
+								err := node.Array.Remove(node)
+								common.LogIfError(err, "")
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	// 逆向合并由更改 AST 后产生的新的可合并节点
+	node.Prev.or2in()
+}
+
+// mergeExprs 将两个属于同一个列的 ComparisonExpr 合并成一个,如果不能合并则返回 nil
+func mergeExprs(left, right sqlparser.Expr) *sqlparser.ComparisonExpr {
+	// 用于对比两个列是否相同
+	colInLeft := ""
+	colInRight := ""
+	lOperator := ""
+	rOperator := ""
+
+	// 用于存放 expr 左右子树中的值
+	var values []sqlparser.SQLNode
+
+	// SQL 中使用到的列
+	var colName *sqlparser.ColName
+
+	// 左子树
+	switch l := left.(type) {
+	case *sqlparser.ComparisonExpr:
+		// 获取列名
+		colName, colInLeft = getColumnName(l.Left)
+		// 获取值
+		if colInLeft != "" {
+			switch v := l.Right.(type) {
+			case *sqlparser.SQLVal, sqlparser.ValTuple, *sqlparser.BoolVal, *sqlparser.NullVal:
+				values = append(values, v)
+			}
+		}
+		// 获取 operator
+		lOperator = l.Operator
+	default:
+		return nil
+	}
+
+	// 右子树
+	switch r := right.(type) {
+	case *sqlparser.ComparisonExpr:
+		// 获取列名
+		if colName.Name.String() != "" {
+			common.Log.Warn("colName shouldn't has value, but now it's %s", colName.Name.String())
+		}
+		colName, colInRight = getColumnName(r.Left)
+		// 获取值
+		if colInRight != "" {
+			switch v := r.Right.(type) {
+			case *sqlparser.SQLVal, sqlparser.ValTuple, *sqlparser.BoolVal, *sqlparser.NullVal:
+				values = append(values, v)
+			}
+		}
+		// 获取 operator
+		rOperator = r.Operator
+	default:
+		return nil
+	}
+
+	// operator 替换,用于在之后判断是否可以合并
+	switch lOperator {
+	case "in", "=":
+		lOperator = "="
+	default:
+		return nil
+	}
+
+	switch rOperator {
+	case "in", "=":
+		rOperator = "="
+	default:
+		return nil
+	}
+
+	// 不匹配则返回
+	if colInLeft == "" || colInLeft != colInRight ||
+		lOperator == "" || lOperator != rOperator {
+		return nil
+	}
+
+	// 合并左右子树的值
+	newValTuple := make(sqlparser.ValTuple, 0)
+	for _, v := range values {
+		switch v := v.(type) {
+		case *sqlparser.SQLVal:
+			newValTuple = append(newValTuple, v)
+		case *sqlparser.BoolVal:
+			newValTuple = append(newValTuple, v)
+		case *sqlparser.NullVal:
+			newValTuple = append(newValTuple, v)
+		case sqlparser.ValTuple:
+			newValTuple = append(newValTuple, v...)
+		}
+	}
+
+	// 去 expr 中除重复的 value,
+	newValTuple = removeDup(newValTuple...)
+	newExpr := &sqlparser.ComparisonExpr{
+		Operator: "in",
+		Left:     colName,
+		Right:    newValTuple,
+	}
+	// 如果只有一个值则是一个等式,没有必要转写成 in
+	if len(newValTuple) == 1 {
+		newExpr = &sqlparser.ComparisonExpr{
+			Operator: lOperator,
+			Left:     colName,
+			Right:    newValTuple[0],
+		}
+	}
+
+	return newExpr
+}
+
+// removeDup 清除 sqlparser.ValTuple 中重复的值
+func removeDup(vt ...sqlparser.Expr) sqlparser.ValTuple {
+	uni := make(sqlparser.ValTuple, 0)
+	m := make(map[string]sqlparser.SQLNode)
+
+	for _, value := range vt {
+		switch v := value.(type) {
+		case *sqlparser.SQLVal:
+			// Type:Val, 冒号用于分隔 Type 和 Val,防止两种不同类型拼接后出现同一个值
+			if _, ok := m[string(v.Type)+":"+sqlparser.String(v)]; !ok {
+				uni = append(uni, v)
+				m[string(v.Type)+":"+sqlparser.String(v)] = v
+			}
+		case *sqlparser.BoolVal:
+			if _, ok := m[sqlparser.String(v)]; !ok {
+				uni = append(uni, v)
+				m[sqlparser.String(v)] = v
+			}
+		case *sqlparser.NullVal:
+			if _, ok := m[sqlparser.String(v)]; !ok {
+				uni = append(uni, v)
+				m[sqlparser.String(v)] = v
+			}
+		case sqlparser.ValTuple:
+			for _, val := range removeDup(v...) {
+				switch v := val.(type) {
+				case *sqlparser.SQLVal:
+					if _, ok := m[string(v.Type)+":"+sqlparser.String(v)]; !ok {
+						uni = append(uni, v)
+						m[string(v.Type)+":"+sqlparser.String(v)] = v
+					}
+				case *sqlparser.BoolVal:
+					if _, ok := m[sqlparser.String(v)]; !ok {
+						uni = append(uni, v)
+						m[sqlparser.String(v)] = v
+					}
+				case *sqlparser.NullVal:
+					if _, ok := m[sqlparser.String(v)]; !ok {
+						uni = append(uni, v)
+						m[sqlparser.String(v)] = v
+					}
+				}
+			}
+		}
+	}
+
+	return uni
+}
+
+// RewriteInNull innull: TODO: 对应ARG.004
+func (rw *Rewrite) RewriteInNull() *Rewrite {
+	return rw
+}
+
+// RewriteRmParenthesis rmparenthesis: 去除无意义的括号
+func (rw *Rewrite) RewriteRmParenthesis() *Rewrite {
+	rw.rmParenthesis()
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// rmParenthesis 用于语出无用的括号
+func (rw *Rewrite) rmParenthesis() {
+	continueFlag := false
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch node := node.(type) {
+		case *sqlparser.Where:
+			if node == nil {
+				return true, nil
+			}
+			switch paren := node.Expr.(type) {
+			case *sqlparser.ParenExpr:
+				switch paren.Expr.(type) {
+				case *sqlparser.ComparisonExpr:
+					node.Expr = paren.Expr
+					continueFlag = true
+				}
+			}
+
+		case *sqlparser.ParenExpr:
+			switch paren := node.Expr.(type) {
+			case *sqlparser.ParenExpr:
+				switch paren.Expr.(type) {
+				case *sqlparser.ComparisonExpr:
+					node.Expr = paren.Expr
+					continueFlag = true
+				}
+			}
+
+		case *sqlparser.AndExpr:
+			switch left := node.Left.(type) {
+			case *sqlparser.ParenExpr:
+				switch inner := left.Expr.(type) {
+				case *sqlparser.ComparisonExpr:
+					node.Left = inner
+					continueFlag = true
+				}
+			}
+
+			switch right := node.Right.(type) {
+			case *sqlparser.ParenExpr:
+				switch inner := right.Expr.(type) {
+				case *sqlparser.ComparisonExpr:
+					node.Right = inner
+					continueFlag = true
+				}
+			}
+
+		case *sqlparser.OrExpr:
+			switch left := node.Left.(type) {
+			case *sqlparser.ParenExpr:
+				switch inner := left.Expr.(type) {
+				case *sqlparser.ComparisonExpr:
+					node.Left = inner
+					continueFlag = true
+				}
+			}
+
+			switch right := node.Right.(type) {
+			case *sqlparser.ParenExpr:
+				switch inner := right.Expr.(type) {
+				case *sqlparser.ComparisonExpr:
+					node.Right = inner
+					continueFlag = true
+				}
+			}
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	// 本层的修改可能使得原本不符合条件的括号变为无意义括号
+	// 每次修改都需要再过滤一遍语法树
+	if continueFlag {
+		rw.rmParenthesis()
+	} else {
+		return
+	}
+}
+
+// RewriteRemoveDMLOrderBy dmlorderby: 对应 RES.004,删除无 LIMIT 条件时 UPDATE, DELETE 中包含的 ORDER BY
+func (rw *Rewrite) RewriteRemoveDMLOrderBy() *Rewrite {
+	switch st := rw.Stmt.(type) {
+	case *sqlparser.Update:
+		err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+			switch n := node.(type) {
+			case *sqlparser.Select:
+				if n.OrderBy != nil && n.Limit == nil {
+					n.OrderBy = nil
+				}
+				return false, nil
+			}
+			return true, nil
+		}, rw.Stmt)
+		common.LogIfError(err, "")
+		if st.OrderBy != nil && st.Limit == nil {
+			st.OrderBy = nil
+		}
+	case *sqlparser.Delete:
+		err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+			switch n := node.(type) {
+			case *sqlparser.Select:
+				if n.OrderBy != nil && n.Limit == nil {
+					n.OrderBy = nil
+				}
+				return false, nil
+			}
+			return true, nil
+		}, rw.Stmt)
+		common.LogIfError(err, "")
+		if st.OrderBy != nil && st.Limit == nil {
+			st.OrderBy = nil
+		}
+	}
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteGroupByConst 对应CLA.004,将GROUP BY CONST替换为列名
+// TODO:
+func (rw *Rewrite) RewriteGroupByConst() *Rewrite {
+	err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch n := node.(type) {
+		case *sqlparser.Select:
+			groupByCol := false
+			if n.GroupBy != nil {
+				for _, group := range n.GroupBy {
+					switch group.(type) {
+					case *sqlparser.SQLVal:
+					default:
+						groupByCol = true
+					}
+				}
+				if !groupByCol {
+					// TODO: 这里只是去掉了GROUP BY并没解决问题
+					n.GroupBy = nil
+				}
+			}
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	rw.NewSQL = sqlparser.String(rw.Stmt)
+	return rw
+}
+
+// RewriteSubQuery2Join 将 subquery 转写成 join
+func (rw *Rewrite) RewriteSubQuery2Join() *Rewrite {
+	var err error
+	// 如果未配置 mysql 环境或从环境中获取失败
+	if common.Config.TestDSN.Disable || len(rw.Columns) == 0 {
+		common.Log.Debug("(rw *Rewrite) RewriteSubQuery2Join(): Rewrite failed. TestDSN.Disable: %v, len(rw.Columns):%d",
+			common.Config.TestDSN.Disable, len(rw.Columns))
+		return rw
+	}
+
+	if rw.NewSQL == "" {
+		rw.NewSQL = sqlparser.String(rw.Stmt)
+	}
+
+	// query backup
+	backup := rw.NewSQL
+	var subQueryList []string
+	err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch sub := node.(type) {
+		case sqlparser.SelectStatement:
+			subStr := sqlparser.String(sub)
+			if strings.HasPrefix(subStr, "(") {
+				subStr = subStr[1 : len(subStr)-1]
+			}
+			subQueryList = append(subQueryList, subStr)
+		}
+		return true, nil
+	}, rw.Stmt)
+	common.LogIfError(err, "")
+	if length := len(subQueryList); length > 1 {
+		lastResult := ""
+		for i := length - 1; i > 0; i-- {
+			if lastResult == "" {
+				lastResult, err = rw.sub2Join(subQueryList[i-1], subQueryList[i])
+			} else {
+				// 将subquery的部分替换成上次合并的结果
+				subQueryList[i-1] = strings.Replace(subQueryList[i-1], subQueryList[i], lastResult, -1)
+				lastResult, err = rw.sub2Join(subQueryList[i-1], lastResult)
+			}
+
+			if err != nil {
+				common.Log.Error("RewriteSubQuery2Join Error: %v", err)
+				return rw
+			}
+		}
+		rw.NewSQL = lastResult
+	} else if length == 1 {
+		var newSQL string
+		newSQL, err = rw.sub2Join(rw.NewSQL, subQueryList[0])
+		if err == nil {
+			rw.NewSQL = newSQL
+		}
+	}
+
+	// 因为这个修改不会直接修改rw.stmt,所以需要将rw.stmt也更新一下
+	newStmt, err := sqlparser.Parse(rw.NewSQL)
+	if err != nil {
+		rw.NewSQL = backup
+		rw.Stmt, _ = sqlparser.Parse(backup)
+	} else {
+		rw.Stmt = newStmt
+	}
+
+	return rw
+}
+
+// sub2Join 将 subquery 转写成 join
+func (rw *Rewrite) sub2Join(parent, sub string) (string, error) {
+	// 只处理SelectStatement
+	if sqlparser.Preview(parent) != sqlparser.StmtSelect || sqlparser.Preview(sub) != sqlparser.StmtSelect {
+		return "", nil
+	}
+
+	// 如果子查询不属于parent,则不处理
+	if !strings.Contains(parent, sub) {
+		return "", nil
+	}
+
+	// 解析外层SQL语法树
+	stmt, err := sqlparser.Parse(parent)
+	if err != nil {
+		common.Log.Warn("(rw *Rewrite) RewriteSubQuery2Join() sub2Join sql `%s` parsed error: %v", parent, err)
+		return "", err
+	}
+
+	switch stmt.(type) {
+	case sqlparser.SelectStatement:
+	default:
+		common.Log.Debug("Query `%s` not select statement.", parent)
+		return "", nil
+	}
+
+	// 解析子查询语法树
+	subStmt, err := sqlparser.Parse(sub)
+	if err != nil {
+		common.Log.Warn("(rw *Rewrite) RewriteSubQuery2Join() sub2Join sql `%s` parsed error: %v", sub, err)
+		return "", err
+	}
+
+	// 获取外部SQL用到的表
+	stmtMeta := GetTableFromExprs(stmt.(*sqlparser.Select).From)
+	// 获取内部SQL用到的表
+	subMeta := GetTableFromExprs(subStmt.(*sqlparser.Select).From)
+
+	// 处理关联条件
+	err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+		switch p := node.(type) {
+		case *sqlparser.ComparisonExpr:
+			// a in (select * from tb)
+			switch subquery := p.Right.(type) {
+			case *sqlparser.Subquery:
+
+				// 获取左边的列
+				var leftColumn *sqlparser.ColName
+
+				switch l := p.Left.(type) {
+				case *sqlparser.ColName:
+					leftColumn = l
+				default:
+					return false, nil
+				}
+
+				// 用于存放获取的subquery中的列,有且只有一个
+				var rightColumn sqlparser.SQLNode
+
+				// 对subquery中的列进行替换
+				switch subSelectStmt := subquery.Select.(type) {
+				case *sqlparser.Select:
+					cachingOperator := p.Operator
+
+					rightColumn = subSelectStmt.SelectExprs[0]
+
+					rightCol, _ := getColumnName(rightColumn.(*sqlparser.AliasedExpr).Expr)
+					if rightCol != nil {
+						// 将subquery替换为等值条件
+						p.Operator = "="
+
+						// selectExpr 信息补齐
+						var newExprs []sqlparser.SelectExpr
+						err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+							switch col := node.(type) {
+							case *sqlparser.StarExpr:
+								if col.TableName.Name.IsEmpty() {
+									for dbName, db := range stmtMeta {
+										for tbName := range db.Table {
+
+											col.TableName.Name = sqlparser.NewTableIdent(tbName)
+											if dbName != "" {
+												col.TableName.Qualifier = sqlparser.NewTableIdent(dbName)
+											}
+
+											newExprs = append(newExprs, col)
+										}
+									}
+								}
+							case *sqlparser.AliasedExpr:
+								switch n := col.Expr.(type) {
+								case *sqlparser.ColName:
+									col.Expr = columnFromWhere(n, stmtMeta, rw.Columns)
+								}
+							}
+							return true, nil
+						}, stmt.(*sqlparser.Select).SelectExprs)
+						common.LogIfError(err, "")
+
+						// 原节点列信息补齐
+						p.Left = columnFromWhere(leftColumn, stmtMeta, rw.Columns)
+
+						// 将子查询中的节点上提,补充前缀信息
+						p.Right = columnFromWhere(rightCol, subMeta, rw.Columns)
+
+						// subquery Where条件中的列信息补齐
+						subWhereExpr := subStmt.(*sqlparser.Select).Where
+						err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
+							switch n := node.(type) {
+							case *sqlparser.ComparisonExpr:
+								switch left := n.Left.(type) {
+								case *sqlparser.ColName:
+									n.Left = columnFromWhere(left, subMeta, rw.Columns)
+								}
+
+								switch right := n.Right.(type) {
+								case *sqlparser.ColName:
+									n.Right = columnFromWhere(right, subMeta, rw.Columns)
+								}
+							}
+							return true, nil
+						}, subWhereExpr)
+						common.LogIfError(err, "")
+						// 如果 subquery 中存在 Where 条件,怼在 parent 的 where 中后面
+						if subWhereExpr != nil {
+							if stmt.(*sqlparser.Select).Where != nil {
+								stmt.(*sqlparser.Select).Where.Expr = &sqlparser.AndExpr{
+									Left:  stmt.(*sqlparser.Select).Where.Expr,
+									Right: subWhereExpr.Expr,
+								}
+							} else {
+								stmt.(*sqlparser.Select).Where = subWhereExpr
+							}
+						}
+
+						switch cachingOperator {
+						case "in":
+							// 将表以 inner join 的形式追加到 parent 的 from 中
+							var newTables []sqlparser.TableExpr
+							for _, subExpr := range subStmt.(*sqlparser.Select).From {
+								has := false
+								for _, expr := range stmt.(*sqlparser.Select).From {
+									if reflect.DeepEqual(expr, subExpr) {
+										has = true
+									}
+								}
+								if !has {
+									newTables = append(newTables, subExpr)
+								}
+							}
+							stmt.(*sqlparser.Select).From = append(stmt.(*sqlparser.Select).From, newTables...)
+						case "not in":
+							// 将表以left join 的形式 追加到 parent 的 from 中
+							// TODO:
+						}
+					}
+
+				}
+			}
+		}
+		return true, nil
+	}, stmt)
+	common.LogIfError(err, "")
+	newSQL := sqlparser.String(stmt)
+	return newSQL, nil
+}
+
+// columnFromWhere 获取列是来自哪个表,并补充前缀
+func columnFromWhere(col *sqlparser.ColName, meta common.Meta, columns common.TableColumns) *sqlparser.ColName {
+
+	for dbName, db := range meta {
+		for tbName := range db.Table {
+			for _, tables := range columns {
+				for _, columns := range tables {
+					for _, column := range columns {
+						if strings.EqualFold(col.Name.String(), column.Name) {
+							if col.Qualifier.Name.IsEmpty() && tbName == column.Table {
+								col.Qualifier.Name = sqlparser.NewTableIdent(column.Table)
+								return col
+							}
+							if (dbName == "" && tbName == column.Table) || (tbName == column.Table && dbName == column.DB) {
+								col.Qualifier.Name = sqlparser.NewTableIdent(column.Table)
+								if dbName != "" {
+									col.Qualifier.Qualifier = sqlparser.NewTableIdent(column.DB)
+								}
+								return col
+							}
+						}
+					}
+				}
+			}
+
+		}
+	}
+	return col
+}
+
+// RewriteJoin2SubQuery join2sub: TODO:
+// https://mariadb.com/kb/en/library/subqueries-and-joins/
+func (rw *Rewrite) RewriteJoin2SubQuery() *Rewrite {
+	return rw
+}
+
+// RewriteDistinctStar distinctstar: 对应DIS.003,将多余的`DISTINCT *`删除
+func (rw *Rewrite) RewriteDistinctStar() *Rewrite {
+	// 注意:这里并未对表是否有主键做检查,按照我们的SQL编程规范,一张表必须有主键
+	switch rw.Stmt.(type) {
+	case *sqlparser.Select:
+		meta := GetMeta(rw.Stmt, nil)
+		for _, m := range meta {
+			if len(m.Table) == 1 {
+				// distinct tbl.*, distinct *, count(distinct *)
+				re := regexp.MustCompile(`(?i)((distinct\s*\*)|(distinct\s+[0-9a-z_` + "`" + `]*\.\*))`)
+				if re.MatchString(rw.SQL) {
+					rw.NewSQL = re.ReplaceAllString(rw.SQL, "*")
+				}
+			}
+			break
+		}
+	}
+	if rw.NewSQL == "" {
+		rw.NewSQL = rw.SQL
+	}
+	rw.Stmt, _ = sqlparser.Parse(rw.NewSQL)
+	return rw
+}
+
+// RewriteTruncate truncate: DELETE 全表修改为 TRUNCATE TABLE
+func (rw *Rewrite) RewriteTruncate() *Rewrite {
+	switch n := rw.Stmt.(type) {
+	case *sqlparser.Delete:
+		meta := GetMeta(rw.Stmt, nil)
+		if len(meta) == 1 && n.Where == nil {
+			for _, db := range meta {
+				for _, tbl := range db.Table {
+					rw.NewSQL = "truncate table " + tbl.TableName
+				}
+			}
+		}
+	}
+	return rw
+}
+
+// RewriteDML2Select dml2select: DML 转成 SELECT,兼容低版本的 EXPLAIN
+func (rw *Rewrite) RewriteDML2Select() *Rewrite {
+	if rw.Stmt == nil {
+		return rw
+	}
+
+	switch stmt := rw.Stmt.(type) {
+	case *sqlparser.Select:
+		rw.NewSQL = rw.SQL
+	case *sqlparser.Delete: // Multi DELETE not support yet.
+		rw.NewSQL = delete2Select(stmt)
+	case *sqlparser.Insert:
+		rw.NewSQL = insert2Select(stmt)
+	case *sqlparser.Update: // Multi UPDATE not support yet.
+		rw.NewSQL = update2Select(stmt)
+	}
+	rw.Stmt, _ = sqlparser.Parse(rw.NewSQL)
+	return rw
+}
+
+// delete2Select 将 Delete 语句改写成 Select
+func delete2Select(stmt *sqlparser.Delete) string {
+	newSQL := &sqlparser.Select{
+		SelectExprs: []sqlparser.SelectExpr{
+			new(sqlparser.StarExpr),
+		},
+		From:    stmt.TableExprs,
+		Where:   stmt.Where,
+		OrderBy: stmt.OrderBy,
+	}
+	return sqlparser.String(newSQL)
+}
+
+// update2Select 将 Update 语句改写成 Select
+func update2Select(stmt *sqlparser.Update) string {
+	newSQL := &sqlparser.Select{
+		SelectExprs: []sqlparser.SelectExpr{
+			new(sqlparser.StarExpr),
+		},
+		From:    stmt.TableExprs,
+		Where:   stmt.Where,
+		OrderBy: stmt.OrderBy,
+		Limit:   stmt.Limit,
+	}
+	return sqlparser.String(newSQL)
+}
+
+// insert2Select 将 Insert 语句改写成 Select
+func insert2Select(stmt *sqlparser.Insert) string {
+	switch row := stmt.Rows.(type) {
+	// 如果insert包含子查询,只需要explain该子树
+	case *sqlparser.Select, *sqlparser.Union, *sqlparser.ParenSelect:
+		return sqlparser.String(row)
+	}
+
+	return "select 1 from DUAL"
+}
+
+// AlterAffectTable 获取ALTER影响的库表名,返回:`db`.`table`
+func AlterAffectTable(stmt sqlparser.Statement) string {
+	switch n := stmt.(type) {
+	case *sqlparser.DDL:
+		tableName := strings.ToLower(n.Table.Name.String())
+		dbName := strings.ToLower(n.Table.Qualifier.String())
+		if tableName != "" && tableName != "dual" {
+			if dbName == "" {
+				return "`" + tableName + "`"
+			}
+
+			return "`" + dbName + "`.`" + tableName + "`"
+		}
+	}
+	return ""
+}
+
+// MergeAlterTables mergealter: 将同一张表的多条 ALTER 语句合成一条 ALTER 语句
+// @input: sql, alter string
+// @output: [[db.]table]sql, 如果找不到 DB,key 为表名;如果找得到 DB,key 为 db.table
+func MergeAlterTables(sqls ...string) map[string]string {
+	alterSQLs := make(map[string][]string)
+	mergedAlterStr := make(map[string]string)
+
+	// table/column/index name can be quoted in back ticks
+	backTicks := "(`[^\\s]*`)"
+
+	alterExp := regexp.MustCompile(`(?i)alter\s*table\s*(` + backTicks + `|([^\s]*))\s*`)   // ALTER TABLE
+	renameExp := regexp.MustCompile(`(?i)rename\s*table\s*(` + backTicks + `|([^\s]*))\s*`) // RENAME TABLE
+	// CREATE [UNIQUE|FULLTEXT|SPATIAL|PRIMARY] [KEY|INDEX] idx_name ON tbl_name
+	createIndexExp := regexp.MustCompile(`(?i)create((unique)|(fulltext)|(spatial)|(primary)|(\s*)\s*)((index)|(key))\s*`)
+	indexNameExp := regexp.MustCompile(`(?i)(` + backTicks + `|([^\s]*))\s*`)
+	indexColsExp := regexp.MustCompile(`(?i)(` + backTicks + `|([^\s]*))\s*on\s*(` + backTicks + `|([^\s]*))\s*`)
+
+	for _, sql := range sqls {
+		sql = strings.Trim(sql, common.Config.Delimiter)
+		stmt, _ := sqlparser.Parse(sql)
+		alterSQL := ""
+		dbName := ""
+		tableName := ""
+		switch n := stmt.(type) {
+		case *sqlparser.DDL:
+			// 注意: 表名和库名不区分大小写
+			tableName = strings.ToLower(n.Table.Name.String())
+			dbName = strings.ToLower(n.Table.Qualifier.String())
+			switch n.Action {
+			case "rename":
+				if alterExp.MatchString(sql) {
+					common.Log.Debug("rename alterExp: ALTER %v %v", tableName, alterExp.ReplaceAllString(sql, ""))
+					alterSQL = fmt.Sprint(alterExp.ReplaceAllString(sql, ""))
+				} else if renameExp.MatchString(sql) {
+					common.Log.Debug("rename renameExp: ALTER %v %v", tableName, alterExp.ReplaceAllString(sql, ""))
+					alterSQL = fmt.Sprint(alterExp.ReplaceAllString(sql, ""))
+				} else {
+					common.Log.Warn("rename not match: ALTER %v %v", tableName, sql)
+				}
+			case "alter":
+				if alterExp.MatchString(sql) {
+					common.Log.Debug("rename alterExp: ALTER %v %v", tableName, alterExp.ReplaceAllString(sql, ""))
+					alterSQL = fmt.Sprint(alterExp.ReplaceAllString(sql, ""))
+				} else if createIndexExp.MatchString(sql) {
+					buf := createIndexExp.ReplaceAllString(sql, "")
+					idxName := strings.TrimSpace(indexNameExp.FindString(buf))
+					buf = indexColsExp.ReplaceAllString(buf, "")
+					common.Log.Debug("alter createIndexExp: ALTER %v ADD INDEX %v %v", tableName, "ADD INDEX", idxName, buf)
+					alterSQL = fmt.Sprint("ADD INDEX", " "+idxName+" ", buf)
+				}
+			default:
+
+			}
+		}
+		if alterSQL != "" && tableName != "" && tableName != "dual" {
+			if dbName == "" {
+				alterSQLs["`"+tableName+"`"] = append(alterSQLs["`"+tableName+"`"], alterSQL)
+			} else {
+				alterSQLs["`"+dbName+"`.`"+tableName+"`"] = append(alterSQLs["`"+dbName+"`.`"+tableName+"`"], alterSQL)
+			}
+		}
+	}
+	for k, v := range alterSQLs {
+		mergedAlterStr[k] = fmt.Sprintln("ALTER TABLE", k, strings.Join(v, ", "), common.Config.Delimiter)
+	}
+	return mergedAlterStr
+}
+
+// RewriteRuleMatch 检查重写规则是否生效
+func RewriteRuleMatch(name string) bool {
+	for _, r := range common.Config.RewriteRules {
+		if r == name {
+			return true
+		}
+	}
+	return false
+}
diff --git a/vendor/github.com/XiaoMi/soar/ast/rewrite_test.go b/vendor/github.com/XiaoMi/soar/ast/rewrite_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..043acb9080d0783b6bec8a4f24a57562d1ff9e74
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/ast/rewrite_test.go
@@ -0,0 +1,705 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 ast
+
+import (
+	"fmt"
+	"sort"
+	"testing"
+
+	"github.com/XiaoMi/soar/common"
+)
+
+func TestRewrite(t *testing.T) {
+	common.Config.TestDSN.Disable = false
+	testSQL := []map[string]string{
+		{
+			"input":  `SELECT * FROM film`,
+			"output": `select film.film_id, film.title, film.description, film.release_year, film.language_id, film.original_language_id, film.rental_duration from film;`,
+		},
+		{
+			"input":  `SELECT film.*, actor.actor_id FROM film,actor`,
+			"output": `select film.film_id, film.title, film.description, film.release_year, film.language_id, film.original_language_id, film.rental_duration, actor.actor_id from film, actor;`,
+		},
+		{
+			"input":  `insert into film values(1,2,3,4,5)`,
+			"output": `insert into film(film_id, title, description, release_year, language_id) values (1, 2, 3, 4, 5);`,
+		},
+		{
+			"input":  `insert into sakila.film values(1,2)`,
+			"output": `insert into sakila.film(film_id, title) values (1, 2);`,
+		},
+		{
+			"input":  `replace into sakila.film select id from tb`,
+			"output": `replace into sakila.film(film_id) select id from tb;`,
+		},
+		{
+			"input":  `replace into sakila.film select id, title, description from tb`,
+			"output": `replace into sakila.film(film_id, title, description) select id, title, description from tb;`,
+		},
+		{
+			"input":  `insert into film values(1,2,3,4,5)`,
+			"output": `insert into film(film_id, title, description, release_year, language_id) values (1, 2, 3, 4, 5);`,
+		},
+		{
+			"input":  `insert into sakila.film values(1,2)`,
+			"output": `insert into sakila.film(film_id, title) values (1, 2);`,
+		},
+		{
+			"input":  `replace into sakila.film select id from tb`,
+			"output": `replace into sakila.film(film_id) select id from tb;`,
+		},
+		{
+			"input":  `replace into sakila.film select id, title, description from tb`,
+			"output": `replace into sakila.film(film_id, title, description) select id, title, description from tb;`,
+		},
+		{
+			"input":  "DELETE FROM tbl WHERE col1=1 ORDER BY col",
+			"output": "delete from tbl where col1 = 1;",
+		},
+		{
+			"input":  "UPDATE tbl SET col =1 WHERE col1=1 ORDER BY col",
+			"output": "update tbl set col = 1 where col1 = 1;",
+		},
+	}
+
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"])
+		rw.Columns = map[string]map[string][]*common.Column{
+			"sakila": {
+				"film": {
+					{Name: "film_id", Table: "film"},
+					{Name: "title", Table: "film"},
+					{Name: "description", Table: "film"},
+					{Name: "release_year", Table: "film"},
+					{Name: "language_id", Table: "film"},
+					{Name: "original_language_id", Table: "film"},
+					{Name: "rental_duration", Table: "film"},
+				},
+			},
+		}
+		rw.Rewrite()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteStar2Columns(t *testing.T) {
+	common.Config.TestDSN.Disable = false
+	testSQL := []map[string]string{
+		{
+			"input":  `SELECT * FROM film`,
+			"output": `select film.film_id, film.title from film`,
+		},
+		{
+			"input":  `SELECT film.*, actor.actor_id FROM film,actor`,
+			"output": `select film.film_id, film.title, actor.actor_id from film, actor`,
+		},
+	}
+
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"])
+		rw.Columns = map[string]map[string][]*common.Column{
+			"sakila": {
+				"film": {
+					{Name: "film_id", Table: "film"},
+					{Name: "title", Table: "film"},
+				},
+			},
+		}
+		rw.RewriteStar2Columns()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteInsertColumns(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `insert into film values(1,2,3,4,5)`,
+			"output": `insert into film(film_id, title, description, release_year, language_id) values (1, 2, 3, 4, 5)`,
+		},
+		{
+			"input":  `insert into sakila.film values(1,2)`,
+			"output": `insert into sakila.film(film_id, title) values (1, 2)`,
+		},
+		{
+			"input":  `replace into sakila.film select id from tb`,
+			"output": `replace into sakila.film(film_id) select id from tb`,
+		},
+		{
+			"input":  `replace into sakila.film select id, title, description from tb`,
+			"output": `replace into sakila.film(film_id, title, description) select id, title, description from tb`,
+		},
+	}
+
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"])
+		rw.Columns = map[string]map[string][]*common.Column{
+			"sakila": {
+				"film": {
+					{Name: "film_id", Table: "film"},
+					{Name: "title", Table: "film"},
+					{Name: "description", Table: "film"},
+					{Name: "release_year", Table: "film"},
+					{Name: "language_id", Table: "film"},
+					{Name: "original_language_id", Table: "film"},
+					{Name: "rental_duration", Table: "film"},
+				},
+			},
+		}
+		rw.RewriteInsertColumns()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteHaving(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `SELECT state, COUNT(*) FROM Drivers GROUP BY state HAVING state IN ('GA', 'TX') ORDER BY state`,
+			"output": "select state, COUNT(*) from Drivers where state in ('GA', 'TX') group by state order by state asc",
+		},
+		{
+			"input":  `SELECT state, COUNT(*) FROM Drivers WHERE col =1 GROUP BY state HAVING state IN ('GA', 'TX') ORDER BY state`,
+			"output": "select state, COUNT(*) from Drivers where (col = 1) and state in ('GA', 'TX') group by state order by state asc",
+		},
+		{
+			"input":  `SELECT state, COUNT(*) FROM Drivers WHERE col =1 or col1 =2 GROUP BY state HAVING state IN ('GA', 'TX') ORDER BY state`,
+			"output": "select state, COUNT(*) from Drivers where (col = 1 or col1 = 2) and state in ('GA', 'TX') group by state order by state asc",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteHaving()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteAddOrderByNull(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "SELECT sum(col1) FROM tbl GROUP BY col",
+			"output": "select sum(col1) from tbl group by col order by null",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteAddOrderByNull()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteRemoveDMLOrderBy(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "DELETE FROM tbl WHERE col1=1 ORDER BY col",
+			"output": "delete from tbl where col1 = 1",
+		},
+		{
+			"input":  "UPDATE tbl SET col =1 WHERE col1=1 ORDER BY col",
+			"output": "update tbl set col = 1 where col1 = 1",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteRemoveDMLOrderBy()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteGroupByConst(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "select 1;",
+			"output": "select 1 from dual",
+		},
+		/*
+				{
+					"input":  "SELECT col1 FROM tbl GROUP BY 1;",
+					"output": "select col1 from tbl GROUP BY col1",
+				},
+			    {
+					"input":  "SELECT col1, col2 FROM tbl GROUP BY 1, 2;",
+					"output": "select col1, col2 from tbl GROUP BY col1, col2",
+				},
+			    {
+					"input":  "SELECT col1, col2, col3 FROM tbl GROUP BY 1, 3;",
+					"output": "select col1, col2, col3 from tbl GROUP BY col1, col3",
+				},
+		*/
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteGroupByConst()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteStandard(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "SELECT sum(col1) FROM tbl GROUP BY 1;",
+			"output": "select sum(col1) from tbl group by 1",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteStandard()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteCountStar(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "SELECT count(col) FROM tbl GROUP BY 1;",
+			"output": "select count(*) from tbl group by 1",
+		},
+		{
+			"input":  "SELECT COUNT(tb.col) FROM tbl GROUP BY 1;",
+			"output": "select COUNT(tb.*) from tbl group by 1",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteCountStar()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteInnoDB(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "CREATE TABLE t1(id bigint(20) NOT NULL AUTO_INCREMENT);",
+			"output": "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB ",
+		},
+		{
+			"input":  "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=memory ",
+			"output": "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB ",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteInnoDB()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteAutoIncrement(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "CREATE TABLE t1(id bigint(20) NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=123802;",
+			"output": "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB auto_increment=1 ",
+		},
+		{
+			"input":  "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB",
+			"output": "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteAutoIncrement()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteIntWidth(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "CREATE TABLE t1(id bigint(10) NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=123802;",
+			"output": "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB auto_increment=123802",
+		},
+		{
+			"input":  "CREATE TABLE t1(id bigint NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=123802;",
+			"output": "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB auto_increment=123802",
+		},
+		{
+			"input":  "create table t1(id int(20) not null auto_increment) ENGINE=InnoDB;",
+			"output": "create table t1 (\n\tid int(10) not null auto_increment\n) ENGINE=InnoDB",
+		},
+		{
+			"input":  "create table t1(id int not null auto_increment) ENGINE=InnoDB;",
+			"output": "create table t1 (\n\tid int not null auto_increment\n) ENGINE=InnoDB",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteIntWidth()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteAlwaysTrue(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "SELECT count(col) FROM tbl where 1=1;",
+			"output": "select count(col) from tbl",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where col=col;",
+			"output": "select count(col) from tbl where col = col",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where col=col2;",
+			"output": "select count(col) from tbl where col = col2",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1>=1;",
+			"output": "select count(col) from tbl",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1<=1;",
+			"output": "select count(col) from tbl",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1=1 and 2=2;",
+			"output": "select count(col) from tbl",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1=1 or 2=3;",
+			"output": "select count(col) from tbl where 2 = 3",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1=1 and 3=3 or 2=3;",
+			"output": "select count(col) from tbl where 2 = 3",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1=1 and 3=3 or 2!=3;",
+			"output": "select count(col) from tbl",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 1=1 or 2=3 and 3=3 ;",
+			"output": "select count(col) from tbl where 2 = 3",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where (1=1);",
+			"output": "select count(col) from tbl",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where ('a'= 'a' or 'b' = 'b') and a = 'b';",
+			"output": "select count(col) from tbl where a = 'b'",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where (('a'= 'a' or 'b' = 'b') and a = 'b');",
+			"output": "select count(col) from tbl where (a = 'b')",
+		},
+		{
+			"input":  "SELECT count(col) FROM tbl where 'a'= 'a' or ('b' = 'b' and a = 'b');",
+			"output": "select count(col) from tbl where (a = 'b')",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteAlwaysTrue()
+		if rw == nil {
+			t.Errorf("NoRw")
+		} else if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+// TODO:
+func TestRewriteSubQuery2Join(t *testing.T) {
+	common.Config.TestDSN.Disable = true
+	testSQL := []map[string]string{
+		{
+			// 这个case是官方文档给的,但不一定正确,需要视表结构的定义来进行判断
+			"input":  `SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);`,
+			"output": "",
+			//"output": `SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;`,
+		},
+		{
+			"input":  `SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);`,
+			"output": "",
+			//"output": `SELECT table1.* FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;`,
+		},
+		{
+			"input":  `SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);`,
+			"output": "",
+			//"output": `SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;`,
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteSubQuery2Join()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteDML2Select(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  "DELETE city, country FROM city INNER JOIN country using (country_id) WHERE city.city_id = 1;",
+			"output": "select * from city join country using (country_id) where city.city_id = 1",
+		}, {
+			"input":  "DELETE city FROM city LEFT JOIN country ON city.country_id = country.country_id WHERE country.country IS NULL;",
+			"output": "select * from city left join country on city.country_id = country.country_id where country.country is null",
+		}, {
+			"input":  "DELETE a1, a2 FROM city AS a1 INNER JOIN country AS a2 WHERE a1.country_id=a2.country_id",
+			"output": "select * from city as a1 join country as a2 where a1.country_id = a2.country_id",
+		}, {
+			"input":  "DELETE FROM a1, a2 USING city AS a1 INNER JOIN country AS a2 WHERE a1.country_id=a2.country_id",
+			"output": "select * from city as a1 join country as a2 where a1.country_id = a2.country_id",
+		}, {
+			"input":  "DELETE FROM film WHERE length > 100;",
+			"output": "select * from film where length > 100",
+		}, {
+			"input":  "UPDATE city INNER JOIN country USING(country_id) SET city.city = 'Abha', city.last_update = '2006-02-15 04:45:25', country.country = 'Afghanistan' WHERE city.city_id=10;",
+			"output": "select * from city join country using (country_id) where city.city_id = 10",
+		}, {
+			"input":  "UPDATE city INNER JOIN country ON city.country_id = country.country_id INNER JOIN address ON city.city_id = address.city_id SET city.city = 'Abha', city.last_update = '2006-02-15 04:45:25', country.country = 'Afghanistan' WHERE city.city_id=10;",
+			"output": "select * from city join country on city.country_id = country.country_id join address on city.city_id = address.city_id where city.city_id = 10",
+		}, {
+			"input":  "UPDATE city, country SET city.city = 'Abha', city.last_update = '2006-02-15 04:45:25', country.country = 'Afghanistan' WHERE city.country_id = country.country_id AND city.city_id=10;",
+			"output": "select * from city, country where city.country_id = country.country_id and city.city_id = 10",
+		}, {
+			"input":  "UPDATE film SET length = 10 WHERE language_id = 20;",
+			"output": "select * from film where language_id = 20",
+		}, {
+			"input":  "INSERT INTO city (country_id) SELECT country_id FROM country;",
+			"output": "select country_id from country",
+		}, {
+			"input":  "INSERT INTO city (country_id) VALUES (1),(2),(3);",
+			"output": "select 1 from DUAL",
+		}, {
+			"input":  "INSERT INTO city (country_id) VALUES (10);",
+			"output": "select 1 from DUAL",
+		}, {
+			"input":  "INSERT INTO city (country_id) SELECT 10 FROM DUAL;",
+			"output": "select 10 from dual",
+		}, {
+			"input":  "replace INTO city (country_id) SELECT 10 FROM DUAL;",
+			"output": "select 10 from dual",
+		},
+	}
+
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteDML2Select()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteDistinctStar(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `SELECT DISTINCT * FROM film;`,
+			"output": "SELECT * FROM film;",
+		},
+		{
+			"input":  `SELECT COUNT(DISTINCT *) FROM film;`,
+			"output": "SELECT COUNT(*) FROM film;",
+		},
+		{
+			"input":  `SELECT DISTINCT film.* FROM film;`,
+			"output": "SELECT * FROM film;",
+		},
+		{
+			"input":  "SELECT DISTINCT col FROM film;",
+			"output": "SELECT DISTINCT col FROM film;",
+		},
+		{
+			"input":  "SELECT DISTINCT film.* FROM film, tbl;",
+			"output": "SELECT DISTINCT film.* FROM film, tbl;",
+		},
+		{
+
+			"input":  "SELECT DISTINCT * FROM film, tbl;",
+			"output": "SELECT DISTINCT * FROM film, tbl;",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteDistinctStar()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestMergeAlterTables(t *testing.T) {
+	sqls := []string{
+		// ADD|DROP INDEX
+		// TODO: PRIMARY KEY, [UNIQUE|FULLTEXT|SPATIAL] INDEX
+		"CREATE INDEX part_of_name ON customer (name(10));",
+		"alter table `sakila`.`t1` add index `idx_col`(`col`)",
+		"alter table `sakila`.`t1` add UNIQUE index `idx_col`(`col`)",
+		"alter table `sakila`.`t1` add index `idx_ID`(`ID`)",
+
+		// ADD|DROP COLUMN
+		"ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;",
+		"ALTER TABLE T2 ADD COLUMN C int;",
+		"ALTER TABLE T2 ADD COLUMN D int FIRST;",
+		"ALTER TABLE T2 ADD COLUMN E int AFTER D;",
+
+		// RENAME COLUMN
+		"ALTER TABLE t1 RENAME COLUMN a TO b",
+
+		// RENAME INDEX
+		"ALTER TABLE t1 RENAME INDEX idx_a TO idx_b",
+		"ALTER TABLE t1 RENAME KEY idx_a TO idx_b",
+
+		// RENAME TABLE
+		"ALTER TABLE db.old_table RENAME new_table;",
+		"ALTER TABLE old_table RENAME TO new_table;",
+		"ALTER TABLE old_table RENAME AS new_table;",
+
+		// MODIFY & CHANGE
+		"ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT 'my column';",
+		"ALTER TABLE t1 CHANGE b a INT NOT NULL;",
+
+		// table name quote in back ticks
+		"alter table `t3`add index `idx_a`(a)",
+		"alter table`t3`drop index`idx_b`(b)",
+	}
+
+	alterSQLs := MergeAlterTables(sqls...)
+	var sortedAlterSQLs []string
+	for item := range alterSQLs {
+		sortedAlterSQLs = append(sortedAlterSQLs, item)
+	}
+	sort.Strings(sortedAlterSQLs)
+
+	err := common.GoldenDiff(func() {
+		for _, tb := range sortedAlterSQLs {
+			fmt.Println(tb, ":", alterSQLs[tb])
+		}
+	}, t.Name(), update)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestRewriteUnionAll(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `select country_id from city union select country_id from country;`,
+			"output": "select country_id from city union all select country_id from country",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteUnionAll()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+func TestRewriteTruncate(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `delete from tbl;`,
+			"output": "truncate table tbl",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteTruncate()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRewriteOr2In(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `select country_id from city where country_id = 1 or country_id = 2 or country_id = 3;`,
+			"output": "select country_id from city where country_id in (1, 2, 3)",
+		},
+		// TODO or中的恒真条件
+		{
+			"input":  `select country_id from city where country_id != 1 or country_id != 2 or country_id = 3;`,
+			"output": "select country_id from city where country_id != 1 or country_id != 2 or country_id = 3",
+		},
+		// col = 1 or col is null不可转为IN
+		{
+			"input":  `select country_id from city where col = 1 or col is null;`,
+			"output": "select country_id from city where col = 1 or col is null",
+		},
+		{
+			"input":  `select country_id from city where col1 = 1 or col2 = 1 or col2 = 2;`,
+			"output": "select country_id from city where col1 = 1 or col2 in (1, 2)",
+		},
+		{
+			"input":  `select country_id from city where col1 = 1 or col2 = 1 or col2 = 2 or col1 = 3;`,
+			"output": "select country_id from city where col2 in (1, 2) or col1 in (1, 3)",
+		},
+		{
+			"input":  `select country_id from city where (col1 = 1 or col2 = 1 or col2 = 2 ) or col1 = 3;`,
+			"output": "select country_id from city where (col1 = 1 or col2 in (1, 2)) or col1 = 3",
+		},
+		{
+			"input":  `select country_id from city where col1 = 1 or (col2 = 1 or col2 = 2 ) or col1 = 3;`,
+			"output": "select country_id from city where (col2 in (1, 2)) or col1 in (1, 3)",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteOr2In()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestRmParenthesis(t *testing.T) {
+	testSQL := []map[string]string{
+		{
+			"input":  `select country_id from city where (country_id = 1);`,
+			"output": "select country_id from city where country_id = 1",
+		},
+		{
+			"input":  `select * from city where a = 1 and (country_id = 1);`,
+			"output": "select * from city where a = 1 and country_id = 1",
+		},
+		{
+			"input":  `select country_id from city where (country_id = 1) or country_id = 1 ;`,
+			"output": "select country_id from city where country_id = 1 or country_id = 1",
+		},
+		{
+			"input":  `select country_id from city where col = 1 or (country_id = 1) or country_id = 1 ;`,
+			"output": "select country_id from city where col = 1 or country_id = 1 or country_id = 1",
+		},
+	}
+	for _, sql := range testSQL {
+		rw := NewRewrite(sql["input"]).RewriteRmParenthesis()
+		if rw.NewSQL != sql["output"] {
+			t.Errorf("want: %s\ngot: %s", sql["output"], rw.NewSQL)
+		}
+	}
+}
+
+func TestListRewriteRules(t *testing.T) {
+	err := common.GoldenDiff(func() {
+		ListRewriteRules(RewriteRules)
+	}, t.Name(), update)
+	if err != nil {
+		t.Error(err)
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/ast/tidb.go b/vendor/github.com/XiaoMi/soar/ast/tidb.go
new file mode 100644
index 0000000000000000000000000000000000000000..4fc27c1b90a3ed967c4dfb15a0efbdc178744d34
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/ast/tidb.go
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 ast
+
+import (
+	"github.com/XiaoMi/soar/common"
+
+	"github.com/kr/pretty"
+	"github.com/pingcap/parser"
+	"github.com/pingcap/parser/ast"
+	_ "github.com/pingcap/tidb/types/parser_driver"
+)
+
+// TiParse TiDB 语法解析
+func TiParse(sql, charset, collation string) ([]ast.StmtNode, error) {
+	p := parser.New()
+	return p.Parse(sql, charset, collation)
+}
+
+// PrintPrettyStmtNode 打印TiParse语法树
+func PrintPrettyStmtNode(sql, charset, collation string) {
+	tree, err := TiParse(sql, charset, collation)
+	if err != nil {
+		common.Log.Warning(err.Error())
+	} else {
+		_, err = pretty.Println(tree)
+		common.LogIfWarn(err, "")
+	}
+}
+
+// TiVisitor TODO:
+type TiVisitor struct {
+	EnterFunc func(node ast.Node) bool
+	LeaveFunc func(node ast.Node) bool
+}
+
+// Enter TODO:
+func (visitor *TiVisitor) Enter(n ast.Node) (node ast.Node, skip bool) {
+	skip = visitor.EnterFunc(n)
+	return
+}
+
+// Leave TODO:
+func (visitor *TiVisitor) Leave(n ast.Node) (node ast.Node, ok bool) {
+	ok = visitor.LeaveFunc(n)
+	return
+}
diff --git a/vendor/github.com/XiaoMi/soar/ast/token.go b/vendor/github.com/XiaoMi/soar/ast/token.go
new file mode 100644
index 0000000000000000000000000000000000000000..ea64ee9a61ac7cd2fd4079e21ed31c4fc4993ce0
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/ast/token.go
@@ -0,0 +1,1028 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 ast
+
+import (
+	"errors"
+	"fmt"
+	"regexp"
+	"strings"
+	"unicode"
+
+	"vitess.io/vitess/go/vt/sqlparser"
+)
+
+// TokenType
+const (
+	TokenTypeWhitespace       = 0
+	TokenTypeWord             = 1
+	TokenTypeQuote            = 2
+	TokenTypeBacktickQuote    = 3
+	TokenTypeReserved         = 4
+	TokenTypeReservedToplevel = 5
+	TokenTypeReservedNewline  = 6
+	TokenTypeBoundary         = 7
+	TokenTypeComment          = 8
+	TokenTypeBlockComment     = 9
+	TokenTypeNumber           = 10
+	TokenTypeError            = 11
+	TokenTypeVariable         = 12
+)
+
+var maxCachekeySize = 15
+var cacheHits int
+var cacheMisses int
+var tokenCache map[string]Token
+
+var tokenBoundaries = []string{",", ";", ":", ")", "(", ".", "=", "<", ">", "+", "-", "*", "/", "!", "^", "%", "|", "&", "#"}
+
+var tokenReserved = []string{
+	"ACCESSIBLE", "ACTION", "AGAINST", "AGGREGATE", "ALGORITHM", "ALL", "ALTER", "ANALYSE", "ANALYZE", "AS", "ASC",
+	"AUTOCOMMIT", "AUTO_INCREMENT", "BACKUP", "BEGIN", "BETWEEN", "BINLOG", "BOTH", "CASCADE", "CASE", "CHANGE", "CHANGED", "CHARACTER SET",
+	"CHARSET", "CHECK", "CHECKSUM", "COLLATE", "COLLATION", "COLUMN", "COLUMNS", "COMMENT", "COMMIT", "COMMITTED", "COMPRESSED", "CONCURRENT",
+	"CONSTRAINT", "CONTAINS", "CONVERT", "CREATE", "CROSS", "CURRENT_TIMESTAMP", "DATABASE", "DATABASES", "DAY", "DAY_HOUR", "DAY_MINUTE",
+	"DAY_SECOND", "DEFAULT", "DEFINER", "DELAYED", "DELETE", "DESC", "DESCRIBE", "DETERMINISTIC", "DISTINCT", "DISTINCTROW", "DIV",
+	"DO", "DUMPFILE", "DUPLICATE", "DYNAMIC", "ELSE", "ENCLOSED", "END", "ENGINE", "ENGINE_TYPE", "ENGINES", "ESCAPE", "ESCAPED", "EVENTS", "EXEC",
+	"EXECUTE", "EXISTS", "EXPLAIN", "EXTENDED", "FAST", "FIELDS", "FILE", "FIRST", "FIXED", "FLUSH", "FOR", "FORCE", "FOREIGN", "FULL", "FULLTEXT",
+	"FUNCTION", "GLOBAL", "GRANT", "GRANTS", "GROUP_CONCAT", "HEAP", "HIGH_PRIORITY", "HOSTS", "HOUR", "HOUR_MINUTE",
+	"HOUR_SECOND", "IDENTIFIED", "IF", "IFNULL", "IGNORE", "IN", "INDEX", "INDEXES", "INFILE", "INSERT", "INSERT_ID", "INSERT_METHOD", "INTERVAL",
+	"INTO", "INVOKER", "IS", "ISOLATION", "KEY", "KEYS", "KILL", "LAST_INSERT_ID", "LEADING", "LEVEL", "LIKE", "LINEAR",
+	"LINES", "LOAD", "LOCAL", "LOCK", "LOCKS", "LOGS", "LOW_PRIORITY", "MARIA", "MASTER", "MASTER_CONNECT_RETRY", "MASTER_HOST", "MASTER_LOG_FILE",
+	"MATCH", "MAX_CONNECTIONS_PER_HOUR", "MAX_QUERIES_PER_HOUR", "MAX_ROWS", "MAX_UPDATES_PER_HOUR", "MAX_USER_CONNECTIONS",
+	"MEDIUM", "MERGE", "MINUTE", "MINUTE_SECOND", "MIN_ROWS", "MODE", "MODIFY",
+	"MONTH", "MRG_MYISAM", "MYISAM", "NAMES", "NATURAL", "NOT", "NOW()", "NULL", "OFFSET", "ON", "OPEN", "OPTIMIZE", "OPTION", "OPTIONALLY",
+	"ON UPDATE", "ON DELETE", "OUTFILE", "PACK_KEYS", "PAGE", "PARTIAL", "PARTITION", "PARTITIONS", "PASSWORD", "PRIMARY", "PRIVILEGES", "PROCEDURE",
+	"PROCESS", "PROCESSLIST", "PURGE", "QUICK", "RANGE", "RAID0", "RAID_CHUNKS", "RAID_CHUNKSIZE", "RAID_TYPE", "READ", "READ_ONLY",
+	"READ_WRITE", "REFERENCES", "REGEXP", "RELOAD", "RENAME", "REPAIR", "REPEATABLE", "REPLACE", "REPLICATION", "RESET", "RESTORE", "RESTRICT",
+	"RETURN", "RETURNS", "REVOKE", "RLIKE", "ROLLBACK", "ROW", "ROWS", "ROW_FORMAT", "SECOND", "SECURITY", "SEPARATOR",
+	"SERIALIZABLE", "SESSION", "SHARE", "SHOW", "SHUTDOWN", "SLAVE", "SONAME", "SOUNDS", "SQL", "SQL_AUTO_IS_NULL", "SQL_BIG_RESULT",
+	"SQL_BIG_SELECTS", "SQL_BIG_TABLES", "SQL_BUFFER_RESULT", "SQL_CALC_FOUND_ROWS", "SQL_LOG_BIN", "SQL_LOG_OFF", "SQL_LOG_UPDATE",
+	"SQL_LOW_PRIORITY_UPDATES", "SQL_MAX_JOIN_SIZE", "SQL_QUOTE_SHOW_CREATE", "SQL_SAFE_UPDATES", "SQL_SELECT_LIMIT", "SQL_SLAVE_SKIP_COUNTER",
+	"SQL_SMALL_RESULT", "SQL_WARNINGS", "SQL_CACHE", "SQL_NO_CACHE", "START", "STARTING", "STATUS", "STOP", "STORAGE",
+	"STRAIGHT_JOIN", "STRING", "STRIPED", "SUPER", "TABLE", "TABLES", "TEMPORARY", "TERMINATED", "THEN", "TO", "TRAILING", "TRANSACTIONAL", "TRUE",
+	"TRUNCATE", "TYPE", "TYPES", "UNCOMMITTED", "UNIQUE", "UNLOCK", "UNSIGNED", "USAGE", "USE", "USING", "VARIABLES",
+	"VIEW", "WHEN", "WITH", "WORK", "WRITE", "YEAR_MONTH",
+}
+
+var tokenReservedTopLevel = []string{
+	"SELECT", "FROM", "WHERE", "SET", "ORDER BY", "GROUP BY", "LIMIT", "DROP",
+	"VALUES", "UPDATE", "HAVING", "ADD", "AFTER", "ALTER TABLE", "DELETE FROM", "UNION ALL", "UNION", "EXCEPT", "INTERSECT",
+}
+
+var tokenFunction = []string{
+	"ABS", "ACOS", "ADDDATE", "ADDTIME", "AES_DECRYPT", "AES_ENCRYPT", "AREA", "ASBINARY", "ASCII", "ASIN", "ASTEXT", "ATAN", "ATAN2",
+	"AVG", "BDMPOLYFROMTEXT", "BDMPOLYFROMWKB", "BDPOLYFROMTEXT", "BDPOLYFROMWKB", "BENCHMARK", "BIN", "BIT_AND", "BIT_COUNT", "BIT_LENGTH",
+	"BIT_OR", "BIT_XOR", "BOUNDARY", "BUFFER", "CAST", "CEIL", "CEILING", "CENTROID", "CHAR", "CHARACTER_LENGTH", "CHARSET", "CHAR_LENGTH",
+	"COALESCE", "COERCIBILITY", "COLLATION", "COMPRESS", "CONCAT", "CONCAT_WS", "CONNECTION_ID", "CONTAINS", "CONV", "CONVERT", "CONVERT_TZ",
+	"CONVEXHULL", "COS", "COT", "COUNT", "CRC32", "CROSSES", "CURDATE", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER",
+	"CURTIME", "DATABASE", "DATE", "DATEDIFF", "DATE_ADD", "DATE_DIFF", "DATE_FORMAT", "DATE_SUB", "DAY", "DAYNAME", "DAYOFMONTH", "DAYOFWEEK",
+	"DAYOFYEAR", "DECODE", "DEFAULT", "DEGREES", "DES_DECRYPT", "DES_ENCRYPT", "DIFFERENCE", "DIMENSION", "DISJOINT", "DISTANCE", "ELT", "ENCODE",
+	"ENCRYPT", "ENDPOINT", "ENVELOPE", "EQUALS", "EXP", "EXPORT_SET", "EXTERIORRING", "EXTRACT", "EXTRACTVALUE", "FIELD", "FIND_IN_SET", "FLOOR",
+	"FORMAT", "FOUND_ROWS", "FROM_DAYS", "FROM_UNIXTIME", "GEOMCOLLFROMTEXT", "GEOMCOLLFROMWKB", "GEOMETRYCOLLECTION", "GEOMETRYCOLLECTIONFROMTEXT",
+	"GEOMETRYCOLLECTIONFROMWKB", "GEOMETRYFROMTEXT", "GEOMETRYFROMWKB", "GEOMETRYN", "GEOMETRYTYPE", "GEOMFROMTEXT", "GEOMFROMWKB", "GET_FORMAT",
+	"GET_LOCK", "GLENGTH", "GREATEST", "GROUP_CONCAT", "GROUP_UNIQUE_USERS", "HEX", "HOUR", "IF", "IFNULL", "INET_ATON", "INET_NTOA", "INSERT", "INSTR",
+	"INTERIORRINGN", "INTERSECTION", "INTERSECTS", "INTERVAL", "ISCLOSED", "ISEMPTY", "ISNULL", "ISRING", "ISSIMPLE", "IS_FREE_LOCK", "IS_USED_LOCK",
+	"LAST_DAY", "LAST_INSERT_ID", "LCASE", "LEAST", "LEFT", "LENGTH", "LINEFROMTEXT", "LINEFROMWKB", "LINESTRING", "LINESTRINGFROMTEXT", "LINESTRINGFROMWKB",
+	"LN", "LOAD_FILE", "LOCALTIME", "LOCALTIMESTAMP", "LOCATE", "LOG", "LOG10", "LOG2", "LOWER", "LPAD", "LTRIM", "MAKEDATE", "MAKETIME", "MAKE_SET",
+	"MASTER_POS_WAIT", "MAX", "MBRCONTAINS", "MBRDISJOINT", "MBREQUAL", "MBRINTERSECTS", "MBROVERLAPS", "MBRTOUCHES", "MBRWITHIN", "MD5", "MICROSECOND",
+	"MID", "MIN", "MINUTE", "MLINEFROMTEXT", "MLINEFROMWKB", "MOD", "MONTH", "MONTHNAME", "MPOINTFROMTEXT", "MPOINTFROMWKB", "MPOLYFROMTEXT", "MPOLYFROMWKB",
+	"MULTILINESTRING", "MULTILINESTRINGFROMTEXT", "MULTILINESTRINGFROMWKB", "MULTIPOINT", "MULTIPOINTFROMTEXT", "MULTIPOINTFROMWKB", "MULTIPOLYGON",
+	"MULTIPOLYGONFROMTEXT", "MULTIPOLYGONFROMWKB", "NAME_CONST", "NULLIF", "NUMGEOMETRIES", "NUMINTERIORRINGS", "NUMPOINTS", "OCT", "OCTET_LENGTH",
+	"OLD_PASSWORD", "ORD", "OVERLAPS", "PASSWORD", "PERIOD_ADD", "PERIOD_DIFF", "PI", "POINT", "POINTFROMTEXT", "POINTFROMWKB", "POINTN", "POINTONSURFACE",
+	"POLYFROMTEXT", "POLYFROMWKB", "POLYGON", "POLYGONFROMTEXT", "POLYGONFROMWKB", "POSITION", "POW", "POWER", "QUARTER", "QUOTE", "RADIANS", "RAND",
+	"RELATED", "RELEASE_LOCK", "REPEAT", "REPLACE", "REVERSE", "RIGHT", "ROUND", "ROW_COUNT", "RPAD", "RTRIM", "SCHEMA", "SECOND", "SEC_TO_TIME",
+	"SESSION_USER", "SHA", "SHA1", "SIGN", "SIN", "SLEEP", "SOUNDEX", "SPACE", "SQRT", "SRID", "STARTPOINT", "STD", "STDDEV", "STDDEV_POP", "STDDEV_SAMP",
+	"STRCMP", "STR_TO_DATE", "SUBDATE", "SUBSTR", "SUBSTRING", "SUBSTRING_INDEX", "SUBTIME", "SUM", "SYMDIFFERENCE", "SYSDATE", "SYSTEM_USER", "TAN",
+	"TIME", "TIMEDIFF", "TIMESTAMP", "TIMESTAMPADD", "TIMESTAMPDIFF", "TIME_FORMAT", "TIME_TO_SEC", "TOUCHES", "TO_DAYS", "TRIM", "TRUNCATE", "UCASE",
+	"UNCOMPRESS", "UNCOMPRESSED_LENGTH", "UNHEX", "UNIQUE_USERS", "UNIX_TIMESTAMP", "UPDATEXML", "UPPER", "USER", "UTC_DATE", "UTC_TIME", "UTC_TIMESTAMP",
+	"UUID", "VARIANCE", "VAR_POP", "VAR_SAMP", "VERSION", "WEEK", "WEEKDAY", "WEEKOFYEAR", "WITHIN", "X", "Y", "YEAR", "YEARWEEK",
+}
+
+var tokenReservedNewLine = []string{
+	"LEFT OUTER JOIN", "RIGHT OUTER JOIN", "LEFT JOIN", "RIGHT JOIN", "OUTER JOIN", "INNER JOIN", "JOIN", "XOR", "OR", "AND",
+}
+
+var regBoundariesString string
+var regReservedToplevelString string
+var regReservedNewlineString string
+var regReservedString string
+var regFunctionString string
+
+func init() {
+	var regs []string
+	for _, reg := range tokenBoundaries {
+		regs = append(regs, regexp.QuoteMeta(reg))
+	}
+	regBoundariesString = "(" + strings.Join(regs, "|") + ")"
+
+	regs = make([]string, 0)
+	for _, reg := range tokenReservedTopLevel {
+		regs = append(regs, regexp.QuoteMeta(reg))
+	}
+	regReservedToplevelString = "(" + strings.Join(regs, "|") + ")"
+
+	regs = make([]string, 0)
+	for _, reg := range tokenReservedNewLine {
+		regs = append(regs, regexp.QuoteMeta(reg))
+	}
+	regReservedNewlineString = "(" + strings.Join(regs, "|") + ")"
+
+	regs = make([]string, 0)
+	for _, reg := range tokenReserved {
+		regs = append(regs, regexp.QuoteMeta(reg))
+	}
+	regReservedString = "(" + strings.Join(regs, "|") + ")"
+
+	regs = make([]string, 0)
+	for _, reg := range tokenFunction {
+		regs = append(regs, regexp.QuoteMeta(reg))
+	}
+	regFunctionString = "(" + strings.Join(regs, "|") + ")"
+}
+
+// TokenString sqlparser tokens
+var TokenString = map[int]string{
+	sqlparser.LEX_ERROR:               "",
+	sqlparser.UNION:                   "union",
+	sqlparser.SELECT:                  "select",
+	sqlparser.STREAM:                  "stream",
+	sqlparser.INSERT:                  "insert",
+	sqlparser.UPDATE:                  "update",
+	sqlparser.DELETE:                  "delete",
+	sqlparser.FROM:                    "from",
+	sqlparser.WHERE:                   "where",
+	sqlparser.GROUP:                   "group",
+	sqlparser.HAVING:                  "having",
+	sqlparser.ORDER:                   "order",
+	sqlparser.BY:                      "by",
+	sqlparser.LIMIT:                   "limit",
+	sqlparser.OFFSET:                  "offset",
+	sqlparser.FOR:                     "for",
+	sqlparser.ALL:                     "all",
+	sqlparser.DISTINCT:                "distinct",
+	sqlparser.AS:                      "as",
+	sqlparser.EXISTS:                  "exists",
+	sqlparser.ASC:                     "asc",
+	sqlparser.DESC:                    "desc",
+	sqlparser.INTO:                    "into",
+	sqlparser.DUPLICATE:               "duplicate",
+	sqlparser.KEY:                     "key",
+	sqlparser.DEFAULT:                 "default",
+	sqlparser.SET:                     "set",
+	sqlparser.LOCK:                    "lock",
+	sqlparser.KEYS:                    "keys",
+	sqlparser.VALUES:                  "values",
+	sqlparser.LAST_INSERT_ID:          "last_insert_id",
+	sqlparser.NEXT:                    "next",
+	sqlparser.VALUE:                   "value",
+	sqlparser.SHARE:                   "share",
+	sqlparser.MODE:                    "mode",
+	sqlparser.SQL_NO_CACHE:            "sql_no_cache",
+	sqlparser.SQL_CACHE:               "sql_cache",
+	sqlparser.JOIN:                    "join",
+	sqlparser.STRAIGHT_JOIN:           "straight_join",
+	sqlparser.LEFT:                    "left",
+	sqlparser.RIGHT:                   "right",
+	sqlparser.INNER:                   "inner",
+	sqlparser.OUTER:                   "outer",
+	sqlparser.CROSS:                   "cross",
+	sqlparser.NATURAL:                 "natural",
+	sqlparser.USE:                     "use",
+	sqlparser.FORCE:                   "force",
+	sqlparser.ON:                      "on",
+	sqlparser.USING:                   "using",
+	sqlparser.ID:                      "id",
+	sqlparser.HEX:                     "hex",
+	sqlparser.STRING:                  "string",
+	sqlparser.INTEGRAL:                "integral",
+	sqlparser.FLOAT:                   "float",
+	sqlparser.HEXNUM:                  "hexnum",
+	sqlparser.VALUE_ARG:               "?",
+	sqlparser.LIST_ARG:                ":",
+	sqlparser.COMMENT:                 "",
+	sqlparser.COMMENT_KEYWORD:         "comment",
+	sqlparser.BIT_LITERAL:             "bit_literal",
+	sqlparser.NULL:                    "null",
+	sqlparser.TRUE:                    "true",
+	sqlparser.FALSE:                   "false",
+	sqlparser.OR:                      "||",
+	sqlparser.AND:                     "&&",
+	sqlparser.NOT:                     "not",
+	sqlparser.BETWEEN:                 "between",
+	sqlparser.CASE:                    "case",
+	sqlparser.WHEN:                    "when",
+	sqlparser.THEN:                    "then",
+	sqlparser.ELSE:                    "else",
+	sqlparser.END:                     "end",
+	sqlparser.LE:                      "<",
+	sqlparser.GE:                      ">=",
+	sqlparser.NE:                      "<>",
+	sqlparser.NULL_SAFE_EQUAL:         "<=>",
+	sqlparser.IS:                      "is",
+	sqlparser.LIKE:                    "like",
+	sqlparser.REGEXP:                  "regexp",
+	sqlparser.IN:                      "in",
+	sqlparser.SHIFT_LEFT:              "<<",
+	sqlparser.SHIFT_RIGHT:             ">>",
+	sqlparser.DIV:                     "div",
+	sqlparser.MOD:                     "mod",
+	sqlparser.UNARY:                   "unary",
+	sqlparser.COLLATE:                 "collate",
+	sqlparser.BINARY:                  "binary",
+	sqlparser.UNDERSCORE_BINARY:       "_binary",
+	sqlparser.INTERVAL:                "interval",
+	sqlparser.JSON_EXTRACT_OP:         "->>",
+	sqlparser.JSON_UNQUOTE_EXTRACT_OP: "->",
+	sqlparser.CREATE:                  "create",
+	sqlparser.ALTER:                   "alter",
+	sqlparser.DROP:                    "drop",
+	sqlparser.RENAME:                  "rename",
+	sqlparser.ANALYZE:                 "analyze",
+	sqlparser.ADD:                     "add",
+	sqlparser.SCHEMA:                  "schema",
+	sqlparser.TABLE:                   "table",
+	sqlparser.INDEX:                   "index",
+	sqlparser.VIEW:                    "view",
+	sqlparser.TO:                      "to",
+	sqlparser.IGNORE:                  "ignore",
+	sqlparser.IF:                      "if",
+	sqlparser.UNIQUE:                  "unique",
+	sqlparser.PRIMARY:                 "primary",
+	sqlparser.COLUMN:                  "column",
+	sqlparser.CONSTRAINT:              "constraint",
+	sqlparser.SPATIAL:                 "spatial",
+	sqlparser.FULLTEXT:                "fulltext",
+	sqlparser.FOREIGN:                 "foreign",
+	sqlparser.SHOW:                    "show",
+	sqlparser.DESCRIBE:                "describe",
+	sqlparser.EXPLAIN:                 "explain",
+	sqlparser.DATE:                    "date",
+	sqlparser.ESCAPE:                  "escape",
+	sqlparser.REPAIR:                  "repair",
+	sqlparser.OPTIMIZE:                "optimize",
+	sqlparser.TRUNCATE:                "truncate",
+	sqlparser.MAXVALUE:                "maxvalue",
+	sqlparser.PARTITION:               "partition",
+	sqlparser.REORGANIZE:              "reorganize",
+	sqlparser.LESS:                    "less",
+	sqlparser.THAN:                    "than",
+	sqlparser.PROCEDURE:               "procedure",
+	sqlparser.TRIGGER:                 "trigger",
+	sqlparser.VINDEX:                  "vindex",
+	sqlparser.VINDEXES:                "vindexes",
+	sqlparser.STATUS:                  "status",
+	sqlparser.VARIABLES:               "variables",
+	sqlparser.BEGIN:                   "begin",
+	sqlparser.START:                   "start",
+	sqlparser.TRANSACTION:             "transaction",
+	sqlparser.COMMIT:                  "commit",
+	sqlparser.ROLLBACK:                "rollback",
+	sqlparser.BIT:                     "bit",
+	sqlparser.TINYINT:                 "tinyint",
+	sqlparser.SMALLINT:                "smallint",
+	sqlparser.MEDIUMINT:               "mediumint",
+	sqlparser.INT:                     "int",
+	sqlparser.INTEGER:                 "integer",
+	sqlparser.BIGINT:                  "bigint",
+	sqlparser.INTNUM:                  "intnum",
+	sqlparser.REAL:                    "real",
+	sqlparser.DOUBLE:                  "double",
+	sqlparser.FLOAT_TYPE:              "float_type",
+	sqlparser.DECIMAL:                 "decimal",
+	sqlparser.NUMERIC:                 "numeric",
+	sqlparser.TIME:                    "time",
+	sqlparser.TIMESTAMP:               "timestamp",
+	sqlparser.DATETIME:                "datetime",
+	sqlparser.YEAR:                    "year",
+	sqlparser.CHAR:                    "char",
+	sqlparser.VARCHAR:                 "varchar",
+	sqlparser.BOOL:                    "bool",
+	sqlparser.CHARACTER:               "character",
+	sqlparser.VARBINARY:               "varbinary",
+	sqlparser.NCHAR:                   "nchar",
+	sqlparser.TEXT:                    "text",
+	sqlparser.TINYTEXT:                "tinytext",
+	sqlparser.MEDIUMTEXT:              "mediumtext",
+	sqlparser.LONGTEXT:                "longtext",
+	sqlparser.BLOB:                    "blob",
+	sqlparser.TINYBLOB:                "tinyblob",
+	sqlparser.MEDIUMBLOB:              "mediumblob",
+	sqlparser.LONGBLOB:                "longblob",
+	sqlparser.JSON:                    "json",
+	sqlparser.ENUM:                    "enum",
+	sqlparser.GEOMETRY:                "geometry",
+	sqlparser.POINT:                   "point",
+	sqlparser.LINESTRING:              "linestring",
+	sqlparser.POLYGON:                 "polygon",
+	sqlparser.GEOMETRYCOLLECTION:      "geometrycollection",
+	sqlparser.MULTIPOINT:              "multipoint",
+	sqlparser.MULTILINESTRING:         "multilinestring",
+	sqlparser.MULTIPOLYGON:            "multipolygon",
+	sqlparser.NULLX:                   "nullx",
+	sqlparser.AUTO_INCREMENT:          "auto_increment",
+	sqlparser.APPROXNUM:               "approxnum",
+	sqlparser.SIGNED:                  "signed",
+	sqlparser.UNSIGNED:                "unsigned",
+	sqlparser.ZEROFILL:                "zerofill",
+	sqlparser.DATABASES:               "databases",
+	sqlparser.TABLES:                  "tables",
+	sqlparser.VITESS_KEYSPACES:        "vitess_keyspaces",
+	sqlparser.VITESS_SHARDS:           "vitess_shards",
+	sqlparser.VITESS_TABLETS:          "vitess_tablets",
+	sqlparser.VSCHEMA_TABLES:          "vschema_tables",
+	sqlparser.NAMES:                   "names",
+	sqlparser.CHARSET:                 "charset",
+	sqlparser.GLOBAL:                  "global",
+	sqlparser.SESSION:                 "session",
+	sqlparser.CURRENT_TIMESTAMP:       "current_timestamp",
+	sqlparser.DATABASE:                "database",
+	sqlparser.CURRENT_DATE:            "current_date",
+	sqlparser.CURRENT_TIME:            "current_time",
+	sqlparser.LOCALTIME:               "localtime",
+	sqlparser.LOCALTIMESTAMP:          "localtimestamp",
+	sqlparser.UTC_DATE:                "utc_date",
+	sqlparser.UTC_TIME:                "utc_time",
+	sqlparser.UTC_TIMESTAMP:           "utc_timestamp",
+	sqlparser.REPLACE:                 "replace",
+	sqlparser.CONVERT:                 "convert",
+	sqlparser.CAST:                    "cast",
+	sqlparser.SUBSTR:                  "substr",
+	sqlparser.SUBSTRING:               "substring",
+	sqlparser.GROUP_CONCAT:            "group_concat",
+	sqlparser.SEPARATOR:               "separator",
+	sqlparser.MATCH:                   "match",
+	sqlparser.AGAINST:                 "against",
+	sqlparser.BOOLEAN:                 "boolean",
+	sqlparser.LANGUAGE:                "language",
+	sqlparser.WITH:                    "with",
+	sqlparser.QUERY:                   "query",
+	sqlparser.EXPANSION:               "expansion",
+	sqlparser.UNUSED:                  "",
+}
+
+// 这个变更从vitess更新过来,如果vitess新开了一个关键字这里也要同步开
+var mySQLKeywords = map[string]string{
+	"add":                "ADD",
+	"against":            "AGAINST",
+	"all":                "ALL",
+	"alter":              "ALTER",
+	"analyze":            "ANALYZE",
+	"and":                "AND",
+	"as":                 "AS",
+	"asc":                "ASC",
+	"auto_increment":     "AUTO_INCREMENT",
+	"begin":              "BEGIN",
+	"between":            "BETWEEN",
+	"bigint":             "BIGINT",
+	"binary":             "BINARY",
+	"_binary":            "UNDERSCORE_BINARY",
+	"bit":                "BIT",
+	"blob":               "BLOB",
+	"bool":               "BOOL",
+	"boolean":            "BOOLEAN",
+	"by":                 "BY",
+	"case":               "CASE",
+	"cast":               "CAST",
+	"char":               "CHAR",
+	"character":          "CHARACTER",
+	"charset":            "CHARSET",
+	"collate":            "COLLATE",
+	"column":             "COLUMN",
+	"comment":            "COMMENT_KEYWORD",
+	"commit":             "COMMIT",
+	"constraint":         "CONSTRAINT",
+	"convert":            "CONVERT",
+	"substr":             "SUBSTR",
+	"substring":          "SUBSTRING",
+	"create":             "CREATE",
+	"cross":              "CROSS",
+	"current_date":       "CURRENT_DATE",
+	"current_time":       "CURRENT_TIME",
+	"current_timestamp":  "CURRENT_TIMESTAMP",
+	"database":           "DATABASE",
+	"databases":          "DATABASES",
+	"date":               "DATE",
+	"datetime":           "DATETIME",
+	"decimal":            "DECIMAL",
+	"default":            "DEFAULT",
+	"delete":             "DELETE",
+	"desc":               "DESC",
+	"describe":           "DESCRIBE",
+	"distinct":           "DISTINCT",
+	"div":                "DIV",
+	"double":             "DOUBLE",
+	"drop":               "DROP",
+	"duplicate":          "DUPLICATE",
+	"else":               "ELSE",
+	"end":                "END",
+	"enum":               "ENUM",
+	"escape":             "ESCAPE",
+	"exists":             "EXISTS",
+	"explain":            "EXPLAIN",
+	"expansion":          "EXPANSION",
+	"false":              "FALSE",
+	"float":              "FLOAT_TYPE",
+	"for":                "FOR",
+	"force":              "FORCE",
+	"foreign":            "FOREIGN",
+	"from":               "FROM",
+	"fulltext":           "FULLTEXT",
+	"geometry":           "GEOMETRY",
+	"geometrycollection": "GEOMETRYCOLLECTION",
+	"global":             "GLOBAL",
+	"group":              "GROUP",
+	"group_concat":       "GROUP_CONCAT",
+	"having":             "HAVING",
+	"if":                 "IF",
+	"ignore":             "IGNORE",
+	"in":                 "IN",
+	"index":              "INDEX",
+	"inner":              "INNER",
+	"insert":             "INSERT",
+	"int":                "INT",
+	"integer":            "INTEGER",
+	"interval":           "INTERVAL",
+	"into":               "INTO",
+	"is":                 "IS",
+	"join":               "JOIN",
+	"json":               "JSON",
+	"key":                "KEY",
+	"keys":               "KEYS",
+	"key_block_size":     "KEY_BLOCK_SIZE",
+	"language":           "LANGUAGE",
+	"last_insert_id":     "LAST_INSERT_ID",
+	"left":               "LEFT",
+	"less":               "LESS",
+	"like":               "LIKE",
+	"limit":              "LIMIT",
+	"linestring":         "LINESTRING",
+	"localtime":          "LOCALTIME",
+	"localtimestamp":     "LOCALTIMESTAMP",
+	"lock":               "LOCK",
+	"longblob":           "LONGBLOB",
+	"longtext":           "LONGTEXT",
+	"match":              "MATCH",
+	"maxvalue":           "MAXVALUE",
+	"mediumblob":         "MEDIUMBLOB",
+	"mediumint":          "MEDIUMINT",
+	"mediumtext":         "MEDIUMTEXT",
+	"mod":                "MOD",
+	"mode":               "MODE",
+	"multilinestring":    "MULTILINESTRING",
+	"multipoint":         "MULTIPOINT",
+	"multipolygon":       "MULTIPOLYGON",
+	"names":              "NAMES",
+	"natural":            "NATURAL",
+	"nchar":              "NCHAR",
+	"next":               "NEXT",
+	"not":                "NOT",
+	"null":               "NULL",
+	"numeric":            "NUMERIC",
+	"offset":             "OFFSET",
+	"on":                 "ON",
+	"optimize":           "OPTIMIZE",
+	"or":                 "OR",
+	"order":              "ORDER",
+	"outer":              "OUTER",
+	"partition":          "PARTITION",
+	"point":              "POINT",
+	"polygon":            "POLYGON",
+	"primary":            "PRIMARY",
+	"procedure":          "PROCEDURE",
+	"query":              "QUERY",
+	"real":               "REAL",
+	"regexp":             "REGEXP",
+	"rename":             "RENAME",
+	"reorganize":         "REORGANIZE",
+	"repair":             "REPAIR",
+	"replace":            "REPLACE",
+	"right":              "RIGHT",
+	"rlike":              "REGEXP",
+	"rollback":           "ROLLBACK",
+	"schema":             "SCHEMA",
+	"select":             "SELECT",
+	"separator":          "SEPARATOR",
+	"session":            "SESSION",
+	"set":                "SET",
+	"share":              "SHARE",
+	"show":               "SHOW",
+	"signed":             "SIGNED",
+	"smallint":           "SMALLINT",
+	"spatial":            "SPATIAL",
+	"sql_cache":          "SQL_CACHE",
+	"sql_no_cache":       "SQL_NO_CACHE",
+	"start":              "START",
+	"status":             "STATUS",
+	"straight_join":      "STRAIGHT_JOIN",
+	"stream":             "STREAM",
+	"table":              "TABLE",
+	"tables":             "TABLES",
+	"text":               "TEXT",
+	"than":               "THAN",
+	"then":               "THEN",
+	"time":               "TIME",
+	"timestamp":          "TIMESTAMP",
+	"tinyblob":           "TINYBLOB",
+	"tinyint":            "TINYINT",
+	"tinytext":           "TINYTEXT",
+	"to":                 "TO",
+	"transaction":        "TRANSACTION",
+	"trigger":            "TRIGGER",
+	"true":               "TRUE",
+	"truncate":           "TRUNCATE",
+	"union":              "UNION",
+	"unique":             "UNIQUE",
+	"unsigned":           "UNSIGNED",
+	"update":             "UPDATE",
+	"use":                "USE",
+	"using":              "USING",
+	"utc_date":           "UTC_DATE",
+	"utc_time":           "UTC_TIME",
+	"utc_timestamp":      "UTC_TIMESTAMP",
+	"values":             "VALUES",
+	"variables":          "VARIABLES",
+	"varbinary":          "VARBINARY",
+	"varchar":            "VARCHAR",
+	"vindex":             "VINDEX",
+	"vindexes":           "VINDEXES",
+	"view":               "VIEW",
+	"vitess_keyspaces":   "VITESS_KEYSPACES",
+	"vitess_shards":      "VITESS_SHARDS",
+	"vitess_tablets":     "VITESS_TABLETS",
+	"vschema_tables":     "VSCHEMA_TABLES",
+	"when":               "WHEN",
+	"where":              "WHERE",
+	"with":               "WITH",
+	"year":               "YEAR",
+	"zerofill":           "ZEROFILL",
+}
+
+// Token 基本定义
+type Token struct {
+	Type int
+	Val  string
+	i    int
+}
+
+// Tokenizer 用于初始化token
+func Tokenizer(sql string) []Token {
+	var tokens []Token
+	tkn := sqlparser.NewStringTokenizer(sql)
+	typ, val := tkn.Scan()
+	for typ != 0 {
+		if val != nil {
+			tokens = append(tokens, Token{Type: typ, Val: string(val)})
+		} else {
+			if typ > 255 {
+				if v, ok := TokenString[typ]; ok {
+					tokens = append(tokens, Token{
+						Type: typ,
+						Val:  v,
+					})
+				} else {
+					tokens = append(tokens, Token{
+						Type: typ,
+						Val:  "",
+					})
+				}
+			} else {
+				tokens = append(tokens, Token{
+					Type: typ,
+					Val:  fmt.Sprintf("%c", typ),
+				})
+			}
+		}
+		typ, val = tkn.Scan()
+	}
+	return tokens
+}
+
+// MysqlEscapeString mysql_real_escape_string
+// https://github.com/liule/golang_escape
+func MysqlEscapeString(source string) (string, error) {
+	var j = 0
+	if len(source) == 0 {
+		return "", errors.New("source is null")
+	}
+	tempStr := source[:]
+	desc := make([]byte, len(tempStr)*2)
+	for i := 0; i < len(tempStr); i++ {
+		flag := false
+		var escape byte
+		switch tempStr[i] {
+		case '\r':
+			flag = true
+			escape = '\r'
+		case '\n':
+			flag = true
+			escape = '\n'
+		case '\\':
+			flag = true
+			escape = '\\'
+		case '\'':
+			flag = true
+			escape = '\''
+		case '"':
+			flag = true
+			escape = '"'
+		case '\032':
+			flag = true
+			escape = 'Z'
+		default:
+		}
+		if flag {
+			desc[j] = '\\'
+			desc[j+1] = escape
+			j = j + 2
+		} else {
+			desc[j] = tempStr[i]
+			j = j + 1
+		}
+	}
+	return string(desc[0:j]), nil
+}
+
+// IsMysqlKeyword 判断是否是关键字
+func IsMysqlKeyword(name string) bool {
+	_, ok := mySQLKeywords[strings.ToLower(strings.TrimSpace(name))]
+	return ok
+}
+
+// getNextToken 从 buf 中获取 token
+func getNextToken(buf string, previous Token) Token {
+	var typ int // TOKEN_TYPE
+
+	// Whitespace
+	whiteSpaceReg := regexp.MustCompile(`^\s+`)
+	if whiteSpaceReg.MatchString(buf) {
+		return Token{
+			Type: TokenTypeWhitespace,
+			Val:  " ",
+		}
+	}
+
+	// Comment (#, --, /**/)
+	if buf[0] == '#' || (len(buf) > 1 && (buf[:2] == "--" || buf[:2] == "/*")) {
+		var last int
+		if buf[0] == '-' || buf[0] == '#' {
+			// Comment until end of line
+			last = strings.Index(buf, "\n")
+			typ = TokenTypeComment
+		} else {
+			// Comment until closing comment tag
+			last = strings.Index(buf[2:], "*/") + 2
+			typ = TokenTypeBlockComment
+		}
+		if last == 0 {
+			last = len(buf)
+		}
+		return Token{
+			Type: typ,
+			Val:  buf[:last],
+		}
+	}
+
+	// Quoted String
+	if buf[0] == '"' || buf[0] == '\'' || buf[0] == '`' || buf[0] == '[' {
+		var typ int
+		switch buf[0] {
+		case '`', '[':
+			typ = TokenTypeBacktickQuote
+		default:
+			typ = TokenTypeQuote
+		}
+		return Token{
+			Type: typ,
+			Val:  getQuotedString(buf),
+		}
+	}
+
+	// User-defined Variable
+	if (buf[0] == '@' || buf[0] == ':') && len(buf) > 1 {
+		ret := Token{
+			Type: TokenTypeVariable,
+			Val:  "",
+		}
+
+		if buf[1] == '"' || buf[1] == '\'' || buf[1] == '`' {
+			// If the variable name is quoted
+			ret.Val = string(buf[0]) + getQuotedString(buf[1:])
+		} else {
+			// Non-quoted variable name
+			varReg := regexp.MustCompile(`^(` + string(buf[0]) + `[a-zA-Z0-9\._\$]+)`)
+			if varReg.MatchString(buf) {
+				ret.Val = varReg.FindString(buf)
+			}
+		}
+
+		if ret.Val != "" {
+			return ret
+		}
+	}
+
+	// Number(decimal, binary, hex...)
+	numReg := regexp.MustCompile(`^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"'` + "`|" + regBoundariesString + ")")
+	if numReg.MatchString(buf) {
+		return Token{
+			Type: TokenTypeNumber,
+			Val:  numReg.FindString(buf),
+		}
+	}
+
+	// Boundary Character(punctuation and symbols)
+	boundaryReg := regexp.MustCompile(`^(` + regBoundariesString + `)`)
+	if boundaryReg.MatchString(buf) {
+		return Token{
+			Type: TokenTypeBoundary,
+			Val:  boundaryReg.FindString(buf),
+		}
+	}
+	sqlUpper := strings.ToUpper(buf)
+	// A reserved word cannot be preceded by a '.'
+	// this makes it so in "mytable.from", "from" is not considered a reserved word
+	if previous.Val != "." {
+		// Top Level Reserved Word
+		reservedToplevelReg := regexp.MustCompile(`^(` + regReservedToplevelString + `)($|\s|` + regBoundariesString + `)`)
+		if reservedToplevelReg.MatchString(sqlUpper) {
+			return Token{
+				Type: TokenTypeReservedToplevel,
+				Val:  reservedToplevelReg.FindString(sqlUpper),
+			}
+		}
+
+		// Newline Reserved Word
+		reservedNewlineReg := regexp.MustCompile(`^(` + regReservedNewlineString + `)($|\s|` + regBoundariesString + `)`)
+		if reservedNewlineReg.MatchString(sqlUpper) {
+			return Token{
+				Type: TokenTypeReservedNewline,
+				Val:  reservedNewlineReg.FindString(sqlUpper),
+			}
+		}
+
+		// Other Reserved Word
+		reservedReg := regexp.MustCompile(`^(` + regReservedString + `)($|\s|` + regBoundariesString + `)`)
+		if reservedNewlineReg.MatchString(sqlUpper) {
+			return Token{
+				Type: TokenTypeReserved,
+				Val:  reservedReg.FindString(sqlUpper),
+			}
+		}
+
+	}
+
+	// function
+	// A function must be succeeded by '('
+	// this makes it so "count(" is considered a function, but "count" alone is not
+	functionReg := regexp.MustCompile(`^(` + regFunctionString + `)($|\s|` + regBoundariesString + `)`)
+	if functionReg.MatchString(sqlUpper) {
+		return Token{
+			Type: TokenTypeReserved,
+			Val:  functionReg.FindString(sqlUpper),
+		}
+	}
+
+	// Non reserved word
+	noReservedReg := regexp.MustCompile(`(.*?)($|\s|["'` + "`]|" + regBoundariesString + `)`)
+	if noReservedReg.MatchString(buf) {
+		return Token{
+			Type: TokenTypeWord,
+			Val:  noReservedReg.FindString(buf),
+		}
+	}
+	return Token{}
+}
+
+// getQuotedString 获取quote
+func getQuotedString(buf string) string {
+	// This checks for the following patterns:
+	// 1. backtick quoted string using `` to escape
+	// 2. double quoted string using "" or \" to escape
+	// 3. single quoted string using '' or \' to escape
+	start := string(buf[0])
+	switch start {
+	case "\"", "`", "'":
+		reg := fmt.Sprintf(`(^%s[^%s\\]*(?:\\.[^%s\\]*)*(%s|$))+`, start, start, start, start)
+		quotedReg := regexp.MustCompile(reg)
+		if quotedReg.MatchString(buf) {
+			buf = quotedReg.FindString(buf)
+		} else {
+			buf = ""
+		}
+	default:
+		buf = ""
+	}
+	return buf
+}
+
+// Tokenize 序列化token
+func Tokenize(sql string) []Token {
+	var token Token
+	var tokenLength int
+	var tokens []Token
+	tokenCache = make(map[string]Token)
+
+	// Used to make sure the string keeps shrinking on each iteration
+	oldStringLen := len(sql) + 1
+
+	currentLength := len(sql)
+	for currentLength > 0 {
+		// If the string stopped shrinking, there was a problem
+		if oldStringLen <= currentLength {
+			tokens = []Token{
+				{
+					Type: TokenTypeError,
+					Val:  sql,
+				},
+			}
+			return tokens
+		}
+
+		oldStringLen = currentLength
+		cacheKey := ""
+		// Determine if we can use caching
+		if currentLength >= maxCachekeySize {
+			cacheKey = sql[:maxCachekeySize]
+		}
+
+		// See if the token is already cached
+		if _, ok := tokenCache[cacheKey]; ok {
+			// Retrieve from cache
+			token = tokenCache[cacheKey]
+			tokenLength = len(token.Val)
+			cacheHits = cacheHits + 1
+		} else {
+			// Get the next token and the token type
+			token = getNextToken(sql, token)
+			tokenLength = len(token.Val)
+			cacheMisses = cacheMisses + 1
+			// If the token is shorter than the max length, store it in cache
+			if cacheKey != "" && tokenLength < maxCachekeySize {
+				tokenCache[cacheKey] = token
+			}
+		}
+
+		tokens = append(tokens, token)
+
+		// Advance the string
+		sql = sql[tokenLength:]
+		currentLength = currentLength - tokenLength
+	}
+	return tokens
+}
+
+// Compress compress sql
+// this method is inspired by eversql.com
+func Compress(sql string) string {
+	regLineTab := regexp.MustCompile(`(?i)([\n\t])`)
+	regSpace := regexp.MustCompile(`\s\s+`)
+	sql = regSpace.ReplaceAllString(regLineTab.ReplaceAllString(sql, " "), " ")
+	return sql
+}
+
+// SplitStatement SQL切分
+// return original sql, remove comment sql, left over buf
+func SplitStatement(buf []byte, delimiter []byte) (string, string, []byte) {
+	var singleLineComment bool
+	var multiLineComment bool
+	var quoted bool
+	var quoteRune byte
+	var sql string
+
+	for i := 0; i < len(buf); i++ {
+		b := buf[i]
+		// single line comment
+		if b == '-' {
+			if i+2 < len(buf) && buf[i+1] == '-' && buf[i+2] == ' ' {
+				singleLineComment = true
+				i = i + 2
+				continue
+			}
+			if i+2 < len(buf) && i == 0 && buf[i+1] == '-' && (buf[i+2] == '\n' || buf[i+2] == '\r') {
+				sql = "--\n"
+				break
+			}
+		}
+
+		if b == '#' {
+			if !multiLineComment && !quoted && !singleLineComment {
+				singleLineComment = true
+				continue
+			}
+		}
+
+		// new line end single line comment
+		if b == '\r' || b == '\n' {
+			if singleLineComment {
+				sql = string(buf[:i])
+				singleLineComment = false
+				if strings.HasPrefix(strings.TrimSpace(sql), "--") ||
+					strings.HasPrefix(strings.TrimSpace(sql), "#") {
+					// just comment, query start with '--', '#'
+					break
+				}
+				// comment in multi-line sql
+				continue
+			}
+			continue
+		}
+
+		// multi line comment
+		if b == '/' && i+1 < len(buf) && buf[i+1] == '*' {
+			if !multiLineComment && !singleLineComment && !quoted && buf[i+2] != '!' {
+				i = i + 2
+				multiLineComment = true
+				continue
+			}
+		}
+
+		if b == '*' && i+1 < len(buf) && buf[i+1] == '/' {
+			if multiLineComment && !quoted && !singleLineComment {
+				i = i + 2
+				multiLineComment = false
+				// '/*comment*/'
+				if i == len(buf) {
+					sql = string(buf[:i])
+				}
+				// '/*comment*/;', 'select 1/*comment*/;'
+				if string(buf[i:]) == string(delimiter) {
+					sql = string(buf)
+				}
+				continue
+			}
+		}
+
+		// quoted string
+		if b == '`' || b == '\'' || b == '"' {
+			if i > 1 && buf[i-1] != '\\' {
+				if quoted && b == quoteRune {
+					quoted = false
+				} else {
+					quoted = true
+					quoteRune = b
+				}
+			}
+		}
+
+		// delimiter
+		if !quoted && !singleLineComment && !multiLineComment {
+			eof := true
+			for k, c := range delimiter {
+				if len(buf) > i+k && buf[i+k] != c {
+					eof = false
+				}
+			}
+			if eof {
+				i = i + len(delimiter)
+				sql = string(buf[:i])
+				break
+			}
+		}
+
+		// ended of buf
+		if i == len(buf)-1 {
+			sql = string(buf)
+		}
+	}
+	orgSQL := string(buf[:len(sql)])
+	buf = buf[len(sql):]
+	return orgSQL, strings.TrimSuffix(sql, string(delimiter)), buf
+}
+
+// LeftNewLines cal left new lines in space
+func LeftNewLines(buf []byte) int {
+	newLines := 0
+	for _, b := range buf {
+		if !unicode.IsSpace(rune(b)) {
+			break
+		}
+		if b == byte('\n') {
+			newLines++
+		}
+	}
+	return newLines
+}
+
+// NewLines cal all new lines
+func NewLines(buf []byte) int {
+	newLines := 0
+	for _, b := range buf {
+		if b == byte('\n') {
+			newLines++
+		}
+	}
+	return newLines
+}
diff --git a/vendor/github.com/XiaoMi/soar/ast/token_test.go b/vendor/github.com/XiaoMi/soar/ast/token_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..97d62542362106de893f45674a2dc788d332e164
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/ast/token_test.go
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 ast
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/XiaoMi/soar/common"
+
+	"github.com/kr/pretty"
+)
+
+func TestTokenize(t *testing.T) {
+	err := common.GoldenDiff(func() {
+		for _, sql := range common.TestSQLs {
+			fmt.Println(sql)
+			fmt.Println(Tokenize(sql))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestTokenizer(t *testing.T) {
+	sqls := []string{
+		"select c1,c2,c3 from t1,t2 join t3 on t1.c1=t2.c1 and t1.c3=t3.c1 where id>1000",
+		"select sourcetable, if(f.lastcontent = ?, f.lastupdate, f.lastcontent) as lastactivity, f.totalcount as activity, type.class as type, (f.nodeoptions & ?) as nounsubscribe from node as f inner join contenttype as type on type.contenttypeid = f.contenttypeid inner join subscribed as sd on sd.did = f.nodeid and sd.userid = ? union all select f.name as title, f.userid as keyval, ? as sourcetable, ifnull(f.lastpost, f.joindate) as lastactivity, f.posts as activity, ? as type, ? as nounsubscribe from user as f inner join userlist as ul on ul.relationid = f.userid and ul.userid = ? where ul.type = ? and ul.aq = ? order by title limit ?",
+		"select c1 from t1 where id>=1000", // test ">="
+		"select SQL_CALC_FOUND_ROWS col from tbl where id>1000",
+		"SELECT * FROM tb WHERE id=?;",
+		"SELECT * FROM tb WHERE id is null;",
+		"SELECT * FROM tb WHERE id is not null;",
+		"SELECT * FROM tb WHERE id between 1 and 3;",
+		"alter table inventory add index idx_store_film` (`store_id`,`film_id`);",
+	}
+	err := common.GoldenDiff(func() {
+		for _, sql := range sqls {
+			pretty.Println(Tokenizer(sql))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestGetQuotedString(t *testing.T) {
+	var str = []string{
+		`"hello world"`,
+		"`hello world`",
+		`'hello world'`,
+		"hello world",
+		`'hello \'world'`,
+		`"hello \"wor\"ld"`,
+		`"hello \"world"`,
+		`""`,
+		`''`,
+		"``",
+		`'hello 'world'`,
+		`"hello "world"`,
+	}
+	err := common.GoldenDiff(func() {
+		for _, s := range str {
+			fmt.Printf("orignal: %s\nquoted: %s\n", s, getQuotedString(s))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestCompress(t *testing.T) {
+	err := common.GoldenDiff(func() {
+		for _, sql := range common.TestSQLs {
+			fmt.Println(sql)
+			fmt.Println(Compress(sql))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+
+}
+
+func TestFormat(t *testing.T) {
+	err := common.GoldenDiff(func() {
+		for _, sql := range common.TestSQLs {
+			fmt.Println(sql)
+			fmt.Println(format(sql))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestSplitStatement(t *testing.T) {
+	bufs := [][]byte{
+		[]byte("select * from test;hello"),
+		[]byte("select 'asd;fas', col from test;hello"),
+		[]byte("-- select * from test;hello"),
+		[]byte("#select * from test;hello"),
+		[]byte("select * /*comment*/from test;hello"),
+		[]byte("select * /*comment;*/from test;hello"),
+		[]byte(`select * /*comment
+		;*/
+		from test;hello`),
+		[]byte(`select * from test`),
+		// https://github.com/XiaoMi/soar/issues/66
+		[]byte(`/*comment*/`),
+		[]byte(`/*comment*/;`),
+		[]byte(`--`),
+		[]byte(`-- comment`),
+		[]byte(`# comment`),
+		// https://github.com/XiaoMi/soar/issues/116
+		[]byte(`select
+*
+-- comment
+from tb
+where col = 1`),
+		[]byte(`select
+* --
+from tb
+where col = 1`),
+		[]byte(`select
+* #
+from tb
+where col = 1`),
+		[]byte(`select
+*
+--
+from tb
+where col = 1`),
+		[]byte(`select * from
+-- comment
+tb;
+select col from tb where col = 1;`),
+		// https://github.com/XiaoMi/soar/issues/120
+		[]byte(`
+-- comment
+select col from tb;
+select col from tb;
+`),
+	}
+	buf2s := [][]byte{
+		[]byte("select * from test\\Ghello"),
+		[]byte("select 'hello\\Gworld', col from test\\Ghello"),
+		[]byte("-- select * from test\\Ghello"),
+		[]byte("#select * from test\\Ghello"),
+		[]byte("select * /*comment*/from test\\Ghello"),
+		[]byte("select * /*comment;*/from test\\Ghello"),
+		[]byte(`select * /*comment
+        \\G*/
+        from test\\Ghello`),
+	}
+	err := common.GoldenDiff(func() {
+		for i, buf := range bufs {
+			sql, _, _ := SplitStatement(buf, []byte(common.Config.Delimiter))
+			fmt.Println(i, sql)
+		}
+		for i, buf := range buf2s {
+			sql, _, _ := SplitStatement(buf, []byte(common.Config.Delimiter))
+			fmt.Println(i, sql)
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestLeftNewLines(t *testing.T) {
+	bufs := [][]byte{
+		[]byte(`
+		select * from test;hello`),
+		[]byte(`select * /*comment
+        ;*/
+        from test;hello`),
+		[]byte(`select * from test`),
+	}
+	err := common.GoldenDiff(func() {
+		for _, buf := range bufs {
+			fmt.Println(LeftNewLines(buf))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestNewLines(t *testing.T) {
+	bufs := [][]byte{
+		[]byte(`
+		select * from test;hello`),
+		[]byte(`select * /*comment
+        ;*/
+        from test;hello`),
+		[]byte(`select * from test`),
+	}
+	err := common.GoldenDiff(func() {
+		for _, buf := range bufs {
+			fmt.Println(NewLines(buf))
+		}
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/cmd/soar/doc.go b/vendor/github.com/XiaoMi/soar/cmd/soar/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..7f50ee8d345ac7b02b20521c0d3beb7f1ffe76f4
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/cmd/soar/doc.go
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 soar is the main program of SOAR
+package main
diff --git a/vendor/github.com/XiaoMi/soar/cmd/soar/soar.go b/vendor/github.com/XiaoMi/soar/cmd/soar/soar.go
new file mode 100644
index 0000000000000000000000000000000000000000..cb7172c5267cb3295b95f7373da182c125de2507
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/cmd/soar/soar.go
@@ -0,0 +1,429 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 main
+
+import (
+	"encoding/json"
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/XiaoMi/soar/advisor"
+	"github.com/XiaoMi/soar/ast"
+	"github.com/XiaoMi/soar/common"
+	"github.com/XiaoMi/soar/database"
+	"github.com/XiaoMi/soar/env"
+
+	"github.com/kr/pretty"
+	"github.com/percona/go-mysql/query"
+	"github.com/ziutek/mymysql/mysql"
+	"vitess.io/vitess/go/vt/sqlparser"
+)
+
+func main() {
+	// 全局变量
+	var err error
+	var sql string                                            // 单条评审指定的 sql 或 explain
+	sqlCounter := 1                                           // SQL 计数器
+	lineCounter := 1                                          // 行计数器
+	var alterSQLs []string                                    // 待评审的 SQL 中所有 ALTER 请求
+	alterTableTimes := make(map[string]int)                   // 待评审的 SQL 中同一经表 ALTER 请求计数器
+	suggestMerged := make(map[string]map[string]advisor.Rule) // 优化建议去重, key 为 sql 的 fingerprint.ID
+
+	// 配置文件&命令行参数解析
+	initConfig()
+
+	// 命令行帮助工具,如 -list-report-types, -check-config等。
+	if isContinue, exitCode := helpTools(); !isContinue {
+		os.Exit(exitCode)
+	}
+
+	// 环境初始化,连接检查线上环境+构建测试环境
+	vEnv, rEnv := env.BuildEnv()
+
+	// 使用 -cleanup-test-database 命令手动清理残余的 optimizer_xxx 数据库
+	if common.Config.CleanupTestDatabase {
+		vEnv.CleanupTestDatabase()
+		return
+	}
+
+	// 如果使用到测试环境,在这里环境清理
+	if common.Config.DropTestTemporary {
+		defer vEnv.CleanUp()
+	}
+
+	// 当程序卡死的时候,或者由于某些原因程序没有退出,可以通过捕获信号量的形式让程序优雅退出并且清理测试环境
+	common.HandleSignal(func() {
+		shutdown(vEnv)
+	})
+
+	// 对指定的库表进行索引重复检查
+	if common.Config.ReportType == "duplicate-key-checker" {
+		dupKeySuggest := advisor.DuplicateKeyChecker(rEnv)
+		_, str := advisor.FormatSuggest("", common.Config.ReportType, dupKeySuggest)
+		if str == "" {
+			fmt.Printf("%s/%s 未发现重复索引\n", common.Config.OnlineDSN.Addr, common.Config.OnlineDSN.Schema)
+		} else {
+			fmt.Println(str)
+		}
+		return
+	}
+
+	// 读入待优化 SQL ,当配置文件或命令行参数未指定 SQL 时从管道读取
+	buf := initQuery(common.Config.Query)
+	lineCounter += ast.LeftNewLines([]byte(buf))
+	buf = strings.TrimSpace(buf)
+
+	// remove bom from file header
+	var bom []byte
+	buf, bom = common.RemoveBOM([]byte(buf))
+
+	if isContinue, exitCode := reportTool(buf, bom); !isContinue {
+		os.Exit(exitCode)
+	}
+
+	// 逐条SQL给出优化建议
+	for ; ; sqlCounter++ {
+		var id string                                     // fingerprint.ID
+		heuristicSuggest := make(map[string]advisor.Rule) // 启发式建议
+		expSuggest := make(map[string]advisor.Rule)       // EXPLAIN 解读
+		idxSuggest := make(map[string]advisor.Rule)       // 索引建议
+		proSuggest := make(map[string]advisor.Rule)       // Profiling 信息
+		traceSuggest := make(map[string]advisor.Rule)     // Trace 信息
+		mysqlSuggest := make(map[string]advisor.Rule)     // MySQL 返回的 ERROR 信息
+
+		if buf == "" {
+			common.Log.Debug("buf: %s, sql: %s empty", buf, sql)
+			break
+		}
+		// 查询请求切分
+		orgSQL, sql, bufBytes := ast.SplitStatement([]byte(buf), []byte(common.Config.Delimiter))
+		// lineCounter
+		lc := ast.NewLines([]byte(orgSQL))
+		// leftLineCounter
+		llc := ast.LeftNewLines([]byte(orgSQL))
+		lineCounter += llc
+		buf = string(bufBytes)
+
+		// 去除无用的备注和空格
+		sql = database.RemoveSQLComments(sql)
+		if sql == "" {
+			common.Log.Debug("empty query or comment, buf: %s", buf)
+			continue
+		}
+		common.Log.Debug("main loop SQL: %s", sql)
+
+		// +++++++++++++++++++++小工具集[开始]+++++++++++++++++++++++{
+		fingerprint := strings.TrimSpace(query.Fingerprint(sql))
+		switch common.Config.ReportType {
+		case "fingerprint":
+			// SQL 指纹
+			fmt.Println(fingerprint)
+			continue
+		case "pretty":
+			// SQL 美化
+			fmt.Println(ast.Pretty(sql, "builtin") + common.Config.Delimiter)
+			continue
+		case "compress":
+			// SQL 压缩
+			fmt.Println(ast.Compress(sql) + common.Config.Delimiter)
+			continue
+		case "ast":
+			// SQL 抽象语法树
+			var tree sqlparser.Statement
+			tree, err = sqlparser.Parse(sql)
+			if err != nil {
+				fmt.Println(err)
+			} else {
+				_, err = pretty.Println(tree)
+				common.LogIfWarn(err, "")
+			}
+			continue
+		case "tiast":
+			// TiDB SQL 抽象语法树
+			ast.PrintPrettyStmtNode(sql, "", "")
+			continue
+		case "tokenize":
+			// SQL 切词
+			_, err = pretty.Println(ast.Tokenize(sql))
+			common.LogIfWarn(err, "")
+			continue
+		default:
+			// SQL 签名
+			id = query.Id(fingerprint)
+			// 建议去重,减少评审整个文件耗时
+			// TODO: 由于 a = 11 和 a = '11' 的 fingerprint 相同,这里一旦跳过即无法检查有些建议了,如: ARG.003
+			if _, ok := suggestMerged[id]; ok {
+				continue
+			}
+			// 黑名单中的SQL不给建议
+			if advisor.InBlackList(fingerprint) {
+				continue
+			}
+		}
+		// +++++++++++++++++++++小工具集[结束]+++++++++++++++++++++++}
+
+		// +++++++++++++++++++++语法检查[开始]+++++++++++++++++++++++{
+		q, syntaxErr := advisor.NewQuery4Audit(sql)
+		stmt := q.Stmt
+
+		// 如果语法检查出错则不需要给优化建议
+		if syntaxErr != nil {
+			errContent := fmt.Sprintf("At SQL %d : %v", sqlCounter, syntaxErr)
+			common.Log.Warning(errContent)
+			if common.Config.OnlySyntaxCheck {
+				fmt.Println(errContent)
+			}
+			if !common.Config.DryRun {
+				os.Exit(1)
+			}
+			// tidb parser 语法检查给出的建议 ERR.000
+			if common.Config.TestDSN.Disable {
+				mysqlSuggest["ERR.000"] = advisor.RuleMySQLError("ERR.000", syntaxErr)
+			}
+		}
+		// 如果只想检查语法直接跳过后面的步骤
+		if common.Config.OnlySyntaxCheck {
+			continue
+		}
+
+		// +++++++++++++++++++++语法检查[结束]+++++++++++++++++++++++}
+
+		// +++++++++++++++++++++启发式规则建议[开始]+++++++++++++++++++++++{
+		common.Log.Debug("start of heuristic advisor Query: %s", q.Query)
+		for item, rule := range advisor.HeuristicRules {
+			// 去除忽略的建议检查
+			okFunc := (*advisor.Query4Audit).RuleOK
+			if !advisor.IsIgnoreRule(item) && &rule.Func != &okFunc {
+				r := rule.Func(q)
+				if r.Item == item {
+					heuristicSuggest[item] = r
+				}
+			}
+		}
+		common.Log.Debug("end of heuristic advisor Query: %s", q.Query)
+		// +++++++++++++++++++++启发式规则建议[结束]+++++++++++++++++++++++}
+
+		// +++++++++++++++++++++索引优化建议[开始]+++++++++++++++++++++++{
+		// 如果配置了索引建议过滤规则,不进行索引优化建议
+		// 在配置文件 ignore-rules 中添加 'IDX.*' 即可屏蔽索引优化建议
+		common.Log.Debug("start of index advisor Query: %s", q.Query)
+		if !advisor.IsIgnoreRule("IDX.") {
+			if vEnv.BuildVirtualEnv(rEnv, q.Query) {
+				idxAdvisor, err := advisor.NewAdvisor(vEnv, *rEnv, *q)
+				if err != nil || (idxAdvisor == nil && vEnv.Error == nil) {
+					if idxAdvisor == nil {
+						// 如果 SQL 是 DDL 语句,则返回的 idxAdvisor 为 nil,可以忽略不处理
+						// TODO alter table add index 语句检查索引是否已经存在
+						common.Log.Debug("idxAdvisor by pass Query: %s", q.Query)
+					} else {
+						common.Log.Warning("advisor.NewAdvisor Error: %v", err)
+					}
+				} else {
+					// 创建环境时没有出现错误,生成索引建议
+					if vEnv.Error == nil {
+						idxSuggest = idxAdvisor.IndexAdvise().Format()
+
+						// 依赖数据字典的启发式建议
+						for i, r := range idxAdvisor.HeuristicCheck(*q) {
+							heuristicSuggest[i] = r
+						}
+					} else {
+						// 根据错误号输出建议
+						switch vEnv.Error.(*mysql.Error).Code {
+						case 1061:
+							idxSuggest["IDX.001"] = advisor.Rule{
+								Item:     "IDX.001",
+								Severity: "L2",
+								Summary:  "索引名称已存在",
+								Content:  strings.Trim(strings.Split(vEnv.Error.Error(), ":")[1], " "),
+								Case:     sql,
+							}
+						default:
+							// vEnv.VEnvBuild 阶段给出的 ERROR 是 ERR.001
+							mysqlSuggest["ERR.001"] = advisor.RuleMySQLError("ERR.001", vEnv.Error)
+							common.Log.Error("BuildVirtualEnv DDL Execute Error : %v", vEnv.Error)
+						}
+					}
+				}
+			} else {
+				common.Log.Error("vEnv.BuildVirtualEnv Error: prepare SQL '%s' in vEnv failed.", q.Query)
+			}
+		}
+		common.Log.Debug("end of index advisor Query: %s", q.Query)
+		// +++++++++++++++++++++索引优化建议[结束]+++++++++++++++++++++++}
+
+		// +++++++++++++++++++++EXPLAIN 建议[开始]+++++++++++++++++++++++{
+		// 如果未配置 Online 或 Test 无法给 Explain 建议
+		common.Log.Debug("start of explain Query: %s", q.Query)
+		if !common.Config.OnlineDSN.Disable && !common.Config.TestDSN.Disable {
+			// 因为 EXPLAIN 依赖数据库环境,所以把这段逻辑放在启发式建议和索引建议后面
+			if common.Config.Explain {
+				// 执行 EXPLAIN
+				explainInfo, err := rEnv.Explain(q.Query,
+					database.ExplainType[common.Config.ExplainType],
+					database.ExplainFormatType[common.Config.ExplainFormat])
+				if err != nil && strings.HasPrefix(vEnv.Database, "optimizer_") {
+					// 线上环境执行失败才到测试环境 EXPLAIN,比如在用户提供建表语句及查询语句的场景
+					common.Log.Warn("rEnv.Explain Warn: %v", err)
+					explainInfo, err = vEnv.Explain(q.Query,
+						database.ExplainType[common.Config.ExplainType],
+						database.ExplainFormatType[common.Config.ExplainFormat])
+					if err != nil {
+						// EXPLAIN 阶段给出的 ERROR 是 ERR.002
+						mysqlSuggest["ERR.002"] = advisor.RuleMySQLError("ERR.002", err)
+						common.Log.Error("vEnv.Explain Error: %v", err)
+						continue
+					}
+				}
+				// 分析 EXPLAIN 结果
+				if explainInfo != nil {
+					expSuggest = advisor.ExplainAdvisor(explainInfo)
+				} else {
+					common.Log.Warn("rEnv&vEnv.Explain explainInfo nil, SQL: %s", q.Query)
+				}
+			}
+		}
+		common.Log.Debug("end of explain Query: %s", q.Query)
+		// +++++++++++++++++++++ EXPLAIN 建议[结束]+++++++++++++++++++++++}
+
+		// +++++++++++++++++++++ Profiling [开始]+++++++++++++++++++++++++{
+		common.Log.Debug("start of profiling Query: %s", q.Query)
+		if common.Config.Profiling {
+			res, err := vEnv.Profiling(q.Query)
+			if err == nil {
+				proSuggest["PRO.001"] = advisor.Rule{
+					Item:     "PRO.001",
+					Severity: "L0",
+					Content:  database.FormatProfiling(res),
+				}
+			} else {
+				common.Log.Error("Profiling Error: %v", err)
+			}
+		}
+		common.Log.Debug("end of profiling Query: %s", q.Query)
+		// +++++++++++++++++++++ Profiling [结束]++++++++++++++++++++++++++}
+
+		// +++++++++++++++++++++ Trace [开始]+++++++++++++++++++++++++{
+		common.Log.Debug("start of trace Query: %s", q.Query)
+		if common.Config.Trace {
+			res, err := vEnv.Trace(q.Query)
+			if err == nil {
+				traceSuggest["TRA.001"] = advisor.Rule{
+					Item:     "TRA.001",
+					Severity: "L0",
+					Content:  database.FormatTrace(res),
+				}
+			} else {
+				common.Log.Error("Trace Error: %v", err)
+			}
+		}
+		common.Log.Debug("end of trace Query: %s", q.Query)
+		// +++++++++++++++++++++Trace [结束]++++++++++++++++++++++++++}
+
+		// +++++++++++++++++++++SQL 重写[开始]+++++++++++++++++++++++++{
+		common.Log.Debug("start of rewrite Query: %s", q.Query)
+		if common.Config.ReportType == "rewrite" {
+			if strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "create") ||
+				strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "alter") ||
+				strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "rename") {
+				// 依赖上下文件的 SQL 重写,如:多条 ALTER SQL 合并
+				// vitess 对 DDL 语法的支持不好,大部分 DDL 会语法解析出错,但即使出错了还是会生成一个 stmt 而且里面的 db.table 还是准确的。
+
+				alterSQLs = append(alterSQLs, sql)
+				alterTbl := ast.AlterAffectTable(stmt)
+				if alterTbl != "" && alterTbl != "dual" {
+					if _, ok := alterTableTimes[alterTbl]; ok {
+						heuristicSuggest["ALT.002"] = advisor.HeuristicRules["ALT.002"]
+						alterTableTimes[alterTbl] = alterTableTimes[alterTbl] + 1
+					} else {
+						alterTableTimes[alterTbl] = 1
+					}
+				}
+			} else {
+				// 其他不依赖上下文件的 SQL 重写
+				rw := ast.NewRewrite(sql)
+				if rw == nil {
+					// 都到这一步了 sql 不会语法不正确,因此 rw 一般不会为 nil
+					common.Log.Critical("NewRewrite nil point error, SQL: %s", sql)
+					os.Exit(1)
+				}
+				// SQL 转写需要的源信息采集,如果没有配置环境则只做有限改写
+				meta := ast.GetMeta(rw.Stmt, nil)
+				rw.Columns = vEnv.GenTableColumns(meta)
+				// 执行定义好的 SQL 重写规则
+				rw.Rewrite()
+				fmt.Println(strings.TrimSpace(rw.NewSQL))
+			}
+		}
+		common.Log.Debug("end of rewrite Query: %s", q.Query)
+		// +++++++++++++++++++++ SQL 重写[结束]++++++++++++++++++++++++++}
+
+		// +++++++++++++++++++++打印单条 SQL 优化建议[开始]++++++++++++++++++++++++++{
+		common.Log.Debug("start of print suggestions, Query: %s", q.Query)
+		sug, str := advisor.FormatSuggest(q.Query, common.Config.ReportType, heuristicSuggest, idxSuggest, expSuggest, proSuggest, traceSuggest, mysqlSuggest)
+		suggestMerged[id] = sug
+		switch common.Config.ReportType {
+		case "json":
+		case "duplicate-key-checker":
+		case "rewrite":
+		case "lint":
+			for _, s := range strings.Split(str, "\n") {
+				// ignore empty output
+				if strings.TrimSpace(s) == "" {
+					continue
+				}
+
+				if common.Config.Query != "" {
+					if _, err = os.Stat(common.Config.Query); err == nil {
+						fmt.Printf("%s:%d:%s\n", common.Config.Query, lineCounter, s)
+					} else {
+						fmt.Printf("null:%d:%s\n", lineCounter, s)
+					}
+				} else {
+					fmt.Printf("stdin:%d:%s\n", lineCounter, s)
+				}
+			}
+			lineCounter += lc - llc
+		case "html":
+			fmt.Println(common.Markdown2HTML(str))
+		default:
+			fmt.Println(str)
+		}
+		common.Log.Debug("end of print suggestions, Query: %s", q.Query)
+		// +++++++++++++++++++++打印单条 SQL 优化建议[结束]++++++++++++++++++++++++++}
+	}
+
+	// 同一张表的多条 ALTER 语句合并为一条
+	if ast.RewriteRuleMatch("mergealter") {
+		for _, v := range ast.MergeAlterTables(alterSQLs...) {
+			fmt.Println(strings.TrimSpace(v))
+		}
+		return
+	}
+
+	// 以 JSON 格式化输出
+	if common.Config.ReportType == "json" {
+		js, err := json.MarshalIndent(suggestMerged, "", "  ")
+		if err == nil {
+			fmt.Println(string(js))
+		} else {
+			common.Log.Error("FormatSuggest json.Marshal Error: %v", err)
+		}
+		return
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/cmd/soar/soar_test.go b/vendor/github.com/XiaoMi/soar/cmd/soar/soar_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..82be3829fafc2b9d3fb9530bead0c7e3628ba556
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/cmd/soar/soar_test.go
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 main
+
+import (
+	"testing"
+
+	"github.com/XiaoMi/soar/common"
+)
+
+func init() {
+	common.Config.OnlineDSN.Schema = "sakila"
+}
+
+func Test_Main(_ *testing.T) {
+	common.Config.OnlineDSN.Disable = true
+	common.Config.LogLevel = 0
+	common.Config.Query = "select * from film;alter table city add index idx_country_id(country_id);"
+	main()
+}
+
+func Test_Main_More(_ *testing.T) {
+	common.Config.LogLevel = 0
+	common.Config.Profiling = true
+	common.Config.Explain = true
+	common.Config.Query = "select * from film where country_id = 1;use sakila;alter table city add index idx_country_id(country_id);"
+	for _, typ := range []string{
+		"json", "html", "markdown", "fingerprint", "compress", "pretty", "rewrite",
+	} {
+		common.Config.ReportType = typ
+		main()
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/cmd/soar/tool.go b/vendor/github.com/XiaoMi/soar/cmd/soar/tool.go
new file mode 100644
index 0000000000000000000000000000000000000000..dd977d69a50df46f076e6f2681c8f18ed11ea9cf
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/cmd/soar/tool.go
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/XiaoMi/soar/advisor"
+	"github.com/XiaoMi/soar/ast"
+	"github.com/XiaoMi/soar/common"
+	"github.com/XiaoMi/soar/database"
+	"github.com/XiaoMi/soar/env"
+)
+
+// initConfig load config from default->file->cmdFlag
+func initConfig() {
+	// 更新 binary 文件所在路径为 BaseDir
+	ex, err := os.Executable()
+	if err != nil {
+		panic(err)
+	}
+	common.BaseDir = filepath.Dir(ex)
+
+	for i, c := range os.Args {
+		// 如果指定了 -config, 它必须是第一个参数
+		if strings.HasPrefix(c, "-config") && i != 1 {
+			fmt.Println("-config must be the first arg")
+			os.Exit(1)
+		}
+		// 等号两边请不要加空格
+		if c == "=" {
+			// -config = soar.yaml not support
+			fmt.Println("wrong format, no space between '=', eg: -config=soar.yaml")
+			os.Exit(1)
+		}
+	}
+
+	// 加载配置文件,处理命令行参数
+	err = common.ParseConfig(common.ArgConfig())
+	// 检查配置文件及命令行参数是否正确
+	if common.CheckConfig && err != nil {
+		fmt.Println(err.Error())
+		os.Exit(1)
+	}
+	common.LogIfWarn(err, "")
+}
+
+// checkConfig for `-check-config` flag
+// if error found return non-zero, no error return zero
+func checkConfig() int {
+	// TestDSN connection check
+	testConn := &database.Connector{
+		Addr:     common.Config.TestDSN.Addr,
+		User:     common.Config.TestDSN.User,
+		Pass:     common.Config.TestDSN.Password,
+		Database: common.Config.TestDSN.Schema,
+		Charset:  common.Config.TestDSN.Charset,
+	}
+	testVersion, err := testConn.Version()
+	if err != nil && !common.Config.TestDSN.Disable {
+		fmt.Println("test-dsn:", testConn, err.Error())
+		return 1
+	}
+	if common.Config.Verbose {
+		if err == nil {
+			fmt.Println("test-dsn", testConn, "Version:", testVersion)
+		} else {
+			fmt.Println("test-dsn", common.Config.TestDSN)
+		}
+	}
+
+	if !testConn.HasAllPrivilege() {
+		fmt.Printf("test-dsn: %s, need all privileges", common.FormatDSN(common.Config.TestDSN))
+		return 1
+	}
+	// OnlineDSN connection check
+	onlineConn := &database.Connector{
+		Addr:     common.Config.OnlineDSN.Addr,
+		User:     common.Config.OnlineDSN.User,
+		Pass:     common.Config.OnlineDSN.Password,
+		Database: common.Config.OnlineDSN.Schema,
+		Charset:  common.Config.OnlineDSN.Charset,
+	}
+	onlineVersion, err := onlineConn.Version()
+	if err != nil && !common.Config.OnlineDSN.Disable {
+		fmt.Println("online-dsn:", onlineConn, err.Error())
+		return 1
+	}
+	if common.Config.Verbose {
+		if err == nil {
+			fmt.Println("online-dsn", onlineConn, "Version:", onlineVersion)
+		} else {
+			fmt.Println("online-dsn", common.Config.OnlineDSN)
+		}
+	}
+
+	if !onlineConn.HasSelectPrivilege() {
+		fmt.Printf("online-dsn: %s, need all privileges", common.FormatDSN(common.Config.OnlineDSN))
+		return 1
+	}
+	return 0
+}
+
+// helpTools help tools in cmd flags
+func helpTools() (isContinue bool, exitCode int) {
+	// environment error check, eg. MySQL password error
+	if common.CheckConfig {
+		return false, checkConfig()
+	}
+	// 打印 SOAR 版本信息
+	if common.PrintVersion {
+		common.SoarVersion()
+		return false, 0
+	}
+	// 打印已加载配置的各配置项,检查配置是否生效
+	if common.PrintConfig {
+		common.PrintConfiguration()
+		return false, 0
+	}
+	// 打印支持启发式建议
+	if common.Config.ListHeuristicRules {
+		advisor.ListHeuristicRules(advisor.HeuristicRules)
+		return false, 0
+	}
+	// 打印支持的 SQL 重写规则
+	if common.Config.ListRewriteRules {
+		ast.ListRewriteRules(ast.RewriteRules)
+		return false, 0
+	}
+	// 打印所有的测试 SQL
+	if common.Config.ListTestSqls {
+		advisor.ListTestSQLs()
+		return false, 0
+	}
+	// 打印支持的 report-type
+	if common.Config.ListReportTypes {
+		common.ListReportTypes()
+		return false, 0
+	}
+
+	return true, 0
+}
+
+// reportTool tools in report type
+func reportTool(sql string, bom []byte) (isContinue bool, exitCode int) {
+	switch common.Config.ReportType {
+	case "html":
+		// HTML 格式输入 CSS 加载
+		fmt.Println(common.MarkdownHTMLHeader())
+		return true, 0
+	case "md2html":
+		// markdown2html 转换小工具
+		fmt.Println(common.MarkdownHTMLHeader())
+		fmt.Println(common.Markdown2HTML(sql))
+		return false, 0
+	case "explain-digest":
+		// 当用户输入为 EXPLAIN 信息,只对 Explain 信息进行分析
+		// 注意: 这里只能处理一条 SQL 的 EXPLAIN 信息,用户一次反馈多条 SQL 的 EXPLAIN 信息无法处理
+		advisor.DigestExplainText(sql)
+		return false, 0
+	case "chardet":
+		// Get charset of input
+		charset := common.CheckCharsetByBOM(bom)
+		if charset == "" {
+			charset = common.Chardet([]byte(sql))
+		}
+		fmt.Println(charset)
+		return false, 0
+	case "remove-comment":
+		fmt.Println(database.RemoveSQLComments(sql))
+		return false, 0
+	default:
+		return true, 0
+	}
+}
+
+// initQuery
+func initQuery(query string) string {
+	// 读入待优化 SQL ,当配置文件或命令行参数未指定 SQL 时从管道读取
+	if query == "" {
+		// check stdin is pipe or terminal
+		// https://stackoverflow.com/questions/22744443/check-if-there-is-something-to-read-on-stdin-in-golang
+		stat, err := os.Stdin.Stat()
+		if stat == nil {
+			common.Log.Critical("os.Stdin.Stat Error: %v", err)
+			os.Exit(1)
+		}
+		if (stat.Mode() & os.ModeCharDevice) != 0 {
+			// stdin is from a terminal
+			fmt.Println("Args format error, use --help see how to use it!")
+			os.Exit(1)
+		}
+		// read from pipe
+		var data []byte
+		data, err = ioutil.ReadAll(os.Stdin)
+		if err != nil {
+			common.Log.Critical("ioutil.ReadAll Error: %v", err)
+		}
+		return string(data)
+	}
+
+	if _, err := os.Stat(query); err == nil {
+		var data []byte
+		data, err = ioutil.ReadFile(query)
+		if err != nil {
+			common.Log.Critical("ioutil.ReadFile Error: %v", err)
+		}
+		return string(data)
+	}
+
+	return query
+}
+
+func shutdown(vEnv *env.VirtualEnv) {
+	if common.Config.DropTestTemporary {
+		vEnv.CleanUp()
+	}
+	os.Exit(0)
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/cases.go b/vendor/github.com/XiaoMi/soar/common/cases.go
new file mode 100644
index 0000000000000000000000000000000000000000..25763f7d831b9aa29ec9adc107fa0eb3e1fbdfc9
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/cases.go
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+// TestSQLs 测试SQL大集合
+var TestSQLs []string
+
+func init() {
+	// 所有的SQL都要以分号结尾,-list-test-sqls 参数会打印这个 list,以分号结尾可方便测试
+	// 如:./soar -list-test-sql | ./soar
+	TestSQLs = []string{
+		// single equality
+		"SELECT * FROM film WHERE length = 86;",    // index(length)
+		"SELECT * FROM film WHERE length IS NULL;", // index(length)
+		"SELECT * FROM film HAVING title = 'abc';", // 无法使用索引
+
+		// single inequality
+		"SELECT * FROM sakila.film WHERE length >= 60;",   // any of <, <=, >=, >; but not <>, !=, IS NOT NULL"
+		"SELECT * FROM sakila.film WHERE length >= '60';", // Implicit Conversion
+		"SELECT * FROM film WHERE length BETWEEN 60 AND 84;",
+		"SELECT * FROM film WHERE title LIKE 'AIR%';", // but not LIKE '%blah'",
+		"SELECT * FROM film WHERE title IS NOT NULL;",
+
+		// multiple equalities
+		"SELECT * FROM film WHERE length = 114 and title = 'ALABAMA DEVIL';", // index(title,length) or index(length,title)",
+
+		// equality and inequality
+		"SELECT * FROM film WHERE length > 100 and title = 'ALABAMA DEVIL';", // index(title, length)",
+
+		// multiple inequality
+		"SELECT * FROM film WHERE length > 100 and language_id < 10 and title = 'xyz';", // index(d, b) or index(d, c) 依赖数据",
+		"SELECT * FROM film WHERE length > 100 and language_id < 10;",                   // index(b) or index(c)",
+
+		// GROUP BY
+		"SELECT release_year, sum(length) FROM film WHERE length = 123 AND language_id = 1 GROUP BY release_year;",  // INDEX(length, language_id, release_year) or INDEX(language_id, length, release_year)",
+		"SELECT release_year, sum(length) FROM film WHERE length >= 123 GROUP BY release_year;",                     // INDEX(length)",
+		"SELECT release_year, language_id, sum(length) FROM film GROUP BY release_year, language_id;",               // INDEX(release_year, language_id) (no WHERE)",
+		"SELECT release_year, sum(length) FROM film WHERE length = 123 GROUP BY release_year,(length+language_id);", // INDEX(length) expression in GROUP BY, so no use including even release_year.",
+		"SELECT release_year, sum(film_id) FROM film GROUP BY release_year;",                                        // INDEX(`release_year`)
+		"SELECT * FROM address GROUP BY address,district;",                                                          // INDEX(address, district)
+		"SELECT title FROM film WHERE ABS(language_id) = 3 GROUP BY title;",                                         // 无法使用索引
+
+		// ORDER BY
+		"SELECT language_id FROM film WHERE length = 123 GROUP BY release_year ORDER BY language_id;",            //  INDEX(length, release_year) should have stopped with Step 2b",
+		"SELECT release_year FROM film WHERE length = 123 GROUP BY release_year ORDER BY release_year;",          //  INDEX(length, release_year) the release_year will be used for both GROUP BY and ORDER BY",
+		"SELECT * FROM film WHERE length = 123 ORDER BY release_year ASC, language_id DESC;",                     //  INDEX(length) mixture of ASC and DESC.",
+		"SELECT release_year FROM film WHERE length = 123 GROUP BY release_year ORDER BY release_year LIMIT 10;", //  INDEX(length, release_year)",
+		"SELECT * FROM film WHERE length = 123 ORDER BY release_year LIMIT 10;",                                  //  INDEX(length, release_year)",
+		"SELECT * FROM film ORDER BY release_year LIMIT 10;",                                                     //  不能单独给release_year加索引
+		"SELECT film_id FROM film ORDER BY release_year LIMIT 10;",                                               //  TODO: INDEX(release_year),film_id 是主键查询列满足索引覆盖的情况才会使用到 release_year 索引
+		"SELECT * FROM film WHERE length > 100 ORDER BY length LIMIT 10;",                                        //  INDEX(length) This "range" is compatible with ORDER BY
+		"SELECT * FROM film WHERE length < 100 ORDER BY length LIMIT 10;",                                        //  INDEX(length) also works
+		"SELECT * FROM customer WHERE address_id in (224,510) ORDER BY last_name;",                               //  INDEX(address_id)
+		"SELECT * FROM film WHERE release_year = 2016 AND length != 1 ORDER BY title;",                           //  INDEX(`release_year`, `length`, `title`)
+
+		// "Covering" IdxRows
+		"SELECT title FROM film WHERE release_year = 1995;",                               //  INDEX(release_year, title)",
+		"SELECT title, replacement_cost FROM film WHERE language_id = 5 AND length = 70;", //  INDEX(language_id, length, title, replacement_cos film ), title, replacement_cost顺序无关,language_id, length顺序视散粒度情况.
+		"SELECT title FROM film WHERE language_id > 5 AND length > 70;",                   //  INDEX(language_id, length, title) language_id or length first (that's as far as the Algorithm goes), then the other two fields afterwards.
+
+		// equalities and sort
+		"SELECT * FROM film WHERE length = 100 and title = 'xyz' ORDER BY release_year;", // 依赖数据特征,index(length, title, release_year) or index(title, length, release_year)需要评估
+
+		// inequality and sort
+		"SELECT * FROM film WHERE length > 100 and title = 'xyz' ORDER BY release_year;", // 依赖数据特征, index(title, release_year),index(title, length)需要评估
+		"SELECT * FROM film WHERE length > 100 ORDER BY release_year;",                   // 依赖数据特征, index(length),index(release_year)需要评估
+
+		// Join
+		// 内连接 INNER JOIN
+		// 在mysql中,inner join...on , join...on , 逗号...WHERE ,cross join...on是一样的含义。
+		// 但是在标准SQL中,它们并不等价,标准 SQL 中 INNER JOIN 与 ON共同使用, CROSS JOIN用于其他情况。
+		// 逗号不支持 on 和 using 语法, 逗号的优先级要低于INNER JOIN, CROSS JOIN, LEFT JOIN
+		// ON子句的语法格式为:tb1.col1 = tb2.col2列名可以不同,筛选连接后的结果,两表的对应列值相同才在结果集中。
+		// 当模式设计对联接表的列采用了相同的命名样式时,就可以使用 USING 语法来简化 ON 语法
+
+		// join, inner join, cross join等价,优先选择小结果集条件表为驱动表
+		// left [outer] join左表为驱动表
+		// right [outer] join右表为驱动表
+		// 驱动表连接列如果没其他条件可以不考虑加索引,反正是需要foreach
+		// 被驱动表连接列需要加索引。即:left [outer] join的右表连接列需要加索引,right [outer] join的左表连接列需要加索引,inner join结果集较大表的连接列需要加索引
+		// 其他索引添加算法与单表索引优化算法相同
+		// 总结:被驱动表列需要添加索引
+		// 建议:将无索引的表通常作为驱动表
+
+		"SELECT * FROM city a INNER JOIN country b ON a.country_id=b.country_id;",
+
+		// 左外连接 LEFT [OUTER] JOIN
+		"SELECT * FROM city a LEFT JOIN country b ON a.country_id=b.country_id;",
+
+		// 右外连接 RIGHT [OUTER] JOIN
+		"SELECT * FROM city a RIGHT JOIN country b ON a.country_id=b.country_id;",
+
+		// 左连接
+		"SELECT * FROM city a LEFT JOIN country b ON a.country_id=b.country_id WHERE b.last_update IS NULL;",
+
+		// 右连接
+		"SELECT * FROM city a RIGHT JOIN country b ON a.country_id=b.country_id WHERE a.last_update IS NULL;",
+
+		// 全连接 FULL JOIN 因为在mysql中并不支持,所以我们用union实现
+		"SELECT * FROM city a LEFT JOIN country b ON a.country_id=b.country_id " +
+			"UNION " +
+			"SELECT * FROM city a RIGHT JOIN country b ON a.country_id=b.country_id;",
+
+		// 两张表中不共同满足的数据集
+		"SELECT * FROM city a RIGHT JOIN country b ON a.country_id=b.country_id WHERE a.last_update IS NULL " +
+			"UNION " +
+			"SELECT * FROM city a LEFT JOIN country b ON a.country_id=b.country_id WHERE b.last_update IS NULL;",
+
+		// NATURAL JOIN 默认是同名字段完全匹配的INNER JOIN
+		"SELECT country_id, last_update FROM city NATURAL JOIN country;",
+
+		// NATURAL LEFT JOIN
+		"SELECT country_id, last_update FROM city NATURAL LEFT JOIN country;",
+
+		// NATURAL RIGHT JOIN
+		"SELECT country_id, last_update FROM city NATURAL RIGHT JOIN country;",
+
+		// STRAIGHT_JOIN 实际上与内连接 INNER JOIN 表现完全一致,
+		// 不同的是使用了 STRAIGHT_JOIN 后指定表载入的顺序,city 先于 country 载入
+		"SELECT a.country_id, a.last_update FROM city a STRAIGHT_JOIN country b ON a.country_id=b.country_id;",
+
+		// SEMI JOIN
+		// 半连接: 当一张表在另一张表找到匹配的记录之后,半连接(semi-join)返回第一张表中的记录。
+		// 与条件连接相反,即使在右节点中找到几条匹配的记录,左节点的表也只会返回一条记录。
+		// 另外,右节点的表一条记录也不会返回。半连接通常使用IN  或 EXISTS 作为连接条件
+		"SELECT d.deptno,d.dname,d.loc FROM scott.dept d WHERE d.deptno IN  (SELECT e.deptno FROM scott.emp e);",
+
+		// Delayed Join
+		// https://www.percona.com/blog/2007/04/06/using-delayed-join-to-optimize-count-and-limit-queries/
+		`SELECT visitor_id, url FROM (SELECT id FROM log WHERE ip="123.45.67.89" order by ts desc limit 50, 10) I JOIN log ON (I.id=log.id) JOIN url ON (url.id=log.url_id) order by TS desc;`,
+
+		// DELETE
+		"DELETE city, country FROM city INNER JOIN country using (country_id) WHERE city.city_id = 1;",
+		"DELETE city FROM city LEFT JOIN country ON city.country_id = country.country_id WHERE country.country IS NULL;",
+		"DELETE a1, a2 FROM city AS a1 INNER JOIN country AS a2 WHERE a1.country_id=a2.country_id;",
+		"DELETE FROM a1, a2 USING city AS a1 INNER JOIN country AS a2 WHERE a1.country_id=a2.country_id;",
+		"DELETE FROM film WHERE length > 100;",
+
+		// UPDATE
+		"UPDATE city INNER JOIN country USING(country_id) SET city.city = 'Abha', city.last_update = '2006-02-15 04:45:25', country.country = 'Afghanistan' WHERE city.city_id=10;",
+		"UPDATE city INNER JOIN country ON city.country_id = country.country_id INNER JOIN address ON city.city_id = address.city_id SET city.city = 'Abha', city.last_update = '2006-02-15 04:45:25', country.country = 'Afghanistan' WHERE city.city_id=10;",
+		"UPDATE city, country SET city.city = 'Abha', city.last_update = '2006-02-15 04:45:25', country.country = 'Afghanistan' WHERE city.country_id = country.country_id AND city.city_id=10;",
+		"UPDATE film SET length = 10 WHERE language_id = 20;",
+
+		// INSERT
+		"INSERT INTO city (country_id) SELECT country_id FROM country;",
+		"INSERT INTO city (country_id) VALUES (1),(2),(3);",
+		"INSERT INTO city (country_id) VALUES (10);",
+		"INSERT INTO city (country_id) SELECT 10 FROM DUAL;",
+
+		// REPLACE
+		"REPLACE INTO city (country_id) SELECT country_id FROM country;",
+		"REPLACE INTO city (country_id) VALUES (1),(2),(3);",
+		"REPLACE INTO city (country_id) VALUES (10);",
+		"REPLACE INTO city (country_id) SELECT 10 FROM DUAL;",
+
+		// DEPTH
+		"SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM ( SELECT film_id FROM  film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film ) film;",
+
+		// SUBQUERY
+		"SELECT * FROM film WHERE language_id = (SELECT language_id FROM language LIMIT 1);",
+		// "SELECT COUNT(*) /* no hint */ FROM t2 WHERE NOT EXISTS (SELECT * FROM t3 WHERE ROW(5 * t2.s1, 77) = (SELECT 50, 11 * s1 FROM t4 UNION SELECT 50, 77 FROM (SELECT * FROM t5) AS t5 ) ) ;",
+		"SELECT * FROM city i left JOIN country o ON i.city_id=o.country_id union SELECT * FROM city i right JOIN country o ON i.city_id=o.country_id;",
+		"SELECT * FROM (SELECT * FROM actor WHERE last_update='2006-02-15 04:34:33' and last_name='CHASE') t WHERE last_update='2006-02-15 04:34:33' and last_name='CHASE' GROUP BY first_name;",
+		"SELECT * FROM city i left JOIN country o ON i.city_id=o.country_id union SELECT * FROM city i right JOIN country o ON i.city_id=o.country_id;",
+		"SELECT * FROM city i left JOIN country o ON i.city_id=o.country_id WHERE o.country_id is null union SELECT * FROM city i right JOIN country o ON i.city_id=o.country_id WHERE i.city_id is null;",
+		"SELECT first_name,last_name,email FROM customer STRAIGHT_JOIN address ON customer.address_id=address.address_id;",
+		"SELECT ID,name FROM (SELECT address FROM customer_list WHERE SID=1 order by phone limit 50,10) a JOIN customer_list l ON (a.address=l.address) JOIN city c ON (c.city=l.city) order by phone desc;",
+
+		// function in conditions
+		"SELECT * FROM film WHERE date(last_update)='2006-02-15';",
+		"SELECT last_update FROM film GROUP BY date(last_update);",
+		"SELECT last_update FROM film order by date(last_update);",
+
+		// CLA.004
+		"SELECT description FROM film WHERE description IN('NEWS','asd') GROUP BY description;",
+
+		// ALTER TABLE ADD INDEX
+		// 已经存在索引的列应该提醒索引已存在
+		"alter table address add index idx_city_id(city_id);",
+		"alter table inventory add index `idx_store_film` (`store_id`,`film_id`);",
+		"alter table inventory add index `idx_store_film` (`store_id`,`film_id`),add index `idx_store_film` (`store_id`,`film_id`),add index `idx_store_film` (`store_id`,`film_id`);",
+
+		// https://github.com/XiaoMi/soar/issues/47
+		`SELECT	DATE_FORMAT(t.atm, '%Y-%m-%d'),	COUNT(DISTINCT (t.usr))	FROM usr_terminal t WHERE t.atm > '2018-10-22 00:00:00'	AND t.agent LIKE '%Chrome%'	AND t.system = 'eip' GROUP BY DATE_FORMAT(t.atm, '%Y-%m-%d')	ORDER BY DATE_FORMAT(t.atm, '%Y-%m-%d')`,
+		// https://github.com/XiaoMi/soar/issues/17
+		"create table hello.t (id int unsigned);",
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/chardet.go b/vendor/github.com/XiaoMi/soar/common/chardet.go
new file mode 100644
index 0000000000000000000000000000000000000000..223b330064f85726ed5e1d85e21cf9f361df1202
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/chardet.go
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"github.com/saintfish/chardet"
+)
+
+// Chardet get best match charset
+func Chardet(buf []byte) string {
+	// check character set by file BOM
+	charset := CheckCharsetByBOM(buf)
+	if charset != "" {
+		return charset
+	}
+
+	// use chardet pkg check file charset
+	charset = "unknown"
+	var confidence int
+	detector := chardet.NewTextDetector()
+
+	// detector.DetectBest is unstable
+	// when the confidence value are equally, the best detect charset will be random
+	result, err := detector.DetectAll(buf)
+	if err != nil {
+		return charset
+	}
+
+	// SOAR's main user speak Chinese, GB-18030, UTF-8 are higher suggested
+	for _, r := range result {
+		if confidence > r.Confidence && r.Confidence != 0 {
+			return charset
+		}
+		confidence = r.Confidence
+		if r.Charset == "GB-18030" || r.Charset == "UTF-8" {
+			return r.Charset
+		}
+		charset = r.Charset
+	}
+	return charset
+}
+
+// CheckCharsetByBOM ref: https://en.wikipedia.org/wiki/Byte_order_mark
+func CheckCharsetByBOM(buf []byte) string {
+	// TODO: There are many kind of BOM
+	// UTF-8	EF BB BF
+	if len(buf) >= 3 {
+		if buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf {
+			return "UTF-8"
+		}
+	}
+	// GB-18030	84 31 95 33
+	if len(buf) >= 4 {
+		if buf[0] == 0x84 && buf[1] == 0x31 && buf[2] == 0x95 && buf[3] == 0x33 {
+			return "GB-18030"
+		}
+	}
+	return ""
+}
+
+// RemoveBOM remove bom from file
+func RemoveBOM(buf []byte) (string, []byte) {
+	// ef bb bf, UTF-8 BOM
+	if len(buf) > 3 {
+		if buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf {
+			return string(buf[3:]), buf[:3]
+		}
+	}
+	// ff fe, UTF-16 (LE) BOM
+	if len(buf) > 2 {
+		if buf[0] == 0xff && buf[1] == 0xfe {
+			return string(buf[2:]), buf[:2]
+		}
+	}
+	return string(buf), []byte{}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/chardet_test.go b/vendor/github.com/XiaoMi/soar/common/chardet_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..0d6e411f32a75d19d74879e7f375a0420a8c0c9f
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/chardet_test.go
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"fmt"
+	"io/ioutil"
+	"testing"
+)
+
+func TestChardet(t *testing.T) {
+	charsets := []string{
+		"GB-18030",
+		"UTF-8",
+	}
+	for _, c := range charsets {
+		fileName := DevPath + "/common/testdata/chardet_" + c + ".txt"
+		buf, err := ioutil.ReadFile(fileName)
+		if err != nil {
+			t.Errorf("ioutil.ReadFile %s, Error: %s", fileName, err.Error())
+		}
+		name := Chardet(buf)
+		if name != c {
+			t.Errorf("file: %s, Want: %s, Get: %s", fileName, c, name)
+		}
+	}
+}
+
+func TestRemoveBOM(t *testing.T) {
+	fileName := DevPath + "/common/testdata/UTF-8.bom.sql"
+	buf, err := ioutil.ReadFile(fileName)
+	if err != nil {
+		t.Errorf("ioutil.ReadFile %s, Error: %s", fileName, err.Error())
+	}
+	GoldenDiff(func() {
+		fmt.Println(RemoveBOM(buf))
+	}, t.Name(), update)
+}
+
+func TestCheckCharsetByBOM(t *testing.T) {
+	fileName := DevPath + "/common/testdata/UTF-8.bom.sql"
+	buf, err := ioutil.ReadFile(fileName)
+	if err != nil {
+		t.Errorf("ioutil.ReadFile %s, Error: %s", fileName, err.Error())
+	}
+
+	if CheckCharsetByBOM(buf) != "UTF-8" {
+		t.Errorf("checkCharsetByBOM Want: UTF-8, Get: %s", CheckCharsetByBOM(buf))
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/config.go b/vendor/github.com/XiaoMi/soar/common/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..4f84116c407b4870c96943b1559912f4354ad480
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/config.go
@@ -0,0 +1,882 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"runtime"
+	"strings"
+
+	"gopkg.in/yaml.v2"
+)
+
+var (
+	// BlackList 黑名单中的SQL不会被评审
+	BlackList []string
+	// PrintConfig -print-config
+	PrintConfig bool
+	// PrintVersion -print-config
+	PrintVersion bool
+	// CheckConfig -check-config
+	CheckConfig bool
+	// 防止 readCmdFlags 函数重入
+	hasParsed bool
+)
+
+// Configuration 配置文件定义结构体
+type Configuration struct {
+	// +++++++++++++++测试环境+++++++++++++++++
+	OnlineDSN               *dsn   `yaml:"online-dsn"`                // 线上环境数据库配置
+	TestDSN                 *dsn   `yaml:"test-dsn"`                  // 测试环境数据库配置
+	AllowOnlineAsTest       bool   `yaml:"allow-online-as-test"`      // 允许 Online 环境也可以当作 Test 环境
+	DropTestTemporary       bool   `yaml:"drop-test-temporary"`       // 是否清理Test环境产生的临时库表
+	CleanupTestDatabase     bool   `yaml:"cleanup-test-database"`     // 清理残余的测试数据库(程序异常退出或未开启drop-test-temporary)  issue #48
+	OnlySyntaxCheck         bool   `yaml:"only-syntax-check"`         // 只做语法检查不输出优化建议
+	SamplingStatisticTarget int    `yaml:"sampling-statistic-target"` // 数据采样因子,对应 PostgreSQL 的 default_statistics_target
+	Sampling                bool   `yaml:"sampling"`                  // 数据采样开关
+	Profiling               bool   `yaml:"profiling"`                 // 在开启数据采样的情况下,在测试环境执行进行profile
+	Trace                   bool   `yaml:"trace"`                     // 在开启数据采样的情况下,在测试环境执行进行Trace
+	Explain                 bool   `yaml:"explain"`                   // Explain开关
+	ConnTimeOut             int    `yaml:"conn-time-out"`             // 数据库连接超时时间,单位秒
+	QueryTimeOut            int    `yaml:"query-time-out"`            // 数据库SQL执行超时时间,单位秒
+	Delimiter               string `yaml:"delimiter"`                 // SQL分隔符
+
+	// +++++++++++++++日志相关+++++++++++++++++
+	// 日志级别,这里使用了 beego 的 log 包
+	// [0:Emergency, 1:Alert, 2:Critical, 3:Error, 4:Warning, 5:Notice, 6:Informational, 7:Debug]
+	LogLevel int `yaml:"log-level"`
+	// 日志输出位置,默认日志输出到控制台
+	// 目前只支持['console', 'file']两种形式,如非console形式这里需要指定文件的路径,可以是相对路径
+	LogOutput string `yaml:"log-output"`
+	// 优化建议输出格式,目前支持: json, text, markdown格式,如指定其他格式会给 pretty.Println 的输出
+	ReportType string `yaml:"report-type"`
+	// 当 ReportType 为 html 格式时使用的 css 风格,如不指定会提供一个默认风格。CSS可 以是本地文件,也可以是一个URL
+	ReportCSS string `yaml:"report-css"`
+	// 当 ReportType 为 html 格式时使用的 javascript 脚本,如不指定默认会加载SQL pretty 使用的 javascript。像CSS一样可以是本地文件,也可以是一个URL
+	ReportJavascript string `yaml:"report-javascript"`
+	// 当ReportType 为 html 格式时,HTML 的 title
+	ReportTitle string `yaml:"report-title"`
+	// blackfriday markdown2html config
+	MarkdownExtensions int `yaml:"markdown-extensions"` // markdown 转 html 支持的扩展包, 参考blackfriday
+	MarkdownHTMLFlags  int `yaml:"markdown-html-flags"` // markdown 转 html 支持的 flag, 参考blackfriday, default 0
+
+	// ++++++++++++++优化建议相关++++++++++++++
+	IgnoreRules          []string `yaml:"ignore-rules"`              // 忽略的优化建议规则
+	RewriteRules         []string `yaml:"rewrite-rules"`             // 生效的重写规则
+	BlackList            string   `yaml:"blacklist"`                 // blacklist 中的 SQL 不会被评审,可以是指纹,也可以是正则
+	MaxJoinTableCount    int      `yaml:"max-join-table-count"`      // 单条 SQL 中 JOIN 表的最大数量
+	MaxGroupByColsCount  int      `yaml:"max-group-by-cols-count"`   // 单条 SQL 中 GroupBy 包含列的最大数量
+	MaxDistinctCount     int      `yaml:"max-distinct-count"`        // 单条 SQL 中 Distinct 的最大数量
+	MaxIdxColsCount      int      `yaml:"max-index-cols-count"`      // 复合索引中包含列的最大数量
+	MaxTotalRows         int64    `yaml:"max-total-rows"`            // 计算散粒度时,当数据行数大于 MaxTotalRows 即开启数据库保护模式,散粒度返回结果可信度下降
+	MaxQueryCost         int64    `yaml:"max-query-cost"`            // last_query_cost 超过该值时将给予警告
+	SpaghettiQueryLength int      `yaml:"spaghetti-query-length"`    // SQL最大长度警告,超过该长度会给警告
+	AllowDropIndex       bool     `yaml:"allow-drop-index"`          // 允许输出删除重复索引的建议
+	MaxInCount           int      `yaml:"max-in-count"`              // IN()最大数量
+	MaxIdxBytesPerColumn int      `yaml:"max-index-bytes-percolumn"` // 索引中单列最大字节数,默认767
+	MaxIdxBytes          int      `yaml:"max-index-bytes"`           // 索引总长度限制,默认3072
+	TableAllowCharsets   []string `yaml:"table-allow-charsets"`      // Table 允许使用的 DEFAULT CHARSET
+	TableAllowEngines    []string `yaml:"table-allow-engines"`       // Table 允许使用的 Engine
+	MaxIdxCount          int      `yaml:"max-index-count"`           // 单张表允许最多索引数
+	MaxColCount          int      `yaml:"max-column-count"`          // 单张表允许最大列数
+	MaxValueCount        int      `yaml:"max-value-count"`           // INSERT/REPLACE 单次允许批量写入的行数
+	IdxPrefix            string   `yaml:"index-prefix"`              // 普通索引建议使用的前缀
+	UkPrefix             string   `yaml:"unique-key-prefix"`         // 唯一键建议使用的前缀
+	MaxSubqueryDepth     int      `yaml:"max-subquery-depth"`        // 子查询最大尝试
+	MaxVarcharLength     int      `yaml:"max-varchar-length"`        // varchar最大长度
+
+	// ++++++++++++++EXPLAIN检查项+++++++++++++
+	ExplainSQLReportType   string   `yaml:"explain-sql-report-type"`  // EXPLAIN markdown 格式输出 SQL 样式,支持 sample, fingerprint, pretty 等
+	ExplainType            string   `yaml:"explain-type"`             // EXPLAIN方式 [traditional, extended, partitions]
+	ExplainFormat          string   `yaml:"explain-format"`           // FORMAT=[json, traditional]
+	ExplainWarnSelectType  []string `yaml:"explain-warn-select-type"` // 哪些 select_type 不建议使用
+	ExplainWarnAccessType  []string `yaml:"explain-warn-access-type"` // 哪些 access type 不建议使用
+	ExplainMaxKeyLength    int      `yaml:"explain-max-keys"`         // 最大 key_len
+	ExplainMinPossibleKeys int      `yaml:"explain-min-keys"`         // 最小 possible_keys 警告
+	ExplainMaxRows         int      `yaml:"explain-max-rows"`         // 最大扫描行数警告
+	ExplainWarnExtra       []string `yaml:"explain-warn-extra"`       // 哪些 extra 信息会给警告
+	ExplainMaxFiltered     float64  `yaml:"explain-max-filtered"`     // filtered 大于该配置给出警告
+	ExplainWarnScalability []string `yaml:"explain-warn-scalability"` // 复杂度警告名单
+	ShowWarnings           bool     `yaml:"show-warnings"`            // explain extended with show warnings
+	ShowLastQueryCost      bool     `yaml:"show-last-query-cost"`     // switch with show status like 'last_query_cost'
+	// ++++++++++++++其他配置项+++++++++++++++
+	Query              string `yaml:"query"`                 // 需要进行调优的SQL
+	ListHeuristicRules bool   `yaml:"list-heuristic-rules"`  // 打印支持的评审规则列表
+	ListRewriteRules   bool   `yaml:"list-rewrite-rules"`    // 打印重写规则
+	ListTestSqls       bool   `yaml:"list-test-sqls"`        // 打印测试case用于测试
+	ListReportTypes    bool   `yaml:"list-report-types"`     // 打印支持的报告输出类型
+	Verbose            bool   `yaml:"verbose"`               // verbose模式,会多输出一些信息
+	DryRun             bool   `yaml:"dry-run"`               // 是否在预演环境执行
+	MaxPrettySQLLength int    `yaml:"max-pretty-sql-length"` // 超出该长度的SQL会转换成指纹输出
+}
+
+// Config 默认设置
+var Config = &Configuration{
+	OnlineDSN: &dsn{
+		Schema:  "information_schema",
+		Charset: "utf8mb4",
+		Disable: true,
+		Version: 99999,
+	},
+	TestDSN: &dsn{
+		Schema:  "information_schema",
+		Charset: "utf8mb4",
+		Disable: true,
+		Version: 99999,
+	},
+	AllowOnlineAsTest:       false,
+	DropTestTemporary:       true,
+	CleanupTestDatabase:     false,
+	DryRun:                  true,
+	OnlySyntaxCheck:         false,
+	SamplingStatisticTarget: 100,
+	Sampling:                false,
+	Profiling:               false,
+	Trace:                   false,
+	Explain:                 true,
+	ConnTimeOut:             3,
+	QueryTimeOut:            30,
+	Delimiter:               ";",
+
+	MaxJoinTableCount:    5,
+	MaxGroupByColsCount:  5,
+	MaxDistinctCount:     5,
+	MaxIdxColsCount:      5,
+	MaxIdxBytesPerColumn: 767,
+	MaxIdxBytes:          3072,
+	MaxTotalRows:         9999999,
+	MaxQueryCost:         9999,
+	SpaghettiQueryLength: 2048,
+	AllowDropIndex:       false,
+	LogLevel:             3,
+	LogOutput:            "soar.log",
+	ReportType:           "markdown",
+	ReportCSS:            "",
+	ReportJavascript:     "",
+	ReportTitle:          "SQL优化分析报告",
+	BlackList:            "",
+	TableAllowCharsets:   []string{"utf8", "utf8mb4"},
+	TableAllowEngines:    []string{"innodb"},
+	MaxIdxCount:          10,
+	MaxColCount:          40,
+	MaxValueCount:        100,
+	MaxInCount:           10,
+	IdxPrefix:            "idx_",
+	UkPrefix:             "uk_",
+	MaxSubqueryDepth:     5,
+	MaxVarcharLength:     1024,
+
+	MarkdownExtensions: 94,
+	MarkdownHTMLFlags:  0,
+
+	ExplainSQLReportType:   "pretty",
+	ExplainType:            "extended",
+	ExplainFormat:          "traditional",
+	ExplainWarnSelectType:  []string{""},
+	ExplainWarnAccessType:  []string{"ALL"},
+	ExplainMaxKeyLength:    3,
+	ExplainMinPossibleKeys: 0,
+	ExplainMaxRows:         10000,
+	ExplainWarnExtra:       []string{"Using temporary", "Using filesort"},
+	ExplainMaxFiltered:     100.0,
+	ExplainWarnScalability: []string{"O(n)"},
+	ShowWarnings:           false,
+	ShowLastQueryCost:      false,
+
+	IgnoreRules: []string{
+		"COL.011",
+	},
+	RewriteRules: []string{
+		"delimiter",
+		"orderbynull",
+		"groupbyconst",
+		"dmlorderby",
+		"having",
+		"star2columns",
+		"insertcolumns",
+		"distinctstar",
+	},
+
+	ListHeuristicRules: false,
+	ListRewriteRules:   false,
+	ListTestSqls:       false,
+	ListReportTypes:    false,
+	MaxPrettySQLLength: 1024,
+}
+
+type dsn struct {
+	Addr   string `yaml:"addr"`
+	Schema string `yaml:"schema"`
+
+	// 数据库用户名和密码可以通过系统环境变量的形式赋值
+	User     string `yaml:"user"`
+	Password string `yaml:"password"`
+	Charset  string `yaml:"charset"`
+	Disable  bool   `yaml:"disable"`
+
+	Version int `yaml:"-"` // 版本自动检查,不可配置
+}
+
+// 解析命令行DSN输入
+func parseDSN(odbc string, d *dsn) *dsn {
+	var addr, user, password, schema, charset string
+	if odbc == FormatDSN(d) {
+		return d
+	}
+
+	if d != nil {
+		addr = d.Addr
+		user = d.User
+		password = d.Password
+		schema = d.Schema
+		charset = d.Charset
+	}
+
+	// 设置为空表示禁用环境
+	odbc = strings.TrimSpace(odbc)
+	if odbc == "" {
+		return &dsn{Disable: true}
+	}
+
+	// username:password@ip:port/database
+	l1 := strings.Split(odbc, "@")
+	if len(l1) < 2 {
+		if strings.HasPrefix(l1[0], ":") {
+			// ":port/database"
+			l2 := strings.Split(strings.TrimLeft(l1[0], ":"), "/")
+			if l2[0] == "" {
+				addr = strings.Split(addr, ":")[0] + ":3306"
+				if len(l2) > 1 {
+					schema = strings.Split(l2[1], "?")[0]
+				}
+			} else {
+				addr = strings.Split(addr, ":")[0] + ":" + l2[0]
+				if len(l2) > 1 {
+					schema = strings.Split(l2[1], "?")[0]
+				}
+			}
+		} else if strings.HasPrefix(l1[0], "/") {
+			// "/database"
+			l2 := strings.TrimLeft(l1[0], "/")
+			schema = l2
+		} else {
+			// ip:port/database
+			l2 := strings.Split(l1[0], "/")
+			if len(l2) == 2 {
+				addr = l2[0]
+				schema = strings.Split(l2[1], "?")[0]
+			} else {
+				addr = l2[0]
+			}
+		}
+	} else {
+		// user:password
+		l2 := strings.Split(l1[0], ":")
+		if len(l2) == 2 {
+			user = l2[0]
+			password = l2[1]
+		} else {
+			user = l2[0]
+		}
+		// ip:port/database
+		l3 := strings.Split(l1[1], "/")
+		if len(l3) == 2 {
+			addr = l3[0]
+			schema = strings.Split(l3[1], "?")[0]
+		} else {
+			addr = l3[0]
+		}
+	}
+
+	// 其他flag参数,目前只支持charset :(
+	if len(strings.Split(odbc, "?")) > 1 {
+		flags := strings.Split(strings.Split(odbc, "?")[1], "&")
+		for _, f := range flags {
+			attr := strings.Split(f, "=")
+			if len(attr) > 1 {
+				arg := strings.TrimSpace(attr[0])
+				val := strings.TrimSpace(attr[1])
+				switch arg {
+				case "charset":
+					charset = val
+				default:
+				}
+			}
+		}
+	}
+
+	// 自动补端口
+	if !strings.Contains(addr, ":") {
+		addr = addr + ":3306"
+	} else {
+		if strings.HasSuffix(addr, ":") {
+			addr = addr + "3306"
+		}
+	}
+
+	// 默认走127.0.0.1
+	if strings.HasPrefix(addr, ":") {
+		addr = "127.0.0.1" + addr
+	}
+
+	// 默认用information_schema库
+	if schema == "" {
+		schema = "information_schema"
+	}
+
+	// 默认utf8mb4使用字符集
+	if charset == "" {
+		charset = "utf8mb4"
+	}
+
+	dsn := &dsn{
+		Addr:     addr,
+		User:     user,
+		Password: password,
+		Schema:   schema,
+		Charset:  charset,
+		Disable:  false,
+		Version:  999,
+	}
+	return dsn
+}
+
+// FormatDSN 格式化打印DSN
+func FormatDSN(env *dsn) string {
+	if env == nil || env.Disable {
+		return ""
+	}
+	// username:password@ip:port/schema?charset=xxx
+	return fmt.Sprintf("%s:%s@%s/%s?charset=%s", env.User, env.Password, env.Addr, env.Schema, env.Charset)
+}
+
+// SoarVersion soar version information
+func SoarVersion() {
+	fmt.Println("Version:", Version)
+	fmt.Println("Branch:", Branch)
+	fmt.Println("Compile:", Compile)
+	fmt.Println("GitDirty:", GitDirty)
+}
+
+// 因为vitess sqlparser 使用了 glog 中也会使用 flag,为了不让用户困扰我们单独写一个 usage
+func usage() {
+	regPwd := regexp.MustCompile(`:.*@`)
+	vitessHelp := []string{
+		"-alsologtostderr",
+		"log to standard error as well as files",
+		"-log_backtrace_at value",
+		"when logging hits line file:N, emit a stack trace",
+		"-log_dir string",
+		"If non-empty, write log files in this directory",
+		"-logtostderr",
+		"log to standard error instead of files",
+		"-sql-max-length-errors int",
+		"truncate queries in error logs to the given length (default unlimited)",
+		"-sql-max-length-ui int",
+		"truncate queries in debug UIs to the given length (default 512) (default 512)",
+		"-stderrthreshold value",
+		"logs at or above this threshold go to stderr",
+		"-v value",
+		"log level for V logs",
+		"-vmodule value",
+		"comma-separated list of pattern=N settings for file-filtered logging",
+	}
+
+	// io redirect
+	restoreStdout := os.Stdout
+	restoreStderr := os.Stderr
+	stdin, stdout, _ := os.Pipe()
+	os.Stderr = stdout
+	os.Stdout = stdout
+
+	flag.PrintDefaults()
+
+	// copy the output in a separate goroutine so printing can't block indefinitely
+	outC := make(chan string)
+	go func() {
+		var buf bytes.Buffer
+		_, err := io.Copy(&buf, stdin)
+		if err != nil {
+			fmt.Println(err.Error())
+		}
+		outC <- buf.String()
+	}()
+
+	// back to normal state
+	stdout.Close()
+	os.Stdout = restoreStdout // restoring the real stderr
+	os.Stderr = restoreStderr
+
+	fmt.Printf("Usage of %s:\n", os.Args[0])
+	// reading our temp stdout
+	out := <-outC
+	for _, line := range strings.Split(out, "\n") {
+		found := false
+		for _, ignore := range vitessHelp {
+			if strings.TrimSpace(line) == strings.TrimSpace(ignore) {
+				found = true
+			}
+			if regPwd.MatchString(line) && !Config.Verbose {
+				line = regPwd.ReplaceAllString(line, ":********@")
+			}
+		}
+		if !found {
+			fmt.Println(line)
+		}
+	}
+}
+
+// PrintConfiguration for `-print-config` flag
+func PrintConfiguration() {
+	// 打印配置的时候密码不显示
+	if !Config.Verbose {
+		Config.OnlineDSN.Password = "********"
+		Config.TestDSN.Password = "********"
+	}
+	data, _ := yaml.Marshal(Config)
+	fmt.Print(string(data))
+}
+
+// 加载配置文件
+func (conf *Configuration) readConfigFile(path string) error {
+	configFile, err := os.Open(path)
+	if err != nil {
+		Log.Warning("readConfigFile(%s) os.Open failed: %v", path, err)
+		return err
+	}
+	defer configFile.Close()
+
+	content, err := ioutil.ReadAll(configFile)
+	if err != nil {
+		Log.Warning("readConfigFile(%s) ioutil.ReadAll failed: %v", path, err)
+		return err
+	}
+
+	err = yaml.Unmarshal(content, Config)
+	if err != nil {
+		Log.Warning("readConfigFile(%s) yaml.Unmarshal failed: %v", path, err)
+		return err
+	}
+	return nil
+}
+
+// 从命令行参数读配置
+func readCmdFlags() error {
+	if hasParsed {
+		Log.Debug("Skip read cmd flags.")
+		return nil
+	}
+
+	_ = flag.String("config", "", "Config file path")
+	// +++++++++++++++测试环境+++++++++++++++++
+	onlineDSN := flag.String("online-dsn", FormatDSN(Config.OnlineDSN), "OnlineDSN, 线上环境数据库配置, username:password@ip:port/schema")
+	testDSN := flag.String("test-dsn", FormatDSN(Config.TestDSN), "TestDSN, 测试环境数据库配置, username:password@ip:port/schema")
+	allowOnlineAsTest := flag.Bool("allow-online-as-test", Config.AllowOnlineAsTest, "AllowOnlineAsTest, 允许线上环境也可以当作测试环境")
+	dropTestTemporary := flag.Bool("drop-test-temporary", Config.DropTestTemporary, "DropTestTemporary, 是否清理测试环境产生的临时库表")
+	cleanupTestDatabase := flag.Bool("cleanup-test-database", Config.CleanupTestDatabase, "单次运行清理历史1小时前残余的测试库。")
+	onlySyntaxCheck := flag.Bool("only-syntax-check", Config.OnlySyntaxCheck, "OnlySyntaxCheck, 只做语法检查不输出优化建议")
+	profiling := flag.Bool("profiling", Config.Profiling, "Profiling, 开启数据采样的情况下在测试环境执行Profile")
+	trace := flag.Bool("trace", Config.Trace, "Trace, 开启数据采样的情况下在测试环境执行Trace")
+	explain := flag.Bool("explain", Config.Explain, "Explain, 是否开启Explain执行计划分析")
+	sampling := flag.Bool("sampling", Config.Sampling, "Sampling, 数据采样开关")
+	samplingStatisticTarget := flag.Int("sampling-statistic-target", Config.SamplingStatisticTarget, "SamplingStatisticTarget, 数据采样因子,对应 PostgreSQL 的 default_statistics_target")
+	connTimeOut := flag.Int("conn-time-out", Config.ConnTimeOut, "ConnTimeOut, 数据库连接超时时间,单位秒")
+	queryTimeOut := flag.Int("query-time-out", Config.QueryTimeOut, "QueryTimeOut, 数据库SQL执行超时时间,单位秒")
+	delimiter := flag.String("delimiter", Config.Delimiter, "Delimiter, SQL分隔符")
+	// +++++++++++++++日志相关+++++++++++++++++
+	logLevel := flag.Int("log-level", Config.LogLevel, "LogLevel, 日志级别, [0:Emergency, 1:Alert, 2:Critical, 3:Error, 4:Warning, 5:Notice, 6:Informational, 7:Debug]")
+	logOutput := flag.String("log-output", Config.LogOutput, "LogOutput, 日志输出位置")
+	reportType := flag.String("report-type", Config.ReportType, "ReportType, 化建议输出格式,目前支持: json, text, markdown, html等")
+	reportCSS := flag.String("report-css", Config.ReportCSS, "ReportCSS, 当 ReportType 为 html 格式时使用的 css 风格,如不指定会提供一个默认风格。CSS可以是本地文件,也可以是一个URL")
+	reportJavascript := flag.String("report-javascript", Config.ReportJavascript, "ReportJavascript, 当 ReportType 为 html 格式时使用的javascript脚本,如不指定默认会加载SQL pretty 使用的 javascript。像CSS一样可以是本地文件,也可以是一个URL")
+	reportTitle := flag.String("report-title", Config.ReportTitle, "ReportTitle, 当 ReportType 为 html 格式时,HTML 的 title")
+	// +++++++++++++++markdown+++++++++++++++++
+	markdownExtensions := flag.Int("markdown-extensions", Config.MarkdownExtensions, "MarkdownExtensions, markdown 转 html支持的扩展包, 参考blackfriday")
+	markdownHTMLFlags := flag.Int("markdown-html-flags", Config.MarkdownHTMLFlags, "MarkdownHTMLFlags, markdown 转 html 支持的 flag, 参考blackfriday")
+	// ++++++++++++++优化建议相关++++++++++++++
+	ignoreRules := flag.String("ignore-rules", strings.Join(Config.IgnoreRules, ","), "IgnoreRules, 忽略的优化建议规则")
+	rewriteRules := flag.String("rewrite-rules", strings.Join(Config.RewriteRules, ","), "RewriteRules, 生效的重写规则")
+	blackList := flag.String("blacklist", Config.BlackList, "指定 blacklist 配置文件的位置,文件中的 SQL 不会被评审。一行一条SQL,可以是指纹,也可以是正则")
+	maxJoinTableCount := flag.Int("max-join-table-count", Config.MaxJoinTableCount, "MaxJoinTableCount, 单条 SQL 中 JOIN 表的最大数量")
+	maxGroupByColsCount := flag.Int("max-group-by-cols-count", Config.MaxGroupByColsCount, "MaxGroupByColsCount, 单条 SQL 中 GroupBy 包含列的最大数量")
+	maxDistinctCount := flag.Int("max-distinct-count", Config.MaxDistinctCount, "MaxDistinctCount, 单条 SQL 中 Distinct 的最大数量")
+	maxIdxColsCount := flag.Int("max-index-cols-count", Config.MaxIdxColsCount, "MaxIdxColsCount, 复合索引中包含列的最大数量")
+	maxTotalRows := flag.Int64("max-total-rows", Config.MaxTotalRows, "MaxTotalRows, 计算散粒度时,当数据行数大于MaxTotalRows即开启数据库保护模式,不计算散粒度")
+	maxQueryCost := flag.Int64("max-query-cost", Config.MaxQueryCost, "MaxQueryCost, last_query_cost 超过该值时将给予警告")
+	spaghettiQueryLength := flag.Int("spaghetti-query-length", Config.SpaghettiQueryLength, "SpaghettiQueryLength, SQL最大长度警告,超过该长度会给警告")
+	allowDropIdx := flag.Bool("allow-drop-index", Config.AllowDropIndex, "AllowDropIndex, 允许输出删除重复索引的建议")
+	maxInCount := flag.Int("max-in-count", Config.MaxInCount, "MaxInCount, IN()最大数量")
+	maxIdxBytesPerColumn := flag.Int("max-index-bytes-percolumn", Config.MaxIdxBytesPerColumn, "MaxIdxBytesPerColumn, 索引中单列最大字节数")
+	maxIdxBytes := flag.Int("max-index-bytes", Config.MaxIdxBytes, "MaxIdxBytes, 索引总长度限制")
+	tableAllowCharsets := flag.String("table-allow-charsets", strings.ToLower(strings.Join(Config.TableAllowCharsets, ",")), "TableAllowCharsets")
+	tableAllowEngines := flag.String("table-allow-engines", strings.ToLower(strings.Join(Config.TableAllowEngines, ",")), "TableAllowEngines")
+	maxIdxCount := flag.Int("max-index-count", Config.MaxIdxCount, "MaxIdxCount, 单表最大索引个数")
+	maxColCount := flag.Int("max-column-count", Config.MaxColCount, "MaxColCount, 单表允许的最大列数")
+	maxValueCount := flag.Int("max-value-count", Config.MaxValueCount, "MaxValueCount, INSERT/REPLACE 单次批量写入允许的行数")
+	idxPrefix := flag.String("index-prefix", Config.IdxPrefix, "IdxPrefix")
+	ukPrefix := flag.String("unique-key-prefix", Config.UkPrefix, "UkPrefix")
+	maxSubqueryDepth := flag.Int("max-subquery-depth", Config.MaxSubqueryDepth, "MaxSubqueryDepth")
+	maxVarcharLength := flag.Int("max-varchar-length", Config.MaxVarcharLength, "MaxVarcharLength")
+	// ++++++++++++++EXPLAIN检查项+++++++++++++
+	explainSQLReportType := flag.String("explain-sql-report-type", strings.ToLower(Config.ExplainSQLReportType), "ExplainSQLReportType [pretty, sample, fingerprint]")
+	explainType := flag.String("explain-type", strings.ToLower(Config.ExplainType), "ExplainType [extended, partitions, traditional]")
+	explainFormat := flag.String("explain-format", strings.ToLower(Config.ExplainFormat), "ExplainFormat [json, traditional]")
+	explainWarnSelectType := flag.String("explain-warn-select-type", strings.Join(Config.ExplainWarnSelectType, ","), "ExplainWarnSelectType, 哪些select_type不建议使用")
+	explainWarnAccessType := flag.String("explain-warn-access-type", strings.Join(Config.ExplainWarnAccessType, ","), "ExplainWarnAccessType, 哪些access type不建议使用")
+	explainMaxKeyLength := flag.Int("explain-max-keys", Config.ExplainMaxKeyLength, "ExplainMaxKeyLength, 最大key_len")
+	explainMinPossibleKeys := flag.Int("explain-min-keys", Config.ExplainMinPossibleKeys, "ExplainMinPossibleKeys, 最小possible_keys警告")
+	explainMaxRows := flag.Int("explain-max-rows", Config.ExplainMaxRows, "ExplainMaxRows, 最大扫描行数警告")
+	explainWarnExtra := flag.String("explain-warn-extra", strings.Join(Config.ExplainWarnExtra, ","), "ExplainWarnExtra, 哪些extra信息会给警告")
+	explainMaxFiltered := flag.Float64("explain-max-filtered", Config.ExplainMaxFiltered, "ExplainMaxFiltered, filtered大于该配置给出警告")
+	explainWarnScalability := flag.String("explain-warn-scalability", strings.Join(Config.ExplainWarnScalability, ","), "ExplainWarnScalability, 复杂度警告名单, 支持O(n),O(log n),O(1),O(?)")
+	showWarnings := flag.Bool("show-warnings", Config.ShowWarnings, "ShowWarnings")
+	showLastQueryCost := flag.Bool("show-last-query-cost", Config.ShowLastQueryCost, "ShowLastQueryCost")
+	// +++++++++++++++++其他+++++++++++++++++++
+	printConfig := flag.Bool("print-config", false, "Print configs")
+	checkConfig := flag.Bool("check-config", false, "Check configs")
+	printVersion := flag.Bool("version", false, "Print version info")
+	query := flag.String("query", Config.Query, "待评审的 SQL 或 SQL 文件,如 SQL 中包含特殊字符建议使用文件名。")
+	listHeuristicRules := flag.Bool("list-heuristic-rules", Config.ListHeuristicRules, "ListHeuristicRules, 打印支持的评审规则列表")
+	listRewriteRules := flag.Bool("list-rewrite-rules", Config.ListRewriteRules, "ListRewriteRules, 打印支持的重写规则列表")
+	listTestSQLs := flag.Bool("list-test-sqls", Config.ListTestSqls, "ListTestSqls, 打印测试case用于测试")
+	listReportTypes := flag.Bool("list-report-types", Config.ListReportTypes, "ListReportTypes, 打印支持的报告输出类型")
+	verbose := flag.Bool("verbose", Config.Verbose, "Verbose")
+	dryrun := flag.Bool("dry-run", Config.DryRun, "是否在预演环境执行")
+	maxPrettySQLLength := flag.Int("max-pretty-sql-length", Config.MaxPrettySQLLength, "MaxPrettySQLLength, 超出该长度的SQL会转换成指纹输出")
+	// 一个不存在 log-level,用于更新 usage。
+	// 因为 vitess 里面也用了 flag,这些 vitess 的参数我们不需要关注
+	if !Config.Verbose && runtime.GOOS != "windows" {
+		flag.Usage = usage
+	}
+	flag.Parse()
+
+	Config.OnlineDSN = parseDSN(*onlineDSN, Config.OnlineDSN)
+	Config.TestDSN = parseDSN(*testDSN, Config.TestDSN)
+	Config.AllowOnlineAsTest = *allowOnlineAsTest
+	Config.DropTestTemporary = *dropTestTemporary
+	Config.CleanupTestDatabase = *cleanupTestDatabase
+	Config.OnlySyntaxCheck = *onlySyntaxCheck
+	Config.Profiling = *profiling
+	Config.Trace = *trace
+	Config.Explain = *explain
+	Config.Sampling = *sampling
+	Config.SamplingStatisticTarget = *samplingStatisticTarget
+	Config.ConnTimeOut = *connTimeOut
+	Config.QueryTimeOut = *queryTimeOut
+
+	Config.LogLevel = *logLevel
+	if strings.HasPrefix(*logOutput, "/") {
+		Config.LogOutput = *logOutput
+	} else {
+		if BaseDir == "" {
+			Config.LogOutput = *logOutput
+		} else {
+			if runtime.GOOS == "windows" {
+				Config.LogOutput = *logOutput
+			} else {
+				Config.LogOutput = BaseDir + "/" + *logOutput
+			}
+		}
+	}
+	Config.ReportType = strings.ToLower(*reportType)
+	Config.ReportCSS = *reportCSS
+	Config.ReportJavascript = *reportJavascript
+	Config.ReportTitle = *reportTitle
+	Config.MarkdownExtensions = *markdownExtensions
+	Config.MarkdownHTMLFlags = *markdownHTMLFlags
+	Config.IgnoreRules = strings.Split(*ignoreRules, ",")
+	Config.RewriteRules = strings.Split(*rewriteRules, ",")
+	*blackList = strings.TrimSpace(*blackList)
+	if strings.HasPrefix(*blackList, "/") || *blackList == "" {
+		Config.BlackList = *blackList
+	} else {
+		pwd, _ := os.Getwd()
+		Config.BlackList = pwd + "/" + *blackList
+	}
+	Config.MaxJoinTableCount = *maxJoinTableCount
+	Config.MaxGroupByColsCount = *maxGroupByColsCount
+	Config.MaxDistinctCount = *maxDistinctCount
+
+	if *maxIdxColsCount < 16 {
+		Config.MaxIdxColsCount = *maxIdxColsCount
+	} else {
+		Config.MaxIdxColsCount = 16
+	}
+
+	Config.MaxIdxBytesPerColumn = *maxIdxBytesPerColumn
+	Config.MaxIdxBytes = *maxIdxBytes
+	Config.TableAllowCharsets = strings.Split(strings.ToLower(*tableAllowCharsets), ",")
+	Config.TableAllowEngines = strings.Split(strings.ToLower(*tableAllowEngines), ",")
+	Config.MaxIdxCount = *maxIdxCount
+	Config.MaxColCount = *maxColCount
+	Config.MaxValueCount = *maxValueCount
+	Config.IdxPrefix = *idxPrefix
+	Config.UkPrefix = *ukPrefix
+	Config.MaxSubqueryDepth = *maxSubqueryDepth
+	Config.MaxTotalRows = *maxTotalRows
+	Config.MaxQueryCost = *maxQueryCost
+	Config.AllowDropIndex = *allowDropIdx
+	Config.MaxInCount = *maxInCount
+	Config.SpaghettiQueryLength = *spaghettiQueryLength
+	Config.Query = *query
+	Config.Delimiter = *delimiter
+
+	Config.ExplainSQLReportType = strings.ToLower(*explainSQLReportType)
+	Config.ExplainType = strings.ToLower(*explainType)
+	Config.ExplainFormat = strings.ToLower(*explainFormat)
+	Config.ExplainWarnSelectType = strings.Split(*explainWarnSelectType, ",")
+	Config.ExplainWarnAccessType = strings.Split(*explainWarnAccessType, ",")
+	Config.ExplainMaxKeyLength = *explainMaxKeyLength
+	Config.ExplainMinPossibleKeys = *explainMinPossibleKeys
+	Config.ExplainMaxRows = *explainMaxRows
+	Config.ExplainWarnExtra = strings.Split(*explainWarnExtra, ",")
+	Config.ExplainMaxFiltered = *explainMaxFiltered
+	Config.ExplainWarnScalability = strings.Split(*explainWarnScalability, ",")
+	Config.ShowWarnings = *showWarnings
+	Config.ShowLastQueryCost = *showLastQueryCost
+	Config.ListHeuristicRules = *listHeuristicRules
+	Config.ListRewriteRules = *listRewriteRules
+	Config.ListTestSqls = *listTestSQLs
+	Config.ListReportTypes = *listReportTypes
+	Config.Verbose = *verbose
+	Config.DryRun = *dryrun
+	Config.MaxPrettySQLLength = *maxPrettySQLLength
+	Config.MaxVarcharLength = *maxVarcharLength
+
+	PrintVersion = *printVersion
+	PrintConfig = *printConfig
+	CheckConfig = *checkConfig
+
+	hasParsed = true
+	return nil
+}
+
+// ParseConfig 加载配置文件和命令行参数
+func ParseConfig(configFile string) error {
+	var err error
+	var configs []string
+	// 指定了配置文件优先读配置文件,未指定配置文件按如下顺序加载,先找到哪个加载哪个
+	if configFile == "" {
+		configs = []string{
+			"/etc/soar.yaml",
+			BaseDir + "/etc/soar.yaml",
+			BaseDir + "/soar.yaml",
+		}
+	} else {
+		configs = []string{
+			configFile,
+		}
+	}
+
+	for _, config := range configs {
+		if _, err = os.Stat(config); err == nil {
+			err = Config.readConfigFile(config)
+			if err != nil {
+				Log.Error("ParseConfig Config.readConfigFile Error: %v", err)
+			}
+			// LogOutput now is "console", if add Log.Debug here will print into stdout anyway.
+			// Log.Debug("ParseConfig use config file: %s", config)
+			break
+		}
+	}
+
+	err = readCmdFlags()
+	if err != nil {
+		Log.Error("ParseConfig readCmdFlags Error: %v", err)
+		return err
+	}
+
+	// parse blacklist & ignore blacklist file parse error
+	if _, e := os.Stat(Config.BlackList); e == nil {
+		var blFd *os.File
+		blFd, err = os.Open(Config.BlackList)
+		if err == nil {
+			bl := bufio.NewReader(blFd)
+			for {
+				rule, e := bl.ReadString('\n')
+				if e != nil {
+					break
+				}
+				rule = strings.TrimSpace(rule)
+				if strings.HasPrefix(rule, "#") || rule == "" {
+					continue
+				}
+				BlackList = append(BlackList, rule)
+			}
+		}
+		defer blFd.Close()
+	}
+	LoggerInit()
+	return err
+}
+
+// ReportType 元数据结构定义
+type ReportType struct {
+	Name        string `json:"Name"`
+	Description string `json:"Description"`
+	Example     string `json:"Example"`
+}
+
+// ReportTypes 命令行-report-type支持的形式
+var ReportTypes = []ReportType{
+	{
+		Name:        "lint",
+		Description: "参考sqlint格式,以插件形式集成到代码编辑器,显示输出更加友好",
+		Example:     `soar -report-type lint -query test.sql`,
+	},
+	{
+		Name:        "markdown",
+		Description: "该格式为默认输出格式,以markdown格式展现,可以用网页浏览器插件直接打开,也可以用markdown编辑器打开",
+		Example:     `echo "select * from film" | soar`,
+	},
+	{
+		Name:        "rewrite",
+		Description: "SQL重写功能,配合-rewrite-rules参数一起使用,可以通过-list-rewrite-rules 查看所有支持的 SQL 重写规则",
+		Example:     `echo "select * from film" | soar -rewrite-rules star2columns,delimiter -report-type rewrite`,
+	},
+	{
+		Name:        "ast",
+		Description: "输出 SQL 的抽象语法树,主要用于测试",
+		Example:     `echo "select * from film" | soar -report-type ast`,
+	},
+	{
+		Name:        "tiast",
+		Description: "输出 SQL 的 TiDB抽象语法树,主要用于测试",
+		Example:     `echo "select * from film" | soar -report-type tiast`,
+	},
+	{
+		Name:        "fingerprint",
+		Description: "输出SQL的指纹",
+		Example:     `echo "select * from film where language_id=1" | soar -report-type fingerprint`,
+	},
+	{
+		Name:        "md2html",
+		Description: "markdown 格式转 html 格式小工具",
+		Example:     `soar -list-heuristic-rules | soar -report-type md2html > heuristic_rules.html`,
+	},
+	{
+		Name:        "explain-digest",
+		Description: "输入为EXPLAIN的表格,JSON 或 Vertical格式,对其进行分析,给出分析结果",
+		Example: `soar -report-type explain-digest << EOF
++----+-------------+-------+------+---------------+------+---------+------+------+-------+
+| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
++----+-------------+-------+------+---------------+------+---------+------+------+-------+
+|  1 | SIMPLE      | film  | ALL  | NULL          | NULL | NULL    | NULL | 1131 |       |
++----+-------------+-------+------+---------------+------+---------+------+------+-------+
+EOF`,
+	},
+	{
+		Name:        "duplicate-key-checker",
+		Description: "对 OnlineDsn 中指定的 database 进行索引重复检查",
+		Example:     `soar -report-type duplicate-key-checker -online-dsn user:password@127.0.0.1:3306/db`,
+	},
+	{
+		Name:        "html",
+		Description: "以HTML格式输出报表",
+		Example:     `echo "select * from film" | soar -report-type html`,
+	},
+	{
+		Name:        "json",
+		Description: "输出JSON格式报表,方便应用程序处理",
+		Example:     `echo "select * from film" | soar -report-type json`,
+	},
+	{
+		Name:        "tokenize",
+		Description: "对SQL进行切词,主要用于测试",
+		Example:     `echo "select * from film" | soar -report-type tokenize`,
+	},
+	{
+		Name:        "compress",
+		Description: "SQL压缩小工具,使用内置SQL压缩逻辑,测试中的功能",
+		Example: `echo "select
+*
+from
+  film" | soar -report-type compress`,
+	},
+	{
+		Name:        "pretty",
+		Description: "使用kr/pretty打印报告,主要用于测试",
+		Example:     `echo "select * from film" | soar -report-type pretty`,
+	},
+	{
+		Name:        "remove-comment",
+		Description: "去除SQL语句中的注释,支持单行多行注释的去除",
+		Example:     `echo "select/*comment*/ * from film" | soar -report-type remove-comment`,
+	},
+	{
+		Name:        "chardet",
+		Description: "猜测输入的 SQL 使用的字符集",
+		Example:     "echo '中文' | soar -report-type chardet",
+	},
+}
+
+// ListReportTypes 查看所有支持的report-type
+func ListReportTypes() {
+	switch Config.ReportType {
+	case "json":
+		js, err := json.MarshalIndent(ReportTypes, "", "  ")
+		if err == nil {
+			fmt.Println(string(js))
+		}
+	default:
+		fmt.Print("# 支持的报告类型\n\n[toc]\n\n")
+		for _, r := range ReportTypes {
+			fmt.Print("## ", MarkdownEscape(r.Name),
+				"\n* **Description**:", r.Description+"\n",
+				"\n* **Example**:\n\n```bash\n", r.Example, "\n```\n")
+		}
+	}
+}
+
+// ArgConfig get -config arg value from cli
+func ArgConfig() string {
+	var configFile string
+	if len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "-config") {
+		if os.Args[1] == "-config" && len(os.Args) > 2 {
+			if os.Args[2] == "=" && len(os.Args) > 3 {
+				// -config = soar.yaml not support
+				fmt.Println("wrong format, no space between '=', eg: -config=soar.yaml")
+			} else {
+				// -config soar.yaml
+				configFile = os.Args[2]
+			}
+			if strings.HasPrefix(configFile, "=") {
+				// -config =soar.yaml
+				configFile = strings.Split(configFile, "=")[1]
+			}
+		}
+		if strings.Contains(os.Args[1], "=") {
+			// -config=soar.yaml
+			configFile = strings.Split(os.Args[1], "=")[1]
+		}
+	} else {
+		for i, c := range os.Args {
+			if strings.HasPrefix(c, "-config") && i != 1 {
+				fmt.Println("-config must be the first arg")
+			}
+		}
+	}
+	return configFile
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/config_test.go b/vendor/github.com/XiaoMi/soar/common/config_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..48f5a7acdcda34fc26ad604e69d310c1c9244b34
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/config_test.go
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"flag"
+	"os"
+	"testing"
+
+	"github.com/kr/pretty"
+)
+
+var update = flag.Bool("update", false, "update .golden files")
+
+func TestParseConfig(t *testing.T) {
+	err := ParseConfig("")
+	if err != nil {
+		t.Error("sqlparser.Parse Error:", err)
+	}
+}
+
+func TestReadConfigFile(t *testing.T) {
+	if Config == nil {
+		Config = new(Configuration)
+	}
+	Config.readConfigFile("../soar.yaml")
+}
+
+func TestParseDSN(t *testing.T) {
+	var dsns = []string{
+		"",
+		"user:password@hostname:3307/database",
+		"user:password@hostname:3307",
+		"user:password@hostname:/database",
+		"user:password@:3307/database",
+		"user:password@",
+		"hostname:3307/database",
+		"@hostname:3307/database",
+		"@hostname",
+		"hostname",
+		"@/database",
+		"@hostname:3307",
+		"@:3307/database",
+		":3307/database",
+		"/database",
+	}
+
+	GoldenDiff(func() {
+		for _, dsn := range dsns {
+			pretty.Println(parseDSN(dsn, nil))
+		}
+	}, t.Name(), update)
+}
+
+func TestListReportTypes(t *testing.T) {
+	err := GoldenDiff(func() { ListReportTypes() }, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+}
+
+func TestArgConfig(t *testing.T) {
+	testArgs1 := [][]string{
+		{"soar", "-config", "=", "soar.yaml"},
+		{"soar", "-print-config", "-config", "soar.yaml"},
+	}
+	testArgs2 := [][]string{
+		{"soar", "-config", "soar.yaml"},
+		{"soar", "-config", "=soar.yaml"},
+		{"soar", "-config=soar.yaml"},
+	}
+	for _, args := range testArgs1 {
+		os.Args = args
+		configFile := ArgConfig()
+		if configFile != "" {
+			t.Errorf("should return '', but got %s", configFile)
+		}
+	}
+	for _, args := range testArgs2 {
+		os.Args = args
+		configFile := ArgConfig()
+		if configFile != "soar.yaml" {
+			t.Errorf("should return soar.yaml, but got %s", configFile)
+		}
+	}
+}
+
+func TestPrintConfiguration(t *testing.T) {
+	Config.Verbose = true
+	PrintConfiguration()
+
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/doc.go b/vendor/github.com/XiaoMi/soar/common/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..95b0973c588bc0d8ce2a54a6005dde2a1b5e71d5
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/doc.go
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common contain many useful functions for logging, formatting and so on.
+package common
diff --git a/vendor/github.com/XiaoMi/soar/common/example_test.go b/vendor/github.com/XiaoMi/soar/common/example_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..8baeb7100c19a78bc3e58731a5fe58824b8bcef5
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/example_test.go
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import "fmt"
+
+func ExampleFormatDSN() {
+	dsxExp := &dsn{
+		Addr:     "127.0.0.1:3306",
+		Schema:   "mysql",
+		User:     "root",
+		Password: "1t'sB1g3rt",
+		Charset:  "utf8mb4",
+		Disable:  false,
+	}
+
+	// 根据 &dsn 生成 dsnStr
+	fmt.Println(FormatDSN(dsxExp))
+
+	// Output: root:1t'sB1g3rt@127.0.0.1:3306/mysql?charset=utf8mb4
+}
+
+func ExampleIsColsPart() {
+	// IsColsPart() 会 按照顺序 检查两个Column队列是否是包含(或相等)关系。
+	a := []*Column{{Name: "1"}, {Name: "2"}, {Name: "3"}}
+	b := []*Column{{Name: "1"}, {Name: "2"}}
+	c := []*Column{{Name: "1"}, {Name: "3"}}
+	d := []*Column{{Name: "1"}, {Name: "2"}, {Name: "3"}, {Name: "4"}}
+
+	ab := IsColsPart(a, b)
+	ac := IsColsPart(a, c)
+	ad := IsColsPart(a, d)
+
+	fmt.Println(ab, ac, ad)
+	// Output: true false true
+}
+
+func ExampleSortedKey() {
+	ages := map[string]int{
+		"a": 1,
+		"c": 3,
+		"d": 4,
+		"b": 2,
+	}
+	for _, name := range SortedKey(ages) {
+		fmt.Print(ages[name])
+	}
+	// Output: 1234
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/logger.go b/vendor/github.com/XiaoMi/soar/common/logger.go
new file mode 100644
index 0000000000000000000000000000000000000000..6323fca2e4a15fdeeca532bc75ad90db6145cdec
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/logger.go
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"fmt"
+	"regexp"
+	"runtime"
+	"strings"
+
+	"github.com/astaxie/beego/logs"
+)
+
+// Log 使用 beego 的 log 库
+var Log *logs.BeeLogger
+
+// BaseDir 日志打印在binary的根路径
+var BaseDir string
+
+func init() {
+	Log = logs.NewLogger(0)
+	Log.EnableFuncCallDepth(true)
+}
+
+// LoggerInit Log配置初始化
+func LoggerInit() {
+	Log.SetLevel(Config.LogLevel)
+	func() { _ = Log.DelLogger(logs.AdapterFile) }()
+	err := Log.SetLogger(logs.AdapterFile, fmt.Sprintf(`{"filename":"%s","level":7,"maxlines":0,"maxsize":0,"daily":false,"maxdays":0}`, Config.LogOutput))
+	if err != nil {
+		fmt.Println(err.Error())
+	}
+}
+
+// Caller returns the caller of the function that called it :)
+// https://stackoverflow.com/questions/35212985/is-it-possible-get-information-about-caller-function-in-golang
+func Caller() string {
+	// we get the callers as uintptrs - but we just need 1
+	fpcs := make([]uintptr, 1)
+
+	// skip 3 levels to get to the caller of whoever called Caller()
+	n := runtime.Callers(3, fpcs)
+	if n == 0 {
+		return "n/a" // proper error her would be better
+	}
+
+	// get the info of the actual function that's in the pointer
+	fun := runtime.FuncForPC(fpcs[0] - 1)
+	if fun == nil {
+		return "n/a"
+	}
+
+	// return its name
+	return fun.Name()
+}
+
+// GetFunctionName 获取调当前函数名
+func GetFunctionName() string {
+	// Skip this function, and fetch the PC and file for its parent
+	pc, _, _, _ := runtime.Caller(1)
+	// Retrieve a Function object this functions parent
+	functionObject := runtime.FuncForPC(pc)
+	// Regex to extract just the function name (and not the module path)
+	extractFnName := regexp.MustCompile(`^.*\.(.*)$`)
+	fnName := extractFnName.ReplaceAllString(functionObject.Name(), "$1")
+	return fnName
+}
+
+// fileName get filename from path
+func fileName(original string) string {
+	i := strings.LastIndex(original, "/")
+	if i == -1 {
+		return original
+	}
+	return original[i+1:]
+}
+
+// LogIfError 简化if err != nil 打 Error 日志代码长度
+func LogIfError(err error, format string, v ...interface{}) {
+	if err != nil {
+		_, fn, line, _ := runtime.Caller(1)
+		if format == "" {
+			format = "[%s:%d] %s"
+			Log.Error(format, fileName(fn), line, err.Error())
+		} else {
+			format = "[%s:%d] " + format + " Error: %s"
+			Log.Error(format, fileName(fn), line, v, err.Error())
+		}
+	}
+}
+
+// LogIfWarn 简化if err != nil 打 Warn 日志代码长度
+func LogIfWarn(err error, format string, v ...interface{}) {
+	if err != nil {
+		_, fn, line, _ := runtime.Caller(1)
+		if format == "" {
+			format = "[%s:%d] %s"
+			Log.Warn(format, fileName(fn), line, err.Error())
+		} else {
+			format = "[%s:%d] " + format + " Error: %s"
+			Log.Warn(format, fileName(fn), line, v, err.Error())
+		}
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/logger_test.go b/vendor/github.com/XiaoMi/soar/common/logger_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..66e2706a7f011f19edac80715fd18283617a6a2a
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/logger_test.go
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"errors"
+	"testing"
+)
+
+func init() {
+	BaseDir = DevPath
+}
+
+func TestLogger(t *testing.T) {
+	Log.Info("info")
+	Log.Debug("debug")
+	Log.Warning("warning")
+	Log.Error("error")
+}
+
+func TestCaller(t *testing.T) {
+	caller := Caller()
+	if caller != "testing.tRunner" {
+		t.Error("get caller failed")
+	}
+}
+
+func TestGetFunctionName(t *testing.T) {
+	f := GetFunctionName()
+	if f != "TestGetFunctionName" {
+		t.Error("get functionname failed")
+	}
+}
+
+func TestIfError(t *testing.T) {
+	err := errors.New("test")
+	LogIfError(err, "")
+	LogIfError(err, "func %s", "func_test")
+}
+
+func TestIfWarn(t *testing.T) {
+	err := errors.New("test")
+	LogIfWarn(err, "")
+	LogIfWarn(err, "func %s", "func_test")
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/markdown.go b/vendor/github.com/XiaoMi/soar/common/markdown.go
new file mode 100644
index 0000000000000000000000000000000000000000..55d91c28b0ec99750c36e676f75bde4bba43cd08
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/markdown.go
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"encoding/base64"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"strings"
+
+	"github.com/russross/blackfriday"
+)
+
+// BuiltinCSS 内置HTML风格
+var BuiltinCSS = `
+a:link,a:visited{text-decoration:none}h3,h4{margin-top:2em}h5,h6{margin-top:20px}h3,h4,h5,h6{margin-bottom:.5em;color:#000}body,h1,h2,h3,h4,h5,h6{color:#000}ol,ul{margin:0 0 0 30px;padding:0 0 12px 6px}ol,ol ol{list-style-position:outside}table td p,table th p{margin-bottom:0}input,select{vertical-align:middle;padding:0}h5,h6,input,select{padding:0}hr,table,textarea{width:100%}body{margin:20px auto;width:800px;background-color:#fff;font:13px "Myriad Pro","Lucida Grande",Lucida,Verdana,sans-serif}h1,table th p{font-weight:700}a:link{color:#00f}a:visited{color:#00a}a:active,a:hover{color:#f60;text-decoration:underline}* html code,* html pre{font-size:101%}code,pre{font-size:11px;font-family:monaco,courier,consolas,monospace}pre{border:1px solid #c7cfd5;background:#f1f5f9;margin:20px 0;padding:8px;text-align:left}hr{color:#919699;size:1;noshade:"noshade"}h1,h2,h3,h4,h5,h6{font-family:"Myriad Pro","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:700}h1{margin-top:1em;margin-bottom:25px;font-size:30px}h2{margin-top:2.5em;font-size:24px;padding-bottom:2px;border-bottom:1px solid #919699}h3{font-size:17px}h4{font-size:15px}h5{font-size:13px}h6{font-size:11px}table td,table th{font-size:12px;border-bottom:1px solid #919699;border-right:1px solid #919699}p{margin-top:0;margin-bottom:10px}ul{list-style:square}li{margin-top:7px}ol{list-style-type:decimal}ol ol{list-style-type:lower-alpha;margin:7px 0 0 30px;padding:0 0 0 10px}ul ul{margin-left:40px;padding:0 0 0 6px}li>p{display:inline}li>a+p,li>p+p{display:block}table{border-top:1px solid #919699;border-left:1px solid #919699;border-spacing:0}table th{padding:4px 8px;background:#E2E2E2}table td{padding:8px;vertical-align:top}table td p+p,table td p+p+p{margin-top:5px}form{margin:0}button{margin:3px 0 10px}input{margin:0 0 5px}select{margin:0 0 3px}textarea{margin:0 0 10px}
+`
+
+// BuiltinJavascript 内置 SQL 美化 Javascript 脚本
+var BuiltinJavascript = `IWZ1bmN0aW9uKGUsRSl7Im9iamVjdCI9PXR5cGVvZiBleHBvcnRzJiYib2JqZWN0Ij09dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1FKCk6ImZ1bmN0aW9uIj09dHlwZW9mIGRlZmluZSYmZGVmaW5lLmFtZD9kZWZpbmUoW10sRSk6Im9iamVjdCI9PXR5cGVvZiBleHBvcnRzP2V4cG9ydHMuc3FsRm9ybWF0dGVyPUUoKTplLnNxbEZvcm1hdHRlcj1FKCl9KHRoaXMsZnVuY3Rpb24oKXtyZXR1cm4gZnVuY3Rpb24oZSl7ZnVuY3Rpb24gRShuKXtpZih0W25dKXJldHVybiB0W25dLmV4cG9ydHM7dmFyIHI9dFtuXT17ZXhwb3J0czp7fSxpZDpuLGxvYWRlZDohMX07cmV0dXJuIGVbbl0uY2FsbChyLmV4cG9ydHMscixyLmV4cG9ydHMsRSksci5sb2FkZWQ9ITAsci5leHBvcnRzfXZhciB0PXt9O3JldHVybiBFLm09ZSxFLmM9dCxFLnA9IiIsRSgwKX0oW2Z1bmN0aW9uKGUsRSx0KXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gbihlKXtyZXR1cm4gZSYmZS5fX2VzTW9kdWxlP2U6eyJkZWZhdWx0IjplfX1FLl9fZXNNb2R1bGU9ITA7dmFyIHI9dCgxOCksVD1uKHIpLFI9dCgxOSksbz1uKFIpLE49dCgyMCksQT1uKE4pLEk9dCgyMSksTz1uKEkpO0VbImRlZmF1bHQiXT17Zm9ybWF0OmZ1bmN0aW9uKGUsRSl7c3dpdGNoKEU9RXx8e30sRS5sYW5ndWFnZSl7Y2FzZSJkYjIiOnJldHVybiBuZXcgVFsiZGVmYXVsdCJdKEUpLmZvcm1hdChlKTtjYXNlIm4xcWwiOnJldHVybiBuZXcgb1siZGVmYXVsdCJdKEUpLmZvcm1hdChlKTtjYXNlInBsL3NxbCI6cmV0dXJuIG5ldyBBWyJkZWZhdWx0Il0oRSkuZm9ybWF0KGUpO2Nhc2Uic3FsIjpjYXNlIHZvaWQgMDpyZXR1cm4gbmV3IE9bImRlZmF1bHQiXShFKS5mb3JtYXQoZSk7ZGVmYXVsdDp0aHJvdyBFcnJvcigiVW5zdXBwb3J0ZWQgU1FMIGRpYWxlY3Q6ICIrRS5sYW5ndWFnZSl9fX0sZS5leHBvcnRzPUVbImRlZmF1bHQiXX0sZnVuY3Rpb24oZSxFKXsidXNlIHN0cmljdCI7RS5fX2VzTW9kdWxlPSEwLEVbImRlZmF1bHQiXT1mdW5jdGlvbihlLEUpe2lmKCEoZSBpbnN0YW5jZW9mIEUpKXRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbiIpfX0sZnVuY3Rpb24oZSxFLHQpe3ZhciBuPXQoMzkpLHI9Im9iamVjdCI9PXR5cGVvZiBzZWxmJiZzZWxmJiZzZWxmLk9iamVjdD09PU9iamVjdCYmc2VsZixUPW58fHJ8fEZ1bmN0aW9uKCJyZXR1cm4gdGhpcyIpKCk7ZS5leHBvcnRzPVR9LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUsRSl7dmFyIHQ9VChlLEUpO3JldHVybiByKHQpP3Q6dm9pZCAwfXZhciByPXQoMzMpLFQ9dCg0MSk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSx0KXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gbihlKXtyZXR1cm4gZSYmZS5fX2VzTW9kdWxlP2U6eyJkZWZhdWx0IjplfX1FLl9fZXNNb2R1bGU9ITA7dmFyIHI9dCgxKSxUPW4ociksUj10KDY2KSxvPW4oUiksTj10KDcpLEE9bihOKSxJPXQoMTUpLE89bihJKSxpPXQoMTYpLFM9bihpKSx1PXQoMTcpLEw9bih1KSxDPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gZShFLHQpeygwLFRbImRlZmF1bHQiXSkodGhpcyxlKSx0aGlzLmNmZz1FfHx7fSx0aGlzLmluZGVudGF0aW9uPW5ldyBPWyJkZWZhdWx0Il0odGhpcy5jZmcuaW5kZW50KSx0aGlzLmlubGluZUJsb2NrPW5ldyBTWyJkZWZhdWx0Il0sdGhpcy5wYXJhbXM9bmV3IExbImRlZmF1bHQiXSh0aGlzLmNmZy5wYXJhbXMpLHRoaXMudG9rZW5pemVyPXQsdGhpcy5wcmV2aW91c1Jlc2VydmVkV29yZD17fX1yZXR1cm4gZS5wcm90b3R5cGUuZm9ybWF0PWZ1bmN0aW9uKGUpe3ZhciBFPXRoaXMudG9rZW5pemVyLnRva2VuaXplKGUpLHQ9dGhpcy5nZXRGb3JtYXR0ZWRRdWVyeUZyb21Ub2tlbnMoRSk7cmV0dXJuIHQudHJpbSgpfSxlLnByb3RvdHlwZS5nZXRGb3JtYXR0ZWRRdWVyeUZyb21Ub2tlbnM9ZnVuY3Rpb24oZSl7dmFyIEU9dGhpcyx0PSIiO3JldHVybiBlLmZvckVhY2goZnVuY3Rpb24obixyKXtuLnR5cGUhPT1BWyJkZWZhdWx0Il0uV0hJVEVTUEFDRSYmKG4udHlwZT09PUFbImRlZmF1bHQiXS5MSU5FX0NPTU1FTlQ/dD1FLmZvcm1hdExpbmVDb21tZW50KG4sdCk6bi50eXBlPT09QVsiZGVmYXVsdCJdLkJMT0NLX0NPTU1FTlQ/dD1FLmZvcm1hdEJsb2NrQ29tbWVudChuLHQpOm4udHlwZT09PUFbImRlZmF1bHQiXS5SRVNFUlZFRF9UT1BMRVZFTD8odD1FLmZvcm1hdFRvcGxldmVsUmVzZXJ2ZWRXb3JkKG4sdCksRS5wcmV2aW91c1Jlc2VydmVkV29yZD1uKTpuLnR5cGU9PT1BWyJkZWZhdWx0Il0uUkVTRVJWRURfTkVXTElORT8odD1FLmZvcm1hdE5ld2xpbmVSZXNlcnZlZFdvcmQobix0KSxFLnByZXZpb3VzUmVzZXJ2ZWRXb3JkPW4pOm4udHlwZT09PUFbImRlZmF1bHQiXS5SRVNFUlZFRD8odD1FLmZvcm1hdFdpdGhTcGFjZXMobix0KSxFLnByZXZpb3VzUmVzZXJ2ZWRXb3JkPW4pOnQ9bi50eXBlPT09QVsiZGVmYXVsdCJdLk9QRU5fUEFSRU4/RS5mb3JtYXRPcGVuaW5nUGFyZW50aGVzZXMoZSxyLHQpOm4udHlwZT09PUFbImRlZmF1bHQiXS5DTE9TRV9QQVJFTj9FLmZvcm1hdENsb3NpbmdQYXJlbnRoZXNlcyhuLHQpOm4udHlwZT09PUFbImRlZmF1bHQiXS5QTEFDRUhPTERFUj9FLmZvcm1hdFBsYWNlaG9sZGVyKG4sdCk6IiwiPT09bi52YWx1ZT9FLmZvcm1hdENvbW1hKG4sdCk6IjoiPT09bi52YWx1ZT9FLmZvcm1hdFdpdGhTcGFjZUFmdGVyKG4sdCk6Ii4iPT09bi52YWx1ZXx8IjsiPT09bi52YWx1ZT9FLmZvcm1hdFdpdGhvdXRTcGFjZXMobix0KTpFLmZvcm1hdFdpdGhTcGFjZXMobix0KSl9KSx0fSxlLnByb3RvdHlwZS5mb3JtYXRMaW5lQ29tbWVudD1mdW5jdGlvbihlLEUpe3JldHVybiB0aGlzLmFkZE5ld2xpbmUoRStlLnZhbHVlKX0sZS5wcm90b3R5cGUuZm9ybWF0QmxvY2tDb21tZW50PWZ1bmN0aW9uKGUsRSl7cmV0dXJuIHRoaXMuYWRkTmV3bGluZSh0aGlzLmFkZE5ld2xpbmUoRSkrdGhpcy5pbmRlbnRDb21tZW50KGUudmFsdWUpKX0sZS5wcm90b3R5cGUuaW5kZW50Q29tbWVudD1mdW5jdGlvbihlKXtyZXR1cm4gZS5yZXBsYWNlKC9cbi9nLCJcbiIrdGhpcy5pbmRlbnRhdGlvbi5nZXRJbmRlbnQoKSl9LGUucHJvdG90eXBlLmZvcm1hdFRvcGxldmVsUmVzZXJ2ZWRXb3JkPWZ1bmN0aW9uKGUsRSl7cmV0dXJuIHRoaXMuaW5kZW50YXRpb24uZGVjcmVhc2VUb3BMZXZlbCgpLEU9dGhpcy5hZGROZXdsaW5lKEUpLHRoaXMuaW5kZW50YXRpb24uaW5jcmVhc2VUb3BsZXZlbCgpLEUrPXRoaXMuZXF1YWxpemVXaGl0ZXNwYWNlKGUudmFsdWUpLHRoaXMuYWRkTmV3bGluZShFKX0sZS5wcm90b3R5cGUuZm9ybWF0TmV3bGluZVJlc2VydmVkV29yZD1mdW5jdGlvbihlLEUpe3JldHVybiB0aGlzLmFkZE5ld2xpbmUoRSkrdGhpcy5lcXVhbGl6ZVdoaXRlc3BhY2UoZS52YWx1ZSkrIiAifSxlLnByb3RvdHlwZS5lcXVhbGl6ZVdoaXRlc3BhY2U9ZnVuY3Rpb24oZSl7cmV0dXJuIGUucmVwbGFjZSgvXHMrL2csIiAiKX0sZS5wcm90b3R5cGUuZm9ybWF0T3BlbmluZ1BhcmVudGhlc2VzPWZ1bmN0aW9uKGUsRSx0KXt2YXIgbj1lW0UtMV07cmV0dXJuIG4mJm4udHlwZSE9PUFbImRlZmF1bHQiXS5XSElURVNQQUNFJiZuLnR5cGUhPT1BWyJkZWZhdWx0Il0uT1BFTl9QQVJFTiYmKHQ9KDAsb1siZGVmYXVsdCJdKSh0KSksdCs9ZVtFXS52YWx1ZSx0aGlzLmlubGluZUJsb2NrLmJlZ2luSWZQb3NzaWJsZShlLEUpLHRoaXMuaW5saW5lQmxvY2suaXNBY3RpdmUoKXx8KHRoaXMuaW5kZW50YXRpb24uaW5jcmVhc2VCbG9ja0xldmVsKCksdD10aGlzLmFkZE5ld2xpbmUodCkpLHR9LGUucHJvdG90eXBlLmZvcm1hdENsb3NpbmdQYXJlbnRoZXNlcz1mdW5jdGlvbihlLEUpe3JldHVybiB0aGlzLmlubGluZUJsb2NrLmlzQWN0aXZlKCk/KHRoaXMuaW5saW5lQmxvY2suZW5kKCksdGhpcy5mb3JtYXRXaXRoU3BhY2VBZnRlcihlLEUpKToodGhpcy5pbmRlbnRhdGlvbi5kZWNyZWFzZUJsb2NrTGV2ZWwoKSx0aGlzLmZvcm1hdFdpdGhTcGFjZXMoZSx0aGlzLmFkZE5ld2xpbmUoRSkpKX0sZS5wcm90b3R5cGUuZm9ybWF0UGxhY2Vob2xkZXI9ZnVuY3Rpb24oZSxFKXtyZXR1cm4gRSt0aGlzLnBhcmFtcy5nZXQoZSkrIiAifSxlLnByb3RvdHlwZS5mb3JtYXRDb21tYT1mdW5jdGlvbihlLEUpe3JldHVybiBFPSgwLG9bImRlZmF1bHQiXSkoRSkrZS52YWx1ZSsiICIsdGhpcy5pbmxpbmVCbG9jay5pc0FjdGl2ZSgpP0U6L15MSU1JVCQvaS50ZXN0KHRoaXMucHJldmlvdXNSZXNlcnZlZFdvcmQudmFsdWUpP0U6dGhpcy5hZGROZXdsaW5lKEUpfSxlLnByb3RvdHlwZS5mb3JtYXRXaXRoU3BhY2VBZnRlcj1mdW5jdGlvbihlLEUpe3JldHVybigwLG9bImRlZmF1bHQiXSkoRSkrZS52YWx1ZSsiICJ9LGUucHJvdG90eXBlLmZvcm1hdFdpdGhvdXRTcGFjZXM9ZnVuY3Rpb24oZSxFKXtyZXR1cm4oMCxvWyJkZWZhdWx0Il0pKEUpK2UudmFsdWV9LGUucHJvdG90eXBlLmZvcm1hdFdpdGhTcGFjZXM9ZnVuY3Rpb24oZSxFKXtyZXR1cm4gRStlLnZhbHVlKyIgIn0sZS5wcm90b3R5cGUuYWRkTmV3bGluZT1mdW5jdGlvbihlKXtyZXR1cm4oMCxvWyJkZWZhdWx0Il0pKGUpKyJcbiIrdGhpcy5pbmRlbnRhdGlvbi5nZXRJbmRlbnQoKX0sZX0oKTtFWyJkZWZhdWx0Il09QyxlLmV4cG9ydHM9RVsiZGVmYXVsdCJdfSxmdW5jdGlvbihlLEUsdCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIG4oZSl7cmV0dXJuIGUmJmUuX19lc01vZHVsZT9lOnsiZGVmYXVsdCI6ZX19RS5fX2VzTW9kdWxlPSEwO3ZhciByPXQoMSksVD1uKHIpLFI9dCg1OCksbz1uKFIpLE49dCg1MyksQT1uKE4pLEk9dCg3KSxPPW4oSSksaT1mdW5jdGlvbigpe2Z1bmN0aW9uIGUoRSl7KDAsVFsiZGVmYXVsdCJdKSh0aGlzLGUpLHRoaXMuV0hJVEVTUEFDRV9SRUdFWD0vXihccyspLyx0aGlzLk5VTUJFUl9SRUdFWD0vXigoLVxzKik/WzAtOV0rKFwuWzAtOV0rKT98MHhbMC05YS1mQS1GXSt8MGJbMDFdKylcYi8sdGhpcy5PUEVSQVRPUl9SRUdFWD0vXighPXw8Pnw9PXw8PXw+PXwhPHwhPnxcfFx8fDo6fC0+PnwtPnx+flwqfH5+fCF+flwqfCF+fnx+XCp8IX5cKnwhfnwuKS8sdGhpcy5CTE9DS19DT01NRU5UX1JFR0VYPS9eKFwvXCpbXl0qPyg/OlwqXC98JCkpLyx0aGlzLkxJTkVfQ09NTUVOVF9SRUdFWD10aGlzLmNyZWF0ZUxpbmVDb21tZW50UmVnZXgoRS5saW5lQ29tbWVudFR5cGVzKSx0aGlzLlJFU0VSVkVEX1RPUExFVkVMX1JFR0VYPXRoaXMuY3JlYXRlUmVzZXJ2ZWRXb3JkUmVnZXgoRS5yZXNlcnZlZFRvcGxldmVsV29yZHMpLHRoaXMuUkVTRVJWRURfTkVXTElORV9SRUdFWD10aGlzLmNyZWF0ZVJlc2VydmVkV29yZFJlZ2V4KEUucmVzZXJ2ZWROZXdsaW5lV29yZHMpLHRoaXMuUkVTRVJWRURfUExBSU5fUkVHRVg9dGhpcy5jcmVhdGVSZXNlcnZlZFdvcmRSZWdleChFLnJlc2VydmVkV29yZHMpLHRoaXMuV09SRF9SRUdFWD10aGlzLmNyZWF0ZVdvcmRSZWdleChFLnNwZWNpYWxXb3JkQ2hhcnMpLHRoaXMuU1RSSU5HX1JFR0VYPXRoaXMuY3JlYXRlU3RyaW5nUmVnZXgoRS5zdHJpbmdUeXBlcyksdGhpcy5PUEVOX1BBUkVOX1JFR0VYPXRoaXMuY3JlYXRlUGFyZW5SZWdleChFLm9wZW5QYXJlbnMpLHRoaXMuQ0xPU0VfUEFSRU5fUkVHRVg9dGhpcy5jcmVhdGVQYXJlblJlZ2V4KEUuY2xvc2VQYXJlbnMpLHRoaXMuSU5ERVhFRF9QTEFDRUhPTERFUl9SRUdFWD10aGlzLmNyZWF0ZVBsYWNlaG9sZGVyUmVnZXgoRS5pbmRleGVkUGxhY2Vob2xkZXJUeXBlcywiWzAtOV0qIiksdGhpcy5JREVOVF9OQU1FRF9QTEFDRUhPTERFUl9SRUdFWD10aGlzLmNyZWF0ZVBsYWNlaG9sZGVyUmVnZXgoRS5uYW1lZFBsYWNlaG9sZGVyVHlwZXMsIlthLXpBLVowLTkuXyRdKyIpLHRoaXMuU1RSSU5HX05BTUVEX1BMQUNFSE9MREVSX1JFR0VYPXRoaXMuY3JlYXRlUGxhY2Vob2xkZXJSZWdleChFLm5hbWVkUGxhY2Vob2xkZXJUeXBlcyx0aGlzLmNyZWF0ZVN0cmluZ1BhdHRlcm4oRS5zdHJpbmdUeXBlcykpfXJldHVybiBlLnByb3RvdHlwZS5jcmVhdGVMaW5lQ29tbWVudFJlZ2V4PWZ1bmN0aW9uKGUpe3JldHVybiBSZWdFeHAoIl4oKD86IitlLm1hcChmdW5jdGlvbihlKXtyZXR1cm4oMCxBWyJkZWZhdWx0Il0pKGUpfSkuam9pbigifCIpKyIpLio/KD86XG58JCkpIil9LGUucHJvdG90eXBlLmNyZWF0ZVJlc2VydmVkV29yZFJlZ2V4PWZ1bmN0aW9uKGUpe3ZhciBFPWUuam9pbigifCIpLnJlcGxhY2UoLyAvZywiXFxzKyIpO3JldHVybiBSZWdFeHAoIl4oIitFKyIpXFxiIiwiaSIpfSxlLnByb3RvdHlwZS5jcmVhdGVXb3JkUmVnZXg9ZnVuY3Rpb24oKXt2YXIgZT1hcmd1bWVudHMubGVuZ3RoPjAmJnZvaWQgMCE9PWFyZ3VtZW50c1swXT9hcmd1bWVudHNbMF06W107cmV0dXJuIFJlZ0V4cCgiXihbXFx3IitlLmpvaW4oIiIpKyJdKykiKX0sZS5wcm90b3R5cGUuY3JlYXRlU3RyaW5nUmVnZXg9ZnVuY3Rpb24oZSl7cmV0dXJuIFJlZ0V4cCgiXigiK3RoaXMuY3JlYXRlU3RyaW5nUGF0dGVybihlKSsiKSIpfSxlLnByb3RvdHlwZS5jcmVhdGVTdHJpbmdQYXR0ZXJuPWZ1bmN0aW9uKGUpe3ZhciBFPXsiYGAiOiIoKGBbXmBdKigkfGApKSspIiwiW10iOiIoKFxcW1teXFxdXSooJHxcXF0pKShcXF1bXlxcXV0qKCR8XFxdKSkqKSIsJyIiJzonKCgiW14iXFxcXF0qKD86XFxcXC5bXiJcXFxcXSopKigifCQpKSspJywiJyciOiIoKCdbXidcXFxcXSooPzpcXFxcLlteJ1xcXFxdKikqKCd8JCkpKykiLCJOJyciOiIoKE4nW15OJ1xcXFxdKig/OlxcXFwuW15OJ1xcXFxdKikqKCd8JCkpKykifTtyZXR1cm4gZS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIEVbZV19KS5qb2luKCJ8Iil9LGUucHJvdG90eXBlLmNyZWF0ZVBhcmVuUmVnZXg9ZnVuY3Rpb24oZSl7dmFyIEU9dGhpcztyZXR1cm4gUmVnRXhwKCJeKCIrZS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIEUuZXNjYXBlUGFyZW4oZSl9KS5qb2luKCJ8IikrIikiLCJpIil9LGUucHJvdG90eXBlLmVzY2FwZVBhcmVuPWZ1bmN0aW9uKGUpe3JldHVybiAxPT09ZS5sZW5ndGg/KDAsQVsiZGVmYXVsdCJdKShlKToiXFxiIitlKyJcXGIifSxlLnByb3RvdHlwZS5jcmVhdGVQbGFjZWhvbGRlclJlZ2V4PWZ1bmN0aW9uKGUsRSl7aWYoKDAsb1siZGVmYXVsdCJdKShlKSlyZXR1cm4hMTt2YXIgdD1lLm1hcChBWyJkZWZhdWx0Il0pLmpvaW4oInwiKTtyZXR1cm4gUmVnRXhwKCJeKCg/OiIrdCsiKSg/OiIrRSsiKSkiKX0sZS5wcm90b3R5cGUudG9rZW5pemU9ZnVuY3Rpb24oZSl7Zm9yKHZhciBFPVtdLHQ9dm9pZCAwO2UubGVuZ3RoOyl0PXRoaXMuZ2V0TmV4dFRva2VuKGUsdCksZT1lLnN1YnN0cmluZyh0LnZhbHVlLmxlbmd0aCksRS5wdXNoKHQpO3JldHVybiBFfSxlLnByb3RvdHlwZS5nZXROZXh0VG9rZW49ZnVuY3Rpb24oZSxFKXtyZXR1cm4gdGhpcy5nZXRXaGl0ZXNwYWNlVG9rZW4oZSl8fHRoaXMuZ2V0Q29tbWVudFRva2VuKGUpfHx0aGlzLmdldFN0cmluZ1Rva2VuKGUpfHx0aGlzLmdldE9wZW5QYXJlblRva2VuKGUpfHx0aGlzLmdldENsb3NlUGFyZW5Ub2tlbihlKXx8dGhpcy5nZXRQbGFjZWhvbGRlclRva2VuKGUpfHx0aGlzLmdldE51bWJlclRva2VuKGUpfHx0aGlzLmdldFJlc2VydmVkV29yZFRva2VuKGUsRSl8fHRoaXMuZ2V0V29yZFRva2VuKGUpfHx0aGlzLmdldE9wZXJhdG9yVG9rZW4oZSl9LGUucHJvdG90eXBlLmdldFdoaXRlc3BhY2VUb2tlbj1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5nZXRUb2tlbk9uRmlyc3RNYXRjaCh7aW5wdXQ6ZSx0eXBlOk9bImRlZmF1bHQiXS5XSElURVNQQUNFLHJlZ2V4OnRoaXMuV0hJVEVTUEFDRV9SRUdFWH0pfSxlLnByb3RvdHlwZS5nZXRDb21tZW50VG9rZW49ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZ2V0TGluZUNvbW1lbnRUb2tlbihlKXx8dGhpcy5nZXRCbG9ja0NvbW1lbnRUb2tlbihlKX0sZS5wcm90b3R5cGUuZ2V0TGluZUNvbW1lbnRUb2tlbj1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5nZXRUb2tlbk9uRmlyc3RNYXRjaCh7aW5wdXQ6ZSx0eXBlOk9bImRlZmF1bHQiXS5MSU5FX0NPTU1FTlQscmVnZXg6dGhpcy5MSU5FX0NPTU1FTlRfUkVHRVh9KX0sZS5wcm90b3R5cGUuZ2V0QmxvY2tDb21tZW50VG9rZW49ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZ2V0VG9rZW5PbkZpcnN0TWF0Y2goe2lucHV0OmUsdHlwZTpPWyJkZWZhdWx0Il0uQkxPQ0tfQ09NTUVOVCxyZWdleDp0aGlzLkJMT0NLX0NPTU1FTlRfUkVHRVh9KX0sZS5wcm90b3R5cGUuZ2V0U3RyaW5nVG9rZW49ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZ2V0VG9rZW5PbkZpcnN0TWF0Y2goe2lucHV0OmUsdHlwZTpPWyJkZWZhdWx0Il0uU1RSSU5HLHJlZ2V4OnRoaXMuU1RSSU5HX1JFR0VYfSl9LGUucHJvdG90eXBlLmdldE9wZW5QYXJlblRva2VuPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmdldFRva2VuT25GaXJzdE1hdGNoKHtpbnB1dDplLHR5cGU6T1siZGVmYXVsdCJdLk9QRU5fUEFSRU4scmVnZXg6dGhpcy5PUEVOX1BBUkVOX1JFR0VYfSl9LGUucHJvdG90eXBlLmdldENsb3NlUGFyZW5Ub2tlbj1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5nZXRUb2tlbk9uRmlyc3RNYXRjaCh7aW5wdXQ6ZSx0eXBlOk9bImRlZmF1bHQiXS5DTE9TRV9QQVJFTixyZWdleDp0aGlzLkNMT1NFX1BBUkVOX1JFR0VYfSl9LGUucHJvdG90eXBlLmdldFBsYWNlaG9sZGVyVG9rZW49ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZ2V0SWRlbnROYW1lZFBsYWNlaG9sZGVyVG9rZW4oZSl8fHRoaXMuZ2V0U3RyaW5nTmFtZWRQbGFjZWhvbGRlclRva2VuKGUpfHx0aGlzLmdldEluZGV4ZWRQbGFjZWhvbGRlclRva2VuKGUpfSxlLnByb3RvdHlwZS5nZXRJZGVudE5hbWVkUGxhY2Vob2xkZXJUb2tlbj1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5nZXRQbGFjZWhvbGRlclRva2VuV2l0aEtleSh7aW5wdXQ6ZSxyZWdleDp0aGlzLklERU5UX05BTUVEX1BMQUNFSE9MREVSX1JFR0VYLHBhcnNlS2V5OmZ1bmN0aW9uKGUpe3JldHVybiBlLnNsaWNlKDEpfX0pfSxlLnByb3RvdHlwZS5nZXRTdHJpbmdOYW1lZFBsYWNlaG9sZGVyVG9rZW49ZnVuY3Rpb24oZSl7dmFyIEU9dGhpcztyZXR1cm4gdGhpcy5nZXRQbGFjZWhvbGRlclRva2VuV2l0aEtleSh7aW5wdXQ6ZSxyZWdleDp0aGlzLlNUUklOR19OQU1FRF9QTEFDRUhPTERFUl9SRUdFWCxwYXJzZUtleTpmdW5jdGlvbihlKXtyZXR1cm4gRS5nZXRFc2NhcGVkUGxhY2Vob2xkZXJLZXkoe2tleTplLnNsaWNlKDIsLTEpLHF1b3RlQ2hhcjplLnNsaWNlKC0xKX0pfX0pfSxlLnByb3RvdHlwZS5nZXRJbmRleGVkUGxhY2Vob2xkZXJUb2tlbj1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5nZXRQbGFjZWhvbGRlclRva2VuV2l0aEtleSh7aW5wdXQ6ZSxyZWdleDp0aGlzLklOREVYRURfUExBQ0VIT0xERVJfUkVHRVgscGFyc2VLZXk6ZnVuY3Rpb24oZSl7cmV0dXJuIGUuc2xpY2UoMSl9fSl9LGUucHJvdG90eXBlLmdldFBsYWNlaG9sZGVyVG9rZW5XaXRoS2V5PWZ1bmN0aW9uKGUpe3ZhciBFPWUuaW5wdXQsdD1lLnJlZ2V4LG49ZS5wYXJzZUtleSxyPXRoaXMuZ2V0VG9rZW5PbkZpcnN0TWF0Y2goe2lucHV0OkUscmVnZXg6dCx0eXBlOk9bImRlZmF1bHQiXS5QTEFDRUhPTERFUn0pO3JldHVybiByJiYoci5rZXk9bihyLnZhbHVlKSkscn0sZS5wcm90b3R5cGUuZ2V0RXNjYXBlZFBsYWNlaG9sZGVyS2V5PWZ1bmN0aW9uKGUpe3ZhciBFPWUua2V5LHQ9ZS5xdW90ZUNoYXI7cmV0dXJuIEUucmVwbGFjZShSZWdFeHAoKDAsQVsiZGVmYXVsdCJdKSgiXFwiKSt0LCJnIiksdCl9LGUucHJvdG90eXBlLmdldE51bWJlclRva2VuPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmdldFRva2VuT25GaXJzdE1hdGNoKHtpbnB1dDplLHR5cGU6T1siZGVmYXVsdCJdLk5VTUJFUixyZWdleDp0aGlzLk5VTUJFUl9SRUdFWH0pfSxlLnByb3RvdHlwZS5nZXRPcGVyYXRvclRva2VuPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmdldFRva2VuT25GaXJzdE1hdGNoKHtpbnB1dDplLHR5cGU6T1siZGVmYXVsdCJdLk9QRVJBVE9SLHJlZ2V4OnRoaXMuT1BFUkFUT1JfUkVHRVh9KX0sZS5wcm90b3R5cGUuZ2V0UmVzZXJ2ZWRXb3JkVG9rZW49ZnVuY3Rpb24oZSxFKXtpZighRXx8IUUudmFsdWV8fCIuIiE9PUUudmFsdWUpcmV0dXJuIHRoaXMuZ2V0VG9wbGV2ZWxSZXNlcnZlZFRva2VuKGUpfHx0aGlzLmdldE5ld2xpbmVSZXNlcnZlZFRva2VuKGUpfHx0aGlzLmdldFBsYWluUmVzZXJ2ZWRUb2tlbihlKX0sZS5wcm90b3R5cGUuZ2V0VG9wbGV2ZWxSZXNlcnZlZFRva2VuPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmdldFRva2VuT25GaXJzdE1hdGNoKHtpbnB1dDplLHR5cGU6T1siZGVmYXVsdCJdLlJFU0VSVkVEX1RPUExFVkVMLHJlZ2V4OnRoaXMuUkVTRVJWRURfVE9QTEVWRUxfUkVHRVh9KX0sZS5wcm90b3R5cGUuZ2V0TmV3bGluZVJlc2VydmVkVG9rZW49ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuZ2V0VG9rZW5PbkZpcnN0TWF0Y2goe2lucHV0OmUsdHlwZTpPWyJkZWZhdWx0Il0uUkVTRVJWRURfTkVXTElORSxyZWdleDp0aGlzLlJFU0VSVkVEX05FV0xJTkVfUkVHRVh9KX0sZS5wcm90b3R5cGUuZ2V0UGxhaW5SZXNlcnZlZFRva2VuPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmdldFRva2VuT25GaXJzdE1hdGNoKHtpbnB1dDplLHR5cGU6T1siZGVmYXVsdCJdLlJFU0VSVkVELHJlZ2V4OnRoaXMuUkVTRVJWRURfUExBSU5fUkVHRVh9KX0sZS5wcm90b3R5cGUuZ2V0V29yZFRva2VuPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLmdldFRva2VuT25GaXJzdE1hdGNoKHtpbnB1dDplLHR5cGU6T1siZGVmYXVsdCJdLldPUkQscmVnZXg6dGhpcy5XT1JEX1JFR0VYfSl9LGUucHJvdG90eXBlLmdldFRva2VuT25GaXJzdE1hdGNoPWZ1bmN0aW9uKGUpe3ZhciBFPWUuaW5wdXQsdD1lLnR5cGUsbj1lLnJlZ2V4LHI9RS5tYXRjaChuKTtpZihyKXJldHVybnt0eXBlOnQsdmFsdWU6clsxXX19LGV9KCk7RVsiZGVmYXVsdCJdPWksZS5leHBvcnRzPUVbImRlZmF1bHQiXX0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUpe3ZhciBFPXR5cGVvZiBlO3JldHVybiBudWxsIT1lJiYoIm9iamVjdCI9PUV8fCJmdW5jdGlvbiI9PUUpfWUuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUpeyJ1c2Ugc3RyaWN0IjtFLl9fZXNNb2R1bGU9ITAsRVsiZGVmYXVsdCJdPXtXSElURVNQQUNFOiJ3aGl0ZXNwYWNlIixXT1JEOiJ3b3JkIixTVFJJTkc6InN0cmluZyIsUkVTRVJWRUQ6InJlc2VydmVkIixSRVNFUlZFRF9UT1BMRVZFTDoicmVzZXJ2ZWQtdG9wbGV2ZWwiLFJFU0VSVkVEX05FV0xJTkU6InJlc2VydmVkLW5ld2xpbmUiLE9QRVJBVE9SOiJvcGVyYXRvciIsT1BFTl9QQVJFTjoib3Blbi1wYXJlbiIsQ0xPU0VfUEFSRU46ImNsb3NlLXBhcmVuIixMSU5FX0NPTU1FTlQ6ImxpbmUtY29tbWVudCIsQkxPQ0tfQ09NTUVOVDoiYmxvY2stY29tbWVudCIsTlVNQkVSOiJudW1iZXIiLFBMQUNFSE9MREVSOiJwbGFjZWhvbGRlciJ9LGUuZXhwb3J0cz1FWyJkZWZhdWx0Il19LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUpe3JldHVybiBudWxsIT1lJiZUKGUubGVuZ3RoKSYmIXIoZSl9dmFyIHI9dCgxMiksVD10KDU5KTtlLmV4cG9ydHM9bn0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSl7cmV0dXJuIG51bGw9PWU/IiI6cihlKX12YXIgcj10KDEwKTtlLmV4cG9ydHM9bn0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSl7aWYoInN0cmluZyI9PXR5cGVvZiBlKXJldHVybiBlO2lmKFQoZSkpcmV0dXJuIE4/Ti5jYWxsKGUpOiIiO3ZhciBFPWUrIiI7cmV0dXJuIjAiPT1FJiYxL2U9PS1SPyItMCI6RX12YXIgcj10KDI2KSxUPXQoMTQpLFI9MS8wLG89cj9yLnByb3RvdHlwZTp2b2lkIDAsTj1vP28udG9TdHJpbmc6dm9pZCAwO2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUpe2Z1bmN0aW9uIHQoZSl7aWYobnVsbCE9ZSl7dHJ5e3JldHVybiByLmNhbGwoZSl9Y2F0Y2goRSl7fXRyeXtyZXR1cm4gZSsiIn1jYXRjaChFKXt9fXJldHVybiIifXZhciBuPUZ1bmN0aW9uLnByb3RvdHlwZSxyPW4udG9TdHJpbmc7ZS5leHBvcnRzPXR9LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUpe3ZhciBFPXIoZSk/Ti5jYWxsKGUpOiIiO3JldHVybiBFPT1UfHxFPT1SfXZhciByPXQoNiksVD0iW29iamVjdCBGdW5jdGlvbl0iLFI9IltvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dIixvPU9iamVjdC5wcm90b3R5cGUsTj1vLnRvU3RyaW5nO2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUpe2Z1bmN0aW9uIHQoZSl7cmV0dXJuIG51bGwhPWUmJiJvYmplY3QiPT10eXBlb2YgZX1lLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSl7cmV0dXJuInN5bWJvbCI9PXR5cGVvZiBlfHxyKGUpJiZvLmNhbGwoZSk9PVR9dmFyIHI9dCgxMyksVD0iW29iamVjdCBTeW1ib2xdIixSPU9iamVjdC5wcm90b3R5cGUsbz1SLnRvU3RyaW5nO2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUsdCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIG4oZSl7cmV0dXJuIGUmJmUuX19lc01vZHVsZT9lOnsiZGVmYXVsdCI6ZX19RS5fX2VzTW9kdWxlPSEwO3ZhciByPXQoMSksVD1uKHIpLFI9dCg2MSksbz1uKFIpLE49dCg2MCksQT1uKE4pLEk9InRvcC1sZXZlbCIsTz0iYmxvY2stbGV2ZWwiLGk9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKEUpeygwLFRbImRlZmF1bHQiXSkodGhpcyxlKSx0aGlzLmluZGVudD1FfHwiICAiLHRoaXMuaW5kZW50VHlwZXM9W119cmV0dXJuIGUucHJvdG90eXBlLmdldEluZGVudD1mdW5jdGlvbigpe3JldHVybigwLG9bImRlZmF1bHQiXSkodGhpcy5pbmRlbnQsdGhpcy5pbmRlbnRUeXBlcy5sZW5ndGgpfSxlLnByb3RvdHlwZS5pbmNyZWFzZVRvcGxldmVsPWZ1bmN0aW9uKCl7dGhpcy5pbmRlbnRUeXBlcy5wdXNoKEkpfSxlLnByb3RvdHlwZS5pbmNyZWFzZUJsb2NrTGV2ZWw9ZnVuY3Rpb24oKXt0aGlzLmluZGVudFR5cGVzLnB1c2goTyl9LGUucHJvdG90eXBlLmRlY3JlYXNlVG9wTGV2ZWw9ZnVuY3Rpb24oKXsoMCxBWyJkZWZhdWx0Il0pKHRoaXMuaW5kZW50VHlwZXMpPT09SSYmdGhpcy5pbmRlbnRUeXBlcy5wb3AoKX0sZS5wcm90b3R5cGUuZGVjcmVhc2VCbG9ja0xldmVsPWZ1bmN0aW9uKCl7Zm9yKDt0aGlzLmluZGVudFR5cGVzLmxlbmd0aD4wOyl7dmFyIGU9dGhpcy5pbmRlbnRUeXBlcy5wb3AoKTtpZihlIT09SSlicmVha319LGV9KCk7RVsiZGVmYXVsdCJdPWksZS5leHBvcnRzPUVbImRlZmF1bHQiXX0sZnVuY3Rpb24oZSxFLHQpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBuKGUpe3JldHVybiBlJiZlLl9fZXNNb2R1bGU/ZTp7ImRlZmF1bHQiOmV9fUUuX19lc01vZHVsZT0hMDt2YXIgcj10KDEpLFQ9bihyKSxSPXQoNyksbz1uKFIpLE49NTAsQT1mdW5jdGlvbigpe2Z1bmN0aW9uIGUoKXsoMCxUWyJkZWZhdWx0Il0pKHRoaXMsZSksdGhpcy5sZXZlbD0wfXJldHVybiBlLnByb3RvdHlwZS5iZWdpbklmUG9zc2libGU9ZnVuY3Rpb24oZSxFKXswPT09dGhpcy5sZXZlbCYmdGhpcy5pc0lubGluZUJsb2NrKGUsRSk/dGhpcy5sZXZlbD0xOnRoaXMubGV2ZWw+MD90aGlzLmxldmVsKys6dGhpcy5sZXZlbD0wfSxlLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24oKXt0aGlzLmxldmVsLS19LGUucHJvdG90eXBlLmlzQWN0aXZlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGV2ZWw+MH0sZS5wcm90b3R5cGUuaXNJbmxpbmVCbG9jaz1mdW5jdGlvbihlLEUpe2Zvcih2YXIgdD0wLG49MCxyPUU7ZS5sZW5ndGg+cjtyKyspe3ZhciBUPWVbcl07aWYodCs9VC52YWx1ZS5sZW5ndGgsdD5OKXJldHVybiExO2lmKFQudHlwZT09PW9bImRlZmF1bHQiXS5PUEVOX1BBUkVOKW4rKztlbHNlIGlmKFQudHlwZT09PW9bImRlZmF1bHQiXS5DTE9TRV9QQVJFTiYmKG4tLSwwPT09bikpcmV0dXJuITA7aWYodGhpcy5pc0ZvcmJpZGRlblRva2VuKFQpKXJldHVybiExfXJldHVybiExfSxlLnByb3RvdHlwZS5pc0ZvcmJpZGRlblRva2VuPWZ1bmN0aW9uKGUpe3ZhciBFPWUudHlwZSx0PWUudmFsdWU7cmV0dXJuIEU9PT1vWyJkZWZhdWx0Il0uUkVTRVJWRURfVE9QTEVWRUx8fEU9PT1vWyJkZWZhdWx0Il0uUkVTRVJWRURfTkVXTElORXx8RT09PW9bImRlZmF1bHQiXS5DT01NRU5UfHxFPT09b1siZGVmYXVsdCJdLkJMT0NLX0NPTU1FTlR8fCI7Ij09PXR9LGV9KCk7RVsiZGVmYXVsdCJdPUEsZS5leHBvcnRzPUVbImRlZmF1bHQiXX0sZnVuY3Rpb24oZSxFLHQpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBuKGUpe3JldHVybiBlJiZlLl9fZXNNb2R1bGU/ZTp7ImRlZmF1bHQiOmV9fUUuX19lc01vZHVsZT0hMDt2YXIgcj10KDEpLFQ9bihyKSxSPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gZShFKXsoMCxUWyJkZWZhdWx0Il0pKHRoaXMsZSksdGhpcy5wYXJhbXM9RSx0aGlzLmluZGV4PTB9cmV0dXJuIGUucHJvdG90eXBlLmdldD1mdW5jdGlvbihlKXt2YXIgRT1lLmtleSx0PWUudmFsdWU7cmV0dXJuIHRoaXMucGFyYW1zP0U/dGhpcy5wYXJhbXNbRV06dGhpcy5wYXJhbXNbdGhpcy5pbmRleCsrXTp0fSxlfSgpO0VbImRlZmF1bHQiXT1SLGUuZXhwb3J0cz1FWyJkZWZhdWx0Il19LGZ1bmN0aW9uKGUsRSx0KXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gbihlKXtyZXR1cm4gZSYmZS5fX2VzTW9kdWxlP2U6eyJkZWZhdWx0IjplfX1FLl9fZXNNb2R1bGU9ITA7dmFyIHI9dCgxKSxUPW4ociksUj10KDQpLG89bihSKSxOPXQoNSksQT1uKE4pLEk9WyJBQlMiLCJBQ1RJVkFURSIsIkFMSUFTIiwiQUxMIiwiQUxMT0NBVEUiLCJBTExPVyIsIkFMVEVSIiwiQU5ZIiwiQVJFIiwiQVJSQVkiLCJBUyIsIkFTQyIsIkFTRU5TSVRJVkUiLCJBU1NPQ0lBVEUiLCJBU1VUSU1FIiwiQVNZTU1FVFJJQyIsIkFUIiwiQVRPTUlDIiwiQVRUUklCVVRFUyIsIkFVRElUIiwiQVVUSE9SSVpBVElPTiIsIkFVWCIsIkFVWElMSUFSWSIsIkFWRyIsIkJFRk9SRSIsIkJFR0lOIiwiQkVUV0VFTiIsIkJJR0lOVCIsIkJJTkFSWSIsIkJMT0IiLCJCT09MRUFOIiwiQk9USCIsIkJVRkZFUlBPT0wiLCJCWSIsIkNBQ0hFIiwiQ0FMTCIsIkNBTExFRCIsIkNBUFRVUkUiLCJDQVJESU5BTElUWSIsIkNBU0NBREVEIiwiQ0FTRSIsIkNBU1QiLCJDQ1NJRCIsIkNFSUwiLCJDRUlMSU5HIiwiQ0hBUiIsIkNIQVJBQ1RFUiIsIkNIQVJBQ1RFUl9MRU5HVEgiLCJDSEFSX0xFTkdUSCIsIkNIRUNLIiwiQ0xPQiIsIkNMT05FIiwiQ0xPU0UiLCJDTFVTVEVSIiwiQ09BTEVTQ0UiLCJDT0xMQVRFIiwiQ09MTEVDVCIsIkNPTExFQ1RJT04iLCJDT0xMSUQiLCJDT0xVTU4iLCJDT01NRU5UIiwiQ09NTUlUIiwiQ09OQ0FUIiwiQ09ORElUSU9OIiwiQ09OTkVDVCIsIkNPTk5FQ1RJT04iLCJDT05TVFJBSU5UIiwiQ09OVEFJTlMiLCJDT05USU5VRSIsIkNPTlZFUlQiLCJDT1JSIiwiQ09SUkVTUE9ORElORyIsIkNPVU5UIiwiQ09VTlRfQklHIiwiQ09WQVJfUE9QIiwiQ09WQVJfU0FNUCIsIkNSRUFURSIsIkNST1NTIiwiQ1VCRSIsIkNVTUVfRElTVCIsIkNVUlJFTlQiLCJDVVJSRU5UX0RBVEUiLCJDVVJSRU5UX0RFRkFVTFRfVFJBTlNGT1JNX0dST1VQIiwiQ1VSUkVOVF9MQ19DVFlQRSIsIkNVUlJFTlRfUEFUSCIsIkNVUlJFTlRfUk9MRSIsIkNVUlJFTlRfU0NIRU1BIiwiQ1VSUkVOVF9TRVJWRVIiLCJDVVJSRU5UX1RJTUUiLCJDVVJSRU5UX1RJTUVTVEFNUCIsIkNVUlJFTlRfVElNRVpPTkUiLCJDVVJSRU5UX1RSQU5TRk9STV9HUk9VUF9GT1JfVFlQRSIsIkNVUlJFTlRfVVNFUiIsIkNVUlNPUiIsIkNZQ0xFIiwiREFUQSIsIkRBVEFCQVNFIiwiREFUQVBBUlRJVElPTk5BTUUiLCJEQVRBUEFSVElUSU9OTlVNIiwiREFURSIsIkRBWSIsIkRBWVMiLCJEQjJHRU5FUkFMIiwiREIyR0VOUkwiLCJEQjJTUUwiLCJEQklORk8iLCJEQlBBUlRJVElPTk5BTUUiLCJEQlBBUlRJVElPTk5VTSIsIkRFQUxMT0NBVEUiLCJERUMiLCJERUNJTUFMIiwiREVDTEFSRSIsIkRFRkFVTFQiLCJERUZBVUxUUyIsIkRFRklOSVRJT04iLCJERUxFVEUiLCJERU5TRVJBTksiLCJERU5TRV9SQU5LIiwiREVSRUYiLCJERVNDUklCRSIsIkRFU0NSSVBUT1IiLCJERVRFUk1JTklTVElDIiwiRElBR05PU1RJQ1MiLCJESVNBQkxFIiwiRElTQUxMT1ciLCJESVNDT05ORUNUIiwiRElTVElOQ1QiLCJETyIsIkRPQ1VNRU5UIiwiRE9VQkxFIiwiRFJPUCIsIkRTU0laRSIsIkRZTkFNSUMiLCJFQUNIIiwiRURJVFBST0MiLCJFTEVNRU5UIiwiRUxTRSIsIkVMU0VJRiIsIkVOQUJMRSIsIkVOQ09ESU5HIiwiRU5DUllQVElPTiIsIkVORCIsIkVORC1FWEVDIiwiRU5ESU5HIiwiRVJBU0UiLCJFU0NBUEUiLCJFVkVSWSIsIkVYQ0VQVElPTiIsIkVYQ0xVRElORyIsIkVYQ0xVU0lWRSIsIkVYRUMiLCJFWEVDVVRFIiwiRVhJU1RTIiwiRVhJVCIsIkVYUCIsIkVYUExBSU4iLCJFWFRFTkRFRCIsIkVYVEVSTkFMIiwiRVhUUkFDVCIsIkZBTFNFIiwiRkVOQ0VEIiwiRkVUQ0giLCJGSUVMRFBST0MiLCJGSUxFIiwiRklMVEVSIiwiRklOQUwiLCJGSVJTVCIsIkZMT0FUIiwiRkxPT1IiLCJGT1IiLCJGT1JFSUdOIiwiRlJFRSIsIkZVTEwiLCJGVU5DVElPTiIsIkZVU0lPTiIsIkdFTkVSQUwiLCJHRU5FUkFURUQiLCJHRVQiLCJHTE9CQUwiLCJHT1RPIiwiR1JBTlQiLCJHUkFQSElDIiwiR1JPVVAiLCJHUk9VUElORyIsIkhBTkRMRVIiLCJIQVNIIiwiSEFTSEVEX1ZBTFVFIiwiSElOVCIsIkhPTEQiLCJIT1VSIiwiSE9VUlMiLCJJREVOVElUWSIsIklGIiwiSU1NRURJQVRFIiwiSU4iLCJJTkNMVURJTkciLCJJTkNMVVNJVkUiLCJJTkNSRU1FTlQiLCJJTkRFWCIsIklORElDQVRPUiIsIklORElDQVRPUlMiLCJJTkYiLCJJTkZJTklUWSIsIklOSEVSSVQiLCJJTk5FUiIsIklOT1VUIiwiSU5TRU5TSVRJVkUiLCJJTlNFUlQiLCJJTlQiLCJJTlRFR0VSIiwiSU5URUdSSVRZIiwiSU5URVJTRUNUSU9OIiwiSU5URVJWQUwiLCJJTlRPIiwiSVMiLCJJU09CSUQiLCJJU09MQVRJT04iLCJJVEVSQVRFIiwiSkFSIiwiSkFWQSIsIktFRVAiLCJLRVkiLCJMQUJFTCIsIkxBTkdVQUdFIiwiTEFSR0UiLCJMQVRFUkFMIiwiTENfQ1RZUEUiLCJMRUFESU5HIiwiTEVBVkUiLCJMRUZUIiwiTElLRSIsIkxJTktUWVBFIiwiTE4iLCJMT0NBTCIsIkxPQ0FMREFURSIsIkxPQ0FMRSIsIkxPQ0FMVElNRSIsIkxPQ0FMVElNRVNUQU1QIiwiTE9DQVRPUiIsIkxPQ0FUT1JTIiwiTE9DSyIsIkxPQ0tNQVgiLCJMT0NLU0laRSIsIkxPTkciLCJMT09QIiwiTE9XRVIiLCJNQUlOVEFJTkVEIiwiTUFUQ0giLCJNQVRFUklBTElaRUQiLCJNQVgiLCJNQVhWQUxVRSIsIk1FTUJFUiIsIk1FUkdFIiwiTUVUSE9EIiwiTUlDUk9TRUNPTkQiLCJNSUNST1NFQ09ORFMiLCJNSU4iLCJNSU5VVEUiLCJNSU5VVEVTIiwiTUlOVkFMVUUiLCJNT0QiLCJNT0RFIiwiTU9ESUZJRVMiLCJNT0RVTEUiLCJNT05USCIsIk1PTlRIUyIsIk1VTFRJU0VUIiwiTkFOIiwiTkFUSU9OQUwiLCJOQVRVUkFMIiwiTkNIQVIiLCJOQ0xPQiIsIk5FVyIsIk5FV19UQUJMRSIsIk5FWFRWQUwiLCJOTyIsIk5PQ0FDSEUiLCJOT0NZQ0xFIiwiTk9ERU5BTUUiLCJOT0RFTlVNQkVSIiwiTk9NQVhWQUxVRSIsIk5PTUlOVkFMVUUiLCJOT05FIiwiTk9PUkRFUiIsIk5PUk1BTElaRSIsIk5PUk1BTElaRUQiLCJOT1QiLCJOVUxMIiwiTlVMTElGIiwiTlVMTFMiLCJOVU1FUklDIiwiTlVNUEFSVFMiLCJPQklEIiwiT0NURVRfTEVOR1RIIiwiT0YiLCJPRkZTRVQiLCJPTEQiLCJPTERfVEFCTEUiLCJPTiIsIk9OTFkiLCJPUEVOIiwiT1BUSU1JWkFUSU9OIiwiT1BUSU1JWkUiLCJPUFRJT04iLCJPUkRFUiIsIk9VVCIsIk9VVEVSIiwiT1ZFUiIsIk9WRVJMQVBTIiwiT1ZFUkxBWSIsIk9WRVJSSURJTkciLCJQQUNLQUdFIiwiUEFEREVEIiwiUEFHRVNJWkUiLCJQQVJBTUVURVIiLCJQQVJUIiwiUEFSVElUSU9OIiwiUEFSVElUSU9ORUQiLCJQQVJUSVRJT05JTkciLCJQQVJUSVRJT05TIiwiUEFTU1dPUkQiLCJQQVRIIiwiUEVSQ0VOVElMRV9DT05UIiwiUEVSQ0VOVElMRV9ESVNDIiwiUEVSQ0VOVF9SQU5LIiwiUElFQ0VTSVpFIiwiUExBTiIsIlBPU0lUSU9OIiwiUE9XRVIiLCJQUkVDSVNJT04iLCJQUkVQQVJFIiwiUFJFVlZBTCIsIlBSSU1BUlkiLCJQUklRVFkiLCJQUklWSUxFR0VTIiwiUFJPQ0VEVVJFIiwiUFJPR1JBTSIsIlBTSUQiLCJQVUJMSUMiLCJRVUVSWSIsIlFVRVJZTk8iLCJSQU5HRSIsIlJBTksiLCJSRUFEIiwiUkVBRFMiLCJSRUFMIiwiUkVDT1ZFUlkiLCJSRUNVUlNJVkUiLCJSRUYiLCJSRUZFUkVOQ0VTIiwiUkVGRVJFTkNJTkciLCJSRUZSRVNIIiwiUkVHUl9BVkdYIiwiUkVHUl9BVkdZIiwiUkVHUl9DT1VOVCIsIlJFR1JfSU5URVJDRVBUIiwiUkVHUl9SMiIsIlJFR1JfU0xPUEUiLCJSRUdSX1NYWCIsIlJFR1JfU1hZIiwiUkVHUl9TWVkiLCJSRUxFQVNFIiwiUkVOQU1FIiwiUkVQRUFUIiwiUkVTRVQiLCJSRVNJR05BTCIsIlJFU1RBUlQiLCJSRVNUUklDVCIsIlJFU1VMVCIsIlJFU1VMVF9TRVRfTE9DQVRPUiIsIlJFVFVSTiIsIlJFVFVSTlMiLCJSRVZPS0UiLCJSSUdIVCIsIlJPTEUiLCJST0xMQkFDSyIsIlJPTExVUCIsIlJPVU5EX0NFSUxJTkciLCJST1VORF9ET1dOIiwiUk9VTkRfRkxPT1IiLCJST1VORF9IQUxGX0RPV04iLCJST1VORF9IQUxGX0VWRU4iLCJST1VORF9IQUxGX1VQIiwiUk9VTkRfVVAiLCJST1VUSU5FIiwiUk9XIiwiUk9XTlVNQkVSIiwiUk9XUyIsIlJPV1NFVCIsIlJPV19OVU1CRVIiLCJSUk4iLCJSVU4iLCJTQVZFUE9JTlQiLCJTQ0hFTUEiLCJTQ09QRSIsIlNDUkFUQ0hQQUQiLCJTQ1JPTEwiLCJTRUFSQ0giLCJTRUNPTkQiLCJTRUNPTkRTIiwiU0VDUVRZIiwiU0VDVVJJVFkiLCJTRU5TSVRJVkUiLCJTRVFVRU5DRSIsIlNFU1NJT04iLCJTRVNTSU9OX1VTRVIiLCJTSUdOQUwiLCJTSU1JTEFSIiwiU0lNUExFIiwiU01BTExJTlQiLCJTTkFOIiwiU09NRSIsIlNPVVJDRSIsIlNQRUNJRklDIiwiU1BFQ0lGSUNUWVBFIiwiU1FMIiwiU1FMRVhDRVBUSU9OIiwiU1FMSUQiLCJTUUxTVEFURSIsIlNRTFdBUk5JTkciLCJTUVJUIiwiU1RBQ0tFRCIsIlNUQU5EQVJEIiwiU1RBUlQiLCJTVEFSVElORyIsIlNUQVRFTUVOVCIsIlNUQVRJQyIsIlNUQVRNRU5UIiwiU1RBWSIsIlNURERFVl9QT1AiLCJTVERERVZfU0FNUCIsIlNUT0dST1VQIiwiU1RPUkVTIiwiU1RZTEUiLCJTVUJNVUxUSVNFVCIsIlNVQlNUUklORyIsIlNVTSIsIlNVTU1BUlkiLCJTWU1NRVRSSUMiLCJTWU5PTllNIiwiU1lTRlVOIiwiU1lTSUJNIiwiU1lTUFJPQyIsIlNZU1RFTSIsIlNZU1RFTV9VU0VSIiwiVEFCTEUiLCJUQUJMRVNBTVBMRSIsIlRBQkxFU1BBQ0UiLCJUSEVOIiwiVElNRSIsIlRJTUVTVEFNUCIsIlRJTUVaT05FX0hPVVIiLCJUSU1FWk9ORV9NSU5VVEUiLCJUTyIsIlRSQUlMSU5HIiwiVFJBTlNBQ1RJT04iLCJUUkFOU0xBVEUiLCJUUkFOU0xBVElPTiIsIlRSRUFUIiwiVFJJR0dFUiIsIlRSSU0iLCJUUlVFIiwiVFJVTkNBVEUiLCJUWVBFIiwiVUVTQ0FQRSIsIlVORE8iLCJVTklRVUUiLCJVTktOT1dOIiwiVU5ORVNUIiwiVU5USUwiLCJVUFBFUiIsIlVTQUdFIiwiVVNFUiIsIlVTSU5HIiwiVkFMSURQUk9DIiwiVkFMVUUiLCJWQVJDSEFSIiwiVkFSSUFCTEUiLCJWQVJJQU5UIiwiVkFSWUlORyIsIlZBUl9QT1AiLCJWQVJfU0FNUCIsIlZDQVQiLCJWRVJTSU9OIiwiVklFVyIsIlZPTEFUSUxFIiwiVk9MVU1FUyIsIldIRU4iLCJXSEVORVZFUiIsIldISUxFIiwiV0lEVEhfQlVDS0VUIiwiV0lORE9XIiwiV0lUSCIsIldJVEhJTiIsIldJVEhPVVQiLCJXTE0iLCJXUklURSIsIlhNTEVMRU1FTlQiLCJYTUxFWElTVFMiLCJYTUxOQU1FU1BBQ0VTIiwiWUVBUiIsIllFQVJTIl0sTz1bIkFERCIsIkFGVEVSIiwiQUxURVIgQ09MVU1OIiwiQUxURVIgVEFCTEUiLCJERUxFVEUgRlJPTSIsIkVYQ0VQVCIsIkZFVENIIEZJUlNUIiwiRlJPTSIsIkdST1VQIEJZIiwiR08iLCJIQVZJTkciLCJJTlNFUlQgSU5UTyIsIklOVEVSU0VDVCIsIkxJTUlUIiwiT1JERVIgQlkiLCJTRUxFQ1QiLCJTRVQgQ1VSUkVOVCBTQ0hFTUEiLCJTRVQgU0NIRU1BIiwiU0VUIiwiVU5JT04gQUxMIiwiVVBEQVRFIiwiVkFMVUVTIiwiV0hFUkUiXSxpPVsiQU5EIiwiQ1JPU1MgSk9JTiIsIklOTkVSIEpPSU4iLCJKT0lOIiwiTEVGVCBKT0lOIiwiTEVGVCBPVVRFUiBKT0lOIiwiT1IiLCJPVVRFUiBKT0lOIiwiUklHSFQgSk9JTiIsIlJJR0hUIE9VVEVSIEpPSU4iXSxTPXZvaWQgMCx1PWZ1bmN0aW9uKCl7ZnVuY3Rpb24gZShFKXsoMCxUWyJkZWZhdWx0Il0pKHRoaXMsZSksdGhpcy5jZmc9RX1yZXR1cm4gZS5wcm90b3R5cGUuZm9ybWF0PWZ1bmN0aW9uKGUpe3JldHVybiBTfHwoUz1uZXcgQVsiZGVmYXVsdCJdKHtyZXNlcnZlZFdvcmRzOkkscmVzZXJ2ZWRUb3BsZXZlbFdvcmRzOk8scmVzZXJ2ZWROZXdsaW5lV29yZHM6aSxzdHJpbmdUeXBlczpbJyIiJywiJyciLCJgYCIsIltdIl0sb3BlblBhcmVuczpbIigiXSxjbG9zZVBhcmVuczpbIikiXSxpbmRleGVkUGxhY2Vob2xkZXJUeXBlczpbIj8iXSxuYW1lZFBsYWNlaG9sZGVyVHlwZXM6WyI6Il0sbGluZUNvbW1lbnRUeXBlczpbIi0tIl0sc3BlY2lhbFdvcmRDaGFyczpbIiMiLCJAIl19KSksbmV3IG9bImRlZmF1bHQiXSh0aGlzLmNmZyxTKS5mb3JtYXQoZSl9LGV9KCk7RVsiZGVmYXVsdCJdPXUsZS5leHBvcnRzPUVbImRlZmF1bHQiXX0sZnVuY3Rpb24oZSxFLHQpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBuKGUpe3JldHVybiBlJiZlLl9fZXNNb2R1bGU/ZTp7ImRlZmF1bHQiOmV9fUUuX19lc01vZHVsZT0hMDt2YXIgcj10KDEpLFQ9bihyKSxSPXQoNCksbz1uKFIpLE49dCg1KSxBPW4oTiksST1bIkFMTCIsIkFMVEVSIiwiQU5BTFlaRSIsIkFORCIsIkFOWSIsIkFSUkFZIiwiQVMiLCJBU0MiLCJCRUdJTiIsIkJFVFdFRU4iLCJCSU5BUlkiLCJCT09MRUFOIiwiQlJFQUsiLCJCVUNLRVQiLCJCVUlMRCIsIkJZIiwiQ0FMTCIsIkNBU0UiLCJDQVNUIiwiQ0xVU1RFUiIsIkNPTExBVEUiLCJDT0xMRUNUSU9OIiwiQ09NTUlUIiwiQ09OTkVDVCIsIkNPTlRJTlVFIiwiQ09SUkVMQVRFIiwiQ09WRVIiLCJDUkVBVEUiLCJEQVRBQkFTRSIsIkRBVEFTRVQiLCJEQVRBU1RPUkUiLCJERUNMQVJFIiwiREVDUkVNRU5UIiwiREVMRVRFIiwiREVSSVZFRCIsIkRFU0MiLCJERVNDUklCRSIsIkRJU1RJTkNUIiwiRE8iLCJEUk9QIiwiRUFDSCIsIkVMRU1FTlQiLCJFTFNFIiwiRU5EIiwiRVZFUlkiLCJFWENFUFQiLCJFWENMVURFIiwiRVhFQ1VURSIsIkVYSVNUUyIsIkVYUExBSU4iLCJGQUxTRSIsIkZFVENIIiwiRklSU1QiLCJGTEFUVEVOIiwiRk9SIiwiRk9SQ0UiLCJGUk9NIiwiRlVOQ1RJT04iLCJHUkFOVCIsIkdST1VQIiwiR1NJIiwiSEFWSU5HIiwiSUYiLCJJR05PUkUiLCJJTElLRSIsIklOIiwiSU5DTFVERSIsIklOQ1JFTUVOVCIsIklOREVYIiwiSU5GRVIiLCJJTkxJTkUiLCJJTk5FUiIsIklOU0VSVCIsIklOVEVSU0VDVCIsIklOVE8iLCJJUyIsIkpPSU4iLCJLRVkiLCJLRVlTIiwiS0VZU1BBQ0UiLCJLTk9XTiIsIkxBU1QiLCJMRUZUIiwiTEVUIiwiTEVUVElORyIsIkxJS0UiLCJMSU1JVCIsIkxTTSIsIk1BUCIsIk1BUFBJTkciLCJNQVRDSEVEIiwiTUFURVJJQUxJWkVEIiwiTUVSR0UiLCJNSU5VUyIsIk1JU1NJTkciLCJOQU1FU1BBQ0UiLCJORVNUIiwiTk9UIiwiTlVMTCIsIk5VTUJFUiIsIk9CSkVDVCIsIk9GRlNFVCIsIk9OIiwiT1BUSU9OIiwiT1IiLCJPUkRFUiIsIk9VVEVSIiwiT1ZFUiIsIlBBUlNFIiwiUEFSVElUSU9OIiwiUEFTU1dPUkQiLCJQQVRIIiwiUE9PTCIsIlBSRVBBUkUiLCJQUklNQVJZIiwiUFJJVkFURSIsIlBSSVZJTEVHRSIsIlBST0NFRFVSRSIsIlBVQkxJQyIsIlJBVyIsIlJFQUxNIiwiUkVEVUNFIiwiUkVOQU1FIiwiUkVUVVJOIiwiUkVUVVJOSU5HIiwiUkVWT0tFIiwiUklHSFQiLCJST0xFIiwiUk9MTEJBQ0siLCJTQVRJU0ZJRVMiLCJTQ0hFTUEiLCJTRUxFQ1QiLCJTRUxGIiwiU0VNSSIsIlNFVCIsIlNIT1ciLCJTT01FIiwiU1RBUlQiLCJTVEFUSVNUSUNTIiwiU1RSSU5HIiwiU1lTVEVNIiwiVEhFTiIsIlRPIiwiVFJBTlNBQ1RJT04iLCJUUklHR0VSIiwiVFJVRSIsIlRSVU5DQVRFIiwiVU5ERVIiLCJVTklPTiIsIlVOSVFVRSIsIlVOS05PV04iLCJVTk5FU1QiLCJVTlNFVCIsIlVQREFURSIsIlVQU0VSVCIsIlVTRSIsIlVTRVIiLCJVU0lORyIsIlZBTElEQVRFIiwiVkFMVUUiLCJWQUxVRUQiLCJWQUxVRVMiLCJWSUEiLCJWSUVXIiwiV0hFTiIsIldIRVJFIiwiV0hJTEUiLCJXSVRIIiwiV0lUSElOIiwiV09SSyIsIlhPUiJdLE89WyJERUxFVEUgRlJPTSIsIkVYQ0VQVCBBTEwiLCJFWENFUFQiLCJFWFBMQUlOIERFTEVURSBGUk9NIiwiRVhQTEFJTiBVUERBVEUiLCJFWFBMQUlOIFVQU0VSVCIsIkZST00iLCJHUk9VUCBCWSIsIkhBVklORyIsIklORkVSIiwiSU5TRVJUIElOVE8iLCJJTlRFUlNFQ1QgQUxMIiwiSU5URVJTRUNUIiwiTEVUIiwiTElNSVQiLCJNRVJHRSIsIk5FU1QiLCJPUkRFUiBCWSIsIlBSRVBBUkUiLCJTRUxFQ1QiLCJTRVQgQ1VSUkVOVCBTQ0hFTUEiLCJTRVQgU0NIRU1BIiwiU0VUIiwiVU5JT04gQUxMIiwiVU5JT04iLCJVTk5FU1QiLCJVUERBVEUiLCJVUFNFUlQiLCJVU0UgS0VZUyIsIlZBTFVFUyIsIldIRVJFIl0saT1bIkFORCIsIklOTkVSIEpPSU4iLCJKT0lOIiwiTEVGVCBKT0lOIiwiTEVGVCBPVVRFUiBKT0lOIiwiT1IiLCJPVVRFUiBKT0lOIiwiUklHSFQgSk9JTiIsIlJJR0hUIE9VVEVSIEpPSU4iLCJYT1IiXSxTPXZvaWQgMCx1PWZ1bmN0aW9uKCl7ZnVuY3Rpb24gZShFKXsoMCxUWyJkZWZhdWx0Il0pKHRoaXMsZSksdGhpcy5jZmc9RX1yZXR1cm4gZS5wcm90b3R5cGUuZm9ybWF0PWZ1bmN0aW9uKGUpe3JldHVybiBTfHwoUz1uZXcgQVsiZGVmYXVsdCJdKHtyZXNlcnZlZFdvcmRzOkkscmVzZXJ2ZWRUb3BsZXZlbFdvcmRzOk8scmVzZXJ2ZWROZXdsaW5lV29yZHM6aSxzdHJpbmdUeXBlczpbJyIiJywiJyciLCJgYCJdLG9wZW5QYXJlbnM6WyIoIiwiWyIsInsiXSxjbG9zZVBhcmVuczpbIikiLCJdIiwifSJdLG5hbWVkUGxhY2Vob2xkZXJUeXBlczpbIiQiXSxsaW5lQ29tbWVudFR5cGVzOlsiIyIsIi0tIl19KSksbmV3IG9bImRlZmF1bHQiXSh0aGlzLmNmZyxTKS5mb3JtYXQoZSl9LGV9KCk7RVsiZGVmYXVsdCJdPXUsZS5leHBvcnRzPUVbImRlZmF1bHQiXX0sZnVuY3Rpb24oZSxFLHQpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBuKGUpe3JldHVybiBlJiZlLl9fZXNNb2R1bGU/ZTp7ImRlZmF1bHQiOmV9fUUuX19lc01vZHVsZT0hMDt2YXIgcj10KDEpLFQ9bihyKSxSPXQoNCksbz1uKFIpLE49dCg1KSxBPW4oTiksST1bIkEiLCJBQ0NFU1NJQkxFIiwiQUdFTlQiLCJBR0dSRUdBVEUiLCJBTEwiLCJBTFRFUiIsIkFOWSIsIkFSUkFZIiwiQVMiLCJBU0MiLCJBVCIsIkFUVFJJQlVURSIsIkFVVEhJRCIsIkFWRyIsIkJFVFdFRU4iLCJCRklMRV9CQVNFIiwiQklOQVJZX0lOVEVHRVIiLCJCSU5BUlkiLCJCTE9CX0JBU0UiLCJCTE9DSyIsIkJPRFkiLCJCT09MRUFOIiwiQk9USCIsIkJPVU5EIiwiQlVMSyIsIkJZIiwiQllURSIsIkMiLCJDQUxMIiwiQ0FMTElORyIsIkNBU0NBREUiLCJDQVNFIiwiQ0hBUl9CQVNFIiwiQ0hBUiIsIkNIQVJBQ1RFUiIsIkNIQVJTRVQiLCJDSEFSU0VURk9STSIsIkNIQVJTRVRJRCIsIkNIRUNLIiwiQ0xPQl9CQVNFIiwiQ0xPTkUiLCJDTE9TRSIsIkNMVVNURVIiLCJDTFVTVEVSUyIsIkNPQUxFU0NFIiwiQ09MQVVUSCIsIkNPTExFQ1QiLCJDT0xVTU5TIiwiQ09NTUVOVCIsIkNPTU1JVCIsIkNPTU1JVFRFRCIsIkNPTVBJTEVEIiwiQ09NUFJFU1MiLCJDT05ORUNUIiwiQ09OU1RBTlQiLCJDT05TVFJVQ1RPUiIsIkNPTlRFWFQiLCJDT05USU5VRSIsIkNPTlZFUlQiLCJDT1VOVCIsIkNSQVNIIiwiQ1JFQVRFIiwiQ1JFREVOVElBTCIsIkNVUlJFTlQiLCJDVVJSVkFMIiwiQ1VSU09SIiwiQ1VTVE9NREFUVU0iLCJEQU5HTElORyIsIkRBVEEiLCJEQVRFX0JBU0UiLCJEQVRFIiwiREFZIiwiREVDSU1BTCIsIkRFRkFVTFQiLCJERUZJTkUiLCJERUxFVEUiLCJERVNDIiwiREVURVJNSU5JU1RJQyIsIkRJUkVDVE9SWSIsIkRJU1RJTkNUIiwiRE8iLCJET1VCTEUiLCJEUk9QIiwiRFVSQVRJT04iLCJFTEVNRU5UIiwiRUxTSUYiLCJFTVBUWSIsIkVTQ0FQRSIsIkVYQ0VQVElPTlMiLCJFWENMVVNJVkUiLCJFWEVDVVRFIiwiRVhJU1RTIiwiRVhJVCIsIkVYVEVORFMiLCJFWFRFUk5BTCIsIkVYVFJBQ1QiLCJGQUxTRSIsIkZFVENIIiwiRklOQUwiLCJGSVJTVCIsIkZJWEVEIiwiRkxPQVQiLCJGT1IiLCJGT1JBTEwiLCJGT1JDRSIsIkZST00iLCJGVU5DVElPTiIsIkdFTkVSQUwiLCJHT1RPIiwiR1JBTlQiLCJHUk9VUCIsIkhBU0giLCJIRUFQIiwiSElEREVOIiwiSE9VUiIsIklERU5USUZJRUQiLCJJRiIsIklNTUVESUFURSIsIklOIiwiSU5DTFVESU5HIiwiSU5ERVgiLCJJTkRFWEVTIiwiSU5ESUNBVE9SIiwiSU5ESUNFUyIsIklORklOSVRFIiwiSU5TVEFOVElBQkxFIiwiSU5UIiwiSU5URUdFUiIsIklOVEVSRkFDRSIsIklOVEVSVkFMIiwiSU5UTyIsIklOVkFMSURBVEUiLCJJUyIsIklTT0xBVElPTiIsIkpBVkEiLCJMQU5HVUFHRSIsIkxBUkdFIiwiTEVBRElORyIsIkxFTkdUSCIsIkxFVkVMIiwiTElCUkFSWSIsIkxJS0UiLCJMSUtFMiIsIkxJS0U0IiwiTElLRUMiLCJMSU1JVEVEIiwiTE9DQUwiLCJMT0NLIiwiTE9ORyIsIk1BUCIsIk1BWCIsIk1BWExFTiIsIk1FTUJFUiIsIk1FUkdFIiwiTUlOIiwiTUlOVVMiLCJNSU5VVEUiLCJNTFNMQUJFTCIsIk1PRCIsIk1PREUiLCJNT05USCIsIk1VTFRJU0VUIiwiTkFNRSIsIk5BTiIsIk5BVElPTkFMIiwiTkFUSVZFIiwiTkFUVVJBTCIsIk5BVFVSQUxOIiwiTkNIQVIiLCJORVciLCJORVhUVkFMIiwiTk9DT01QUkVTUyIsIk5PQ09QWSIsIk5PVCIsIk5PV0FJVCIsIk5VTEwiLCJOVUxMSUYiLCJOVU1CRVJfQkFTRSIsIk5VTUJFUiIsIk9CSkVDVCIsIk9DSUNPTEwiLCJPQ0lEQVRFIiwiT0NJREFURVRJTUUiLCJPQ0lEVVJBVElPTiIsIk9DSUlOVEVSVkFMIiwiT0NJTE9CTE9DQVRPUiIsIk9DSU5VTUJFUiIsIk9DSVJBVyIsIk9DSVJFRiIsIk9DSVJFRkNVUlNPUiIsIk9DSVJPV0lEIiwiT0NJU1RSSU5HIiwiT0NJVFlQRSIsIk9GIiwiT0xEIiwiT04iLCJPTkxZIiwiT1BBUVVFIiwiT1BFTiIsIk9QRVJBVE9SIiwiT1BUSU9OIiwiT1JBQ0xFIiwiT1JBREFUQSIsIk9SREVSIiwiT1JHQU5JWkFUSU9OIiwiT1JMQU5ZIiwiT1JMVkFSWSIsIk9USEVSUyIsIk9VVCIsIk9WRVJMQVBTIiwiT1ZFUlJJRElORyIsIlBBQ0tBR0UiLCJQQVJBTExFTF9FTkFCTEUiLCJQQVJBTUVURVIiLCJQQVJBTUVURVJTIiwiUEFSRU5UIiwiUEFSVElUSU9OIiwiUEFTQ0FMIiwiUENURlJFRSIsIlBJUEUiLCJQSVBFTElORUQiLCJQTFNfSU5URUdFUiIsIlBMVUdHQUJMRSIsIlBPU0lUSVZFIiwiUE9TSVRJVkVOIiwiUFJBR01BIiwiUFJFQ0lTSU9OIiwiUFJJT1IiLCJQUklWQVRFIiwiUFJPQ0VEVVJFIiwiUFVCTElDIiwiUkFJU0UiLCJSQU5HRSIsIlJBVyIsIlJFQUQiLCJSRUFMIiwiUkVDT1JEIiwiUkVGIiwiUkVGRVJFTkNFIiwiUkVMRUFTRSIsIlJFTElFU19PTiIsIlJFTSIsIlJFTUFJTkRFUiIsIlJFTkFNRSIsIlJFU09VUkNFIiwiUkVTVUxUX0NBQ0hFIiwiUkVTVUxUIiwiUkVUVVJOIiwiUkVUVVJOSU5HIiwiUkVWRVJTRSIsIlJFVk9LRSIsIlJPTExCQUNLIiwiUk9XIiwiUk9XSUQiLCJST1dOVU0iLCJST1dUWVBFIiwiU0FNUExFIiwiU0FWRSIsIlNBVkVQT0lOVCIsIlNCMSIsIlNCMiIsIlNCNCIsIlNFQ09ORCIsIlNFR01FTlQiLCJTRUxGIiwiU0VQQVJBVEUiLCJTRVFVRU5DRSIsIlNFUklBTElaQUJMRSIsIlNIQVJFIiwiU0hPUlQiLCJTSVpFX1QiLCJTSVpFIiwiU01BTExJTlQiLCJTT01FIiwiU1BBQ0UiLCJTUEFSU0UiLCJTUUwiLCJTUUxDT0RFIiwiU1FMREFUQSIsIlNRTEVSUk0iLCJTUUxOQU1FIiwiU1FMU1RBVEUiLCJTVEFOREFSRCIsIlNUQVJUIiwiU1RBVElDIiwiU1REREVWIiwiU1RPUkVEIiwiU1RSSU5HIiwiU1RSVUNUIiwiU1RZTEUiLCJTVUJNVUxUSVNFVCIsIlNVQlBBUlRJVElPTiIsIlNVQlNUSVRVVEFCTEUiLCJTVUJUWVBFIiwiU1VDQ0VTU0ZVTCIsIlNVTSIsIlNZTk9OWU0iLCJTWVNEQVRFIiwiVEFCQVVUSCIsIlRBQkxFIiwiVERPIiwiVEhFIiwiVEhFTiIsIlRJTUUiLCJUSU1FU1RBTVAiLCJUSU1FWk9ORV9BQkJSIiwiVElNRVpPTkVfSE9VUiIsIlRJTUVaT05FX01JTlVURSIsIlRJTUVaT05FX1JFR0lPTiIsIlRPIiwiVFJBSUxJTkciLCJUUkFOU0FDVElPTiIsIlRSQU5TQUNUSU9OQUwiLCJUUklHR0VSIiwiVFJVRSIsIlRSVVNURUQiLCJUWVBFIiwiVUIxIiwiVUIyIiwiVUI0IiwiVUlEIiwiVU5ERVIiLCJVTklRVUUiLCJVTlBMVUciLCJVTlNJR05FRCIsIlVOVFJVU1RFRCIsIlVTRSIsIlVTRVIiLCJVU0lORyIsIlZBTElEQVRFIiwiVkFMSVNUIiwiVkFMVUUiLCJWQVJDSEFSIiwiVkFSQ0hBUjIiLCJWQVJJQUJMRSIsIlZBUklBTkNFIiwiVkFSUkFZIiwiVkFSWUlORyIsIlZJRVciLCJWSUVXUyIsIlZPSUQiLCJXSEVORVZFUiIsIldISUxFIiwiV0lUSCIsIldPUksiLCJXUkFQUEVEIiwiV1JJVEUiLCJZRUFSIiwiWk9ORSJdLE89WyJBREQiLCJBTFRFUiBDT0xVTU4iLCJBTFRFUiBUQUJMRSIsIkJFR0lOIiwiQ09OTkVDVCBCWSIsIkRFQ0xBUkUiLCJERUxFVEUgRlJPTSIsIkRFTEVURSIsIkVORCIsIkVYQ0VQVCIsIkVYQ0VQVElPTiIsIkZFVENIIEZJUlNUIiwiRlJPTSIsIkdST1VQIEJZIiwiSEFWSU5HIiwiSU5TRVJUIElOVE8iLCJJTlNFUlQiLCJJTlRFUlNFQ1QiLCJMSU1JVCIsIkxPT1AiLCJNT0RJRlkiLCJPUkRFUiBCWSIsIlNFTEVDVCIsIlNFVCBDVVJSRU5UIFNDSEVNQSIsIlNFVCBTQ0hFTUEiLCJTRVQiLCJTVEFSVCBXSVRIIiwiVU5JT04gQUxMIiwiVU5JT04iLCJVUERBVEUiLCJWQUxVRVMiLCJXSEVSRSJdLGk9WyJBTkQiLCJDUk9TUyBBUFBMWSIsIkNST1NTIEpPSU4iLCJFTFNFIiwiRU5EIiwiSU5ORVIgSk9JTiIsIkpPSU4iLCJMRUZUIEpPSU4iLCJMRUZUIE9VVEVSIEpPSU4iLCJPUiIsIk9VVEVSIEFQUExZIiwiT1VURVIgSk9JTiIsIlJJR0hUIEpPSU4iLCJSSUdIVCBPVVRFUiBKT0lOIiwiV0hFTiIsIlhPUiJdLFM9dm9pZCAwLHU9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKEUpeygwLFRbImRlZmF1bHQiXSkodGhpcyxlKSx0aGlzLmNmZz1FfXJldHVybiBlLnByb3RvdHlwZS5mb3JtYXQ9ZnVuY3Rpb24oZSl7cmV0dXJuIFN8fChTPW5ldyBBWyJkZWZhdWx0Il0oe3Jlc2VydmVkV29yZHM6SSxyZXNlcnZlZFRvcGxldmVsV29yZHM6TyxyZXNlcnZlZE5ld2xpbmVXb3JkczppLHN0cmluZ1R5cGVzOlsnIiInLCJOJyciLCInJyIsImBgIl0sb3BlblBhcmVuczpbIigiLCJDQVNFIl0sY2xvc2VQYXJlbnM6WyIpIiwiRU5EIl0saW5kZXhlZFBsYWNlaG9sZGVyVHlwZXM6WyI/Il0sbmFtZWRQbGFjZWhvbGRlclR5cGVzOlsiOiJdLGxpbmVDb21tZW50VHlwZXM6WyItLSJdLHNwZWNpYWxXb3JkQ2hhcnM6WyJfIiwiJCIsIiMiLCIuIiwiQCJdfSkpLG5ldyBvWyJkZWZhdWx0Il0odGhpcy5jZmcsUykuZm9ybWF0KGUpfSxlfSgpO0VbImRlZmF1bHQiXT11LGUuZXhwb3J0cz1FWyJkZWZhdWx0Il19LGZ1bmN0aW9uKGUsRSx0KXsidXNlIHN0cmljdCI7ZnVuY3Rpb24gbihlKXtyZXR1cm4gZSYmZS5fX2VzTW9kdWxlP2U6eyJkZWZhdWx0IjplfX1FLl9fZXNNb2R1bGU9ITA7dmFyIHI9dCgxKSxUPW4ociksUj10KDQpLG89bihSKSxOPXQoNSksQT1uKE4pLEk9WyJBQ0NFU1NJQkxFIiwiQUNUSU9OIiwiQUdBSU5TVCIsIkFHR1JFR0FURSIsIkFMR09SSVRITSIsIkFMTCIsIkFMVEVSIiwiQU5BTFlTRSIsIkFOQUxZWkUiLCJBUyIsIkFTQyIsIkFVVE9DT01NSVQiLCJBVVRPX0lOQ1JFTUVOVCIsIkJBQ0tVUCIsIkJFR0lOIiwiQkVUV0VFTiIsIkJJTkxPRyIsIkJPVEgiLCJDQVNDQURFIiwiQ0FTRSIsIkNIQU5HRSIsIkNIQU5HRUQiLCJDSEFSQUNURVIgU0VUIiwiQ0hBUlNFVCIsIkNIRUNLIiwiQ0hFQ0tTVU0iLCJDT0xMQVRFIiwiQ09MTEFUSU9OIiwiQ09MVU1OIiwiQ09MVU1OUyIsIkNPTU1FTlQiLCJDT01NSVQiLCJDT01NSVRURUQiLCJDT01QUkVTU0VEIiwiQ09OQ1VSUkVOVCIsIkNPTlNUUkFJTlQiLCJDT05UQUlOUyIsIkNPTlZFUlQiLCJDUkVBVEUiLCJDUk9TUyIsIkNVUlJFTlRfVElNRVNUQU1QIiwiREFUQUJBU0UiLCJEQVRBQkFTRVMiLCJEQVkiLCJEQVlfSE9VUiIsIkRBWV9NSU5VVEUiLCJEQVlfU0VDT05EIiwiREVGQVVMVCIsIkRFRklORVIiLCJERUxBWUVEIiwiREVMRVRFIiwiREVTQyIsIkRFU0NSSUJFIiwiREVURVJNSU5JU1RJQyIsIkRJU1RJTkNUIiwiRElTVElOQ1RST1ciLCJESVYiLCJETyIsIkRST1AiLCJEVU1QRklMRSIsIkRVUExJQ0FURSIsIkRZTkFNSUMiLCJFTFNFIiwiRU5DTE9TRUQiLCJFTkQiLCJFTkdJTkUiLCJFTkdJTkVTIiwiRU5HSU5FX1RZUEUiLCJFU0NBUEUiLCJFU0NBUEVEIiwiRVZFTlRTIiwiRVhFQyIsIkVYRUNVVEUiLCJFWElTVFMiLCJFWFBMQUlOIiwiRVhURU5ERUQiLCJGQVNUIiwiRkVUQ0giLCJGSUVMRFMiLCJGSUxFIiwiRklSU1QiLCJGSVhFRCIsIkZMVVNIIiwiRk9SIiwiRk9SQ0UiLCJGT1JFSUdOIiwiRlVMTCIsIkZVTExURVhUIiwiRlVOQ1RJT04iLCJHTE9CQUwiLCJHUkFOVCIsIkdSQU5UUyIsIkdST1VQX0NPTkNBVCIsIkhFQVAiLCJISUdIX1BSSU9SSVRZIiwiSE9TVFMiLCJIT1VSIiwiSE9VUl9NSU5VVEUiLCJIT1VSX1NFQ09ORCIsIklERU5USUZJRUQiLCJJRiIsIklGTlVMTCIsIklHTk9SRSIsIklOIiwiSU5ERVgiLCJJTkRFWEVTIiwiSU5GSUxFIiwiSU5TRVJUIiwiSU5TRVJUX0lEIiwiSU5TRVJUX01FVEhPRCIsIklOVEVSVkFMIiwiSU5UTyIsIklOVk9LRVIiLCJJUyIsIklTT0xBVElPTiIsIktFWSIsIktFWVMiLCJLSUxMIiwiTEFTVF9JTlNFUlRfSUQiLCJMRUFESU5HIiwiTEVWRUwiLCJMSUtFIiwiTElORUFSIiwiTElORVMiLCJMT0FEIiwiTE9DQUwiLCJMT0NLIiwiTE9DS1MiLCJMT0dTIiwiTE9XX1BSSU9SSVRZIiwiTUFSSUEiLCJNQVNURVIiLCJNQVNURVJfQ09OTkVDVF9SRVRSWSIsIk1BU1RFUl9IT1NUIiwiTUFTVEVSX0xPR19GSUxFIiwiTUFUQ0giLCJNQVhfQ09OTkVDVElPTlNfUEVSX0hPVVIiLCJNQVhfUVVFUklFU19QRVJfSE9VUiIsIk1BWF9ST1dTIiwiTUFYX1VQREFURVNfUEVSX0hPVVIiLCJNQVhfVVNFUl9DT05ORUNUSU9OUyIsIk1FRElVTSIsIk1FUkdFIiwiTUlOVVRFIiwiTUlOVVRFX1NFQ09ORCIsIk1JTl9ST1dTIiwiTU9ERSIsIk1PRElGWSIsIk1PTlRIIiwiTVJHX01ZSVNBTSIsIk1ZSVNBTSIsIk5BTUVTIiwiTkFUVVJBTCIsIk5PVCIsIk5PVygpIiwiTlVMTCIsIk9GRlNFVCIsIk9OIERFTEVURSIsIk9OIFVQREFURSIsIk9OIiwiT05MWSIsIk9QRU4iLCJPUFRJTUlaRSIsIk9QVElPTiIsIk9QVElPTkFMTFkiLCJPVVRGSUxFIiwiUEFDS19LRVlTIiwiUEFHRSIsIlBBUlRJQUwiLCJQQVJUSVRJT04iLCJQQVJUSVRJT05TIiwiUEFTU1dPUkQiLCJQUklNQVJZIiwiUFJJVklMRUdFUyIsIlBST0NFRFVSRSIsIlBST0NFU1MiLCJQUk9DRVNTTElTVCIsIlBVUkdFIiwiUVVJQ0siLCJSQUlEMCIsIlJBSURfQ0hVTktTIiwiUkFJRF9DSFVOS1NJWkUiLCJSQUlEX1RZUEUiLCJSQU5HRSIsIlJFQUQiLCJSRUFEX09OTFkiLCJSRUFEX1dSSVRFIiwiUkVGRVJFTkNFUyIsIlJFR0VYUCIsIlJFTE9BRCIsIlJFTkFNRSIsIlJFUEFJUiIsIlJFUEVBVEFCTEUiLCJSRVBMQUNFIiwiUkVQTElDQVRJT04iLCJSRVNFVCIsIlJFU1RPUkUiLCJSRVNUUklDVCIsIlJFVFVSTiIsIlJFVFVSTlMiLCJSRVZPS0UiLCJSTElLRSIsIlJPTExCQUNLIiwiUk9XIiwiUk9XUyIsIlJPV19GT1JNQVQiLCJTRUNPTkQiLCJTRUNVUklUWSIsIlNFUEFSQVRPUiIsIlNFUklBTElaQUJMRSIsIlNFU1NJT04iLCJTSEFSRSIsIlNIT1ciLCJTSFVURE9XTiIsIlNMQVZFIiwiU09OQU1FIiwiU09VTkRTIiwiU1FMIiwiU1FMX0FVVE9fSVNfTlVMTCIsIlNRTF9CSUdfUkVTVUxUIiwiU1FMX0JJR19TRUxFQ1RTIiwiU1FMX0JJR19UQUJMRVMiLCJTUUxfQlVGRkVSX1JFU1VMVCIsIlNRTF9DQUNIRSIsIlNRTF9DQUxDX0ZPVU5EX1JPV1MiLCJTUUxfTE9HX0JJTiIsIlNRTF9MT0dfT0ZGIiwiU1FMX0xPR19VUERBVEUiLCJTUUxfTE9XX1BSSU9SSVRZX1VQREFURVMiLCJTUUxfTUFYX0pPSU5fU0laRSIsIlNRTF9OT19DQUNIRSIsIlNRTF9RVU9URV9TSE9XX0NSRUFURSIsIlNRTF9TQUZFX1VQREFURVMiLCJTUUxfU0VMRUNUX0xJTUlUIiwiU1FMX1NMQVZFX1NLSVBfQ09VTlRFUiIsIlNRTF9TTUFMTF9SRVNVTFQiLCJTUUxfV0FSTklOR1MiLCJTVEFSVCIsIlNUQVJUSU5HIiwiU1RBVFVTIiwiU1RPUCIsIlNUT1JBR0UiLCJTVFJBSUdIVF9KT0lOIiwiU1RSSU5HIiwiU1RSSVBFRCIsIlNVUEVSIiwiVEFCTEUiLCJUQUJMRVMiLCJURU1QT1JBUlkiLCJURVJNSU5BVEVEIiwiVEhFTiIsIlRPIiwiVFJBSUxJTkciLCJUUkFOU0FDVElPTkFMIiwiVFJVRSIsIlRSVU5DQVRFIiwiVFlQRSIsIlRZUEVTIiwiVU5DT01NSVRURUQiLCJVTklRVUUiLCJVTkxPQ0siLCJVTlNJR05FRCIsIlVTQUdFIiwiVVNFIiwiVVNJTkciLCJWQVJJQUJMRVMiLCJWSUVXIiwiV0hFTiIsIldJVEgiLCJXT1JLIiwiV1JJVEUiLCJZRUFSX01PTlRIIl0sTz1bIkFERCIsIkFGVEVSIiwiQUxURVIgQ09MVU1OIiwiQUxURVIgVEFCTEUiLCJERUxFVEUgRlJPTSIsIkVYQ0VQVCIsIkZFVENIIEZJUlNUIiwiRlJPTSIsIkdST1VQIEJZIiwiR08iLCJIQVZJTkciLCJJTlNFUlQgSU5UTyIsIklOU0VSVCIsIklOVEVSU0VDVCIsIkxJTUlUIiwiTU9ESUZZIiwiT1JERVIgQlkiLCJTRUxFQ1QiLCJTRVQgQ1VSUkVOVCBTQ0hFTUEiLCJTRVQgU0NIRU1BIiwiU0VUIiwiVU5JT04gQUxMIiwiVU5JT04iLCJVUERBVEUiLCJWQUxVRVMiLCJXSEVSRSJdLGk9WyJBTkQiLCJDUk9TUyBBUFBMWSIsIkNST1NTIEpPSU4iLCJFTFNFIiwiSU5ORVIgSk9JTiIsIkpPSU4iLCJMRUZUIEpPSU4iLCJMRUZUIE9VVEVSIEpPSU4iLCJPUiIsIk9VVEVSIEFQUExZIiwiT1VURVIgSk9JTiIsIlJJR0hUIEpPSU4iLCJSSUdIVCBPVVRFUiBKT0lOIiwiV0hFTiIsIlhPUiJdLFM9dm9pZCAwLHU9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKEUpeygwLFRbImRlZmF1bHQiXSkodGhpcyxlKSx0aGlzLmNmZz1FfXJldHVybiBlLnByb3RvdHlwZS5mb3JtYXQ9ZnVuY3Rpb24oZSl7cmV0dXJuIFN8fChTPW5ldyBBWyJkZWZhdWx0Il0oe3Jlc2VydmVkV29yZHM6SSxyZXNlcnZlZFRvcGxldmVsV29yZHM6TyxyZXNlcnZlZE5ld2xpbmVXb3JkczppLHN0cmluZ1R5cGVzOlsnIiInLCJOJyciLCInJyIsImBgIiwiW10iXSxvcGVuUGFyZW5zOlsiKCIsIkNBU0UiXSxjbG9zZVBhcmVuczpbIikiLCJFTkQiXSxpbmRleGVkUGxhY2Vob2xkZXJUeXBlczpbIj8iXSxuYW1lZFBsYWNlaG9sZGVyVHlwZXM6WyJAIiwiOiJdLGxpbmVDb21tZW50VHlwZXM6WyIjIiwiLS0iXX0pKSxuZXcgb1siZGVmYXVsdCJdKHRoaXMuY2ZnLFMpLmZvcm1hdChlKX0sZX0oKTtFWyJkZWZhdWx0Il09dSxlLmV4cG9ydHM9RVsiZGVmYXVsdCJdfSxmdW5jdGlvbihlLEUsdCl7dmFyIG49dCgzKSxyPXQoMiksVD1uKHIsIkRhdGFWaWV3Iik7ZS5leHBvcnRzPVR9LGZ1bmN0aW9uKGUsRSx0KXt2YXIgbj10KDMpLHI9dCgyKSxUPW4ociwiTWFwIik7ZS5leHBvcnRzPVR9LGZ1bmN0aW9uKGUsRSx0KXt2YXIgbj10KDMpLHI9dCgyKSxUPW4ociwiUHJvbWlzZSIpO2UuZXhwb3J0cz1UfSxmdW5jdGlvbihlLEUsdCl7dmFyIG49dCgzKSxyPXQoMiksVD1uKHIsIlNldCIpO2UuZXhwb3J0cz1UfSxmdW5jdGlvbihlLEUsdCl7dmFyIG49dCgyKSxyPW4uU3ltYm9sO2UuZXhwb3J0cz1yfSxmdW5jdGlvbihlLEUsdCl7dmFyIG49dCgzKSxyPXQoMiksVD1uKHIsIldlYWtNYXAiKTtlLmV4cG9ydHM9VH0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUpe3JldHVybiBlLnNwbGl0KCIiKX1lLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUsRSx0LG4pe2Zvcih2YXIgcj1lLmxlbmd0aCxUPXQrKG4/MTotMSk7bj9ULS06KytUPHI7KWlmKEUoZVtUXSxULGUpKXJldHVybiBUOwpyZXR1cm4tMX1lLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUpe3JldHVybiByLmNhbGwoZSl9dmFyIG49T2JqZWN0LnByb3RvdHlwZSxyPW4udG9TdHJpbmc7ZS5leHBvcnRzPXR9LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUsRSx0KXtyZXR1cm4gRT09PUU/UihlLEUsdCk6cihlLFQsdCl9dmFyIHI9dCgyOSksVD10KDMyKSxSPXQoNDkpO2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUpe2Z1bmN0aW9uIHQoZSl7cmV0dXJuIGUhPT1lfWUuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlKXtpZighUihlKXx8VChlKSlyZXR1cm4hMTt2YXIgRT1yKGUpP3U6QTtyZXR1cm4gRS50ZXN0KG8oZSkpfXZhciByPXQoMTIpLFQ9dCg0NSksUj10KDYpLG89dCgxMSksTj0vW1xcXiQuKis/KClbXF17fXxdL2csQT0vXlxbb2JqZWN0IC4rP0NvbnN0cnVjdG9yXF0kLyxJPUZ1bmN0aW9uLnByb3RvdHlwZSxPPU9iamVjdC5wcm90b3R5cGUsaT1JLnRvU3RyaW5nLFM9Ty5oYXNPd25Qcm9wZXJ0eSx1PVJlZ0V4cCgiXiIraS5jYWxsKFMpLnJlcGxhY2UoTiwiXFwkJiIpLnJlcGxhY2UoL2hhc093blByb3BlcnR5fChmdW5jdGlvbikuKj8oPz1cXFwoKXwgZm9yIC4rPyg/PVxcXF0pL2csIiQxLio/IikrIiQiKTtlLmV4cG9ydHM9bn0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUsRSl7dmFyIHQ9IiI7aWYoIWV8fDE+RXx8RT5uKXJldHVybiB0O2RvIEUlMiYmKHQrPWUpLEU9cihFLzIpLEUmJihlKz1lKTt3aGlsZShFKTtyZXR1cm4gdH12YXIgbj05MDA3MTk5MjU0NzQwOTkxLHI9TWF0aC5mbG9vcjtlLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUsRSx0KXt2YXIgbj0tMSxyPWUubGVuZ3RoOzA+RSYmKEU9LUU+cj8wOnIrRSksdD10PnI/cjp0LDA+dCYmKHQrPXIpLHI9RT50PzA6dC1FPj4+MCxFPj4+PTA7Zm9yKHZhciBUPUFycmF5KHIpOysrbjxyOylUW25dPWVbbitFXTtyZXR1cm4gVH1lLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSxFLHQpe3ZhciBuPWUubGVuZ3RoO3JldHVybiB0PXZvaWQgMD09PXQ/bjp0LEV8fG4+dD9yKGUsRSx0KTplfXZhciByPXQoMzUpO2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlLEUpe2Zvcih2YXIgdD1lLmxlbmd0aDt0LS0mJnIoRSxlW3RdLDApPi0xOyk7cmV0dXJuIHR9dmFyIHI9dCgzMSk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSx0KXt2YXIgbj10KDIpLHI9blsiX19jb3JlLWpzX3NoYXJlZF9fIl07ZS5leHBvcnRzPXJ9LGZ1bmN0aW9uKGUsRSl7KGZ1bmN0aW9uKEUpe3ZhciB0PSJvYmplY3QiPT10eXBlb2YgRSYmRSYmRS5PYmplY3Q9PT1PYmplY3QmJkU7ZS5leHBvcnRzPXR9KS5jYWxsKEUsZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30oKSl9LGZ1bmN0aW9uKGUsRSx0KXt2YXIgbj10KDIyKSxyPXQoMjMpLFQ9dCgyNCksUj10KDI1KSxvPXQoMjcpLE49dCgzMCksQT10KDExKSxJPSJbb2JqZWN0IE1hcF0iLE89IltvYmplY3QgT2JqZWN0XSIsaT0iW29iamVjdCBQcm9taXNlXSIsUz0iW29iamVjdCBTZXRdIix1PSJbb2JqZWN0IFdlYWtNYXBdIixMPSJbb2JqZWN0IERhdGFWaWV3XSIsQz1PYmplY3QucHJvdG90eXBlLHM9Qy50b1N0cmluZyxhPUEobiksZj1BKHIpLGM9QShUKSxwPUEoUiksbD1BKG8pLEQ9TjsobiYmRChuZXcgbihuZXcgQXJyYXlCdWZmZXIoMSkpKSE9THx8ciYmRChuZXcgcikhPUl8fFQmJkQoVC5yZXNvbHZlKCkpIT1pfHxSJiZEKG5ldyBSKSE9U3x8byYmRChuZXcgbykhPXUpJiYoRD1mdW5jdGlvbihlKXt2YXIgRT1zLmNhbGwoZSksdD1FPT1PP2UuY29uc3RydWN0b3I6dm9pZCAwLG49dD9BKHQpOnZvaWQgMDtpZihuKXN3aXRjaChuKXtjYXNlIGE6cmV0dXJuIEw7Y2FzZSBmOnJldHVybiBJO2Nhc2UgYzpyZXR1cm4gaTtjYXNlIHA6cmV0dXJuIFM7Y2FzZSBsOnJldHVybiB1fXJldHVybiBFfSksZS5leHBvcnRzPUR9LGZ1bmN0aW9uKGUsRSl7ZnVuY3Rpb24gdChlLEUpe3JldHVybiBudWxsPT1lP3ZvaWQgMDplW0VdfWUuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUpe2Z1bmN0aW9uIHQoZSl7cmV0dXJuIE4udGVzdChlKX12YXIgbj0iXFx1ZDgwMC1cXHVkZmZmIixyPSJcXHUwMzAwLVxcdTAzNmZcXHVmZTIwLVxcdWZlMjMiLFQ9IlxcdTIwZDAtXFx1MjBmMCIsUj0iXFx1ZmUwZVxcdWZlMGYiLG89IlxcdTIwMGQiLE49UmVnRXhwKCJbIitvK24rcitUK1IrIl0iKTtlLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUsRSl7cmV0dXJuIEU9bnVsbD09RT9uOkUsISFFJiYoIm51bWJlciI9PXR5cGVvZiBlfHxyLnRlc3QoZSkpJiZlPi0xJiZlJTE9PTAmJkU+ZX12YXIgbj05MDA3MTk5MjU0NzQwOTkxLHI9L14oPzowfFsxLTldXGQqKSQvO2UuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlLEUsdCl7aWYoIW8odCkpcmV0dXJuITE7dmFyIG49dHlwZW9mIEU7cmV0dXJuISEoIm51bWJlciI9PW4/VCh0KSYmUihFLHQubGVuZ3RoKToic3RyaW5nIj09biYmRSBpbiB0KSYmcih0W0VdLGUpfXZhciByPXQoNTIpLFQ9dCg4KSxSPXQoNDMpLG89dCg2KTtlLmV4cG9ydHM9bn0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSl7cmV0dXJuISFUJiZUIGluIGV9dmFyIHI9dCgzOCksVD1mdW5jdGlvbigpe3ZhciBlPS9bXi5dKyQvLmV4ZWMociYmci5rZXlzJiZyLmtleXMuSUVfUFJPVE98fCIiKTtyZXR1cm4gZT8iU3ltYm9sKHNyYylfMS4iK2U6IiJ9KCk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSl7ZnVuY3Rpb24gdChlKXt2YXIgRT1lJiZlLmNvbnN0cnVjdG9yLHQ9ImZ1bmN0aW9uIj09dHlwZW9mIEUmJkUucHJvdG90eXBlfHxuO3JldHVybiBlPT09dH12YXIgbj1PYmplY3QucHJvdG90eXBlO2UuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUsdCl7dmFyIG49dCg0OCkscj1uKE9iamVjdC5rZXlzLE9iamVjdCk7ZS5leHBvcnRzPXJ9LGZ1bmN0aW9uKGUsRSl7ZnVuY3Rpb24gdChlLEUpe3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gZShFKHQpKX19ZS5leHBvcnRzPXR9LGZ1bmN0aW9uKGUsRSl7ZnVuY3Rpb24gdChlLEUsdCl7Zm9yKHZhciBuPXQtMSxyPWUubGVuZ3RoOysrbjxyOylpZihlW25dPT09RSlyZXR1cm4gbjtyZXR1cm4tMX1lLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSl7cmV0dXJuIFQoZSk/UihlKTpyKGUpfXZhciByPXQoMjgpLFQ9dCg0MiksUj10KDUxKTtlLmV4cG9ydHM9bn0sZnVuY3Rpb24oZSxFKXtmdW5jdGlvbiB0KGUpe3JldHVybiBlLm1hdGNoKGMpfHxbXX12YXIgbj0iXFx1ZDgwMC1cXHVkZmZmIixyPSJcXHUwMzAwLVxcdTAzNmZcXHVmZTIwLVxcdWZlMjMiLFQ9IlxcdTIwZDAtXFx1MjBmMCIsUj0iXFx1ZmUwZVxcdWZlMGYiLG89IlsiK24rIl0iLE49IlsiK3IrVCsiXSIsQT0iXFx1ZDgzY1tcXHVkZmZiLVxcdWRmZmZdIixJPSIoPzoiK04rInwiK0ErIikiLE89IlteIituKyJdIixpPSIoPzpcXHVkODNjW1xcdWRkZTYtXFx1ZGRmZl0pezJ9IixTPSJbXFx1ZDgwMC1cXHVkYmZmXVtcXHVkYzAwLVxcdWRmZmZdIix1PSJcXHUyMDBkIixMPUkrIj8iLEM9IlsiK1IrIl0/IixzPSIoPzoiK3UrIig/OiIrW08saSxTXS5qb2luKCJ8IikrIikiK0MrTCsiKSoiLGE9QytMK3MsZj0iKD86IitbTytOKyI/IixOLGksUyxvXS5qb2luKCJ8IikrIikiLGM9UmVnRXhwKEErIig/PSIrQSsiKXwiK2YrYSwiZyIpO2UuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUpe2Z1bmN0aW9uIHQoZSxFKXtyZXR1cm4gZT09PUV8fGUhPT1lJiZFIT09RX1lLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSxFLHQpe2Z1bmN0aW9uIG4oZSl7cmV0dXJuIGU9cihlKSxlJiZSLnRlc3QoZSk/ZS5yZXBsYWNlKFQsIlxcJCYiKTplfXZhciByPXQoOSksVD0vW1xcXiQuKis/KClbXF17fXxdL2csUj1SZWdFeHAoVC5zb3VyY2UpO2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlKXtyZXR1cm4gcihlKSYmby5jYWxsKGUsImNhbGxlZSIpJiYoIUEuY2FsbChlLCJjYWxsZWUiKXx8Ti5jYWxsKGUpPT1UKX12YXIgcj10KDU2KSxUPSJbb2JqZWN0IEFyZ3VtZW50c10iLFI9T2JqZWN0LnByb3RvdHlwZSxvPVIuaGFzT3duUHJvcGVydHksTj1SLnRvU3RyaW5nLEE9Ui5wcm9wZXJ0eUlzRW51bWVyYWJsZTtlLmV4cG9ydHM9bn0sZnVuY3Rpb24oZSxFKXt2YXIgdD1BcnJheS5pc0FycmF5O2UuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlKXtyZXR1cm4gVChlKSYmcihlKX12YXIgcj10KDgpLFQ9dCgxMyk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSx0KXsoZnVuY3Rpb24oZSl7dmFyIG49dCgyKSxyPXQoNjIpLFQ9Im9iamVjdCI9PXR5cGVvZiBFJiZFJiYhRS5ub2RlVHlwZSYmRSxSPVQmJiJvYmplY3QiPT10eXBlb2YgZSYmZSYmIWUubm9kZVR5cGUmJmUsbz1SJiZSLmV4cG9ydHM9PT1ULE49bz9uLkJ1ZmZlcjp2b2lkIDAsQT1OP04uaXNCdWZmZXI6dm9pZCAwLEk9QXx8cjtlLmV4cG9ydHM9SX0pLmNhbGwoRSx0KDY3KShlKSl9LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUpe2lmKG8oZSkmJihSKGUpfHwic3RyaW5nIj09dHlwZW9mIGV8fCJmdW5jdGlvbiI9PXR5cGVvZiBlLnNwbGljZXx8TihlKXx8VChlKSkpcmV0dXJuIWUubGVuZ3RoO3ZhciBFPXIoZSk7aWYoRT09T3x8RT09aSlyZXR1cm4hZS5zaXplO2lmKEEoZSkpcmV0dXJuIUkoZSkubGVuZ3RoO2Zvcih2YXIgdCBpbiBlKWlmKHUuY2FsbChlLHQpKXJldHVybiExO3JldHVybiEwfXZhciByPXQoNDApLFQ9dCg1NCksUj10KDU1KSxvPXQoOCksTj10KDU3KSxBPXQoNDYpLEk9dCg0NyksTz0iW29iamVjdCBNYXBdIixpPSJbb2JqZWN0IFNldF0iLFM9T2JqZWN0LnByb3RvdHlwZSx1PVMuaGFzT3duUHJvcGVydHk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSl7ZnVuY3Rpb24gdChlKXtyZXR1cm4ibnVtYmVyIj09dHlwZW9mIGUmJmU+LTEmJmUlMT09MCYmbj49ZX12YXIgbj05MDA3MTk5MjU0NzQwOTkxO2UuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUpe2Z1bmN0aW9uIHQoZSl7dmFyIEU9ZT9lLmxlbmd0aDowO3JldHVybiBFP2VbRS0xXTp2b2lkIDB9ZS5leHBvcnRzPXR9LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUsRSx0KXtyZXR1cm4gRT0odD9UKGUsRSx0KTp2b2lkIDA9PT1FKT8xOlIoRSkscihvKGUpLEUpfXZhciByPXQoMzQpLFQ9dCg0NCksUj10KDY0KSxvPXQoOSk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSl7ZnVuY3Rpb24gdCgpe3JldHVybiExfWUuZXhwb3J0cz10fSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlKXtpZighZSlyZXR1cm4gMD09PWU/ZTowO2lmKGU9cihlKSxlPT09VHx8ZT09PS1UKXt2YXIgRT0wPmU/LTE6MTtyZXR1cm4gRSpSfXJldHVybiBlPT09ZT9lOjB9dmFyIHI9dCg2NSksVD0xLzAsUj0xLjc5NzY5MzEzNDg2MjMxNTdlMzA4O2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlKXt2YXIgRT1yKGUpLHQ9RSUxO3JldHVybiBFPT09RT90P0UtdDpFOjB9dmFyIHI9dCg2Myk7ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSx0KXtmdW5jdGlvbiBuKGUpe2lmKCJudW1iZXIiPT10eXBlb2YgZSlyZXR1cm4gZTtpZihUKGUpKXJldHVybiBSO2lmKHIoZSkpe3ZhciBFPSJmdW5jdGlvbiI9PXR5cGVvZiBlLnZhbHVlT2Y/ZS52YWx1ZU9mKCk6ZTtlPXIoRSk/RSsiIjpFfWlmKCJzdHJpbmciIT10eXBlb2YgZSlyZXR1cm4gMD09PWU/ZTorZTtlPWUucmVwbGFjZShvLCIiKTt2YXIgdD1BLnRlc3QoZSk7cmV0dXJuIHR8fEkudGVzdChlKT9PKGUuc2xpY2UoMiksdD8yOjgpOk4udGVzdChlKT9SOitlfXZhciByPXQoNiksVD10KDE0KSxSPU5hTixvPS9eXHMrfFxzKyQvZyxOPS9eWy0rXTB4WzAtOWEtZl0rJC9pLEE9L14wYlswMV0rJC9pLEk9L14wb1swLTddKyQvaSxPPXBhcnNlSW50O2UuZXhwb3J0cz1ufSxmdW5jdGlvbihlLEUsdCl7ZnVuY3Rpb24gbihlLEUsdCl7aWYoZT1OKGUpLGUmJih0fHx2b2lkIDA9PT1FKSlyZXR1cm4gZS5yZXBsYWNlKEEsIiIpO2lmKCFlfHwhKEU9cihFKSkpcmV0dXJuIGU7dmFyIG49byhlKSxJPVIobixvKEUpKSsxO3JldHVybiBUKG4sMCxJKS5qb2luKCIiKX12YXIgcj10KDEwKSxUPXQoMzYpLFI9dCgzNyksbz10KDUwKSxOPXQoOSksQT0vXHMrJC87ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsRSl7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBlLndlYnBhY2tQb2x5ZmlsbHx8KGUuZGVwcmVjYXRlPWZ1bmN0aW9uKCl7fSxlLnBhdGhzPVtdLGUuY2hpbGRyZW49W10sZS53ZWJwYWNrUG9seWZpbGw9MSksZX19XSl9KTsKCgkJZnVuY3Rpb24gZXNjYXBlMkh0bWwoc3RyKSB7CiAgICAJICAgIHZhciBhcnJFbnRpdGllcyA9IHsnbHQnOiAnPCcsICdndCc6ICc+JywgJ25ic3AnOiAnJywgJ2FtcCc6ICcmJywgJ3F1b3QnOiAnIid9OwogICAgCSAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyYobHR8Z3R8bmJzcHxhbXB8cXVvdCk7L2lnLCBmdW5jdGlvbiAoYWxsLCB0KSB7CiAgICAJICAgICAgICByZXR1cm4gYXJyRW50aXRpZXNbdF07CiAgICAJICAgIH0pOwogICAgCX0KCQogICAgCWZ1bmN0aW9uIGxvYWQoKSB7CiAgICAJICAgIGxldCBjb2RlTGlzdCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ2xhbmd1YWdlLXNxbCcpOwoJCiAgICAJICAgIGZvciAobGV0IGkgPSAwIDtpPGNvZGVMaXN0Lmxlbmd0aDtpKyspIHsKICAgIAkgICAgICAgIGNvZGVMaXN0W2ldLmlubmVySFRNTCA9IHdpbmRvdy5zcWxGb3JtYXR0ZXIuZm9ybWF0KGVzY2FwZTJIdG1sKGNvZGVMaXN0W2ldLmlubmVySFRNTCkpCiAgICAJICAgIH0KICAgIAl9Owo=
+`
+
+// MarkdownEscape markdown格式转义,原样输出
+func MarkdownEscape(str string) string {
+	for _, b := range "_`*" {
+		str = strings.Replace(str, string(b), "\\"+string(b), -1)
+	}
+	return str
+}
+
+//
+func loadExternalResource(resource string) string {
+	var content string
+	var body []byte
+	if strings.HasPrefix(resource, "http") {
+		resp, err := http.Get(resource)
+		if err == nil {
+			body, err = ioutil.ReadAll(resp.Body)
+			if err == nil {
+				content = string(body)
+			} else {
+				Log.Debug("ioutil.ReadAll %s Error: %v", resource, err)
+			}
+		} else {
+			Log.Debug("http.Get %s Error: %v", resource, err)
+		}
+		defer resp.Body.Close()
+	} else {
+		fd, err := os.Open(resource)
+		defer func() {
+			err = fd.Close()
+			if err != nil {
+				Log.Error("loadExternalResource(%s) fd.Close failed: %s", resource, err.Error())
+			}
+		}()
+		if err == nil {
+			body, err = ioutil.ReadAll(fd)
+			if err != nil {
+				Log.Debug("ioutil.ReadAll %s Error: %v", resource, err)
+			} else {
+				content = string(body)
+			}
+		} else {
+			Log.Debug("os.Open %s Error: %v", resource, err)
+		}
+	}
+	return content
+}
+
+// MarkdownHTMLHeader markdown 转 HTML 输出时添加 HTML 头
+func MarkdownHTMLHeader() string {
+	// load css
+	var css string
+	if Config.ReportCSS == "" {
+		css = BuiltinCSS
+	} else {
+		css = loadExternalResource(Config.ReportCSS)
+	}
+
+	// load javascript
+	var js string
+	if Config.ReportJavascript == "" {
+		decode, _ := base64.StdEncoding.DecodeString(BuiltinJavascript)
+		js = string(decode)
+	} else {
+		js = loadExternalResource(Config.ReportJavascript)
+	}
+
+	header := `
+
+` + Config.ReportTitle + `
+
+
+
+
+`
+	return header
+}
+
+// Markdown2HTML markdown 转 HTML 输出
+func Markdown2HTML(buf string) string {
+	// extensions default: 94
+	// extensions |= blackfriday.EXTENSION_TABLES
+	// extensions |= blackfriday.EXTENSION_FENCED_CODE
+	// extensions |= blackfriday.EXTENSION_AUTOLINK
+	// extensions |= blackfriday.EXTENSION_STRIKETHROUGH
+	// extensions |= blackfriday.EXTENSION_SPACE_HEADERS
+	extensions := Config.MarkdownExtensions
+
+	// htmlFlags
+	htmlFlags := Config.MarkdownHTMLFlags
+
+	renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
+	buf = string(blackfriday.Markdown([]byte(buf), renderer, extensions))
+	return buf
+}
+
+// Score SQL评审打分
+func Score(score int) string {
+	// 不需要打分的功能
+	switch Config.ReportType {
+	case "duplicate-key-checker", "explain-digest":
+		return ""
+	}
+	s1, s2 := "★ ", "☆ "
+	if score > 100 {
+		score = 100
+		Log.Debug("Score Error: score larger than 100, %d", score)
+	}
+	if score < 0 {
+		score = 0
+		Log.Debug("Score Warn: score less than 0, %d", score)
+	}
+	s1Count := score / 20
+	s2Count := 5 - s1Count
+	str := fmt.Sprintf("%s %d分", strings.TrimSpace(strings.Repeat(s1, s1Count)+strings.Repeat(s2, s2Count)), score)
+	return str
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/markdown_test.go b/vendor/github.com/XiaoMi/soar/common/markdown_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..8788e0dfbac4a06b67f12ef0bba115a8fbec33b0
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/markdown_test.go
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+func TestMarkdownEscape(_ *testing.T) {
+	var strs = []string{
+		"a`bc",
+		"abc",
+		"a'bc",
+		"a\"bc",
+	}
+	for _, str := range strs {
+		fmt.Println(MarkdownEscape(str))
+	}
+}
+
+func TestMarkdown2Html(t *testing.T) {
+	md := filepath.Join("testdata", t.Name()+".md")
+	buf, err := ioutil.ReadFile(md)
+	if err != nil {
+		t.Error(err.Error())
+	}
+	err = GoldenDiff(func() {
+		fmt.Println(Markdown2HTML(string(buf)))
+	}, t.Name(), update)
+	if nil != err {
+		t.Fatal(err)
+	}
+
+	// golden 文件拷贝成 html 文件,这步是给人看的
+	gd, err := os.OpenFile("testdata/"+t.Name()+".golden", os.O_RDONLY, 0666)
+	if nil != err {
+		t.Fatal(err)
+	}
+	html, err := os.OpenFile("testdata/"+t.Name()+".html", os.O_CREATE|os.O_RDWR, 0666)
+	if nil != err {
+		t.Fatal(err)
+	}
+	io.Copy(html, gd)
+}
+
+func TestScore(t *testing.T) {
+	score := Score(50)
+	if score != "★ ★ ☆ ☆ ☆ 50分" {
+		t.Error(score)
+	}
+}
+
+func TestLoadExternalResource(t *testing.T) {
+	buf := loadExternalResource("../doc/themes/github.css")
+	if buf == "" {
+		t.Error("loadExternalResource local error")
+	}
+	buf = loadExternalResource("http://www.baidu.com")
+	if buf == "" {
+		t.Error("loadExternalResource http error")
+	}
+}
+
+func TestMarkdownHTMLHeader(t *testing.T) {
+	err := GoldenDiff(func() {
+		MarkdownHTMLHeader()
+	}, t.Name(), update)
+	if err != nil {
+		t.Error(err)
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/meta.go b/vendor/github.com/XiaoMi/soar/common/meta.go
new file mode 100644
index 0000000000000000000000000000000000000000..433704eff8c0059df662a48542a877a2165707e1
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/meta.go
@@ -0,0 +1,495 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"strconv"
+	"strings"
+)
+
+// Meta 以 'database' 为 key, DB 的 map, 按 db->table->column 组织的元数据
+type Meta map[string]*DB
+
+// DB 数据库相关的结构体
+type DB struct {
+	Name  string
+	Table map[string]*Table // ['table_name']*Table
+}
+
+// NewDB 用于初始化*DB
+func NewDB(db string) *DB {
+	return &DB{
+		Name:  db,
+		Table: make(map[string]*Table),
+	}
+}
+
+// Table 含有表的属性
+type Table struct {
+	TableName    string
+	TableAliases []string
+	Column       map[string]*Column
+}
+
+// NewTable 初始化*Table
+func NewTable(tb string) *Table {
+	return &Table{
+		TableName:    tb,
+		TableAliases: make([]string, 0),
+		Column:       make(map[string]*Column),
+	}
+}
+
+// KeyType 用于标志每个Key的类别
+type KeyType int
+
+// Column 含有列的定义属性
+type Column struct {
+	Name        string   `json:"col_name"`    // 列名
+	Alias       []string `json:"alias"`       // 别名
+	Table       string   `json:"tb_name"`     // 表名
+	DB          string   `json:"db_name"`     // 数据库名称
+	DataType    string   `json:"data_type"`   // 数据类型
+	Character   string   `json:"character"`   // 字符集
+	Collation   string   `json:"collation"`   // collation
+	Cardinality float64  `json:"cardinality"` // 散粒度
+	Null        string   `json:"null"`        // 是否为空: YES/NO
+	Key         string   `json:"key"`         // 键类型
+	Default     string   `json:"default"`     // 默认值
+	Extra       string   `json:"extra"`       // 其他
+	Comment     string   `json:"comment"`     // 备注
+	Privileges  string   `json:"privileges"`  // 权限
+}
+
+// TableColumns 这个结构体中的元素是有序的  map[db]map[table][]columns
+type TableColumns map[string]map[string][]*Column
+
+// Equal 判断两个column是否相等
+func (col *Column) Equal(column *Column) bool {
+	return col.Name == column.Name &&
+		col.Table == column.Table &&
+		col.DB == column.DB
+}
+
+// IsColsPart 判断两个column队列是否是包含关系(包括相等)
+func IsColsPart(a, b []*Column) bool {
+	times := len(a)
+	if len(b) < times {
+		times = len(b)
+	}
+
+	for i := 0; i < times; i++ {
+		if a[i].DB != b[i].DB || a[i].Table != b[i].Table || a[i].Name != b[i].Name {
+			return false
+		}
+	}
+
+	return true
+}
+
+// JoinColumnsName 将所有的列合并
+func JoinColumnsName(cols []*Column, sep string) string {
+	name := ""
+	for _, col := range cols {
+		name += col.Name + sep
+	}
+	return strings.Trim(name, sep)
+}
+
+// Tables 获取 Meta 中指定 db 的所有表名
+// Input:数据库名
+// Output:表名组成的list
+func (b Meta) Tables(db string) []string {
+	var result []string
+	if b[db] != nil {
+		for tb := range b[db].Table {
+			result = append(result, tb)
+		}
+
+	}
+	return result
+}
+
+// SetDefault 设置默认值
+func (b Meta) SetDefault(defaultDB string) Meta {
+	if defaultDB == "" {
+		return b
+	}
+
+	for db := range b {
+		if db == "" {
+			// 当获取到的 join 中的 DB 为空的时候,说明 SQL 未显示的指定 DB,即使用的是 rEnv 默认 DB, 需要将表合并到原 DB 中
+			if _, ok := b[defaultDB]; ok {
+				for tbName, table := range b[""].Table {
+					if _, ok := b[defaultDB].Table[tbName]; ok {
+						b[defaultDB].Table[tbName].TableAliases = append(
+							b[defaultDB].Table[tbName].TableAliases,
+							table.TableAliases...,
+						)
+						continue
+					}
+					b[defaultDB].Table[tbName] = table
+				}
+				delete(b, "")
+			}
+
+			// 如果没有出现DB指定不一致的情况,直接进行合并
+			b[defaultDB] = b[""]
+			delete(b, "")
+		}
+	}
+
+	return b
+}
+
+// MergeColumn 将使用到的列按 db->table 组织去重
+// 注意:Column 中的 db, table 信息可能为空,需要提前通过env环境补齐再调用该函数。
+// @input: 目标列list, 源列list(可以将多个源合并到一个目标列list)
+// @output: 合并后的列list
+func MergeColumn(dst []*Column, src ...*Column) []*Column {
+	var tmp []*Column
+	for _, newCol := range src {
+		if len(dst) == 0 {
+			tmp = append(tmp, newCol)
+			continue
+		}
+
+		has := false
+		for _, oldCol := range dst {
+			if (newCol.Name == oldCol.Name) && (newCol.Table == oldCol.Table) && (newCol.DB == oldCol.DB) {
+				has = true
+			}
+		}
+
+		if !has {
+			tmp = append(tmp, newCol)
+		}
+
+	}
+	return append(dst, tmp...)
+}
+
+// ColumnSort 通过散粒度对 colList 进行排序, 散粒度排序由大到小
+func ColumnSort(colList []*Column) []*Column {
+	// 使用冒泡排序保持相等情况下左右两边顺序不变
+	if len(colList) < 2 {
+		return colList
+	}
+
+	for i := 0; i < len(colList)-1; i++ {
+		for j := i + 1; j < len(colList); j++ {
+			if colList[i].Cardinality < colList[j].Cardinality {
+				colList[i], colList[j] = colList[j], colList[i]
+			}
+		}
+	}
+
+	return colList
+}
+
+// GetDataTypeBase 获取dataType中的数据类型,忽略长度
+func GetDataTypeBase(dataType string) string {
+	if i := strings.Index(dataType, "("); i > 0 {
+		return dataType[0:i]
+	}
+
+	return dataType
+}
+
+// GetDataTypeLength 获取dataType中的数据类型长度
+func GetDataTypeLength(dataType string) []int {
+	var length []int
+	if si := strings.Index(dataType, "("); si > 0 {
+		dataLength := dataType[si+1:]
+		if ei := strings.Index(dataLength, ")"); ei > 0 {
+			dataLength = dataLength[:ei]
+			for _, l := range strings.Split(dataLength, ",") {
+				v, err := strconv.Atoi(l)
+				if err != nil {
+					Log.Debug("GetDataTypeLength() Error: %v", err)
+					return []int{-1}
+				}
+				length = append(length, v)
+			}
+		}
+	}
+
+	if len(length) == 0 {
+		length = []int{-1}
+	}
+
+	return length
+}
+
+// GetDataBytes 计算数据类型字节数
+// https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html
+// return -1 表示该列无法计算数据大小
+func (col *Column) GetDataBytes(dbVersion int) int {
+	if col.DataType == "" {
+		Log.Warning("Can't get %s.%s data type", col.Table, col.Name)
+		return -1
+	}
+	switch strings.ToLower(GetDataTypeBase(col.DataType)) {
+	case "tinyint", "smallint", "mediumint",
+		"int", "integer", "bigint",
+		"double", "real", "float", "decimal",
+		"numeric", "bit":
+		// numeric
+		return numericStorageReq(col.DataType)
+
+	case "year", "date", "time", "datetime", "timestamp":
+		// date & time
+		return timeStorageReq(col.DataType, dbVersion)
+
+	case "char", "binary", "varchar", "varbinary", "enum", "set":
+		// string
+		return StringStorageReq(col.DataType, col.Character)
+	case "tinyblob", "tinytext", "blob", "text", "mediumblob", "mediumtext",
+		"longblob", "longtext":
+		// strings length depend on it's values
+		// 这些字段为不定长字段,添加索引时必须指定前缀,索引前缀与字符集相关
+		return Config.MaxIdxBytesPerColumn + 1
+	default:
+		Log.Warning("Type %s not support:", col.DataType)
+		return -1
+	}
+}
+
+// Numeric Type Storage Requirements
+// return bytes count
+func numericStorageReq(dataType string) int {
+	typeLength := GetDataTypeLength(dataType)
+	baseType := strings.ToLower(GetDataTypeBase(dataType))
+
+	switch baseType {
+	case "tinyint":
+		return 1
+	case "smallint":
+		return 2
+	case "mediumint":
+		return 3
+	case "int", "integer":
+		return 4
+	case "bigint", "double", "real":
+		return 8
+	case "float":
+		if typeLength[0] == -1 || typeLength[0] >= 0 && typeLength[0] <= 24 {
+			// 4 bytes if 0 <= p <= 24
+			return 4
+		}
+		// 8 bytes if no p || 25 <= p <= 53
+		return 8
+	case "decimal", "numeric":
+		// Values for DECIMAL (and NUMERIC) columns are represented using a binary format
+		// that packs nine decimal (base 10) digits into four bytes. Storage for the integer
+		// and fractional parts of each value are determined separately. Each multiple of nine
+		// digits requires four bytes, and the “leftover” digits require some fraction of four bytes.
+
+		if typeLength[0] == -1 {
+			return 4
+		}
+
+		leftover := func(leftover int) int {
+			if leftover > 0 && leftover <= 2 {
+				return 1
+			} else if leftover > 2 && leftover <= 4 {
+				return 2
+			} else if leftover > 4 && leftover <= 6 {
+				return 3
+			} else if leftover > 6 && leftover <= 8 {
+				return 4
+			} else {
+				return 4
+			}
+		}
+
+		integer := typeLength[0]/9*4 + leftover(typeLength[0]%9)
+		fractional := typeLength[1]/9*4 + leftover(typeLength[1]%9)
+
+		return integer + fractional
+
+	case "bit":
+		// approximately (M+7)/8 bytes
+		if typeLength[0] == -1 {
+			return 1
+		}
+		return (typeLength[0] + 7) / 8
+
+	default:
+		Log.Error("No such numeric type: %s", baseType)
+		return 8
+	}
+}
+
+// Date and Time Type Storage Requirements
+// return bytes count
+func timeStorageReq(dataType string, version int) int {
+	/*
+			https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html
+			*   ============================================================================================
+			*   |	Data Type |	Storage Required Before MySQL 5.6.4	| Storage Required as of MySQL 5.6.4   |
+			*   | ---------------------------------------------------------------------------------------- |
+			*   |	YEAR	  |	1 byte	                            | 1 byte                               |
+			*   |	DATE	  | 3 bytes	                            | 3 bytes                              |
+			*   |	TIME	  | 3 bytes	                            | 3 bytes + fractional seconds storage |
+			*   |	DATETIME  | 8 bytes	                            | 5 bytes + fractional seconds storage |
+			*   |	TIMESTAMP |	4 bytes	                            | 4 bytes + fractional seconds storage |
+			*   ============================================================================================
+			*	|  Fractional Seconds Precision |Storage Required  |
+			*   | ------------------------------------------------ |
+			*	|  0	    					|0 bytes		   |
+			*	|  1, 2						    |1 byte            |
+			*	|  3, 4						    |2 bytes           |
+			*	|  5, 6						    |3 bytes           |
+		    *   ====================================================
+	*/
+
+	typeLength := GetDataTypeLength(dataType)
+
+	extr := func(length int) int {
+		if length > 0 && length <= 2 {
+			return 1
+		} else if length > 2 && length <= 4 {
+			return 2
+		} else if length > 4 && length <= 6 || length > 6 {
+			return 3
+		}
+		return 0
+	}
+
+	switch strings.ToLower(GetDataTypeBase(dataType)) {
+	case "year":
+		return 1
+	case "date":
+		return 3
+	case "time":
+		if version < 50604 {
+			return 3
+		}
+		// 3 bytes + fractional seconds storage
+		return 3 + extr(typeLength[0])
+	case "datetime":
+		if version < 50604 {
+			return 8
+		}
+		// 5 bytes + fractional seconds storage
+		return 5 + extr(typeLength[0])
+	case "timestamp":
+		if version < 50604 {
+			return 4
+		}
+		// 4 bytes + fractional seconds storage
+		return 4 + extr(typeLength[0])
+	default:
+		return 8
+	}
+}
+
+// SHOW CHARACTER SET
+
+// CharSets character bytes per charcharacter bytes per char
+var CharSets = map[string]int{
+	"armscii8": 1,
+	"ascii":    1,
+	"big5":     2,
+	"binary":   1,
+	"cp1250":   1,
+	"cp1251":   1,
+	"cp1256":   1,
+	"cp1257":   1,
+	"cp850":    1,
+	"cp852":    1,
+	"cp866":    1,
+	"cp932":    2,
+	"dec8":     1,
+	"eucjpms":  3,
+	"euckr":    2,
+	"gb18030":  4,
+	"gb2312":   2,
+	"gbk":      2,
+	"geostd8":  1,
+	"greek":    1,
+	"hebrew":   1,
+	"hp8":      1,
+	"keybcs2":  1,
+	"koi8r":    1,
+	"koi8u":    1,
+	"latin1":   1,
+	"latin2":   1,
+	"latin5":   1,
+	"latin7":   1,
+	"macce":    1,
+	"macroman": 1,
+	"sjis":     2,
+	"swe7":     1,
+	"tis620":   1,
+	"ucs2":     2,
+	"ujis":     3,
+	"utf16":    4,
+	"utf16le":  4,
+	"utf32":    4,
+	"utf8":     3,
+	"utf8mb4":  4,
+}
+
+// StringStorageReq String Type Storage Requirements return bytes count
+func StringStorageReq(dataType string, charset string) int {
+	// get bytes per character, default 1
+	bysPerChar := 1
+	if _, ok := CharSets[strings.ToLower(charset)]; ok {
+		bysPerChar = CharSets[strings.ToLower(charset)]
+	}
+
+	// get length
+	typeLength := GetDataTypeLength(dataType)
+	if typeLength[0] == -1 {
+		return 0
+	}
+
+	// get type
+	baseType := strings.ToLower(GetDataTypeBase(dataType))
+
+	switch baseType {
+	case "char":
+		// Otherwise, M × w bytes, <= M <= 255,
+		// where w is the number of bytes required for the maximum-length character in the character set.
+		if typeLength[0] > 255 {
+			typeLength[0] = 255
+		}
+		return typeLength[0] * bysPerChar
+	case "binary":
+		// M bytes, 0 <= M <= 255
+		if typeLength[0] > 255 {
+			typeLength[0] = 255
+		}
+		return typeLength[0]
+	case "varchar", "varbinary":
+		if typeLength[0] < 255 {
+			return typeLength[0]*bysPerChar + 1
+		}
+		return typeLength[0]*bysPerChar + 2
+
+	case "enum":
+		// 1 or 2 bytes, depending on the number of enumeration values (65,535 values maximum)
+		return 2
+	case "set":
+		// 1, 2, 3, 4, or 8 bytes, depending on the number of set members (64 members maximum)
+		return 8
+	default:
+		return 0
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/meta_test.go b/vendor/github.com/XiaoMi/soar/common/meta_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c6e8080dad5125774b827e0b4e76318569a3fe6e
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/meta_test.go
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"testing"
+)
+
+func TestGetDataTypeLength(t *testing.T) {
+	typeList := map[string][]int{
+		"varchar(20)":  {20},
+		"int(2)":       {2},
+		"int(2000000)": {2000000},
+		"DECIMAL(1,2)": {1, 2},
+		"int":          {-1},
+	}
+
+	for typ, want := range typeList {
+		got := GetDataTypeLength(typ)
+		for i := 0; i < len(want); i++ {
+			if want[i] != got[i] {
+				t.Errorf("Not match, want %v, got %v", want, got)
+			}
+		}
+	}
+
+}
+
+func TestGetDataTypeBase(t *testing.T) {
+	typeList := map[string]string{
+		"varchar(20)":  "varchar",
+		"int(2)":       "int",
+		"int(2000000)": "int",
+	}
+
+	for typ := range typeList {
+		if got := GetDataTypeBase(typ); got != typeList[typ] {
+			t.Errorf("Not match, want %s, got %s", typeList[typ], got)
+		}
+	}
+
+}
+
+func TestGetDataBytes(t *testing.T) {
+	cols50604 := map[*Column]int{
+		// numeric type
+		{Name: "col000", DataType: "tinyint", Character: "utf8"}:        1,
+		{Name: "col001", DataType: "SMALLINT", Character: "utf8"}:       2,
+		{Name: "col002", DataType: "MEDIUMINT", Character: "utf8"}:      3,
+		{Name: "col003", DataType: "int(32)", Character: "utf8"}:        4,
+		{Name: "col004", DataType: "integer(32)", Character: "utf8"}:    4,
+		{Name: "col005", DataType: "bigint(10)", Character: "utf8"}:     8,
+		{Name: "col006", DataType: "float(12)", Character: "utf8"}:      4,
+		{Name: "col007", DataType: "float(50)", Character: "utf8"}:      8,
+		{Name: "col008", DataType: "float(100)", Character: "utf8"}:     8,
+		{Name: "col009", DataType: "float", Character: "utf8"}:          4,
+		{Name: "col010", DataType: "double", Character: "utf8"}:         8,
+		{Name: "col011", DataType: "real", Character: "utf8"}:           8,
+		{Name: "col012", DataType: "BIT(32)", Character: "utf8"}:        4,
+		{Name: "col013", DataType: "numeric(32,32)", Character: "utf8"}: 30,
+		{Name: "col013", DataType: "decimal(2,32)", Character: "utf8"}:  16,
+		{Name: "col014", DataType: "BIT(32)", Character: "utf8"}:        4,
+
+		// date & time
+		{Name: "col015", DataType: "year(32)", Character: "utf8mb4"}:      1,
+		{Name: "col016", DataType: "date", Character: "utf8mb4"}:          3,
+		{Name: "col017", DataType: "time", Character: "utf8mb4"}:          3,
+		{Name: "col018", DataType: "time(0)", Character: "utf8mb4"}:       3,
+		{Name: "col019", DataType: "time(2)", Character: "utf8mb4"}:       4,
+		{Name: "col020", DataType: "time(4)", Character: "utf8mb4"}:       5,
+		{Name: "col021", DataType: "time(6)", Character: "utf8mb4"}:       6,
+		{Name: "col022", DataType: "datetime", Character: "utf8mb4"}:      5,
+		{Name: "col023", DataType: "timestamp(32)", Character: "utf8mb4"}: 7,
+
+		// string
+		{Name: "col024", DataType: "varchar(255)", Character: "utf8"}:    767,
+		{Name: "col025", DataType: "varchar(191)", Character: "utf8mb4"}: 765,
+	}
+
+	for col, bytes := range cols50604 {
+		if got := col.GetDataBytes(50604); got != bytes {
+			t.Errorf("Version 5.6.4, %s Not match, want %d, got %d", col.Name, bytes, got)
+		}
+	}
+
+	cols50500 := map[*Column]int{
+		// numeric type
+		{Name: "col000", DataType: "tinyint", Character: "utf8"}:        1,
+		{Name: "col001", DataType: "SMALLINT", Character: "utf8"}:       2,
+		{Name: "col002", DataType: "MEDIUMINT", Character: "utf8"}:      3,
+		{Name: "col003", DataType: "int(32)", Character: "utf8"}:        4,
+		{Name: "col004", DataType: "integer(32)", Character: "utf8"}:    4,
+		{Name: "col005", DataType: "bigint(10)", Character: "utf8"}:     8,
+		{Name: "col006", DataType: "float(12)", Character: "utf8"}:      4,
+		{Name: "col007", DataType: "float(50)", Character: "utf8"}:      8,
+		{Name: "col008", DataType: "float(100)", Character: "utf8"}:     8,
+		{Name: "col009", DataType: "float", Character: "utf8"}:          4,
+		{Name: "col010", DataType: "double", Character: "utf8"}:         8,
+		{Name: "col011", DataType: "real", Character: "utf8"}:           8,
+		{Name: "col012", DataType: "BIT(32)", Character: "utf8"}:        4,
+		{Name: "col013", DataType: "numeric(32,32)", Character: "utf8"}: 30,
+		{Name: "col013", DataType: "decimal(2,32)", Character: "utf8"}:  16,
+		{Name: "col014", DataType: "BIT(32)", Character: "utf8"}:        4,
+
+		// date & time
+		{Name: "col015", DataType: "year(32)", Character: "utf8mb4"}:      1,
+		{Name: "col016", DataType: "date", Character: "utf8mb4"}:          3,
+		{Name: "col017", DataType: "time", Character: "utf8mb4"}:          3,
+		{Name: "col018", DataType: "time(0)", Character: "utf8mb4"}:       3,
+		{Name: "col019", DataType: "time(2)", Character: "utf8mb4"}:       3,
+		{Name: "col020", DataType: "time(4)", Character: "utf8mb4"}:       3,
+		{Name: "col021", DataType: "time(6)", Character: "utf8mb4"}:       3,
+		{Name: "col022", DataType: "datetime", Character: "utf8mb4"}:      8,
+		{Name: "col023", DataType: "timestamp(32)", Character: "utf8mb4"}: 4,
+
+		// string
+		{Name: "col024", DataType: "varchar(255)", Character: "utf8"}:    767,
+		{Name: "col025", DataType: "varchar(191)", Character: "utf8mb4"}: 765,
+	}
+
+	for col, bytes := range cols50500 {
+		if got := col.GetDataBytes(50500); got != bytes {
+			t.Errorf("Version: 5.5.0, %s Not match, want %d, got %d", col.Name, bytes, got)
+		}
+	}
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/signal.go b/vendor/github.com/XiaoMi/soar/common/signal.go
new file mode 100644
index 0000000000000000000000000000000000000000..79ae5ca963dfada77453deb76317fb4f12a00150
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/signal.go
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+)
+
+// HandleSignal 当程序卡死的时候,或者由于某些原因程序没有退出,可以通过捕获信号量的形式让程序优雅退出并且清理测试环境
+func HandleSignal(f func()) {
+	sc := make(chan os.Signal, 1)
+	signal.Notify(sc,
+		syscall.SIGHUP,
+		syscall.SIGINT,
+		syscall.SIGTERM,
+		syscall.SIGQUIT)
+
+	go func() {
+		n := <-sc
+		Log.Info("receive signal %v, closing", n)
+		f()
+	}()
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/signal_test.go b/vendor/github.com/XiaoMi/soar/common/signal_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..853a2fa2dea225ebdca072ce4daa9fa1f294fbf0
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/signal_test.go
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestHandleSignal(t *testing.T) {
+	HandleSignal(func() {
+		fmt.Println("done")
+	})
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/tricks.go b/vendor/github.com/XiaoMi/soar/common/tricks.go
new file mode 100644
index 0000000000000000000000000000000000000000..9e89a5795127ed0709a510dafbb5e2271dd4a916
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/tricks.go
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 common
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"sort"
+)
+
+// GoldenDiff 从 gofmt 学来的测试方法
+// https://medium.com/soon-london/testing-with-golden-files-in-go-7fccc71c43d3
+func GoldenDiff(f func(), name string, update *bool) error {
+	var b bytes.Buffer
+	w := bufio.NewWriter(&b)
+	str := captureOutput(f)
+	_, err := w.WriteString(str)
+	if err != nil {
+		Log.Warning(err.Error())
+	}
+	err = w.Flush()
+	if err != nil {
+		Log.Warning(err.Error())
+	}
+
+	gp := filepath.Join("testdata", name+".golden")
+	if *update {
+		if err = ioutil.WriteFile(gp, b.Bytes(), 0644); err != nil {
+			err = fmt.Errorf("%s failed to update golden file: %s", name, err)
+			return err
+		}
+	}
+	g, err := ioutil.ReadFile(gp)
+	if err != nil {
+		err = fmt.Errorf("%s failed reading .golden: %s", name, err)
+	}
+	if !bytes.Equal(b.Bytes(), g) {
+		err = fmt.Errorf("%s does not match .golden file", name)
+	}
+	return err
+}
+
+// captureOutput 获取函数标准输出
+func captureOutput(f func()) string {
+	// keep backup of the real stdout
+	oldStdout := os.Stdout
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
+	// execute function
+	f()
+
+	outC := make(chan string)
+	// copy the output in a separate goroutine so printing can't block indefinitely
+	go func() {
+		var buf bytes.Buffer
+		_, err := io.Copy(&buf, r)
+		if err != nil {
+			Log.Warning(err.Error())
+		}
+		outC <- buf.String()
+	}()
+
+	// back to normal state
+	err := w.Close()
+	if err != nil {
+		Log.Warning(err.Error())
+	}
+	os.Stdout = oldStdout // restoring the real stdout
+	out := <-outC
+	os.Stdout = oldStdout
+	return out
+}
+
+// SortedKey sort map[string]interface{}, use in range clause
+func SortedKey(m interface{}) []string {
+	var keys []string
+	switch reflect.TypeOf(m).Kind() {
+	case reflect.Map:
+		switch reflect.TypeOf(m).Key().Kind() {
+		case reflect.String:
+			for _, k := range reflect.ValueOf(m).MapKeys() {
+				keys = append(keys, k.String())
+			}
+		}
+	}
+	sort.Strings(keys)
+	return keys
+}
diff --git a/vendor/github.com/XiaoMi/soar/common/version.go b/vendor/github.com/XiaoMi/soar/common/version.go
new file mode 100644
index 0000000000000000000000000000000000000000..d26a3b848966b602ac98142d83cfad37d414ea28
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/common/version.go
@@ -0,0 +1,10 @@
+package common
+
+// -version输出信息
+const (
+	Version  = "2018-11-27 09:12:27 +0800 v0.8.1-112-gbbf012d"
+	Compile  = "2018-11-27 11:33:40 +0800 by go version go1.10.4 darwin/amd64"
+	Branch   = "master"
+	GitDirty = 35486
+	DevPath  = "/Users/lpx/code/gopath/src/github.com/XiaoMi/soar"
+)
diff --git a/vendor/github.com/XiaoMi/soar/database/doc.go b/vendor/github.com/XiaoMi/soar/database/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..9deb6a09a5388efe574e3cc12280584142f7979d
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/database/doc.go
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 database will take cover of communicate with mysql database.
+package database
diff --git a/vendor/github.com/XiaoMi/soar/database/explain.go b/vendor/github.com/XiaoMi/soar/database/explain.go
new file mode 100644
index 0000000000000000000000000000000000000000..0e17e6479ca31dab4331487e06a6d9834392ed50
--- /dev/null
+++ b/vendor/github.com/XiaoMi/soar/database/explain.go
@@ -0,0 +1,1095 @@
+/*
+ * Copyright 2018 Xiaomi, Inc.
+ *
+ * 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 database
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+
+	"github.com/XiaoMi/soar/ast"
+	"github.com/XiaoMi/soar/common"
+
+	tidb "github.com/pingcap/parser/ast"
+	"github.com/tidwall/gjson"
+	"vitess.io/vitess/go/vt/sqlparser"
+)
+
+// format_type 支持的输出格式
+// https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
+const (
+	TraditionalFormatExplain = iota // 默认输出
+	JSONFormatExplain               // JSON格式输出
+)
+
+// ExplainFormatType EXPLAIN 支持的 FORMAT_TYPE
+var ExplainFormatType = map[string]int{
+	"traditional": 0,
+	"json":        1,
+}
+
+// explain_type
+const (
+	TraditionalExplainType = iota // 默认转出
+	ExtendedExplainType           // EXTENDED输出
+	PartitionsExplainType         // PARTITIONS输出
+)
+
+// ExplainType EXPLAIN命令支持的参数
+var ExplainType = map[string]int{
+	"traditional": 0,
+	"extended":    1,
+	"partitions":  2,
+}
+
+// 为TraditionalFormatExplain准备的结构体 { start
+
+// ExplainInfo 用于存放Explain信息
+type ExplainInfo struct {
+	SQL           string
+	ExplainFormat int
+	ExplainRows   []*ExplainRow
+	ExplainJSON   *ExplainJSON
+	Warnings      []*ExplainWarning
+	QueryCost     float64
+}
+
+// ExplainRow 单行Explain
+type ExplainRow struct {
+	ID           int
+	SelectType   string
+	TableName    string
+	Partitions   string // explain partitions
+	AccessType   string
+	PossibleKeys []string
+	Key          string
+	KeyLen       string // 索引长度,如果发生了index_merge, KeyLen 格式为 N,N,所以不能定义为整型
+	Ref          []string
+	Rows         int
+	Filtered     float64 // 5.6 JSON, 5.7+, 5.5 EXTENDED
+	Scalability  string  // O(1), O(n), O(log n), O(log n)+
+	Extra        string
+}
+
+// ExplainWarning explain extended 后 SHOW WARNINGS 输出的结果
+type ExplainWarning struct {
+	Level   string
+	Code    int
+	Message string
+}
+
+// 为TraditionalFormatExplain准备的结构体 end }
+
+// 为JSONFormatExplain准备的结构体 { start
+
+// ExplainJSONCostInfo JSON
+type ExplainJSONCostInfo struct {
+	ReadCost        string `json:"read_cost"`
+	EvalCost        string `json:"eval_cost"`
+	PrefixCost      string `json:"prefix_cost"`
+	DataReadPerJoin string `json:"data_read_per_join"`
+	QueryCost       string `json:"query_cost"`
+	SortCost        string `json:"sort_cost"`
+}
+
+// ExplainJSONMaterializedFromSubquery JSON
+type ExplainJSONMaterializedFromSubquery struct {
+	UsingTemporaryTable bool                   `json:"using_temporary_table"`
+	Dependent           bool                   `json:"dependent"`
+	Cacheable           bool                   `json:"cacheable"`
+	QueryBlock          *ExplainJSONQueryBlock `json:"query_block"`
+}
+
+// 该变量用于存放 JSON 到 Traditional 模式的所有 ExplainJSONTable
+var explainJSONTables []*ExplainJSONTable
+
+// ExplainJSONTable JSON
+type ExplainJSONTable struct {
+	TableName                string                              `json:"table_name"`
+	AccessType               string                              `json:"access_type"`
+	PossibleKeys             []string                            `json:"possible_keys"`
+	Key                      string                              `json:"key"`
+	UsedKeyParts             []string                            `json:"used_key_parts"`
+	KeyLength                string                              `json:"key_length"`
+	Ref                      []string                            `json:"ref"`
+	RowsExaminedPerScan      int                                 `json:"rows_examined_per_scan"`
+	RowsProducedPerJoin      int                                 `json:"rows_produced_per_join"`
+	Filtered                 string                              `json:"filtered"`
+	UsingIndex               bool                                `json:"using_index"`
+	UsingIndexForGroupBy     bool                                `json:"using_index_for_group_by"`
+	CostInfo                 ExplainJSONCostInfo                 `json:"cost_info"`
+	UsedColumns              []string                            `json:"used_columns"`
+	AttachedCondition        string                              `json:"attached_condition"`
+	AttachedSubqueries       []ExplainJSONSubqueries             `json:"attached_subqueries"`
+	MaterializedFromSubquery ExplainJSONMaterializedFromSubquery `json:"materialized_from_subquery"`
+}
+
+// ExplainJSONNestedLoop JSON
+type ExplainJSONNestedLoop struct {
+	Table ExplainJSONTable `json:"table"`
+}
+
+// ExplainJSONBufferResult JSON
+type ExplainJSONBufferResult struct {
+	UsingTemporaryTable bool                    `json:"using_temporary_table"`
+	NestedLoop          []ExplainJSONNestedLoop `json:"nested_loop"`
+}
+
+// ExplainJSONSubqueries JSON
+type ExplainJSONSubqueries struct {
+	Dependent  bool                  `json:"dependent"`
+	Cacheable  bool                  `json:"cacheable"`
+	QueryBlock ExplainJSONQueryBlock `json:"query_block"`
+}
+
+// ExplainJSONGroupingOperation JSON
+type ExplainJSONGroupingOperation struct {
+	UsingTemporaryTable bool                    `json:"using_temporary_table"`
+	UsingFilesort       bool                    `json:"using_filesort"`
+	Table               ExplainJSONTable        `json:"table"`
+	CostInfo            ExplainJSONCostInfo     `json:"cost_info"`
+	NestedLoop          []ExplainJSONNestedLoop `json:"nested_loop"`
+	GroupBySubqueries   []ExplainJSONSubqueries `json:"group_by_subqueries"`
+}
+
+// ExplainJSONDuplicatesRemoval JSON
+type ExplainJSONDuplicatesRemoval struct {
+	UsingTemporaryTable bool                         `json:"using_temporary_table"`
+	UsingFilesort       bool                         `json:"using_filesort"`
+	BufferResult        ExplainJSONBufferResult      `json:"buffer_result"`
+	GroupingOperation   ExplainJSONGroupingOperation `json:"grouping_operation"`
+}
+
+// ExplainJSONOrderingOperation JSON
+type ExplainJSONOrderingOperation struct {
+	UsingFilesort     bool                         `json:"using_filesort"`
+	Table             ExplainJSONTable             `json:"table"`
+	DuplicatesRemoval ExplainJSONDuplicatesRemoval `json:"duplicates_removal"`
+	GroupingOperation ExplainJSONGroupingOperation `json:"grouping_operation"`
+	OrderbySubqueries []ExplainJSONSubqueries      `json:"order_by_subqueries"`
+}
+
+// ExplainJSONQueryBlock JSON
+type ExplainJSONQueryBlock struct {
+	SelectID                int                          `json:"select_id"`
+	CostInfo                ExplainJSONCostInfo          `json:"cost_info"`
+	Table                   ExplainJSONTable             `json:"table"`
+	NestedLoop              []ExplainJSONNestedLoop      `json:"nested_loop"`
+	OrderingOperation       ExplainJSONOrderingOperation `json:"ordering_operation"`
+	GroupingOperation       ExplainJSONGroupingOperation `json:"grouping_operation"`
+	OptimizedAwaySubqueries []ExplainJSONSubqueries      `json:"optimized_away_subqueries"`
+	HavingSubqueries        []ExplainJSONSubqueries      `json:"having_subqueries"`
+	SelectListSubqueries    []ExplainJSONSubqueries      `json:"select_list_subqueries"`
+	UpdateValueSubqueries   []ExplainJSONSubqueries      `json:"update_value_subqueries"`
+	QuerySpecifications     []ExplainJSONSubqueries      `json:"query_specifications"`
+	UnionResult             ExplainJSONUnionResult       `json:"union_result"`
+	Message                 string                       `json:"message"`
+}
+
+// ExplainJSONUnionResult JSON
+type ExplainJSONUnionResult struct {
+	UsingTemporaryTable bool                    `json:"using_temporary_table"`
+	TableName           string                  `json:"table_name"`
+	AccessType          string                  `json:"access_type"`
+	QuerySpecifications []ExplainJSONSubqueries `json:"query_specifications"`
+}
+
+// ExplainJSON 根结点
+type ExplainJSON struct {
+	QueryBlock ExplainJSONQueryBlock `json:"query_block"`
+}
+
+// 为JSONFormatExplain准备的结构体 end }
+
+// ExplainKeyWords 需要解释的关键字
+var ExplainKeyWords = []string{
+	"access_type",
+	"attached_condition",
+	"attached_subqueries",
+	"buffer_result",
+	"cacheable",
+	"cost_info",
+	"data_read_per_join",
+	"dependent",
+	"duplicates_removal",
+	"eval_cost",
+	"filtered",
+	"group_by_subqueries",
+	"grouping_operation",
+	"having_subqueries",
+	"key",
+	"key_length",
+	"materialized_from_subquery",
+	"message",
+	"nested_loop",
+	"optimized_away_subqueries",
+	"order_by_subqueries",
+	"ordering_operation",
+	"possible_keys",
+	"prefix_cost",
+	"query_block",
+	"query_cost",
+	"query_specifications",
+	"read_cost",
+	"ref",
+	"rows_examined_per_scan",
+	"rows_produced_per_join",
+	"select_id",
+	"select_list_subqueries",
+	"sort_cost",
+	"table",
+	"table_name",
+	"union_result",
+	"update_value_subqueries",
+	"used_columns",
+	"used_key_parts",
+	"using_filesort",
+	"using_index",
+	"using_index_for_group_by",
+	"using_temporary_table",
+}
+
+// ExplainColumnIndent EXPLAIN表头
+var ExplainColumnIndent = map[string]string{
+	"id":            "id为SELECT的标识符. 它是在SELECT查询中的顺序编号. 如果这一行表示其他行的union结果, 这个值可以为空. 在这种情况下, table列会显示为形如, 表示它是id为M和N的查询行的联合结果.",
+	"select_type":   "表示查询的类型. ",
+	"table":         "输出行所引用的表.",
+	"type":          "type显示连接使用的类型, 有关不同类型的描述, 请参见解释连接类型.",
+	"possible_keys": "指出MySQL能在该表中使用哪些索引有助于查询. 如果为空, 说明没有可用的索引.",
+	"key":           "MySQL实际从possible_keys选择使用的索引. 如果为NULL, 则没有使用索引. 很少情况下, MySQL会选择优化不足的索引. 这种情况下, 可以在select语句中使用USE INDEX (indexname)来强制使用一个索引或者用IGNORE INDEX (indexname)来强制MySQL忽略索引.",
+	"key_len":       "显示MySQL使用索引键的长度. 如果key是NULL, 则key_len为NULL. 使用的索引的长度. 在不损失精确性的情况下, 长度越短越好.",
+	"ref":           "显示索引的哪一列被使用了.",
+	"rows":          "表示MySQL认为必须检查的用来返回请求数据的行数.",
+	"filtered":      "表示返回结果的行占需要读到的行(rows列的值)的百分比.",
+	"Extra":         "该列显示MySQL在查询过程中的一些详细信息, MySQL查询优化器执行查询的过程中对查询计划的重要补充信息.",
+}
+
+// ExplainSelectType EXPLAIN中SELECT TYPE会出现的类型
+var ExplainSelectType = map[string]string{
+	"SIMPLE":               "简单SELECT(不使用UNION或子查询等).",
+	"PRIMARY":              "最外层的select.",
+	"UNION":                "UNION中的第二个或后面的SELECT查询, 不依赖于外部查询的结果集.",
+	"DEPENDENT":            "UNION中的第二个或后面的SELECT查询, 依赖于外部查询的结果集.",
+	"UNION RESULT":         "UNION查询的结果集.",
+	"SUBQUERY":             "子查询中的第一个SELECT查询, 不依赖于外部查询的结果集.",
+	"DEPENDENT SUBQUERY":   "子查询中的第一个SELECT查询, 依赖于外部查询的结果集.",
+	"DERIVED":              "用于from子句里有子查询的情况. MySQL会递归执行这些子查询, 把结果放在临时表里.",
+	"MATERIALIZED":         "Materialized subquery.",
+	"UNCACHEABLE SUBQUERY": "结果集不能被缓存的子查询, 必须重新为外层查询的每一行进行评估.",
+	"UNCACHEABLE UNION":    "UNION中的第二个或后面的select查询, 属于不可缓存的子查询(类似于UNCACHEABLE SUBQUERY).",
+}
+
+// ExplainAccessType EXPLAIN中ACCESS TYPE会出现的类型
+var ExplainAccessType = map[string]string{
+	"system":          "这是const连接类型的一种特例, 该表仅有一行数据(=系统表).",
+	"const":           `const用于使用常数值比较PRIMARY KEY时, 当查询的表仅有一行时, 使用system. 例:SELECT * FROM tbl WHERE col =1.`,
+	"eq_ref":          `除const类型外最好的可能实现的连接类型. 它用在一个索引的所有部分被连接使用并且索引是UNIQUE或PRIMARY KEY, 对于每个索引键, 表中只有一条记录与之匹配. 例:'SELECT * FROM ref_table,tbl WHERE ref_table.key_column=tbl.column;'.`,
+	"ref":             `连接不能基于关键字选择单个行, 可能查找到多个符合条件的行. 叫做ref是因为索引要跟某个参考值相比较. 这个参考值或者是一个数, 或者是来自一个表里的多表查询的结果值. 例:'SELECT * FROM tbl WHERE idx_col=expr;'.`,
+	"fulltext":        "查询时使用 FULLTEXT 索引.",
+	"ref_or_null":     "如同ref, 但是MySQL必须在初次查找的结果里找出null条目, 然后进行二次查找.",
+	"index_merge":     `表示使用了索引合并优化方法. 在这种情况下. key列包含了使用的索引的清单, key_len包含了使用的索引的最长的关键元素. 详情请见 8.2.1.4, “Index Merge Optimization”.`,
+	"unique_subquery": `在某些IN查询中使用此种类型,而不是常规的ref:'value IN (SELECT primary_key FROM single_table WHERE some_expr)'.`,
+	"index_subquery":  "在某些IN查询中使用此种类型, 与unique_subquery类似, 但是查询的是非唯一索引性索引.",
+	"range":           `只检索给定范围的行, 使用一个索引来选择行. key列显示使用了哪个索引. key_len包含所使用索引的最长关键元素.`,
+	"index":           "全表扫描, 只是扫描表的时候按照索引次序进行而不是行. 主要优点就是避免了排序, 但是开销仍然非常大.",
+	"ALL":             `最坏的情况, 从头到尾全表扫描.`,
+}
+
+// ExplainScalability ACCESS TYPE对应的运算复杂度 [AccessType]scalability map
+var ExplainScalability = map[string]string{
+	"ALL":             "O(n)",
+	"index":           "O(n)",
+	"range":           "O(log n)+",
+	"index_subquery":  "O(log n)+",
+	"unique_subquery": "O(log n)+",
+	"index_merge":     "O(log n)+",
+	"ref_or_null":     "O(log n)+",
+	"fulltext":        "O(log n)+",
+	"ref":             "O(log n)",
+	"eq_ref":          "O(log n)",
+	"const":           "O(1)",
+	"system":          "O(1)",
+}
+
+// ExplainExtra Extra信息解读
+// https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
+// sql/opt_explain_traditional.cc:traditional_extra_tags
+var ExplainExtra = map[string]string{
+	"Using temporary":                   "表示MySQL在对查询结果排序时使用临时表. 常见于排序order by和分组查询group by.",
+	"Using filesort":                    "MySQL会对结果使用一个外部索引排序,而不是从表里按照索引次序读到相关内容. 可能在内存或者磁盘上进行排序. MySQL中无法利用索引完成的排序操作称为'文件排序'.",
+	"Using index condition":             "在5.6版本后加入的新特性(Index Condition Pushdown)。Using index condition 会先条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行。",
+	"Range checked for each record":     "MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。",
+	"Using where with pushed condition": "这是一个仅仅在NDBCluster存储引擎中才会出现的信息,打开condition pushdown优化功能才可能被使用。",
+	"Using MRR":                         "使用了 MRR Optimization IO 层面进行了优化,减少 IO 方面的开销。",
+	"Skip_open_table":                   "Tables are read using the Multi-Range Read optimization strategy.",
+	"Open_frm_only":                     "Table files do not need to be opened. The information is already available from the data dictionary.",
+	"Open_full_table":                   "Unoptimized information lookup. Table information must be read from the data dictionary and by reading table files.",
+	"Scanned":                           "This indicates how many directory scans the server performs when processing a query for INFORMATION_SCHEMA tables.",
+	"Using index for group-by":          "Similar to the Using index table access method, Using index for group-by indicates that MySQL found an index that can be used to retrieve all columns of a GROUP BY or DISTINCT query without any extra disk access to the actual table. Additionally, the index is used in the most efficient way so that for each group, only a few index entries are read.",
+	"Start temporary":                   "This indicates temporary table use for the semi-join Duplicate Weedout strategy.Start",
+	"End temporary":                     "This indicates temporary table use for the semi-join Duplicate Weedout strategy.End",
+	"FirstMatch":                        "The semi-join FirstMatch join shortcutting strategy is used for tbl_name.",
+	"Materialize":                       "Materialized subquery",
+	"Start materialize":                 "Materialized subquery Start",
+	"End materialize":                   "Materialized subquery End",
+	"unique row not found":              "For a query such as SELECT ... FROM tbl_name, no rows satisfy the condition for a UNIQUE index or PRIMARY KEY on the table.",
+	// "Scan":                                                "",
+	// "Impossible ON condition":                             "",
+	// "Ft_hints:":                                           "",
+	// "Backward index scan":                                 "",
+	// "Recursive":                                           "",
+	// "Table function:":                                     "",
+	"Index dive skipped due to FORCE":                     "This item applies to NDB tables only. It means that MySQL Cluster is using the Condition Pushdown optimization to improve the efficiency of a direct comparison between a nonindexed column and a constant. In such cases, the condition is “pushed down” to the cluster's data nodes and is evaluated on all data nodes simultaneously. This eliminates the need to send nonmatching rows over the network, and can speed up such queries by a factor of 5 to 10 times over cases where Condition Pushdown could be but is not used.",
+	"Impossible WHERE noticed after reading const tables": "查询了所有const(和system)表, 但发现WHERE查询条件不起作用.",
+	"Using where":                              "WHERE条件用于筛选出与下一个表匹配的数据然后返回给客户端. 除非故意做的全表扫描, 否则连接类型是ALL或者是index, 且在Extra列的值中没有Using Where, 则该查询可能是有问题的.",
+	"Using join buffer":                        "从已有连接中找被读入缓存的数据, 并且通过缓存来完成与当前表的连接.",
+	"Using index":                              "只需通过索引就可以从表中获取列的信息, 无需额外去读取真实的行数据. 如果查询使用的列值仅仅是一个简单索引的部分值, 则会使用这种策略来优化查询.",
+	"const row not found":                      "空表做类似 SELECT ... FROM tbl_name 的查询操作.",
+	"Distinct":                                 "MySQL is looking for distinct values, so it stops searching for more rows for the current row combination after it has found the first matching row.",
+	"Full scan on NULL key":                    "子查询中的一种优化方式, 常见于无法通过索引访问null值.",
+	"Impossible HAVING":                        "HAVING条件过滤没有效果, 返回已有查询的结果集.",
+	"Impossible WHERE":                         "WHERE条件过滤没有效果, 最终是全表扫描.",
+	"LooseScan":                                "使用半连接LooseScan策略.",
+	"No matching min/max row":                  "没有行满足查询的条件, 如 SELECT MIN(...) FROM ... WHERE condition.",
+	"no matching row in const table":           "对于连接查询, 列未满足唯一索引的条件或表为空.",
+	"No matching rows after partition pruning": "对于DELETE 或 UPDATE, 优化器在分区之后, 未发现任何要删除或更新的内容. 类似查询 Impossible WHERE.",
+	"No tables used":                           "查询没有FROM子句, 或者有一个 FROM DUAL子句.",
+	"Not exists":                               "MySQL能够对LEFT JOIN查询进行优化, 并且在查找到符合LEFT JOIN条件的行后, 则不再查找更多的行.",
+	"Plan isn't ready yet":                     "This value occurs with EXPLAIN FOR CONNECTION when the optimizer has not finished creating the execution plan for the statement executing in the named connection. If execution plan output comprises multiple lines, any or all of them could have this Extra value, depending on the progress of the optimizer in determining the full execution plan.",
+	"Using intersect":                          "开启了index merge,即:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并,使用的算法为:index_merge_intersection",
+	"Using union":                              "开启了index merge,即:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并,使用的算法为:index_merge_union",
+	"Using sort_union":                         "开启了index merge,即:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并,使用的算法为:index_merge_sort_union",
+}
+
+// 提取ExplainJSON中所有的ExplainJSONTable, 将其写入全局变量explainJSONTables
+// depth只是用于debug,逻辑上并未使用
+func findTablesInJSON(explainJSON string, depth int) {
+	common.Log.Debug("findTablesInJSON Enter: depth(%d), json(%s)", depth, explainJSON)
+	// 去除注释,语法检查
+	explainJSON = RemoveSQLComments(explainJSON)
+	if !gjson.Valid(explainJSON) {
+		return
+	}
+	// 提取所有ExplainJSONTable struct
+	for _, key := range ExplainKeyWords {
+		result := gjson.Get(explainJSON, key)
+		if result.String() == "" {
+			continue
+		}
+
+		if key == "table" {
+			table := new(ExplainJSONTable)
+			common.Log.Debug("findTablesInJSON FindTable: depth(%d), table(%s)", depth, result.String)
+			err := json.Unmarshal([]byte(result.Raw), table)
+			common.LogIfError(err, "")
+			if table.TableName != "" {
+				explainJSONTables = append(explainJSONTables, table)
+			}
+			findTablesInJSON(result.String(), depth+1)
+		} else {
+			common.Log.Debug("findTablesInJSON ScanOther: depth(%d), key(%s), array_len(%d), json(%s)", depth, key, len(result.Array()), result.String)
+			for _, val := range result.Array() {
+				if val.String() != "" {
+					findTablesInJSON(val.String(), depth+1)
+				}
+			}
+			findTablesInJSON(result.String(), depth+1)
+		}
+	}
+}
+
+// FormatJSONIntoTraditional 将JSON形式转换为TRADITIONAL形式,方便前端展现
+func FormatJSONIntoTraditional(explainJSON string) []*ExplainRow {
+	// 查找JSON中的所有ExplainJSONTable
+	explainJSONTables = []*ExplainJSONTable{}
+	findTablesInJSON(explainJSON, 0)
+
+	var explainRows []*ExplainRow
+	id := -1
+	for _, table := range explainJSONTables {
+		keyLen := table.KeyLength
+		filtered, err := strconv.ParseFloat(table.Filtered, 64)
+		if err != nil {
+			filtered = 0.00
+		}
+		if filtered > 100.00 {
+			filtered = 100.00
+		}
+		explainRows = append(explainRows, &ExplainRow{
+			ID:           id + 1,
+			SelectType:   "",
+			TableName:    table.TableName,
+			Partitions:   "NULL",
+			AccessType:   table.AccessType,
+			PossibleKeys: table.PossibleKeys,
+			Key:          table.Key,
+			KeyLen:       keyLen,
+			Ref:          table.Ref,
+			Rows:         table.RowsExaminedPerScan,
+			Filtered:     filtered,
+			Scalability:  ExplainScalability[table.AccessType],
+			Extra:        "",
+		})
+	}
+	return explainRows
+}
+
+// ConvertExplainJSON2Row 将 JSON 格式转成 ROW 格式,为方便统一做优化建议
+// 但是会损失一些 JSON 特有的分析结果
+func ConvertExplainJSON2Row(explainJSON *ExplainJSON) []*ExplainRow {
+	buf, err := json.Marshal(explainJSON)
+	if err != nil {
+		return nil
+	}
+	return FormatJSONIntoTraditional(string(buf))
+}
+
+// 用于检测 MySQL 版本是否低于 MySQL5.6
+// 低于5.6 返回 true, 表示需要改写非 SELECT 的 SQL --> SELECT
+func (db *Connector) supportExplainWrite() (bool, error) {
+	defer func() {
+		err := recover()
+		if err != nil {
+			common.Log.Error("Recover supportExplainWrite() Error:", err)
+		}
+	}()
+
+	// 5.6以上版本支持 EXPLAIN UPDATE/DELETE 等语句,但需要开启写入
+	// 如开启了 read_only, EXPLAIN UPDATE/DELETE 也会受限制
+	if common.Config.TestDSN.Version >= 50600 {
+		readOnly, err := db.SingleIntValue("read_only")
+		if err != nil {
+			return false, err
+		}
+		superReadOnly, err := db.SingleIntValue("super_read_only")
+		// Percona, MariaDB 5.6就已经有super_read_only了,但社区版5.6还没有这个参数
+		if err != nil {
+			if !strings.Contains(err.Error(), "Unknown system variable") {
+				return false, err
+			}
+			superReadOnly = readOnly
+		}
+
+		if readOnly == 1 || superReadOnly == 1 {
+			return true, nil
+		}
+
+		return false, nil
+	}
+
+	return true, nil
+}
+
+// 将SQL语句转换为可以被Explain的语句,如:写转读
+// 当输出为空时,表示语法错误或不支持EXPLAIN
+func (db *Connector) explainAbleSQL(sql string) (string, error) {
+	stmt, err := sqlparser.Parse(sql)
+	if err != nil {
+		// TODO: charset, collation
+		tiStmt, tiErr := ast.TiParse(sql, "", "")
+		if tiErr != nil {
+			common.Log.Error("explainAbleSQL ast.TiParse Error: %v", tiErr)
+			return "", tiErr
+		}
+
+		var isSelect bool
+		for _, st := range tiStmt {
+			switch st.(type) {
+			case *tidb.SelectStmt, *tidb.UnionStmt:
+				isSelect = true
+			default:
+				isSelect = false
+			}
+			if !isSelect {
+				break
+			}
+		}
+
+		if isSelect {
+			return sql, nil
+		}
+
+		common.Log.Error("explainAbleSQL sqlparser.Parse Error: %v", err)
+		return "", err
+	}
+
+	switch stmt.(type) {
+	case *sqlparser.Insert, *sqlparser.Update, *sqlparser.Delete: // REPLACE 和 INSERT 的 AST 基本相同,只是 Action 不同
+		// 判断 Explain 的 SQL 是否需要被改写
+		need, err := db.supportExplainWrite()
+		if err != nil {
+			common.Log.Error("explainAbleSQL db.supportExplainWrite Error: %v", err)
+			return "", err
+		}
+		if need {
+			rw := ast.NewRewrite(sql)
+			if rw != nil {
+				return rw.RewriteDML2Select().NewSQL, nil
+			}
+		}
+		return sql, nil
+
+	case *sqlparser.Union, *sqlparser.ParenSelect, *sqlparser.Select, sqlparser.SelectStatement:
+		return sql, nil
+	default:
+	}
+	return "", nil
+}
+
+// 执行explain请求,返回mysql.Result执行结果
+func (db *Connector) executeExplain(sql string, explainType int, formatType int) (*QueryResult, error) {
+	var err error
+	sql, err = db.explainAbleSQL(sql)
+	if sql == "" {
+		return nil, err
+	}
+
+	// 5.6以上支持FORMAT=JSON
+	explainFormat := ""
+	switch formatType {
+	case JSONFormatExplain:
+		if common.Config.TestDSN.Version >= 50600 {
+			explainFormat = "FORMAT=JSON"
+		}
+	}
+	// 执行explain
+	var res *QueryResult
+	switch explainType {
+	case ExtendedExplainType:
+		// 5.6以上extended关键字已经不推荐使用,8.0废弃了这个关键字
+		if common.Config.TestDSN.Version >= 50600 {
+			res, err = db.Query("explain %s", sql)
+		} else {
+			res, err = db.Query("explain extended %s", sql)
+		}
+	case PartitionsExplainType:
+		res, err = db.Query("explain partitions %s", sql)
+
+	default:
+		res, err = db.Query("explain %s %s", explainFormat, sql)
+	}
+	return res, err
+}
+
+// MySQLExplainWarnings WARNINGS信息中包含的优化器信息
+func MySQLExplainWarnings(exp *ExplainInfo) string {
+	content := "## MySQL优化器调优结果\n\n```sql\n"
+	for _, row := range exp.Warnings {
+		content += "\n" + row.Message + "\n"
+	}
+	content += "\n```"
+	return content
+}
+
+// MySQLExplainQueryCost 将last_query_cost信息补充到评审结果中
+func MySQLExplainQueryCost(exp *ExplainInfo) string {
+	var content string
+	if exp.QueryCost > 0 {
+
+		tmp := fmt.Sprintf("%.3f\n", exp.QueryCost)
+
+		content = "Query cost: "
+		if exp.QueryCost > float64(common.Config.MaxQueryCost) {
+			content += fmt.Sprintf("☠️ **%s**", tmp)
+		} else {
+			content += tmp
+		}
+
+	}
+	return content
+}
+
+// ExplainInfoTranslator 将explain信息翻译成人能读懂的
+func ExplainInfoTranslator(exp *ExplainInfo) string {
+	var buf []string
+	var selectTypeBuf []string
+	var accessTypeBuf []string
+	var extraTypeBuf []string
+	buf = append(buf, fmt.Sprint("### Explain信息解读\n"))
+	rows := exp.ExplainRows
+	if exp.ExplainFormat == JSONFormatExplain {
+		// JSON形式遍历分析不方便,转成Row格式统一处理
+		rows = ConvertExplainJSON2Row(exp.ExplainJSON)
+	}
+	if len(rows) == 0 {
+		return ""
+	}
+
+	// SelectType信息解读
+	explainSelectType := make(map[string]string)
+	for k, v := range ExplainSelectType {
+		explainSelectType[k] = v
+	}
+	for _, row := range rows {
+		if _, ok := explainSelectType[row.SelectType]; ok {
+			desc := fmt.Sprintf("* **%s**: %s\n", row.SelectType, explainSelectType[row.SelectType])
+			selectTypeBuf = append(selectTypeBuf, desc)
+			delete(explainSelectType, row.SelectType)
+		}
+	}
+	if len(selectTypeBuf) > 0 {
+		buf = append(buf, fmt.Sprint("#### SelectType信息解读\n"))
+		buf = append(buf, strings.Join(selectTypeBuf, "\n"))
+	}
+
+	// #### Type信息解读
+	explainAccessType := make(map[string]string)
+	for k, v := range ExplainAccessType {
+		explainAccessType[k] = v
+	}
+	for _, row := range rows {
+		if _, ok := explainAccessType[row.AccessType]; ok {
+			var warn bool
+			var desc string
+			for _, t := range common.Config.ExplainWarnAccessType {
+				if row.AccessType == t {
+					warn = true
+				}
+			}
+			if warn {
+				desc = fmt.Sprintf("* ☠️ **%s**: %s\n", row.AccessType, explainAccessType[row.AccessType])
+			} else {
+				desc = fmt.Sprintf("* **%s**: %s\n", row.AccessType, explainAccessType[row.AccessType])
+			}
+
+			accessTypeBuf = append(accessTypeBuf, desc)
+			delete(explainAccessType, row.AccessType)
+		}
+	}
+	if len(accessTypeBuf) > 0 {
+		buf = append(buf, fmt.Sprint("#### Type信息解读\n"))
+		buf = append(buf, strings.Join(accessTypeBuf, "\n"))
+	}
+
+	// #### Extra信息解读
+	if exp.ExplainFormat != JSONFormatExplain {
+		explainExtra := make(map[string]string)
+		for k, v := range ExplainExtra {
+			explainExtra[k] = v
+		}
+		for _, row := range rows {
+			for k, c := range explainExtra {
+				if strings.Contains(row.Extra, k) {
+					if k == "Impossible WHERE" {
+						if strings.Contains(row.Extra, "Impossible WHERE noticed after reading const tables") {
+							continue
+						}
+					}
+					warn := false
+					for _, w := range common.Config.ExplainWarnExtra {
+						if k == w {
+							warn = true
+						}
+					}
+					if warn {
+						extraTypeBuf = append(extraTypeBuf, fmt.Sprintf("* ☠️ **%s**: %s\n", k, c))
+					} else {
+						extraTypeBuf = append(extraTypeBuf, fmt.Sprintf("* **%s**: %s\n", k, c))
+					}
+					delete(explainExtra, k)
+				}
+			}
+		}
+	}
+	if len(extraTypeBuf) > 0 {
+		buf = append(buf, fmt.Sprint("#### Extra信息解读\n"))
+		buf = append(buf, strings.Join(extraTypeBuf, "\n"))
+	}
+
+	return strings.Join(buf, "\n")
+}
+
+// ParseExplainText 解析explain文本信息(很可能是用户复制粘贴得到),返回格式化数据
+func ParseExplainText(content string) (exp *ExplainInfo, err error) {
+	exp = &ExplainInfo{ExplainFormat: TraditionalFormatExplain}
+
+	content = strings.TrimSpace(content)
+	verticalFormat := strings.HasPrefix(content, "*")
+	jsonFormat := strings.HasPrefix(content, "{")
+	traditionalFormat := strings.HasPrefix(content, "+")
+
+	if verticalFormat && traditionalFormat && jsonFormat {
+		return nil, errors.New("not supported explain type")
+	}
+
+	if verticalFormat {
+		exp.ExplainRows, err = parseVerticalExplainText(content)
+	}
+
+	if jsonFormat {
+		exp.ExplainFormat = JSONFormatExplain
+		exp.ExplainJSON, err = parseJSONExplainText(content)
+	}
+
+	if traditionalFormat {
+		exp.ExplainRows, err = parseTraditionalExplainText(content)
+	}
+	return exp, err
+}
+
+// 解析文本形式传统形式Explain信息
+func parseTraditionalExplainText(content string) (explainRows []*ExplainRow, err error) {
+	LS := regexp.MustCompile(`^\+`) // 华丽的分隔线:)
+
+	// 格式正确性检查
+	lines := strings.Split(content, "\n")
+	if len(lines) < 3 {
+		return nil, errors.New("explain Rows less than 3")
+	}
+
+	// 提取头部,用于后续list到map的转换
+	var header []string
+	for _, h := range strings.Split(strings.Trim(lines[1], "|"), "|") {
+		header = append(header, strings.TrimSpace(h))
+	}
+	colIdx := make(map[string]int)
+	for i, item := range header {
+		colIdx[strings.ToLower(item)] = i
+	}
+
+	// explain format=json未把外面的框去了
+	if strings.ToLower(header[0]) == "explain" {
+		return nil, errors.New("json format explain need remove")
+	}
+
+	// 将每一列填充至ExplainRow结构体
+	colsMap := make(map[string]string)
+	for _, l := range lines[3:] {
+		var keylen string
+		var rows int
+		var filtered float64
+		var partitions string
+		// 跳过分割线
+		if LS.MatchString(l) || strings.TrimSpace(l) == "" {
+			continue
+		}
+
+		// list到map的转换
+		var cols []string
+		for _, c := range strings.Split(strings.Trim(l, "|"), "|") {
+			cols = append(cols, strings.TrimSpace(c))
+		}
+		for item, i := range colIdx {
+			colsMap[item] = cols[i]
+		}
+
+		// 值类型转换
+		id, err := strconv.Atoi(colsMap["id"])
+		if err != nil {
+			return nil, err
+		}
+
+		// 不存在字段给默认值
+		if colsMap["partitions"] == "" {
+			partitions = "NULL"
+		} else {
+			partitions = colsMap["partitions"]
+		}
+
+		keylen = colsMap["key_len"]
+
+		rows, err = strconv.Atoi(colsMap["Rows"])
+		if err != nil {
+			rows = 0
+		}
+
+		filtered, err = strconv.ParseFloat(colsMap["filtered"], 64)
+		if err != nil {
+			filtered = 0.00
+		}
+		// filtered may larger than 100.00
+		// https://bugs.mysql.com/bug.php?id=34124
+		if filtered > 100.00 {
+			filtered = 100.00
+		}
+
+		// 拼接结构体
+		explainRows = append(explainRows, &ExplainRow{
+			ID:           id,
+			SelectType:   colsMap["select_type"],
+			TableName:    colsMap["table"],
+			Partitions:   partitions,
+			AccessType:   colsMap["type"],
+			PossibleKeys: strings.Split(colsMap["possible_keys"], ","),
+			Key:          colsMap["key"],
+			KeyLen:       keylen,
+			Ref:          strings.Split(colsMap["ref"], ","),
+			Rows:         rows,
+			Filtered:     filtered,
+			Scalability:  ExplainScalability[colsMap["type"]],
+			Extra:        colsMap["extra"],
+		})
+	}
+	return explainRows, nil
+}
+
+// 解析文本形式竖排版 Explain信息
+func parseVerticalExplainText(content string) (explainRows []*ExplainRow, err error) {
+	var lines []string
+	explainRow := &ExplainRow{
+		Partitions: "NULL",
+		Filtered:   0.00,
+	}
+	LS := regexp.MustCompile(`^\*.*\*$`) // 华丽的分隔线:)
+
+	// 格式正确性检查
+	for _, l := range strings.Split(content, "\n") {
+		lines = append(lines, strings.TrimSpace(l))
+	}
+	if len(lines) < 11 {
+		return nil, errors.New("explain rows less than 11")
+	}
+
+	// 将每一行填充至ExplainRow结构体
+	for _, l := range lines {
+		if LS.MatchString(l) || strings.TrimSpace(l) == "" {
+			continue
+		}
+		if strings.HasPrefix(l, "id:") {
+			id := strings.TrimPrefix(l, "id: ")
+			explainRow.ID, err = strconv.Atoi(id)
+			if err != nil {
+				return nil, err
+			}
+		}
+		if strings.HasPrefix(l, "select_type:") {
+			explainRow.SelectType = strings.TrimPrefix(l, "select_type: ")
+		}
+		if strings.HasPrefix(l, "table:") {
+			explainRow.TableName = strings.TrimPrefix(l, "table: ")
+		}
+		if strings.HasPrefix(l, "partitions:") {
+			explainRow.AccessType = strings.TrimPrefix(l, "partitions: ")
+		}
+		if strings.HasPrefix(l, "type:") {
+			explainRow.AccessType = strings.TrimPrefix(l, "type: ")
+			explainRow.Scalability = ExplainScalability[explainRow.AccessType]
+		}
+		if strings.HasPrefix(l, "possible_keys:") {
+			explainRow.PossibleKeys = strings.Split(strings.TrimPrefix(l, "possible_keys: "), ",")
+		}
+		if strings.HasPrefix(l, "key:") {
+			explainRow.Key = strings.TrimPrefix(l, "key: ")
+		}
+		if strings.HasPrefix(l, "key_len:") {
+			keyLen := strings.TrimPrefix(l, "key_len: ")
+			explainRow.KeyLen = keyLen
+		}
+		if strings.HasPrefix(l, "ref:") {
+			explainRow.Ref = strings.Split(strings.TrimPrefix(l, "ref: "), ",")
+		}
+		if strings.HasPrefix(l, "Rows:") {
+			rows := strings.TrimPrefix(l, "Rows: ")
+			explainRow.Rows, err = strconv.Atoi(rows)
+			if err != nil {
+				explainRow.Rows = 0
+			}
+		}
+		if strings.HasPrefix(l, "filtered:") {
+			filtered := strings.TrimPrefix(l, "filtered: ")
+			explainRow.Filtered, err = strconv.ParseFloat(filtered, 64)
+			if err != nil {
+				return nil, err
+			} else if explainRow.Filtered > 100.00 {
+				explainRow.Filtered = 100.00
+			}
+		}
+		if strings.HasPrefix(l, "Extra:") {
+			explainRow.Extra = strings.TrimPrefix(l, "Extra: ")
+			explainRows = append(explainRows, explainRow)
+		}
+	}
+	return explainRows, err
+}
+
+// 解析文本形式JSON Explain信息
+func parseJSONExplainText(content string) (*ExplainJSON, error) {
+	explainJSON := new(ExplainJSON)
+	err := json.Unmarshal([]byte(RemoveSQLComments(content)), explainJSON)
+	return explainJSON, err
+}
+
+// ParseExplainResult 分析 mysql 执行 explain 的结果,返回 ExplainInfo 结构化数据
+func ParseExplainResult(res *QueryResult, formatType int) (exp *ExplainInfo, err error) {
+	exp = &ExplainInfo{
+		ExplainFormat: formatType,
+	}
+	// JSON 格式直接调用文本方式解析
+	if formatType == JSONFormatExplain {
+		exp.ExplainJSON, err = parseJSONExplainText(res.Rows[0].Str(0))
+		return exp, err
+	}
+
+	// 生成表头
+	colIdx := make(map[int]string)
+	for i, f := range res.Result.Fields() {
+		colIdx[i] = strings.ToLower(f.Name)
+	}
+	// 补全 ExplainRows
+	var explainrows []*ExplainRow
+	for _, row := range res.Rows {
+		expRow := &ExplainRow{Partitions: "NULL", Filtered: 0.00}
+		// list 到 map 的转换
+		for i := range row {
+			switch colIdx[i] {
+			case "id":
+				expRow.ID = row.ForceInt(i)
+			case "select_type":
+				expRow.SelectType = row.Str(i)
+			case "table":
+				expRow.TableName = row.Str(i)
+				if expRow.TableName == "" {
+					expRow.TableName = "NULL"
+				}
+			case "type":
+				expRow.AccessType = row.Str(i)
+				if expRow.AccessType == "" {
+					expRow.AccessType = "NULL"
+				}
+				expRow.Scalability = ExplainScalability[expRow.AccessType]
+			case "possible_keys":
+				expRow.PossibleKeys = strings.Split(row.Str(i), ",")
+			case "key":
+				expRow.Key = row.Str(i)
+				if expRow.Key == "" {
+					expRow.Key = "NULL"
+				}
+			case "key_len":
+				expRow.KeyLen = row.Str(i)
+			case "ref":
+				expRow.Ref = strings.Split(row.Str(i), ",")
+			case "rows":
+				expRow.Rows = row.ForceInt(i)
+			case "extra":
+				expRow.Extra = row.Str(i)
+				if expRow.Extra == "" {
+					expRow.Extra = "NULL"
+				}
+			case "filtered":
+				expRow.Filtered = row.ForceFloat(i)
+				// MySQL bug: https://bugs.mysql.com/bug.php?id=34124
+				if expRow.Filtered > 100.00 {
+					expRow.Filtered = 100.00
+				}
+			}
+		}
+		explainrows = append(explainrows, expRow)
+	}
+	exp.ExplainRows = explainrows
+	for _, w := range res.Warning {
+		// 'EXTENDED' is deprecated and will be removed in a future release.
+		if w.Int(1) != 1681 {
+			exp.Warnings = append(exp.Warnings, &ExplainWarning{Level: w.Str(0), Code: w.Int(1), Message: w.Str(2)})
+		}
+	}
+
+	// 添加 last_query_cost
+	exp.QueryCost = res.QueryCost
+
+	return exp, err
+}
+
+// Explain 获取 SQL 的 explain 信息
+func (db *Connector) Explain(sql string, explainType int, formatType int) (exp *ExplainInfo, err error) {
+	exp = &ExplainInfo{SQL: sql}
+	if explainType != TraditionalExplainType {
+		formatType = TraditionalFormatExplain
+	}
+	defer func() {
+		if e := recover(); e != nil {
+			const size = 4096
+			buf := make([]byte, size)
+			buf = buf[:runtime.Stack(buf, false)]
+			common.Log.Error("Recover Explain() Error: %v\n%v", e, string(buf))
+			err = errors.New(fmt.Sprint(e))
+		}
+	}()
+
+	// 执行EXPLAIN请求
+	res, err := db.executeExplain(sql, explainType, formatType)
+	if err != nil || res == nil {
+		return exp, err
+	}
+
+	// 解析mysql结果,输出ExplainInfo
+	exp, err = ParseExplainResult(res, formatType)
+
+	return exp, err
+}
+
+// PrintMarkdownExplainTable 打印 markdown 格式的 explain table
+func PrintMarkdownExplainTable(exp *ExplainInfo) string {
+	var buf []string
+	rows := exp.ExplainRows
+	// JSON 转换为 TRADITIONAL 格式
+	if exp.ExplainFormat == JSONFormatExplain {
+		buf = append(buf, fmt.Sprint("以下为 JSON 格式转为传统格式 EXPLAIN 表格", "\n\n"))
+		rows = ConvertExplainJSON2Row(exp.ExplainJSON)
+	}
+
+	// explain出错
+	if len(rows) == 0 {
+		return ""
+	}
+	if exp.ExplainFormat == JSONFormatExplain {
+		buf = append(buf, fmt.Sprintln("| table | partitions | type | possible\\_keys | key | key\\_len | ref | rows | filtered | scalability | Extra |"))
+		buf = append(buf, fmt.Sprintln("|---|---|---|---|---|---|---|---|---|---|---|"))
+		for _, row := range rows {
+			buf = append(buf, fmt.Sprintln("|", row.TableName, "|", row.Partitions, "|", row.AccessType,
+				"|", strings.Join(row.PossibleKeys, ","), "|", row.Key, "|", row.KeyLen, "|",
+				strings.Join(row.Ref, ","), "|", row.Rows, "|", fmt.Sprintf("%.2f%s", row.Filtered, "%"),
+				"|", row.Scalability, "|", row.Extra, "|"))
+		}
+	} else {
+		buf = append(buf, fmt.Sprintln("| id | select\\_type | table | partitions | type | possible_keys | key | key\\_len | ref | rows | filtered | scalability | Extra |"))
+		buf = append(buf, fmt.Sprintln("|---|---|---|---|---|---|---|---|---|---|---|---|---|"))
+		for _, row := range rows {
+			// 加粗
+			rows := fmt.Sprint(row.Rows)
+			if row.Rows >= common.Config.ExplainMaxRows {
+				rows = "☠️ **" + rows + "**"
+			}
+			filtered := fmt.Sprintf("%.2f%s", row.Filtered, "%")
+			if row.Filtered >= common.Config.ExplainMaxFiltered {
+				filtered = "☠️ **" + filtered + "**"
+			}
+			scalability := row.Scalability
+			for _, s := range common.Config.ExplainWarnScalability {
+				scalability = "☠️ **" + s + "**"
+			}
+			buf = append(buf, fmt.Sprintln("|", row.ID, " |",
+				common.MarkdownEscape(row.SelectType),
+				"| *"+common.MarkdownEscape(row.TableName)+"* |",
+				common.MarkdownEscape(row.Partitions), "|",
+				common.MarkdownEscape(row.AccessType), "|",
+				common.MarkdownEscape(strings.Join(row.PossibleKeys, ",
")), "|", + common.MarkdownEscape(row.Key), "|", + row.KeyLen, "|", + common.MarkdownEscape(strings.Join(row.Ref, ",
")), + "|", rows, "|", + filtered, "|", scalability, "|", + strings.Replace(common.MarkdownEscape(row.Extra), ",", ",
", -1), + "|")) + } + } + buf = append(buf, "\n") + return strings.Join(buf, "") +} diff --git a/vendor/github.com/XiaoMi/soar/database/explain_test.go b/vendor/github.com/XiaoMi/soar/database/explain_test.go new file mode 100644 index 0000000000000000000000000000000000000000..01ef50f923322d55c2fb48bdf1d12207e39537b8 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/explain_test.go @@ -0,0 +1,2463 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "fmt" + "os" + "testing" + + "github.com/XiaoMi/soar/common" + + "github.com/kr/pretty" +) + +var connTest *Connector + +func init() { + common.BaseDir = common.DevPath + common.ParseConfig("") + connTest = &Connector{ + Addr: common.Config.OnlineDSN.Addr, + User: common.Config.OnlineDSN.User, + Pass: common.Config.OnlineDSN.Password, + Database: common.Config.OnlineDSN.Schema, + } + if _, err := connTest.Version(); err != nil { + common.Log.Critical("Test env Error: %v", err) + os.Exit(0) + } +} + +var sqls = []string{ + `select * from city where country_id = 44;`, + `select * from address where address2 is not null;`, + `select * from address where address2 is null;`, + `select * from address where address2 >= 44;`, + `select * from city where country_id between 44 and 107;`, + `select * from city where city like 'Ad%';`, + `select * from city where city = 'Aden' and country_id = 107;`, + `select * from city where country_id > 31 and city = 'Aden';`, + `select * from address where address_id > 8 and city_id < 400 and district = 'Nantou';`, + `select * from address where address_id > 8 and city_id < 400;`, + `select * from actor where last_update='2006-02-15 04:34:33' and last_name='CHASE' group by first_name;`, + `select * from address where last_update >='2014-09-25 22:33:47' group by district;`, + `select * from address group by address,district;`, + `select * from address where last_update='2014-09-25 22:30:27' group by district,(address_id+city_id);`, + `select * from customer where active=1 order by last_name limit 10;`, + `select * from customer order by last_name limit 10;`, + `select * from customer where address_id > 224 order by address_id limit 10;`, + `select * from customer where address_id < 224 order by address_id limit 10;`, + `select * from customer where active=1 order by last_name;`, + `select * from customer where address_id > 224 order by address_id;`, + `select * from customer where address_id in (224,510) order by last_name;`, + `select city from city where country_id = 44;`, + `select city,city_id from city where country_id = 44 and last_update='2006-02-15 04:45:25';`, + `select city from city where country_id > 44 and last_update > '2006-02-15 04:45:25';`, + `select * from city where country_id=1 and city='Kabul' order by last_update;`, + `select * from city where country_id>1 and city='Kabul' order by last_update;`, + `select * from city where city_id>251 order by last_update;`, + `select * from city i inner join country o on i.country_id=o.country_id;`, + `select * from city i left join country o on i.city_id=o.country_id;`, + `select * from city i right join country o on i.city_id=o.country_id;`, + `select * from city i left join country o on i.city_id=o.country_id where o.country_id is null;`, + `select * from city i right join country o on i.city_id=o.country_id where i.city_id is null;`, + `select * from city i left join country o on i.city_id=o.country_id union select * from city i right join country o on i.city_id=o.country_id;`, + `select * from city i left join country o on i.city_id=o.country_id where o.country_id is null union select * from city i right join country o on i.city_id=o.country_id where i.city_id is null;`, + `select first_name,last_name,email from customer natural left join address;`, + `select first_name,last_name,email from customer natural left join address;`, + `select first_name,last_name,email from customer natural right join address;`, + `select first_name,last_name,email from customer STRAIGHT_JOIN address on customer.address_id=address.address_id;`, + `select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;`, + `SELECT a.table_name 表名, a.table_comment 表说明, b.COLUMN_NAME 字段名, b.column_comment 字段说明, b.column_type 字段类型, b.column_key 约束 FROM information_schema.TABLES a LEFT JOIN information_schema. COLUMNS b ON a.table_name = b.TABLE_NAME WHERE a.table_schema IN ('a') AND b.column_comment LIKE '%一%' ORDER BY a.table_name`, +} + +var exp = []string{ + `+----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+ +| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+ +| 1 | SIMPLE | country | index | PRIMARY,country_id | country | 152 | NULL | 109 | Using index | +| 1 | SIMPLE | city | ref | idx_fk_country_id,idx_country_id_city,idx_all,idx_other | idx_fk_country_id | 2 | sakila.country.country_id | 2 | Using index | ++----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+`, + `+----+-------------+---------+------------+-------+-------------------+-------------------+---------+---------------------------+------+----------+-------------+ +| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | ++----+-------------+---------+------------+-------+-------------------+-------------------+---------+---------------------------+------+----------+-------------+ +| 1 | SIMPLE | country | NULL | index | PRIMARY | PRIMARY | 2 | NULL | 109 | 100.00 | Using index | +| 1 | SIMPLE | city | NULL | ref | idx_fk_country_id | idx_fk_country_id | 2 | sakila.country.country_id | 5 | 100.00 | Using index | ++----+-------------+---------+------------+-------+-------------------+-------------------+---------+---------------------------+------+----------+-------------+`, + `*************************** 1. row *************************** + id: 1 + select_type: SIMPLE + table: country + type: index +possible_keys: PRIMARY,country_id + key: country + key_len: 152 + ref: NULL + rows: 109 + Extra: Using index +*************************** 2. row *************************** + id: 1 + select_type: SIMPLE + table: city + type: ref +possible_keys: idx_fk_country_id,idx_country_id_city,idx_all,idx_other + key: idx_fk_country_id + key_len: 2 + ref: sakila.country.country_id + rows: 2 + Extra: Using index`, + `+----+-------------+---------+------------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+ +| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra | ++----+-------------+---------+------------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+ +| 1 | SIMPLE | country | NULL | index | PRIMARY,country_id | country | 152 | NULL | 109 | Using index | +| 1 | SIMPLE | city | NULL | ref | idx_fk_country_id,idx_country_id_city,idx_all,idx_other | idx_fk_country_id | 2 | sakila.country.country_id | 2 | Using index | ++----+-------------+---------+------------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+`, + `{ + "query_block": { + "select_id": 1, + "message": "No tables used" + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "message": "no matching row in const table" + } +}`, + `{ + "query_block": { + "select_id": 1, + "table": { + "insert": true, + "table_name": "t1", + "access_type": "ALL" + } /* table */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "message": "no matching row in const table" + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "message": "no matching row in const table" + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "13.50" + } /* cost_info */, + "table": { + "table_name": "a4", + "access_type": "ALL", + "rows_examined_per_scan": 14, + "rows_produced_per_join": 14, + "filtered": "100.00", + "cost_info": { + "read_cost": "10.70", + "eval_cost": "2.80", + "prefix_cost": "13.50", + "data_read_per_join": "224" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "13.50" + } /* cost_info */, + "table": { + "table_name": "a3", + "access_type": "ALL", + "rows_examined_per_scan": 14, + "rows_produced_per_join": 14, + "filtered": "100.00", + "cost_info": { + "read_cost": "10.70", + "eval_cost": "2.80", + "prefix_cost": "13.50", + "data_read_per_join": "224" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "13.50" + } /* cost_info */, + "table": { + "table_name": "a2", + "access_type": "ALL", + "rows_examined_per_scan": 14, + "rows_produced_per_join": 14, + "filtered": "100.00", + "cost_info": { + "read_cost": "10.70", + "eval_cost": "2.80", + "prefix_cost": "13.50", + "data_read_per_join": "224" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 4, + "cost_info": { + "query_cost": "15.55" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */ + } /* table */ + }, + { + "table": { + "table_name": "a1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 14, + "filtered": "100.00", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "10.35", + "eval_cost": "2.80", + "prefix_cost": "15.55", + "data_read_per_join": "224" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 5, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "5.81" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 0, + "filtered": "14.29", + "cost_info": { + "read_cost": "3.21", + "eval_cost": "0.20", + "prefix_cost": "3.41", + "data_read_per_join": "7" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "attached_condition": "(test.t1.i = 10)" + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 0, + "filtered": "50.00", + "first_match": "t1", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.20", + "eval_cost": "0.20", + "prefix_cost": "5.82", + "data_read_per_join": "7" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "attached_condition": "(test.t2.i = 10)" + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "attached_condition": "((test.t1.i ,(/* select#2 */ select 1 from test.t2 where ((test.t1.i = 10) and ((test.t1.i) = test.t2.i)))) or (test.t1.i.test.t1.i in ( (/* select#3 */ select NULL from test.t4 where 1 ), (test.t1.i in on where ((test.t1.i = materialized-subquery.i))))))", + "attached_subqueries": [ + { + "table": { + "table_name": "", + "access_type": "eq_ref", + "key": "", + "key_length": "5", + "rows_examined_per_scan": 1, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 3, + "message": "no matching row in const table" + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + }, + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 1, + "filtered": "50.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.20", + "prefix_cost": "2.40", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "attached_condition": "((test.t1.i = 10) and ((test.t1.i) = test.t2.i))" + } /* table */ + } /* query_block */ + } + ] /* attached_subqueries */ + } /* table */ + } /* query_block */ +}`, + `{ + "query_block": { + "union_result": { + "using_temporary_table": true, + "table_name": "", + "access_type": "ALL", + "query_specifications": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "message": "no matching row in const table" + } /* query_block */ + } + ] /* query_specifications */ + } /* union_result */ + } /* query_block */ +}`, + `{ + "query_block": { + "union_result": { + "using_temporary_table": false, + "query_specifications": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "7.21" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */ + } /* table */ + }, + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 14, + "filtered": "100.00", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "2.80", + "prefix_cost": "7.22", + "data_read_per_join": "112" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "message": "no matching row in const table" + } /* query_block */ + } + ] /* query_specifications */ + } /* union_result */ + } /* query_block */ +}`, + `{ + "query_block": { + "ordering_operation": { + "using_filesort": true, + "union_result": { + "using_temporary_table": true, + "table_name": "", + "access_type": "ALL", + "query_specifications": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* query_specifications */ + } /* union_result */, + "order_by_subqueries": [ + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 3, + "message": "No tables used" + } /* query_block */ + } + ] /* order_by_subqueries */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "ordering_operation": { + "using_filesort": false, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */, + "optimized_away_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */ + } /* table */ + } /* query_block */ + } + ] /* optimized_away_subqueries */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */, + "having_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* having_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "10.41" + } /* cost_info */, + "grouping_operation": { + "using_temporary_table": true, + "using_filesort": true, + "cost_info": { + "sort_cost": "7.00" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */, + "group_by_subqueries": [ + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "attached_condition": "(outer_field_is_not_null, (((test.t1.i) >= test.t2.i) or isnull(test.t2.i)), true)" + } /* table */ + } /* query_block */ + }, + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */, + "attached_condition": "(outer_field_is_not_null, (((test.t1.i) <= test.t2.i) or isnull(test.t2.i)), true)" + } /* table */ + } /* query_block */ + } + ] /* group_by_subqueries */ + } /* grouping_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */, + "select_list_subqueries": [ + { + "dependent": false, + "cacheable": false, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "3.41" + } /* cost_info */, + "ordering_operation": { + "using_temporary_table": true, + "using_filesort": true, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 7, + "rows_produced_per_join": 7, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.40", + "prefix_cost": "3.41", + "data_read_per_join": "56" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* ordering_operation */ + } /* query_block */ + } + ] /* select_list_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "message": "no matching row in const table" + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "5.21" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "32" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */, + "attached_condition": "(((/* select#3 */ select test.t3.e from test.t3),(/* select#4 */ select 1 from test.t3 where (test.t1.b and (outer_field_is_not_null, ((((/* select#3 */ select test.t3.e from test.t3)) < test.t3.e) or isnull(test.t3.e)), true)) having (outer_field_is_not_null, (test.t3.e), true))))", + "attached_subqueries": [ + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 4, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "e" + ] /* used_columns */, + "attached_condition": "(test.t1.b and (outer_field_is_not_null, ((((/* select#3 */ select test.t3.e from test.t3)) < test.t3.e) or isnull(test.t3.e)), true))" + } /* table */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "e" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* attached_subqueries */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "50.00", + "first_match": "t1", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "5.21", + "data_read_per_join": "32" + } /* cost_info */, + "used_columns": [ + "c" + ] /* used_columns */, + "attached_condition": "(test.t2.c = test.t1.a)" + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "35.44" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 12, + "rows_produced_per_join": 12, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "2.40", + "prefix_cost": "4.42", + "data_read_per_join": "96" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */, + "attached_condition": "((test.t1.a is not null) and (test.t1.a is not null))" + } /* table */ + }, + { + "table": { + "table_name": "", + "access_type": "eq_ref", + "key": "", + "key_length": "5", + "ref": [ + "test.t1.a" + ] /* ref */, + "rows_examined_per_scan": 1, + "materialized_from_subquery": { + "using_temporary_table": true, + "query_block": { + "nested_loop": [ + { + "table": { + "table_name": "t4", + "access_type": "ALL", + "rows_examined_per_scan": 12, + "rows_produced_per_join": 3, + "filtered": "33.33", + "cost_info": { + "read_cost": "3.62", + "eval_cost": "0.80", + "prefix_cost": "4.42", + "data_read_per_join": "31" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */, + "attached_condition": "(test.t4.a > 0)" + } /* table */ + }, + { + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows_examined_per_scan": 12, + "rows_produced_per_join": 4, + "filtered": "10.00", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "0.96", + "prefix_cost": "16.04", + "data_read_per_join": "38" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */, + "attached_condition": "(test.t3.a = test.t4.a)" + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + }, + { + "table": { + "table_name": "", + "access_type": "eq_ref", + "key": "", + "key_length": "5", + "ref": [ + "test.t1.a" + ] /* ref */, + "rows_examined_per_scan": 1, + "materialized_from_subquery": { + "using_temporary_table": true, + "query_block": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 12, + "rows_produced_per_join": 3, + "filtered": "33.33", + "cost_info": { + "read_cost": "3.62", + "eval_cost": "0.80", + "prefix_cost": "4.42", + "data_read_per_join": "31" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */, + "attached_condition": "(test.t2.a > 0)" + } /* table */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "1.20" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "1.00", + "eval_cost": "0.20", + "prefix_cost": "1.20", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i1", + "c1" + ] /* used_columns */, + "attached_condition": "exists(/* select#2 */ select test.t2.c1 from test.t2 join test.t3 where ((test.t2.c1 = test.t3.c1) and (test.t2.c2 = (/* select#3 */ select min(test.t3.c1) from test.t3)) and ((/* select#3 */ select min(test.t3.c1) from test.t3) <> test.t1.c1)))", + "attached_subqueries": [ + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "1.00", + "eval_cost": "0.20", + "prefix_cost": "1.20", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "c1" + ] /* used_columns */, + "attached_condition": "((/* select#3 */ select min(test.t3.c1) from test.t3) <> test.t1.c1)", + "attached_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "1.20" + } /* cost_info */, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "1.00", + "eval_cost": "0.20", + "prefix_cost": "1.20", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "c1" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* attached_subqueries */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "ref", + "possible_keys": [ + "c1" + ] /* possible_keys */, + "key": "c1", + "used_key_parts": [ + "c1" + ] /* used_key_parts */, + "key_length": "3", + "ref": [ + "test.t3.c1" + ] /* ref */, + "rows_examined_per_scan": 1, + "rows_produced_per_join": 0, + "filtered": "50.00", + "cost_info": { + "read_cost": "1.00", + "eval_cost": "0.10", + "prefix_cost": "2.40", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "c1", + "c2" + ] /* used_columns */, + "attached_condition": "(test.t2.c2 = (/* select#3 */ select min(test.t3.c1) from test.t3))", + "attached_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "1.20" + } /* cost_info */, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "1.00", + "eval_cost": "0.20", + "prefix_cost": "1.20", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "c1" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* attached_subqueries */ + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ + } + ] /* attached_subqueries */ + } /* table */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "20.82" + } /* cost_info */, + "duplicates_removal": { + "using_temporary_table": true, + "nested_loop": [ + { + "table": { + "table_name": "t5", + "access_type": "ALL", + "rows_examined_per_scan": 3, + "rows_produced_per_join": 3, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "0.60", + "prefix_cost": "2.61", + "data_read_per_join": "24" + } /* cost_info */, + "used_columns": [ + "c" + ] /* used_columns */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 3, + "rows_produced_per_join": 3, + "filtered": "33.33", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "0.60", + "prefix_cost": "6.41", + "data_read_per_join": "48" + } /* cost_info */, + "used_columns": [ + "c", + "c_key" + ] /* used_columns */, + "attached_condition": "(test.t2.c = test.t5.c)" + } /* table */ + }, + { + "table": { + "table_name": "t1", + "access_type": "index", + "possible_keys": [ + "c_key" + ] /* possible_keys */, + "key": "c_key", + "used_key_parts": [ + "c_key" + ] /* used_key_parts */, + "key_length": "5", + "rows_examined_per_scan": 3, + "rows_produced_per_join": 3, + "filtered": "33.33", + "using_index": true, + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "0.60", + "prefix_cost": "12.22", + "data_read_per_join": "24" + } /* cost_info */, + "used_columns": [ + "c_key" + ] /* used_columns */, + "attached_condition": "(test.t1.c_key = test.t2.c_key)" + } /* table */ + }, + { + "table": { + "table_name": "t4", + "access_type": "ALL", + "rows_examined_per_scan": 3, + "rows_produced_per_join": 3, + "filtered": "33.33", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "0.60", + "prefix_cost": "16.02", + "data_read_per_join": "48" + } /* cost_info */, + "used_columns": [ + "c", + "c_key" + ] /* used_columns */, + "attached_condition": "((test.t4.c = test.t5.c) and (test.t4.c_key is not null))" + } /* table */ + }, + { + "table": { + "table_name": "t3", + "access_type": "ref", + "possible_keys": [ + "c_key" + ] /* possible_keys */, + "key": "c_key", + "used_key_parts": [ + "c_key" + ] /* used_key_parts */, + "key_length": "5", + "ref": [ + "test.t4.c_key" + ] /* ref */, + "rows_examined_per_scan": 1, + "rows_produced_per_join": 3, + "filtered": "100.00", + "using_index": true, + "cost_info": { + "read_cost": "3.00", + "eval_cost": "0.60", + "prefix_cost": "20.82", + "data_read_per_join": "24" + } /* cost_info */, + "used_columns": [ + "c_key" + ] /* used_columns */ + } /* table */ + } + ] /* nested_loop */ + } /* duplicates_removal */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "table": { + "update": true, + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 1, + "filtered": "100.00" + } /* table */, + "update_value_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* update_value_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "update": true, + "table_name": "t1", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */ + } /* table */ + } + ] /* nested_loop */, + "update_value_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "t3", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* update_value_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "insert": true, + "table_name": "t1", + "access_type": "ALL" + } /* table */, + "insert_from": { + "table": { + "table_name": "t2", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* insert_from */, + "update_value_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* update_value_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "table": { + "insert": true, + "table_name": "t1", + "access_type": "ALL" + } /* table */, + "update_value_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* update_value_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "table": { + "insert": true, + "table_name": "t3", + "access_type": "ALL" + } /* table */, + "optimized_away_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */ + } /* query_block */ + } + ] /* optimized_away_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "10.50" + } /* cost_info */, + "ordering_operation": { + "using_filesort": true, + "grouping_operation": { + "using_temporary_table": true, + "using_filesort": false, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "10.10", + "eval_cost": "0.40", + "prefix_cost": "10.50", + "data_read_per_join": "48" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": false, + "cacheable": true, + "query_block": { + "union_result": { + "using_temporary_table": false, + "query_specifications": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "message": "No tables used" + } /* query_block */ + }, + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "message": "No tables used" + } /* query_block */ + } + ] /* query_specifications */ + } /* union_result */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } /* grouping_operation */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "4.40" + } /* cost_info */, + "grouping_operation": { + "using_temporary_table": true, + "using_filesort": true, + "cost_info": { + "sort_cost": "2.00" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "32" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */ + } /* table */, + "group_by_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "1.00" + } /* cost_info */, + "table": { + "table_name": "d", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "b" + ] /* used_columns */, + "materialized_from_subquery": { + "using_temporary_table": true, + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "5.21" + } /* cost_info */, + "ordering_operation": { + "using_temporary_table": true, + "using_filesort": true, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "32" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 4, + "filtered": "100.00", + "using_join_buffer": "Block Nested Loop", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.80", + "prefix_cost": "5.21", + "data_read_per_join": "64" + } /* cost_info */ + } /* table */ + } + ] /* nested_loop */ + } /* ordering_operation */ + } /* query_block */ + } /* materialized_from_subquery */ + } /* table */ + } /* query_block */ + } + ] /* group_by_subqueries */ + } /* grouping_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */ + } /* table */, + "optimized_away_subqueries": [ + { + "dependent": false, + "cacheable": true, + "query_block": { + "select_id": 3, + "cost_info": { + "query_cost": "4.40" + } /* cost_info */, + "grouping_operation": { + "using_temporary_table": true, + "using_filesort": true, + "cost_info": { + "sort_cost": "2.00" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "f1" + ] /* used_columns */ + } /* table */ + } /* grouping_operation */ + } /* query_block */ + } + ] /* optimized_away_subqueries */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "4.02" + } /* cost_info */, + "ordering_operation": { + "using_filesort": true, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 10, + "rows_produced_per_join": 10, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "2.00", + "prefix_cost": "4.02", + "data_read_per_join": "80" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */, + "order_by_subqueries": [ + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "4.02" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 10, + "rows_produced_per_join": 1, + "filtered": "10.00", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "0.20", + "prefix_cost": "4.02", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i", + "j" + ] /* used_columns */, + "attached_condition": "(test.t2.i = test.t1.i)" + } /* table */ + } /* query_block */ + } + ] /* order_by_subqueries */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "4.02" + } /* cost_info */, + "grouping_operation": { + "using_temporary_table": true, + "using_filesort": true, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 10, + "rows_produced_per_join": 10, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "2.00", + "prefix_cost": "4.02", + "data_read_per_join": "80" + } /* cost_info */, + "used_columns": [ + "i" + ] /* used_columns */ + } /* table */, + "group_by_subqueries": [ + { + "dependent": true, + "cacheable": false, + "query_block": { + "select_id": 2, + "cost_info": { + "query_cost": "4.02" + } /* cost_info */, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows_examined_per_scan": 10, + "rows_produced_per_join": 1, + "filtered": "10.00", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "0.20", + "prefix_cost": "4.02", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "i", + "j" + ] /* used_columns */, + "attached_condition": "(test.t2.i = test.t1.i)" + } /* table */ + } /* query_block */ + } + ] /* group_by_subqueries */ + } /* grouping_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "6.50" + } /* cost_info */, + "ordering_operation": { + "using_temporary_table": true, + "using_filesort": true, + "grouping_operation": { + "using_filesort": false, + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": [ + "k1" + ] /* possible_keys */, + "key": "k1", + "used_key_parts": [ + "a" + ] /* used_key_parts */, + "key_length": "4", + "rows_examined_per_scan": 11, + "rows_produced_per_join": 11, + "filtered": "100.00", + "using_index_for_group_by": true, + "cost_info": { + "read_cost": "4.30", + "eval_cost": "2.20", + "prefix_cost": "6.50", + "data_read_per_join": "176" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */ + } /* table */ + } /* grouping_operation */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "6.20" + } /* cost_info */, + "ordering_operation": { + "using_temporary_table": true, + "using_filesort": true, + "grouping_operation": { + "using_filesort": true, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "possible_keys": [ + "PRIMARY" + ] /* possible_keys */, + "rows_examined_per_scan": 3, + "rows_produced_per_join": 3, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "0.60", + "prefix_cost": "2.61", + "data_read_per_join": "48" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "ref", + "possible_keys": [ + "PRIMARY" + ] /* possible_keys */, + "key": "PRIMARY", + "used_key_parts": [ + "a" + ] /* used_key_parts */, + "key_length": "4", + "ref": [ + "test.t1.a" + ] /* ref */, + "rows_examined_per_scan": 1, + "rows_produced_per_join": 3, + "filtered": "100.00", + "using_index": true, + "cost_info": { + "read_cost": "3.00", + "eval_cost": "0.60", + "prefix_cost": "6.21", + "data_read_per_join": "48" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */ + } /* table */ + } + ] /* nested_loop */ + } /* grouping_operation */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "12.82" + } /* cost_info */, + "grouping_operation": { + "using_filesort": true, + "cost_info": { + "sort_cost": "9.00" + } /* cost_info */, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 9, + "rows_produced_per_join": 9, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.02", + "eval_cost": "1.80", + "prefix_cost": "3.82", + "data_read_per_join": "144" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */ + } /* table */ + } /* grouping_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "3.01" + } /* cost_info */, + "ordering_operation": { + "using_filesort": true, + "duplicates_removal": { + "using_temporary_table": true, + "using_filesort": false, + "grouping_operation": { + "using_temporary_table": true, + "using_filesort": false, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows_examined_per_scan": 5, + "rows_produced_per_join": 5, + "filtered": "100.00", + "cost_info": { + "read_cost": "2.01", + "eval_cost": "1.00", + "prefix_cost": "3.01", + "data_read_per_join": "80" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */ + } /* table */ + } /* grouping_operation */ + } /* duplicates_removal */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "2.40" + } /* cost_info */, + "ordering_operation": { + "using_filesort": false, + "duplicates_removal": { + "using_temporary_table": true, + "using_filesort": false, + "buffer_result": { + "using_temporary_table": true, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "system", + "rows_examined_per_scan": 1, + "rows_produced_per_join": 1, + "filtered": "100.00", + "cost_info": { + "read_cost": "0.00", + "eval_cost": "0.20", + "prefix_cost": "0.00", + "data_read_per_join": "8" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */ + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "index", + "key": "PRIMARY", + "used_key_parts": [ + "a" + ] /* used_key_parts */, + "key_length": "4", + "rows_examined_per_scan": 2, + "rows_produced_per_join": 2, + "filtered": "100.00", + "using_index": true, + "distinct": true, + "cost_info": { + "read_cost": "2.00", + "eval_cost": "0.40", + "prefix_cost": "2.40", + "data_read_per_join": "16" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */ + } /* table */ + } + ] /* nested_loop */ + } /* buffer_result */ + } /* duplicates_removal */ + } /* ordering_operation */ + } /* query_block */ +}`, + `{ + "query_block": { + "select_id": 1, + "cost_info": { + "query_cost": "6.41" + } /* cost_info */, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "possible_keys": [ + "PRIMARY" + ] /* possible_keys */, + "rows_examined_per_scan": 4, + "rows_produced_per_join": 3, + "filtered": "75.00", + "cost_info": { + "read_cost": "2.21", + "eval_cost": "0.60", + "prefix_cost": "2.81", + "data_read_per_join": "48" + } /* cost_info */, + "used_columns": [ + "a", + "b" + ] /* used_columns */, + "attached_condition": "(test.t1.b <> 30)" + } /* table */ + }, + { + "table": { + "table_name": "t2", + "access_type": "eq_ref", + "possible_keys": [ + "PRIMARY" + ] /* possible_keys */, + "key": "PRIMARY", + "used_key_parts": [ + "a" + ] /* used_key_parts */, + "key_length": "4", + "ref": [ + "test.t1.a" + ] /* ref */, + "rows_examined_per_scan": 1, + "rows_produced_per_join": 3, + "filtered": "100.00", + "using_index": true, + "cost_info": { + "read_cost": "3.00", + "eval_cost": "0.60", + "prefix_cost": "6.41", + "data_read_per_join": "24" + } /* cost_info */, + "used_columns": [ + "a" + ] /* used_columns */ + } /* table */ + } + ] /* nested_loop */ + } /* query_block */ +}`, +} + +func TestExplain(t *testing.T) { + for _, sql := range sqls { + exp, err := connTest.Explain(sql, TraditionalExplainType, TraditionalFormatExplain) + //exp, err := conn.Explain(sql, TraditionalExplainType, JSONFormatExplain) + fmt.Println("Old: ", sql) + fmt.Println("New: ", exp.SQL) + if err != nil { + fmt.Println(err) + } + pretty.Println(exp) + fmt.Println() + } +} + +func TestParseExplainText(t *testing.T) { + for _, content := range exp { + pretty.Println(RemoveSQLComments(content)) + pretty.Println(ParseExplainText(content)) + } + /* + //length := len(exp) + pretty.Println(string(RemoveSQLComments([]byte(exp[9])))) + explainInfo, err := ParseExplainText(exp[9]) + pretty.Println(explainInfo) + fmt.Println(err) + */ +} + +func TestFindTablesInJson(t *testing.T) { + idx := 9 + for _, j := range exp[idx : idx+1] { + pretty.Println(j) + findTablesInJSON(j, 0) + } + pretty.Println(len(explainJSONTables), explainJSONTables) +} + +func TestFormatJsonIntoTraditional(t *testing.T) { + idx := 11 + for _, j := range exp[idx : idx+1] { + pretty.Println(j) + pretty.Println(FormatJSONIntoTraditional(j)) + } +} + +func TestPrintMarkdownExplainTable(t *testing.T) { + expInfo, err := connTest.Explain("select 1", TraditionalExplainType, TraditionalFormatExplain) + if err != nil { + t.Error(err) + } + err = common.GoldenDiff(func() { + PrintMarkdownExplainTable(expInfo) + }, t.Name(), update) + if err != nil { + t.Error(err) + } +} + +func TestExplainInfoTranslator(t *testing.T) { + expInfo, err := connTest.Explain("select 1", TraditionalExplainType, TraditionalFormatExplain) + if err != nil { + t.Error(err) + } + err = common.GoldenDiff(func() { + ExplainInfoTranslator(expInfo) + }, t.Name(), update) + if err != nil { + t.Error(err) + } +} + +func TestMySQLExplainWarnings(t *testing.T) { + expInfo, err := connTest.Explain("select 1", TraditionalExplainType, TraditionalFormatExplain) + if err != nil { + t.Error(err) + } + err = common.GoldenDiff(func() { + MySQLExplainWarnings(expInfo) + }, t.Name(), update) + if err != nil { + t.Error(err) + } +} + +func TestMySQLExplainQueryCost(t *testing.T) { + expInfo, err := connTest.Explain("select 1", TraditionalExplainType, TraditionalFormatExplain) + if err != nil { + t.Error(err) + } + err = common.GoldenDiff(func() { + MySQLExplainQueryCost(expInfo) + }, t.Name(), update) + if err != nil { + t.Error(err) + } +} + +func TestSupportExplainWrite(t *testing.T) { + _, err := connTest.supportExplainWrite() + if err != nil { + t.Error(err) + } +} + +func TestExplainAbleSQL(t *testing.T) { + for _, sql := range sqls { + if _, err := connTest.explainAbleSQL(sql); err != nil { + t.Errorf("SQL: %s, not explain able", sql) + } + } +} diff --git a/vendor/github.com/XiaoMi/soar/database/mysql.go b/vendor/github.com/XiaoMi/soar/database/mysql.go new file mode 100644 index 0000000000000000000000000000000000000000..fa6927d46d17252829fc5e594f7b35d3beb0c843 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/mysql.go @@ -0,0 +1,306 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "regexp" + "strconv" + "strings" + "time" + + "github.com/XiaoMi/soar/ast" + "github.com/XiaoMi/soar/common" + + "github.com/ziutek/mymysql/mysql" + // mymysql driver + _ "github.com/ziutek/mymysql/native" + "vitess.io/vitess/go/vt/sqlparser" +) + +// Connector 数据库连接基本对象 +type Connector struct { + Addr string + User string + Pass string + Database string + Charset string +} + +// QueryResult 数据库查询返回值 +type QueryResult struct { + Rows []mysql.Row + Result mysql.Result + Error error + Warning []mysql.Row + QueryCost float64 +} + +// NewConnection 创建新连接 +func (db *Connector) NewConnection() mysql.Conn { + return mysql.New("tcp", "", db.Addr, db.User, db.Pass, db.Database) +} + +// Query 执行SQL +func (db *Connector) Query(sql string, params ...interface{}) (*QueryResult, error) { + // 测试环境如果检查是关闭的,则SQL不会被执行 + if common.Config.TestDSN.Disable { + return nil, errors.New("Dsn Disable") + } + + // 数据库安全性检查:如果 Connector 的 IP 端口与 TEST 环境不一致,则启用SQL白名单 + // 不在白名单中的SQL不允许执行 + // 执行环境与test环境不相同 + if db.Addr != common.Config.TestDSN.Addr && db.dangerousQuery(sql) { + return nil, fmt.Errorf("query execution deny: execute SQL with DSN(%s/%s) '%s'", + db.Addr, db.Database, fmt.Sprintf(sql, params...)) + } + + common.Log.Debug("Execute SQL with DSN(%s/%s) : %s", db.Addr, db.Database, fmt.Sprintf(sql, params...)) + conn := db.NewConnection() + + // 设置SQL连接超时时间 + conn.SetTimeout(time.Duration(common.Config.ConnTimeOut) * time.Second) + defer conn.Close() + err := conn.Connect() + if err != nil { + return nil, err + } + + // 添加SQL执行超时限制 + ch := make(chan QueryResult, 1) + go func() { + res := QueryResult{} + res.Rows, res.Result, res.Error = conn.Query(sql, params...) + + if common.Config.ShowWarnings { + warning, _, err := conn.Query("SHOW WARNINGS") + if err == nil { + res.Warning = warning + } + } + + // SHOW WARNINGS 并不会影响 last_query_cost + if common.Config.ShowLastQueryCost { + cost, _, err := conn.Query("SHOW SESSION STATUS LIKE 'last_query_cost'") + if err == nil { + if len(cost) > 0 { + res.QueryCost = cost[0].Float(1) + } + } + } + + ch <- res + }() + + select { + case res := <-ch: + return &res, res.Error + case <-time.After(time.Duration(common.Config.QueryTimeOut) * time.Second): + return nil, errors.New("query execution timeout") + } + +} + +// Version 获取MySQL数据库版本 +func (db *Connector) Version() (int, error) { + version := 99999 + // 从数据库中获取版本信息 + res, err := db.Query("select @@version") + if err != nil { + common.Log.Warn("(db *Connector) Version() Error: %v", err) + return version, err + } + + // MariaDB https://mariadb.com/kb/en/library/comment-syntax/ + // MySQL https://dev.mysql.com/doc/refman/8.0/en/comments.html + versionStr := strings.Split(res.Rows[0].Str(0), "-")[0] + versionSeg := strings.Split(versionStr, ".") + if len(versionSeg) == 3 { + versionStr = fmt.Sprintf("%s%02s%02s", versionSeg[0], versionSeg[1], versionSeg[2]) + version, err = strconv.Atoi(versionStr) + } + return version, err +} + +// Source execute sql from file +func (db *Connector) Source(file string) ([]*QueryResult, error) { + var sqlCounter int // SQL 计数器 + var result []*QueryResult + + fd, err := os.Open(file) + defer func() { + err = fd.Close() + if err != nil { + common.Log.Error("(db *Connector) Source(%s) fd.Close failed: %s", file, err.Error()) + } + }() + if err != nil { + common.Log.Warning("(db *Connector) Source(%s) os.Open failed: %s", file, err.Error()) + return nil, err + } + data, err := ioutil.ReadAll(fd) + if err != nil { + common.Log.Critical("ioutil.ReadAll Error: %s", err.Error()) + return nil, err + } + + sql := strings.TrimSpace(string(data)) + buf := strings.TrimSpace(sql) + for ; ; sqlCounter++ { + if buf == "" { + break + } + + // 查询请求切分 + _, sql, bufBytes := ast.SplitStatement([]byte(buf), []byte(common.Config.Delimiter)) + buf = string(bufBytes) + sql = strings.TrimSpace(sql) + common.Log.Debug("Source Query SQL: %s", sql) + + res, e := db.Query(sql) + if e != nil { + common.Log.Error("(db *Connector) Source Filename: %s, SQLCounter.: %d", file, sqlCounter) + return result, e + } + result = append(result, res) + } + return result, nil +} + +// SingleIntValue 获取某个int型变量的值 +func (db *Connector) SingleIntValue(option string) (int, error) { + // 从数据库中获取信息 + res, err := db.Query("select @@%s", option) + if err != nil { + common.Log.Warn("(db *Connector) SingleIntValue() Error: %v", err) + return -1, err + } + + return res.Rows[0].Int(0), err +} + +// ColumnCardinality 粒度计算 +func (db *Connector) ColumnCardinality(tb, col string) float64 { + // 获取该表上的已有的索引 + + // show table status 获取总行数(近似) + tbStatus, err := db.ShowTableStatus(tb) + if err != nil { + common.Log.Warn("(db *Connector) ColumnCardinality() ShowTableStatus Error: %v", err) + return 0 + } + + // 如果是视图或表中无数据,rowTotal 都为0 + // 视图不需要加索引,无数据相当于散粒度为1 + if len(tbStatus.Rows) == 0 { + common.Log.Debug("(db *Connector) ColumnCardinality() No table status: %s", tb) + return 1 + } + rowTotal := tbStatus.Rows[0].Rows + if rowTotal == 0 { + if common.Config.Sampling { + common.Log.Debug("ColumnCardinality, %s rowTotal == 0", tb) + } + return 1 + } + + // rowTotal > xxx 时保护数据库,不对该值计算散粒度,xxx可以在配置中设置 + if rowTotal > common.Config.MaxTotalRows { + return 0.5 + } + + // 计算该列散粒度 + res, err := db.Query("select count(distinct `%s`) from `%s`.`%s`", col, db.Database, tb) + if err != nil { + common.Log.Warn("(db *Connector) ColumnCardinality() Query Error: %v", err) + return 0 + } + + colNum := res.Rows[0].Float(0) + + // 散粒度区间:[0,1] + return colNum / float64(rowTotal) +} + +// IsView 判断表是否是视图 +func (db *Connector) IsView(tbName string) bool { + tbStatus, err := db.ShowTableStatus(tbName) + if err != nil { + common.Log.Error("(db *Connector) IsView Error: %v:", err) + return false + } + + if len(tbStatus.Rows) > 0 { + if tbStatus.Rows[0].Comment == "VIEW" { + return true + } + } + + return false + +} + +// RemoveSQLComments 去除SQL中的注释 +func RemoveSQLComments(sql string) string { + buf := []byte(sql) + cmtReg := regexp.MustCompile(`("(""|[^"])*")|('(''|[^'])*')|(--[^\n\r]*)|(#.*)|(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)`) + + res := cmtReg.ReplaceAllFunc(buf, func(s []byte) []byte { + if (s[0] == '"' && s[len(s)-1] == '"') || + (s[0] == '\'' && s[len(s)-1] == '\'') || + (string(s[:3]) == "/*!") { + return s + } + return []byte("") + }) + return strings.TrimSpace(string(res)) +} + +// 为了防止在 Online 环境进行误操作,通过 dangerousQuery 来判断能否在 Online 执行 +func (db *Connector) dangerousQuery(query string) bool { + queries, err := sqlparser.SplitStatementToPieces(strings.TrimSpace(strings.ToLower(query))) + if err != nil { + return true + } + + for _, sql := range queries { + dangerous := true + whiteList := []string{ + "select", + "show", + "explain", + "describe", + } + + for _, prefix := range whiteList { + if strings.HasPrefix(sql, prefix) { + dangerous = false + break + } + } + + if dangerous { + return true + } + } + + return false +} diff --git a/vendor/github.com/XiaoMi/soar/database/mysql_test.go b/vendor/github.com/XiaoMi/soar/database/mysql_test.go new file mode 100644 index 0000000000000000000000000000000000000000..79ea7bdd2a84c6254086dbdeb665d08bd528391e --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/mysql_test.go @@ -0,0 +1,111 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "fmt" + "testing" + + "github.com/XiaoMi/soar/common" + "github.com/kr/pretty" +) + +// TODO: go test -race不通过待解决 +func TestQuery(t *testing.T) { + common.Config.QueryTimeOut = 1 + _, err := connTest.Query("select sleep(2)") + if err == nil { + t.Error("connTest.Query not timeout") + } +} + +func TestColumnCardinality(_ *testing.T) { + connTest.Database = "information_schema" + a := connTest.ColumnCardinality("TABLES", "TABLE_SCHEMA") + fmt.Println("TABLES.TABLE_SCHEMA:", a) +} + +func TestDangerousSQL(t *testing.T) { + testCase := map[string]bool{ + "select * from tb;delete from tb;": true, + "show database;": false, + "select * from t;": false, + "explain delete from t;": false, + } + + db := Connector{} + for sql, want := range testCase { + got := db.dangerousQuery(sql) + if got != want { + t.Errorf("SQL:%s got:%v want:%v", sql, got, want) + } + } +} + +func TestWarningsAndQueryCost(t *testing.T) { + common.Config.ShowWarnings = true + common.Config.ShowLastQueryCost = true + res, err := connTest.Query("explain select * from sakila.film") + if err != nil { + t.Error("Query Error: ", err) + } else { + for _, w := range res.Warning { + pretty.Println(w.Str(2)) + } + fmt.Println(res.QueryCost) + pretty.Println(err) + } +} + +func TestVersion(t *testing.T) { + version, err := connTest.Version() + if err != nil { + t.Error(err.Error()) + } + fmt.Println(version) +} + +func TestSource(t *testing.T) { + res, err := connTest.Source("testdata/" + t.Name() + ".sql") + if err != nil { + t.Error("Query Error: ", err) + } + if res[0].Rows[0].Int(0) != 1 || res[1].Rows[0].Int(0) != 1 { + t.Error("Source result not match, expect 1, 1") + } +} + +func TestRemoveSQLComments(t *testing.T) { + SQLs := []string{ + `-- comment`, + `--`, + `# comment`, + `/* multi-line +comment*/`, + `-- +-- comment`, + } + + err := common.GoldenDiff(func() { + for _, sql := range SQLs { + fmt.Println(RemoveSQLComments(sql)) + } + }, t.Name(), update) + if err != nil { + t.Error(err) + } +} diff --git a/vendor/github.com/XiaoMi/soar/database/privilege.go b/vendor/github.com/XiaoMi/soar/database/privilege.go new file mode 100644 index 0000000000000000000000000000000000000000..762de2898d046ae29aca169a4c92ee971fd74f00 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/privilege.go @@ -0,0 +1,104 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "errors" + "strings" + + "github.com/XiaoMi/soar/common" +) + +// CurrentUser get current user with current_user() function +func (db *Connector) CurrentUser() (string, string, error) { + res, err := db.Query("select current_user()") + if err != nil { + return "", "", err + } + if len(res.Rows) > 0 { + cols := strings.Split(res.Rows[0].Str(0), "@") + if len(cols) == 2 { + user := strings.Trim(cols[0], "'") + host := strings.Trim(cols[1], "'") + if strings.Contains(user, "'") || strings.Contains(host, "'") { + return "", "", errors.New("user or host contains irregular character") + } + return user, host, nil + } + return "", "", errors.New("user or host contains irregular character") + } + return "", "", errors.New("no privilege info") +} + +// HasSelectPrivilege if user has select privilege +func (db *Connector) HasSelectPrivilege() bool { + user, host, err := db.CurrentUser() + if err != nil { + common.Log.Error("User: %s, HasSelectPrivilege: %s", db.User, err.Error()) + return false + } + res, err := db.Query("select Select_priv from mysql.user where user='%s' and host='%s'", user, host) + if err != nil { + common.Log.Error("HasSelectPrivilege, DSN: %s, Error: %s", db.Addr, err.Error()) + return false + } + // Select_priv + if len(res.Rows) > 0 { + if res.Rows[0].Str(0) == "Y" { + return true + } + } + return false +} + +// HasAllPrivilege if user has all privileges +func (db *Connector) HasAllPrivilege() bool { + user, host, err := db.CurrentUser() + if err != nil { + common.Log.Error("User: %s, HasAllPrivilege: %s", db.User, err.Error()) + return false + } + + // concat privilege columns + res, err := db.Query("SELECT GROUP_CONCAT(COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA='mysql' and TABLE_NAME='user' and COLUMN_NAME like '%%_priv'") + if err != nil { + common.Log.Error("HasAllPrivilege, DSN: %s, Error: %s", db.Addr, err.Error()) + return false + } + var priv string + if len(res.Rows) > 0 { + priv = res.Rows[0].Str(0) + } else { + common.Log.Error("HasAllPrivilege, DSN: %s, get privilege string error", db.Addr) + return false + } + + // get all privilege status + res, err = db.Query("select concat("+priv+") from mysql.user where user='%s' and host='%s'", user, host) + if err != nil { + common.Log.Error("HasAllPrivilege, DSN: %s, Error: %s", db.Addr, err.Error()) + return false + } + + // %_priv + if len(res.Rows) > 0 { + if strings.Replace(res.Rows[0].Str(0), "Y", "", -1) == "" { + return true + } + } + return false +} diff --git a/vendor/github.com/XiaoMi/soar/database/privilege_test.go b/vendor/github.com/XiaoMi/soar/database/privilege_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4ed0fbc609d70550cca119c59b6e7583975e0fdc --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/privilege_test.go @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import "testing" + +func TestHasSelectPrivilege(t *testing.T) { + if !connTest.HasSelectPrivilege() { + t.Errorf("DSN: %s, User: %s, should has select privilege", connTest.Addr, connTest.User) + } +} + +func TestHasAllPrivilege(t *testing.T) { + if !connTest.HasAllPrivilege() { + t.Errorf("DSN: %s, User: %s, should has all privilege", connTest.Addr, connTest.User) + } +} diff --git a/vendor/github.com/XiaoMi/soar/database/profiling.go b/vendor/github.com/XiaoMi/soar/database/profiling.go new file mode 100644 index 0000000000000000000000000000000000000000..a6072313e09e554ecb04ac2fd89aa91bac3a9be1 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/profiling.go @@ -0,0 +1,135 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "errors" + "fmt" + "io" + "strings" + "time" + + "github.com/XiaoMi/soar/common" + + "vitess.io/vitess/go/vt/sqlparser" +) + +// Profiling show profile输出的结果 +type Profiling struct { + Rows []ProfilingRow +} + +// ProfilingRow show profile每一行信息 +type ProfilingRow struct { + Status string + Duration float64 + // TODO: 支持show profile all,不过目前看all的信息过多有点眼花缭乱 +} + +// Profiling 执行SQL,并对其Profiling +func (db *Connector) Profiling(sql string, params ...interface{}) (*QueryResult, error) { + // 过滤不需要 profiling 的 SQL + switch sqlparser.Preview(sql) { + case sqlparser.StmtSelect, sqlparser.StmtUpdate, sqlparser.StmtDelete: + default: + return nil, errors.New("no need profiling") + } + + // 测试环境如果检查是关闭的,则SQL不会被执行 + if common.Config.TestDSN.Disable { + return nil, errors.New("Dsn Disable") + } + + // 数据库安全性检查:如果 Connector 的 IP 端口与 TEST 环境不一致,则启用 SQL 白名单 + // 不在白名单中的SQL不允许执行 + // 执行环境与test环境不相同 + if db.Addr != common.Config.TestDSN.Addr && db.dangerousQuery(sql) { + return nil, fmt.Errorf("query execution deny: Execute SQL with DSN(%s/%s) '%s'", + db.Addr, db.Database, fmt.Sprintf(sql, params...)) + } + + common.Log.Debug("Execute SQL with DSN(%s/%s) : %s", db.Addr, db.Database, sql) + conn := db.NewConnection() + + // 设置SQL连接超时时间 + conn.SetTimeout(time.Duration(common.Config.ConnTimeOut) * time.Second) + defer conn.Close() + err := conn.Connect() + if err != nil { + return nil, err + } + + // 添加SQL执行超时限制 + ch := make(chan QueryResult, 1) + go func() { + // 开启Profiling + _, _, err = conn.Query("set @@profiling=1") + common.LogIfError(err, "") + + // 执行SQL,抛弃返回结果 + result, err := conn.Start(sql, params...) + if err != nil { + ch <- QueryResult{ + Error: err, + } + return + } + row := result.MakeRow() + for { + err = result.ScanRow(row) + if err == io.EOF { + break + } + } + + // 返回Profiling结果 + res := QueryResult{} + res.Rows, res.Result, res.Error = conn.Query("show profile") + _, _, err = conn.Query("set @@profiling=0") + common.LogIfError(err, "") + ch <- res + }() + + select { + case res := <-ch: + return &res, res.Error + case <-time.After(time.Duration(common.Config.QueryTimeOut) * time.Second): + return nil, errors.New("query execution timeout") + } +} + +func getProfiling(res *QueryResult) Profiling { + var rows []ProfilingRow + for _, row := range res.Rows { + rows = append(rows, ProfilingRow{ + Status: row.Str(0), + Duration: row.Float(1), + }) + } + return Profiling{Rows: rows} +} + +// FormatProfiling 格式化输出Profiling信息 +func FormatProfiling(res *QueryResult) string { + profiling := getProfiling(res) + str := []string{"| Status | Duration |"} + str = append(str, "| --- | --- |") + for _, row := range profiling.Rows { + str = append(str, fmt.Sprintf("| %s | %f |", row.Status, row.Duration)) + } + return strings.Join(str, "\n") +} diff --git a/vendor/github.com/XiaoMi/soar/database/profiling_test.go b/vendor/github.com/XiaoMi/soar/database/profiling_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4b226ba90e4db8f482f3f55fc6f16c92a247ed8a --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/profiling_test.go @@ -0,0 +1,53 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "testing" + + "github.com/XiaoMi/soar/common" + + "github.com/kr/pretty" +) + +func TestProfiling(t *testing.T) { + common.Config.QueryTimeOut = 1 + res, err := connTest.Profiling("select 1") + if err == nil { + pretty.Println(res) + } else { + t.Error(err) + } +} + +func TestFormatProfiling(t *testing.T) { + res, err := connTest.Profiling("select 1") + if err == nil { + pretty.Println(FormatProfiling(res)) + } else { + t.Error(err) + } +} + +func TestGetProfiling(t *testing.T) { + res, err := connTest.Profiling("select 1") + if err == nil { + pretty.Println(getProfiling(res)) + } else { + t.Error(err) + } +} diff --git a/vendor/github.com/XiaoMi/soar/database/sampling.go b/vendor/github.com/XiaoMi/soar/database/sampling.go new file mode 100644 index 0000000000000000000000000000000000000000..f8565b4cd610fc6259ccc089729418a6832c6af7 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/sampling.go @@ -0,0 +1,230 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "fmt" + "io" + "strconv" + "strings" + "time" + + "github.com/XiaoMi/soar/common" + "github.com/ziutek/mymysql/mysql" +) + +/*-------------------- +* The following choice of minrows is based on the paper +* "Random sampling for histogram construction: how much is enough?" +* by Surajit Chaudhuri, Rajeev Motwani and Vivek Narasayya, in +* Proceedings of ACM SIGMOD International Conference on Management +* of Data, 1998, Pages 436-447. Their Corollary 1 to Theorem 5 +* says that for table size n, histogram size k, maximum relative +* error in bin size f, and error probability gamma, the minimum +* random sample size is +* r = 4 * k * ln(2*n/gamma) / f^2 +* Taking f = 0.5, gamma = 0.01, n = 10^6 rows, we obtain +* r = 305.82 * k +* Note that because of the log function, the dependence on n is +* quite weak; even at n = 10^12, a 300*k sample gives <= 0.66 +* bin size error with probability 0.99. So there's no real need to +* scale for n, which is a good thing because we don't necessarily +* know it at this point. +*-------------------- + */ + +// SamplingData 将数据从Remote拉取到 db 中 +func (db *Connector) SamplingData(remote Connector, tables ...string) error { + // 计算需要泵取的数据量 + wantRowsCount := 300 * common.Config.SamplingStatisticTarget + + // 设置数据采样单条 SQL 中 value 的数量 + // 该数值越大,在内存中缓存的data就越多,但相对的,插入时速度就越快 + maxValCount := 200 + + // 获取数据库连接对象 + conn := remote.NewConnection() + localConn := db.NewConnection() + + // 连接数据库 + err := conn.Connect() + defer conn.Close() + if err != nil { + return err + } + + err = localConn.Connect() + defer localConn.Close() + if err != nil { + return err + } + + for _, table := range tables { + // 表类型检查 + if remote.IsView(table) { + return nil + } + + tableStatus, err := remote.ShowTableStatus(table) + if err != nil { + return err + } + + if len(tableStatus.Rows) == 0 { + common.Log.Info("SamplingData, Table %s with no data, stop sampling", table) + return nil + } + + tableRows := tableStatus.Rows[0].Rows + if tableRows == 0 { + common.Log.Info("SamplingData, Table %s with no data, stop sampling", table) + return nil + } + + factor := float64(wantRowsCount) / float64(tableRows) + common.Log.Debug("SamplingData, tableRows: %d, wantRowsCount: %d, factor: %f", tableRows, wantRowsCount, factor) + + err = startSampling(conn, localConn, db.Database, table, factor, wantRowsCount, maxValCount) + if err != nil { + common.Log.Error("(db *Connector) SamplingData Error : %v", err) + } + } + return nil +} + +// 开始从环境中泵取数据 +// 因为涉及到的数据量问题,所以泵取与插入时同时进行的 +// TODO 加 ref link +func startSampling(conn, localConn mysql.Conn, database, table string, factor float64, wants, maxValCount int) error { + // 从线上数据库获取所需dump的表中所有列的数据类型,备用 + // 由于测试库中的库表为刚建立的,所以在information_schema中很可能没有这个表的信息 + var dataTypes []string + q := fmt.Sprintf("select DATA_TYPE from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME = '%s'", + database, table) + common.Log.Debug("Sampling data execute: %s", q) + rs, _, err := localConn.Query(q) + if err != nil { + common.Log.Debug("Sampling data got data type Err: %v", err) + } else { + for _, r := range rs { + dataTypes = append(dataTypes, r.Str(0)) + } + } + + // 生成where条件 + where := fmt.Sprintf("where RAND()<=%f", factor) + if factor >= 1 { + where = "" + } + + sql := fmt.Sprintf("select * from `%s` %s limit %d;", table, where, wants) + res, err := conn.Start(sql) + if err != nil { + return err + } + + // GetRow method allocates a new chunk of memory for every received row. + row := res.MakeRow() + rowCount := 0 + valCount := 0 + + // 获取所有的列名 + columns := make([]string, len(res.Fields())) + for i, filed := range res.Fields() { + columns[i] = filed.Name + } + colDef := strings.Join(columns, ",") + + // 开始填充数据 + var valList []string + for { + err := res.ScanRow(row) + if err == io.EOF { + // 扫描结束 + if len(valList) > 0 { + // 如果缓存中还存在未插入的数据,则把缓存中的数据刷新到DB中 + doSampling(localConn, database, table, colDef, strings.Join(valList, ",")) + } + break + } + + if err != nil { + return err + } + + values := make([]string, len(columns)) + for i := range row { + // TODO 不支持坐标类型的导出 + switch data := row[i].(type) { + case nil: + // str = "" + case []byte: + // 先尝试转成数字,如果报错则转换成string + if v, err := row.Int64Err(i); err != nil { + values[i] = string(data) + } else { + values[i] = strconv.FormatInt(v, 10) + } + case time.Time: + values[i] = mysql.TimeString(data) + case time.Duration: + values[i] = mysql.DurationString(data) + default: + values[i] = fmt.Sprint(data) + } + + // 非text/varchar类的数据类型,如果dump出的数据为空,则说明该值为null值 + // 应转换其 value 为 null,如果用空('')进行替代,会导致出现语法错误。 + if len(dataTypes) == len(res.Fields()) && values[i] == "" && + (!strings.Contains(dataTypes[i], "char") || + !strings.Contains(dataTypes[i], "text")) { + values[i] = "null" + } else { + values[i] = "'" + values[i] + "'" + } + } + + valuesStr := fmt.Sprintf(`(%s)`, strings.Join(values, `,`)) + valList = append(valList, valuesStr) + + rowCount++ + valCount++ + + if rowCount%maxValCount == 0 { + doSampling(localConn, database, table, colDef, strings.Join(valList, ",")) + valCount = 0 + valList = make([]string, 0) + + } + } + + common.Log.Debug("%d rows sampling out", rowCount) + return nil +} + +// 将泵取的数据转换成Insert语句并在数据库中执行 +func doSampling(conn mysql.Conn, dbName, table, colDef, values string) { + sql := fmt.Sprintf("Insert into `%s`.`%s`(%s) values%s;", dbName, table, + colDef, values) + + _, _, err := conn.Query(sql) + + if err != nil { + common.Log.Error("doSampling Error from %s.%s: %v", dbName, table, err) + } + +} diff --git a/vendor/github.com/XiaoMi/soar/database/sampling_test.go b/vendor/github.com/XiaoMi/soar/database/sampling_test.go new file mode 100644 index 0000000000000000000000000000000000000000..082d5e9fc3bd03202da2fb7a3897f318e782b7ac --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/sampling_test.go @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "testing" + + "github.com/XiaoMi/soar/common" +) + +func init() { + common.BaseDir = common.DevPath +} + +func TestSamplingData(t *testing.T) { + online := &Connector{ + Addr: common.Config.OnlineDSN.Addr, + User: common.Config.OnlineDSN.User, + Pass: common.Config.OnlineDSN.Password, + Database: common.Config.OnlineDSN.Schema, + } + + offline := &Connector{ + Addr: common.Config.TestDSN.Addr, + User: common.Config.TestDSN.User, + Pass: common.Config.TestDSN.Password, + Database: common.Config.TestDSN.Schema, + } + + offline.Database = "test" + + err := connTest.SamplingData(*online, "film") + if err != nil { + t.Error(err) + } +} diff --git a/vendor/github.com/XiaoMi/soar/database/show.go b/vendor/github.com/XiaoMi/soar/database/show.go new file mode 100644 index 0000000000000000000000000000000000000000..a14a5fbe90e555bb8a3f513e95333657eab7e70d --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/show.go @@ -0,0 +1,584 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "fmt" + "regexp" + "strconv" + "strings" + "time" + + "github.com/XiaoMi/soar/common" +) + +// SHOW TABLE STATUS Syntax +// https://dev.mysql.com/doc/refman/5.7/en/show-table-status.html + +// TableStatInfo 用以保存 show table status 之后获取的table信息 +type TableStatInfo struct { + Name string + Rows []tableStatusRow +} + +// tableStatusRow 用于 show table status value +type tableStatusRow struct { + Name string // 表名 + Engine string // 该表使用的存储引擎 + Version int // 该表的 .frm 文件版本号 + RowFormat string // 该表使用的行存储格式 + Rows int64 // 表行数, InnoDB 引擎中为预估值,甚至可能会有40%~50%的数值偏差 + AvgRowLength int // 平均行长度 + + // MyISAM: Data_length 为数据文件的大小,单位为 bytes + // InnoDB: Data_length 为聚簇索引分配的近似内存量,单位为 bytes, 计算方式为聚簇索引数量乘以 InnoDB 页面大小 + // 其他不同的存储引擎中该值的意义可能不尽相同 + DataLength int + + // MyISAM: Max_data_length 为数据文件长度的最大值。这是在给定使用的数据指针大小的情况下,可以存储在表中的数据的最大字节数 + // InnoDB: 未使用 + // 其他不同的存储引擎中该值的意义可能不尽相同 + MaxDataLength int + + // MyISAM: Index_length 为 index 文件的大小,单位为 bytes + // InnoDB: Index_length 为非聚簇索引分配的近似内存量,单位为 bytes,计算方式为非聚簇索引数量乘以 InnoDB 页面大小 + // 其他不同的存储引擎中该值的意义可能不尽相同 + IndexLength int + + DataFree int // 已分配但未使用的字节数 + AutoIncrement int // 下一个自增值 + CreateTime time.Time // 创建时间 + UpdateTime time.Time // 最近一次更新时间,该值不准确 + CheckTime time.Time // 上次检查时间 + Collation string // 字符集及排序规则信息 + Checksum string // 校验和 + CreateOptions string // 创建表的时候的时候一切其他属性 + Comment string // 注释 +} + +// newTableStat 构造 table Stat 对象 +func newTableStat(tableName string) *TableStatInfo { + return &TableStatInfo{ + Name: tableName, + Rows: make([]tableStatusRow, 0), + } +} + +// ShowTables 执行 show tables +func (db *Connector) ShowTables() ([]string, error) { + defer func() { + err := recover() + if err != nil { + common.Log.Error("recover ShowTableStatus()", err) + } + }() + + // 执行 show table status + res, err := db.Query("show tables") + if err != nil { + return []string{}, err + } + + // 获取值 + var tables []string + for _, row := range res.Rows { + tables = append(tables, row.Str(0)) + } + + return tables, err +} + +// ShowTableStatus 执行 show table status +func (db *Connector) ShowTableStatus(tableName string) (*TableStatInfo, error) { + defer func() { + err := recover() + if err != nil { + common.Log.Error("recover ShowTableStatus()", err) + } + }() + + // 初始化struct + ts := newTableStat(tableName) + + // 执行 show table status + res, err := db.Query("show table status where name = '%s'", ts.Name) + if err != nil { + return ts, err + } + + rs := res.Result.Map("Rows") + name := res.Result.Map("Name") + df := res.Result.Map("Data_free") + sum := res.Result.Map("Checksum") + engine := res.Result.Map("Engine") + version := res.Result.Map("Version") + comment := res.Result.Map("Comment") + ai := res.Result.Map("Auto_increment") + collation := res.Result.Map("Collation") + rowFormat := res.Result.Map("Row_format") + checkTime := res.Result.Map("Check_time") + dataLength := res.Result.Map("Data_length") + idxLength := res.Result.Map("Index_length") + createTime := res.Result.Map("Create_time") + updateTime := res.Result.Map("Update_time") + options := res.Result.Map("Create_options") + avgRowLength := res.Result.Map("Avg_row_length") + maxDataLength := res.Result.Map("Max_data_length") + + // 获取值 + for _, row := range res.Rows { + value := tableStatusRow{ + Name: row.Str(name), + Engine: row.Str(engine), + Version: row.Int(version), + Rows: row.Int64(rs), + RowFormat: row.Str(rowFormat), + AvgRowLength: row.Int(avgRowLength), + DataLength: row.Int(dataLength), + MaxDataLength: row.Int(maxDataLength), + IndexLength: row.Int(idxLength), + DataFree: row.Int(df), + AutoIncrement: row.Int(ai), + CreateTime: row.Time(createTime, time.Local), + UpdateTime: row.Time(updateTime, time.Local), + CheckTime: row.Time(checkTime, time.Local), + Collation: row.Str(collation), + Checksum: row.Str(sum), + CreateOptions: row.Str(options), + Comment: row.Str(comment), + } + ts.Rows = append(ts.Rows, value) + } + + return ts, err +} + +// https://dev.mysql.com/doc/refman/5.7/en/show-index.html + +// TableIndexInfo 用以保存 show index 之后获取的 index 信息 +type TableIndexInfo struct { + TableName string + IdxRows []TableIndexRow +} + +// TableIndexRow 用以存放show index之后获取的每一条index信息 +type TableIndexRow struct { + Table string // 表名 + NonUnique int // 0:unique key,1:not unique + KeyName string // index的名称,如果是主键则为 "PRIMARY" + SeqInIndex int // 该列在索引中的位置。计数从 1 开始 + ColumnName string // 列名 + Collation string // A or Null + Cardinality int // 索引中唯一值的数量,"ANALYZE TABLE" 可更新该值 + SubPart int // 索引前缀字节数 + Packed int + Null string // 表示该列是否可以为空,如果可以为 'YES',反之'' + IndexType string // BTREE, FULLTEXT, HASH, RTREE + Comment string + IndexComment string +} + +// NewTableIndexInfo 构造 TableIndexInfo +func NewTableIndexInfo(tableName string) *TableIndexInfo { + return &TableIndexInfo{ + TableName: tableName, + IdxRows: make([]TableIndexRow, 0), + } +} + +// ShowIndex show Index +func (db *Connector) ShowIndex(tableName string) (*TableIndexInfo, error) { + tbIndex := NewTableIndexInfo(tableName) + + // 执行 show create table + res, err := db.Query("show index from `%s`.`%s`", db.Database, tableName) + if err != nil { + return nil, err + } + + table := res.Result.Map("Table") + unique := res.Result.Map("Non_unique") + keyName := res.Result.Map("Key_name") + seq := res.Result.Map("Seq_in_index") + cName := res.Result.Map("Column_name") + collation := res.Result.Map("Collation") + cardinality := res.Result.Map("Cardinality") + subPart := res.Result.Map("Sub_part") + packed := res.Result.Map("Packed") + null := res.Result.Map("Null") + idxType := res.Result.Map("Index_type") + comment := res.Result.Map("Comment") + idxComment := res.Result.Map("Index_comment") + + // 获取值 + for _, row := range res.Rows { + value := TableIndexRow{ + Table: row.Str(table), + NonUnique: row.Int(unique), + KeyName: row.Str(keyName), + SeqInIndex: row.Int(seq), + ColumnName: row.Str(cName), + Collation: row.Str(collation), + Cardinality: row.Int(cardinality), + SubPart: row.Int(subPart), + Packed: row.Int(packed), + Null: row.Str(null), + IndexType: row.Str(idxType), + Comment: row.Str(comment), + IndexComment: row.Str(idxComment), + } + tbIndex.IdxRows = append(tbIndex.IdxRows, value) + } + return tbIndex, err +} + +// IndexSelectKey 用以对 TableIndexInfo 进行查询 +type IndexSelectKey string + +// 索引相关 +const ( + IndexKeyName = IndexSelectKey("KeyName") // 索引名称 + IndexColumnName = IndexSelectKey("ColumnName") // 索引列名称 + IndexIndexType = IndexSelectKey("IndexType") // 索引类型 + IndexNonUnique = IndexSelectKey("NonUnique") // 唯一索引 +) + +// FindIndex 获取TableIndexInfo中需要的索引 +func (tbIndex *TableIndexInfo) FindIndex(arg IndexSelectKey, value string) []TableIndexRow { + var result []TableIndexRow + if tbIndex == nil { + return result + } + + value = strings.ToLower(value) + + switch arg { + case IndexKeyName: + for _, index := range tbIndex.IdxRows { + if strings.ToLower(index.KeyName) == value { + result = append(result, index) + } + } + + case IndexColumnName: + for _, index := range tbIndex.IdxRows { + if strings.ToLower(index.ColumnName) == value { + result = append(result, index) + } + } + + case IndexIndexType: + for _, index := range tbIndex.IdxRows { + if strings.ToLower(index.IndexType) == value { + result = append(result, index) + } + } + + case IndexNonUnique: + for _, index := range tbIndex.IdxRows { + unique := strconv.Itoa(index.NonUnique) + if unique == value { + result = append(result, index) + } + } + + default: + common.Log.Error("no such args: TableIndexRow") + } + + return result +} + +// desc table +// https://dev.mysql.com/doc/refman/5.7/en/show-columns.html + +// TableDesc show columns from rental; +type TableDesc struct { + Name string + DescValues []TableDescValue +} + +// TableDescValue 含有每一列的属性 +type TableDescValue struct { + Field string // 列名 + Type string // 数据类型 + Null string // 是否有NULL(NO、YES) + Collation string // 字符集 + Privileges string // 权限s + Key string // 键类型 + Default string // 默认值 + Extra string // 其他 + Comment string // 备注 +} + +// NewTableDesc 初始化一个*TableDesc +func NewTableDesc(tableName string) *TableDesc { + return &TableDesc{ + Name: tableName, + DescValues: make([]TableDescValue, 0), + } +} + +// ShowColumns 获取 DB 中所有的 columns +func (db *Connector) ShowColumns(tableName string) (*TableDesc, error) { + tbDesc := NewTableDesc(tableName) + + // 执行 show create table + res, err := db.Query("show full columns from `%s`.`%s`", db.Database, tableName) + if err != nil { + return nil, err + } + + field := res.Result.Map("Field") + tp := res.Result.Map("Type") + null := res.Result.Map("Null") + key := res.Result.Map("Key") + def := res.Result.Map("Default") + extra := res.Result.Map("Extra") + collation := res.Result.Map("Collation") + privileges := res.Result.Map("Privileges") + comm := res.Result.Map("Comment") + + // 获取值 + for _, row := range res.Rows { + value := TableDescValue{ + Field: row.Str(field), + Type: row.Str(tp), + Null: row.Str(null), + Key: row.Str(key), + Default: row.Str(def), + Extra: row.Str(extra), + Privileges: row.Str(privileges), + Collation: row.Str(collation), + Comment: row.Str(comm), + } + tbDesc.DescValues = append(tbDesc.DescValues, value) + } + return tbDesc, err +} + +// Columns 用于获取TableDesc中所有列的名称 +func (td TableDesc) Columns() []string { + var cols []string + for _, col := range td.DescValues { + cols = append(cols, col.Field) + } + return cols +} + +// showCreate show create +func (db *Connector) showCreate(createType, name string) (string, error) { + // 执行 show create table + res, err := db.Query("show create %s `%s`", createType, name) + if err != nil { + return "", err + } + + // 获取ddl + var ddl string + for _, row := range res.Rows { + ddl = row.Str(1) + } + + return ddl, err +} + +// ShowCreateDatabase show create database +func (db *Connector) ShowCreateDatabase(dbName string) (string, error) { + defer func() { + err := recover() + if err != nil { + common.Log.Error("recover ShowCreateDatabase()", err) + } + }() + return db.showCreate("database", dbName) +} + +// ShowCreateTable show create table +func (db *Connector) ShowCreateTable(tableName string) (string, error) { + defer func() { + err := recover() + if err != nil { + common.Log.Error("recover ShowCreateTable()", err) + } + }() + + ddl, err := db.showCreate("table", tableName) + + // 去除外键关联条件 + var noConstraint []string + relationReg, _ := regexp.Compile("CONSTRAINT") + for _, line := range strings.Split(ddl, "\n") { + + if relationReg.Match([]byte(line)) { + continue + } + + // 去除外键语句会使DDL中多一个','导致语法错误,要把多余的逗号去除 + if strings.Index(line, ")") == 0 { + lineWrongSyntax := noConstraint[len(noConstraint)-1] + // 如果')'前一句的末尾是',' 删除 ',' 保证语法正确性 + if strings.Index(lineWrongSyntax, ",") == len(lineWrongSyntax)-1 { + noConstraint[len(noConstraint)-1] = lineWrongSyntax[:len(lineWrongSyntax)-1] + } + } + + noConstraint = append(noConstraint, line) + } + + return strings.Join(noConstraint, "\n"), err +} + +// FindColumn find column +func (db *Connector) FindColumn(name, dbName string, tables ...string) ([]*common.Column, error) { + // 执行 show create table + var columns []*common.Column + sql := fmt.Sprintf("SELECT "+ + "c.TABLE_NAME,c.TABLE_SCHEMA,c.COLUMN_TYPE,c.CHARACTER_SET_NAME, c.COLLATION_NAME "+ + "FROM `INFORMATION_SCHEMA`.`COLUMNS` as c where c.COLUMN_NAME = '%s' ", name) + + if len(tables) > 0 { + var tmp []string + for _, table := range tables { + tmp = append(tmp, "'"+table+"'") + } + sql += fmt.Sprintf(" and c.table_name in (%s)", strings.Join(tmp, ",")) + } + + if dbName != "" { + sql += fmt.Sprintf(" and c.table_schema = '%s'", dbName) + } + + res, err := db.Query(sql) + if err != nil { + common.Log.Error("(db *Connector) FindColumn Error : ", err) + return columns, err + } + + tbName := res.Result.Map("TABLE_NAME") + schema := res.Result.Map("TABLE_SCHEMA") + colTyp := res.Result.Map("COLUMN_TYPE") + colCharset := res.Result.Map("CHARACTER_SET_NAME") + collation := res.Result.Map("COLLATION_NAME") + + // 获取ddl + for _, row := range res.Rows { + col := &common.Column{ + Name: name, + Table: row.Str(tbName), + DB: row.Str(schema), + DataType: row.Str(colTyp), + Character: row.Str(colCharset), + Collation: row.Str(collation), + } + + // 填充字符集和排序规则 + if col.Character == "" { + // 当从`INFORMATION_SCHEMA`.`COLUMNS`表中查询不到相关列的character和collation的信息时 + // 认为该列使用的character和collation与其所处的表一致 + // 由于`INFORMATION_SCHEMA`.`TABLES`表中未找到表的character,所以从按照MySQL中collation的规则从中截取character + + sql = fmt.Sprintf("SELECT `t`.`TABLE_COLLATION` FROM `INFORMATION_SCHEMA`.`TABLES` AS `t` "+ + "WHERE `t`.`TABLE_NAME`='%s' AND `t`.`TABLE_SCHEMA` = '%s'", col.Table, col.DB) + var newRes *QueryResult + newRes, err = db.Query(sql) + if err != nil { + common.Log.Error("(db *Connector) FindColumn Error : ", err) + return columns, err + } + + tbCollation := newRes.Rows[0].Str(0) + if tbCollation != "" { + col.Character = strings.Split(tbCollation, "_")[0] + col.Collation = tbCollation + } + } + + columns = append(columns, col) + } + + return columns, err +} + +// IsFKey 判断列是否是外键 +func (db *Connector) IsFKey(dbName, tbName, column string) bool { + sql := fmt.Sprintf("SELECT REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE C "+ + "WHERE REFERENCED_TABLE_SCHEMA <> 'NULL' AND"+ + " TABLE_NAME='%s' AND"+ + " TABLE_SCHEMA='%s' AND"+ + " COLUMN_NAME='%s'", tbName, dbName, column) + + res, err := db.Query(sql) + if err == nil && len(res.Rows) == 0 { + return false + } + + return true +} + +// Reference 用于存储关系 +type Reference map[string][]ReferenceValue + +// ReferenceValue 用于处理表之间的关系 +type ReferenceValue struct { + RefDBName string // 夫表所属数据库 + RefTable string // 父表 + DBName string // 子表所属数据库 + Table string // 子表 + ConstraintName string // 关系名称 +} + +// ShowReference 查找所有的外键信息 +func (db *Connector) ShowReference(dbName string, tbName ...string) ([]ReferenceValue, error) { + var referenceValues []ReferenceValue + sql := `SELECT C.REFERENCED_TABLE_SCHEMA,C.REFERENCED_TABLE_NAME,C.TABLE_SCHEMA,C.TABLE_NAME,C.CONSTRAINT_NAME +FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE C JOIN INFORMATION_SCHEMA. TABLES T ON T.TABLE_NAME = C.TABLE_NAME +WHERE C.REFERENCED_TABLE_NAME IS NOT NULL` + sql = sql + fmt.Sprintf(` AND C.TABLE_SCHEMA = "%s"`, dbName) + + if len(tbName) > 0 { + extra := fmt.Sprintf(` AND C.TABLE_NAME IN ("%s")`, strings.Join(tbName, `","`)) + sql = sql + extra + } + + // 执行SQL查找外键关联关系 + res, err := db.Query(sql) + if err != nil { + return referenceValues, err + } + + refDb := res.Result.Map("REFERENCED_TABLE_SCHEMA") + refTb := res.Result.Map("REFERENCED_TABLE_NAME") + schema := res.Result.Map("TABLE_SCHEMA") + tb := res.Result.Map("TABLE_NAME") + cName := res.Result.Map("CONSTRAINT_NAME") + + // 获取值 + for _, row := range res.Rows { + value := ReferenceValue{ + RefDBName: row.Str(refDb), + RefTable: row.Str(refTb), + DBName: row.Str(schema), + Table: row.Str(tb), + ConstraintName: row.Str(cName), + } + referenceValues = append(referenceValues, value) + } + + return referenceValues, err + +} diff --git a/vendor/github.com/XiaoMi/soar/database/show_test.go b/vendor/github.com/XiaoMi/soar/database/show_test.go new file mode 100644 index 0000000000000000000000000000000000000000..66f98d4714b43f5dae50f0611891569105c1ebfe --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/show_test.go @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "fmt" + "testing" + + "github.com/kr/pretty" + "vitess.io/vitess/go/vt/sqlparser" +) + +func TestShowTableStatus(t *testing.T) { + connTest.Database = "information_schema" + ts, err := connTest.ShowTableStatus("TABLES") + if err != nil { + t.Error("ShowTableStatus Error: ", err) + } + pretty.Println(ts) +} + +func TestShowTables(t *testing.T) { + connTest.Database = "information_schema" + ts, err := connTest.ShowTables() + if err != nil { + t.Error("ShowTableStatus Error: ", err) + } + pretty.Println(ts) +} + +func TestShowCreateTable(t *testing.T) { + connTest.Database = "information_schema" + ts, err := connTest.ShowCreateTable("TABLES") + if err != nil { + t.Error("ShowCreateTable Error: ", err) + } + fmt.Println(ts) + stmt, err := sqlparser.Parse(ts) + pretty.Println(stmt, err) +} + +func TestShowIndex(t *testing.T) { + connTest.Database = "information_schema" + ti, err := connTest.ShowIndex("TABLES") + if err != nil { + t.Error("ShowIndex Error: ", err) + } + pretty.Println(ti.FindIndex(IndexKeyName, "idx_store_id_film_id")) +} + +func TestShowColumns(t *testing.T) { + connTest.Database = "information_schema" + ti, err := connTest.ShowColumns("TABLES") + if err != nil { + t.Error("ShowColumns Error: ", err) + } + pretty.Println(ti) +} + +func TestFindColumn(t *testing.T) { + ti, err := connTest.FindColumn("id", "") + if err != nil { + t.Error("FindColumn Error: ", err) + } + pretty.Println(ti) +} + +func TestShowReference(t *testing.T) { + rv, err := connTest.ShowReference("test2", "homeImg") + if err != nil { + t.Error("ShowReference Error: ", err) + } + pretty.Println(rv) +} + +func TestIsFKey(t *testing.T) { + if !connTest.IsFKey("sakila", "film", "language_id") { + t.Error("want True. got false") + } +} diff --git a/vendor/github.com/XiaoMi/soar/database/trace.go b/vendor/github.com/XiaoMi/soar/database/trace.go new file mode 100644 index 0000000000000000000000000000000000000000..0ba611aba68fc5f62bc41aa2518f7011b763da27 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/trace.go @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "errors" + "fmt" + "io" + "regexp" + "strings" + "time" + + "github.com/XiaoMi/soar/common" + + "vitess.io/vitess/go/vt/sqlparser" +) + +// Trace 用于存放 Select * From Information_Schema.Optimizer_Trace;输出的结果 +type Trace struct { + Rows []TraceRow +} + +// TraceRow 中含有trace的基本信息 +type TraceRow struct { + Query string + Trace string + MissingBytesBeyondMaxMemSize int + InsufficientPrivileges int +} + +// Trace 执行SQL,并对其Trace +func (db *Connector) Trace(sql string, params ...interface{}) (*QueryResult, error) { + common.Log.Debug("Trace SQL: %s", sql) + if common.Config.TestDSN.Version < 50600 { + return nil, errors.New("version < 5.6, not support trace") + } + + // 过滤不需要 Trace 的 SQL + switch sqlparser.Preview(sql) { + case sqlparser.StmtSelect, sqlparser.StmtUpdate, sqlparser.StmtDelete: + sql = "explain " + sql + case sqlparser.EXPLAIN: + default: + return nil, errors.New("no need trace") + } + + // 测试环境如果检查是关闭的,则SQL不会被执行 + if common.Config.TestDSN.Disable { + return nil, errors.New("Dsn Disable") + } + + // 数据库安全性检查:如果 Connector 的 IP 端口与 TEST 环境不一致,则启用SQL白名单 + // 不在白名单中的SQL不允许执行 + // 执行环境与test环境不相同 + if db.Addr != common.Config.TestDSN.Addr && db.dangerousQuery(sql) { + return nil, fmt.Errorf("query Execution Deny: Execute SQL with DSN(%s/%s) '%s'", + db.Addr, db.Database, fmt.Sprintf(sql, params...)) + } + + common.Log.Debug("Execute SQL with DSN(%s/%s) : %s", db.Addr, db.Database, sql) + conn := db.NewConnection() + + // 设置SQL连接超时时间 + conn.SetTimeout(time.Duration(common.Config.ConnTimeOut) * time.Second) + defer conn.Close() + err := conn.Connect() + if err != nil { + return nil, err + } + + // 添加SQL执行超时限制 + ch := make(chan QueryResult, 1) + go func() { + // 开启Trace + common.Log.Debug("SET SESSION OPTIMIZER_TRACE='enabled=on'") + _, _, err = conn.Query("SET SESSION OPTIMIZER_TRACE='enabled=on'") + common.LogIfError(err, "") + + // 执行SQL,抛弃返回结果 + result, err := conn.Start(sql, params...) + if err != nil { + ch <- QueryResult{ + Error: err, + } + return + } + row := result.MakeRow() + for { + err = result.ScanRow(row) + if err == io.EOF { + break + } + } + + // 返回Trace结果 + res := QueryResult{} + res.Rows, res.Result, res.Error = conn.Query("SELECT * FROM information_schema.OPTIMIZER_TRACE") + + // 关闭Trace + common.Log.Debug("SET SESSION OPTIMIZER_TRACE='enabled=off'") + _, _, err = conn.Query("SET SESSION OPTIMIZER_TRACE='enabled=off'") + if err != nil { + fmt.Println(err.Error()) + } + ch <- res + }() + + select { + case res := <-ch: + return &res, res.Error + case <-time.After(time.Duration(common.Config.QueryTimeOut) * time.Second): + return nil, errors.New("query execution timeout") + } +} + +// getTrace 获取trace信息 +func getTrace(res *QueryResult) Trace { + var rows []TraceRow + for _, row := range res.Rows { + rows = append(rows, TraceRow{ + Query: row.Str(0), + Trace: row.Str(1), + MissingBytesBeyondMaxMemSize: row.Int(2), + InsufficientPrivileges: row.Int(3), + }) + } + return Trace{Rows: rows} +} + +// FormatTrace 格式化输出Trace信息 +func FormatTrace(res *QueryResult) string { + explainReg := regexp.MustCompile(`(?i)^explain\s+`) + trace := getTrace(res) + str := []string{""} + for _, row := range trace.Rows { + str = append(str, "```sql") + sql := explainReg.ReplaceAllString(row.Query, "") + str = append(str, sql) + str = append(str, "```\n") + str = append(str, "```json") + str = append(str, row.Trace) + str = append(str, "```\n") + } + return strings.Join(str, "\n") +} diff --git a/vendor/github.com/XiaoMi/soar/database/trace_test.go b/vendor/github.com/XiaoMi/soar/database/trace_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8dea2d7ffa8270facee7c4003566625e5ac04221 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/database/trace_test.go @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 database + +import ( + "flag" + "testing" + + "github.com/XiaoMi/soar/common" + + "github.com/kr/pretty" +) + +var update = flag.Bool("update", false, "update .golden files") + +func TestTrace(t *testing.T) { + common.Config.QueryTimeOut = 1 + res, err := connTest.Trace("select 1") + if err == nil { + common.GoldenDiff(func() { + pretty.Println(res) + }, t.Name(), update) + } else { + t.Error(err) + } +} + +func TestFormatTrace(t *testing.T) { + res, err := connTest.Trace("select 1") + if err == nil { + pretty.Println(FormatTrace(res)) + } else { + t.Error(err) + } +} + +func TestGetTrace(t *testing.T) { + res, err := connTest.Trace("select 1") + if err == nil { + pretty.Println(getTrace(res)) + } else { + t.Error(err) + } +} diff --git a/vendor/github.com/XiaoMi/soar/deps.sh b/vendor/github.com/XiaoMi/soar/deps.sh new file mode 100755 index 0000000000000000000000000000000000000000..afeb3e08d6aff7e50d5f05428b93d0852015a828 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/deps.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +NEEDED_COMMANDS="mysql docker git go govendor retool" + +for cmd in ${NEEDED_COMMANDS} ; do + if ! command -v "${cmd}" &> /dev/null ; then + echo -e "\033[91m${cmd} missing\033[0m" + exit 1 + else + echo "${cmd} found" + fi +done diff --git a/vendor/github.com/XiaoMi/soar/doc.go b/vendor/github.com/XiaoMi/soar/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..3c347f0f8f0e6808c0c4ebdf21f916aa55d0967b --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/doc.go @@ -0,0 +1,18 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 soar is a command-line tool for SQL optimizing and rewriting. +package soar diff --git a/vendor/github.com/XiaoMi/soar/env/doc.go b/vendor/github.com/XiaoMi/soar/env/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..e0b20d0f5199e590f887c81caabab69df0ca9f77 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/env/doc.go @@ -0,0 +1,18 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 env contain virtual database build, rehash, cleanup. +package env diff --git a/vendor/github.com/XiaoMi/soar/env/env.go b/vendor/github.com/XiaoMi/soar/env/env.go new file mode 100644 index 0000000000000000000000000000000000000000..9b3f6ea0910b441df8a4b121d1a3ba7f0ed8e2b2 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/env/env.go @@ -0,0 +1,546 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 env + +import ( + "fmt" + "strings" + "time" + + "github.com/XiaoMi/soar/ast" + "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/database" + + "github.com/dchest/uniuri" + "vitess.io/vitess/go/vt/sqlparser" +) + +// VirtualEnv SQL优化评审 测试环境 +// DB使用的信息从配置文件中获取 +type VirtualEnv struct { + *database.Connector + + // 保存DB测试环境映射关系,防止vEnv环境冲突。 + DBRef map[string]string // db -> optimizer_xxx + hash2Db map[string]string // optimizer_xxx -> db + // 保存Table创建关系,防止重复创建表 + TableMap map[string]map[string]string + // 错误 + Error error +} + +// NewVirtualEnv 初始化一个新的测试环境 +func NewVirtualEnv(vEnv *database.Connector) *VirtualEnv { + return &VirtualEnv{ + Connector: vEnv, + DBRef: make(map[string]string), + hash2Db: make(map[string]string), + TableMap: make(map[string]map[string]string), + } +} + +// BuildEnv 测试环境初始化&连接线上环境检查 +// @output *VirtualEnv 测试环境 +// @output *database.Connector 线上环境连接句柄 +func BuildEnv() (*VirtualEnv, *database.Connector) { + // 生成测试环境 + vEnv := NewVirtualEnv(&database.Connector{ + Addr: common.Config.TestDSN.Addr, + User: common.Config.TestDSN.User, + Pass: common.Config.TestDSN.Password, + Database: common.Config.TestDSN.Schema, + Charset: common.Config.TestDSN.Charset, + }) + + // 检查测试环境可用性,并记录数据库版本 + vEnvVersion, err := vEnv.Version() + common.Config.TestDSN.Version = vEnvVersion + if err != nil { + common.Log.Warn("BuildEnv TestDSN: %s:********@%s/%s not available , Error: %s", + vEnv.User, vEnv.Addr, vEnv.Database, err.Error()) + common.Config.TestDSN.Disable = true + } + + // 连接线上环境 + // 如果未配置线上环境线测试环境配置为线上环境 + if common.Config.OnlineDSN.Addr == "" { + common.Log.Warn("BuildEnv AllowOnlineAsTest: OnlineDSN not config, use TestDSN: %s:********@%s/%s as OnlineDSN", + vEnv.User, vEnv.Addr, vEnv.Database) + common.Config.OnlineDSN = common.Config.TestDSN + } + conn := &database.Connector{ + Addr: common.Config.OnlineDSN.Addr, + User: common.Config.OnlineDSN.User, + Pass: common.Config.OnlineDSN.Password, + Database: common.Config.OnlineDSN.Schema, + Charset: common.Config.OnlineDSN.Charset, + } + + // 检查线上环境可用性版本 + rEnvVersion, err := vEnv.Version() + common.Config.OnlineDSN.Version = rEnvVersion + if err != nil { + common.Log.Warn("BuildEnv OnlineDSN: %s:********@%s/%s not available , Error: %s", + vEnv.User, vEnv.Addr, vEnv.Database, err.Error()) + common.Config.TestDSN.Disable = true + } + + // 检查是否允许Online和Test一致,防止误操作 + if common.FormatDSN(common.Config.OnlineDSN) == common.FormatDSN(common.Config.TestDSN) && + !common.Config.AllowOnlineAsTest { + common.Log.Warn("BuildEnv AllowOnlineAsTest: %s:********@%s/%s OnlineDSN can't config as TestDSN", + vEnv.User, vEnv.Addr, vEnv.Database) + common.Config.TestDSN.Disable = true + common.Config.OnlineDSN.Disable = true + } + + // 判断测试环境与remote环境版本是否一致 + if vEnvVersion < rEnvVersion { + common.Log.Warning("TestDSN MySQL version older than OnlineDSN, TestDSN will not be used", vEnvVersion, rEnvVersion) + common.Config.TestDSN.Disable = true + } + + return vEnv, conn +} + +// RealDB 从测试环境中获取通过hash后的DB +func (ve VirtualEnv) RealDB(hash string) string { + if _, ok := ve.hash2Db[hash]; ok { + return ve.hash2Db[hash] + } + return hash +} + +// DBHash 从测试环境中根据DB找到对应的hash值 +func (ve VirtualEnv) DBHash(db string) string { + if _, ok := ve.DBRef[db]; ok { + return ve.DBRef[db] + } + return db +} + +// CleanUp 环境清理 +func (ve VirtualEnv) CleanUp() bool { + if !common.Config.TestDSN.Disable && common.Config.DropTestTemporary { + common.Log.Debug("CleanUp ...") + for db := range ve.hash2Db { + ve.Database = db + _, err := ve.Query("drop database %s", db) + if err != nil { + common.Log.Error("CleanUp failed Error: %s", err) + return false + } + } + common.Log.Debug("CleanUp, done") + } + return true +} + +// CleanupTestDatabase 清除一小时前的环境 +func (ve *VirtualEnv) CleanupTestDatabase() { + common.Log.Debug("CleanupTestDatabase ...") + dbs, err := ve.Query("show databases like 'optimizer%%'") + if err != nil { + common.Log.Error("CleanupTestDatabase failed Error:%s", err.Error()) + return + } + + // TODO: 1 hour should be config-able + minHour := 1 + for _, row := range dbs.Rows { + testDatabase := row.Str(0) + // test temporary database format `optimizer_YYMMDDHHmmss_randomString(16)` + if len(testDatabase) != 39 { + common.Log.Debug("CleanupTestDatabase by pass %s", testDatabase) + continue + } + s := strings.Split(testDatabase, "_") + pastTime, err := time.Parse("060102150405", s[1]) + if err != nil { + common.Log.Error("CleanupTestDatabase compute pastTime Error: %s", err.Error()) + continue + } + + subHour := time.Since(pastTime).Hours() + if subHour > float64(minHour) { + if _, err := ve.Query("drop database %s", testDatabase); err != nil { + common.Log.Error("CleanupTestDatabase failed Error: %s", err.Error()) + continue + } + common.Log.Debug("CleanupTestDatabase drop database %s success", testDatabase) + continue + } + common.Log.Debug("CleanupTestDatabase by pass database %s, %.2f less than %d hours", testDatabase, subHour, minHour) + } + + common.Log.Debug("CleanupTestDatabase done") +} + +// BuildVirtualEnv rEnv为SQL源环境,DB使用的信息从接口获取 +// 注意:如果是USE,DDL等语句,执行完第一条就会返回,后面的SQL不会执行 +func (ve *VirtualEnv) BuildVirtualEnv(rEnv *database.Connector, SQLs ...string) bool { + var stmt sqlparser.Statement + var err error + + // 置空错误信息 + ve.Error = nil + // 检测是否已经创建初始数据库,如果未创建则创建一个名称hash过的映射数据库 + err = ve.createDatabase(*rEnv, rEnv.Database) + common.LogIfWarn(err, "") + + // 测试环境检测 + if common.Config.TestDSN.Disable { + common.Log.Info("BuildVirtualEnv TestDSN not config") + return true + } + + // 判断rEnv中是否指定了DB + if rEnv.Database == "" { + common.Log.Error("BuildVirtualEnv no database specified, TestDSN init failed") + return false + } + + // 库表提取 + meta := make(map[string]*common.DB) + for _, sql := range SQLs { + + common.Log.Debug("BuildVirtualEnv Database&Table Mapping, SQL: %s", sql) + + stmt, err = sqlparser.Parse(sql) + if err != nil { + common.Log.Error("BuildVirtualEnv Error : %v", err) + return false + } + + // 语句类型判断 + switch stmt := stmt.(type) { + case *sqlparser.Use: + // 如果是use语句,则更改基础环配置 + if _, ok := meta[stmt.DBName.String()]; !ok { + // 如果USE了一个线上环境不存在的数据库,将创建该数据库,字符集默认utf8mb4 + meta[stmt.DBName.String()] = common.NewDB(stmt.DBName.String()) + rEnv.Database = stmt.DBName.String() + + // use DB 后检查 DB是否已经创建,如果没有创建则创建DB + err = ve.createDatabase(*rEnv, rEnv.Database) + common.LogIfWarn(err, "") + } + return true + case *sqlparser.DDL: + // 如果是DDL,则先获取DDL对应的表结构,然后直接在测试环境接执行SQL + // 为不影响其他SQL操作,复制一个Connector对象,将数据库切换到对应的DB上直接执行 + tmpDB := *ve.Connector + tmpDB.Database = ve.DBRef[rEnv.Database] + + // 为了支持并发,需要将DB进行映射,但db.table这种形式无法保证DB的映射是正确的 + // TODO:暂不支持 create db.tableName (id int) 形式的建表语句 + if stmt.Table.Qualifier.String() != "" { + common.Log.Error("BuildVirtualEnv DDL Not support '.'") + return false + } + + for _, tb := range stmt.FromTables { + if tb.Qualifier.String() != "" { + common.Log.Error("BuildVirtualEnv DDL Not support '.'") + return false + } + } + + for _, tb := range stmt.ToTables { + if tb.Qualifier.String() != "" { + common.Log.Error("BuildVirtualEnv DDL Not support '.'") + return false + } + } + + // 拉取表结构 + table := stmt.Table.Name.String() + if table != "" { + err = ve.createTable(*rEnv, rEnv.Database, table) + // 这里如果报错可能有两种可能: + // 1. SQL 是 Create 语句,线上环境并没有相关的库表结构 + // 2. 在测试环境中执行 SQL 报错 + // 如果是因为 Create 语句报错,后续会在测试环境中直接执行 create 语句,不会对程序有负面影响 + // 如果是因为执行 SQL 报错,那么其他地方执行 SQL 的时候也一定会报错 + // 所以这里不需要 `return false`,可以继续执行 + if err != nil { + common.Log.Error("BuildVirtualEnv Error : %v", err) + } + } + + _, err = tmpDB.Query(sql) + if err != nil { + switch stmt.Action { + case "create", "alter": + // 如果是创建或者修改语句,且报错信息为如重复建表、重复索引等信息,将错误反馈到上一次层输出建议 + ve.Error = err + default: + common.Log.Error("BuildVirtualEnv DDL Execute Error : %v", err) + } + } + return true + } + + meta := ast.GetMeta(stmt, nil) + + // 由于DB环境可能是变的,所以需要每一次都单独的提取库表结构,整体随着rEnv的变动而发生变化 + for db, table := range meta { + if db == "" { + db = rEnv.Database + } + tmpEnv := *rEnv + tmpEnv.Database = db + + // 创建数据库环境 + for _, tb := range table.Table { + if tb.TableName == "" { + continue + } + + // 视图检查 + common.Log.Debug("BuildVirtualEnv Checking view -- %s.%s", tmpEnv.Database, tb.TableName) + tbStatus, err := tmpEnv.ShowTableStatus(tb.TableName) + if err != nil { + common.Log.Error("BuildVirtualEnv ShowTableStatus Error : %v", err) + return false + } + + // 如果是视图,解析语句 + if len(tbStatus.Rows) > 0 && tbStatus.Rows[0].Comment == "VIEW" { + tmpEnv.Database = db + var viewDDL string + viewDDL, err = tmpEnv.ShowCreateTable(tb.TableName) + if err != nil { + common.Log.Error("BuildVirtualEnv create view failed: %v", err) + return false + } + + startIdx := strings.Index(viewDDL, "AS") + viewDDL = viewDDL[startIdx+2:] + if !ve.BuildVirtualEnv(&tmpEnv, viewDDL) { + return false + } + } + + err = ve.createTable(tmpEnv, db, tb.TableName) + if err != nil { + common.Log.Error("BuildVirtualEnv Error : %v", err) + return false + } + } + } + } + return true +} + +func (ve VirtualEnv) createDatabase(rEnv database.Connector, dbName string) error { + // 生成映射关系 + if _, ok := ve.DBRef[dbName]; ok { + common.Log.Debug("createDatabase, Database `%s` created", dbName) + return nil + } + + // optimizer_YYMMDDHHmmss_xxxx + dbHash := fmt.Sprintf("optimizer_%s_%s", time.Now().Format("060102150405"), uniuri.New()) + common.Log.Debug("createDatabase, mapping `%s` :`%s`-->`%s`", dbName, dbName, dbHash) + ddl, err := rEnv.ShowCreateDatabase(dbName) + if err != nil { + common.Log.Warning("createDatabase, rEnv.ShowCreateDatabase Error : %v", err) + ddl = fmt.Sprintf("create database `%s` character set utf8mb4", dbName) + } + + ddl = strings.Replace(ddl, dbName, dbHash, -1) + _, err = ve.Query(ddl) + if err != nil { + common.Log.Warning("createDatabase, Error : %v", err) + return err + } + + // 创建成功,添加映射记录 + ve.DBRef[dbName] = dbHash + ve.hash2Db[dbHash] = dbName + return nil +} + +/* + @input: + database.Connector 为一个线上环境数据库连接句柄的复制,因为在处理SQL时需要对上下文进行关联处理, + 所以存在修改DB连接参数(主要是数据库名称变更)的可能性,为了不影响整体上下文的环境,所以需要一个镜像句柄来做当前环境的操作。 + + dbName, tbName: 需要在环境中操作的库表名称, + + @output: + return 执行过程中的错误 + + NOTE: + 该函数会将线上环境中使用到的库表结构复制到测试环境中,为后续操作提供基础环境。 + 传入的库表名称均来自于对AST的解析,库表名称的获取遵循以下原则: + 如果未在SQL中指定数据库名称,则数据库一定是配置文件(或命令行参数传入DSN)中指定的数据库 + 如果一个SQL中存在多个数据库,则只能有一个数据库是没有在SQL中被显示指定的(即DSN中指定的数据库) + TODO: + 在一些可能的情况下,由于数据库配置的不一致(如SQL_MODE不同)导致remote环境的库表无法正确的在测试环境进行同步, + soar 能够做出判断并进行 session 级别的修改,但是这一阶段可用性保证应该是由用户提供两个完全相同(或测试环境兼容线上环境) + 的数据库环境来实现的。 +*/ +func (ve VirtualEnv) createTable(rEnv database.Connector, dbName, tbName string) error { + + if dbName == "" { + dbName = rEnv.Database + } + // 如果 dbName 不为空,说明指定了DB,临时修改rEnv中DB参数,来确保执行正确性 + rEnv.Database = dbName + + if ve.TableMap[dbName] == nil { + ve.TableMap[dbName] = make(map[string]string) + } + + if strings.ToLower(tbName) == "dual" { + common.Log.Debug("createTable, %s no need create", tbName) + return nil + } + + if ve.TableMap[dbName][tbName] != "" { + common.Log.Debug("createTable, `%s`.`%s` created", dbName, tbName) + return nil + } + + common.Log.Debug("createTable, Database: %s, Table: %s", dbName, tbName) + + // TODO:查看是否有外键关联(done),对外键的支持 (未解决循环依赖的问题) + + // 判断数据库是否已经创建 + if ve.DBRef[dbName] == "" { + // 若没创建,则创建数据库 + err := ve.createDatabase(rEnv, dbName) + if err != nil { + return err + } + } + + // 记录Table创建信息 + ve.TableMap[dbName][tbName] = tbName + + // 生成建表语句 + common.Log.Debug("createTable DSN(%s/%s): generate ddl", rEnv.Addr, rEnv.Database) + + ddl, err := rEnv.ShowCreateTable(tbName) + if err != nil { + // 有可能是用户新建表,因此线上环境查不到 + common.Log.Error("createTable, %s DDL Error : %v", tbName, err) + return err + } + + // 改变数据环境 + ve.Database = ve.DBRef[dbName] + _, err = ve.Query(ddl) + if err != nil { + // 有可能是用户新建表,因此线上环境查不到 + common.Log.Error("createTable, %s Error : %v", tbName, err) + return err + } + + // 泵取数据 + if common.Config.Sampling { + common.Log.Debug("createTable, Start Sampling data from %s.%s to %s.%s ...", dbName, tbName, ve.DBRef[dbName], tbName) + err := ve.SamplingData(rEnv, tbName) + if err != nil { + common.Log.Error(" (ve VirtualEnv) createTable SamplingData Error: %v", err) + return err + } + } + return nil +} + +// GenTableColumns 为Rewrite提供的结构体初始化 +func (ve *VirtualEnv) GenTableColumns(meta common.Meta) common.TableColumns { + tableColumns := make(common.TableColumns) + for dbName, db := range meta { + for _, tb := range db.Table { + // 防止传入非预期值 + if tb == nil { + break + } + td, err := ve.Connector.ShowColumns(tb.TableName) + if err != nil { + common.Log.Warn("GenTableColumns, ShowColumns Error: " + err.Error()) + break + } + + // tableColumns 初始化 + if dbName == "" { + dbName = ve.RealDB(ve.Connector.Database) + } + + if _, ok := tableColumns[dbName]; !ok { + tableColumns[dbName] = make(map[string][]*common.Column) + } + + if _, ok := tableColumns[dbName][tb.TableName]; !ok { + tableColumns[dbName][tb.TableName] = make([]*common.Column, 0) + } + + if len(tb.Column) == 0 { + // tb.column为空说明SQL里这个表是用的*来查询 + if err != nil { + common.Log.Error("ast.Rewrite ShowColumns, Error: %v", err) + break + } + + for _, colInfo := range td.DescValues { + tableColumns[dbName][tb.TableName] = append(tableColumns[dbName][tb.TableName], &common.Column{ + Name: colInfo.Field, + DB: dbName, + Table: tb.TableName, + DataType: colInfo.Type, + Character: colInfo.Collation, + Key: colInfo.Key, + Default: colInfo.Default, + Extra: colInfo.Extra, + Comment: colInfo.Comment, + Privileges: colInfo.Privileges, + Null: colInfo.Null, + }) + } + } else { + // tb.column如果不为空则需要把使用到的列填写进去 + var columns []*common.Column + for _, col := range tb.Column { + for _, colInfo := range td.DescValues { + if col.Name == colInfo.Field { + // 根据获取的信息将列的信息补全 + col.DB = dbName + col.Table = tb.TableName + col.DataType = colInfo.Type + col.Character = colInfo.Collation + col.Key = colInfo.Key + col.Default = colInfo.Default + col.Extra = colInfo.Extra + col.Comment = colInfo.Comment + col.Privileges = colInfo.Privileges + col.Null = colInfo.Null + + columns = append(columns, col) + break + } + } + } + tableColumns[dbName][tb.TableName] = columns + } + } + } + return tableColumns +} diff --git a/vendor/github.com/XiaoMi/soar/env/env_test.go b/vendor/github.com/XiaoMi/soar/env/env_test.go new file mode 100644 index 0000000000000000000000000000000000000000..887c347c38946ab8d874e28d04b6d9fe6ea610d6 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/env/env_test.go @@ -0,0 +1,211 @@ +/* + * Copyright 2018 Xiaomi, Inc. + * + * 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 env + +import ( + "flag" + "testing" + + "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/database" + "github.com/kr/pretty" + "github.com/ziutek/mymysql/mysql" +) + +var connTest *database.Connector +var update = flag.Bool("update", false, "update .golden files") + +func init() { + common.BaseDir = common.DevPath + err := common.ParseConfig("") + common.LogIfError(err, "init ParseConfig") + connTest = &database.Connector{ + Addr: common.Config.TestDSN.Addr, + User: common.Config.TestDSN.User, + Pass: common.Config.TestDSN.Password, + Database: common.Config.TestDSN.Schema, + Charset: common.Config.TestDSN.Charset, + } +} + +func TestNewVirtualEnv(t *testing.T) { + testSQL := []string{ + "create table t(id int,c1 varchar(20),PRIMARY KEY (id));", + "alter table t add index `idx_c1`(c1);", + "alter table t add index `idx_c1`(c1);", + "select * from city where country_id = 44;", + "select * from address where address2 is not null;", + "select * from address where address2 is null;", + "select * from address where address2 >= 44;", + "select * from city where country_id between 44 and 107;", + "select * from city where city like 'Ad%';", + "select * from city where city = 'Aden' and country_id = 107;", + "select * from city where country_id > 31 and city = 'Aden';", + "select * from address where address_id > 8 and city_id < 400 and district = 'Nantou';", + "select * from address where address_id > 8 and city_id < 400;", + "select * from actor where last_update='2006-02-15 04:34:33' and last_name='CHASE' group by first_name;", + "select * from address where last_update >='2014-09-25 22:33:47' group by district;", + "select * from address group by address,district;", + "select * from address where last_update='2014-09-25 22:30:27' group by district,(address_id+city_id);", + "select * from customer where active=1 order by last_name limit 10;", + "select * from customer order by last_name limit 10;", + "select * from customer where address_id > 224 order by address_id limit 10;", + "select * from customer where address_id < 224 order by address_id limit 10;", + "select * from customer where active=1 order by last_name;", + "select * from customer where address_id > 224 order by address_id;", + "select * from customer where address_id in (224,510) order by last_name;", + "select city from city where country_id = 44;", + "select city,city_id from city where country_id = 44 and last_update='2006-02-15 04:45:25';", + "select city from city where country_id > 44 and last_update > '2006-02-15 04:45:25';", + "select * from city where country_id=1 and city='Kabul' order by last_update;", + "select * from city where country_id>1 and city='Kabul' order by last_update;", + "select * from city where city_id>251 order by last_update; ", + "select * from city i inner join country o on i.country_id=o.country_id;", + "select * from city i left join country o on i.city_id=o.country_id;", + "select * from city i right join country o on i.city_id=o.country_id;", + "select * from city i left join country o on i.city_id=o.country_id where o.country_id is null;", + "select * from city i right join country o on i.city_id=o.country_id where i.city_id is null;", + "select * from city i left join country o on i.city_id=o.country_id union select * from city i right join country o on i.city_id=o.country_id;", + "select * from city i left join country o on i.city_id=o.country_id where o.country_id is null union select * from city i right join country o on i.city_id=o.country_id where i.city_id is null;", + "select first_name,last_name,email from customer natural left join address;", + "select first_name,last_name,email from customer natural left join address;", + "select first_name,last_name,email from customer natural right join address;", + "select first_name,last_name,email from customer STRAIGHT_JOIN address on customer.address_id=address.address_id;", + "select ID,name from (select address from customer_list where SID=1 order by phone limit 50,10) a join customer_list l on (a.address=l.address) join city c on (c.city=l.city) order by phone desc;", + } + + rEnv := connTest + + env := NewVirtualEnv(connTest) + defer env.CleanUp() + common.GoldenDiff(func() { + for _, sql := range testSQL { + env.BuildVirtualEnv(rEnv, sql) + switch err := env.Error.(type) { + case nil: + pretty.Println(sql, "OK") + case error: + // unexpected EOF + // 测试环境无法访问,或者被Disable的时候会进入这个分支 + pretty.Println(sql, err) + case *mysql.Error: + if err.Code != 1061 { + t.Error(err) + } + default: + t.Error(err) + } + } + }, t.Name(), update) +} + +func TestCleanupTestDatabase(t *testing.T) { + vEnv, _ := BuildEnv() + if common.Config.TestDSN.Disable { + common.Log.Warn("common.Config.TestDSN.Disable=true, by pass TestCleanupTestDatabase") + return + } + vEnv.Query("drop database if exists optimizer_060102150405_xxxxxxxxxxxxxxxx") + _, err := vEnv.Query("create database optimizer_060102150405_xxxxxxxxxxxxxxxx") + if err != nil { + t.Error(err) + } + vEnv.CleanupTestDatabase() + _, err = vEnv.Query("show create database optimizer_060102150405_xxxxxxxxxxxxxxxx") + if err == nil { + t.Error("optimizer_060102150405_xxxxxxxxxxxxxxxx exist, should be dropped") + } + + vEnv.Query("drop database if exists optimizer_060102150405") + _, err = vEnv.Query("create database optimizer_060102150405") + if err != nil { + t.Error(err) + } + vEnv.CleanupTestDatabase() + _, err = vEnv.Query("drop database optimizer_060102150405") + if err != nil { + t.Error("optimizer_060102150405 not exist, should not be dropped") + } +} + +func TestGenTableColumns(t *testing.T) { + vEnv, rEnv := BuildEnv() + defer vEnv.CleanUp() + + pretty.Println(common.Config.TestDSN.Disable) + if common.Config.TestDSN.Disable { + common.Log.Warn("common.Config.TestDSN.Disable=true, by pass TestGenTableColumns") + return + } + + // 只能对sakila数据库进行测试 + if rEnv.Database == "sakila" { + testSQL := []string{ + "select * from city where country_id = 44;", + "select country_id from city where country_id = 44;", + "select country_id from city where country_id > 44;", + } + + metaList := []common.Meta{ + { + "": &common.DB{ + Table: map[string]*common.Table{ + "city": common.NewTable("city"), + }, + }, + }, + { + "sakila": &common.DB{ + Table: map[string]*common.Table{ + "city": common.NewTable("city"), + }, + }, + }, + { + "sakila": &common.DB{ + Table: map[string]*common.Table{ + "city": { + TableName: "city", + Column: map[string]*common.Column{ + "country_id": { + Name: "country_id", + }, + }, + }, + }, + }, + }, + } + + for i, sql := range testSQL { + vEnv.BuildVirtualEnv(rEnv, sql) + tFlag := false + columns := vEnv.GenTableColumns(metaList[i]) + if _, ok := columns["sakila"]; ok { + if _, okk := columns["sakila"]["city"]; okk { + if length := len(columns["sakila"]["city"]); length >= 1 { + tFlag = true + } + } + } + + if !tFlag { + t.Errorf("columns: \n%s", pretty.Sprint(columns)) + } + } + } +} diff --git a/vendor/github.com/XiaoMi/soar/genver.sh b/vendor/github.com/XiaoMi/soar/genver.sh new file mode 100755 index 0000000000000000000000000000000000000000..52550257e4de141d6e15d5aa4bd0714fc3f52495 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/genver.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +## Generate Repository Version +version="$(git log --date=iso --pretty=format:"%cd" -1) $(git describe --tags --always)" +if [ "X${version}" == "X" ]; then + version="not a git repo" +fi + +git_dirty=$(git diff --no-ext-diff 2>/dev/null | wc -l) + +compile="$(date +"%F %T %z") by $(go version)" + +branch=$(git rev-parse --abbrev-ref HEAD) + +dev_path=$( + cd "$(dirname "$0")" || exit + pwd +) + +cat <common/version.go +package common + +// -version输出信息 +const ( + Version = "${version}" + Compile = "${compile}" + Branch = "${branch}" + GitDirty= ${git_dirty} + DevPath = "${dev_path}" +) +EOF diff --git a/vendor/github.com/XiaoMi/soar/retool-install.sh b/vendor/github.com/XiaoMi/soar/retool-install.sh new file mode 100755 index 0000000000000000000000000000000000000000..877ef91ef5598ecdcb9d3f84f94b5c9041888648 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/retool-install.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +# This script generates tools.json +# It helps record what releases/branches are being used +which retool >/dev/null || go get -u github.com/twitchtv/retool + +# This tool can run other checks in a standardized way +retool add gopkg.in/alecthomas/gometalinter.v2 v2.0.11 + +# check spelling +# misspell works with gometalinter +retool add github.com/client9/misspell/cmd/misspell v0.3.4 +# goword adds additional capability to check comments +retool add github.com/chzchzchz/goword a9744cb52b033fe5c269df48eeef2c954526cd79 + +# checks correctness +retool add github.com/gordonklaus/ineffassign 7bae11eba15a3285c75e388f77eb6357a2d73ee2 +retool add honnef.co/go/tools/cmd/megacheck master +retool add github.com/dnephin/govet 4a96d43e39d340b63daa8bc5576985aa599885f6 + +# slow checks +retool add github.com/kisielk/errcheck v1.1.0 +retool add github.com/securego/gosec/cmd/gosec 1.0.0 + +# linter +retool add github.com/mgechev/revive 7773f47324c2bf1c8f7a5500aff2b6c01d3ed73b +retool add github.com/golangci/golangci-lint/cmd/golangci-lint v1.10 diff --git a/vendor/github.com/XiaoMi/soar/revive.toml b/vendor/github.com/XiaoMi/soar/revive.toml new file mode 100644 index 0000000000000000000000000000000000000000..ebe13ddc3b0ac6a39c5373b010dc8920ad25a0b7 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/revive.toml @@ -0,0 +1,51 @@ +ignoreGeneratedHeader = false +severity = "error" +confidence = 0.8 +errorCode = 0 +warningCode = 0 + +[rule.blank-imports] +[rule.context-as-argument] +[rule.dot-imports] +[rule.error-return] +[rule.error-strings] +[rule.error-naming] +[rule.exported] +[rule.if-return] +[rule.var-naming] +[rule.package-comments] +[rule.range] +[rule.receiver-naming] +[rule.indent-error-flow] +[rule.superfluous-else] +[rule.modifies-parameter] + +# This can be checked by other tools like megacheck +#[rule.unreachable-code] + + +# Currently this makes too much noise, but should add it in +# and perhaps ignore it in a few files +#[rule.confusing-naming] +# severity = "warning" +#[rule.confusing-results] +# severity = "warning" +#[rule.unused-parameter] +# severity = "warning" +#[rule.deep-exit] +# severity = "warning" +#[rule.flag-parameter] +# severity = "warning" + + + +# Adding these will slow down the linter +# They are already provided by megacheck +#[rule.unexported-return] +#[rule.time-naming] +#[rule.errorf] + +# Adding these will slow down the linter +# Not sure if they are already provided by megacheck +#[rule.var-declaration] +#[rule.context-keys-type] diff --git a/vendor/github.com/XiaoMi/soar/tools.json b/vendor/github.com/XiaoMi/soar/tools.json new file mode 100644 index 0000000000000000000000000000000000000000..b9e5b2df1e568f30063b0d776ff636f6cd0c5341 --- /dev/null +++ b/vendor/github.com/XiaoMi/soar/tools.json @@ -0,0 +1,45 @@ +{ + "Tools": [ + { + "Repository": "gopkg.in/alecthomas/gometalinter.v2", + "Commit": "46cc1ea3778b247666c2949669a3333c532fa9c6" + }, + { + "Repository": "github.com/client9/misspell/cmd/misspell", + "Commit": "7888c6b6ce89353cd98e196bce3c3f9e4cdf31f6" + }, + { + "Repository": "github.com/chzchzchz/goword", + "Commit": "a9744cb52b033fe5c269df48eeef2c954526cd79" + }, + { + "Repository": "github.com/gordonklaus/ineffassign", + "Commit": "7bae11eba15a3285c75e388f77eb6357a2d73ee2" + }, + { + "Repository": "github.com/dnephin/govet", + "Commit": "4a96d43e39d340b63daa8bc5576985aa599885f6" + }, + { + "Repository": "github.com/securego/gosec/cmd/gosec", + "Commit": "5fb530cda357c16175f2c049577d2030de735b28" + }, + { + "Repository": "github.com/kisielk/errcheck", + "Commit": "55d8f507faff4d6eddd0c41a3e713e2567fca4e5" + }, + { + "Repository": "github.com/mgechev/revive", + "Commit": "7773f47324c2bf1c8f7a5500aff2b6c01d3ed73b" + }, + { + "Repository": "github.com/golangci/golangci-lint/cmd/golangci-lint", + "Commit": "a2b901227c37337bce9860499a413db2b464481b" + }, + { + "Repository": "honnef.co/go/tools/cmd/megacheck", + "Commit": "88497007e8588ea5b6baee991f74a1607e809487" + } + ], + "RetoolVersion": "1.3.7" +} \ No newline at end of file diff --git a/vendor/github.com/cznic/mathutil/AUTHORS b/vendor/github.com/cznic/mathutil/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..c0a01b6931ea681cc731c85de337da34078de55b --- /dev/null +++ b/vendor/github.com/cznic/mathutil/AUTHORS @@ -0,0 +1,13 @@ +# This file lists authors for copyright purposes. This file is distinct from +# the CONTRIBUTORS files. See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization +# +# The email address is not required for organizations. +# +# Please keep the list sorted. + +CZ.NIC z.s.p.o. +Edward Betts +Jan Mercl <0xjnml@gmail.com> diff --git a/vendor/github.com/cznic/mathutil/CONTRIBUTORS b/vendor/github.com/cznic/mathutil/CONTRIBUTORS new file mode 100644 index 0000000000000000000000000000000000000000..8f2b983b48171aa6d978ec9f709a257046e35e64 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/CONTRIBUTORS @@ -0,0 +1,14 @@ +# This file lists people who contributed code to this repository. The AUTHORS +# file lists the copyright holders; this file lists people. +# +# Names should be added to this file like so: +# Name +# +# Please keep the list sorted. + +Bodecker DellaMaria +Edward Betts +Faiz Abbasi +Gary Burd +Jan Mercl <0xjnml@gmail.com> +Muhammad Surya diff --git a/vendor/github.com/cznic/mathutil/Makefile b/vendor/github.com/cznic/mathutil/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a9f9e8a9702a4de892a5b8b43d88efc46ab8f39f --- /dev/null +++ b/vendor/github.com/cznic/mathutil/Makefile @@ -0,0 +1,57 @@ +# Copyright (c) 2016 The mathutil Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +.PHONY: all clean cover cpu editor internalError later mem nuke todo edit + +grep=--include=*.go --include=*.l --include=*.y --include=*.yy +ngrep='TODOOK\|parser\.go\|scanner\.go\|.*_string\.go' + +all: editor + go vet 2>&1 | grep -v $(ngrep) || true + golint 2>&1 | grep -v $(ngrep) || true + make todo + unused . || true + misspell *.go + gosimple || true + unconvert || true + maligned || true + +clean: + go clean + rm -f *~ *.test *.out + +cover: + t=$(shell tempfile) ; go test -coverprofile $$t && go tool cover -html $$t && unlink $$t + +cpu: clean + go test -run @ -bench . -cpuprofile cpu.out + go tool pprof -lines *.test cpu.out + +edit: + @ 1>/dev/null 2>/dev/null gvim -p Makefile *.go + +editor: + gofmt -l -s -w *.go + go test + go build + +internalError: + egrep -ho '"internal error.*"' *.go | sort | cat -n + +later: + @grep -n $(grep) LATER * || true + @grep -n $(grep) MAYBE * || true + +mem: clean + go test -run @ -bench . -memprofile mem.out -memprofilerate 1 -timeout 24h + go tool pprof -lines -web -alloc_space *.test mem.out + +nuke: clean + go clean -i + +todo: + @grep -nr $(grep) ^[[:space:]]*_[[:space:]]*=[[:space:]][[:alpha:]][[:alnum:]]* * | grep -v $(ngrep) || true + @grep -nr $(grep) TODO * | grep -v $(ngrep) || true + @grep -nr $(grep) BUG * | grep -v $(ngrep) || true + @grep -nr $(grep) [^[:alpha:]]println * | grep -v $(ngrep) || true diff --git a/vendor/github.com/cznic/mathutil/README b/vendor/github.com/cznic/mathutil/README new file mode 100644 index 0000000000000000000000000000000000000000..a9ee59c401c94c0f7d225898a2f9931ac0b2d7b7 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/README @@ -0,0 +1,10 @@ +This is a goinstall-able mirror of modified code already published at: +http://git.nic.cz/redmine/projects/gornd/repository + +Packages in this repository: + +Install: $ go get github.com/cznic/mathutil +Godocs: http://godoc.org/github.com/cznic/mathutil + +Install: $ go get github.com/cznic/mathutil/mersenne +Godocs: http://godoc.org/github.com/cznic/mathutil/mersenne diff --git a/vendor/github.com/cznic/mathutil/binarylog.go b/vendor/github.com/cznic/mathutil/binarylog.go new file mode 100644 index 0000000000000000000000000000000000000000..40df459ffa1f0f86a34cf7acc54d18ab74ab70fd --- /dev/null +++ b/vendor/github.com/cznic/mathutil/binarylog.go @@ -0,0 +1,88 @@ +// Copyright (c) 2016 The mathutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathutil + +import ( + "math/big" + + "github.com/remyoudompheng/bigfft" +) + +type float struct { + n *big.Int + fracBits int + maxFracBits int +} + +func newFloat(n *big.Int, fracBits, maxFracBits int) float { + f := float{n: n, fracBits: fracBits, maxFracBits: maxFracBits} + f.normalize() + return f +} + +func (f *float) normalize() { + n := f.n.BitLen() + if n == 0 { + return + } + + if n := f.fracBits - f.maxFracBits; n > 0 { + bit := f.n.Bit(n - 1) + f.n.Rsh(f.n, uint(n)) + if bit != 0 { + f.n.Add(f.n, _1) + } + f.fracBits -= n + } + + var i int + for ; f.fracBits > 0 && i <= f.fracBits && f.n.Bit(i) == 0; i++ { + f.fracBits-- + } + + if i != 0 { + f.n.Rsh(f.n, uint(i)) + } +} + +func (f *float) eq1() bool { return f.fracBits == 0 && f.n.BitLen() == 1 } +func (f *float) ge2() bool { return f.n.BitLen() > f.fracBits+1 } + +func (f *float) div2() { + f.fracBits++ + f.normalize() +} + +func (f *float) sqr() { + f.n = bigfft.Mul(f.n, f.n) + f.fracBits *= 2 + f.normalize() +} + +// BinaryLog computes the binary logarithm of n. The result consists of a +// characteristic and a mantissa having precision mantissaBits. The value of +// the binary logarithm is +// +// characteristic + mantissa*(2^-mantissaBits) +// +// BinaryLog panics for n <= 0 or mantissaBits < 0. +func BinaryLog(n *big.Int, mantissaBits int) (characteristic int, mantissa *big.Int) { + if n.Sign() <= 0 || mantissaBits < 0 { + panic("invalid argument of BinaryLog") + } + + characteristic = n.BitLen() - 1 + mantissa = big.NewInt(0) + x := newFloat(n, characteristic, mantissaBits) + for ; mantissaBits != 0 && !x.eq1(); mantissaBits-- { + x.sqr() + mantissa.Lsh(mantissa, 1) + if x.ge2() { + mantissa.SetBit(mantissa, 0, 1) + x.div2() + } + } + return characteristic, mantissa +} diff --git a/vendor/github.com/cznic/mathutil/int.go b/vendor/github.com/cznic/mathutil/int.go new file mode 100644 index 0000000000000000000000000000000000000000..8255c426b258037b36caec832c15ff56eecd0f4b --- /dev/null +++ b/vendor/github.com/cznic/mathutil/int.go @@ -0,0 +1,155 @@ +// Copyright (c) 2018 The mathutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathutil + +import ( + "fmt" + "math" + "math/big" +) + +var ( + // The maximun Int128 value. + MaxInt128 *big.Int + // The minimun Int128 value. + MinInt128 *big.Int +) + +func init() { + MaxInt128 = big.NewInt(0) + MaxInt128.SetBit(MaxInt128, 127, 1) + MaxInt128.Sub(MaxInt128, _1) + MinInt128 = big.NewInt(0) + MinInt128.Set(MaxInt128) + MinInt128.Add(MinInt128, _1) + MinInt128.Neg(MinInt128) +} + +// Int128 is an 128 bit integer. +type Int128 struct { + Lo int64 // Bits 63..0. + Hi int64 // Bits 127..64. +} + +// Add returns the sum of x and y and a carry indication. +func (x Int128) Add(y Int128) (r Int128, cy bool) { + r.Lo = x.Lo + y.Lo + r.Hi = x.Hi + y.Hi + if uint64(r.Lo) < uint64(x.Lo) { + r.Hi++ + } + return r, (r.Cmp(x) < 0) == (y.Sign() >= 0) +} + +// BigInt returns x in the form of a big.Int. +func (x Int128) BigInt() *big.Int { + r := big.NewInt(x.Hi) + r.Lsh(r, 64) + lo := big.NewInt(0) + lo.SetUint64(uint64(x.Lo)) + return r.Add(r, lo) +} + +// Cmp compares x and y and returns: +// +// -1 if x < y +// 0 if x == y +// +1 if x > y +func (x Int128) Cmp(y Int128) int { + if x.Hi > y.Hi { + return 1 + } + + if x.Hi < y.Hi { + return -1 + } + + if uint64(x.Lo) > uint64(y.Lo) { + return 1 + } + + if uint64(x.Lo) < uint64(y.Lo) { + return -1 + } + + return 0 +} + +// Neg returns -x and an indication that x was not equal to MinInt128. +func (x Int128) Neg() (r Int128, ok bool) { + if x == (Int128{Hi: math.MinInt64}) { + return x, false + } + + x.Lo = ^x.Lo + x.Hi = ^x.Hi + r, _ = x.Add(Int128{Lo: 1}) + return r, true +} + +// SetBigInt sets x to y, returns x and an error, if any. +func (x *Int128) SetBigInt(y *big.Int) (r Int128, err error) { + if y.Cmp(MaxInt128) > 0 { + return *x, fmt.Errorf("%T.SetInt: overflow", x) + } + if y.Cmp(MinInt128) < 0 { + return *x, fmt.Errorf("%T.SetInt: underflow", x) + } + neg := y.Sign() < 0 + var z big.Int + z.Set(y) + if neg { + z.Neg(&z) + } + r.Lo = z.Int64() + z.Rsh(&z, 64) + r.Hi = z.Int64() + if neg { + r, _ = r.Neg() + } + *x = r + return r, nil +} + +// SetInt64 sets x to y and returns x. +func (x *Int128) SetInt64(y int64) (r Int128) { + r.Lo = y + if y >= 0 { + r.Hi = 0 + *x = r + return r + } + + r.Hi = -1 + *x = r + return r +} + +// SetInt64 sets x to y and returns x. +func (x *Int128) SetUint64(y uint64) (r Int128) { + r = Int128{Lo: int64(y)} + *x = r + return r +} + +// Sign returns: +// +// -1 if x < 0 +// 0 if x == 0 +// +1 if x > 0 +func (x Int128) Sign() int { + if x.Hi < 0 { + return -1 + } + + if x.Hi != 0 || x.Lo != 0 { + return 1 + } + + return 0 +} + +// String implements fmt.Stringer() +func (x Int128) String() string { return x.BigInt().String() } diff --git a/vendor/github.com/cznic/mathutil/nist-sts-2-1-1-report b/vendor/github.com/cznic/mathutil/nist-sts-2-1-1-report new file mode 100644 index 0000000000000000000000000000000000000000..20e686c61b7fc52c1a3e135d67a4e0d9bde269c8 --- /dev/null +++ b/vendor/github.com/cznic/mathutil/nist-sts-2-1-1-report @@ -0,0 +1,267 @@ +$ ./example -max 100000000 > rnd.dat +$ ./assess 1000000 + G E N E R A T O R S E L E C T I O N + ______________________________________ + + [0] Input File [1] Linear Congruential + [2] Quadratic Congruential I [3] Quadratic Congruential II + [4] Cubic Congruential [5] XOR + [6] Modular Exponentiation [7] Blum-Blum-Shub + [8] Micali-Schnorr [9] G Using SHA-1 + + Enter Choice: 0 + + + User Prescribed Input File: rnd.dat + + S T A T I S T I C A L T E S T S + _________________________________ + + [01] Frequency [02] Block Frequency + [03] Cumulative Sums [04] Runs + [05] Longest Run of Ones [06] Rank + [07] Discrete Fourier Transform [08] Nonperiodic Template Matchings + [09] Overlapping Template Matchings [10] Universal Statistical + [11] Approximate Entropy [12] Random Excursions + [13] Random Excursions Variant [14] Serial + [15] Linear Complexity + + INSTRUCTIONS + Enter 0 if you DO NOT want to apply all of the + statistical tests to each sequence and 1 if you DO. + + Enter Choice: 1 + + P a r a m e t e r A d j u s t m e n t s + ----------------------------------------- + [1] Block Frequency Test - block length(M): 128 + [2] NonOverlapping Template Test - block length(m): 9 + [3] Overlapping Template Test - block length(m): 9 + [4] Approximate Entropy Test - block length(m): 10 + [5] Serial Test - block length(m): 16 + [6] Linear Complexity Test - block length(M): 500 + + Select Test (0 to continue): 0 + + How many bitstreams? 200 + + Input File Format: + [0] ASCII - A sequence of ASCII 0's and 1's + [1] Binary - Each byte in data file contains 8 bits of data + + Select input mode: 1 + + Statistical Testing In Progress......... + + Statistical Testing Complete!!!!!!!!!!!! + +$ cat experiments/AlgorithmTesting/finalAnalysisReport.txt +------------------------------------------------------------------------------ +RESULTS FOR THE UNIFORMITY OF P-VALUES AND THE PROPORTION OF PASSING SEQUENCES +------------------------------------------------------------------------------ + generator is +------------------------------------------------------------------------------ + C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 P-VALUE PROPORTION STATISTICAL TEST +------------------------------------------------------------------------------ + 28 22 17 19 15 8 24 23 19 25 0.093720 198/200 Frequency + 20 18 24 14 18 17 16 28 21 24 0.504219 199/200 BlockFrequency + 25 22 17 24 19 21 22 15 16 19 0.825505 197/200 CumulativeSums + 27 17 16 22 14 26 14 25 19 20 0.304126 199/200 CumulativeSums + 22 19 14 23 22 22 13 28 13 24 0.224821 199/200 Runs + 20 24 18 21 15 13 22 23 24 20 0.719747 197/200 LongestRun + 22 26 18 22 26 15 17 22 20 12 0.410055 199/200 Rank + 25 22 26 22 20 16 20 20 16 13 0.585209 195/200 FFT + 22 11 15 26 33 24 21 13 14 21 0.013102 197/200 NonOverlappingTemplate + 17 11 16 27 19 24 19 20 28 19 0.219006 200/200 NonOverlappingTemplate + 23 27 24 15 21 11 18 27 15 19 0.162606 197/200 NonOverlappingTemplate + 21 18 13 20 19 23 20 17 26 23 0.749884 197/200 NonOverlappingTemplate + 24 22 24 24 24 21 13 15 17 16 0.494392 196/200 NonOverlappingTemplate + 24 16 23 15 23 18 25 16 18 22 0.699313 199/200 NonOverlappingTemplate + 19 23 21 16 27 18 17 20 18 21 0.859637 198/200 NonOverlappingTemplate + 12 20 16 19 26 14 30 20 24 19 0.141256 198/200 NonOverlappingTemplate + 18 21 17 21 20 14 25 19 24 21 0.859637 198/200 NonOverlappingTemplate + 24 25 21 18 23 15 23 17 16 18 0.749884 199/200 NonOverlappingTemplate + 20 22 22 18 16 22 28 16 14 22 0.574903 198/200 NonOverlappingTemplate + 18 23 22 17 24 25 19 16 23 13 0.626709 199/200 NonOverlappingTemplate + 17 22 14 19 21 21 18 19 24 25 0.842937 198/200 NonOverlappingTemplate + 18 17 26 21 22 15 22 18 21 20 0.883171 197/200 NonOverlappingTemplate + 19 25 16 32 15 19 20 18 16 20 0.236810 199/200 NonOverlappingTemplate + 19 18 15 21 24 22 18 21 20 22 0.964295 200/200 NonOverlappingTemplate + 21 14 17 23 26 19 20 22 20 18 0.834308 196/200 NonOverlappingTemplate + 15 21 17 27 26 23 21 17 24 9 0.129620 198/200 NonOverlappingTemplate + 25 17 19 19 18 22 21 22 21 16 0.951205 196/200 NonOverlappingTemplate + 20 19 24 21 19 24 16 18 17 22 0.946308 197/200 NonOverlappingTemplate + 27 16 19 18 23 19 22 17 22 17 0.807412 197/200 NonOverlappingTemplate + 14 18 21 23 23 20 14 22 20 25 0.719747 198/200 NonOverlappingTemplate + 18 22 19 12 24 25 25 22 18 15 0.474986 198/200 NonOverlappingTemplate + 21 18 23 17 19 18 28 19 20 17 0.825505 198/200 NonOverlappingTemplate + 20 19 15 16 27 20 26 17 20 20 0.657933 198/200 NonOverlappingTemplate + 17 25 21 21 11 19 22 16 27 21 0.401199 198/200 NonOverlappingTemplate + 19 16 15 18 24 19 25 25 19 20 0.769527 199/200 NonOverlappingTemplate + 18 20 20 26 20 12 24 25 19 16 0.524101 198/200 NonOverlappingTemplate + 14 16 18 23 21 21 19 19 28 21 0.668321 197/200 NonOverlappingTemplate + 21 20 23 25 21 22 19 17 14 18 0.875539 197/200 NonOverlappingTemplate + 14 16 29 22 23 13 20 29 17 17 0.099513 197/200 NonOverlappingTemplate + 14 19 27 19 17 23 18 24 20 19 0.709558 199/200 NonOverlappingTemplate + 18 15 21 19 27 22 21 23 17 17 0.779188 198/200 NonOverlappingTemplate + 13 23 13 22 22 23 22 21 21 20 0.689019 199/200 NonOverlappingTemplate + 17 14 26 26 16 21 30 15 21 14 0.096578 199/200 NonOverlappingTemplate + 18 21 24 23 21 13 23 23 19 15 0.719747 197/200 NonOverlappingTemplate + 19 21 14 32 20 15 16 18 24 21 0.202268 199/200 NonOverlappingTemplate + 27 22 20 21 21 14 15 22 14 24 0.474986 196/200 NonOverlappingTemplate + 31 12 25 11 21 18 19 16 24 23 0.050305 197/200 NonOverlappingTemplate + 17 26 20 22 15 27 22 19 12 20 0.383827 199/200 NonOverlappingTemplate + 15 22 14 14 31 15 27 18 23 21 0.078086 194/200 NonOverlappingTemplate + 19 19 14 15 24 21 25 21 20 22 0.788728 197/200 NonOverlappingTemplate + 20 21 19 22 25 18 13 24 28 10 0.153763 195/200 NonOverlappingTemplate + 23 17 21 25 21 20 13 30 14 16 0.196920 196/200 NonOverlappingTemplate + 17 31 17 22 16 15 28 23 11 20 0.050305 197/200 NonOverlappingTemplate + 15 21 26 27 15 18 19 21 18 20 0.605916 198/200 NonOverlappingTemplate + 23 18 15 14 20 21 20 20 20 29 0.554420 200/200 NonOverlappingTemplate + 22 19 19 18 19 17 22 21 31 12 0.311542 199/200 NonOverlappingTemplate + 16 22 23 21 19 19 18 24 21 17 0.960198 197/200 NonOverlappingTemplate + 21 21 17 20 16 23 25 22 18 17 0.917870 200/200 NonOverlappingTemplate + 27 17 17 16 21 20 22 18 21 21 0.859637 197/200 NonOverlappingTemplate + 18 24 15 27 18 21 18 16 24 19 0.657933 199/200 NonOverlappingTemplate + 13 16 21 21 15 25 18 22 29 20 0.326749 198/200 NonOverlappingTemplate + 18 17 23 23 15 19 26 30 11 18 0.125927 198/200 NonOverlappingTemplate + 30 21 18 22 17 21 15 17 21 18 0.544254 195/200 NonOverlappingTemplate + 12 18 19 24 16 24 18 24 28 17 0.311542 199/200 NonOverlappingTemplate + 20 15 23 15 18 30 23 18 17 21 0.410055 196/200 NonOverlappingTemplate + 15 18 23 16 29 21 22 16 19 21 0.544254 200/200 NonOverlappingTemplate + 18 16 27 13 21 22 22 21 16 24 0.534146 199/200 NonOverlappingTemplate + 20 25 18 21 16 21 17 28 21 13 0.484646 200/200 NonOverlappingTemplate + 23 22 13 22 14 20 26 18 19 23 0.574903 197/200 NonOverlappingTemplate + 21 24 25 13 19 22 18 13 24 21 0.504219 199/200 NonOverlappingTemplate + 19 13 18 25 22 15 23 28 19 18 0.410055 195/200 NonOverlappingTemplate + 20 15 27 22 26 26 14 13 21 16 0.181557 198/200 NonOverlappingTemplate + 18 18 19 23 18 20 19 21 24 20 0.991468 200/200 NonOverlappingTemplate + 18 23 17 14 20 25 22 22 22 17 0.816537 198/200 NonOverlappingTemplate + 26 15 15 11 23 21 21 16 36 16 0.005557 196/200 NonOverlappingTemplate + 27 13 21 23 21 16 19 20 16 24 0.544254 198/200 NonOverlappingTemplate + 16 15 32 17 20 23 22 19 20 16 0.262249 200/200 NonOverlappingTemplate + 26 19 24 13 24 16 18 18 13 29 0.137282 199/200 NonOverlappingTemplate + 15 18 14 27 32 21 15 20 19 19 0.112047 198/200 NonOverlappingTemplate + 22 23 22 18 20 23 19 22 16 15 0.924076 196/200 NonOverlappingTemplate + 18 17 21 22 14 17 22 24 20 25 0.798139 199/200 NonOverlappingTemplate + 15 17 19 24 21 23 17 25 23 16 0.739918 196/200 NonOverlappingTemplate + 22 11 15 26 32 25 21 13 14 21 0.017305 197/200 NonOverlappingTemplate + 22 16 19 23 22 21 21 19 17 20 0.985788 200/200 NonOverlappingTemplate + 22 28 18 24 14 20 23 21 20 10 0.230755 198/200 NonOverlappingTemplate + 14 13 22 28 14 28 17 22 23 19 0.129620 197/200 NonOverlappingTemplate + 22 16 22 20 21 21 16 19 18 25 0.935716 198/200 NonOverlappingTemplate + 15 20 23 17 19 22 21 23 18 22 0.951205 200/200 NonOverlappingTemplate + 20 24 21 19 17 19 19 24 15 22 0.930026 198/200 NonOverlappingTemplate + 18 21 15 21 17 28 24 22 20 14 0.534146 200/200 NonOverlappingTemplate + 19 15 19 19 20 20 15 25 23 25 0.779188 198/200 NonOverlappingTemplate + 17 24 25 16 15 21 18 19 23 22 0.788728 198/200 NonOverlappingTemplate + 15 20 18 25 24 15 21 31 18 13 0.141256 200/200 NonOverlappingTemplate + 24 17 19 20 18 21 15 22 24 20 0.924076 196/200 NonOverlappingTemplate + 23 18 17 21 17 28 23 21 18 14 0.605916 197/200 NonOverlappingTemplate + 21 19 22 23 16 17 20 21 22 19 0.985788 200/200 NonOverlappingTemplate + 27 17 21 27 24 15 15 17 15 22 0.304126 199/200 NonOverlappingTemplate + 25 28 20 24 13 14 16 22 19 19 0.304126 197/200 NonOverlappingTemplate + 27 16 14 24 22 18 24 20 18 17 0.564639 196/200 NonOverlappingTemplate + 18 18 24 19 19 19 26 11 27 19 0.375313 195/200 NonOverlappingTemplate + 20 15 29 19 26 16 21 11 18 25 0.141256 197/200 NonOverlappingTemplate + 19 14 21 25 11 23 22 25 26 14 0.176657 199/200 NonOverlappingTemplate + 18 23 20 17 19 18 29 22 26 8 0.102526 199/200 NonOverlappingTemplate + 22 17 18 16 18 20 19 19 25 26 0.834308 198/200 NonOverlappingTemplate + 25 18 14 16 16 24 18 18 30 21 0.268917 198/200 NonOverlappingTemplate + 24 21 23 13 12 22 20 23 20 22 0.554420 196/200 NonOverlappingTemplate + 18 21 21 30 22 17 19 14 18 20 0.534146 197/200 NonOverlappingTemplate + 25 20 22 21 15 18 17 20 17 25 0.825505 199/200 NonOverlappingTemplate + 18 21 22 21 18 20 26 16 20 18 0.941144 197/200 NonOverlappingTemplate + 23 18 22 25 12 16 17 19 26 22 0.474986 198/200 NonOverlappingTemplate + 22 18 29 23 19 23 17 17 15 17 0.534146 198/200 NonOverlappingTemplate + 19 21 17 26 18 15 22 26 15 21 0.626709 197/200 NonOverlappingTemplate + 16 20 20 23 18 21 18 18 25 21 0.955835 199/200 NonOverlappingTemplate + 23 21 20 21 22 10 15 27 15 26 0.186566 198/200 NonOverlappingTemplate + 18 26 20 26 26 18 17 17 20 12 0.358641 198/200 NonOverlappingTemplate + 24 20 21 18 24 12 19 27 14 21 0.401199 195/200 NonOverlappingTemplate + 16 25 15 21 24 18 18 25 22 16 0.657933 199/200 NonOverlappingTemplate + 24 14 17 26 15 17 17 25 21 24 0.428095 200/200 NonOverlappingTemplate + 22 24 11 20 22 24 19 18 12 28 0.176657 196/200 NonOverlappingTemplate + 27 16 27 18 27 14 13 16 21 21 0.141256 197/200 NonOverlappingTemplate + 23 25 20 18 23 17 15 23 19 17 0.834308 196/200 NonOverlappingTemplate + 19 21 20 27 16 16 18 25 16 22 0.678686 199/200 NonOverlappingTemplate + 25 22 21 19 15 19 22 19 25 13 0.657933 197/200 NonOverlappingTemplate + 19 28 21 25 20 12 18 13 29 15 0.073417 198/200 NonOverlappingTemplate + 20 24 21 19 21 15 17 24 20 19 0.941144 198/200 NonOverlappingTemplate + 18 29 23 17 24 19 17 18 16 19 0.585209 200/200 NonOverlappingTemplate + 18 28 18 16 25 21 18 20 14 22 0.544254 198/200 NonOverlappingTemplate + 22 19 23 22 22 21 21 26 12 12 0.401199 199/200 NonOverlappingTemplate + 22 15 25 16 21 27 14 22 21 17 0.484646 199/200 NonOverlappingTemplate + 18 25 20 23 30 17 13 22 18 14 0.213309 200/200 NonOverlappingTemplate + 20 23 21 21 23 29 16 13 16 18 0.410055 199/200 NonOverlappingTemplate + 21 19 16 22 31 18 20 17 18 18 0.514124 198/200 NonOverlappingTemplate + 26 22 12 14 23 17 21 24 21 20 0.455937 197/200 NonOverlappingTemplate + 21 17 18 17 14 32 21 26 18 16 0.162606 197/200 NonOverlappingTemplate + 22 24 22 23 11 15 17 18 29 19 0.230755 198/200 NonOverlappingTemplate + 19 27 20 19 23 15 24 15 21 17 0.657933 198/200 NonOverlappingTemplate + 20 25 16 10 24 13 23 21 21 27 0.149495 200/200 NonOverlappingTemplate + 19 21 21 27 17 17 19 21 21 17 0.904708 200/200 NonOverlappingTemplate + 18 23 15 19 24 21 23 21 13 23 0.719747 198/200 NonOverlappingTemplate + 26 16 28 19 19 18 17 17 16 24 0.474986 199/200 NonOverlappingTemplate + 24 32 17 18 20 13 18 18 19 21 0.236810 195/200 NonOverlappingTemplate + 26 25 18 17 12 19 20 23 21 19 0.585209 196/200 NonOverlappingTemplate + 18 26 25 12 18 16 24 19 18 24 0.410055 199/200 NonOverlappingTemplate + 27 21 22 27 21 14 18 14 23 13 0.219006 197/200 NonOverlappingTemplate + 18 23 24 16 19 21 16 26 20 17 0.798139 199/200 NonOverlappingTemplate + 19 30 15 27 14 19 24 11 22 19 0.073417 198/200 NonOverlappingTemplate + 20 23 22 20 22 15 22 21 18 17 0.964295 198/200 NonOverlappingTemplate + 22 31 16 26 13 19 17 22 24 10 0.037566 197/200 NonOverlappingTemplate + 18 24 22 14 23 19 16 18 19 27 0.637119 197/200 NonOverlappingTemplate + 19 20 21 22 21 18 19 22 20 18 0.999438 198/200 NonOverlappingTemplate + 27 15 21 18 28 18 15 23 18 17 0.375313 195/200 NonOverlappingTemplate + 26 23 20 20 23 19 20 23 14 12 0.514124 199/200 NonOverlappingTemplate + 18 19 11 15 21 24 20 26 23 23 0.428095 198/200 NonOverlappingTemplate + 19 16 21 25 19 21 15 24 24 16 0.749884 197/200 NonOverlappingTemplate + 17 26 23 18 20 26 23 14 18 15 0.494392 198/200 NonOverlappingTemplate + 15 17 19 24 21 23 17 25 23 16 0.739918 196/200 NonOverlappingTemplate + 26 19 20 20 24 22 22 13 14 20 0.605916 198/200 OverlappingTemplate + 29 24 17 21 18 13 18 21 17 22 0.446556 196/200 Universal + 22 18 22 20 20 21 22 21 18 16 0.992952 198/200 ApproximateEntropy + 14 8 13 9 11 13 13 8 7 10 0.719747 106/106 RandomExcursions + 13 18 9 7 12 12 9 6 12 8 0.236810 104/106 RandomExcursions + 11 15 10 7 11 14 9 6 12 11 0.595549 106/106 RandomExcursions + 15 7 12 12 9 11 16 8 10 6 0.350485 106/106 RandomExcursions + 10 10 12 16 10 12 10 7 13 6 0.554420 106/106 RandomExcursions + 8 7 12 10 11 16 11 13 10 8 0.657933 106/106 RandomExcursions + 9 6 12 12 14 9 11 13 10 10 0.816537 104/106 RandomExcursions + 10 10 7 12 11 9 10 13 14 10 0.911413 105/106 RandomExcursions + 8 8 12 9 10 5 13 12 17 12 0.319084 104/106 RandomExcursionsVariant + 5 11 10 11 7 11 10 15 11 15 0.455937 104/106 RandomExcursionsVariant + 6 12 11 8 12 12 12 13 13 7 0.699313 104/106 RandomExcursionsVariant + 14 10 11 6 12 9 8 12 11 13 0.779188 104/106 RandomExcursionsVariant + 12 12 10 7 17 6 6 12 13 11 0.262249 103/106 RandomExcursionsVariant + 13 8 14 13 7 6 6 13 15 11 0.249284 102/106 RandomExcursionsVariant + 12 12 12 13 7 9 6 13 12 10 0.739918 105/106 RandomExcursionsVariant + 13 15 12 8 9 10 6 9 14 10 0.574903 106/106 RandomExcursionsVariant + 10 15 9 12 14 10 8 11 7 10 0.739918 105/106 RandomExcursionsVariant + 13 12 8 11 12 11 9 10 11 9 0.978072 103/106 RandomExcursionsVariant + 10 13 12 12 8 13 8 9 14 7 0.739918 104/106 RandomExcursionsVariant + 12 10 10 14 7 8 7 13 14 11 0.657933 106/106 RandomExcursionsVariant + 10 13 10 10 13 10 12 6 10 12 0.897763 106/106 RandomExcursionsVariant + 9 12 15 8 13 8 12 8 11 10 0.779188 106/106 RandomExcursionsVariant + 9 13 15 10 10 10 8 14 6 11 0.616305 106/106 RandomExcursionsVariant + 7 17 9 12 9 11 10 16 4 11 0.129620 106/106 RandomExcursionsVariant + 10 9 10 15 7 12 7 8 12 16 0.419021 106/106 RandomExcursionsVariant + 9 12 11 8 8 9 15 12 9 13 0.798139 106/106 RandomExcursionsVariant + 17 34 11 22 22 17 19 20 13 25 0.026057 199/200 Serial + 22 20 16 22 20 18 20 18 23 21 0.989786 199/200 Serial + 12 33 25 29 21 11 21 15 14 19 0.003996 199/200 LinearComplexity + + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +The minimum pass rate for each statistical test with the exception of the +random excursion (variant) test is approximately = 193 for a +sample size = 200 binary sequences. + +The minimum pass rate for the random excursion (variant) test +is approximately = 101 for a sample size = 106 binary sequences. + +For further guidelines construct a probability table using the MAPLE program +provided in the addendum section of the documentation. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +$ diff --git a/vendor/github.com/cznic/mathutil/poly.go b/vendor/github.com/cznic/mathutil/poly.go new file mode 100644 index 0000000000000000000000000000000000000000..52b58ff9f16174d3877c7e2dc21717d2997024bb --- /dev/null +++ b/vendor/github.com/cznic/mathutil/poly.go @@ -0,0 +1,248 @@ +// Copyright (c) 2016 The mathutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathutil + +import ( + "fmt" + "math/big" +) + +func abs(n int) uint64 { + if n >= 0 { + return uint64(n) + } + + return uint64(-n) +} + +// QuadPolyDiscriminant returns the discriminant of a quadratic polynomial in +// one variable of the form a*x^2+b*x+c with integer coefficients a, b, c, or +// an error on overflow. +// +// ds is the square of the discriminant. If |ds| is a square number, d is set +// to sqrt(|ds|), otherwise d is < 0. +func QuadPolyDiscriminant(a, b, c int) (ds, d int, _ error) { + if 2*BitLenUint64(abs(b)) > IntBits-1 || + 2+BitLenUint64(abs(a))+BitLenUint64(abs(c)) > IntBits-1 { + return 0, 0, fmt.Errorf("overflow") + } + + ds = b*b - 4*a*c + s := ds + if s < 0 { + s = -s + } + d64 := SqrtUint64(uint64(s)) + if d64*d64 != uint64(s) { + return ds, -1, nil + } + + return ds, int(d64), nil +} + +// PolyFactor describes an irreducible factor of a polynomial in one variable +// with integer coefficients P, Q of the form P*x+Q. +type PolyFactor struct { + P, Q int +} + +// QuadPolyFactors returns the content and the irreducible factors of the +// primitive part of a quadratic polynomial in one variable with integer +// coefficients a, b, c of the form a*x^2+b*x+c in integers, or an error on +// overflow. +// +// If the factorization in integers does not exists, the return value is (0, +// nil, nil). +// +// See also: +// https://en.wikipedia.org/wiki/Factorization_of_polynomials#Primitive_part.E2.80.93content_factorization +func QuadPolyFactors(a, b, c int) (content int, primitivePart []PolyFactor, _ error) { + content = int(GCDUint64(abs(a), GCDUint64(abs(b), abs(c)))) + switch { + case content == 0: + content = 1 + case content > 0: + if a < 0 || a == 0 && b < 0 { + content = -content + } + } + a /= content + b /= content + c /= content + if a == 0 { + if b == 0 { + return content, []PolyFactor{{0, c}}, nil + } + + if b < 0 && c < 0 { + b = -b + c = -c + } + if b < 0 { + b = -b + c = -c + } + return content, []PolyFactor{{b, c}}, nil + } + + ds, d, err := QuadPolyDiscriminant(a, b, c) + if err != nil { + return 0, nil, err + } + + if ds < 0 || d < 0 { + return 0, nil, nil + } + + x1num := -b + d + x1denom := 2 * a + gcd := int(GCDUint64(abs(x1num), abs(x1denom))) + x1num /= gcd + x1denom /= gcd + + x2num := -b - d + x2denom := 2 * a + gcd = int(GCDUint64(abs(x2num), abs(x2denom))) + x2num /= gcd + x2denom /= gcd + + return content, []PolyFactor{{x1denom, -x1num}, {x2denom, -x2num}}, nil +} + +// QuadPolyDiscriminantBig returns the discriminant of a quadratic polynomial +// in one variable of the form a*x^2+b*x+c with integer coefficients a, b, c. +// +// ds is the square of the discriminant. If |ds| is a square number, d is set +// to sqrt(|ds|), otherwise d is nil. +func QuadPolyDiscriminantBig(a, b, c *big.Int) (ds, d *big.Int) { + ds = big.NewInt(0).Set(b) + ds.Mul(ds, b) + x := big.NewInt(4) + x.Mul(x, a) + x.Mul(x, c) + ds.Sub(ds, x) + + s := big.NewInt(0).Set(ds) + if s.Sign() < 0 { + s.Neg(s) + } + + if s.Bit(1) != 0 { // s is not a square number + return ds, nil + } + + d = SqrtBig(s) + x.Set(d) + x.Mul(x, x) + if x.Cmp(s) != 0 { // s is not a square number + d = nil + } + return ds, d +} + +// PolyFactorBig describes an irreducible factor of a polynomial in one +// variable with integer coefficients P, Q of the form P*x+Q. +type PolyFactorBig struct { + P, Q *big.Int +} + +// QuadPolyFactorsBig returns the content and the irreducible factors of the +// primitive part of a quadratic polynomial in one variable with integer +// coefficients a, b, c of the form a*x^2+b*x+c in integers. +// +// If the factorization in integers does not exists, the return value is (nil, +// nil). +// +// See also: +// https://en.wikipedia.org/wiki/Factorization_of_polynomials#Primitive_part.E2.80.93content_factorization +func QuadPolyFactorsBig(a, b, c *big.Int) (content *big.Int, primitivePart []PolyFactorBig) { + content = bigGCD(bigAbs(a), bigGCD(bigAbs(b), bigAbs(c))) + switch { + case content.Sign() == 0: + content.SetInt64(1) + case content.Sign() > 0: + if a.Sign() < 0 || a.Sign() == 0 && b.Sign() < 0 { + content = bigNeg(content) + } + } + a = bigDiv(a, content) + b = bigDiv(b, content) + c = bigDiv(c, content) + + if a.Sign() == 0 { + if b.Sign() == 0 { + return content, []PolyFactorBig{{big.NewInt(0), c}} + } + + if b.Sign() < 0 && c.Sign() < 0 { + b = bigNeg(b) + c = bigNeg(c) + } + if b.Sign() < 0 { + b = bigNeg(b) + c = bigNeg(c) + } + return content, []PolyFactorBig{{b, c}} + } + + ds, d := QuadPolyDiscriminantBig(a, b, c) + if ds.Sign() < 0 || d == nil { + return nil, nil + } + + x1num := bigAdd(bigNeg(b), d) + x1denom := bigMul(_2, a) + gcd := bigGCD(bigAbs(x1num), bigAbs(x1denom)) + x1num = bigDiv(x1num, gcd) + x1denom = bigDiv(x1denom, gcd) + + x2num := bigAdd(bigNeg(b), bigNeg(d)) + x2denom := bigMul(_2, a) + gcd = bigGCD(bigAbs(x2num), bigAbs(x2denom)) + x2num = bigDiv(x2num, gcd) + x2denom = bigDiv(x2denom, gcd) + + return content, []PolyFactorBig{{x1denom, bigNeg(x1num)}, {x2denom, bigNeg(x2num)}} +} + +func bigAbs(n *big.Int) *big.Int { + n = big.NewInt(0).Set(n) + if n.Sign() >= 0 { + return n + } + + return n.Neg(n) +} + +func bigDiv(a, b *big.Int) *big.Int { + a = big.NewInt(0).Set(a) + return a.Div(a, b) +} + +func bigGCD(a, b *big.Int) *big.Int { + a = big.NewInt(0).Set(a) + b = big.NewInt(0).Set(b) + for b.Sign() != 0 { + c := big.NewInt(0) + c.Mod(a, b) + a, b = b, c + } + return a +} + +func bigNeg(n *big.Int) *big.Int { + n = big.NewInt(0).Set(n) + return n.Neg(n) +} + +func bigMul(a, b *big.Int) *big.Int { + r := big.NewInt(0).Set(a) + return r.Mul(r, b) +} + +func bigAdd(a, b *big.Int) *big.Int { + r := big.NewInt(0).Set(a) + return r.Add(r, b) +} diff --git a/vendor/github.com/go-ole/go-ole/ChangeLog.md b/vendor/github.com/go-ole/go-ole/ChangeLog.md new file mode 100644 index 0000000000000000000000000000000000000000..4ba6a8c64d00b2ea3ebd43ad73a6413ddc423097 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ChangeLog.md @@ -0,0 +1,49 @@ +# Version 1.x.x + +* **Add more test cases and reference new test COM server project.** (Placeholder for future additions) + +# Version 1.2.0-alphaX + +**Minimum supported version is now Go 1.4. Go 1.1 support is deprecated, but should still build.** + + * Added CI configuration for Travis-CI and AppVeyor. + * Added test InterfaceID and ClassID for the COM Test Server project. + * Added more inline documentation (#83). + * Added IEnumVARIANT implementation (#88). + * Added IEnumVARIANT test cases (#99, #100, #101). + * Added support for retrieving `time.Time` from VARIANT (#92). + * Added test case for IUnknown (#64). + * Added test case for IDispatch (#64). + * Added test cases for scalar variants (#64, #76). + +# Version 1.1.1 + + * Fixes for Linux build. + * Fixes for Windows build. + +# Version 1.1.0 + +The change to provide building on all platforms is a new feature. The increase in minor version reflects that and allows those who wish to stay on 1.0.x to continue to do so. Support for 1.0.x will be limited to bug fixes. + + * Move GUID out of variables.go into its own file to make new documentation available. + * Move OleError out of ole.go into its own file to make new documentation available. + * Add documentation to utility functions. + * Add documentation to variant receiver functions. + * Add documentation to ole structures. + * Make variant available to other systems outside of Windows. + * Make OLE structures available to other systems outside of Windows. + +## New Features + + * Library should now be built on all platforms supported by Go. Library will NOOP on any platform that is not Windows. + * More functions are now documented and available on godoc.org. + +# Version 1.0.1 + + 1. Fix package references from repository location change. + +# Version 1.0.0 + +This version is stable enough for use. The COM API is still incomplete, but provides enough functionality for accessing COM servers using IDispatch interface. + +There is no changelog for this version. Check commits for history. diff --git a/vendor/github.com/go-ole/go-ole/LICENSE b/vendor/github.com/go-ole/go-ole/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..623ec06f91cacea96632e39c26338ddb1471a436 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2013-2017 Yasuhiro Matsumoto, + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-ole/go-ole/README.md b/vendor/github.com/go-ole/go-ole/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7b577558d1cd66224ffbb3873efbd871f99aa051 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/README.md @@ -0,0 +1,46 @@ +# Go OLE + +[![Build status](https://ci.appveyor.com/api/projects/status/qr0u2sf7q43us9fj?svg=true)](https://ci.appveyor.com/project/jacobsantos/go-ole-jgs28) +[![Build Status](https://travis-ci.org/go-ole/go-ole.svg?branch=master)](https://travis-ci.org/go-ole/go-ole) +[![GoDoc](https://godoc.org/github.com/go-ole/go-ole?status.svg)](https://godoc.org/github.com/go-ole/go-ole) + +Go bindings for Windows COM using shared libraries instead of cgo. + +By Yasuhiro Matsumoto. + +## Install + +To experiment with go-ole, you can just compile and run the example program: + +``` +go get github.com/go-ole/go-ole +cd /path/to/go-ole/ +go test + +cd /path/to/go-ole/example/excel +go run excel.go +``` + +## Continuous Integration + +Continuous integration configuration has been added for both Travis-CI and AppVeyor. You will have to add these to your own account for your fork in order for it to run. + +**Travis-CI** + +Travis-CI was added to check builds on Linux to ensure that `go get` works when cross building. Currently, Travis-CI is not used to test cross-building, but this may be changed in the future. It is also not currently possible to test the library on Linux, since COM API is specific to Windows and it is not currently possible to run a COM server on Linux or even connect to a remote COM server. + +**AppVeyor** + +AppVeyor is used to build on Windows using the (in-development) test COM server. It is currently only used to test the build and ensure that the code works on Windows. It will be used to register a COM server and then run the test cases based on the test COM server. + +The tests currently do run and do pass and this should be maintained with commits. + +## Versioning + +Go OLE uses [semantic versioning](http://semver.org) for version numbers, which is similar to the version contract of the Go language. Which means that the major version will always maintain backwards compatibility with minor versions. Minor versions will only add new additions and changes. Fixes will always be in patch. + +This contract should allow you to upgrade to new minor and patch versions without breakage or modifications to your existing code. Leave a ticket, if there is breakage, so that it could be fixed. + +## LICENSE + +Under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/go-ole/go-ole/appveyor.yml b/vendor/github.com/go-ole/go-ole/appveyor.yml new file mode 100644 index 0000000000000000000000000000000000000000..0d557ac2ff556853c3e0b45077e52c9dcf91e0b5 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/appveyor.yml @@ -0,0 +1,54 @@ +# Notes: +# - Minimal appveyor.yml file is an empty file. All sections are optional. +# - Indent each level of configuration with 2 spaces. Do not use tabs! +# - All section names are case-sensitive. +# - Section names should be unique on each level. + +version: "1.3.0.{build}-alpha-{branch}" + +os: Windows Server 2012 R2 + +branches: + only: + - master + - v1.2 + - v1.1 + - v1.0 + +skip_tags: true + +clone_folder: c:\gopath\src\github.com\go-ole\go-ole + +environment: + GOPATH: c:\gopath + matrix: + - GOARCH: amd64 + GOVERSION: 1.5 + GOROOT: c:\go + DOWNLOADPLATFORM: "x64" + +install: + - choco install mingw + - SET PATH=c:\tools\mingw64\bin;%PATH% + # - Download COM Server + - ps: Start-FileDownload "https://github.com/go-ole/test-com-server/releases/download/v1.0.2/test-com-server-${env:DOWNLOADPLATFORM}.zip" + - 7z e test-com-server-%DOWNLOADPLATFORM%.zip -oc:\gopath\src\github.com\go-ole\go-ole > NUL + - c:\gopath\src\github.com\go-ole\go-ole\build\register-assembly.bat + # - set + - go version + - go env + - go get -u golang.org/x/tools/cmd/cover + - go get -u golang.org/x/tools/cmd/godoc + - go get -u golang.org/x/tools/cmd/stringer + +build_script: + - cd c:\gopath\src\github.com\go-ole\go-ole + - go get -v -t ./... + - go build + - go test -v -cover ./... + +# disable automatic tests +test: off + +# disable deployment +deploy: off diff --git a/vendor/github.com/go-ole/go-ole/com.go b/vendor/github.com/go-ole/go-ole/com.go new file mode 100644 index 0000000000000000000000000000000000000000..6f986b1894eeae6c128f19e278c4660e4ee1ee62 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/com.go @@ -0,0 +1,344 @@ +// +build windows + +package ole + +import ( + "syscall" + "unicode/utf16" + "unsafe" +) + +var ( + procCoInitialize, _ = modole32.FindProc("CoInitialize") + procCoInitializeEx, _ = modole32.FindProc("CoInitializeEx") + procCoUninitialize, _ = modole32.FindProc("CoUninitialize") + procCoCreateInstance, _ = modole32.FindProc("CoCreateInstance") + procCoTaskMemFree, _ = modole32.FindProc("CoTaskMemFree") + procCLSIDFromProgID, _ = modole32.FindProc("CLSIDFromProgID") + procCLSIDFromString, _ = modole32.FindProc("CLSIDFromString") + procStringFromCLSID, _ = modole32.FindProc("StringFromCLSID") + procStringFromIID, _ = modole32.FindProc("StringFromIID") + procIIDFromString, _ = modole32.FindProc("IIDFromString") + procCoGetObject, _ = modole32.FindProc("CoGetObject") + procGetUserDefaultLCID, _ = modkernel32.FindProc("GetUserDefaultLCID") + procCopyMemory, _ = modkernel32.FindProc("RtlMoveMemory") + procVariantInit, _ = modoleaut32.FindProc("VariantInit") + procVariantClear, _ = modoleaut32.FindProc("VariantClear") + procVariantTimeToSystemTime, _ = modoleaut32.FindProc("VariantTimeToSystemTime") + procSysAllocString, _ = modoleaut32.FindProc("SysAllocString") + procSysAllocStringLen, _ = modoleaut32.FindProc("SysAllocStringLen") + procSysFreeString, _ = modoleaut32.FindProc("SysFreeString") + procSysStringLen, _ = modoleaut32.FindProc("SysStringLen") + procCreateDispTypeInfo, _ = modoleaut32.FindProc("CreateDispTypeInfo") + procCreateStdDispatch, _ = modoleaut32.FindProc("CreateStdDispatch") + procGetActiveObject, _ = modoleaut32.FindProc("GetActiveObject") + + procGetMessageW, _ = moduser32.FindProc("GetMessageW") + procDispatchMessageW, _ = moduser32.FindProc("DispatchMessageW") +) + +// coInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func coInitialize() (err error) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx + // Suggests that no value should be passed to CoInitialized. + // Could just be Call() since the parameter is optional. <-- Needs testing to be sure. + hr, _, _ := procCoInitialize.Call(uintptr(0)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// coInitializeEx initializes COM library with concurrency model. +func coInitializeEx(coinit uint32) (err error) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms695279(v=vs.85).aspx + // Suggests that the first parameter is not only optional but should always be NULL. + hr, _, _ := procCoInitializeEx.Call(uintptr(0), uintptr(coinit)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// CoInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func CoInitialize(p uintptr) (err error) { + // p is ignored and won't be used. + // Avoid any variable not used errors. + p = uintptr(0) + return coInitialize() +} + +// CoInitializeEx initializes COM library with concurrency model. +func CoInitializeEx(p uintptr, coinit uint32) (err error) { + // Avoid any variable not used errors. + p = uintptr(0) + return coInitializeEx(coinit) +} + +// CoUninitialize uninitializes COM Library. +func CoUninitialize() { + procCoUninitialize.Call() +} + +// CoTaskMemFree frees memory pointer. +func CoTaskMemFree(memptr uintptr) { + procCoTaskMemFree.Call(memptr) +} + +// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. +// +// The Programmatic Identifier must be registered, because it will be looked up +// in the Windows Registry. The registry entry has the following keys: CLSID, +// Insertable, Protocol and Shell +// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). +// +// programID identifies the class id with less precision and is not guaranteed +// to be unique. These are usually found in the registry under +// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of +// "Program.Component.Version" with version being optional. +// +// CLSIDFromProgID in Windows API. +func CLSIDFromProgID(progId string) (clsid *GUID, err error) { + var guid GUID + lpszProgID := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) + hr, _, _ := procCLSIDFromProgID.Call(lpszProgID, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// CLSIDFromString retrieves Class ID from string representation. +// +// This is technically the string version of the GUID and will convert the +// string to object. +// +// CLSIDFromString in Windows API. +func CLSIDFromString(str string) (clsid *GUID, err error) { + var guid GUID + lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(str))) + hr, _, _ := procCLSIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// StringFromCLSID returns GUID formated string from GUID object. +func StringFromCLSID(clsid *GUID) (str string, err error) { + var p *uint16 + hr, _, _ := procStringFromCLSID.Call(uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(&p))) + if hr != 0 { + err = NewError(hr) + } + str = LpOleStrToString(p) + return +} + +// IIDFromString returns GUID from program ID. +func IIDFromString(progId string) (clsid *GUID, err error) { + var guid GUID + lpsz := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))) + hr, _, _ := procIIDFromString.Call(lpsz, uintptr(unsafe.Pointer(&guid))) + if hr != 0 { + err = NewError(hr) + } + clsid = &guid + return +} + +// StringFromIID returns GUID formatted string from GUID object. +func StringFromIID(iid *GUID) (str string, err error) { + var p *uint16 + hr, _, _ := procStringFromIID.Call(uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(&p))) + if hr != 0 { + err = NewError(hr) + } + str = LpOleStrToString(p) + return +} + +// CreateInstance of single uninitialized object with GUID. +func CreateInstance(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procCoCreateInstance.Call( + uintptr(unsafe.Pointer(clsid)), + 0, + CLSCTX_SERVER, + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// GetActiveObject retrieves pointer to active object. +func GetActiveObject(clsid *GUID, iid *GUID) (unk *IUnknown, err error) { + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procGetActiveObject.Call( + uintptr(unsafe.Pointer(clsid)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +type BindOpts struct { + CbStruct uint32 + GrfFlags uint32 + GrfMode uint32 + TickCountDeadline uint32 +} + +// GetObject retrieves pointer to active object. +func GetObject(programID string, bindOpts *BindOpts, iid *GUID) (unk *IUnknown, err error) { + if bindOpts != nil { + bindOpts.CbStruct = uint32(unsafe.Sizeof(BindOpts{})) + } + if iid == nil { + iid = IID_IUnknown + } + hr, _, _ := procCoGetObject.Call( + uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(programID))), + uintptr(unsafe.Pointer(bindOpts)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&unk))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// VariantInit initializes variant. +func VariantInit(v *VARIANT) (err error) { + hr, _, _ := procVariantInit.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// VariantClear clears value in Variant settings to VT_EMPTY. +func VariantClear(v *VARIANT) (err error) { + hr, _, _ := procVariantClear.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// SysAllocString allocates memory for string and copies string into memory. +func SysAllocString(v string) (ss *int16) { + pss, _, _ := procSysAllocString.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v)))) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +// SysAllocStringLen copies up to length of given string returning pointer. +func SysAllocStringLen(v string) (ss *int16) { + utf16 := utf16.Encode([]rune(v + "\x00")) + ptr := &utf16[0] + + pss, _, _ := procSysAllocStringLen.Call(uintptr(unsafe.Pointer(ptr)), uintptr(len(utf16)-1)) + ss = (*int16)(unsafe.Pointer(pss)) + return +} + +// SysFreeString frees string system memory. This must be called with SysAllocString. +func SysFreeString(v *int16) (err error) { + hr, _, _ := procSysFreeString.Call(uintptr(unsafe.Pointer(v))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// SysStringLen is the length of the system allocated string. +func SysStringLen(v *int16) uint32 { + l, _, _ := procSysStringLen.Call(uintptr(unsafe.Pointer(v))) + return uint32(l) +} + +// CreateStdDispatch provides default IDispatch implementation for IUnknown. +// +// This handles default IDispatch implementation for objects. It haves a few +// limitations with only supporting one language. It will also only return +// default exception codes. +func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (disp *IDispatch, err error) { + hr, _, _ := procCreateStdDispatch.Call( + uintptr(unsafe.Pointer(unk)), + v, + uintptr(unsafe.Pointer(ptinfo)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. +// +// This will not handle the full implementation of the interface. +func CreateDispTypeInfo(idata *INTERFACEDATA) (pptinfo *IUnknown, err error) { + hr, _, _ := procCreateDispTypeInfo.Call( + uintptr(unsafe.Pointer(idata)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&pptinfo))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// copyMemory moves location of a block of memory. +func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) { + procCopyMemory.Call(uintptr(dest), uintptr(src), uintptr(length)) +} + +// GetUserDefaultLCID retrieves current user default locale. +func GetUserDefaultLCID() (lcid uint32) { + ret, _, _ := procGetUserDefaultLCID.Call() + lcid = uint32(ret) + return +} + +// GetMessage in message queue from runtime. +// +// This function appears to block. PeekMessage does not block. +func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) { + r0, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax)) + ret = int32(r0) + return +} + +// DispatchMessage to window procedure. +func DispatchMessage(msg *Msg) (ret int32) { + r0, _, _ := procDispatchMessageW.Call(uintptr(unsafe.Pointer(msg))) + ret = int32(r0) + return +} diff --git a/vendor/github.com/go-ole/go-ole/com_func.go b/vendor/github.com/go-ole/go-ole/com_func.go new file mode 100644 index 0000000000000000000000000000000000000000..cef539d9ddd6a99281c8f59930d961cbc8335c2c --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/com_func.go @@ -0,0 +1,174 @@ +// +build !windows + +package ole + +import ( + "time" + "unsafe" +) + +// coInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func coInitialize() error { + return NewError(E_NOTIMPL) +} + +// coInitializeEx initializes COM library with concurrency model. +func coInitializeEx(coinit uint32) error { + return NewError(E_NOTIMPL) +} + +// CoInitialize initializes COM library on current thread. +// +// MSDN documentation suggests that this function should not be called. Call +// CoInitializeEx() instead. The reason has to do with threading and this +// function is only for single-threaded apartments. +// +// That said, most users of the library have gotten away with just this +// function. If you are experiencing threading issues, then use +// CoInitializeEx(). +func CoInitialize(p uintptr) error { + return NewError(E_NOTIMPL) +} + +// CoInitializeEx initializes COM library with concurrency model. +func CoInitializeEx(p uintptr, coinit uint32) error { + return NewError(E_NOTIMPL) +} + +// CoUninitialize uninitializes COM Library. +func CoUninitialize() {} + +// CoTaskMemFree frees memory pointer. +func CoTaskMemFree(memptr uintptr) {} + +// CLSIDFromProgID retrieves Class Identifier with the given Program Identifier. +// +// The Programmatic Identifier must be registered, because it will be looked up +// in the Windows Registry. The registry entry has the following keys: CLSID, +// Insertable, Protocol and Shell +// (https://msdn.microsoft.com/en-us/library/dd542719(v=vs.85).aspx). +// +// programID identifies the class id with less precision and is not guaranteed +// to be unique. These are usually found in the registry under +// HKEY_LOCAL_MACHINE\SOFTWARE\Classes, usually with the format of +// "Program.Component.Version" with version being optional. +// +// CLSIDFromProgID in Windows API. +func CLSIDFromProgID(progId string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// CLSIDFromString retrieves Class ID from string representation. +// +// This is technically the string version of the GUID and will convert the +// string to object. +// +// CLSIDFromString in Windows API. +func CLSIDFromString(str string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// StringFromCLSID returns GUID formated string from GUID object. +func StringFromCLSID(clsid *GUID) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// IIDFromString returns GUID from program ID. +func IIDFromString(progId string) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// StringFromIID returns GUID formatted string from GUID object. +func StringFromIID(iid *GUID) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// CreateInstance of single uninitialized object with GUID. +func CreateInstance(clsid *GUID, iid *GUID) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// GetActiveObject retrieves pointer to active object. +func GetActiveObject(clsid *GUID, iid *GUID) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// VariantInit initializes variant. +func VariantInit(v *VARIANT) error { + return NewError(E_NOTIMPL) +} + +// VariantClear clears value in Variant settings to VT_EMPTY. +func VariantClear(v *VARIANT) error { + return NewError(E_NOTIMPL) +} + +// SysAllocString allocates memory for string and copies string into memory. +func SysAllocString(v string) *int16 { + u := int16(0) + return &u +} + +// SysAllocStringLen copies up to length of given string returning pointer. +func SysAllocStringLen(v string) *int16 { + u := int16(0) + return &u +} + +// SysFreeString frees string system memory. This must be called with SysAllocString. +func SysFreeString(v *int16) error { + return NewError(E_NOTIMPL) +} + +// SysStringLen is the length of the system allocated string. +func SysStringLen(v *int16) uint32 { + return uint32(0) +} + +// CreateStdDispatch provides default IDispatch implementation for IUnknown. +// +// This handles default IDispatch implementation for objects. It haves a few +// limitations with only supporting one language. It will also only return +// default exception codes. +func CreateStdDispatch(unk *IUnknown, v uintptr, ptinfo *IUnknown) (*IDispatch, error) { + return nil, NewError(E_NOTIMPL) +} + +// CreateDispTypeInfo provides default ITypeInfo implementation for IDispatch. +// +// This will not handle the full implementation of the interface. +func CreateDispTypeInfo(idata *INTERFACEDATA) (*IUnknown, error) { + return nil, NewError(E_NOTIMPL) +} + +// copyMemory moves location of a block of memory. +func copyMemory(dest unsafe.Pointer, src unsafe.Pointer, length uint32) {} + +// GetUserDefaultLCID retrieves current user default locale. +func GetUserDefaultLCID() uint32 { + return uint32(0) +} + +// GetMessage in message queue from runtime. +// +// This function appears to block. PeekMessage does not block. +func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (int32, error) { + return int32(0), NewError(E_NOTIMPL) +} + +// DispatchMessage to window procedure. +func DispatchMessage(msg *Msg) int32 { + return int32(0) +} + +func GetVariantDate(value uint64) (time.Time, error) { + return time.Now(), NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/connect.go b/vendor/github.com/go-ole/go-ole/connect.go new file mode 100644 index 0000000000000000000000000000000000000000..b2ac2ec67ac9fb5c6e23eefbc8d3edaf1319e0e6 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/connect.go @@ -0,0 +1,192 @@ +package ole + +// Connection contains IUnknown for fluent interface interaction. +// +// Deprecated. Use oleutil package instead. +type Connection struct { + Object *IUnknown // Access COM +} + +// Initialize COM. +func (*Connection) Initialize() (err error) { + return coInitialize() +} + +// Uninitialize COM. +func (*Connection) Uninitialize() { + CoUninitialize() +} + +// Create IUnknown object based first on ProgId and then from String. +func (c *Connection) Create(progId string) (err error) { + var clsid *GUID + clsid, err = CLSIDFromProgID(progId) + if err != nil { + clsid, err = CLSIDFromString(progId) + if err != nil { + return + } + } + + unknown, err := CreateInstance(clsid, IID_IUnknown) + if err != nil { + return + } + c.Object = unknown + + return +} + +// Release IUnknown object. +func (c *Connection) Release() { + c.Object.Release() +} + +// Load COM object from list of programIDs or strings. +func (c *Connection) Load(names ...string) (errors []error) { + var tempErrors []error = make([]error, len(names)) + var numErrors int = 0 + for _, name := range names { + err := c.Create(name) + if err != nil { + tempErrors = append(tempErrors, err) + numErrors += 1 + continue + } + break + } + + copy(errors, tempErrors[0:numErrors]) + return +} + +// Dispatch returns Dispatch object. +func (c *Connection) Dispatch() (object *Dispatch, err error) { + dispatch, err := c.Object.QueryInterface(IID_IDispatch) + if err != nil { + return + } + object = &Dispatch{dispatch} + return +} + +// Dispatch stores IDispatch object. +type Dispatch struct { + Object *IDispatch // Dispatch object. +} + +// Call method on IDispatch with parameters. +func (d *Dispatch) Call(method string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(method) + if err != nil { + return + } + + result, err = d.Invoke(id, DISPATCH_METHOD, params) + return +} + +// MustCall method on IDispatch with parameters. +func (d *Dispatch) MustCall(method string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(method) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_METHOD, params) + if err != nil { + panic(err) + } + + return +} + +// Get property on IDispatch with parameters. +func (d *Dispatch) Get(name string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(name) + if err != nil { + return + } + result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) + return +} + +// MustGet property on IDispatch with parameters. +func (d *Dispatch) MustGet(name string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(name) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_PROPERTYGET, params) + if err != nil { + panic(err) + } + return +} + +// Set property on IDispatch with parameters. +func (d *Dispatch) Set(name string, params ...interface{}) (result *VARIANT, err error) { + id, err := d.GetId(name) + if err != nil { + return + } + result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) + return +} + +// MustSet property on IDispatch with parameters. +func (d *Dispatch) MustSet(name string, params ...interface{}) (result *VARIANT) { + id, err := d.GetId(name) + if err != nil { + panic(err) + } + + result, err = d.Invoke(id, DISPATCH_PROPERTYPUT, params) + if err != nil { + panic(err) + } + return +} + +// GetId retrieves ID of name on IDispatch. +func (d *Dispatch) GetId(name string) (id int32, err error) { + var dispid []int32 + dispid, err = d.Object.GetIDsOfName([]string{name}) + if err != nil { + return + } + id = dispid[0] + return +} + +// GetIds retrieves all IDs of names on IDispatch. +func (d *Dispatch) GetIds(names ...string) (dispid []int32, err error) { + dispid, err = d.Object.GetIDsOfName(names) + return +} + +// Invoke IDispatch on DisplayID of dispatch type with parameters. +// +// There have been problems where if send cascading params..., it would error +// out because the parameters would be empty. +func (d *Dispatch) Invoke(id int32, dispatch int16, params []interface{}) (result *VARIANT, err error) { + if len(params) < 1 { + result, err = d.Object.Invoke(id, dispatch) + } else { + result, err = d.Object.Invoke(id, dispatch, params...) + } + return +} + +// Release IDispatch object. +func (d *Dispatch) Release() { + d.Object.Release() +} + +// Connect initializes COM and attempts to load IUnknown based on given names. +func Connect(names ...string) (connection *Connection) { + connection.Initialize() + connection.Load(names...) + return +} diff --git a/vendor/github.com/go-ole/go-ole/constants.go b/vendor/github.com/go-ole/go-ole/constants.go new file mode 100644 index 0000000000000000000000000000000000000000..fd0c6d74b0e9a377f7c77ad59f0dd9abc6fc4c7b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/constants.go @@ -0,0 +1,153 @@ +package ole + +const ( + CLSCTX_INPROC_SERVER = 1 + CLSCTX_INPROC_HANDLER = 2 + CLSCTX_LOCAL_SERVER = 4 + CLSCTX_INPROC_SERVER16 = 8 + CLSCTX_REMOTE_SERVER = 16 + CLSCTX_ALL = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER + CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER + CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER +) + +const ( + COINIT_APARTMENTTHREADED = 0x2 + COINIT_MULTITHREADED = 0x0 + COINIT_DISABLE_OLE1DDE = 0x4 + COINIT_SPEED_OVER_MEMORY = 0x8 +) + +const ( + DISPATCH_METHOD = 1 + DISPATCH_PROPERTYGET = 2 + DISPATCH_PROPERTYPUT = 4 + DISPATCH_PROPERTYPUTREF = 8 +) + +const ( + S_OK = 0x00000000 + E_UNEXPECTED = 0x8000FFFF + E_NOTIMPL = 0x80004001 + E_OUTOFMEMORY = 0x8007000E + E_INVALIDARG = 0x80070057 + E_NOINTERFACE = 0x80004002 + E_POINTER = 0x80004003 + E_HANDLE = 0x80070006 + E_ABORT = 0x80004004 + E_FAIL = 0x80004005 + E_ACCESSDENIED = 0x80070005 + E_PENDING = 0x8000000A + + CO_E_CLASSSTRING = 0x800401F3 +) + +const ( + CC_FASTCALL = iota + CC_CDECL + CC_MSCPASCAL + CC_PASCAL = CC_MSCPASCAL + CC_MACPASCAL + CC_STDCALL + CC_FPFASTCALL + CC_SYSCALL + CC_MPWCDECL + CC_MPWPASCAL + CC_MAX = CC_MPWPASCAL +) + +type VT uint16 + +const ( + VT_EMPTY VT = 0x0 + VT_NULL VT = 0x1 + VT_I2 VT = 0x2 + VT_I4 VT = 0x3 + VT_R4 VT = 0x4 + VT_R8 VT = 0x5 + VT_CY VT = 0x6 + VT_DATE VT = 0x7 + VT_BSTR VT = 0x8 + VT_DISPATCH VT = 0x9 + VT_ERROR VT = 0xa + VT_BOOL VT = 0xb + VT_VARIANT VT = 0xc + VT_UNKNOWN VT = 0xd + VT_DECIMAL VT = 0xe + VT_I1 VT = 0x10 + VT_UI1 VT = 0x11 + VT_UI2 VT = 0x12 + VT_UI4 VT = 0x13 + VT_I8 VT = 0x14 + VT_UI8 VT = 0x15 + VT_INT VT = 0x16 + VT_UINT VT = 0x17 + VT_VOID VT = 0x18 + VT_HRESULT VT = 0x19 + VT_PTR VT = 0x1a + VT_SAFEARRAY VT = 0x1b + VT_CARRAY VT = 0x1c + VT_USERDEFINED VT = 0x1d + VT_LPSTR VT = 0x1e + VT_LPWSTR VT = 0x1f + VT_RECORD VT = 0x24 + VT_INT_PTR VT = 0x25 + VT_UINT_PTR VT = 0x26 + VT_FILETIME VT = 0x40 + VT_BLOB VT = 0x41 + VT_STREAM VT = 0x42 + VT_STORAGE VT = 0x43 + VT_STREAMED_OBJECT VT = 0x44 + VT_STORED_OBJECT VT = 0x45 + VT_BLOB_OBJECT VT = 0x46 + VT_CF VT = 0x47 + VT_CLSID VT = 0x48 + VT_BSTR_BLOB VT = 0xfff + VT_VECTOR VT = 0x1000 + VT_ARRAY VT = 0x2000 + VT_BYREF VT = 0x4000 + VT_RESERVED VT = 0x8000 + VT_ILLEGAL VT = 0xffff + VT_ILLEGALMASKED VT = 0xfff + VT_TYPEMASK VT = 0xfff +) + +const ( + DISPID_UNKNOWN = -1 + DISPID_VALUE = 0 + DISPID_PROPERTYPUT = -3 + DISPID_NEWENUM = -4 + DISPID_EVALUATE = -5 + DISPID_CONSTRUCTOR = -6 + DISPID_DESTRUCTOR = -7 + DISPID_COLLECT = -8 +) + +const ( + TKIND_ENUM = 1 + TKIND_RECORD = 2 + TKIND_MODULE = 3 + TKIND_INTERFACE = 4 + TKIND_DISPATCH = 5 + TKIND_COCLASS = 6 + TKIND_ALIAS = 7 + TKIND_UNION = 8 + TKIND_MAX = 9 +) + +// Safe Array Feature Flags + +const ( + FADF_AUTO = 0x0001 + FADF_STATIC = 0x0002 + FADF_EMBEDDED = 0x0004 + FADF_FIXEDSIZE = 0x0010 + FADF_RECORD = 0x0020 + FADF_HAVEIID = 0x0040 + FADF_HAVEVARTYPE = 0x0080 + FADF_BSTR = 0x0100 + FADF_UNKNOWN = 0x0200 + FADF_DISPATCH = 0x0400 + FADF_VARIANT = 0x0800 + FADF_RESERVED = 0xF008 +) diff --git a/vendor/github.com/go-ole/go-ole/error.go b/vendor/github.com/go-ole/go-ole/error.go new file mode 100644 index 0000000000000000000000000000000000000000..096b456d3a1fc74e36da71d7ec8d9b13c356757e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error.go @@ -0,0 +1,51 @@ +package ole + +// OleError stores COM errors. +type OleError struct { + hr uintptr + description string + subError error +} + +// NewError creates new error with HResult. +func NewError(hr uintptr) *OleError { + return &OleError{hr: hr} +} + +// NewErrorWithDescription creates new COM error with HResult and description. +func NewErrorWithDescription(hr uintptr, description string) *OleError { + return &OleError{hr: hr, description: description} +} + +// NewErrorWithSubError creates new COM error with parent error. +func NewErrorWithSubError(hr uintptr, description string, err error) *OleError { + return &OleError{hr: hr, description: description, subError: err} +} + +// Code is the HResult. +func (v *OleError) Code() uintptr { + return uintptr(v.hr) +} + +// String description, either manually set or format message with error code. +func (v *OleError) String() string { + if v.description != "" { + return errstr(int(v.hr)) + " (" + v.description + ")" + } + return errstr(int(v.hr)) +} + +// Error implements error interface. +func (v *OleError) Error() string { + return v.String() +} + +// Description retrieves error summary, if there is one. +func (v *OleError) Description() string { + return v.description +} + +// SubError returns parent error, if there is one. +func (v *OleError) SubError() error { + return v.subError +} diff --git a/vendor/github.com/go-ole/go-ole/error_func.go b/vendor/github.com/go-ole/go-ole/error_func.go new file mode 100644 index 0000000000000000000000000000000000000000..8a2ffaa2724fa7d36116596ce92066b64b940abe --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error_func.go @@ -0,0 +1,8 @@ +// +build !windows + +package ole + +// errstr converts error code to string. +func errstr(errno int) string { + return "" +} diff --git a/vendor/github.com/go-ole/go-ole/error_windows.go b/vendor/github.com/go-ole/go-ole/error_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..d0e8e68595c4dec458fbbc480411acf5c27e5424 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/error_windows.go @@ -0,0 +1,24 @@ +// +build windows + +package ole + +import ( + "fmt" + "syscall" + "unicode/utf16" +) + +// errstr converts error code to string. +func errstr(errno int) string { + // ask windows for the remaining errors + var flags uint32 = syscall.FORMAT_MESSAGE_FROM_SYSTEM | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS + b := make([]uint16, 300) + n, err := syscall.FormatMessage(flags, 0, uint32(errno), 0, b, nil) + if err != nil { + return fmt.Sprintf("error %d (FormatMessage failed with: %v)", errno, err) + } + // trim terminating \r and \n + for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- { + } + return string(utf16.Decode(b[:n])) +} diff --git a/vendor/github.com/go-ole/go-ole/guid.go b/vendor/github.com/go-ole/go-ole/guid.go new file mode 100644 index 0000000000000000000000000000000000000000..8d20f68fbf4a96921f3b4fe044142d3a4263ab1d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/guid.go @@ -0,0 +1,284 @@ +package ole + +var ( + // IID_NULL is null Interface ID, used when no other Interface ID is known. + IID_NULL = NewGUID("{00000000-0000-0000-0000-000000000000}") + + // IID_IUnknown is for IUnknown interfaces. + IID_IUnknown = NewGUID("{00000000-0000-0000-C000-000000000046}") + + // IID_IDispatch is for IDispatch interfaces. + IID_IDispatch = NewGUID("{00020400-0000-0000-C000-000000000046}") + + // IID_IEnumVariant is for IEnumVariant interfaces + IID_IEnumVariant = NewGUID("{00020404-0000-0000-C000-000000000046}") + + // IID_IConnectionPointContainer is for IConnectionPointContainer interfaces. + IID_IConnectionPointContainer = NewGUID("{B196B284-BAB4-101A-B69C-00AA00341D07}") + + // IID_IConnectionPoint is for IConnectionPoint interfaces. + IID_IConnectionPoint = NewGUID("{B196B286-BAB4-101A-B69C-00AA00341D07}") + + // IID_IInspectable is for IInspectable interfaces. + IID_IInspectable = NewGUID("{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}") + + // IID_IProvideClassInfo is for IProvideClassInfo interfaces. + IID_IProvideClassInfo = NewGUID("{B196B283-BAB4-101A-B69C-00AA00341D07}") +) + +// These are for testing and not part of any library. +var ( + // IID_ICOMTestString is for ICOMTestString interfaces. + // + // {E0133EB4-C36F-469A-9D3D-C66B84BE19ED} + IID_ICOMTestString = NewGUID("{E0133EB4-C36F-469A-9D3D-C66B84BE19ED}") + + // IID_ICOMTestInt8 is for ICOMTestInt8 interfaces. + // + // {BEB06610-EB84-4155-AF58-E2BFF53680B4} + IID_ICOMTestInt8 = NewGUID("{BEB06610-EB84-4155-AF58-E2BFF53680B4}") + + // IID_ICOMTestInt16 is for ICOMTestInt16 interfaces. + // + // {DAA3F9FA-761E-4976-A860-8364CE55F6FC} + IID_ICOMTestInt16 = NewGUID("{DAA3F9FA-761E-4976-A860-8364CE55F6FC}") + + // IID_ICOMTestInt32 is for ICOMTestInt32 interfaces. + // + // {E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0} + IID_ICOMTestInt32 = NewGUID("{E3DEDEE7-38A2-4540-91D1-2EEF1D8891B0}") + + // IID_ICOMTestInt64 is for ICOMTestInt64 interfaces. + // + // {8D437CBC-B3ED-485C-BC32-C336432A1623} + IID_ICOMTestInt64 = NewGUID("{8D437CBC-B3ED-485C-BC32-C336432A1623}") + + // IID_ICOMTestFloat is for ICOMTestFloat interfaces. + // + // {BF1ED004-EA02-456A-AA55-2AC8AC6B054C} + IID_ICOMTestFloat = NewGUID("{BF1ED004-EA02-456A-AA55-2AC8AC6B054C}") + + // IID_ICOMTestDouble is for ICOMTestDouble interfaces. + // + // {BF908A81-8687-4E93-999F-D86FAB284BA0} + IID_ICOMTestDouble = NewGUID("{BF908A81-8687-4E93-999F-D86FAB284BA0}") + + // IID_ICOMTestBoolean is for ICOMTestBoolean interfaces. + // + // {D530E7A6-4EE8-40D1-8931-3D63B8605010} + IID_ICOMTestBoolean = NewGUID("{D530E7A6-4EE8-40D1-8931-3D63B8605010}") + + // IID_ICOMEchoTestObject is for ICOMEchoTestObject interfaces. + // + // {6485B1EF-D780-4834-A4FE-1EBB51746CA3} + IID_ICOMEchoTestObject = NewGUID("{6485B1EF-D780-4834-A4FE-1EBB51746CA3}") + + // IID_ICOMTestTypes is for ICOMTestTypes interfaces. + // + // {CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0} + IID_ICOMTestTypes = NewGUID("{CCA8D7AE-91C0-4277-A8B3-FF4EDF28D3C0}") + + // CLSID_COMEchoTestObject is for COMEchoTestObject class. + // + // {3C24506A-AE9E-4D50-9157-EF317281F1B0} + CLSID_COMEchoTestObject = NewGUID("{3C24506A-AE9E-4D50-9157-EF317281F1B0}") + + // CLSID_COMTestScalarClass is for COMTestScalarClass class. + // + // {865B85C5-0334-4AC6-9EF6-AACEC8FC5E86} + CLSID_COMTestScalarClass = NewGUID("{865B85C5-0334-4AC6-9EF6-AACEC8FC5E86}") +) + +const hextable = "0123456789ABCDEF" +const emptyGUID = "{00000000-0000-0000-0000-000000000000}" + +// GUID is Windows API specific GUID type. +// +// This exists to match Windows GUID type for direct passing for COM. +// Format is in xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx. +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +// NewGUID converts the given string into a globally unique identifier that is +// compliant with the Windows API. +// +// The supplied string may be in any of these formats: +// +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// The conversion of the supplied string is not case-sensitive. +func NewGUID(guid string) *GUID { + d := []byte(guid) + var d1, d2, d3, d4a, d4b []byte + + switch len(d) { + case 38: + if d[0] != '{' || d[37] != '}' { + return nil + } + d = d[1:37] + fallthrough + case 36: + if d[8] != '-' || d[13] != '-' || d[18] != '-' || d[23] != '-' { + return nil + } + d1 = d[0:8] + d2 = d[9:13] + d3 = d[14:18] + d4a = d[19:23] + d4b = d[24:36] + case 32: + d1 = d[0:8] + d2 = d[8:12] + d3 = d[12:16] + d4a = d[16:20] + d4b = d[20:32] + default: + return nil + } + + var g GUID + var ok1, ok2, ok3, ok4 bool + g.Data1, ok1 = decodeHexUint32(d1) + g.Data2, ok2 = decodeHexUint16(d2) + g.Data3, ok3 = decodeHexUint16(d3) + g.Data4, ok4 = decodeHexByte64(d4a, d4b) + if ok1 && ok2 && ok3 && ok4 { + return &g + } + return nil +} + +func decodeHexUint32(src []byte) (value uint32, ok bool) { + var b1, b2, b3, b4 byte + var ok1, ok2, ok3, ok4 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + b3, ok3 = decodeHexByte(src[4], src[5]) + b4, ok4 = decodeHexByte(src[6], src[7]) + value = (uint32(b1) << 24) | (uint32(b2) << 16) | (uint32(b3) << 8) | uint32(b4) + ok = ok1 && ok2 && ok3 && ok4 + return +} + +func decodeHexUint16(src []byte) (value uint16, ok bool) { + var b1, b2 byte + var ok1, ok2 bool + b1, ok1 = decodeHexByte(src[0], src[1]) + b2, ok2 = decodeHexByte(src[2], src[3]) + value = (uint16(b1) << 8) | uint16(b2) + ok = ok1 && ok2 + return +} + +func decodeHexByte64(s1 []byte, s2 []byte) (value [8]byte, ok bool) { + var ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8 bool + value[0], ok1 = decodeHexByte(s1[0], s1[1]) + value[1], ok2 = decodeHexByte(s1[2], s1[3]) + value[2], ok3 = decodeHexByte(s2[0], s2[1]) + value[3], ok4 = decodeHexByte(s2[2], s2[3]) + value[4], ok5 = decodeHexByte(s2[4], s2[5]) + value[5], ok6 = decodeHexByte(s2[6], s2[7]) + value[6], ok7 = decodeHexByte(s2[8], s2[9]) + value[7], ok8 = decodeHexByte(s2[10], s2[11]) + ok = ok1 && ok2 && ok3 && ok4 && ok5 && ok6 && ok7 && ok8 + return +} + +func decodeHexByte(c1, c2 byte) (value byte, ok bool) { + var n1, n2 byte + var ok1, ok2 bool + n1, ok1 = decodeHexChar(c1) + n2, ok2 = decodeHexChar(c2) + value = (n1 << 4) | n2 + ok = ok1 && ok2 + return +} + +func decodeHexChar(c byte) (byte, bool) { + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + + return 0, false +} + +// String converts the GUID to string form. It will adhere to this pattern: +// +// {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} +// +// If the GUID is nil, the string representation of an empty GUID is returned: +// +// {00000000-0000-0000-0000-000000000000} +func (guid *GUID) String() string { + if guid == nil { + return emptyGUID + } + + var c [38]byte + c[0] = '{' + putUint32Hex(c[1:9], guid.Data1) + c[9] = '-' + putUint16Hex(c[10:14], guid.Data2) + c[14] = '-' + putUint16Hex(c[15:19], guid.Data3) + c[19] = '-' + putByteHex(c[20:24], guid.Data4[0:2]) + c[24] = '-' + putByteHex(c[25:37], guid.Data4[2:8]) + c[37] = '}' + return string(c[:]) +} + +func putUint32Hex(b []byte, v uint32) { + b[0] = hextable[byte(v>>24)>>4] + b[1] = hextable[byte(v>>24)&0x0f] + b[2] = hextable[byte(v>>16)>>4] + b[3] = hextable[byte(v>>16)&0x0f] + b[4] = hextable[byte(v>>8)>>4] + b[5] = hextable[byte(v>>8)&0x0f] + b[6] = hextable[byte(v)>>4] + b[7] = hextable[byte(v)&0x0f] +} + +func putUint16Hex(b []byte, v uint16) { + b[0] = hextable[byte(v>>8)>>4] + b[1] = hextable[byte(v>>8)&0x0f] + b[2] = hextable[byte(v)>>4] + b[3] = hextable[byte(v)&0x0f] +} + +func putByteHex(dst, src []byte) { + for i := 0; i < len(src); i++ { + dst[i*2] = hextable[src[i]>>4] + dst[i*2+1] = hextable[src[i]&0x0f] + } +} + +// IsEqualGUID compares two GUID. +// +// Not constant time comparison. +func IsEqualGUID(guid1 *GUID, guid2 *GUID) bool { + return guid1.Data1 == guid2.Data1 && + guid1.Data2 == guid2.Data2 && + guid1.Data3 == guid2.Data3 && + guid1.Data4[0] == guid2.Data4[0] && + guid1.Data4[1] == guid2.Data4[1] && + guid1.Data4[2] == guid2.Data4[2] && + guid1.Data4[3] == guid2.Data4[3] && + guid1.Data4[4] == guid2.Data4[4] && + guid1.Data4[5] == guid2.Data4[5] && + guid1.Data4[6] == guid2.Data4[6] && + guid1.Data4[7] == guid2.Data4[7] +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go new file mode 100644 index 0000000000000000000000000000000000000000..9e6c49f41f0a8be057f93fa6ab9e67c57beb4755 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint.go @@ -0,0 +1,20 @@ +package ole + +import "unsafe" + +type IConnectionPoint struct { + IUnknown +} + +type IConnectionPointVtbl struct { + IUnknownVtbl + GetConnectionInterface uintptr + GetConnectionPointContainer uintptr + Advise uintptr + Unadvise uintptr + EnumConnections uintptr +} + +func (v *IConnectionPoint) VTable() *IConnectionPointVtbl { + return (*IConnectionPointVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go new file mode 100644 index 0000000000000000000000000000000000000000..5414dc3cd3bc3ea00399db79e4cd1537c5140fa0 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_func.go @@ -0,0 +1,21 @@ +// +build !windows + +package ole + +import "unsafe" + +func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { + return int32(0) +} + +func (v *IConnectionPoint) Advise(unknown *IUnknown) (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} + +func (v *IConnectionPoint) Unadvise(cookie uint32) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) (err error) { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..32bc183248d95007e58da48d5f78db86df54ebdc --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpoint_windows.go @@ -0,0 +1,43 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *IConnectionPoint) GetConnectionInterface(piid **GUID) int32 { + // XXX: This doesn't look like it does what it's supposed to + return release((*IUnknown)(unsafe.Pointer(v))) +} + +func (v *IConnectionPoint) Advise(unknown *IUnknown) (cookie uint32, err error) { + hr, _, _ := syscall.Syscall( + v.VTable().Advise, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(unknown)), + uintptr(unsafe.Pointer(&cookie))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (v *IConnectionPoint) Unadvise(cookie uint32) (err error) { + hr, _, _ := syscall.Syscall( + v.VTable().Unadvise, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(cookie), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (v *IConnectionPoint) EnumConnections(p *unsafe.Pointer) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go new file mode 100644 index 0000000000000000000000000000000000000000..165860d199e8c5ab2f275c181d5121a160322083 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer.go @@ -0,0 +1,17 @@ +package ole + +import "unsafe" + +type IConnectionPointContainer struct { + IUnknown +} + +type IConnectionPointContainerVtbl struct { + IUnknownVtbl + EnumConnectionPoints uintptr + FindConnectionPoint uintptr +} + +func (v *IConnectionPointContainer) VTable() *IConnectionPointContainerVtbl { + return (*IConnectionPointContainerVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go new file mode 100644 index 0000000000000000000000000000000000000000..5dfa42aaebb781d31b39d4babf0ef10f025b1b34 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_func.go @@ -0,0 +1,11 @@ +// +build !windows + +package ole + +func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..ad30d79efc4e654f8a42da50d361b90dfad66d4c --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iconnectionpointcontainer_windows.go @@ -0,0 +1,25 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *IConnectionPointContainer) EnumConnectionPoints(points interface{}) error { + return NewError(E_NOTIMPL) +} + +func (v *IConnectionPointContainer) FindConnectionPoint(iid *GUID, point **IConnectionPoint) (err error) { + hr, _, _ := syscall.Syscall( + v.VTable().FindConnectionPoint, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(point))) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch.go b/vendor/github.com/go-ole/go-ole/idispatch.go new file mode 100644 index 0000000000000000000000000000000000000000..d4af1240925ddd1560d47e9036741eb4a98d1647 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch.go @@ -0,0 +1,94 @@ +package ole + +import "unsafe" + +type IDispatch struct { + IUnknown +} + +type IDispatchVtbl struct { + IUnknownVtbl + GetTypeInfoCount uintptr + GetTypeInfo uintptr + GetIDsOfNames uintptr + Invoke uintptr +} + +func (v *IDispatch) VTable() *IDispatchVtbl { + return (*IDispatchVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IDispatch) GetIDsOfName(names []string) (dispid []int32, err error) { + dispid, err = getIDsOfName(v, names) + return +} + +func (v *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { + result, err = invoke(v, dispid, dispatch, params...) + return +} + +func (v *IDispatch) GetTypeInfoCount() (c uint32, err error) { + c, err = getTypeInfoCount(v) + return +} + +func (v *IDispatch) GetTypeInfo() (tinfo *ITypeInfo, err error) { + tinfo, err = getTypeInfo(v) + return +} + +// GetSingleIDOfName is a helper that returns single display ID for IDispatch name. +// +// This replaces the common pattern of attempting to get a single name from the list of available +// IDs. It gives the first ID, if it is available. +func (v *IDispatch) GetSingleIDOfName(name string) (displayID int32, err error) { + var displayIDs []int32 + displayIDs, err = v.GetIDsOfName([]string{name}) + if err != nil { + return + } + displayID = displayIDs[0] + return +} + +// InvokeWithOptionalArgs accepts arguments as an array, works like Invoke. +// +// Accepts name and will attempt to retrieve Display ID to pass to Invoke. +// +// Passing params as an array is a workaround that could be fixed in later versions of Go that +// prevent passing empty params. During testing it was discovered that this is an acceptable way of +// getting around not being able to pass params normally. +func (v *IDispatch) InvokeWithOptionalArgs(name string, dispatch int16, params []interface{}) (result *VARIANT, err error) { + displayID, err := v.GetSingleIDOfName(name) + if err != nil { + return + } + + if len(params) < 1 { + result, err = v.Invoke(displayID, dispatch) + } else { + result, err = v.Invoke(displayID, dispatch, params...) + } + + return +} + +// CallMethod invokes named function with arguments on object. +func (v *IDispatch) CallMethod(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_METHOD, params) +} + +// GetProperty retrieves the property with the name with the ability to pass arguments. +// +// Most of the time you will not need to pass arguments as most objects do not allow for this +// feature. Or at least, should not allow for this feature. Some servers don't follow best practices +// and this is provided for those edge cases. +func (v *IDispatch) GetProperty(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYGET, params) +} + +// PutProperty attempts to mutate a property in the object. +func (v *IDispatch) PutProperty(name string, params ...interface{}) (*VARIANT, error) { + return v.InvokeWithOptionalArgs(name, DISPATCH_PROPERTYPUT, params) +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_func.go b/vendor/github.com/go-ole/go-ole/idispatch_func.go new file mode 100644 index 0000000000000000000000000000000000000000..b8fbbe319f1acc4dbf104f208e724524b7c1b225 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func getIDsOfName(disp *IDispatch, names []string) ([]int32, error) { + return []int32{}, NewError(E_NOTIMPL) +} + +func getTypeInfoCount(disp *IDispatch) (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} + +func getTypeInfo(disp *IDispatch) (*ITypeInfo, error) { + return nil, NewError(E_NOTIMPL) +} + +func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (*VARIANT, error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/idispatch_windows.go b/vendor/github.com/go-ole/go-ole/idispatch_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..6ec180b55fd57e62dc92eee113fe9ccc73ff9f6e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/idispatch_windows.go @@ -0,0 +1,200 @@ +// +build windows + +package ole + +import ( + "math/big" + "syscall" + "time" + "unsafe" +) + +func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) { + wnames := make([]*uint16, len(names)) + for i := 0; i < len(names); i++ { + wnames[i] = syscall.StringToUTF16Ptr(names[i]) + } + dispid = make([]int32, len(names)) + namelen := uint32(len(names)) + hr, _, _ := syscall.Syscall6( + disp.VTable().GetIDsOfNames, + 6, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(unsafe.Pointer(&wnames[0])), + uintptr(namelen), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&dispid[0]))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func getTypeInfoCount(disp *IDispatch) (c uint32, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetTypeInfoCount, + 2, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(&c)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetTypeInfo, + 3, + uintptr(unsafe.Pointer(disp)), + uintptr(GetUserDefaultLCID()), + uintptr(unsafe.Pointer(&tinfo))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) { + var dispparams DISPPARAMS + + if dispatch&DISPATCH_PROPERTYPUT != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.cNamedArgs = 1 + } else if dispatch&DISPATCH_PROPERTYPUTREF != 0 { + dispnames := [1]int32{DISPID_PROPERTYPUT} + dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) + dispparams.cNamedArgs = 1 + } + var vargs []VARIANT + if len(params) > 0 { + vargs = make([]VARIANT, len(params)) + for i, v := range params { + //n := len(params)-i-1 + n := len(params) - i - 1 + VariantInit(&vargs[n]) + switch vv := v.(type) { + case bool: + if vv { + vargs[n] = NewVariant(VT_BOOL, 0xffff) + } else { + vargs[n] = NewVariant(VT_BOOL, 0) + } + case *bool: + vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool))))) + case uint8: + vargs[n] = NewVariant(VT_I1, int64(v.(uint8))) + case *uint8: + vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) + case int8: + vargs[n] = NewVariant(VT_I1, int64(v.(int8))) + case *int8: + vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8))))) + case int16: + vargs[n] = NewVariant(VT_I2, int64(v.(int16))) + case *int16: + vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16))))) + case uint16: + vargs[n] = NewVariant(VT_UI2, int64(v.(uint16))) + case *uint16: + vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16))))) + case int32: + vargs[n] = NewVariant(VT_I4, int64(v.(int32))) + case *int32: + vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32))))) + case uint32: + vargs[n] = NewVariant(VT_UI4, int64(v.(uint32))) + case *uint32: + vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32))))) + case int64: + vargs[n] = NewVariant(VT_I8, int64(v.(int64))) + case *int64: + vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64))))) + case uint64: + vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64)))) + case *uint64: + vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64))))) + case int: + vargs[n] = NewVariant(VT_I4, int64(v.(int))) + case *int: + vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int))))) + case uint: + vargs[n] = NewVariant(VT_UI4, int64(v.(uint))) + case *uint: + vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint))))) + case float32: + vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv))) + case *float32: + vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32))))) + case float64: + vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv))) + case *float64: + vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64))))) + case *big.Int: + vargs[n] = NewVariant(VT_DECIMAL, v.(*big.Int).Int64()) + case string: + vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string)))))) + case *string: + vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string))))) + case time.Time: + s := vv.Format("2006-01-02 15:04:05") + vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s))))) + case *time.Time: + s := vv.Format("2006-01-02 15:04:05") + vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s)))) + case *IDispatch: + vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))) + case **IDispatch: + vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))) + case nil: + vargs[n] = NewVariant(VT_NULL, 0) + case *VARIANT: + vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))) + case []byte: + safeByteArray := safeArrayFromByteSlice(v.([]byte)) + vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray)))) + defer VariantClear(&vargs[n]) + case []string: + safeByteArray := safeArrayFromStringSlice(v.([]string)) + vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray)))) + defer VariantClear(&vargs[n]) + default: + panic("unknown type") + } + } + dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0])) + dispparams.cArgs = uint32(len(params)) + } + + result = new(VARIANT) + var excepInfo EXCEPINFO + VariantInit(result) + hr, _, _ := syscall.Syscall9( + disp.VTable().Invoke, + 9, + uintptr(unsafe.Pointer(disp)), + uintptr(dispid), + uintptr(unsafe.Pointer(IID_NULL)), + uintptr(GetUserDefaultLCID()), + uintptr(dispatch), + uintptr(unsafe.Pointer(&dispparams)), + uintptr(unsafe.Pointer(result)), + uintptr(unsafe.Pointer(&excepInfo)), + 0) + if hr != 0 { + err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo) + } + for i, varg := range vargs { + n := len(params) - i - 1 + if varg.VT == VT_BSTR && varg.Val != 0 { + SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) + } + if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 { + *(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val)))) + } + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant.go b/vendor/github.com/go-ole/go-ole/ienumvariant.go new file mode 100644 index 0000000000000000000000000000000000000000..243389754430088c0ed409fef39d7352aa3b712f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant.go @@ -0,0 +1,19 @@ +package ole + +import "unsafe" + +type IEnumVARIANT struct { + IUnknown +} + +type IEnumVARIANTVtbl struct { + IUnknownVtbl + Next uintptr + Skip uintptr + Reset uintptr + Clone uintptr +} + +func (v *IEnumVARIANT) VTable() *IEnumVARIANTVtbl { + return (*IEnumVARIANTVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_func.go b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go new file mode 100644 index 0000000000000000000000000000000000000000..c14848199cb8caad67e712888ad698f3ef4487d8 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func (enum *IEnumVARIANT) Clone() (*IEnumVARIANT, error) { + return nil, NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Reset() error { + return NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Skip(celt uint) error { + return NewError(E_NOTIMPL) +} + +func (enum *IEnumVARIANT) Next(celt uint) (VARIANT, uint, error) { + return NewVariant(VT_NULL, int64(0)), 0, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..4781f3b8b0075d3b0242fed2955672f333dbdd7f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ienumvariant_windows.go @@ -0,0 +1,63 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (enum *IEnumVARIANT) Clone() (cloned *IEnumVARIANT, err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Clone, + 2, + uintptr(unsafe.Pointer(enum)), + uintptr(unsafe.Pointer(&cloned)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Reset() (err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Reset, + 1, + uintptr(unsafe.Pointer(enum)), + 0, + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Skip(celt uint) (err error) { + hr, _, _ := syscall.Syscall( + enum.VTable().Skip, + 2, + uintptr(unsafe.Pointer(enum)), + uintptr(celt), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} + +func (enum *IEnumVARIANT) Next(celt uint) (array VARIANT, length uint, err error) { + hr, _, _ := syscall.Syscall6( + enum.VTable().Next, + 4, + uintptr(unsafe.Pointer(enum)), + uintptr(celt), + uintptr(unsafe.Pointer(&array)), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable.go b/vendor/github.com/go-ole/go-ole/iinspectable.go new file mode 100644 index 0000000000000000000000000000000000000000..f4a19e253af7da4a953d2c0c6929f594ec7e8194 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable.go @@ -0,0 +1,18 @@ +package ole + +import "unsafe" + +type IInspectable struct { + IUnknown +} + +type IInspectableVtbl struct { + IUnknownVtbl + GetIIds uintptr + GetRuntimeClassName uintptr + GetTrustLevel uintptr +} + +func (v *IInspectable) VTable() *IInspectableVtbl { + return (*IInspectableVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_func.go b/vendor/github.com/go-ole/go-ole/iinspectable_func.go new file mode 100644 index 0000000000000000000000000000000000000000..348829bf062fc023839347fcd4952f11eb7d0a85 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable_func.go @@ -0,0 +1,15 @@ +// +build !windows + +package ole + +func (v *IInspectable) GetIids() ([]*GUID, error) { + return []*GUID{}, NewError(E_NOTIMPL) +} + +func (v *IInspectable) GetRuntimeClassName() (string, error) { + return "", NewError(E_NOTIMPL) +} + +func (v *IInspectable) GetTrustLevel() (uint32, error) { + return uint32(0), NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iinspectable_windows.go b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..4519a4aa44951f0c94fd24b35dabfbc80e802180 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iinspectable_windows.go @@ -0,0 +1,72 @@ +// +build windows + +package ole + +import ( + "bytes" + "encoding/binary" + "reflect" + "syscall" + "unsafe" +) + +func (v *IInspectable) GetIids() (iids []*GUID, err error) { + var count uint32 + var array uintptr + hr, _, _ := syscall.Syscall( + v.VTable().GetIIds, + 3, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&count)), + uintptr(unsafe.Pointer(&array))) + if hr != 0 { + err = NewError(hr) + return + } + defer CoTaskMemFree(array) + + iids = make([]*GUID, count) + byteCount := count * uint32(unsafe.Sizeof(GUID{})) + slicehdr := reflect.SliceHeader{Data: array, Len: int(byteCount), Cap: int(byteCount)} + byteSlice := *(*[]byte)(unsafe.Pointer(&slicehdr)) + reader := bytes.NewReader(byteSlice) + for i := range iids { + guid := GUID{} + err = binary.Read(reader, binary.LittleEndian, &guid) + if err != nil { + return + } + iids[i] = &guid + } + return +} + +func (v *IInspectable) GetRuntimeClassName() (s string, err error) { + var hstring HString + hr, _, _ := syscall.Syscall( + v.VTable().GetRuntimeClassName, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&hstring)), + 0) + if hr != 0 { + err = NewError(hr) + return + } + s = hstring.String() + DeleteHString(hstring) + return +} + +func (v *IInspectable) GetTrustLevel() (level uint32, err error) { + hr, _, _ := syscall.Syscall( + v.VTable().GetTrustLevel, + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&level)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go new file mode 100644 index 0000000000000000000000000000000000000000..25f3a6f24a9196e5bf83e2a4491ea140f99f553f --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo.go @@ -0,0 +1,21 @@ +package ole + +import "unsafe" + +type IProvideClassInfo struct { + IUnknown +} + +type IProvideClassInfoVtbl struct { + IUnknownVtbl + GetClassInfo uintptr +} + +func (v *IProvideClassInfo) VTable() *IProvideClassInfoVtbl { + return (*IProvideClassInfoVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IProvideClassInfo) GetClassInfo() (cinfo *ITypeInfo, err error) { + cinfo, err = getClassInfo(v) + return +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go new file mode 100644 index 0000000000000000000000000000000000000000..7e3cb63ea7394353898d1ec2cce0134e414177e3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_func.go @@ -0,0 +1,7 @@ +// +build !windows + +package ole + +func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..2ad0163949746555f65551ee12754be99a1d388d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iprovideclassinfo_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func getClassInfo(disp *IProvideClassInfo) (tinfo *ITypeInfo, err error) { + hr, _, _ := syscall.Syscall( + disp.VTable().GetClassInfo, + 2, + uintptr(unsafe.Pointer(disp)), + uintptr(unsafe.Pointer(&tinfo)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo.go b/vendor/github.com/go-ole/go-ole/itypeinfo.go new file mode 100644 index 0000000000000000000000000000000000000000..dd3c5e21bbf31702b34e54ce5fd7e20ac7f65488 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo.go @@ -0,0 +1,34 @@ +package ole + +import "unsafe" + +type ITypeInfo struct { + IUnknown +} + +type ITypeInfoVtbl struct { + IUnknownVtbl + GetTypeAttr uintptr + GetTypeComp uintptr + GetFuncDesc uintptr + GetVarDesc uintptr + GetNames uintptr + GetRefTypeOfImplType uintptr + GetImplTypeFlags uintptr + GetIDsOfNames uintptr + Invoke uintptr + GetDocumentation uintptr + GetDllEntry uintptr + GetRefTypeInfo uintptr + AddressOfMember uintptr + CreateInstance uintptr + GetMops uintptr + GetContainingTypeLib uintptr + ReleaseTypeAttr uintptr + ReleaseFuncDesc uintptr + ReleaseVarDesc uintptr +} + +func (v *ITypeInfo) VTable() *ITypeInfoVtbl { + return (*ITypeInfoVtbl)(unsafe.Pointer(v.RawVTable)) +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_func.go b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go new file mode 100644 index 0000000000000000000000000000000000000000..8364a659bae1dbc23e86307811efa1f00d030621 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo_func.go @@ -0,0 +1,7 @@ +// +build !windows + +package ole + +func (v *ITypeInfo) GetTypeAttr() (*TYPEATTR, error) { + return nil, NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..54782b3da5dd529b5cca3fcc416fef5a3e85e2b2 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/itypeinfo_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package ole + +import ( + "syscall" + "unsafe" +) + +func (v *ITypeInfo) GetTypeAttr() (tattr *TYPEATTR, err error) { + hr, _, _ := syscall.Syscall( + uintptr(v.VTable().GetTypeAttr), + 2, + uintptr(unsafe.Pointer(v)), + uintptr(unsafe.Pointer(&tattr)), + 0) + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown.go b/vendor/github.com/go-ole/go-ole/iunknown.go new file mode 100644 index 0000000000000000000000000000000000000000..108f28ea61084955e91d756fccc4972362d70bc1 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown.go @@ -0,0 +1,57 @@ +package ole + +import "unsafe" + +type IUnknown struct { + RawVTable *interface{} +} + +type IUnknownVtbl struct { + QueryInterface uintptr + AddRef uintptr + Release uintptr +} + +type UnknownLike interface { + QueryInterface(iid *GUID) (disp *IDispatch, err error) + AddRef() int32 + Release() int32 +} + +func (v *IUnknown) VTable() *IUnknownVtbl { + return (*IUnknownVtbl)(unsafe.Pointer(v.RawVTable)) +} + +func (v *IUnknown) PutQueryInterface(interfaceID *GUID, obj interface{}) error { + return reflectQueryInterface(v, v.VTable().QueryInterface, interfaceID, obj) +} + +func (v *IUnknown) IDispatch(interfaceID *GUID) (dispatch *IDispatch, err error) { + err = v.PutQueryInterface(interfaceID, &dispatch) + return +} + +func (v *IUnknown) IEnumVARIANT(interfaceID *GUID) (enum *IEnumVARIANT, err error) { + err = v.PutQueryInterface(interfaceID, &enum) + return +} + +func (v *IUnknown) QueryInterface(iid *GUID) (*IDispatch, error) { + return queryInterface(v, iid) +} + +func (v *IUnknown) MustQueryInterface(iid *GUID) (disp *IDispatch) { + unk, err := queryInterface(v, iid) + if err != nil { + panic(err) + } + return unk +} + +func (v *IUnknown) AddRef() int32 { + return addRef(v) +} + +func (v *IUnknown) Release() int32 { + return release(v) +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_func.go b/vendor/github.com/go-ole/go-ole/iunknown_func.go new file mode 100644 index 0000000000000000000000000000000000000000..d0a62cfd730271cb4cad108cb53fd2253b409cb4 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown_func.go @@ -0,0 +1,19 @@ +// +build !windows + +package ole + +func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { + return NewError(E_NOTIMPL) +} + +func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { + return nil, NewError(E_NOTIMPL) +} + +func addRef(unk *IUnknown) int32 { + return 0 +} + +func release(unk *IUnknown) int32 { + return 0 +} diff --git a/vendor/github.com/go-ole/go-ole/iunknown_windows.go b/vendor/github.com/go-ole/go-ole/iunknown_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..ede5bb8c173227a53523571bb05c8c2f7ce728bf --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/iunknown_windows.go @@ -0,0 +1,58 @@ +// +build windows + +package ole + +import ( + "reflect" + "syscall" + "unsafe" +) + +func reflectQueryInterface(self interface{}, method uintptr, interfaceID *GUID, obj interface{}) (err error) { + selfValue := reflect.ValueOf(self).Elem() + objValue := reflect.ValueOf(obj).Elem() + + hr, _, _ := syscall.Syscall( + method, + 3, + selfValue.UnsafeAddr(), + uintptr(unsafe.Pointer(interfaceID)), + objValue.Addr().Pointer()) + if hr != 0 { + err = NewError(hr) + } + return +} + +func queryInterface(unk *IUnknown, iid *GUID) (disp *IDispatch, err error) { + hr, _, _ := syscall.Syscall( + unk.VTable().QueryInterface, + 3, + uintptr(unsafe.Pointer(unk)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&disp))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func addRef(unk *IUnknown) int32 { + ret, _, _ := syscall.Syscall( + unk.VTable().AddRef, + 1, + uintptr(unsafe.Pointer(unk)), + 0, + 0) + return int32(ret) +} + +func release(unk *IUnknown) int32 { + ret, _, _ := syscall.Syscall( + unk.VTable().Release, + 1, + uintptr(unsafe.Pointer(unk)), + 0, + 0) + return int32(ret) +} diff --git a/vendor/github.com/go-ole/go-ole/ole.go b/vendor/github.com/go-ole/go-ole/ole.go new file mode 100644 index 0000000000000000000000000000000000000000..e2ae4f4bbfeb55d009cd4eef2f5ebe348452a5f9 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/ole.go @@ -0,0 +1,157 @@ +package ole + +import ( + "fmt" + "strings" +) + +// DISPPARAMS are the arguments that passed to methods or property. +type DISPPARAMS struct { + rgvarg uintptr + rgdispidNamedArgs uintptr + cArgs uint32 + cNamedArgs uint32 +} + +// EXCEPINFO defines exception info. +type EXCEPINFO struct { + wCode uint16 + wReserved uint16 + bstrSource *uint16 + bstrDescription *uint16 + bstrHelpFile *uint16 + dwHelpContext uint32 + pvReserved uintptr + pfnDeferredFillIn uintptr + scode uint32 +} + +// WCode return wCode in EXCEPINFO. +func (e EXCEPINFO) WCode() uint16 { + return e.wCode +} + +// SCODE return scode in EXCEPINFO. +func (e EXCEPINFO) SCODE() uint32 { + return e.scode +} + +// String convert EXCEPINFO to string. +func (e EXCEPINFO) String() string { + var src, desc, hlp string + if e.bstrSource == nil { + src = "" + } else { + src = BstrToString(e.bstrSource) + } + + if e.bstrDescription == nil { + desc = "" + } else { + desc = BstrToString(e.bstrDescription) + } + + if e.bstrHelpFile == nil { + hlp = "" + } else { + hlp = BstrToString(e.bstrHelpFile) + } + + return fmt.Sprintf( + "wCode: %#x, bstrSource: %v, bstrDescription: %v, bstrHelpFile: %v, dwHelpContext: %#x, scode: %#x", + e.wCode, src, desc, hlp, e.dwHelpContext, e.scode, + ) +} + +// Error implements error interface and returns error string. +func (e EXCEPINFO) Error() string { + if e.bstrDescription != nil { + return strings.TrimSpace(BstrToString(e.bstrDescription)) + } + + src := "Unknown" + if e.bstrSource != nil { + src = BstrToString(e.bstrSource) + } + + code := e.scode + if e.wCode != 0 { + code = uint32(e.wCode) + } + + return fmt.Sprintf("%v: %#x", src, code) +} + +// PARAMDATA defines parameter data type. +type PARAMDATA struct { + Name *int16 + Vt uint16 +} + +// METHODDATA defines method info. +type METHODDATA struct { + Name *uint16 + Data *PARAMDATA + Dispid int32 + Meth uint32 + CC int32 + CArgs uint32 + Flags uint16 + VtReturn uint32 +} + +// INTERFACEDATA defines interface info. +type INTERFACEDATA struct { + MethodData *METHODDATA + CMembers uint32 +} + +// Point is 2D vector type. +type Point struct { + X int32 + Y int32 +} + +// Msg is message between processes. +type Msg struct { + Hwnd uint32 + Message uint32 + Wparam int32 + Lparam int32 + Time uint32 + Pt Point +} + +// TYPEDESC defines data type. +type TYPEDESC struct { + Hreftype uint32 + VT uint16 +} + +// IDLDESC defines IDL info. +type IDLDESC struct { + DwReserved uint32 + WIDLFlags uint16 +} + +// TYPEATTR defines type info. +type TYPEATTR struct { + Guid GUID + Lcid uint32 + dwReserved uint32 + MemidConstructor int32 + MemidDestructor int32 + LpstrSchema *uint16 + CbSizeInstance uint32 + Typekind int32 + CFuncs uint16 + CVars uint16 + CImplTypes uint16 + CbSizeVft uint16 + CbAlignment uint16 + WTypeFlags uint16 + WMajorVerNum uint16 + WMinorVerNum uint16 + TdescAlias TYPEDESC + IdldescType IDLDESC +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection.go b/vendor/github.com/go-ole/go-ole/oleutil/connection.go new file mode 100644 index 0000000000000000000000000000000000000000..60df73cda00142942e3d864153b2f628c604ad35 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection.go @@ -0,0 +1,100 @@ +// +build windows + +package oleutil + +import ( + "reflect" + "unsafe" + + ole "github.com/go-ole/go-ole" +) + +type stdDispatch struct { + lpVtbl *stdDispatchVtbl + ref int32 + iid *ole.GUID + iface interface{} + funcMap map[string]int32 +} + +type stdDispatchVtbl struct { + pQueryInterface uintptr + pAddRef uintptr + pRelease uintptr + pGetTypeInfoCount uintptr + pGetTypeInfo uintptr + pGetIDsOfNames uintptr + pInvoke uintptr +} + +func dispQueryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uint32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + *punk = nil + if ole.IsEqualGUID(iid, ole.IID_IUnknown) || + ole.IsEqualGUID(iid, ole.IID_IDispatch) { + dispAddRef(this) + *punk = this + return ole.S_OK + } + if ole.IsEqualGUID(iid, pthis.iid) { + dispAddRef(this) + *punk = this + return ole.S_OK + } + return ole.E_NOINTERFACE +} + +func dispAddRef(this *ole.IUnknown) int32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + pthis.ref++ + return pthis.ref +} + +func dispRelease(this *ole.IUnknown) int32 { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + pthis.ref-- + return pthis.ref +} + +func dispGetIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames []*uint16, namelen int, lcid int, pdisp []int32) uintptr { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + names := make([]string, len(wnames)) + for i := 0; i < len(names); i++ { + names[i] = ole.LpOleStrToString(wnames[i]) + } + for n := 0; n < namelen; n++ { + if id, ok := pthis.funcMap[names[n]]; ok { + pdisp[n] = id + } + } + return ole.S_OK +} + +func dispGetTypeInfoCount(pcount *int) uintptr { + if pcount != nil { + *pcount = 0 + } + return ole.S_OK +} + +func dispGetTypeInfo(ptypeif *uintptr) uintptr { + return ole.E_NOTIMPL +} + +func dispInvoke(this *ole.IDispatch, dispid int32, riid *ole.GUID, lcid int, flags int16, dispparams *ole.DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr { + pthis := (*stdDispatch)(unsafe.Pointer(this)) + found := "" + for name, id := range pthis.funcMap { + if id == dispid { + found = name + } + } + if found != "" { + rv := reflect.ValueOf(pthis.iface).Elem() + rm := rv.MethodByName(found) + rr := rm.Call([]reflect.Value{}) + println(len(rr)) + return ole.S_OK + } + return ole.E_NOTIMPL +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go new file mode 100644 index 0000000000000000000000000000000000000000..8818fb8275ad261cd45f339e4aac656de3a1721e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_func.go @@ -0,0 +1,10 @@ +// +build !windows + +package oleutil + +import ole "github.com/go-ole/go-ole" + +// ConnectObject creates a connection point between two services for communication. +func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (uint32, error) { + return 0, ole.NewError(ole.E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..ab9c0d8dcbd4f9a07a17412b718d6d90349e73c2 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/connection_windows.go @@ -0,0 +1,58 @@ +// +build windows + +package oleutil + +import ( + "reflect" + "syscall" + "unsafe" + + ole "github.com/go-ole/go-ole" +) + +// ConnectObject creates a connection point between two services for communication. +func ConnectObject(disp *ole.IDispatch, iid *ole.GUID, idisp interface{}) (cookie uint32, err error) { + unknown, err := disp.QueryInterface(ole.IID_IConnectionPointContainer) + if err != nil { + return + } + + container := (*ole.IConnectionPointContainer)(unsafe.Pointer(unknown)) + var point *ole.IConnectionPoint + err = container.FindConnectionPoint(iid, &point) + if err != nil { + return + } + if edisp, ok := idisp.(*ole.IUnknown); ok { + cookie, err = point.Advise(edisp) + container.Release() + if err != nil { + return + } + } + rv := reflect.ValueOf(disp).Elem() + if rv.Type().Kind() == reflect.Struct { + dest := &stdDispatch{} + dest.lpVtbl = &stdDispatchVtbl{} + dest.lpVtbl.pQueryInterface = syscall.NewCallback(dispQueryInterface) + dest.lpVtbl.pAddRef = syscall.NewCallback(dispAddRef) + dest.lpVtbl.pRelease = syscall.NewCallback(dispRelease) + dest.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(dispGetTypeInfoCount) + dest.lpVtbl.pGetTypeInfo = syscall.NewCallback(dispGetTypeInfo) + dest.lpVtbl.pGetIDsOfNames = syscall.NewCallback(dispGetIDsOfNames) + dest.lpVtbl.pInvoke = syscall.NewCallback(dispInvoke) + dest.iface = disp + dest.iid = iid + cookie, err = point.Advise((*ole.IUnknown)(unsafe.Pointer(dest))) + container.Release() + if err != nil { + point.Release() + return + } + return + } + + container.Release() + + return 0, ole.NewError(ole.E_INVALIDARG) +} diff --git a/vendor/github.com/go-ole/go-ole/oleutil/go-get.go b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go new file mode 100644 index 0000000000000000000000000000000000000000..58347628f24c63c92c2c68fe7c780184dde255c6 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/go-get.go @@ -0,0 +1,6 @@ +// This file is here so go get succeeds as without it errors with: +// no buildable Go source files in ... +// +// +build !windows + +package oleutil diff --git a/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go new file mode 100644 index 0000000000000000000000000000000000000000..f7803c1e30f24d28bcc716f3b6656d27f9ac576e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/oleutil/oleutil.go @@ -0,0 +1,127 @@ +package oleutil + +import ole "github.com/go-ole/go-ole" + +// ClassIDFrom retrieves class ID whether given is program ID or application string. +func ClassIDFrom(programID string) (classID *ole.GUID, err error) { + return ole.ClassIDFrom(programID) +} + +// CreateObject creates object from programID based on interface type. +// +// Only supports IUnknown. +// +// Program ID can be either program ID or application string. +func CreateObject(programID string) (unknown *ole.IUnknown, err error) { + classID, err := ole.ClassIDFrom(programID) + if err != nil { + return + } + + unknown, err = ole.CreateInstance(classID, ole.IID_IUnknown) + if err != nil { + return + } + + return +} + +// GetActiveObject retrieves active object for program ID and interface ID based +// on interface type. +// +// Only supports IUnknown. +// +// Program ID can be either program ID or application string. +func GetActiveObject(programID string) (unknown *ole.IUnknown, err error) { + classID, err := ole.ClassIDFrom(programID) + if err != nil { + return + } + + unknown, err = ole.GetActiveObject(classID, ole.IID_IUnknown) + if err != nil { + return + } + + return +} + +// CallMethod calls method on IDispatch with parameters. +func CallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_METHOD, params) +} + +// MustCallMethod calls method on IDispatch with parameters or panics. +func MustCallMethod(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := CallMethod(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// GetProperty retrieves property from IDispatch. +func GetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYGET, params) +} + +// MustGetProperty retrieves property from IDispatch or panics. +func MustGetProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := GetProperty(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// PutProperty mutates property. +func PutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUT, params) +} + +// MustPutProperty mutates property or panics. +func MustPutProperty(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := PutProperty(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +// PutPropertyRef mutates property reference. +func PutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT, err error) { + return disp.InvokeWithOptionalArgs(name, ole.DISPATCH_PROPERTYPUTREF, params) +} + +// MustPutPropertyRef mutates property reference or panics. +func MustPutPropertyRef(disp *ole.IDispatch, name string, params ...interface{}) (result *ole.VARIANT) { + r, err := PutPropertyRef(disp, name, params...) + if err != nil { + panic(err.Error()) + } + return r +} + +func ForEach(disp *ole.IDispatch, f func(v *ole.VARIANT) error) error { + newEnum, err := disp.GetProperty("_NewEnum") + if err != nil { + return err + } + defer newEnum.Clear() + + enum, err := newEnum.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + defer enum.Release() + + for item, length, err := enum.Next(1); length > 0; item, length, err = enum.Next(1) { + if err != nil { + return err + } + if ferr := f(&item); ferr != nil { + return ferr + } + } + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/safearray.go b/vendor/github.com/go-ole/go-ole/safearray.go new file mode 100644 index 0000000000000000000000000000000000000000..a5201b56c3d9015a7d34b11a646248215cf7b273 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray.go @@ -0,0 +1,27 @@ +// Package is meant to retrieve and process safe array data returned from COM. + +package ole + +// SafeArrayBound defines the SafeArray boundaries. +type SafeArrayBound struct { + Elements uint32 + LowerBound int32 +} + +// SafeArray is how COM handles arrays. +type SafeArray struct { + Dimensions uint16 + FeaturesFlag uint16 + ElementsSize uint32 + LocksAmount uint32 + Data uint32 + Bounds [16]byte +} + +// SAFEARRAY is obsolete, exists for backwards compatibility. +// Use SafeArray +type SAFEARRAY SafeArray + +// SAFEARRAYBOUND is obsolete, exists for backwards compatibility. +// Use SafeArrayBound +type SAFEARRAYBOUND SafeArrayBound diff --git a/vendor/github.com/go-ole/go-ole/safearray_func.go b/vendor/github.com/go-ole/go-ole/safearray_func.go new file mode 100644 index 0000000000000000000000000000000000000000..8ff0baa41dddd5e1b44768d71db7d74e02114f7d --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray_func.go @@ -0,0 +1,211 @@ +// +build !windows + +package ole + +import ( + "unsafe" +) + +// safeArrayAccessData returns raw array pointer. +// +// AKA: SafeArrayAccessData in Windows API. +func safeArrayAccessData(safearray *SafeArray) (uintptr, error) { + return uintptr(0), NewError(E_NOTIMPL) +} + +// safeArrayUnaccessData releases raw array. +// +// AKA: SafeArrayUnaccessData in Windows API. +func safeArrayUnaccessData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayAllocData allocates SafeArray. +// +// AKA: SafeArrayAllocData in Windows API. +func safeArrayAllocData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayAllocDescriptor allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptor in Windows API. +func safeArrayAllocDescriptor(dimensions uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayAllocDescriptorEx allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptorEx in Windows API. +func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCopy returns copy of SafeArray. +// +// AKA: SafeArrayCopy in Windows API. +func safeArrayCopy(original *SafeArray) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCopyData duplicates SafeArray into another SafeArray object. +// +// AKA: SafeArrayCopyData in Windows API. +func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayCreate creates SafeArray. +// +// AKA: SafeArrayCreate in Windows API. +func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateEx creates SafeArray. +// +// AKA: SafeArrayCreateEx in Windows API. +func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateVector creates SafeArray. +// +// AKA: SafeArrayCreateVector in Windows API. +func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayCreateVectorEx creates SafeArray. +// +// AKA: SafeArrayCreateVectorEx in Windows API. +func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (*SafeArray, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayDestroy destroys SafeArray object. +// +// AKA: SafeArrayDestroy in Windows API. +func safeArrayDestroy(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayDestroyData destroys SafeArray object. +// +// AKA: SafeArrayDestroyData in Windows API. +func safeArrayDestroyData(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayDestroyDescriptor destroys SafeArray object. +// +// AKA: SafeArrayDestroyDescriptor in Windows API. +func safeArrayDestroyDescriptor(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetDim is the amount of dimensions in the SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetDim in Windows API. +func safeArrayGetDim(safearray *SafeArray) (*uint32, error) { + u := uint32(0) + return &u, NewError(E_NOTIMPL) +} + +// safeArrayGetElementSize is the element size in bytes. +// +// AKA: SafeArrayGetElemsize in Windows API. +func safeArrayGetElementSize(safearray *SafeArray) (*uint32, error) { + u := uint32(0) + return &u, NewError(E_NOTIMPL) +} + +// safeArrayGetElement retrieves element at given index. +func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetElement retrieves element at given index and converts to string. +func safeArrayGetElementString(safearray *SafeArray, index int64) (string, error) { + return "", NewError(E_NOTIMPL) +} + +// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. +// +// AKA: SafeArrayGetIID in Windows API. +func safeArrayGetIID(safearray *SafeArray) (*GUID, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArrayGetLBound returns lower bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetLBound in Windows API. +func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (int64, error) { + return int64(0), NewError(E_NOTIMPL) +} + +// safeArrayGetUBound returns upper bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetUBound in Windows API. +func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (int64, error) { + return int64(0), NewError(E_NOTIMPL) +} + +// safeArrayGetVartype returns data type of SafeArray. +// +// AKA: SafeArrayGetVartype in Windows API. +func safeArrayGetVartype(safearray *SafeArray) (uint16, error) { + return uint16(0), NewError(E_NOTIMPL) +} + +// safeArrayLock locks SafeArray for reading to modify SafeArray. +// +// This must be called during some calls to ensure that another process does not +// read or write to the SafeArray during editing. +// +// AKA: SafeArrayLock in Windows API. +func safeArrayLock(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayUnlock unlocks SafeArray for reading. +// +// AKA: SafeArrayUnlock in Windows API. +func safeArrayUnlock(safearray *SafeArray) error { + return NewError(E_NOTIMPL) +} + +// safeArrayPutElement stores the data element at the specified location in the +// array. +// +// AKA: SafeArrayPutElement in Windows API. +func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) error { + return NewError(E_NOTIMPL) +} + +// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. +// +// AKA: SafeArrayGetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArrayGetRecordInfo(safearray *SafeArray) (interface{}, error) { + return nil, NewError(E_NOTIMPL) +} + +// safeArraySetRecordInfo mutates IRecordInfo info for custom types. +// +// AKA: SafeArraySetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) error { + return NewError(E_NOTIMPL) +} diff --git a/vendor/github.com/go-ole/go-ole/safearray_windows.go b/vendor/github.com/go-ole/go-ole/safearray_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..b27936e24ed0126de9cb8c2f2ba097cb6ccbc3fd --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearray_windows.go @@ -0,0 +1,337 @@ +// +build windows + +package ole + +import ( + "unsafe" +) + +var ( + procSafeArrayAccessData, _ = modoleaut32.FindProc("SafeArrayAccessData") + procSafeArrayAllocData, _ = modoleaut32.FindProc("SafeArrayAllocData") + procSafeArrayAllocDescriptor, _ = modoleaut32.FindProc("SafeArrayAllocDescriptor") + procSafeArrayAllocDescriptorEx, _ = modoleaut32.FindProc("SafeArrayAllocDescriptorEx") + procSafeArrayCopy, _ = modoleaut32.FindProc("SafeArrayCopy") + procSafeArrayCopyData, _ = modoleaut32.FindProc("SafeArrayCopyData") + procSafeArrayCreate, _ = modoleaut32.FindProc("SafeArrayCreate") + procSafeArrayCreateEx, _ = modoleaut32.FindProc("SafeArrayCreateEx") + procSafeArrayCreateVector, _ = modoleaut32.FindProc("SafeArrayCreateVector") + procSafeArrayCreateVectorEx, _ = modoleaut32.FindProc("SafeArrayCreateVectorEx") + procSafeArrayDestroy, _ = modoleaut32.FindProc("SafeArrayDestroy") + procSafeArrayDestroyData, _ = modoleaut32.FindProc("SafeArrayDestroyData") + procSafeArrayDestroyDescriptor, _ = modoleaut32.FindProc("SafeArrayDestroyDescriptor") + procSafeArrayGetDim, _ = modoleaut32.FindProc("SafeArrayGetDim") + procSafeArrayGetElement, _ = modoleaut32.FindProc("SafeArrayGetElement") + procSafeArrayGetElemsize, _ = modoleaut32.FindProc("SafeArrayGetElemsize") + procSafeArrayGetIID, _ = modoleaut32.FindProc("SafeArrayGetIID") + procSafeArrayGetLBound, _ = modoleaut32.FindProc("SafeArrayGetLBound") + procSafeArrayGetUBound, _ = modoleaut32.FindProc("SafeArrayGetUBound") + procSafeArrayGetVartype, _ = modoleaut32.FindProc("SafeArrayGetVartype") + procSafeArrayLock, _ = modoleaut32.FindProc("SafeArrayLock") + procSafeArrayPtrOfIndex, _ = modoleaut32.FindProc("SafeArrayPtrOfIndex") + procSafeArrayUnaccessData, _ = modoleaut32.FindProc("SafeArrayUnaccessData") + procSafeArrayUnlock, _ = modoleaut32.FindProc("SafeArrayUnlock") + procSafeArrayPutElement, _ = modoleaut32.FindProc("SafeArrayPutElement") + //procSafeArrayRedim, _ = modoleaut32.FindProc("SafeArrayRedim") // TODO + //procSafeArraySetIID, _ = modoleaut32.FindProc("SafeArraySetIID") // TODO + procSafeArrayGetRecordInfo, _ = modoleaut32.FindProc("SafeArrayGetRecordInfo") + procSafeArraySetRecordInfo, _ = modoleaut32.FindProc("SafeArraySetRecordInfo") +) + +// safeArrayAccessData returns raw array pointer. +// +// AKA: SafeArrayAccessData in Windows API. +// Todo: Test +func safeArrayAccessData(safearray *SafeArray) (element uintptr, err error) { + err = convertHresultToError( + procSafeArrayAccessData.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&element)))) + return +} + +// safeArrayUnaccessData releases raw array. +// +// AKA: SafeArrayUnaccessData in Windows API. +func safeArrayUnaccessData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayUnaccessData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayAllocData allocates SafeArray. +// +// AKA: SafeArrayAllocData in Windows API. +func safeArrayAllocData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayAllocData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayAllocDescriptor allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptor in Windows API. +func safeArrayAllocDescriptor(dimensions uint32) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayAllocDescriptor.Call(uintptr(dimensions), uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayAllocDescriptorEx allocates SafeArray. +// +// AKA: SafeArrayAllocDescriptorEx in Windows API. +func safeArrayAllocDescriptorEx(variantType VT, dimensions uint32) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayAllocDescriptorEx.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayCopy returns copy of SafeArray. +// +// AKA: SafeArrayCopy in Windows API. +func safeArrayCopy(original *SafeArray) (safearray *SafeArray, err error) { + err = convertHresultToError( + procSafeArrayCopy.Call( + uintptr(unsafe.Pointer(original)), + uintptr(unsafe.Pointer(&safearray)))) + return +} + +// safeArrayCopyData duplicates SafeArray into another SafeArray object. +// +// AKA: SafeArrayCopyData in Windows API. +func safeArrayCopyData(original *SafeArray, duplicate *SafeArray) (err error) { + err = convertHresultToError( + procSafeArrayCopyData.Call( + uintptr(unsafe.Pointer(original)), + uintptr(unsafe.Pointer(duplicate)))) + return +} + +// safeArrayCreate creates SafeArray. +// +// AKA: SafeArrayCreate in Windows API. +func safeArrayCreate(variantType VT, dimensions uint32, bounds *SafeArrayBound) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreate.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(bounds))) + safearray = (*SafeArray)(unsafe.Pointer(&sa)) + return +} + +// safeArrayCreateEx creates SafeArray. +// +// AKA: SafeArrayCreateEx in Windows API. +func safeArrayCreateEx(variantType VT, dimensions uint32, bounds *SafeArrayBound, extra uintptr) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateEx.Call( + uintptr(variantType), + uintptr(dimensions), + uintptr(unsafe.Pointer(bounds)), + extra) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayCreateVector creates SafeArray. +// +// AKA: SafeArrayCreateVector in Windows API. +func safeArrayCreateVector(variantType VT, lowerBound int32, length uint32) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateVector.Call( + uintptr(variantType), + uintptr(lowerBound), + uintptr(length)) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayCreateVectorEx creates SafeArray. +// +// AKA: SafeArrayCreateVectorEx in Windows API. +func safeArrayCreateVectorEx(variantType VT, lowerBound int32, length uint32, extra uintptr) (safearray *SafeArray, err error) { + sa, _, err := procSafeArrayCreateVectorEx.Call( + uintptr(variantType), + uintptr(lowerBound), + uintptr(length), + extra) + safearray = (*SafeArray)(unsafe.Pointer(sa)) + return +} + +// safeArrayDestroy destroys SafeArray object. +// +// AKA: SafeArrayDestroy in Windows API. +func safeArrayDestroy(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayDestroyData destroys SafeArray object. +// +// AKA: SafeArrayDestroyData in Windows API. +func safeArrayDestroyData(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroyData.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayDestroyDescriptor destroys SafeArray object. +// +// AKA: SafeArrayDestroyDescriptor in Windows API. +func safeArrayDestroyDescriptor(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayDestroyDescriptor.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayGetDim is the amount of dimensions in the SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetDim in Windows API. +func safeArrayGetDim(safearray *SafeArray) (dimensions *uint32, err error) { + l, _, err := procSafeArrayGetDim.Call(uintptr(unsafe.Pointer(safearray))) + dimensions = (*uint32)(unsafe.Pointer(l)) + return +} + +// safeArrayGetElementSize is the element size in bytes. +// +// AKA: SafeArrayGetElemsize in Windows API. +func safeArrayGetElementSize(safearray *SafeArray) (length *uint32, err error) { + l, _, err := procSafeArrayGetElemsize.Call(uintptr(unsafe.Pointer(safearray))) + length = (*uint32)(unsafe.Pointer(l)) + return +} + +// safeArrayGetElement retrieves element at given index. +func safeArrayGetElement(safearray *SafeArray, index int64, pv unsafe.Pointer) error { + return convertHresultToError( + procSafeArrayGetElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(pv))) +} + +// safeArrayGetElementString retrieves element at given index and converts to string. +func safeArrayGetElementString(safearray *SafeArray, index int64) (str string, err error) { + var element *int16 + err = convertHresultToError( + procSafeArrayGetElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(unsafe.Pointer(&element)))) + str = BstrToString(*(**uint16)(unsafe.Pointer(&element))) + SysFreeString(element) + return +} + +// safeArrayGetIID is the InterfaceID of the elements in the SafeArray. +// +// AKA: SafeArrayGetIID in Windows API. +func safeArrayGetIID(safearray *SafeArray) (guid *GUID, err error) { + err = convertHresultToError( + procSafeArrayGetIID.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&guid)))) + return +} + +// safeArrayGetLBound returns lower bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetLBound in Windows API. +func safeArrayGetLBound(safearray *SafeArray, dimension uint32) (lowerBound int64, err error) { + err = convertHresultToError( + procSafeArrayGetLBound.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(dimension), + uintptr(unsafe.Pointer(&lowerBound)))) + return +} + +// safeArrayGetUBound returns upper bounds of SafeArray. +// +// SafeArrays may have multiple dimensions. Meaning, it could be +// multidimensional array. +// +// AKA: SafeArrayGetUBound in Windows API. +func safeArrayGetUBound(safearray *SafeArray, dimension uint32) (upperBound int64, err error) { + err = convertHresultToError( + procSafeArrayGetUBound.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(dimension), + uintptr(unsafe.Pointer(&upperBound)))) + return +} + +// safeArrayGetVartype returns data type of SafeArray. +// +// AKA: SafeArrayGetVartype in Windows API. +func safeArrayGetVartype(safearray *SafeArray) (varType uint16, err error) { + err = convertHresultToError( + procSafeArrayGetVartype.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&varType)))) + return +} + +// safeArrayLock locks SafeArray for reading to modify SafeArray. +// +// This must be called during some calls to ensure that another process does not +// read or write to the SafeArray during editing. +// +// AKA: SafeArrayLock in Windows API. +func safeArrayLock(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayLock.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayUnlock unlocks SafeArray for reading. +// +// AKA: SafeArrayUnlock in Windows API. +func safeArrayUnlock(safearray *SafeArray) (err error) { + err = convertHresultToError(procSafeArrayUnlock.Call(uintptr(unsafe.Pointer(safearray)))) + return +} + +// safeArrayPutElement stores the data element at the specified location in the +// array. +// +// AKA: SafeArrayPutElement in Windows API. +func safeArrayPutElement(safearray *SafeArray, index int64, element uintptr) (err error) { + err = convertHresultToError( + procSafeArrayPutElement.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&index)), + uintptr(unsafe.Pointer(element)))) + return +} + +// safeArrayGetRecordInfo accesses IRecordInfo info for custom types. +// +// AKA: SafeArrayGetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArrayGetRecordInfo(safearray *SafeArray) (recordInfo interface{}, err error) { + err = convertHresultToError( + procSafeArrayGetRecordInfo.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&recordInfo)))) + return +} + +// safeArraySetRecordInfo mutates IRecordInfo info for custom types. +// +// AKA: SafeArraySetRecordInfo in Windows API. +// +// XXX: Must implement IRecordInfo interface for this to return. +func safeArraySetRecordInfo(safearray *SafeArray, recordInfo interface{}) (err error) { + err = convertHresultToError( + procSafeArraySetRecordInfo.Call( + uintptr(unsafe.Pointer(safearray)), + uintptr(unsafe.Pointer(&recordInfo)))) + return +} diff --git a/vendor/github.com/go-ole/go-ole/safearrayconversion.go b/vendor/github.com/go-ole/go-ole/safearrayconversion.go new file mode 100644 index 0000000000000000000000000000000000000000..ffeb2b97b020cca14d841c653c4d14f9d79f8dc3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearrayconversion.go @@ -0,0 +1,140 @@ +// Helper for converting SafeArray to array of objects. + +package ole + +import ( + "unsafe" +) + +type SafeArrayConversion struct { + Array *SafeArray +} + +func (sac *SafeArrayConversion) ToStringArray() (strings []string) { + totalElements, _ := sac.TotalElements(0) + strings = make([]string, totalElements) + + for i := int64(0); i < totalElements; i++ { + strings[int32(i)], _ = safeArrayGetElementString(sac.Array, i) + } + + return +} + +func (sac *SafeArrayConversion) ToByteArray() (bytes []byte) { + totalElements, _ := sac.TotalElements(0) + bytes = make([]byte, totalElements) + + for i := int64(0); i < totalElements; i++ { + safeArrayGetElement(sac.Array, i, unsafe.Pointer(&bytes[int32(i)])) + } + + return +} + +func (sac *SafeArrayConversion) ToValueArray() (values []interface{}) { + totalElements, _ := sac.TotalElements(0) + values = make([]interface{}, totalElements) + vt, _ := safeArrayGetVartype(sac.Array) + + for i := 0; i < int(totalElements); i++ { + switch VT(vt) { + case VT_BOOL: + var v bool + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I1: + var v int8 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I2: + var v int16 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I4: + var v int32 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_I8: + var v int64 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI1: + var v uint8 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI2: + var v uint16 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI4: + var v uint32 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_UI8: + var v uint64 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_R4: + var v float32 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_R8: + var v float64 + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_BSTR: + var v string + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v + case VT_VARIANT: + var v VARIANT + safeArrayGetElement(sac.Array, int64(i), unsafe.Pointer(&v)) + values[i] = v.Value() + default: + // TODO + } + } + + return +} + +func (sac *SafeArrayConversion) GetType() (varType uint16, err error) { + return safeArrayGetVartype(sac.Array) +} + +func (sac *SafeArrayConversion) GetDimensions() (dimensions *uint32, err error) { + return safeArrayGetDim(sac.Array) +} + +func (sac *SafeArrayConversion) GetSize() (length *uint32, err error) { + return safeArrayGetElementSize(sac.Array) +} + +func (sac *SafeArrayConversion) TotalElements(index uint32) (totalElements int64, err error) { + if index < 1 { + index = 1 + } + + // Get array bounds + var LowerBounds int64 + var UpperBounds int64 + + LowerBounds, err = safeArrayGetLBound(sac.Array, index) + if err != nil { + return + } + + UpperBounds, err = safeArrayGetUBound(sac.Array, index) + if err != nil { + return + } + + totalElements = UpperBounds - LowerBounds + 1 + return +} + +// Release Safe Array memory +func (sac *SafeArrayConversion) Release() { + safeArrayDestroy(sac.Array) +} diff --git a/vendor/github.com/go-ole/go-ole/safearrayslices.go b/vendor/github.com/go-ole/go-ole/safearrayslices.go new file mode 100644 index 0000000000000000000000000000000000000000..a9fa885f1d8142c31f5207e51ba8df14c5640b44 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/safearrayslices.go @@ -0,0 +1,33 @@ +// +build windows + +package ole + +import ( + "unsafe" +) + +func safeArrayFromByteSlice(slice []byte) *SafeArray { + array, _ := safeArrayCreateVector(VT_UI1, 0, uint32(len(slice))) + + if array == nil { + panic("Could not convert []byte to SAFEARRAY") + } + + for i, v := range slice { + safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(&v))) + } + return array +} + +func safeArrayFromStringSlice(slice []string) *SafeArray { + array, _ := safeArrayCreateVector(VT_BSTR, 0, uint32(len(slice))) + + if array == nil { + panic("Could not convert []string to SAFEARRAY") + } + // SysAllocStringLen(s) + for i, v := range slice { + safeArrayPutElement(array, int64(i), uintptr(unsafe.Pointer(SysAllocStringLen(v)))) + } + return array +} diff --git a/vendor/github.com/go-ole/go-ole/utility.go b/vendor/github.com/go-ole/go-ole/utility.go new file mode 100644 index 0000000000000000000000000000000000000000..99ee82dc345154650d9c1377c6075bab91055f10 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/utility.go @@ -0,0 +1,101 @@ +package ole + +import ( + "unicode/utf16" + "unsafe" +) + +// ClassIDFrom retrieves class ID whether given is program ID or application string. +// +// Helper that provides check against both Class ID from Program ID and Class ID from string. It is +// faster, if you know which you are using, to use the individual functions, but this will check +// against available functions for you. +func ClassIDFrom(programID string) (classID *GUID, err error) { + classID, err = CLSIDFromProgID(programID) + if err != nil { + classID, err = CLSIDFromString(programID) + if err != nil { + return + } + } + return +} + +// BytePtrToString converts byte pointer to a Go string. +func BytePtrToString(p *byte) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + +// UTF16PtrToString is alias for LpOleStrToString. +// +// Kept for compatibility reasons. +func UTF16PtrToString(p *uint16) string { + return LpOleStrToString(p) +} + +// LpOleStrToString converts COM Unicode to Go string. +func LpOleStrToString(p *uint16) string { + if p == nil { + return "" + } + + length := lpOleStrLen(p) + a := make([]uint16, length) + + ptr := unsafe.Pointer(p) + + for i := 0; i < int(length); i++ { + a[i] = *(*uint16)(ptr) + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + + return string(utf16.Decode(a)) +} + +// BstrToString converts COM binary string to Go string. +func BstrToString(p *uint16) string { + if p == nil { + return "" + } + length := SysStringLen((*int16)(unsafe.Pointer(p))) + a := make([]uint16, length) + + ptr := unsafe.Pointer(p) + + for i := 0; i < int(length); i++ { + a[i] = *(*uint16)(ptr) + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + return string(utf16.Decode(a)) +} + +// lpOleStrLen returns the length of Unicode string. +func lpOleStrLen(p *uint16) (length int64) { + if p == nil { + return 0 + } + + ptr := unsafe.Pointer(p) + + for i := 0; ; i++ { + if 0 == *(*uint16)(ptr) { + length = int64(i) + break + } + ptr = unsafe.Pointer(uintptr(ptr) + 2) + } + return +} + +// convertHresultToError converts syscall to error, if call is unsuccessful. +func convertHresultToError(hr uintptr, r2 uintptr, ignore error) (err error) { + if hr != 0 { + err = NewError(hr) + } + return +} diff --git a/vendor/github.com/go-ole/go-ole/variables.go b/vendor/github.com/go-ole/go-ole/variables.go new file mode 100644 index 0000000000000000000000000000000000000000..ebe00f1cfc9b73638ae76a496cdc4221b5055f72 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variables.go @@ -0,0 +1,16 @@ +// +build windows + +package ole + +import ( + "syscall" +) + +var ( + modcombase = syscall.NewLazyDLL("combase.dll") + modkernel32, _ = syscall.LoadDLL("kernel32.dll") + modole32, _ = syscall.LoadDLL("ole32.dll") + modoleaut32, _ = syscall.LoadDLL("oleaut32.dll") + modmsvcrt, _ = syscall.LoadDLL("msvcrt.dll") + moduser32, _ = syscall.LoadDLL("user32.dll") +) diff --git a/vendor/github.com/go-ole/go-ole/variant.go b/vendor/github.com/go-ole/go-ole/variant.go new file mode 100644 index 0000000000000000000000000000000000000000..967a23fea9abad16229811bf99659099747651cc --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant.go @@ -0,0 +1,105 @@ +package ole + +import "unsafe" + +// NewVariant returns new variant based on type and value. +func NewVariant(vt VT, val int64) VARIANT { + return VARIANT{VT: vt, Val: val} +} + +// ToIUnknown converts Variant to Unknown object. +func (v *VARIANT) ToIUnknown() *IUnknown { + if v.VT != VT_UNKNOWN { + return nil + } + return (*IUnknown)(unsafe.Pointer(uintptr(v.Val))) +} + +// ToIDispatch converts variant to dispatch object. +func (v *VARIANT) ToIDispatch() *IDispatch { + if v.VT != VT_DISPATCH { + return nil + } + return (*IDispatch)(unsafe.Pointer(uintptr(v.Val))) +} + +// ToArray converts variant to SafeArray helper. +func (v *VARIANT) ToArray() *SafeArrayConversion { + if v.VT != VT_SAFEARRAY { + if v.VT&VT_ARRAY == 0 { + return nil + } + } + var safeArray *SafeArray = (*SafeArray)(unsafe.Pointer(uintptr(v.Val))) + return &SafeArrayConversion{safeArray} +} + +// ToString converts variant to Go string. +func (v *VARIANT) ToString() string { + if v.VT != VT_BSTR { + return "" + } + return BstrToString(*(**uint16)(unsafe.Pointer(&v.Val))) +} + +// Clear the memory of variant object. +func (v *VARIANT) Clear() error { + return VariantClear(v) +} + +// Value returns variant value based on its type. +// +// Currently supported types: 2- and 4-byte integers, strings, bools. +// Note that 64-bit integers, datetimes, and other types are stored as strings +// and will be returned as strings. +// +// Needs to be further converted, because this returns an interface{}. +func (v *VARIANT) Value() interface{} { + switch v.VT { + case VT_I1: + return int8(v.Val) + case VT_UI1: + return uint8(v.Val) + case VT_I2: + return int16(v.Val) + case VT_UI2: + return uint16(v.Val) + case VT_I4: + return int32(v.Val) + case VT_UI4: + return uint32(v.Val) + case VT_I8: + return int64(v.Val) + case VT_UI8: + return uint64(v.Val) + case VT_INT: + return int(v.Val) + case VT_UINT: + return uint(v.Val) + case VT_INT_PTR: + return uintptr(v.Val) // TODO + case VT_UINT_PTR: + return uintptr(v.Val) + case VT_R4: + return *(*float32)(unsafe.Pointer(&v.Val)) + case VT_R8: + return *(*float64)(unsafe.Pointer(&v.Val)) + case VT_BSTR: + return v.ToString() + case VT_DATE: + // VT_DATE type will either return float64 or time.Time. + d := uint64(v.Val) + date, err := GetVariantDate(d) + if err != nil { + return float64(v.Val) + } + return date + case VT_UNKNOWN: + return v.ToIUnknown() + case VT_DISPATCH: + return v.ToIDispatch() + case VT_BOOL: + return v.Val != 0 + } + return nil +} diff --git a/vendor/github.com/go-ole/go-ole/variant_386.go b/vendor/github.com/go-ole/go-ole/variant_386.go new file mode 100644 index 0000000000000000000000000000000000000000..e73736bf391791b783a7e121fda36b1de76e059e --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_386.go @@ -0,0 +1,11 @@ +// +build 386 + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_amd64.go b/vendor/github.com/go-ole/go-ole/variant_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..dccdde132333caed9ab72e87bebae63bcea60a7b --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_amd64.go @@ -0,0 +1,12 @@ +// +build amd64 + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_date_386.go b/vendor/github.com/go-ole/go-ole/variant_date_386.go new file mode 100644 index 0000000000000000000000000000000000000000..1b970f63f5fbc5a08f54af61b54498b13151f894 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_date_386.go @@ -0,0 +1,22 @@ +// +build windows,386 + +package ole + +import ( + "errors" + "syscall" + "time" + "unsafe" +) + +// GetVariantDate converts COM Variant Time value to Go time.Time. +func GetVariantDate(value uint64) (time.Time, error) { + var st syscall.Systemtime + v1 := uint32(value) + v2 := uint32(value >> 32) + r, _, _ := procVariantTimeToSystemTime.Call(uintptr(v1), uintptr(v2), uintptr(unsafe.Pointer(&st))) + if r != 0 { + return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil + } + return time.Now(), errors.New("Could not convert to time, passing current time.") +} diff --git a/vendor/github.com/go-ole/go-ole/variant_date_amd64.go b/vendor/github.com/go-ole/go-ole/variant_date_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..6952f1f0de64e3f1e09dc7c163fc6ea238a49672 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_date_amd64.go @@ -0,0 +1,20 @@ +// +build windows,amd64 + +package ole + +import ( + "errors" + "syscall" + "time" + "unsafe" +) + +// GetVariantDate converts COM Variant Time value to Go time.Time. +func GetVariantDate(value uint64) (time.Time, error) { + var st syscall.Systemtime + r, _, _ := procVariantTimeToSystemTime.Call(uintptr(value), uintptr(unsafe.Pointer(&st))) + if r != 0 { + return time.Date(int(st.Year), time.Month(st.Month), int(st.Day), int(st.Hour), int(st.Minute), int(st.Second), int(st.Milliseconds/1000), time.UTC), nil + } + return time.Now(), errors.New("Could not convert to time, passing current time.") +} diff --git a/vendor/github.com/go-ole/go-ole/variant_ppc64le.go b/vendor/github.com/go-ole/go-ole/variant_ppc64le.go new file mode 100644 index 0000000000000000000000000000000000000000..326427a7d14443506588530d933cef8e246fc8f3 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_ppc64le.go @@ -0,0 +1,12 @@ +// +build ppc64le + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/variant_s390x.go b/vendor/github.com/go-ole/go-ole/variant_s390x.go new file mode 100644 index 0000000000000000000000000000000000000000..9874ca66b4f5fce651992b96c2651bdc2c32efba --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/variant_s390x.go @@ -0,0 +1,12 @@ +// +build s390x + +package ole + +type VARIANT struct { + VT VT // 2 + wReserved1 uint16 // 4 + wReserved2 uint16 // 6 + wReserved3 uint16 // 8 + Val int64 // 16 + _ [8]byte // 24 +} diff --git a/vendor/github.com/go-ole/go-ole/vt_string.go b/vendor/github.com/go-ole/go-ole/vt_string.go new file mode 100644 index 0000000000000000000000000000000000000000..729b4a04dd9da71c89a86363424db2a10c04f0cc --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/vt_string.go @@ -0,0 +1,58 @@ +// generated by stringer -output vt_string.go -type VT; DO NOT EDIT + +package ole + +import "fmt" + +const ( + _VT_name_0 = "VT_EMPTYVT_NULLVT_I2VT_I4VT_R4VT_R8VT_CYVT_DATEVT_BSTRVT_DISPATCHVT_ERRORVT_BOOLVT_VARIANTVT_UNKNOWNVT_DECIMAL" + _VT_name_1 = "VT_I1VT_UI1VT_UI2VT_UI4VT_I8VT_UI8VT_INTVT_UINTVT_VOIDVT_HRESULTVT_PTRVT_SAFEARRAYVT_CARRAYVT_USERDEFINEDVT_LPSTRVT_LPWSTR" + _VT_name_2 = "VT_RECORDVT_INT_PTRVT_UINT_PTR" + _VT_name_3 = "VT_FILETIMEVT_BLOBVT_STREAMVT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTVT_CFVT_CLSID" + _VT_name_4 = "VT_BSTR_BLOBVT_VECTOR" + _VT_name_5 = "VT_ARRAY" + _VT_name_6 = "VT_BYREF" + _VT_name_7 = "VT_RESERVED" + _VT_name_8 = "VT_ILLEGAL" +) + +var ( + _VT_index_0 = [...]uint8{0, 8, 15, 20, 25, 30, 35, 40, 47, 54, 65, 73, 80, 90, 100, 110} + _VT_index_1 = [...]uint8{0, 5, 11, 17, 23, 28, 34, 40, 47, 54, 64, 70, 82, 91, 105, 113, 122} + _VT_index_2 = [...]uint8{0, 9, 19, 30} + _VT_index_3 = [...]uint8{0, 11, 18, 27, 37, 55, 71, 85, 90, 98} + _VT_index_4 = [...]uint8{0, 12, 21} + _VT_index_5 = [...]uint8{0, 8} + _VT_index_6 = [...]uint8{0, 8} + _VT_index_7 = [...]uint8{0, 11} + _VT_index_8 = [...]uint8{0, 10} +) + +func (i VT) String() string { + switch { + case 0 <= i && i <= 14: + return _VT_name_0[_VT_index_0[i]:_VT_index_0[i+1]] + case 16 <= i && i <= 31: + i -= 16 + return _VT_name_1[_VT_index_1[i]:_VT_index_1[i+1]] + case 36 <= i && i <= 38: + i -= 36 + return _VT_name_2[_VT_index_2[i]:_VT_index_2[i+1]] + case 64 <= i && i <= 72: + i -= 64 + return _VT_name_3[_VT_index_3[i]:_VT_index_3[i+1]] + case 4095 <= i && i <= 4096: + i -= 4095 + return _VT_name_4[_VT_index_4[i]:_VT_index_4[i+1]] + case i == 8192: + return _VT_name_5 + case i == 16384: + return _VT_name_6 + case i == 32768: + return _VT_name_7 + case i == 65535: + return _VT_name_8 + default: + return fmt.Sprintf("VT(%d)", i) + } +} diff --git a/vendor/github.com/go-ole/go-ole/winrt.go b/vendor/github.com/go-ole/go-ole/winrt.go new file mode 100644 index 0000000000000000000000000000000000000000..4e9eca73244ee1cf75566c888233c633660792a1 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/winrt.go @@ -0,0 +1,99 @@ +// +build windows + +package ole + +import ( + "reflect" + "syscall" + "unicode/utf8" + "unsafe" +) + +var ( + procRoInitialize = modcombase.NewProc("RoInitialize") + procRoActivateInstance = modcombase.NewProc("RoActivateInstance") + procRoGetActivationFactory = modcombase.NewProc("RoGetActivationFactory") + procWindowsCreateString = modcombase.NewProc("WindowsCreateString") + procWindowsDeleteString = modcombase.NewProc("WindowsDeleteString") + procWindowsGetStringRawBuffer = modcombase.NewProc("WindowsGetStringRawBuffer") +) + +func RoInitialize(thread_type uint32) (err error) { + hr, _, _ := procRoInitialize.Call(uintptr(thread_type)) + if hr != 0 { + err = NewError(hr) + } + return +} + +func RoActivateInstance(clsid string) (ins *IInspectable, err error) { + hClsid, err := NewHString(clsid) + if err != nil { + return nil, err + } + defer DeleteHString(hClsid) + + hr, _, _ := procRoActivateInstance.Call( + uintptr(unsafe.Pointer(hClsid)), + uintptr(unsafe.Pointer(&ins))) + if hr != 0 { + err = NewError(hr) + } + return +} + +func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { + hClsid, err := NewHString(clsid) + if err != nil { + return nil, err + } + defer DeleteHString(hClsid) + + hr, _, _ := procRoGetActivationFactory.Call( + uintptr(unsafe.Pointer(hClsid)), + uintptr(unsafe.Pointer(iid)), + uintptr(unsafe.Pointer(&ins))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// HString is handle string for pointers. +type HString uintptr + +// NewHString returns a new HString for Go string. +func NewHString(s string) (hstring HString, err error) { + u16 := syscall.StringToUTF16Ptr(s) + len := uint32(utf8.RuneCountInString(s)) + hr, _, _ := procWindowsCreateString.Call( + uintptr(unsafe.Pointer(u16)), + uintptr(len), + uintptr(unsafe.Pointer(&hstring))) + if hr != 0 { + err = NewError(hr) + } + return +} + +// DeleteHString deletes HString. +func DeleteHString(hstring HString) (err error) { + hr, _, _ := procWindowsDeleteString.Call(uintptr(hstring)) + if hr != 0 { + err = NewError(hr) + } + return +} + +// String returns Go string value of HString. +func (h HString) String() string { + var u16buf uintptr + var u16len uint32 + u16buf, _, _ = procWindowsGetStringRawBuffer.Call( + uintptr(h), + uintptr(unsafe.Pointer(&u16len))) + + u16hdr := reflect.SliceHeader{Data: u16buf, Len: int(u16len), Cap: int(u16len)} + u16 := *(*[]uint16)(unsafe.Pointer(&u16hdr)) + return syscall.UTF16ToString(u16) +} diff --git a/vendor/github.com/go-ole/go-ole/winrt_doc.go b/vendor/github.com/go-ole/go-ole/winrt_doc.go new file mode 100644 index 0000000000000000000000000000000000000000..52e6d74c9ab3abc58908eb83c1a766b15e1ac9b4 --- /dev/null +++ b/vendor/github.com/go-ole/go-ole/winrt_doc.go @@ -0,0 +1,36 @@ +// +build !windows + +package ole + +// RoInitialize +func RoInitialize(thread_type uint32) (err error) { + return NewError(E_NOTIMPL) +} + +// RoActivateInstance +func RoActivateInstance(clsid string) (ins *IInspectable, err error) { + return nil, NewError(E_NOTIMPL) +} + +// RoGetActivationFactory +func RoGetActivationFactory(clsid string, iid *GUID) (ins *IInspectable, err error) { + return nil, NewError(E_NOTIMPL) +} + +// HString is handle string for pointers. +type HString uintptr + +// NewHString returns a new HString for Go string. +func NewHString(s string) (hstring HString, err error) { + return HString(uintptr(0)), NewError(E_NOTIMPL) +} + +// DeleteHString deletes HString. +func DeleteHString(hstring HString) (err error) { + return NewError(E_NOTIMPL) +} + +// String returns Go string value of HString. +func (h HString) String() string { + return "" +} diff --git a/vendor/github.com/golang/protobuf/proto/deprecated.go b/vendor/github.com/golang/protobuf/proto/deprecated.go new file mode 100644 index 0000000000000000000000000000000000000000..69de0ea0efebecef142a426effd445f245d3c582 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/deprecated.go @@ -0,0 +1,38 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2018 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +// Deprecated: do not use. +type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 } + +// Deprecated: do not use. +func GetStats() Stats { return Stats{} } diff --git a/vendor/github.com/pingcap/errors/LICENSE b/vendor/github.com/pingcap/errors/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..835ba3e755cef8c0dde475f1ebfd41e4ba0c79bf --- /dev/null +++ b/vendor/github.com/pingcap/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pingcap/errors/README.md b/vendor/github.com/pingcap/errors/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6483ba2afb51278516423dc013fcfa275ee597a9 --- /dev/null +++ b/vendor/github.com/pingcap/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Contributing + +We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. + +Before proposing a change, please discuss your change by raising an issue. + +## License + +BSD-2-Clause diff --git a/vendor/github.com/pingcap/errors/appveyor.yml b/vendor/github.com/pingcap/errors/appveyor.yml new file mode 100644 index 0000000000000000000000000000000000000000..a932eade0240aa2b5f9f5347b695ab173da0236a --- /dev/null +++ b/vendor/github.com/pingcap/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pingcap/errors/errors.go b/vendor/github.com/pingcap/errors/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..2e1d3f62896680452864f739ea330ac743c034e2 --- /dev/null +++ b/vendor/github.com/pingcap/errors/errors.go @@ -0,0 +1,324 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Annotate function returns a new error that adds context to the +// original error by recording a stack trace at the point Annotate is called, +// and the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Annotate(err, "read failed") +// } +// +// If additional control is required the errors.AddStack and errors.WithMessage +// functions destructure errors.Annotate into its component operations of annotating +// an error with a stack trace and an a message, respectively. +// +// Retrieving the cause of an error +// +// Using errors.Annotate constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Annotate to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error which does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// causer interface is not exported by this package, but is considered a part +// of stable public API. +// errors.Unwrap is also available: this will retrieve the next error in the chain. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported +// +// %s print the error. If the error has a Cause it will be +// printed recursively +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Annotate, and Annotatef record a stack trace at the point they are invoked. +// This information can be retrieved with the StackTracer interface that returns +// a StackTrace. Where errors.StackTrace is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if stacked := errors.GetStackTracer(err); stacked != nil { +// for _, f := range stacked.StackTrace() { +// fmt.Printf("%+s:%d", f) +// } +// } +// +// See the documentation for Frame.Format for more details. +// +// errors.Find can be used to search for an error in the error chain. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// StackTraceAware is an optimization to avoid repetitive traversals of an error chain. +// HasStack checks for this marker first. +// Annotate/Wrap and Annotatef/Wrapf will produce this marker. +type StackTraceAware interface { + HasStack() bool +} + +// HasStack tells whether a StackTracer exists in the error chain +func HasStack(err error) bool { + if errWithStack, ok := err.(StackTraceAware); ok { + return errWithStack.HasStack() + } + return GetStackTracer(err) != nil +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +// +// For most use cases this is deprecated and AddStack should be used (which will ensure just one stack trace). +// However, one may want to use this in some situations, for example to create a 2nd trace across a goroutine. +func WithStack(err error) error { + if err == nil { + return nil + } + + return &withStack{ + err, + callers(), + } +} + +// AddStack is similar to WithStack. +// However, it will first check with HasStack to see if a stack trace already exists in the causer chain before creating another one. +func AddStack(err error) error { + if HasStack(err) { + return err + } + return WithStack(err) +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +// +// For most use cases this is deprecated in favor of Annotate. +// Annotate avoids creating duplicate stack traces. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + hasStack := HasStack(err) + err = &withMessage{ + cause: err, + msg: message, + causeHasStack: hasStack, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is call, and the format specifier. +// If err is nil, Wrapf returns nil. +// +// For most use cases this is deprecated in favor of Annotatef. +// Annotatef avoids creating duplicate stack traces. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + hasStack := HasStack(err) + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + causeHasStack: hasStack, + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + causeHasStack: HasStack(err), + } +} + +type withMessage struct { + cause error + msg string + causeHasStack bool +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } +func (w *withMessage) HasStack() bool { return w.causeHasStack } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + cause := Unwrap(err) + if cause == nil { + return err + } + return Cause(cause) +} + +// Unwrap uses causer to return the next error in the chain or nil. +// This goes one-level deeper, whereas Cause goes as far as possible +func Unwrap(err error) error { + type causer interface { + Cause() error + } + if unErr, ok := err.(causer); ok { + return unErr.Cause() + } + return nil +} + +// Find an error in the chain that matches a test function. +// returns nil if no error is found. +func Find(origErr error, test func(error) bool) error { + var foundErr error + WalkDeep(origErr, func(err error) bool { + if test(err) { + foundErr = err + return true + } + return false + }) + return foundErr +} diff --git a/vendor/github.com/pingcap/errors/group.go b/vendor/github.com/pingcap/errors/group.go new file mode 100644 index 0000000000000000000000000000000000000000..e5a969ab76f76c5b88cfe0f155b2b9121ba1e297 --- /dev/null +++ b/vendor/github.com/pingcap/errors/group.go @@ -0,0 +1,42 @@ +package errors + +// ErrorGroup is an interface for multiple errors that are not a chain. +// This happens for example when executing multiple operations in parallel. +type ErrorGroup interface { + Errors() []error +} + +// Errors uses the ErrorGroup interface to return a slice of errors. +// If the ErrorGroup interface is not implemented it returns an array containing just the given error. +func Errors(err error) []error { + if eg, ok := err.(ErrorGroup); ok { + return eg.Errors() + } + return []error{err} +} + +// WalkDeep does a depth-first traversal of all errors. +// Any ErrorGroup is traversed (after going deep). +// The visitor function can return true to end the traversal early +// In that case, WalkDeep will return true, otherwise false. +func WalkDeep(err error, visitor func(err error) bool) bool { + // Go deep + unErr := err + for unErr != nil { + if done := visitor(unErr); done { + return true + } + unErr = Unwrap(unErr) + } + + // Go wide + if group, ok := err.(ErrorGroup); ok { + for _, err := range group.Errors() { + if early := WalkDeep(err, visitor); early { + return true + } + } + } + + return false +} diff --git a/vendor/github.com/pingcap/errors/juju_adaptor.go b/vendor/github.com/pingcap/errors/juju_adaptor.go new file mode 100644 index 0000000000000000000000000000000000000000..8bcfe2f37bd5b7c35aa7928fd3370b2770ddb672 --- /dev/null +++ b/vendor/github.com/pingcap/errors/juju_adaptor.go @@ -0,0 +1,100 @@ +package errors + +import ( + "fmt" + "strings" +) + +// ==================== juju adaptor start ======================== + +// Trace just calls AddStack. +func Trace(err error) error { + return AddStack(err) +} + +// Annotate adds a message and ensures there is a stack trace. +func Annotate(err error, message string) error { + if err == nil { + return nil + } + hasStack := HasStack(err) + err = &withMessage{ + cause: err, + msg: message, + causeHasStack: hasStack, + } + if hasStack { + return err + } + return &withStack{ + err, + callers(), + } +} + +// Annotatef adds a message and ensures there is a stack trace. +func Annotatef(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + hasStack := HasStack(err) + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + causeHasStack: hasStack, + } + if hasStack { + return err + } + return &withStack{ + err, + callers(), + } +} + +// ErrorStack will format a stack trace if it is available, otherwise it will be Error() +// If the error is nil, the empty string is returned +// Note that this just calls fmt.Sprintf("%+v", err) +func ErrorStack(err error) string { + if err == nil { + return "" + } + return fmt.Sprintf("%+v", err) +} + +// IsNotFound reports whether err was not found error. +func IsNotFound(err error) bool { + return strings.Contains(err.Error(), "not found") +} + +// NotFoundf represents an error with not found message. +func NotFoundf(format string, args ...interface{}) error { + return Errorf(format+" not found", args...) +} + +// BadRequestf represents an error with bad request message. +func BadRequestf(format string, args ...interface{}) error { + return Errorf(format+" bad request", args...) +} + +// NotSupportedf represents an error with not supported message. +func NotSupportedf(format string, args ...interface{}) error { + return Errorf(format+" not supported", args...) +} + +// NotValidf represents an error with not valid message. +func NotValidf(format string, args ...interface{}) error { + return Errorf(format+" not valid", args...) +} + +// IsAlreadyExists reports whether err was already exists error. +func IsAlreadyExists(err error) bool { + return strings.Contains(err.Error(), "already exists") +} + +// AlreadyExistsf represents an error with already exists message. +func AlreadyExistsf(format string, args ...interface{}) error { + return Errorf(format+" already exists", args...) +} + +// ==================== juju adaptor end ======================== diff --git a/vendor/github.com/pingcap/errors/stack.go b/vendor/github.com/pingcap/errors/stack.go new file mode 100644 index 0000000000000000000000000000000000000000..bb1e6a84f339d84a9e2701f1c37071f5ab6af799 --- /dev/null +++ b/vendor/github.com/pingcap/errors/stack.go @@ -0,0 +1,226 @@ +package errors + +import ( + "bytes" + "fmt" + "io" + "path" + "runtime" + "strconv" + "strings" +) + +// StackTracer retrieves the StackTrace +// Generally you would want to use the GetStackTracer function to do that. +type StackTracer interface { + StackTrace() StackTrace +} + +// GetStackTracer will return the first StackTracer in the causer chain. +// This function is used by AddStack to avoid creating redundant stack traces. +// +// You can also use the StackTracer interface on the returned error to get the stack trace. +func GetStackTracer(origErr error) StackTracer { + var stacked StackTracer + WalkDeep(origErr, func(err error) bool { + if stackTracer, ok := err.(StackTracer); ok { + stacked = stackTracer + return true + } + return false + }) + return stacked +} + +// Frame represents a program counter inside a stack frame. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s function name and path of source file relative to the compile time +// GOPATH separated by \n\t (\n\t) +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + f.format(s, s, verb) +} + +// format allows stack trace printing calls to be made with a bytes.Buffer. +func (f Frame) format(w io.Writer, s fmt.State, verb rune) { + switch verb { + case 's': + switch { + case s.Flag('+'): + pc := f.pc() + fn := runtime.FuncForPC(pc) + if fn == nil { + io.WriteString(w, "unknown") + } else { + file, _ := fn.FileLine(pc) + io.WriteString(w, fn.Name()) + io.WriteString(w, "\n\t") + io.WriteString(w, file) + } + default: + io.WriteString(w, path.Base(f.file())) + } + case 'd': + io.WriteString(w, strconv.Itoa(f.line())) + case 'n': + name := runtime.FuncForPC(f.pc()).Name() + io.WriteString(w, funcname(name)) + case 'v': + f.format(w, s, 's') + io.WriteString(w, ":") + f.format(w, s, 'd') + } +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +// Format formats the stack of Frames according to the fmt.Formatter interface. +// +// %s lists source files for each Frame in the stack +// %v lists the source file and line number for each Frame in the stack +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+v Prints filename, function, and line number for each Frame in the stack. +func (st StackTrace) Format(s fmt.State, verb rune) { + var b bytes.Buffer + switch verb { + case 'v': + switch { + case s.Flag('+'): + b.Grow(len(st) * stackMinLen) + for _, fr := range st { + b.WriteByte('\n') + fr.format(&b, s, verb) + } + case s.Flag('#'): + fmt.Fprintf(&b, "%#v", []Frame(st)) + default: + st.formatSlice(&b, s, verb) + } + case 's': + st.formatSlice(&b, s, verb) + } + io.Copy(s, &b) +} + +// formatSlice will format this StackTrace into the given buffer as a slice of +// Frame, only valid when called with '%s' or '%v'. +func (st StackTrace) formatSlice(b *bytes.Buffer, s fmt.State, verb rune) { + b.WriteByte('[') + if len(st) == 0 { + b.WriteByte(']') + return + } + + b.Grow(len(st) * (stackMinLen / 4)) + st[0].format(b, s, verb) + for _, fr := range st[1:] { + b.WriteByte(' ') + fr.format(b, s, verb) + } + b.WriteByte(']') +} + +// stackMinLen is a best-guess at the minimum length of a stack trace. It +// doesn't need to be exact, just give a good enough head start for the buffer +// to avoid the expensive early growth. +const stackMinLen = 96 + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + var b bytes.Buffer + b.Grow(len(*s) * stackMinLen) + for _, pc := range *s { + f := Frame(pc) + b.WriteByte('\n') + f.format(&b, st, 'v') + } + io.Copy(st, &b) + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + return callersSkip(4) +} + +func callersSkip(skip int) *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(skip, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} + +// NewStack is for library implementers that want to generate a stack trace. +// Normally you should insted use AddStack to get an error with a stack trace. +// +// The result of this function can be turned into a stack trace by calling .StackTrace() +// +// This function takes an argument for the number of stack frames to skip. +// This avoids putting stack generation function calls like this one in the stack trace. +// A value of 0 will give you the line that called NewStack(0) +// A library author wrapping this in their own function will want to use a value of at least 1. +func NewStack(skip int) StackTracer { + return callersSkip(skip + 3) +} diff --git a/vendor/github.com/pingcap/parser/LICENSE b/vendor/github.com/pingcap/parser/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64 --- /dev/null +++ b/vendor/github.com/pingcap/parser/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/pingcap/parser/Makefile b/vendor/github.com/pingcap/parser/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4ae44861cdb5b579884317407ef1ce3fa1d1093e --- /dev/null +++ b/vendor/github.com/pingcap/parser/Makefile @@ -0,0 +1,37 @@ +.PHONY: all parser clean + +ARCH:="`uname -s`" +MAC:="Darwin" +LINUX:="Linux" + +all: parser.go + +test: parser.go + sh test.sh + +parser.go: parser.y + make parser + +parser: bin/goyacc + bin/goyacc -o /dev/null parser.y + bin/goyacc -o parser.go parser.y 2>&1 | egrep "(shift|reduce)/reduce" | awk '{print} END {if (NR > 0) {print "Find conflict in parser.y. Please check y.output for more information."; exit 1;}}' + rm -f y.output + + @if [ $(ARCH) = $(LINUX) ]; \ + then \ + sed -i -e 's|//line.*||' -e 's/yyEofCode/yyEOFCode/' parser.go; \ + elif [ $(ARCH) = $(MAC) ]; \ + then \ + /usr/bin/sed -i "" 's|//line.*||' parser.go; \ + /usr/bin/sed -i "" 's/yyEofCode/yyEOFCode/' parser.go; \ + fi + + @awk 'BEGIN{print "// Code generated by goyacc DO NOT EDIT."} {print $0}' parser.go > tmp_parser.go && mv tmp_parser.go parser.go; + +bin/goyacc: goyacc/main.go + GO111MODULE=on go build -o bin/goyacc goyacc/main.go + +clean: + go clean -i ./... + rm -rf *.out + rm parser.go diff --git a/vendor/github.com/pingcap/parser/README.md b/vendor/github.com/pingcap/parser/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8fd7ba019b99e56d33dfe92a8a7f0ad02f4ae77f --- /dev/null +++ b/vendor/github.com/pingcap/parser/README.md @@ -0,0 +1,60 @@ +# Parser + +[![Go Report Card](https://goreportcard.com/badge/github.com/pingcap/parser)](https://goreportcard.com/report/github.com/pingcap/parser) [![CircleCI Status](https://circleci.com/gh/pingcap/parser.svg?style=shield)](https://circleci.com/gh/pingcap/parser) [![GoDoc](https://godoc.org/github.com/pingcap/parser?status.svg)](https://godoc.org/github.com/pingcap/parser) + +TiDB SQL Parser + +## How to update parser for TiDB + +Assuming that you want to file a PR (pull request) to TiDB, and your PR includes a change in the parser, follow these steps to update the parser in TiDB. + +### Step 1: Make changes in your parser repository + +Fork this repository to your own account and commit the changes to your repository. + +> **Note:** +> +> - Don't forget to run `make test` before you commit! +> - Make sure `parser.go` is updated. + +Suppose the forked repository is `https://github.com/your-repo/parser`. + +### Step 2: Make your parser changes take effect in TiDB and run CI + +1. In your TiDB repository, modify the `go.mod` file, remove `github.com/pingcap/parser` from the `require` instruction, and add a new line at the end of the file like this: + + ``` + replace github.com/pingcap/parser => github.com/your-repo/parser v0.0.0-20181102150703-4acd198f5092 + ``` + + This change tells TiDB to use the modified parser from your repository. You can just use below command to replace the dependent parser version: + + ``` + GO111MODULE=on go mod edit -replace github.com/pingcap/parser=github.com/your-repo/parser@your-branch + ``` + +2. You can get correct version information by running this command in your TiDB directory: + + ``` + GO111MODULE=on go get -u github.com/your-repo/parser@master + ``` + + If some error is reported, you can ignore it and still edit the `go.mod` file manually. + +3. File a PR to TiDB. + +### Step 3: Merge the PR about the parser to this repository + +File a PR to this repository. **Link the related PR in TiDB in your PR description or comment.** + +This PR will be reviewed, and if everything goes well, it will be merged. + +### Step 4: Update TiDB to use the latest parser + +In your TiDB pull request, modify the `go.mod` file manually or use this command: + +``` +GO111MODULE=on go get -u github.com/pingcap/parser@master +``` + +Make sure the `replace` instruction is changed back to the `require` instruction and the version is the latest. diff --git a/vendor/github.com/pingcap/parser/ast/ast.go b/vendor/github.com/pingcap/parser/ast/ast.go new file mode 100644 index 0000000000000000000000000000000000000000..2f3be0b4b4f5a972ac988673c5ea153040d44117 --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/ast.go @@ -0,0 +1,156 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package ast is the abstract syntax tree parsed from a SQL statement by parser. +// It can be analysed and transformed by optimizer. +package ast + +import ( + "io" + + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/types" +) + +// Node is the basic element of the AST. +// Interfaces embed Node should have 'Node' name suffix. +type Node interface { + // Accept accepts Visitor to visit itself. + // The returned node should replace original node. + // ok returns false to stop visiting. + // + // Implementation of this method should first call visitor.Enter, + // assign the returned node to its method receiver, if skipChildren returns true, + // children should be skipped. Otherwise, call its children in particular order that + // later elements depends on former elements. Finally, return visitor.Leave. + Accept(v Visitor) (node Node, ok bool) + // Text returns the original text of the element. + Text() string + // SetText sets original text to the Node. + SetText(text string) +} + +// Flags indicates whether an expression contains certain types of expression. +const ( + FlagConstant uint64 = 0 + FlagHasParamMarker uint64 = 1 << iota + FlagHasFunc + FlagHasReference + FlagHasAggregateFunc + FlagHasSubquery + FlagHasVariable + FlagHasDefault + FlagPreEvaluated +) + +// ExprNode is a node that can be evaluated. +// Name of implementations should have 'Expr' suffix. +type ExprNode interface { + // Node is embedded in ExprNode. + Node + // SetType sets evaluation type to the expression. + SetType(tp *types.FieldType) + // GetType gets the evaluation type of the expression. + GetType() *types.FieldType + // SetFlag sets flag to the expression. + // Flag indicates whether the expression contains + // parameter marker, reference, aggregate function... + SetFlag(flag uint64) + // GetFlag returns the flag of the expression. + GetFlag() uint64 + + // Format formats the AST into a writer. + Format(w io.Writer) +} + +// OptBinary is used for parser. +type OptBinary struct { + IsBinary bool + Charset string +} + +// FuncNode represents function call expression node. +type FuncNode interface { + ExprNode + functionExpression() +} + +// StmtNode represents statement node. +// Name of implementations should have 'Stmt' suffix. +type StmtNode interface { + Node + statement() +} + +// DDLNode represents DDL statement node. +type DDLNode interface { + StmtNode + ddlStatement() +} + +// DMLNode represents DML statement node. +type DMLNode interface { + StmtNode + dmlStatement() +} + +// ResultField represents a result field which can be a column from a table, +// or an expression in select field. It is a generated property during +// binding process. ResultField is the key element to evaluate a ColumnNameExpr. +// After resolving process, every ColumnNameExpr will be resolved to a ResultField. +// During execution, every row retrieved from table will set the row value to +// ResultFields of that table, so ColumnNameExpr resolved to that ResultField can be +// easily evaluated. +type ResultField struct { + Column *model.ColumnInfo + ColumnAsName model.CIStr + Table *model.TableInfo + TableAsName model.CIStr + DBName model.CIStr + + // Expr represents the expression for the result field. If it is generated from a select field, it would + // be the expression of that select field, otherwise the type would be ValueExpr and value + // will be set for every retrieved row. + Expr ExprNode + TableName *TableName + // Referenced indicates the result field has been referenced or not. + // If not, we don't need to get the values. + Referenced bool +} + +// ResultSetNode interface has a ResultFields property, represents a Node that returns result set. +// Implementations include SelectStmt, SubqueryExpr, TableSource, TableName and Join. +type ResultSetNode interface { + Node +} + +// SensitiveStmtNode overloads StmtNode and provides a SecureText method. +type SensitiveStmtNode interface { + StmtNode + // SecureText is different from Text that it hide password information. + SecureText() string +} + +// Visitor visits a Node. +type Visitor interface { + // Enter is called before children nodes are visited. + // The returned node must be the same type as the input node n. + // skipChildren returns true means children nodes should be skipped, + // this is useful when work is done in Enter and there is no need to visit children. + Enter(n Node) (node Node, skipChildren bool) + // Leave is called after children nodes have been visited. + // The returned node's type can be different from the input node if it is a ExprNode, + // Non-expression node must be the same type as the input node n. + // ok returns false to stop visiting. + Leave(n Node) (node Node, ok bool) +} diff --git a/vendor/github.com/pingcap/parser/ast/base.go b/vendor/github.com/pingcap/parser/ast/base.go new file mode 100644 index 0000000000000000000000000000000000000000..984d8e4d9580277659dca5860d168d2ed6cf7229 --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/base.go @@ -0,0 +1,101 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import "github.com/pingcap/parser/types" + +// node is the struct implements node interface except for Accept method. +// Node implementations should embed it in. +type node struct { + text string +} + +// SetText implements Node interface. +func (n *node) SetText(text string) { + n.text = text +} + +// Text implements Node interface. +func (n *node) Text() string { + return n.text +} + +// stmtNode implements StmtNode interface. +// Statement implementations should embed it in. +type stmtNode struct { + node +} + +// statement implements StmtNode interface. +func (sn *stmtNode) statement() {} + +// ddlNode implements DDLNode interface. +// DDL implementations should embed it in. +type ddlNode struct { + stmtNode +} + +// ddlStatement implements DDLNode interface. +func (dn *ddlNode) ddlStatement() {} + +// dmlNode is the struct implements DMLNode interface. +// DML implementations should embed it in. +type dmlNode struct { + stmtNode +} + +// dmlStatement implements DMLNode interface. +func (dn *dmlNode) dmlStatement() {} + +// exprNode is the struct implements Expression interface. +// Expression implementations should embed it in. +type exprNode struct { + node + Type types.FieldType + flag uint64 +} + +// TexprNode is exported for parser driver. +type TexprNode = exprNode + +// SetType implements ExprNode interface. +func (en *exprNode) SetType(tp *types.FieldType) { + en.Type = *tp +} + +// GetType implements ExprNode interface. +func (en *exprNode) GetType() *types.FieldType { + return &en.Type +} + +// SetFlag implements ExprNode interface. +func (en *exprNode) SetFlag(flag uint64) { + en.flag = flag +} + +// GetFlag implements ExprNode interface. +func (en *exprNode) GetFlag() uint64 { + return en.flag +} + +type funcNode struct { + exprNode +} + +// functionExpression implements FunctionNode interface. +func (fn *funcNode) functionExpression() {} + +type resultSetNode struct { + resultFields []*ResultField +} diff --git a/vendor/github.com/pingcap/parser/ast/ddl.go b/vendor/github.com/pingcap/parser/ast/ddl.go new file mode 100644 index 0000000000000000000000000000000000000000..48a7cc7b4654515f288e07399ead824fcc095769 --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/ddl.go @@ -0,0 +1,896 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/types" +) + +var ( + _ DDLNode = &AlterTableStmt{} + _ DDLNode = &CreateDatabaseStmt{} + _ DDLNode = &CreateIndexStmt{} + _ DDLNode = &CreateTableStmt{} + _ DDLNode = &CreateViewStmt{} + _ DDLNode = &DropDatabaseStmt{} + _ DDLNode = &DropIndexStmt{} + _ DDLNode = &DropTableStmt{} + _ DDLNode = &RenameTableStmt{} + _ DDLNode = &TruncateTableStmt{} + + _ Node = &AlterTableSpec{} + _ Node = &ColumnDef{} + _ Node = &ColumnOption{} + _ Node = &ColumnPosition{} + _ Node = &Constraint{} + _ Node = &IndexColName{} + _ Node = &ReferenceDef{} +) + +// CharsetOpt is used for parsing charset option from SQL. +type CharsetOpt struct { + Chs string + Col string +} + +// DatabaseOptionType is the type for database options. +type DatabaseOptionType int + +// Database option types. +const ( + DatabaseOptionNone DatabaseOptionType = iota + DatabaseOptionCharset + DatabaseOptionCollate +) + +// DatabaseOption represents database option. +type DatabaseOption struct { + Tp DatabaseOptionType + Value string +} + +// CreateDatabaseStmt is a statement to create a database. +// See https://dev.mysql.com/doc/refman/5.7/en/create-database.html +type CreateDatabaseStmt struct { + ddlNode + + IfNotExists bool + Name string + Options []*DatabaseOption +} + +// Accept implements Node Accept interface. +func (n *CreateDatabaseStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*CreateDatabaseStmt) + return v.Leave(n) +} + +// DropDatabaseStmt is a statement to drop a database and all tables in the database. +// See https://dev.mysql.com/doc/refman/5.7/en/drop-database.html +type DropDatabaseStmt struct { + ddlNode + + IfExists bool + Name string +} + +// Accept implements Node Accept interface. +func (n *DropDatabaseStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DropDatabaseStmt) + return v.Leave(n) +} + +// IndexColName is used for parsing index column name from SQL. +type IndexColName struct { + node + + Column *ColumnName + Length int +} + +// Accept implements Node Accept interface. +func (n *IndexColName) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*IndexColName) + node, ok := n.Column.Accept(v) + if !ok { + return n, false + } + n.Column = node.(*ColumnName) + return v.Leave(n) +} + +// ReferenceDef is used for parsing foreign key reference option from SQL. +// See http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html +type ReferenceDef struct { + node + + Table *TableName + IndexColNames []*IndexColName + OnDelete *OnDeleteOpt + OnUpdate *OnUpdateOpt +} + +// Accept implements Node Accept interface. +func (n *ReferenceDef) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ReferenceDef) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + for i, val := range n.IndexColNames { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.IndexColNames[i] = node.(*IndexColName) + } + onDelete, ok := n.OnDelete.Accept(v) + if !ok { + return n, false + } + n.OnDelete = onDelete.(*OnDeleteOpt) + onUpdate, ok := n.OnUpdate.Accept(v) + if !ok { + return n, false + } + n.OnUpdate = onUpdate.(*OnUpdateOpt) + return v.Leave(n) +} + +// ReferOptionType is the type for refer options. +type ReferOptionType int + +// Refer option types. +const ( + ReferOptionNoOption ReferOptionType = iota + ReferOptionRestrict + ReferOptionCascade + ReferOptionSetNull + ReferOptionNoAction +) + +// String implements fmt.Stringer interface. +func (r ReferOptionType) String() string { + switch r { + case ReferOptionRestrict: + return "RESTRICT" + case ReferOptionCascade: + return "CASCADE" + case ReferOptionSetNull: + return "SET NULL" + case ReferOptionNoAction: + return "NO ACTION" + } + return "" +} + +// OnDeleteOpt is used for optional on delete clause. +type OnDeleteOpt struct { + node + ReferOpt ReferOptionType +} + +// Accept implements Node Accept interface. +func (n *OnDeleteOpt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*OnDeleteOpt) + return v.Leave(n) +} + +// OnUpdateOpt is used for optional on update clause. +type OnUpdateOpt struct { + node + ReferOpt ReferOptionType +} + +// Accept implements Node Accept interface. +func (n *OnUpdateOpt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*OnUpdateOpt) + return v.Leave(n) +} + +// ColumnOptionType is the type for ColumnOption. +type ColumnOptionType int + +// ColumnOption types. +const ( + ColumnOptionNoOption ColumnOptionType = iota + ColumnOptionPrimaryKey + ColumnOptionNotNull + ColumnOptionAutoIncrement + ColumnOptionDefaultValue + ColumnOptionUniqKey + ColumnOptionNull + ColumnOptionOnUpdate // For Timestamp and Datetime only. + ColumnOptionFulltext + ColumnOptionComment + ColumnOptionGenerated + ColumnOptionReference +) + +// ColumnOption is used for parsing column constraint info from SQL. +type ColumnOption struct { + node + + Tp ColumnOptionType + // Expr is used for ColumnOptionDefaultValue/ColumnOptionOnUpdateColumnOptionGenerated. + // For ColumnOptionDefaultValue or ColumnOptionOnUpdate, it's the target value. + // For ColumnOptionGenerated, it's the target expression. + Expr ExprNode + // Stored is only for ColumnOptionGenerated, default is false. + Stored bool + // Refer is used for foreign key. + Refer *ReferenceDef +} + +// Accept implements Node Accept interface. +func (n *ColumnOption) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ColumnOption) + if n.Expr != nil { + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + } + return v.Leave(n) +} + +// IndexOption is the index options. +// KEY_BLOCK_SIZE [=] value +// | index_type +// | WITH PARSER parser_name +// | COMMENT 'string' +// See http://dev.mysql.com/doc/refman/5.7/en/create-table.html +type IndexOption struct { + node + + KeyBlockSize uint64 + Tp model.IndexType + Comment string +} + +// Accept implements Node Accept interface. +func (n *IndexOption) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*IndexOption) + return v.Leave(n) +} + +// ConstraintType is the type for Constraint. +type ConstraintType int + +// ConstraintTypes +const ( + ConstraintNoConstraint ConstraintType = iota + ConstraintPrimaryKey + ConstraintKey + ConstraintIndex + ConstraintUniq + ConstraintUniqKey + ConstraintUniqIndex + ConstraintForeignKey + ConstraintFulltext +) + +// Constraint is constraint for table definition. +type Constraint struct { + node + + Tp ConstraintType + Name string + + Keys []*IndexColName // Used for PRIMARY KEY, UNIQUE, ...... + + Refer *ReferenceDef // Used for foreign key. + + Option *IndexOption // Index Options +} + +// Accept implements Node Accept interface. +func (n *Constraint) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*Constraint) + for i, val := range n.Keys { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Keys[i] = node.(*IndexColName) + } + if n.Refer != nil { + node, ok := n.Refer.Accept(v) + if !ok { + return n, false + } + n.Refer = node.(*ReferenceDef) + } + if n.Option != nil { + node, ok := n.Option.Accept(v) + if !ok { + return n, false + } + n.Option = node.(*IndexOption) + } + return v.Leave(n) +} + +// ColumnDef is used for parsing column definition from SQL. +type ColumnDef struct { + node + + Name *ColumnName + Tp *types.FieldType + Options []*ColumnOption +} + +// Accept implements Node Accept interface. +func (n *ColumnDef) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ColumnDef) + node, ok := n.Name.Accept(v) + if !ok { + return n, false + } + n.Name = node.(*ColumnName) + for i, val := range n.Options { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Options[i] = node.(*ColumnOption) + } + return v.Leave(n) +} + +// CreateTableStmt is a statement to create a table. +// See https://dev.mysql.com/doc/refman/5.7/en/create-table.html +type CreateTableStmt struct { + ddlNode + + IfNotExists bool + Table *TableName + ReferTable *TableName + Cols []*ColumnDef + Constraints []*Constraint + Options []*TableOption + Partition *PartitionOptions + OnDuplicate OnDuplicateCreateTableSelectType + Select ResultSetNode +} + +// Accept implements Node Accept interface. +func (n *CreateTableStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*CreateTableStmt) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + if n.ReferTable != nil { + node, ok = n.ReferTable.Accept(v) + if !ok { + return n, false + } + n.ReferTable = node.(*TableName) + } + for i, val := range n.Cols { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.Cols[i] = node.(*ColumnDef) + } + for i, val := range n.Constraints { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.Constraints[i] = node.(*Constraint) + } + if n.Select != nil { + node, ok := n.Select.Accept(v) + if !ok { + return n, false + } + n.Select = node.(ResultSetNode) + } + + return v.Leave(n) +} + +// DropTableStmt is a statement to drop one or more tables. +// See https://dev.mysql.com/doc/refman/5.7/en/drop-table.html +type DropTableStmt struct { + ddlNode + + IfExists bool + Tables []*TableName +} + +// Accept implements Node Accept interface. +func (n *DropTableStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DropTableStmt) + for i, val := range n.Tables { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Tables[i] = node.(*TableName) + } + return v.Leave(n) +} + +// RenameTableStmt is a statement to rename a table. +// See http://dev.mysql.com/doc/refman/5.7/en/rename-table.html +type RenameTableStmt struct { + ddlNode + + OldTable *TableName + NewTable *TableName + + // TableToTables is only useful for syncer which depends heavily on tidb parser to do some dirty work for now. + // TODO: Refactor this when you are going to add full support for multiple schema changes. + TableToTables []*TableToTable +} + +// Accept implements Node Accept interface. +func (n *RenameTableStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*RenameTableStmt) + node, ok := n.OldTable.Accept(v) + if !ok { + return n, false + } + n.OldTable = node.(*TableName) + node, ok = n.NewTable.Accept(v) + if !ok { + return n, false + } + n.NewTable = node.(*TableName) + + for i, t := range n.TableToTables { + node, ok := t.Accept(v) + if !ok { + return n, false + } + n.TableToTables[i] = node.(*TableToTable) + } + + return v.Leave(n) +} + +// TableToTable represents renaming old table to new table used in RenameTableStmt. +type TableToTable struct { + node + OldTable *TableName + NewTable *TableName +} + +// Accept implements Node Accept interface. +func (n *TableToTable) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TableToTable) + node, ok := n.OldTable.Accept(v) + if !ok { + return n, false + } + n.OldTable = node.(*TableName) + node, ok = n.NewTable.Accept(v) + if !ok { + return n, false + } + n.NewTable = node.(*TableName) + return v.Leave(n) +} + +// CreateViewStmt is a statement to create a View. +// See https://dev.mysql.com/doc/refman/5.7/en/create-view.html +type CreateViewStmt struct { + ddlNode + + OrReplace bool + ViewName *TableName + Cols []model.CIStr + Select StmtNode +} + +// Accept implements Node Accept interface. +func (n *CreateViewStmt) Accept(v Visitor) (Node, bool) { + // TODO: implement the details. + return n, true +} + +// CreateIndexStmt is a statement to create an index. +// See https://dev.mysql.com/doc/refman/5.7/en/create-index.html +type CreateIndexStmt struct { + ddlNode + + IndexName string + Table *TableName + Unique bool + IndexColNames []*IndexColName + IndexOption *IndexOption +} + +// Accept implements Node Accept interface. +func (n *CreateIndexStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*CreateIndexStmt) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + for i, val := range n.IndexColNames { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.IndexColNames[i] = node.(*IndexColName) + } + if n.IndexOption != nil { + node, ok := n.IndexOption.Accept(v) + if !ok { + return n, false + } + n.IndexOption = node.(*IndexOption) + } + return v.Leave(n) +} + +// DropIndexStmt is a statement to drop the index. +// See https://dev.mysql.com/doc/refman/5.7/en/drop-index.html +type DropIndexStmt struct { + ddlNode + + IfExists bool + IndexName string + Table *TableName +} + +// Accept implements Node Accept interface. +func (n *DropIndexStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DropIndexStmt) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + return v.Leave(n) +} + +// TableOptionType is the type for TableOption +type TableOptionType int + +// TableOption types. +const ( + TableOptionNone TableOptionType = iota + TableOptionEngine + TableOptionCharset + TableOptionCollate + TableOptionAutoIncrement + TableOptionComment + TableOptionAvgRowLength + TableOptionCheckSum + TableOptionCompression + TableOptionConnection + TableOptionPassword + TableOptionKeyBlockSize + TableOptionMaxRows + TableOptionMinRows + TableOptionDelayKeyWrite + TableOptionRowFormat + TableOptionStatsPersistent + TableOptionShardRowID + TableOptionPackKeys +) + +// RowFormat types +const ( + RowFormatDefault uint64 = iota + 1 + RowFormatDynamic + RowFormatFixed + RowFormatCompressed + RowFormatRedundant + RowFormatCompact +) + +// OnDuplicateCreateTableSelectType is the option that handle unique key values in 'CREATE TABLE ... SELECT'. +// See https://dev.mysql.com/doc/refman/5.7/en/create-table-select.html +type OnDuplicateCreateTableSelectType int + +// OnDuplicateCreateTableSelect types +const ( + OnDuplicateCreateTableSelectError OnDuplicateCreateTableSelectType = iota + OnDuplicateCreateTableSelectIgnore + OnDuplicateCreateTableSelectReplace +) + +// TableOption is used for parsing table option from SQL. +type TableOption struct { + Tp TableOptionType + StrValue string + UintValue uint64 +} + +// ColumnPositionType is the type for ColumnPosition. +type ColumnPositionType int + +// ColumnPosition Types +const ( + ColumnPositionNone ColumnPositionType = iota + ColumnPositionFirst + ColumnPositionAfter +) + +// ColumnPosition represent the position of the newly added column +type ColumnPosition struct { + node + // Tp is either ColumnPositionNone, ColumnPositionFirst or ColumnPositionAfter. + Tp ColumnPositionType + // RelativeColumn is the column the newly added column after if type is ColumnPositionAfter + RelativeColumn *ColumnName +} + +// Accept implements Node Accept interface. +func (n *ColumnPosition) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ColumnPosition) + if n.RelativeColumn != nil { + node, ok := n.RelativeColumn.Accept(v) + if !ok { + return n, false + } + n.RelativeColumn = node.(*ColumnName) + } + return v.Leave(n) +} + +// AlterTableType is the type for AlterTableSpec. +type AlterTableType int + +// AlterTable types. +const ( + AlterTableOption AlterTableType = iota + 1 + AlterTableAddColumns + AlterTableAddConstraint + AlterTableDropColumn + AlterTableDropPrimaryKey + AlterTableDropIndex + AlterTableDropForeignKey + AlterTableModifyColumn + AlterTableChangeColumn + AlterTableRenameTable + AlterTableAlterColumn + AlterTableLock + AlterTableAlgorithm + AlterTableRenameIndex + AlterTableForce + AlterTableAddPartitions + AlterTableCoalescePartitions + AlterTableDropPartition + +// TODO: Add more actions +) + +// LockType is the type for AlterTableSpec. +// See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html#alter-table-concurrency +type LockType byte + +// Lock Types. +const ( + LockTypeNone LockType = iota + 1 + LockTypeDefault + LockTypeShared + LockTypeExclusive +) + +// AlterTableSpec represents alter table specification. +type AlterTableSpec struct { + node + + Tp AlterTableType + Name string + Constraint *Constraint + Options []*TableOption + NewTable *TableName + NewColumns []*ColumnDef + OldColumnName *ColumnName + Position *ColumnPosition + LockType LockType + Comment string + FromKey model.CIStr + ToKey model.CIStr + PartDefinitions []*PartitionDefinition + Num uint64 +} + +// Accept implements Node Accept interface. +func (n *AlterTableSpec) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*AlterTableSpec) + if n.Constraint != nil { + node, ok := n.Constraint.Accept(v) + if !ok { + return n, false + } + n.Constraint = node.(*Constraint) + } + if n.NewTable != nil { + node, ok := n.NewTable.Accept(v) + if !ok { + return n, false + } + n.NewTable = node.(*TableName) + } + for _, col := range n.NewColumns { + node, ok := col.Accept(v) + if !ok { + return n, false + } + col = node.(*ColumnDef) + } + if n.OldColumnName != nil { + node, ok := n.OldColumnName.Accept(v) + if !ok { + return n, false + } + n.OldColumnName = node.(*ColumnName) + } + if n.Position != nil { + node, ok := n.Position.Accept(v) + if !ok { + return n, false + } + n.Position = node.(*ColumnPosition) + } + return v.Leave(n) +} + +// AlterTableStmt is a statement to change the structure of a table. +// See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html +type AlterTableStmt struct { + ddlNode + + Table *TableName + Specs []*AlterTableSpec +} + +// Accept implements Node Accept interface. +func (n *AlterTableStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*AlterTableStmt) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + for i, val := range n.Specs { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.Specs[i] = node.(*AlterTableSpec) + } + return v.Leave(n) +} + +// TruncateTableStmt is a statement to empty a table completely. +// See https://dev.mysql.com/doc/refman/5.7/en/truncate-table.html +type TruncateTableStmt struct { + ddlNode + + Table *TableName +} + +// Accept implements Node Accept interface. +func (n *TruncateTableStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TruncateTableStmt) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + return v.Leave(n) +} + +// PartitionDefinition defines a single partition. +type PartitionDefinition struct { + Name model.CIStr + LessThan []ExprNode + MaxValue bool + Comment string +} + +// PartitionOptions specifies the partition options. +type PartitionOptions struct { + Tp model.PartitionType + Expr ExprNode + ColumnNames []*ColumnName + Definitions []*PartitionDefinition + Num uint64 +} diff --git a/vendor/github.com/pingcap/parser/ast/dml.go b/vendor/github.com/pingcap/parser/ast/dml.go new file mode 100644 index 0000000000000000000000000000000000000000..82268cc7e6aa226b8d29e13335f9b66f5ca87efa --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/dml.go @@ -0,0 +1,1211 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "github.com/pingcap/parser/auth" + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/mysql" +) + +var ( + _ DMLNode = &DeleteStmt{} + _ DMLNode = &InsertStmt{} + _ DMLNode = &UnionStmt{} + _ DMLNode = &UpdateStmt{} + _ DMLNode = &SelectStmt{} + _ DMLNode = &ShowStmt{} + _ DMLNode = &LoadDataStmt{} + + _ Node = &Assignment{} + _ Node = &ByItem{} + _ Node = &FieldList{} + _ Node = &GroupByClause{} + _ Node = &HavingClause{} + _ Node = &Join{} + _ Node = &Limit{} + _ Node = &OnCondition{} + _ Node = &OrderByClause{} + _ Node = &SelectField{} + _ Node = &TableName{} + _ Node = &TableRefsClause{} + _ Node = &TableSource{} + _ Node = &UnionSelectList{} + _ Node = &WildCardField{} + _ Node = &WindowSpec{} + _ Node = &PartitionByClause{} + _ Node = &FrameClause{} + _ Node = &FrameBound{} +) + +// JoinType is join type, including cross/left/right/full. +type JoinType int + +const ( + // CrossJoin is cross join type. + CrossJoin JoinType = iota + 1 + // LeftJoin is left Join type. + LeftJoin + // RightJoin is right Join type. + RightJoin +) + +// Join represents table join. +type Join struct { + node + resultSetNode + + // Left table can be TableSource or JoinNode. + Left ResultSetNode + // Right table can be TableSource or JoinNode or nil. + Right ResultSetNode + // Tp represents join type. + Tp JoinType + // On represents join on condition. + On *OnCondition + // Using represents join using clause. + Using []*ColumnName + // NaturalJoin represents join is natural join. + NaturalJoin bool + // StraightJoin represents a straight join. + StraightJoin bool +} + +// Accept implements Node Accept interface. +func (n *Join) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*Join) + node, ok := n.Left.Accept(v) + if !ok { + return n, false + } + n.Left = node.(ResultSetNode) + if n.Right != nil { + node, ok = n.Right.Accept(v) + if !ok { + return n, false + } + n.Right = node.(ResultSetNode) + } + if n.On != nil { + node, ok = n.On.Accept(v) + if !ok { + return n, false + } + n.On = node.(*OnCondition) + } + return v.Leave(n) +} + +// TableName represents a table name. +type TableName struct { + node + resultSetNode + + Schema model.CIStr + Name model.CIStr + + DBInfo *model.DBInfo + TableInfo *model.TableInfo + + IndexHints []*IndexHint +} + +// IndexHintType is the type for index hint use, ignore or force. +type IndexHintType int + +// IndexHintUseType values. +const ( + HintUse IndexHintType = 1 + HintIgnore IndexHintType = 2 + HintForce IndexHintType = 3 +) + +// IndexHintScope is the type for index hint for join, order by or group by. +type IndexHintScope int + +// Index hint scopes. +const ( + HintForScan IndexHintScope = 1 + HintForJoin IndexHintScope = 2 + HintForOrderBy IndexHintScope = 3 + HintForGroupBy IndexHintScope = 4 +) + +// IndexHint represents a hint for optimizer to use/ignore/force for join/order by/group by. +type IndexHint struct { + IndexNames []model.CIStr + HintType IndexHintType + HintScope IndexHintScope +} + +// Accept implements Node Accept interface. +func (n *TableName) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TableName) + return v.Leave(n) +} + +// DeleteTableList is the tablelist used in delete statement multi-table mode. +type DeleteTableList struct { + node + Tables []*TableName +} + +// Accept implements Node Accept interface. +func (n *DeleteTableList) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DeleteTableList) + if n != nil { + for i, t := range n.Tables { + node, ok := t.Accept(v) + if !ok { + return n, false + } + n.Tables[i] = node.(*TableName) + } + } + return v.Leave(n) +} + +// OnCondition represents JOIN on condition. +type OnCondition struct { + node + + Expr ExprNode +} + +// Accept implements Node Accept interface. +func (n *OnCondition) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*OnCondition) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// TableSource represents table source with a name. +type TableSource struct { + node + + // Source is the source of the data, can be a TableName, + // a SelectStmt, a UnionStmt, or a JoinNode. + Source ResultSetNode + + // AsName is the alias name of the table source. + AsName model.CIStr +} + +// Accept implements Node Accept interface. +func (n *TableSource) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TableSource) + node, ok := n.Source.Accept(v) + if !ok { + return n, false + } + n.Source = node.(ResultSetNode) + return v.Leave(n) +} + +// SelectLockType is the lock type for SelectStmt. +type SelectLockType int + +// Select lock types. +const ( + SelectLockNone SelectLockType = iota + SelectLockForUpdate + SelectLockInShareMode +) + +// String implements fmt.Stringer. +func (slt SelectLockType) String() string { + switch slt { + case SelectLockNone: + return "none" + case SelectLockForUpdate: + return "for update" + case SelectLockInShareMode: + return "in share mode" + } + return "unsupported select lock type" +} + +// WildCardField is a special type of select field content. +type WildCardField struct { + node + + Table model.CIStr + Schema model.CIStr +} + +// Accept implements Node Accept interface. +func (n *WildCardField) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*WildCardField) + return v.Leave(n) +} + +// SelectField represents fields in select statement. +// There are two type of select field: wildcard +// and expression with optional alias name. +type SelectField struct { + node + + // Offset is used to get original text. + Offset int + // WildCard is not nil, Expr will be nil. + WildCard *WildCardField + // Expr is not nil, WildCard will be nil. + Expr ExprNode + // AsName is alias name for Expr. + AsName model.CIStr + // Auxiliary stands for if this field is auxiliary. + // When we add a Field into SelectField list which is used for having/orderby clause but the field is not in select clause, + // we should set its Auxiliary to true. Then the TrimExec will trim the field. + Auxiliary bool +} + +// Accept implements Node Accept interface. +func (n *SelectField) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SelectField) + if n.Expr != nil { + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + } + return v.Leave(n) +} + +// FieldList represents field list in select statement. +type FieldList struct { + node + + Fields []*SelectField +} + +// Accept implements Node Accept interface. +func (n *FieldList) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*FieldList) + for i, val := range n.Fields { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Fields[i] = node.(*SelectField) + } + return v.Leave(n) +} + +// TableRefsClause represents table references clause in dml statement. +type TableRefsClause struct { + node + + TableRefs *Join +} + +// Accept implements Node Accept interface. +func (n *TableRefsClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TableRefsClause) + node, ok := n.TableRefs.Accept(v) + if !ok { + return n, false + } + n.TableRefs = node.(*Join) + return v.Leave(n) +} + +// ByItem represents an item in order by or group by. +type ByItem struct { + node + + Expr ExprNode + Desc bool +} + +// Accept implements Node Accept interface. +func (n *ByItem) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ByItem) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// GroupByClause represents group by clause. +type GroupByClause struct { + node + Items []*ByItem +} + +// Accept implements Node Accept interface. +func (n *GroupByClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*GroupByClause) + for i, val := range n.Items { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Items[i] = node.(*ByItem) + } + return v.Leave(n) +} + +// HavingClause represents having clause. +type HavingClause struct { + node + Expr ExprNode +} + +// Accept implements Node Accept interface. +func (n *HavingClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*HavingClause) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// OrderByClause represents order by clause. +type OrderByClause struct { + node + Items []*ByItem + ForUnion bool +} + +// Accept implements Node Accept interface. +func (n *OrderByClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*OrderByClause) + for i, val := range n.Items { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Items[i] = node.(*ByItem) + } + return v.Leave(n) +} + +// SelectStmt represents the select query node. +// See https://dev.mysql.com/doc/refman/5.7/en/select.html +type SelectStmt struct { + dmlNode + resultSetNode + + // SelectStmtOpts wraps around select hints and switches. + *SelectStmtOpts + // Distinct represents whether the select has distinct option. + Distinct bool + // From is the from clause of the query. + From *TableRefsClause + // Where is the where clause in select statement. + Where ExprNode + // Fields is the select expression list. + Fields *FieldList + // GroupBy is the group by expression list. + GroupBy *GroupByClause + // Having is the having condition. + Having *HavingClause + // WindowSpecs is the window specification list. + WindowSpecs []WindowSpec + // OrderBy is the ordering expression list. + OrderBy *OrderByClause + // Limit is the limit clause. + Limit *Limit + // LockTp is the lock type + LockTp SelectLockType + // TableHints represents the table level Optimizer Hint for join type + TableHints []*TableOptimizerHint + // IsAfterUnionDistinct indicates whether it's a stmt after "union distinct". + IsAfterUnionDistinct bool + // IsInBraces indicates whether it's a stmt in brace. + IsInBraces bool +} + +// Accept implements Node Accept interface. +func (n *SelectStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*SelectStmt) + if n.TableHints != nil && len(n.TableHints) != 0 { + newHints := make([]*TableOptimizerHint, len(n.TableHints)) + for i, hint := range n.TableHints { + node, ok := hint.Accept(v) + if !ok { + return n, false + } + newHints[i] = node.(*TableOptimizerHint) + } + n.TableHints = newHints + } + + if n.From != nil { + node, ok := n.From.Accept(v) + if !ok { + return n, false + } + n.From = node.(*TableRefsClause) + } + + if n.Where != nil { + node, ok := n.Where.Accept(v) + if !ok { + return n, false + } + n.Where = node.(ExprNode) + } + + if n.Fields != nil { + node, ok := n.Fields.Accept(v) + if !ok { + return n, false + } + n.Fields = node.(*FieldList) + } + + if n.GroupBy != nil { + node, ok := n.GroupBy.Accept(v) + if !ok { + return n, false + } + n.GroupBy = node.(*GroupByClause) + } + + if n.Having != nil { + node, ok := n.Having.Accept(v) + if !ok { + return n, false + } + n.Having = node.(*HavingClause) + } + + for i, spec := range n.WindowSpecs { + node, ok := spec.Accept(v) + if !ok { + return n, false + } + n.WindowSpecs[i] = *node.(*WindowSpec) + } + + if n.OrderBy != nil { + node, ok := n.OrderBy.Accept(v) + if !ok { + return n, false + } + n.OrderBy = node.(*OrderByClause) + } + + if n.Limit != nil { + node, ok := n.Limit.Accept(v) + if !ok { + return n, false + } + n.Limit = node.(*Limit) + } + + return v.Leave(n) +} + +// UnionSelectList represents the select list in a union statement. +type UnionSelectList struct { + node + + Selects []*SelectStmt +} + +// Accept implements Node Accept interface. +func (n *UnionSelectList) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*UnionSelectList) + for i, sel := range n.Selects { + node, ok := sel.Accept(v) + if !ok { + return n, false + } + n.Selects[i] = node.(*SelectStmt) + } + return v.Leave(n) +} + +// UnionStmt represents "union statement" +// See https://dev.mysql.com/doc/refman/5.7/en/union.html +type UnionStmt struct { + dmlNode + resultSetNode + + SelectList *UnionSelectList + OrderBy *OrderByClause + Limit *Limit +} + +// Accept implements Node Accept interface. +func (n *UnionStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*UnionStmt) + if n.SelectList != nil { + node, ok := n.SelectList.Accept(v) + if !ok { + return n, false + } + n.SelectList = node.(*UnionSelectList) + } + if n.OrderBy != nil { + node, ok := n.OrderBy.Accept(v) + if !ok { + return n, false + } + n.OrderBy = node.(*OrderByClause) + } + if n.Limit != nil { + node, ok := n.Limit.Accept(v) + if !ok { + return n, false + } + n.Limit = node.(*Limit) + } + return v.Leave(n) +} + +// Assignment is the expression for assignment, like a = 1. +type Assignment struct { + node + // Column is the column name to be assigned. + Column *ColumnName + // Expr is the expression assigning to ColName. + Expr ExprNode +} + +// Accept implements Node Accept interface. +func (n *Assignment) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*Assignment) + node, ok := n.Column.Accept(v) + if !ok { + return n, false + } + n.Column = node.(*ColumnName) + node, ok = n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// LoadDataStmt is a statement to load data from a specified file, then insert this rows into an existing table. +// See https://dev.mysql.com/doc/refman/5.7/en/load-data.html +type LoadDataStmt struct { + dmlNode + + IsLocal bool + Path string + Table *TableName + Columns []*ColumnName + FieldsInfo *FieldsClause + LinesInfo *LinesClause + IgnoreLines uint64 +} + +// Accept implements Node Accept interface. +func (n *LoadDataStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*LoadDataStmt) + if n.Table != nil { + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + } + for i, val := range n.Columns { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Columns[i] = node.(*ColumnName) + } + return v.Leave(n) +} + +// FieldsClause represents fields references clause in load data statement. +type FieldsClause struct { + Terminated string + Enclosed byte + Escaped byte +} + +// LinesClause represents lines references clause in load data statement. +type LinesClause struct { + Starting string + Terminated string +} + +// InsertStmt is a statement to insert new rows into an existing table. +// See https://dev.mysql.com/doc/refman/5.7/en/insert.html +type InsertStmt struct { + dmlNode + + IsReplace bool + IgnoreErr bool + Table *TableRefsClause + Columns []*ColumnName + Lists [][]ExprNode + Setlist []*Assignment + Priority mysql.PriorityEnum + OnDuplicate []*Assignment + Select ResultSetNode +} + +// Accept implements Node Accept interface. +func (n *InsertStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*InsertStmt) + if n.Select != nil { + node, ok := n.Select.Accept(v) + if !ok { + return n, false + } + n.Select = node.(ResultSetNode) + } + + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableRefsClause) + + for i, val := range n.Columns { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Columns[i] = node.(*ColumnName) + } + for i, list := range n.Lists { + for j, val := range list { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Lists[i][j] = node.(ExprNode) + } + } + for i, val := range n.Setlist { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Setlist[i] = node.(*Assignment) + } + for i, val := range n.OnDuplicate { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.OnDuplicate[i] = node.(*Assignment) + } + return v.Leave(n) +} + +// DeleteStmt is a statement to delete rows from table. +// See https://dev.mysql.com/doc/refman/5.7/en/delete.html +type DeleteStmt struct { + dmlNode + + // TableRefs is used in both single table and multiple table delete statement. + TableRefs *TableRefsClause + // Tables is only used in multiple table delete statement. + Tables *DeleteTableList + Where ExprNode + Order *OrderByClause + Limit *Limit + Priority mysql.PriorityEnum + IgnoreErr bool + Quick bool + IsMultiTable bool + BeforeFrom bool + // TableHints represents the table level Optimizer Hint for join type. + TableHints []*TableOptimizerHint +} + +// Accept implements Node Accept interface. +func (n *DeleteStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*DeleteStmt) + node, ok := n.TableRefs.Accept(v) + if !ok { + return n, false + } + n.TableRefs = node.(*TableRefsClause) + + node, ok = n.Tables.Accept(v) + if !ok { + return n, false + } + n.Tables = node.(*DeleteTableList) + + if n.Where != nil { + node, ok = n.Where.Accept(v) + if !ok { + return n, false + } + n.Where = node.(ExprNode) + } + if n.Order != nil { + node, ok = n.Order.Accept(v) + if !ok { + return n, false + } + n.Order = node.(*OrderByClause) + } + if n.Limit != nil { + node, ok = n.Limit.Accept(v) + if !ok { + return n, false + } + n.Limit = node.(*Limit) + } + return v.Leave(n) +} + +// UpdateStmt is a statement to update columns of existing rows in tables with new values. +// See https://dev.mysql.com/doc/refman/5.7/en/update.html +type UpdateStmt struct { + dmlNode + + TableRefs *TableRefsClause + List []*Assignment + Where ExprNode + Order *OrderByClause + Limit *Limit + Priority mysql.PriorityEnum + IgnoreErr bool + MultipleTable bool + TableHints []*TableOptimizerHint +} + +// Accept implements Node Accept interface. +func (n *UpdateStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*UpdateStmt) + node, ok := n.TableRefs.Accept(v) + if !ok { + return n, false + } + n.TableRefs = node.(*TableRefsClause) + for i, val := range n.List { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.List[i] = node.(*Assignment) + } + if n.Where != nil { + node, ok = n.Where.Accept(v) + if !ok { + return n, false + } + n.Where = node.(ExprNode) + } + if n.Order != nil { + node, ok = n.Order.Accept(v) + if !ok { + return n, false + } + n.Order = node.(*OrderByClause) + } + if n.Limit != nil { + node, ok = n.Limit.Accept(v) + if !ok { + return n, false + } + n.Limit = node.(*Limit) + } + return v.Leave(n) +} + +// Limit is the limit clause. +type Limit struct { + node + + Count ExprNode + Offset ExprNode +} + +// Accept implements Node Accept interface. +func (n *Limit) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + if n.Count != nil { + node, ok := n.Count.Accept(v) + if !ok { + return n, false + } + n.Count = node.(ExprNode) + } + if n.Offset != nil { + node, ok := n.Offset.Accept(v) + if !ok { + return n, false + } + n.Offset = node.(ExprNode) + } + + n = newNode.(*Limit) + return v.Leave(n) +} + +// ShowStmtType is the type for SHOW statement. +type ShowStmtType int + +// Show statement types. +const ( + ShowNone = iota + ShowEngines + ShowDatabases + ShowTables + ShowTableStatus + ShowColumns + ShowWarnings + ShowCharset + ShowVariables + ShowStatus + ShowCollation + ShowCreateTable + ShowGrants + ShowTriggers + ShowProcedureStatus + ShowIndex + ShowProcessList + ShowCreateDatabase + ShowEvents + ShowStatsMeta + ShowStatsHistograms + ShowStatsBuckets + ShowStatsHealthy + ShowPlugins + ShowProfiles + ShowMasterStatus + ShowPrivileges + ShowErrors +) + +// ShowStmt is a statement to provide information about databases, tables, columns and so on. +// See https://dev.mysql.com/doc/refman/5.7/en/show.html +type ShowStmt struct { + dmlNode + resultSetNode + + Tp ShowStmtType // Databases/Tables/Columns/.... + DBName string + Table *TableName // Used for showing columns. + Column *ColumnName // Used for `desc table column`. + Flag int // Some flag parsed from sql, such as FULL. + Full bool + User *auth.UserIdentity // Used for show grants. + + // GlobalScope is used by show variables + GlobalScope bool + Pattern *PatternLikeExpr + Where ExprNode +} + +// Accept implements Node Accept interface. +func (n *ShowStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ShowStmt) + if n.Table != nil { + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + } + if n.Column != nil { + node, ok := n.Column.Accept(v) + if !ok { + return n, false + } + n.Column = node.(*ColumnName) + } + if n.Pattern != nil { + node, ok := n.Pattern.Accept(v) + if !ok { + return n, false + } + n.Pattern = node.(*PatternLikeExpr) + } + + switch n.Tp { + case ShowTriggers, ShowProcedureStatus, ShowProcessList, ShowEvents: + // We don't have any data to return for those types, + // but visiting Where may cause resolving error, so return here to avoid error. + return v.Leave(n) + } + + if n.Where != nil { + node, ok := n.Where.Accept(v) + if !ok { + return n, false + } + n.Where = node.(ExprNode) + } + return v.Leave(n) +} + +// WindowSpec is the specification of a window. +type WindowSpec struct { + node + + Name model.CIStr + // Ref is the reference window of this specification. For example, in `w2 as (w1 order by a)`, + // the definition of `w2` references `w1`. + Ref model.CIStr + + PartitionBy *PartitionByClause + OrderBy *OrderByClause + Frame *FrameClause +} + +// Accept implements Node Accept interface. +func (n *WindowSpec) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*WindowSpec) + if n.PartitionBy != nil { + node, ok := n.PartitionBy.Accept(v) + if !ok { + return n, false + } + n.PartitionBy = node.(*PartitionByClause) + } + if n.OrderBy != nil { + node, ok := n.OrderBy.Accept(v) + if !ok { + return n, false + } + n.OrderBy = node.(*OrderByClause) + } + if n.Frame != nil { + node, ok := n.Frame.Accept(v) + if !ok { + return n, false + } + n.Frame = node.(*FrameClause) + } + return v.Leave(n) +} + +// PartitionByClause represents partition by clause. +type PartitionByClause struct { + node + + Items []*ByItem +} + +// Accept implements Node Accept interface. +func (n *PartitionByClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PartitionByClause) + for i, val := range n.Items { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Items[i] = node.(*ByItem) + } + return v.Leave(n) +} + +// FrameType is the type of window function frame. +type FrameType int + +// Window function frame types. +// MySQL only supports `ROWS` and `RANGES`. +const ( + Rows = iota + Ranges + Groups +) + +// FrameClause represents frame clause. +type FrameClause struct { + node + + Type FrameType + Extent FrameExtent +} + +// Accept implements Node Accept interface. +func (n *FrameClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*FrameClause) + node, ok := n.Extent.Start.Accept(v) + if !ok { + return n, false + } + n.Extent.Start = *node.(*FrameBound) + node, ok = n.Extent.End.Accept(v) + if !ok { + return n, false + } + n.Extent.End = *node.(*FrameBound) + return v.Leave(n) +} + +// FrameExtent represents frame extent. +type FrameExtent struct { + Start FrameBound + End FrameBound +} + +// FrameType is the type of window function frame bound. +type BoundType int + +// Frame bound types. +const ( + Following = iota + Preceding + CurrentRow +) + +// FrameBound represents frame bound. +type FrameBound struct { + node + + Type BoundType + UnBounded bool + Expr ExprNode + // `Unit` is used to indicate the units in which the `Expr` should be interpreted. + // For example: '2:30' MINUTE_SECOND. + Unit ExprNode +} + +// Accept implements Node Accept interface. +func (n *FrameBound) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*FrameBound) + if n.Expr != nil { + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + } + if n.Unit != nil { + node, ok := n.Unit.Accept(v) + if !ok { + return n, false + } + n.Unit = node.(ExprNode) + } + return v.Leave(n) +} diff --git a/vendor/github.com/pingcap/parser/ast/expressions.go b/vendor/github.com/pingcap/parser/ast/expressions.go new file mode 100644 index 0000000000000000000000000000000000000000..402f7aed0d55a123b2c17eed0f35437423401435 --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/expressions.go @@ -0,0 +1,923 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "fmt" + "io" + "regexp" + "strings" + + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/opcode" +) + +var ( + _ ExprNode = &BetweenExpr{} + _ ExprNode = &BinaryOperationExpr{} + _ ExprNode = &CaseExpr{} + _ ExprNode = &ColumnNameExpr{} + _ ExprNode = &CompareSubqueryExpr{} + _ ExprNode = &DefaultExpr{} + _ ExprNode = &ExistsSubqueryExpr{} + _ ExprNode = &IsNullExpr{} + _ ExprNode = &IsTruthExpr{} + _ ExprNode = &ParenthesesExpr{} + _ ExprNode = &PatternInExpr{} + _ ExprNode = &PatternLikeExpr{} + _ ExprNode = &PatternRegexpExpr{} + _ ExprNode = &PositionExpr{} + _ ExprNode = &RowExpr{} + _ ExprNode = &SubqueryExpr{} + _ ExprNode = &UnaryOperationExpr{} + _ ExprNode = &ValuesExpr{} + _ ExprNode = &VariableExpr{} + + _ Node = &ColumnName{} + _ Node = &WhenClause{} +) + +// ValueExpr define a interface for ValueExpr. +type ValueExpr interface { + ExprNode + SetValue(val interface{}) + GetValue() interface{} + GetDatumString() string + GetString() string + GetProjectionOffset() int + SetProjectionOffset(offset int) +} + +// NewValueExpr creates a ValueExpr with value, and sets default field type. +var NewValueExpr func(interface{}) ValueExpr + +// NewParamMarkerExpr creates a ParamMarkerExpr. +var NewParamMarkerExpr func(offset int) ParamMarkerExpr + +// BetweenExpr is for "between and" or "not between and" expression. +type BetweenExpr struct { + exprNode + // Expr is the expression to be checked. + Expr ExprNode + // Left is the expression for minimal value in the range. + Left ExprNode + // Right is the expression for maximum value in the range. + Right ExprNode + // Not is true, the expression is "not between and". + Not bool +} + +// Format the ExprNode into a Writer. +func (n *BetweenExpr) Format(w io.Writer) { + n.Expr.Format(w) + if n.Not { + fmt.Fprint(w, " NOT BETWEEN ") + } else { + fmt.Fprint(w, " BETWEEN ") + } + n.Left.Format(w) + fmt.Fprint(w, " AND ") + n.Right.Format(w) +} + +// Accept implements Node interface. +func (n *BetweenExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*BetweenExpr) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + + node, ok = n.Left.Accept(v) + if !ok { + return n, false + } + n.Left = node.(ExprNode) + + node, ok = n.Right.Accept(v) + if !ok { + return n, false + } + n.Right = node.(ExprNode) + + return v.Leave(n) +} + +// BinaryOperationExpr is for binary operation like `1 + 1`, `1 - 1`, etc. +type BinaryOperationExpr struct { + exprNode + // Op is the operator code for BinaryOperation. + Op opcode.Op + // L is the left expression in BinaryOperation. + L ExprNode + // R is the right expression in BinaryOperation. + R ExprNode +} + +// Format the ExprNode into a Writer. +func (n *BinaryOperationExpr) Format(w io.Writer) { + n.L.Format(w) + fmt.Fprint(w, " ") + n.Op.Format(w) + fmt.Fprint(w, " ") + n.R.Format(w) +} + +// Accept implements Node interface. +func (n *BinaryOperationExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*BinaryOperationExpr) + node, ok := n.L.Accept(v) + if !ok { + return n, false + } + n.L = node.(ExprNode) + + node, ok = n.R.Accept(v) + if !ok { + return n, false + } + n.R = node.(ExprNode) + + return v.Leave(n) +} + +// WhenClause is the when clause in Case expression for "when condition then result". +type WhenClause struct { + node + // Expr is the condition expression in WhenClause. + Expr ExprNode + // Result is the result expression in WhenClause. + Result ExprNode +} + +// Accept implements Node Accept interface. +func (n *WhenClause) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*WhenClause) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + + node, ok = n.Result.Accept(v) + if !ok { + return n, false + } + n.Result = node.(ExprNode) + return v.Leave(n) +} + +// CaseExpr is the case expression. +type CaseExpr struct { + exprNode + // Value is the compare value expression. + Value ExprNode + // WhenClauses is the condition check expression. + WhenClauses []*WhenClause + // ElseClause is the else result expression. + ElseClause ExprNode +} + +// Format the ExprNode into a Writer. +func (n *CaseExpr) Format(w io.Writer) { + fmt.Fprint(w, "CASE ") + // Because the presence of `case when` syntax, `Value` could be nil and we need check this. + if n.Value != nil { + n.Value.Format(w) + fmt.Fprint(w, " ") + } + for _, clause := range n.WhenClauses { + fmt.Fprint(w, "WHEN ") + clause.Expr.Format(w) + fmt.Fprint(w, " THEN ") + clause.Result.Format(w) + } + if n.ElseClause != nil { + fmt.Fprint(w, " ELSE ") + n.ElseClause.Format(w) + } + fmt.Fprint(w, " END") +} + +// Accept implements Node Accept interface. +func (n *CaseExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*CaseExpr) + if n.Value != nil { + node, ok := n.Value.Accept(v) + if !ok { + return n, false + } + n.Value = node.(ExprNode) + } + for i, val := range n.WhenClauses { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.WhenClauses[i] = node.(*WhenClause) + } + if n.ElseClause != nil { + node, ok := n.ElseClause.Accept(v) + if !ok { + return n, false + } + n.ElseClause = node.(ExprNode) + } + return v.Leave(n) +} + +// SubqueryExpr represents a subquery. +type SubqueryExpr struct { + exprNode + // Query is the query SelectNode. + Query ResultSetNode + Evaluated bool + Correlated bool + MultiRows bool + Exists bool +} + +// Format the ExprNode into a Writer. +func (n *SubqueryExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *SubqueryExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SubqueryExpr) + node, ok := n.Query.Accept(v) + if !ok { + return n, false + } + n.Query = node.(ResultSetNode) + return v.Leave(n) +} + +// CompareSubqueryExpr is the expression for "expr cmp (select ...)". +// See https://dev.mysql.com/doc/refman/5.7/en/comparisons-using-subqueries.html +// See https://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html +// See https://dev.mysql.com/doc/refman/5.7/en/all-subqueries.html +type CompareSubqueryExpr struct { + exprNode + // L is the left expression + L ExprNode + // Op is the comparison opcode. + Op opcode.Op + // R is the subquery for right expression, may be rewritten to other type of expression. + R ExprNode + // All is true, we should compare all records in subquery. + All bool +} + +// Format the ExprNode into a Writer. +func (n *CompareSubqueryExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *CompareSubqueryExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*CompareSubqueryExpr) + node, ok := n.L.Accept(v) + if !ok { + return n, false + } + n.L = node.(ExprNode) + node, ok = n.R.Accept(v) + if !ok { + return n, false + } + n.R = node.(ExprNode) + return v.Leave(n) +} + +// ColumnName represents column name. +type ColumnName struct { + node + Schema model.CIStr + Table model.CIStr + Name model.CIStr +} + +// Accept implements Node Accept interface. +func (n *ColumnName) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ColumnName) + return v.Leave(n) +} + +// String implements Stringer interface. +func (n *ColumnName) String() string { + result := n.Name.L + if n.Table.L != "" { + result = n.Table.L + "." + result + } + if n.Schema.L != "" { + result = n.Schema.L + "." + result + } + return result +} + +// OrigColName returns the full original column name. +func (n *ColumnName) OrigColName() (ret string) { + ret = n.Name.O + if n.Table.O == "" { + return + } + ret = n.Table.O + "." + ret + if n.Schema.O == "" { + return + } + ret = n.Schema.O + "." + ret + return +} + +// ColumnNameExpr represents a column name expression. +type ColumnNameExpr struct { + exprNode + + // Name is the referenced column name. + Name *ColumnName + + // Refer is the result field the column name refers to. + // The value of Refer.Expr is used as the value of the expression. + Refer *ResultField +} + +// Format the ExprNode into a Writer. +func (n *ColumnNameExpr) Format(w io.Writer) { + name := strings.Replace(n.Name.String(), ".", "`.`", -1) + fmt.Fprintf(w, "`%s`", name) +} + +// Accept implements Node Accept interface. +func (n *ColumnNameExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ColumnNameExpr) + node, ok := n.Name.Accept(v) + if !ok { + return n, false + } + n.Name = node.(*ColumnName) + return v.Leave(n) +} + +// DefaultExpr is the default expression using default value for a column. +type DefaultExpr struct { + exprNode + // Name is the column name. + Name *ColumnName +} + +// Format the ExprNode into a Writer. +func (n *DefaultExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *DefaultExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DefaultExpr) + if n.Name != nil { + node, ok := n.Name.Accept(v) + if !ok { + return n, false + } + n.Name = node.(*ColumnName) + } + return v.Leave(n) +} + +// ExistsSubqueryExpr is the expression for "exists (select ...)". +// See https://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html +type ExistsSubqueryExpr struct { + exprNode + // Sel is the subquery, may be rewritten to other type of expression. + Sel ExprNode + // Not is true, the expression is "not exists". + Not bool +} + +// Format the ExprNode into a Writer. +func (n *ExistsSubqueryExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *ExistsSubqueryExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ExistsSubqueryExpr) + node, ok := n.Sel.Accept(v) + if !ok { + return n, false + } + n.Sel = node.(ExprNode) + return v.Leave(n) +} + +// PatternInExpr is the expression for in operator, like "expr in (1, 2, 3)" or "expr in (select c from t)". +type PatternInExpr struct { + exprNode + // Expr is the value expression to be compared. + Expr ExprNode + // List is the list expression in compare list. + List []ExprNode + // Not is true, the expression is "not in". + Not bool + // Sel is the subquery, may be rewritten to other type of expression. + Sel ExprNode +} + +// Format the ExprNode into a Writer. +func (n *PatternInExpr) Format(w io.Writer) { + n.Expr.Format(w) + if n.Not { + fmt.Fprint(w, " NOT IN (") + } else { + fmt.Fprint(w, " IN (") + } + for i, expr := range n.List { + expr.Format(w) + if i != len(n.List)-1 { + fmt.Fprint(w, ",") + } + } + fmt.Fprint(w, ")") +} + +// Accept implements Node Accept interface. +func (n *PatternInExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PatternInExpr) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + for i, val := range n.List { + node, ok = val.Accept(v) + if !ok { + return n, false + } + n.List[i] = node.(ExprNode) + } + if n.Sel != nil { + node, ok = n.Sel.Accept(v) + if !ok { + return n, false + } + n.Sel = node.(ExprNode) + } + return v.Leave(n) +} + +// IsNullExpr is the expression for null check. +type IsNullExpr struct { + exprNode + // Expr is the expression to be checked. + Expr ExprNode + // Not is true, the expression is "is not null". + Not bool +} + +// Format the ExprNode into a Writer. +func (n *IsNullExpr) Format(w io.Writer) { + n.Expr.Format(w) + if n.Not { + fmt.Fprint(w, " IS NOT NULL") + return + } + fmt.Fprint(w, " IS NULL") +} + +// Accept implements Node Accept interface. +func (n *IsNullExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*IsNullExpr) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// IsTruthExpr is the expression for true/false check. +type IsTruthExpr struct { + exprNode + // Expr is the expression to be checked. + Expr ExprNode + // Not is true, the expression is "is not true/false". + Not bool + // True indicates checking true or false. + True int64 +} + +// Format the ExprNode into a Writer. +func (n *IsTruthExpr) Format(w io.Writer) { + n.Expr.Format(w) + if n.Not { + fmt.Fprint(w, " IS NOT") + } else { + fmt.Fprint(w, " IS") + } + if n.True > 0 { + fmt.Fprint(w, " TRUE") + } else { + fmt.Fprint(w, " FALSE") + } +} + +// Accept implements Node Accept interface. +func (n *IsTruthExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*IsTruthExpr) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// PatternLikeExpr is the expression for like operator, e.g, expr like "%123%" +type PatternLikeExpr struct { + exprNode + // Expr is the expression to be checked. + Expr ExprNode + // Pattern is the like expression. + Pattern ExprNode + // Not is true, the expression is "not like". + Not bool + + Escape byte + + PatChars []byte + PatTypes []byte +} + +// Format the ExprNode into a Writer. +func (n *PatternLikeExpr) Format(w io.Writer) { + n.Expr.Format(w) + if n.Not { + fmt.Fprint(w, " NOT LIKE ") + } else { + fmt.Fprint(w, " LIKE ") + } + n.Pattern.Format(w) + if n.Escape != '\\' { + fmt.Fprint(w, " ESCAPE ") + fmt.Fprintf(w, "'%c'", n.Escape) + } +} + +// Accept implements Node Accept interface. +func (n *PatternLikeExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PatternLikeExpr) + if n.Expr != nil { + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + } + if n.Pattern != nil { + node, ok := n.Pattern.Accept(v) + if !ok { + return n, false + } + n.Pattern = node.(ExprNode) + } + return v.Leave(n) +} + +// ParamMarkerExpr expression holds a place for another expression. +// Used in parsing prepare statement. +type ParamMarkerExpr interface { + ValueExpr + SetOrder(int) +} + +// ParenthesesExpr is the parentheses expression. +type ParenthesesExpr struct { + exprNode + // Expr is the expression in parentheses. + Expr ExprNode +} + +// Format the ExprNode into a Writer. +func (n *ParenthesesExpr) Format(w io.Writer) { + fmt.Fprint(w, "(") + n.Expr.Format(w) + fmt.Fprint(w, ")") +} + +// Accept implements Node Accept interface. +func (n *ParenthesesExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ParenthesesExpr) + if n.Expr != nil { + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + } + return v.Leave(n) +} + +// PositionExpr is the expression for order by and group by position. +// MySQL use position expression started from 1, it looks a little confused inner. +// maybe later we will use 0 at first. +type PositionExpr struct { + exprNode + // N is the position, started from 1 now. + N int + // P is the parameterized position. + P ExprNode + // Refer is the result field the position refers to. + Refer *ResultField +} + +// Format the ExprNode into a Writer. +func (n *PositionExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *PositionExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PositionExpr) + if n.P != nil { + node, ok := n.P.Accept(v) + if !ok { + return n, false + } + n.P = node.(ExprNode) + } + return v.Leave(n) +} + +// PatternRegexpExpr is the pattern expression for pattern match. +type PatternRegexpExpr struct { + exprNode + // Expr is the expression to be checked. + Expr ExprNode + // Pattern is the expression for pattern. + Pattern ExprNode + // Not is true, the expression is "not rlike", + Not bool + + // Re is the compiled regexp. + Re *regexp.Regexp + // Sexpr is the string for Expr expression. + Sexpr *string +} + +// Format the ExprNode into a Writer. +func (n *PatternRegexpExpr) Format(w io.Writer) { + n.Expr.Format(w) + if n.Not { + fmt.Fprint(w, " NOT REGEXP ") + } else { + fmt.Fprint(w, " REGEXP ") + } + n.Pattern.Format(w) +} + +// Accept implements Node Accept interface. +func (n *PatternRegexpExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PatternRegexpExpr) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + node, ok = n.Pattern.Accept(v) + if !ok { + return n, false + } + n.Pattern = node.(ExprNode) + return v.Leave(n) +} + +// RowExpr is the expression for row constructor. +// See https://dev.mysql.com/doc/refman/5.7/en/row-subqueries.html +type RowExpr struct { + exprNode + + Values []ExprNode +} + +// Format the ExprNode into a Writer. +func (n *RowExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *RowExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*RowExpr) + for i, val := range n.Values { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Values[i] = node.(ExprNode) + } + return v.Leave(n) +} + +// UnaryOperationExpr is the expression for unary operator. +type UnaryOperationExpr struct { + exprNode + // Op is the operator opcode. + Op opcode.Op + // V is the unary expression. + V ExprNode +} + +// Format the ExprNode into a Writer. +func (n *UnaryOperationExpr) Format(w io.Writer) { + n.Op.Format(w) + n.V.Format(w) +} + +// Accept implements Node Accept interface. +func (n *UnaryOperationExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*UnaryOperationExpr) + node, ok := n.V.Accept(v) + if !ok { + return n, false + } + n.V = node.(ExprNode) + return v.Leave(n) +} + +// ValuesExpr is the expression used in INSERT VALUES. +type ValuesExpr struct { + exprNode + // Column is column name. + Column *ColumnNameExpr +} + +// Format the ExprNode into a Writer. +func (n *ValuesExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *ValuesExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ValuesExpr) + node, ok := n.Column.Accept(v) + if !ok { + return n, false + } + // `node` may be *ast.ValueExpr, to avoid panic, we write `ok` but do not use + // it. + n.Column, ok = node.(*ColumnNameExpr) + return v.Leave(n) +} + +// VariableExpr is the expression for variable. +type VariableExpr struct { + exprNode + // Name is the variable name. + Name string + // IsGlobal indicates whether this variable is global. + IsGlobal bool + // IsSystem indicates whether this variable is a system variable in current session. + IsSystem bool + // ExplicitScope indicates whether this variable scope is set explicitly. + ExplicitScope bool + // Value is the variable value. + Value ExprNode +} + +// Format the ExprNode into a Writer. +func (n *VariableExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *VariableExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*VariableExpr) + if n.Value == nil { + return v.Leave(n) + } + + node, ok := n.Value.Accept(v) + if !ok { + return n, false + } + n.Value = node.(ExprNode) + return v.Leave(n) +} + +// MaxValueExpr is the expression for "maxvalue" used in partition. +type MaxValueExpr struct { + exprNode +} + +// Format the ExprNode into a Writer. +func (n *MaxValueExpr) Format(w io.Writer) { + fmt.Fprint(w, "MAXVALUE") +} + +// Accept implements Node Accept interface. +func (n *MaxValueExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + return v.Leave(n) +} diff --git a/vendor/github.com/pingcap/parser/ast/flag.go b/vendor/github.com/pingcap/parser/ast/flag.go new file mode 100644 index 0000000000000000000000000000000000000000..773a2b44483e7bca2d9643ab1760b8fcbf8963fe --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/flag.go @@ -0,0 +1,156 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +// HasAggFlag checks if the expr contains FlagHasAggregateFunc. +func HasAggFlag(expr ExprNode) bool { + return expr.GetFlag()&FlagHasAggregateFunc > 0 +} + +// SetFlag sets flag for expression. +func SetFlag(n Node) { + var setter flagSetter + n.Accept(&setter) +} + +type flagSetter struct { +} + +func (f *flagSetter) Enter(in Node) (Node, bool) { + return in, false +} + +func (f *flagSetter) Leave(in Node) (Node, bool) { + if x, ok := in.(ParamMarkerExpr); ok { + x.SetFlag(FlagHasParamMarker) + } + switch x := in.(type) { + case *AggregateFuncExpr: + f.aggregateFunc(x) + case *BetweenExpr: + x.SetFlag(x.Expr.GetFlag() | x.Left.GetFlag() | x.Right.GetFlag()) + case *BinaryOperationExpr: + x.SetFlag(x.L.GetFlag() | x.R.GetFlag()) + case *CaseExpr: + f.caseExpr(x) + case *ColumnNameExpr: + x.SetFlag(FlagHasReference) + case *CompareSubqueryExpr: + x.SetFlag(x.L.GetFlag() | x.R.GetFlag()) + case *DefaultExpr: + x.SetFlag(FlagHasDefault) + case *ExistsSubqueryExpr: + x.SetFlag(x.Sel.GetFlag()) + case *FuncCallExpr: + f.funcCall(x) + case *FuncCastExpr: + x.SetFlag(FlagHasFunc | x.Expr.GetFlag()) + case *IsNullExpr: + x.SetFlag(x.Expr.GetFlag()) + case *IsTruthExpr: + x.SetFlag(x.Expr.GetFlag()) + case *ParenthesesExpr: + x.SetFlag(x.Expr.GetFlag()) + case *PatternInExpr: + f.patternIn(x) + case *PatternLikeExpr: + f.patternLike(x) + case *PatternRegexpExpr: + f.patternRegexp(x) + case *PositionExpr: + x.SetFlag(FlagHasReference) + case *RowExpr: + f.row(x) + case *SubqueryExpr: + x.SetFlag(FlagHasSubquery) + case *UnaryOperationExpr: + x.SetFlag(x.V.GetFlag()) + case *ValuesExpr: + x.SetFlag(FlagHasReference) + case *VariableExpr: + if x.Value == nil { + x.SetFlag(FlagHasVariable) + } else { + x.SetFlag(FlagHasVariable | x.Value.GetFlag()) + } + } + + return in, true +} + +func (f *flagSetter) caseExpr(x *CaseExpr) { + var flag uint64 + if x.Value != nil { + flag |= x.Value.GetFlag() + } + for _, val := range x.WhenClauses { + flag |= val.Expr.GetFlag() + flag |= val.Result.GetFlag() + } + if x.ElseClause != nil { + flag |= x.ElseClause.GetFlag() + } + x.SetFlag(flag) +} + +func (f *flagSetter) patternIn(x *PatternInExpr) { + flag := x.Expr.GetFlag() + for _, val := range x.List { + flag |= val.GetFlag() + } + if x.Sel != nil { + flag |= x.Sel.GetFlag() + } + x.SetFlag(flag) +} + +func (f *flagSetter) patternLike(x *PatternLikeExpr) { + flag := x.Pattern.GetFlag() + if x.Expr != nil { + flag |= x.Expr.GetFlag() + } + x.SetFlag(flag) +} + +func (f *flagSetter) patternRegexp(x *PatternRegexpExpr) { + flag := x.Pattern.GetFlag() + if x.Expr != nil { + flag |= x.Expr.GetFlag() + } + x.SetFlag(flag) +} + +func (f *flagSetter) row(x *RowExpr) { + var flag uint64 + for _, val := range x.Values { + flag |= val.GetFlag() + } + x.SetFlag(flag) +} + +func (f *flagSetter) funcCall(x *FuncCallExpr) { + flag := FlagHasFunc + for _, val := range x.Args { + flag |= val.GetFlag() + } + x.SetFlag(flag) +} + +func (f *flagSetter) aggregateFunc(x *AggregateFuncExpr) { + flag := FlagHasAggregateFunc + for _, val := range x.Args { + flag |= val.GetFlag() + } + x.SetFlag(flag) +} diff --git a/vendor/github.com/pingcap/parser/ast/functions.go b/vendor/github.com/pingcap/parser/ast/functions.go new file mode 100644 index 0000000000000000000000000000000000000000..6363296bf95279a7291e8d4b73c951e027d1f9a7 --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/functions.go @@ -0,0 +1,599 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "fmt" + "io" + + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/types" +) + +var ( + _ FuncNode = &AggregateFuncExpr{} + _ FuncNode = &FuncCallExpr{} + _ FuncNode = &FuncCastExpr{} + _ FuncNode = &WindowFuncExpr{} +) + +// List scalar function names. +const ( + LogicAnd = "and" + Cast = "cast" + LeftShift = "leftshift" + RightShift = "rightshift" + LogicOr = "or" + GE = "ge" + LE = "le" + EQ = "eq" + NE = "ne" + LT = "lt" + GT = "gt" + Plus = "plus" + Minus = "minus" + And = "bitand" + Or = "bitor" + Mod = "mod" + Xor = "bitxor" + Div = "div" + Mul = "mul" + UnaryNot = "not" // Avoid name conflict with Not in github/pingcap/check. + BitNeg = "bitneg" + IntDiv = "intdiv" + LogicXor = "xor" + NullEQ = "nulleq" + UnaryPlus = "unaryplus" + UnaryMinus = "unaryminus" + In = "in" + Like = "like" + Case = "case" + Regexp = "regexp" + IsNull = "isnull" + IsTruth = "istrue" // Avoid name conflict with IsTrue in github/pingcap/check. + IsFalsity = "isfalse" // Avoid name conflict with IsFalse in github/pingcap/check. + RowFunc = "row" + SetVar = "setvar" + GetVar = "getvar" + Values = "values" + BitCount = "bit_count" + GetParam = "getparam" + + // common functions + Coalesce = "coalesce" + Greatest = "greatest" + Least = "least" + Interval = "interval" + + // math functions + Abs = "abs" + Acos = "acos" + Asin = "asin" + Atan = "atan" + Atan2 = "atan2" + Ceil = "ceil" + Ceiling = "ceiling" + Conv = "conv" + Cos = "cos" + Cot = "cot" + CRC32 = "crc32" + Degrees = "degrees" + Exp = "exp" + Floor = "floor" + Ln = "ln" + Log = "log" + Log2 = "log2" + Log10 = "log10" + PI = "pi" + Pow = "pow" + Power = "power" + Radians = "radians" + Rand = "rand" + Round = "round" + Sign = "sign" + Sin = "sin" + Sqrt = "sqrt" + Tan = "tan" + Truncate = "truncate" + + // time functions + AddDate = "adddate" + AddTime = "addtime" + ConvertTz = "convert_tz" + Curdate = "curdate" + CurrentDate = "current_date" + CurrentTime = "current_time" + CurrentTimestamp = "current_timestamp" + Curtime = "curtime" + Date = "date" + DateLiteral = "dateliteral" + DateAdd = "date_add" + DateFormat = "date_format" + DateSub = "date_sub" + DateDiff = "datediff" + Day = "day" + DayName = "dayname" + DayOfMonth = "dayofmonth" + DayOfWeek = "dayofweek" + DayOfYear = "dayofyear" + Extract = "extract" + FromDays = "from_days" + FromUnixTime = "from_unixtime" + GetFormat = "get_format" + Hour = "hour" + LocalTime = "localtime" + LocalTimestamp = "localtimestamp" + MakeDate = "makedate" + MakeTime = "maketime" + MicroSecond = "microsecond" + Minute = "minute" + Month = "month" + MonthName = "monthname" + Now = "now" + PeriodAdd = "period_add" + PeriodDiff = "period_diff" + Quarter = "quarter" + SecToTime = "sec_to_time" + Second = "second" + StrToDate = "str_to_date" + SubDate = "subdate" + SubTime = "subtime" + Sysdate = "sysdate" + Time = "time" + TimeLiteral = "timeliteral" + TimeFormat = "time_format" + TimeToSec = "time_to_sec" + TimeDiff = "timediff" + Timestamp = "timestamp" + TimestampLiteral = "timestampliteral" + TimestampAdd = "timestampadd" + TimestampDiff = "timestampdiff" + ToDays = "to_days" + ToSeconds = "to_seconds" + UnixTimestamp = "unix_timestamp" + UTCDate = "utc_date" + UTCTime = "utc_time" + UTCTimestamp = "utc_timestamp" + Week = "week" + Weekday = "weekday" + WeekOfYear = "weekofyear" + Year = "year" + YearWeek = "yearweek" + LastDay = "last_day" + TiDBParseTso = "tidb_parse_tso" + + // string functions + ASCII = "ascii" + Bin = "bin" + Concat = "concat" + ConcatWS = "concat_ws" + Convert = "convert" + Elt = "elt" + ExportSet = "export_set" + Field = "field" + Format = "format" + FromBase64 = "from_base64" + InsertFunc = "insert_func" + Instr = "instr" + Lcase = "lcase" + Left = "left" + Length = "length" + LoadFile = "load_file" + Locate = "locate" + Lower = "lower" + Lpad = "lpad" + LTrim = "ltrim" + MakeSet = "make_set" + Mid = "mid" + Oct = "oct" + Ord = "ord" + Position = "position" + Quote = "quote" + Repeat = "repeat" + Replace = "replace" + Reverse = "reverse" + Right = "right" + RTrim = "rtrim" + Space = "space" + Strcmp = "strcmp" + Substring = "substring" + Substr = "substr" + SubstringIndex = "substring_index" + ToBase64 = "to_base64" + Trim = "trim" + Upper = "upper" + Ucase = "ucase" + Hex = "hex" + Unhex = "unhex" + Rpad = "rpad" + BitLength = "bit_length" + CharFunc = "char_func" + CharLength = "char_length" + CharacterLength = "character_length" + FindInSet = "find_in_set" + + // information functions + Benchmark = "benchmark" + Charset = "charset" + Coercibility = "coercibility" + Collation = "collation" + ConnectionID = "connection_id" + CurrentUser = "current_user" + Database = "database" + FoundRows = "found_rows" + LastInsertId = "last_insert_id" + RowCount = "row_count" + Schema = "schema" + SessionUser = "session_user" + SystemUser = "system_user" + User = "user" + Version = "version" + TiDBVersion = "tidb_version" + TiDBIsDDLOwner = "tidb_is_ddl_owner" + + // control functions + If = "if" + Ifnull = "ifnull" + Nullif = "nullif" + + // miscellaneous functions + AnyValue = "any_value" + DefaultFunc = "default_func" + InetAton = "inet_aton" + InetNtoa = "inet_ntoa" + Inet6Aton = "inet6_aton" + Inet6Ntoa = "inet6_ntoa" + IsFreeLock = "is_free_lock" + IsIPv4 = "is_ipv4" + IsIPv4Compat = "is_ipv4_compat" + IsIPv4Mapped = "is_ipv4_mapped" + IsIPv6 = "is_ipv6" + IsUsedLock = "is_used_lock" + MasterPosWait = "master_pos_wait" + NameConst = "name_const" + ReleaseAllLocks = "release_all_locks" + Sleep = "sleep" + UUID = "uuid" + UUIDShort = "uuid_short" + // get_lock() and release_lock() is parsed but do nothing. + // It is used for preventing error in Ruby's activerecord migrations. + GetLock = "get_lock" + ReleaseLock = "release_lock" + + // encryption and compression functions + AesDecrypt = "aes_decrypt" + AesEncrypt = "aes_encrypt" + Compress = "compress" + Decode = "decode" + DesDecrypt = "des_decrypt" + DesEncrypt = "des_encrypt" + Encode = "encode" + Encrypt = "encrypt" + MD5 = "md5" + OldPassword = "old_password" + PasswordFunc = "password_func" + RandomBytes = "random_bytes" + SHA1 = "sha1" + SHA = "sha" + SHA2 = "sha2" + Uncompress = "uncompress" + UncompressedLength = "uncompressed_length" + ValidatePasswordStrength = "validate_password_strength" + + // json functions + JSONType = "json_type" + JSONExtract = "json_extract" + JSONUnquote = "json_unquote" + JSONArray = "json_array" + JSONObject = "json_object" + JSONMerge = "json_merge" + JSONSet = "json_set" + JSONInsert = "json_insert" + JSONReplace = "json_replace" + JSONRemove = "json_remove" + JSONContains = "json_contains" + JSONContainsPath = "json_contains_path" + JSONValid = "json_valid" + JSONArrayAppend = "json_array_append" + JSONArrayInsert = "json_array_insert" + JSONMergePatch = "json_merge_patch" + JSONMergePreserve = "json_merge_preserve" + JSONPretty = "json_pretty" + JSONQuote = "json_quote" + JSONSearch = "json_search" + JSONStorageSize = "json_storage_size" + JSONDepth = "json_depth" + JSONKeys = "json_keys" + JSONLength = "json_length" +) + +// FuncCallExpr is for function expression. +type FuncCallExpr struct { + funcNode + // FnName is the function name. + FnName model.CIStr + // Args is the function args. + Args []ExprNode +} + +// Format the ExprNode into a Writer. +func (n *FuncCallExpr) Format(w io.Writer) { + fmt.Fprintf(w, "%s(", n.FnName.L) + if !n.specialFormatArgs(w) { + for i, arg := range n.Args { + arg.Format(w) + if i != len(n.Args)-1 { + fmt.Fprint(w, ", ") + } + } + } + fmt.Fprint(w, ")") +} + +// specialFormatArgs formats argument list for some special functions. +func (n *FuncCallExpr) specialFormatArgs(w io.Writer) bool { + switch n.FnName.L { + case DateAdd, DateSub, AddDate, SubDate: + n.Args[0].Format(w) + fmt.Fprint(w, ", INTERVAL ") + n.Args[1].Format(w) + fmt.Fprintf(w, " %s", n.Args[2].(ValueExpr).GetDatumString()) + return true + case TimestampAdd, TimestampDiff: + fmt.Fprintf(w, "%s, ", n.Args[0].(ValueExpr).GetDatumString()) + n.Args[1].Format(w) + fmt.Fprint(w, ", ") + n.Args[2].Format(w) + return true + } + return false +} + +// Accept implements Node interface. +func (n *FuncCallExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*FuncCallExpr) + for i, val := range n.Args { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Args[i] = node.(ExprNode) + } + return v.Leave(n) +} + +// CastFunctionType is the type for cast function. +type CastFunctionType int + +// CastFunction types +const ( + CastFunction CastFunctionType = iota + 1 + CastConvertFunction + CastBinaryOperator +) + +// FuncCastExpr is the cast function converting value to another type, e.g, cast(expr AS signed). +// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html +type FuncCastExpr struct { + funcNode + // Expr is the expression to be converted. + Expr ExprNode + // Tp is the conversion type. + Tp *types.FieldType + // FunctionType is either Cast, Convert or Binary. + FunctionType CastFunctionType +} + +// Format the ExprNode into a Writer. +func (n *FuncCastExpr) Format(w io.Writer) { + switch n.FunctionType { + case CastFunction: + fmt.Fprint(w, "CAST(") + n.Expr.Format(w) + fmt.Fprint(w, " AS ") + n.Tp.FormatAsCastType(w) + fmt.Fprint(w, ")") + case CastConvertFunction: + fmt.Fprint(w, "CONVERT(") + n.Expr.Format(w) + fmt.Fprint(w, ", ") + n.Tp.FormatAsCastType(w) + fmt.Fprint(w, ")") + case CastBinaryOperator: + fmt.Fprint(w, "BINARY ") + n.Expr.Format(w) + } +} + +// Accept implements Node Accept interface. +func (n *FuncCastExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*FuncCastExpr) + node, ok := n.Expr.Accept(v) + if !ok { + return n, false + } + n.Expr = node.(ExprNode) + return v.Leave(n) +} + +// TrimDirectionType is the type for trim direction. +type TrimDirectionType int + +const ( + // TrimBothDefault trims from both direction by default. + TrimBothDefault TrimDirectionType = iota + // TrimBoth trims from both direction with explicit notation. + TrimBoth + // TrimLeading trims from left. + TrimLeading + // TrimTrailing trims from right. + TrimTrailing +) + +// DateArithType is type for DateArith type. +type DateArithType byte + +const ( + // DateArithAdd is to run adddate or date_add function option. + // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate + // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-add + DateArithAdd DateArithType = iota + 1 + // DateArithSub is to run subdate or date_sub function option. + // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate + // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-sub + DateArithSub +) + +const ( + // AggFuncCount is the name of Count function. + AggFuncCount = "count" + // AggFuncSum is the name of Sum function. + AggFuncSum = "sum" + // AggFuncAvg is the name of Avg function. + AggFuncAvg = "avg" + // AggFuncFirstRow is the name of FirstRowColumn function. + AggFuncFirstRow = "firstrow" + // AggFuncMax is the name of max function. + AggFuncMax = "max" + // AggFuncMin is the name of min function. + AggFuncMin = "min" + // AggFuncGroupConcat is the name of group_concat function. + AggFuncGroupConcat = "group_concat" + // AggFuncBitOr is the name of bit_or function. + AggFuncBitOr = "bit_or" + // AggFuncBitXor is the name of bit_xor function. + AggFuncBitXor = "bit_xor" + // AggFuncBitAnd is the name of bit_and function. + AggFuncBitAnd = "bit_and" + // AggFuncStddevPop is the name of stddev_pop function + AggFuncStddevPop = "stddev_pop" + // AggFuncStddevSamp is the name of stddev_samp function + AggFuncStddevSamp = "stddev_samp" +) + +// AggregateFuncExpr represents aggregate function expression. +type AggregateFuncExpr struct { + funcNode + // F is the function name. + F string + // Args is the function args. + Args []ExprNode + // Distinct is true, function hence only aggregate distinct values. + // For example, column c1 values are "1", "2", "2", "sum(c1)" is "5", + // but "sum(distinct c1)" is "3". + Distinct bool +} + +// Format the ExprNode into a Writer. +func (n *AggregateFuncExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *AggregateFuncExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*AggregateFuncExpr) + for i, val := range n.Args { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Args[i] = node.(ExprNode) + } + return v.Leave(n) +} + +const ( + // WindowFuncRowNumber is the name of row_number function. + WindowFuncRowNumber = "row_number" + // WindowFuncRank is the name of rank function. + WindowFuncRank = "rank" + // WindowFuncDenseRank is the name of dense_rank function. + WindowFuncDenseRank = "dense_rank" + // WindowFuncCumeDist is the name of cume_dist function. + WindowFuncCumeDist = "cume_dist" + // WindowFuncPercentRank is the name of percent_rank function. + WindowFuncPercentRank = "percent_rank" + // WindowFuncNtile is the name of ntile function. + WindowFuncNtile = "ntile" + // WindowFuncLead is the name of lead function. + WindowFuncLead = "lead" + // WindowFuncLag is the name of lag function. + WindowFuncLag = "lag" + // WindowFuncFirstValue is the name of first_value function. + WindowFuncFirstValue = "first_value" + // WindowFuncLastValue is the name of last_value function. + WindowFuncLastValue = "last_value" + // WindowFuncNthValue is the name of nth_value function. + WindowFuncNthValue = "nth_value" +) + +// WindowFuncExpr represents window function expression. +type WindowFuncExpr struct { + funcNode + + // F is the function name. + F string + // Args is the function args. + Args []ExprNode + // Distinct cannot be true for most window functions, except `max` and `min`. + // We need to raise error if it is not allowed to be true. + Distinct bool + // IgnoreNull indicates how to handle null value. + // MySQL only supports `RESPECT NULLS`, so we need to raise error if it is true. + IgnoreNull bool + // FromLast indicates the calculation direction of this window function. + // MySQL only supports calculation from first, so we need to raise error if it is true. + FromLast bool + // Spec is the specification of this window. + Spec WindowSpec +} + +// Format formats the window function expression into a Writer. +func (n *WindowFuncExpr) Format(w io.Writer) { + panic("Not implemented") +} + +// Accept implements Node Accept interface. +func (n *WindowFuncExpr) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*WindowFuncExpr) + for i, val := range n.Args { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Args[i] = node.(ExprNode) + } + node, ok := n.Spec.Accept(v) + if !ok { + return n, false + } + n.Spec = *node.(*WindowSpec) + return v.Leave(n) +} diff --git a/vendor/github.com/pingcap/parser/ast/misc.go b/vendor/github.com/pingcap/parser/ast/misc.go new file mode 100644 index 0000000000000000000000000000000000000000..fdcc569d238be42c117de1c4a971dde89c71626d --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/misc.go @@ -0,0 +1,880 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "bytes" + "fmt" + "strings" + + "github.com/pingcap/parser/auth" + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/mysql" +) + +var ( + _ StmtNode = &AdminStmt{} + _ StmtNode = &AlterUserStmt{} + _ StmtNode = &BeginStmt{} + _ StmtNode = &BinlogStmt{} + _ StmtNode = &CommitStmt{} + _ StmtNode = &CreateUserStmt{} + _ StmtNode = &DeallocateStmt{} + _ StmtNode = &DoStmt{} + _ StmtNode = &ExecuteStmt{} + _ StmtNode = &ExplainStmt{} + _ StmtNode = &GrantStmt{} + _ StmtNode = &PrepareStmt{} + _ StmtNode = &RollbackStmt{} + _ StmtNode = &SetPwdStmt{} + _ StmtNode = &SetStmt{} + _ StmtNode = &UseStmt{} + _ StmtNode = &FlushStmt{} + _ StmtNode = &KillStmt{} + + _ Node = &PrivElem{} + _ Node = &VariableAssignment{} +) + +// Isolation level constants. +const ( + ReadCommitted = "READ-COMMITTED" + ReadUncommitted = "READ-UNCOMMITTED" + Serializable = "SERIALIZABLE" + RepeatableRead = "REPEATABLE-READ" + + // Valid formats for explain statement. + ExplainFormatROW = "row" + ExplainFormatDOT = "dot" +) + +var ( + // ExplainFormats stores the valid formats for explain statement, used by validator. + ExplainFormats = []string{ + ExplainFormatROW, + ExplainFormatDOT, + } +) + +// TypeOpt is used for parsing data type option from SQL. +type TypeOpt struct { + IsUnsigned bool + IsZerofill bool +} + +// FloatOpt is used for parsing floating-point type option from SQL. +// See http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html +type FloatOpt struct { + Flen int + Decimal int +} + +// AuthOption is used for parsing create use statement. +type AuthOption struct { + // ByAuthString set as true, if AuthString is used for authorization. Otherwise, authorization is done by HashString. + ByAuthString bool + AuthString string + HashString string + // TODO: support auth_plugin +} + +// TraceStmt is a statement to trace what sql actually does at background. +type TraceStmt struct { + stmtNode + + Stmt StmtNode + Format string +} + +// Accept implements Node Accept interface. +func (n *TraceStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TraceStmt) + node, ok := n.Stmt.Accept(v) + if !ok { + return n, false + } + n.Stmt = node.(DMLNode) + return v.Leave(n) +} + +// ExplainStmt is a statement to provide information about how is SQL statement executed +// or get columns information in a table. +// See https://dev.mysql.com/doc/refman/5.7/en/explain.html +type ExplainStmt struct { + stmtNode + + Stmt StmtNode + Format string + Analyze bool +} + +// Accept implements Node Accept interface. +func (n *ExplainStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ExplainStmt) + node, ok := n.Stmt.Accept(v) + if !ok { + return n, false + } + n.Stmt = node.(DMLNode) + return v.Leave(n) +} + +// PrepareStmt is a statement to prepares a SQL statement which contains placeholders, +// and it is executed with ExecuteStmt and released with DeallocateStmt. +// See https://dev.mysql.com/doc/refman/5.7/en/prepare.html +type PrepareStmt struct { + stmtNode + + Name string + SQLText string + SQLVar *VariableExpr +} + +// Accept implements Node Accept interface. +func (n *PrepareStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PrepareStmt) + if n.SQLVar != nil { + node, ok := n.SQLVar.Accept(v) + if !ok { + return n, false + } + n.SQLVar = node.(*VariableExpr) + } + return v.Leave(n) +} + +// DeallocateStmt is a statement to release PreparedStmt. +// See https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html +type DeallocateStmt struct { + stmtNode + + Name string +} + +// Accept implements Node Accept interface. +func (n *DeallocateStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DeallocateStmt) + return v.Leave(n) +} + +// Prepared represents a prepared statement. +type Prepared struct { + Stmt StmtNode + Params []ParamMarkerExpr + SchemaVersion int64 + UseCache bool +} + +// ExecuteStmt is a statement to execute PreparedStmt. +// See https://dev.mysql.com/doc/refman/5.7/en/execute.html +type ExecuteStmt struct { + stmtNode + + Name string + UsingVars []ExprNode + ExecID uint32 +} + +// Accept implements Node Accept interface. +func (n *ExecuteStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*ExecuteStmt) + for i, val := range n.UsingVars { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.UsingVars[i] = node.(ExprNode) + } + return v.Leave(n) +} + +// BeginStmt is a statement to start a new transaction. +// See https://dev.mysql.com/doc/refman/5.7/en/commit.html +type BeginStmt struct { + stmtNode +} + +// Accept implements Node Accept interface. +func (n *BeginStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*BeginStmt) + return v.Leave(n) +} + +// BinlogStmt is an internal-use statement. +// We just parse and ignore it. +// See http://dev.mysql.com/doc/refman/5.7/en/binlog.html +type BinlogStmt struct { + stmtNode + Str string +} + +// Accept implements Node Accept interface. +func (n *BinlogStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*BinlogStmt) + return v.Leave(n) +} + +// CommitStmt is a statement to commit the current transaction. +// See https://dev.mysql.com/doc/refman/5.7/en/commit.html +type CommitStmt struct { + stmtNode +} + +// Accept implements Node Accept interface. +func (n *CommitStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*CommitStmt) + return v.Leave(n) +} + +// RollbackStmt is a statement to roll back the current transaction. +// See https://dev.mysql.com/doc/refman/5.7/en/commit.html +type RollbackStmt struct { + stmtNode +} + +// Accept implements Node Accept interface. +func (n *RollbackStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*RollbackStmt) + return v.Leave(n) +} + +// UseStmt is a statement to use the DBName database as the current database. +// See https://dev.mysql.com/doc/refman/5.7/en/use.html +type UseStmt struct { + stmtNode + + DBName string +} + +// Accept implements Node Accept interface. +func (n *UseStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*UseStmt) + return v.Leave(n) +} + +const ( + // SetNames is the const for set names/charset stmt. + // If VariableAssignment.Name == Names, it should be set names/charset stmt. + SetNames = "SetNAMES" +) + +// VariableAssignment is a variable assignment struct. +type VariableAssignment struct { + node + Name string + Value ExprNode + IsGlobal bool + IsSystem bool + + // ExtendValue is a way to store extended info. + // VariableAssignment should be able to store information for SetCharset/SetPWD Stmt. + // For SetCharsetStmt, Value is charset, ExtendValue is collation. + // TODO: Use SetStmt to implement set password statement. + ExtendValue ValueExpr +} + +// Accept implements Node interface. +func (n *VariableAssignment) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*VariableAssignment) + node, ok := n.Value.Accept(v) + if !ok { + return n, false + } + n.Value = node.(ExprNode) + return v.Leave(n) +} + +// FlushStmtType is the type for FLUSH statement. +type FlushStmtType int + +// Flush statement types. +const ( + FlushNone FlushStmtType = iota + FlushTables + FlushPrivileges + FlushStatus +) + +// FlushStmt is a statement to flush tables/privileges/optimizer costs and so on. +type FlushStmt struct { + stmtNode + + Tp FlushStmtType // Privileges/Tables/... + NoWriteToBinLog bool + Tables []*TableName // For FlushTableStmt, if Tables is empty, it means flush all tables. + ReadLock bool +} + +// Accept implements Node Accept interface. +func (n *FlushStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*FlushStmt) + return v.Leave(n) +} + +// KillStmt is a statement to kill a query or connection. +type KillStmt struct { + stmtNode + + // Query indicates whether terminate a single query on this connection or the whole connection. + // If Query is true, terminates the statement the connection is currently executing, but leaves the connection itself intact. + // If Query is false, terminates the connection associated with the given ConnectionID, after terminating any statement the connection is executing. + Query bool + ConnectionID uint64 + // TiDBExtension is used to indicate whether the user knows he is sending kill statement to the right tidb-server. + // When the SQL grammar is "KILL TIDB [CONNECTION | QUERY] connectionID", TiDBExtension will be set. + // It's a special grammar extension in TiDB. This extension exists because, when the connection is: + // client -> LVS proxy -> TiDB, and type Ctrl+C in client, the following action will be executed: + // new a connection; kill xxx; + // kill command may send to the wrong TiDB, because the exists of LVS proxy, and kill the wrong session. + // So, "KILL TIDB" grammar is introduced, and it REQUIRES DIRECT client -> TiDB TOPOLOGY. + // TODO: The standard KILL grammar will be supported once we have global connectionID. + TiDBExtension bool +} + +// Accept implements Node Accept interface. +func (n *KillStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*KillStmt) + return v.Leave(n) +} + +// SetStmt is the statement to set variables. +type SetStmt struct { + stmtNode + // Variables is the list of variable assignment. + Variables []*VariableAssignment +} + +// Accept implements Node Accept interface. +func (n *SetStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SetStmt) + for i, val := range n.Variables { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Variables[i] = node.(*VariableAssignment) + } + return v.Leave(n) +} + +/* +// SetCharsetStmt is a statement to assign values to character and collation variables. +// See https://dev.mysql.com/doc/refman/5.7/en/set-statement.html +type SetCharsetStmt struct { + stmtNode + + Charset string + Collate string +} + +// Accept implements Node Accept interface. +func (n *SetCharsetStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SetCharsetStmt) + return v.Leave(n) +} +*/ + +// SetPwdStmt is a statement to assign a password to user account. +// See https://dev.mysql.com/doc/refman/5.7/en/set-password.html +type SetPwdStmt struct { + stmtNode + + User *auth.UserIdentity + Password string +} + +// SecureText implements SensitiveStatement interface. +func (n *SetPwdStmt) SecureText() string { + return fmt.Sprintf("set password for user %s", n.User) +} + +// Accept implements Node Accept interface. +func (n *SetPwdStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*SetPwdStmt) + return v.Leave(n) +} + +// UserSpec is used for parsing create user statement. +type UserSpec struct { + User *auth.UserIdentity + AuthOpt *AuthOption +} + +// SecurityString formats the UserSpec without password information. +func (u *UserSpec) SecurityString() string { + withPassword := false + if opt := u.AuthOpt; opt != nil { + if len(opt.AuthString) > 0 || len(opt.HashString) > 0 { + withPassword = true + } + } + if withPassword { + return fmt.Sprintf("{%s password = ***}", u.User) + } + return u.User.String() +} + +// EncodedPassword returns the encoded password (which is the real data mysql.user). +// The boolean value indicates input's password format is legal or not. +func (u *UserSpec) EncodedPassword() (string, bool) { + if u.AuthOpt == nil { + return "", true + } + + opt := u.AuthOpt + if opt.ByAuthString { + return auth.EncodePassword(opt.AuthString), true + } + + // Not a legal password string. + if len(opt.HashString) != 41 || !strings.HasPrefix(opt.HashString, "*") { + return "", false + } + return opt.HashString, true +} + +// CreateUserStmt creates user account. +// See https://dev.mysql.com/doc/refman/5.7/en/create-user.html +type CreateUserStmt struct { + stmtNode + + IfNotExists bool + Specs []*UserSpec +} + +// Accept implements Node Accept interface. +func (n *CreateUserStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*CreateUserStmt) + return v.Leave(n) +} + +// SecureText implements SensitiveStatement interface. +func (n *CreateUserStmt) SecureText() string { + var buf bytes.Buffer + buf.WriteString("create user") + for _, user := range n.Specs { + buf.WriteString(" ") + buf.WriteString(user.SecurityString()) + } + return buf.String() +} + +// AlterUserStmt modifies user account. +// See https://dev.mysql.com/doc/refman/5.7/en/alter-user.html +type AlterUserStmt struct { + stmtNode + + IfExists bool + CurrentAuth *AuthOption + Specs []*UserSpec +} + +// SecureText implements SensitiveStatement interface. +func (n *AlterUserStmt) SecureText() string { + var buf bytes.Buffer + buf.WriteString("alter user") + for _, user := range n.Specs { + buf.WriteString(" ") + buf.WriteString(user.SecurityString()) + } + return buf.String() +} + +// Accept implements Node Accept interface. +func (n *AlterUserStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*AlterUserStmt) + return v.Leave(n) +} + +// DropUserStmt creates user account. +// See http://dev.mysql.com/doc/refman/5.7/en/drop-user.html +type DropUserStmt struct { + stmtNode + + IfExists bool + UserList []*auth.UserIdentity +} + +// Accept implements Node Accept interface. +func (n *DropUserStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DropUserStmt) + return v.Leave(n) +} + +// DoStmt is the struct for DO statement. +type DoStmt struct { + stmtNode + + Exprs []ExprNode +} + +// Accept implements Node Accept interface. +func (n *DoStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DoStmt) + for i, val := range n.Exprs { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Exprs[i] = node.(ExprNode) + } + return v.Leave(n) +} + +// AdminStmtType is the type for admin statement. +type AdminStmtType int + +// Admin statement types. +const ( + AdminShowDDL = iota + 1 + AdminCheckTable + AdminShowDDLJobs + AdminCancelDDLJobs + AdminCheckIndex + AdminRecoverIndex + AdminCleanupIndex + AdminCheckIndexRange + AdminShowDDLJobQueries + AdminChecksumTable + AdminShowSlow + AdminShowNextRowID +) + +// HandleRange represents a range where handle value >= Begin and < End. +type HandleRange struct { + Begin int64 + End int64 +} + +// ShowSlowType defines the type for SlowSlow statement. +type ShowSlowType int + +const ( + // ShowSlowTop is a ShowSlowType constant. + ShowSlowTop ShowSlowType = iota + // ShowSlowRecent is a ShowSlowType constant. + ShowSlowRecent +) + +// ShowSlowKind defines the kind for SlowSlow statement when the type is ShowSlowTop. +type ShowSlowKind int + +const ( + // ShowSlowKindDefault is a ShowSlowKind constant. + ShowSlowKindDefault ShowSlowKind = iota + // ShowSlowKindInternal is a ShowSlowKind constant. + ShowSlowKindInternal + // ShowSlowKindAll is a ShowSlowKind constant. + ShowSlowKindAll +) + +// ShowSlow is used for the following command: +// admin show slow top [ internal | all] N +// admin show slow recent N +type ShowSlow struct { + Tp ShowSlowType + Count uint64 + Kind ShowSlowKind +} + +// AdminStmt is the struct for Admin statement. +type AdminStmt struct { + stmtNode + + Tp AdminStmtType + Index string + Tables []*TableName + JobIDs []int64 + JobNumber int64 + + HandleRanges []HandleRange + ShowSlow *ShowSlow +} + +// Accept implements Node Accept interface. +func (n *AdminStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + + n = newNode.(*AdminStmt) + for i, val := range n.Tables { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Tables[i] = node.(*TableName) + } + + return v.Leave(n) +} + +// PrivElem is the privilege type and optional column list. +type PrivElem struct { + node + + Priv mysql.PrivilegeType + Cols []*ColumnName +} + +// Accept implements Node Accept interface. +func (n *PrivElem) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*PrivElem) + for i, val := range n.Cols { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Cols[i] = node.(*ColumnName) + } + return v.Leave(n) +} + +// ObjectTypeType is the type for object type. +type ObjectTypeType int + +const ( + // ObjectTypeNone is for empty object type. + ObjectTypeNone ObjectTypeType = iota + 1 + // ObjectTypeTable means the following object is a table. + ObjectTypeTable +) + +// GrantLevelType is the type for grant level. +type GrantLevelType int + +const ( + // GrantLevelNone is the dummy const for default value. + GrantLevelNone GrantLevelType = iota + 1 + // GrantLevelGlobal means the privileges are administrative or apply to all databases on a given server. + GrantLevelGlobal + // GrantLevelDB means the privileges apply to all objects in a given database. + GrantLevelDB + // GrantLevelTable means the privileges apply to all columns in a given table. + GrantLevelTable +) + +// GrantLevel is used for store the privilege scope. +type GrantLevel struct { + Level GrantLevelType + DBName string + TableName string +} + +// RevokeStmt is the struct for REVOKE statement. +type RevokeStmt struct { + stmtNode + + Privs []*PrivElem + ObjectType ObjectTypeType + Level *GrantLevel + Users []*UserSpec +} + +// Accept implements Node Accept interface. +func (n *RevokeStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*RevokeStmt) + for i, val := range n.Privs { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Privs[i] = node.(*PrivElem) + } + return v.Leave(n) +} + +// GrantStmt is the struct for GRANT statement. +type GrantStmt struct { + stmtNode + + Privs []*PrivElem + ObjectType ObjectTypeType + Level *GrantLevel + Users []*UserSpec + WithGrant bool +} + +// SecureText implements SensitiveStatement interface. +func (n *GrantStmt) SecureText() string { + text := n.text + // Filter "identified by xxx" because it would expose password information. + idx := strings.Index(strings.ToLower(text), "identified") + if idx > 0 { + text = text[:idx] + } + return text +} + +// Accept implements Node Accept interface. +func (n *GrantStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*GrantStmt) + for i, val := range n.Privs { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.Privs[i] = node.(*PrivElem) + } + return v.Leave(n) +} + +// Ident is the table identifier composed of schema name and table name. +type Ident struct { + Schema model.CIStr + Name model.CIStr +} + +// String implements fmt.Stringer interface. +func (i Ident) String() string { + if i.Schema.O == "" { + return i.Name.O + } + return fmt.Sprintf("%s.%s", i.Schema, i.Name) +} + +// SelectStmtOpts wrap around select hints and switches +type SelectStmtOpts struct { + Distinct bool + SQLCache bool + CalcFoundRows bool + StraightJoin bool + Priority mysql.PriorityEnum + TableHints []*TableOptimizerHint +} + +// TableOptimizerHint is Table level optimizer hint +type TableOptimizerHint struct { + node + // HintName is the name or alias of the table(s) which the hint will affect. + // Table hints has no schema info + // It allows only table name or alias (if table has an alias) + HintName model.CIStr + Tables []model.CIStr + // Statement Execution Time Optimizer Hints + // See https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time + MaxExecutionTime uint64 +} + +// Accept implements Node Accept interface. +func (n *TableOptimizerHint) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*TableOptimizerHint) + return v.Leave(n) +} + +// NewDecimal creates a types.Decimal value, it's provided by parser driver. +var NewDecimal func(string) (interface{}, error) + +// NewHexLiteral creates a types.HexLiteral value, it's provided by parser driver. +var NewHexLiteral func(string) (interface{}, error) + +// NewBitLiteral creates a types.BitLiteral value, it's provided by parser driver. +var NewBitLiteral func(string) (interface{}, error) diff --git a/vendor/github.com/pingcap/parser/ast/read_only_checker.go b/vendor/github.com/pingcap/parser/ast/read_only_checker.go new file mode 100644 index 0000000000000000000000000000000000000000..99c48f5800fad55cb894bdf61ef5417b13ab479f --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/read_only_checker.go @@ -0,0 +1,61 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +// IsReadOnly checks whether the input ast is readOnly. +func IsReadOnly(node Node) bool { + switch st := node.(type) { + case *SelectStmt: + if st.LockTp == SelectLockForUpdate { + return false + } + + checker := readOnlyChecker{ + readOnly: true, + } + + node.Accept(&checker) + return checker.readOnly + case *ExplainStmt, *DoStmt: + return true + default: + return false + } +} + +// readOnlyChecker checks whether a query's ast is readonly, if it satisfied +// 1. selectstmt; +// 2. need not to set var; +// it is readonly statement. +type readOnlyChecker struct { + readOnly bool +} + +// Enter implements Visitor interface. +func (checker *readOnlyChecker) Enter(in Node) (out Node, skipChildren bool) { + switch node := in.(type) { + case *VariableExpr: + // like func rewriteVariable(), this stands for SetVar. + if !node.IsSystem && node.Value != nil { + checker.readOnly = false + return in, true + } + } + return in, false +} + +// Leave implements Visitor interface. +func (checker *readOnlyChecker) Leave(in Node) (out Node, ok bool) { + return in, checker.readOnly +} diff --git a/vendor/github.com/pingcap/parser/ast/stats.go b/vendor/github.com/pingcap/parser/ast/stats.go new file mode 100644 index 0000000000000000000000000000000000000000..5db8664a511e2374641606ff958e71b5f73e40d1 --- /dev/null +++ b/vendor/github.com/pingcap/parser/ast/stats.go @@ -0,0 +1,91 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import "github.com/pingcap/parser/model" + +var ( + _ StmtNode = &AnalyzeTableStmt{} + _ StmtNode = &DropStatsStmt{} + _ StmtNode = &LoadStatsStmt{} +) + +// AnalyzeTableStmt is used to create table statistics. +type AnalyzeTableStmt struct { + stmtNode + + TableNames []*TableName + PartitionNames []model.CIStr + IndexNames []model.CIStr + MaxNumBuckets uint64 + + // IndexFlag is true when we only analyze indices for a table. + IndexFlag bool +} + +// Accept implements Node Accept interface. +func (n *AnalyzeTableStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*AnalyzeTableStmt) + for i, val := range n.TableNames { + node, ok := val.Accept(v) + if !ok { + return n, false + } + n.TableNames[i] = node.(*TableName) + } + return v.Leave(n) +} + +// DropStatsStmt is used to drop table statistics. +type DropStatsStmt struct { + stmtNode + + Table *TableName +} + +// Accept implements Node Accept interface. +func (n *DropStatsStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*DropStatsStmt) + node, ok := n.Table.Accept(v) + if !ok { + return n, false + } + n.Table = node.(*TableName) + return v.Leave(n) +} + +// LoadStatsStmt is the statement node for loading statistic. +type LoadStatsStmt struct { + stmtNode + + Path string +} + +// Accept implements Node Accept interface. +func (n *LoadStatsStmt) Accept(v Visitor) (Node, bool) { + newNode, skipChildren := v.Enter(n) + if skipChildren { + return v.Leave(newNode) + } + n = newNode.(*LoadStatsStmt) + return v.Leave(n) +} diff --git a/vendor/github.com/pingcap/parser/auth/auth.go b/vendor/github.com/pingcap/parser/auth/auth.go new file mode 100644 index 0000000000000000000000000000000000000000..1d33fbdc01e3787c98220d5180a78870592c43f1 --- /dev/null +++ b/vendor/github.com/pingcap/parser/auth/auth.go @@ -0,0 +1,103 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package auth + +import ( + "bytes" + "crypto/sha1" + "encoding/hex" + "fmt" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/terror" +) + +// UserIdentity represents username and hostname. +type UserIdentity struct { + Username string + Hostname string + CurrentUser bool + AuthUsername string // Username matched in privileges system + AuthHostname string // Match in privs system (i.e. could be a wildcard) +} + +// String converts UserIdentity to the format user@host. +func (user *UserIdentity) String() string { + // TODO: Escape username and hostname. + return fmt.Sprintf("%s@%s", user.Username, user.Hostname) +} + +// AuthIdentityString returns matched identity in user@host format +func (user *UserIdentity) AuthIdentityString() string { + // TODO: Escape username and hostname. + return fmt.Sprintf("%s@%s", user.AuthUsername, user.AuthHostname) +} + +// CheckScrambledPassword check scrambled password received from client. +// The new authentication is performed in following manner: +// SERVER: public_seed=create_random_string() +// send(public_seed) +// CLIENT: recv(public_seed) +// hash_stage1=sha1("password") +// hash_stage2=sha1(hash_stage1) +// reply=xor(hash_stage1, sha1(public_seed,hash_stage2) +// // this three steps are done in scramble() +// send(reply) +// SERVER: recv(reply) +// hash_stage1=xor(reply, sha1(public_seed,hash_stage2)) +// candidate_hash2=sha1(hash_stage1) +// check(candidate_hash2==hash_stage2) +// // this three steps are done in check_scramble() +func CheckScrambledPassword(salt, hpwd, auth []byte) bool { + crypt := sha1.New() + _, err := crypt.Write(salt) + terror.Log(errors.Trace(err)) + _, err = crypt.Write(hpwd) + terror.Log(errors.Trace(err)) + hash := crypt.Sum(nil) + // token = scrambleHash XOR stage1Hash + for i := range hash { + hash[i] ^= auth[i] + } + + return bytes.Equal(hpwd, Sha1Hash(hash)) +} + +// Sha1Hash is an util function to calculate sha1 hash. +func Sha1Hash(bs []byte) []byte { + crypt := sha1.New() + _, err := crypt.Write(bs) + terror.Log(errors.Trace(err)) + return crypt.Sum(nil) +} + +// EncodePassword converts plaintext password to hashed hex string. +func EncodePassword(pwd string) string { + if len(pwd) == 0 { + return "" + } + hash1 := Sha1Hash([]byte(pwd)) + hash2 := Sha1Hash(hash1) + + return fmt.Sprintf("*%X", hash2) +} + +// DecodePassword converts hex string password without prefix '*' to byte array. +func DecodePassword(pwd string) ([]byte, error) { + x, err := hex.DecodeString(pwd[1:]) + if err != nil { + return nil, errors.Trace(err) + } + return x, nil +} diff --git a/vendor/github.com/pingcap/parser/charset/charset.go b/vendor/github.com/pingcap/parser/charset/charset.go new file mode 100644 index 0000000000000000000000000000000000000000..c42c13e4b09fcd2cc364bc1ef2a7701098af2a3a --- /dev/null +++ b/vendor/github.com/pingcap/parser/charset/charset.go @@ -0,0 +1,422 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "strings" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/mysql" +) + +// Charset is a charset. +// Now we only support MySQL. +type Charset struct { + Name string + DefaultCollation string + Collations map[string]*Collation + Desc string + Maxlen int +} + +// Collation is a collation. +// Now we only support MySQL. +type Collation struct { + ID int + CharsetName string + Name string + IsDefault bool +} + +var charsets = make(map[string]*Charset) + +// All the supported charsets should be in the following table. +var charsetInfos = []*Charset{ + {CharsetUTF8, CollationUTF8, make(map[string]*Collation), "UTF-8 Unicode", 3}, + {CharsetUTF8MB4, CollationUTF8MB4, make(map[string]*Collation), "UTF-8 Unicode", 4}, + {CharsetASCII, CollationASCII, make(map[string]*Collation), "US ASCII", 1}, + {CharsetLatin1, CollationLatin1, make(map[string]*Collation), "Latin1", 1}, + {CharsetBin, CollationBin, make(map[string]*Collation), "binary", 1}, +} + +// Desc is a charset description. +type Desc struct { + Name string + Desc string + DefaultCollation string + Maxlen int +} + +// GetAllCharsets gets all charset descriptions in the local charsets. +func GetAllCharsets() []*Desc { + descs := make([]*Desc, 0, len(charsets)) + // The charsetInfos is an array, so the iterate order will be stable. + for _, ci := range charsetInfos { + c, ok := charsets[ci.Name] + if !ok { + continue + } + desc := &Desc{ + Name: c.Name, + DefaultCollation: c.DefaultCollation, + Desc: c.Desc, + Maxlen: c.Maxlen, + } + descs = append(descs, desc) + } + return descs +} + +// ValidCharsetAndCollation checks the charset and the collation validity +// and returns a boolean. +func ValidCharsetAndCollation(cs string, co string) bool { + // We will use utf8 as a default charset. + if cs == "" { + cs = "utf8" + } + cs = strings.ToLower(cs) + c, ok := charsets[cs] + if !ok { + return false + } + + if co == "" { + return true + } + _, ok = c.Collations[co] + if !ok { + return false + } + + return true +} + +// GetDefaultCollation returns the default collation for charset. +func GetDefaultCollation(charset string) (string, error) { + charset = strings.ToLower(charset) + if charset == CharsetBin { + return CollationBin, nil + } + c, ok := charsets[charset] + if !ok { + return "", errors.Errorf("Unknown charset %s", charset) + } + return c.DefaultCollation, nil +} + +// GetDefaultCharsetAndCollate returns the default charset and collation. +func GetDefaultCharsetAndCollate() (string, string) { + return mysql.DefaultCharset, mysql.DefaultCollationName +} + +// GetCharsetInfo returns charset and collation for cs as name. +func GetCharsetInfo(cs string) (string, string, error) { + c, ok := charsets[strings.ToLower(cs)] + if !ok { + return "", "", errors.Errorf("Unknown charset %s", cs) + } + return c.Name, c.DefaultCollation, nil +} + +// GetCharsetDesc gets charset descriptions in the local charsets. +func GetCharsetDesc(cs string) (*Desc, error) { + c, ok := charsets[strings.ToLower(cs)] + if !ok { + return nil, errors.Errorf("Unknown charset %s", cs) + } + desc := &Desc{ + Name: c.Name, + DefaultCollation: c.DefaultCollation, + Desc: c.Desc, + Maxlen: c.Maxlen, + } + return desc, nil +} + +// GetCharsetInfoByID returns charset and collation for id as cs_number. +func GetCharsetInfoByID(coID int) (string, string, error) { + if coID == mysql.DefaultCollationID { + return mysql.DefaultCharset, mysql.DefaultCollationName, nil + } + for _, collation := range collations { + if coID == collation.ID { + return collation.CharsetName, collation.Name, nil + } + } + return "", "", errors.Errorf("Unknown charset id %d", coID) +} + +// GetCollations returns a list for all collations. +func GetCollations() []*Collation { + return collations +} + +const ( + // CharsetBin is used for marking binary charset. + CharsetBin = "binary" + // CollationBin is the default collation for CharsetBin. + CollationBin = "binary" + // CharsetUTF8 is the default charset for string types. + CharsetUTF8 = "utf8" + // CollationUTF8 is the default collation for CharsetUTF8. + CollationUTF8 = "utf8_bin" + // CharsetUTF8MB4 represents 4 bytes utf8, which works the same way as utf8 in Go. + CharsetUTF8MB4 = "utf8mb4" + // CollationUTF8MB4 is the default collation for CharsetUTF8MB4. + CollationUTF8MB4 = "utf8mb4_bin" + // CharsetASCII is a subset of UTF8. + CharsetASCII = "ascii" + // CollationASCII is the default collation for CharsetACSII. + CollationASCII = "ascii_bin" + // CharsetLatin1 is a single byte charset. + CharsetLatin1 = "latin1" + // CollationLatin1 is the default collation for CharsetLatin1. + CollationLatin1 = "latin1_bin" +) + +var collations = []*Collation{ + {1, "big5", "big5_chinese_ci", true}, + {2, "latin2", "latin2_czech_cs", false}, + {3, "dec8", "dec8_swedish_ci", true}, + {4, "cp850", "cp850_general_ci", true}, + {5, "latin1", "latin1_german1_ci", false}, + {6, "hp8", "hp8_english_ci", true}, + {7, "koi8r", "koi8r_general_ci", true}, + {8, "latin1", "latin1_swedish_ci", true}, + {9, "latin2", "latin2_general_ci", true}, + {10, "swe7", "swe7_swedish_ci", true}, + {11, "ascii", "ascii_general_ci", true}, + {12, "ujis", "ujis_japanese_ci", true}, + {13, "sjis", "sjis_japanese_ci", true}, + {14, "cp1251", "cp1251_bulgarian_ci", false}, + {15, "latin1", "latin1_danish_ci", false}, + {16, "hebrew", "hebrew_general_ci", true}, + {18, "tis620", "tis620_thai_ci", true}, + {19, "euckr", "euckr_korean_ci", true}, + {20, "latin7", "latin7_estonian_cs", false}, + {21, "latin2", "latin2_hungarian_ci", false}, + {22, "koi8u", "koi8u_general_ci", true}, + {23, "cp1251", "cp1251_ukrainian_ci", false}, + {24, "gb2312", "gb2312_chinese_ci", true}, + {25, "greek", "greek_general_ci", true}, + {26, "cp1250", "cp1250_general_ci", true}, + {27, "latin2", "latin2_croatian_ci", false}, + {28, "gbk", "gbk_chinese_ci", true}, + {29, "cp1257", "cp1257_lithuanian_ci", false}, + {30, "latin5", "latin5_turkish_ci", true}, + {31, "latin1", "latin1_german2_ci", false}, + {32, "armscii8", "armscii8_general_ci", true}, + {33, "utf8", "utf8_general_ci", true}, + {34, "cp1250", "cp1250_czech_cs", false}, + {35, "ucs2", "ucs2_general_ci", true}, + {36, "cp866", "cp866_general_ci", true}, + {37, "keybcs2", "keybcs2_general_ci", true}, + {38, "macce", "macce_general_ci", true}, + {39, "macroman", "macroman_general_ci", true}, + {40, "cp852", "cp852_general_ci", true}, + {41, "latin7", "latin7_general_ci", true}, + {42, "latin7", "latin7_general_cs", false}, + {43, "macce", "macce_bin", false}, + {44, "cp1250", "cp1250_croatian_ci", false}, + {45, "utf8mb4", "utf8mb4_general_ci", true}, + {46, "utf8mb4", "utf8mb4_bin", false}, + {47, "latin1", "latin1_bin", false}, + {48, "latin1", "latin1_general_ci", false}, + {49, "latin1", "latin1_general_cs", false}, + {50, "cp1251", "cp1251_bin", false}, + {51, "cp1251", "cp1251_general_ci", true}, + {52, "cp1251", "cp1251_general_cs", false}, + {53, "macroman", "macroman_bin", false}, + {54, "utf16", "utf16_general_ci", true}, + {55, "utf16", "utf16_bin", false}, + {56, "utf16le", "utf16le_general_ci", true}, + {57, "cp1256", "cp1256_general_ci", true}, + {58, "cp1257", "cp1257_bin", false}, + {59, "cp1257", "cp1257_general_ci", true}, + {60, "utf32", "utf32_general_ci", true}, + {61, "utf32", "utf32_bin", false}, + {62, "utf16le", "utf16le_bin", false}, + {63, "binary", "binary", true}, + {64, "armscii8", "armscii8_bin", false}, + {65, "ascii", "ascii_bin", false}, + {66, "cp1250", "cp1250_bin", false}, + {67, "cp1256", "cp1256_bin", false}, + {68, "cp866", "cp866_bin", false}, + {69, "dec8", "dec8_bin", false}, + {70, "greek", "greek_bin", false}, + {71, "hebrew", "hebrew_bin", false}, + {72, "hp8", "hp8_bin", false}, + {73, "keybcs2", "keybcs2_bin", false}, + {74, "koi8r", "koi8r_bin", false}, + {75, "koi8u", "koi8u_bin", false}, + {77, "latin2", "latin2_bin", false}, + {78, "latin5", "latin5_bin", false}, + {79, "latin7", "latin7_bin", false}, + {80, "cp850", "cp850_bin", false}, + {81, "cp852", "cp852_bin", false}, + {82, "swe7", "swe7_bin", false}, + {83, "utf8", "utf8_bin", false}, + {84, "big5", "big5_bin", false}, + {85, "euckr", "euckr_bin", false}, + {86, "gb2312", "gb2312_bin", false}, + {87, "gbk", "gbk_bin", false}, + {88, "sjis", "sjis_bin", false}, + {89, "tis620", "tis620_bin", false}, + {90, "ucs2", "ucs2_bin", false}, + {91, "ujis", "ujis_bin", false}, + {92, "geostd8", "geostd8_general_ci", true}, + {93, "geostd8", "geostd8_bin", false}, + {94, "latin1", "latin1_spanish_ci", false}, + {95, "cp932", "cp932_japanese_ci", true}, + {96, "cp932", "cp932_bin", false}, + {97, "eucjpms", "eucjpms_japanese_ci", true}, + {98, "eucjpms", "eucjpms_bin", false}, + {99, "cp1250", "cp1250_polish_ci", false}, + {101, "utf16", "utf16_unicode_ci", false}, + {102, "utf16", "utf16_icelandic_ci", false}, + {103, "utf16", "utf16_latvian_ci", false}, + {104, "utf16", "utf16_romanian_ci", false}, + {105, "utf16", "utf16_slovenian_ci", false}, + {106, "utf16", "utf16_polish_ci", false}, + {107, "utf16", "utf16_estonian_ci", false}, + {108, "utf16", "utf16_spanish_ci", false}, + {109, "utf16", "utf16_swedish_ci", false}, + {110, "utf16", "utf16_turkish_ci", false}, + {111, "utf16", "utf16_czech_ci", false}, + {112, "utf16", "utf16_danish_ci", false}, + {113, "utf16", "utf16_lithuanian_ci", false}, + {114, "utf16", "utf16_slovak_ci", false}, + {115, "utf16", "utf16_spanish2_ci", false}, + {116, "utf16", "utf16_roman_ci", false}, + {117, "utf16", "utf16_persian_ci", false}, + {118, "utf16", "utf16_esperanto_ci", false}, + {119, "utf16", "utf16_hungarian_ci", false}, + {120, "utf16", "utf16_sinhala_ci", false}, + {121, "utf16", "utf16_german2_ci", false}, + {122, "utf16", "utf16_croatian_ci", false}, + {123, "utf16", "utf16_unicode_520_ci", false}, + {124, "utf16", "utf16_vietnamese_ci", false}, + {128, "ucs2", "ucs2_unicode_ci", false}, + {129, "ucs2", "ucs2_icelandic_ci", false}, + {130, "ucs2", "ucs2_latvian_ci", false}, + {131, "ucs2", "ucs2_romanian_ci", false}, + {132, "ucs2", "ucs2_slovenian_ci", false}, + {133, "ucs2", "ucs2_polish_ci", false}, + {134, "ucs2", "ucs2_estonian_ci", false}, + {135, "ucs2", "ucs2_spanish_ci", false}, + {136, "ucs2", "ucs2_swedish_ci", false}, + {137, "ucs2", "ucs2_turkish_ci", false}, + {138, "ucs2", "ucs2_czech_ci", false}, + {139, "ucs2", "ucs2_danish_ci", false}, + {140, "ucs2", "ucs2_lithuanian_ci", false}, + {141, "ucs2", "ucs2_slovak_ci", false}, + {142, "ucs2", "ucs2_spanish2_ci", false}, + {143, "ucs2", "ucs2_roman_ci", false}, + {144, "ucs2", "ucs2_persian_ci", false}, + {145, "ucs2", "ucs2_esperanto_ci", false}, + {146, "ucs2", "ucs2_hungarian_ci", false}, + {147, "ucs2", "ucs2_sinhala_ci", false}, + {148, "ucs2", "ucs2_german2_ci", false}, + {149, "ucs2", "ucs2_croatian_ci", false}, + {150, "ucs2", "ucs2_unicode_520_ci", false}, + {151, "ucs2", "ucs2_vietnamese_ci", false}, + {159, "ucs2", "ucs2_general_mysql500_ci", false}, + {160, "utf32", "utf32_unicode_ci", false}, + {161, "utf32", "utf32_icelandic_ci", false}, + {162, "utf32", "utf32_latvian_ci", false}, + {163, "utf32", "utf32_romanian_ci", false}, + {164, "utf32", "utf32_slovenian_ci", false}, + {165, "utf32", "utf32_polish_ci", false}, + {166, "utf32", "utf32_estonian_ci", false}, + {167, "utf32", "utf32_spanish_ci", false}, + {168, "utf32", "utf32_swedish_ci", false}, + {169, "utf32", "utf32_turkish_ci", false}, + {170, "utf32", "utf32_czech_ci", false}, + {171, "utf32", "utf32_danish_ci", false}, + {172, "utf32", "utf32_lithuanian_ci", false}, + {173, "utf32", "utf32_slovak_ci", false}, + {174, "utf32", "utf32_spanish2_ci", false}, + {175, "utf32", "utf32_roman_ci", false}, + {176, "utf32", "utf32_persian_ci", false}, + {177, "utf32", "utf32_esperanto_ci", false}, + {178, "utf32", "utf32_hungarian_ci", false}, + {179, "utf32", "utf32_sinhala_ci", false}, + {180, "utf32", "utf32_german2_ci", false}, + {181, "utf32", "utf32_croatian_ci", false}, + {182, "utf32", "utf32_unicode_520_ci", false}, + {183, "utf32", "utf32_vietnamese_ci", false}, + {192, "utf8", "utf8_unicode_ci", false}, + {193, "utf8", "utf8_icelandic_ci", false}, + {194, "utf8", "utf8_latvian_ci", false}, + {195, "utf8", "utf8_romanian_ci", false}, + {196, "utf8", "utf8_slovenian_ci", false}, + {197, "utf8", "utf8_polish_ci", false}, + {198, "utf8", "utf8_estonian_ci", false}, + {199, "utf8", "utf8_spanish_ci", false}, + {200, "utf8", "utf8_swedish_ci", false}, + {201, "utf8", "utf8_turkish_ci", false}, + {202, "utf8", "utf8_czech_ci", false}, + {203, "utf8", "utf8_danish_ci", false}, + {204, "utf8", "utf8_lithuanian_ci", false}, + {205, "utf8", "utf8_slovak_ci", false}, + {206, "utf8", "utf8_spanish2_ci", false}, + {207, "utf8", "utf8_roman_ci", false}, + {208, "utf8", "utf8_persian_ci", false}, + {209, "utf8", "utf8_esperanto_ci", false}, + {210, "utf8", "utf8_hungarian_ci", false}, + {211, "utf8", "utf8_sinhala_ci", false}, + {212, "utf8", "utf8_german2_ci", false}, + {213, "utf8", "utf8_croatian_ci", false}, + {214, "utf8", "utf8_unicode_520_ci", false}, + {215, "utf8", "utf8_vietnamese_ci", false}, + {223, "utf8", "utf8_general_mysql500_ci", false}, + {224, "utf8mb4", "utf8mb4_unicode_ci", false}, + {225, "utf8mb4", "utf8mb4_icelandic_ci", false}, + {226, "utf8mb4", "utf8mb4_latvian_ci", false}, + {227, "utf8mb4", "utf8mb4_romanian_ci", false}, + {228, "utf8mb4", "utf8mb4_slovenian_ci", false}, + {229, "utf8mb4", "utf8mb4_polish_ci", false}, + {230, "utf8mb4", "utf8mb4_estonian_ci", false}, + {231, "utf8mb4", "utf8mb4_spanish_ci", false}, + {232, "utf8mb4", "utf8mb4_swedish_ci", false}, + {233, "utf8mb4", "utf8mb4_turkish_ci", false}, + {234, "utf8mb4", "utf8mb4_czech_ci", false}, + {235, "utf8mb4", "utf8mb4_danish_ci", false}, + {236, "utf8mb4", "utf8mb4_lithuanian_ci", false}, + {237, "utf8mb4", "utf8mb4_slovak_ci", false}, + {238, "utf8mb4", "utf8mb4_spanish2_ci", false}, + {239, "utf8mb4", "utf8mb4_roman_ci", false}, + {240, "utf8mb4", "utf8mb4_persian_ci", false}, + {241, "utf8mb4", "utf8mb4_esperanto_ci", false}, + {242, "utf8mb4", "utf8mb4_hungarian_ci", false}, + {243, "utf8mb4", "utf8mb4_sinhala_ci", false}, + {244, "utf8mb4", "utf8mb4_german2_ci", false}, + {245, "utf8mb4", "utf8mb4_croatian_ci", false}, + {246, "utf8mb4", "utf8mb4_unicode_520_ci", false}, + {247, "utf8mb4", "utf8mb4_vietnamese_ci", false}, +} + +// init method always puts to the end of file. +func init() { + for _, c := range charsetInfos { + charsets[c.Name] = c + } + for _, c := range collations { + charset, ok := charsets[c.CharsetName] + if !ok { + continue + } + charset.Collations[c.Name] = c + } +} diff --git a/vendor/github.com/pingcap/parser/charset/encoding_table.go b/vendor/github.com/pingcap/parser/charset/encoding_table.go new file mode 100644 index 0000000000000000000000000000000000000000..37a5550b794251539c843586ad54c95ac2afe638 --- /dev/null +++ b/vendor/github.com/pingcap/parser/charset/encoding_table.go @@ -0,0 +1,260 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package charset + +import ( + "strings" + + "golang.org/x/text/encoding" + "golang.org/x/text/encoding/charmap" + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/encoding/korean" + "golang.org/x/text/encoding/simplifiedchinese" + "golang.org/x/text/encoding/traditionalchinese" + "golang.org/x/text/encoding/unicode" +) + +// Lookup returns the encoding with the specified label, and its canonical +// name. It returns nil and the empty string if label is not one of the +// standard encodings for HTML. Matching is case-insensitive and ignores +// leading and trailing whitespace. +func Lookup(label string) (e encoding.Encoding, name string) { + label = strings.ToLower(strings.Trim(label, "\t\n\r\f ")) + enc := encodings[label] + return enc.e, enc.name +} + +var encodings = map[string]struct { + e encoding.Encoding + name string +}{ + "unicode-1-1-utf-8": {encoding.Nop, "utf-8"}, + "utf-8": {encoding.Nop, "utf-8"}, + "utf8": {encoding.Nop, "utf-8"}, + "utf8mb4": {encoding.Nop, "utf-8"}, + "binary": {encoding.Nop, "binary"}, + "866": {charmap.CodePage866, "ibm866"}, + "cp866": {charmap.CodePage866, "ibm866"}, + "csibm866": {charmap.CodePage866, "ibm866"}, + "ibm866": {charmap.CodePage866, "ibm866"}, + "csisolatin2": {charmap.ISO8859_2, "iso-8859-2"}, + "iso-8859-2": {charmap.ISO8859_2, "iso-8859-2"}, + "iso-ir-101": {charmap.ISO8859_2, "iso-8859-2"}, + "iso8859-2": {charmap.ISO8859_2, "iso-8859-2"}, + "iso88592": {charmap.ISO8859_2, "iso-8859-2"}, + "iso_8859-2": {charmap.ISO8859_2, "iso-8859-2"}, + "iso_8859-2:1987": {charmap.ISO8859_2, "iso-8859-2"}, + "l2": {charmap.ISO8859_2, "iso-8859-2"}, + "latin2": {charmap.ISO8859_2, "iso-8859-2"}, + "csisolatin3": {charmap.ISO8859_3, "iso-8859-3"}, + "iso-8859-3": {charmap.ISO8859_3, "iso-8859-3"}, + "iso-ir-109": {charmap.ISO8859_3, "iso-8859-3"}, + "iso8859-3": {charmap.ISO8859_3, "iso-8859-3"}, + "iso88593": {charmap.ISO8859_3, "iso-8859-3"}, + "iso_8859-3": {charmap.ISO8859_3, "iso-8859-3"}, + "iso_8859-3:1988": {charmap.ISO8859_3, "iso-8859-3"}, + "l3": {charmap.ISO8859_3, "iso-8859-3"}, + "latin3": {charmap.ISO8859_3, "iso-8859-3"}, + "csisolatin4": {charmap.ISO8859_4, "iso-8859-4"}, + "iso-8859-4": {charmap.ISO8859_4, "iso-8859-4"}, + "iso-ir-110": {charmap.ISO8859_4, "iso-8859-4"}, + "iso8859-4": {charmap.ISO8859_4, "iso-8859-4"}, + "iso88594": {charmap.ISO8859_4, "iso-8859-4"}, + "iso_8859-4": {charmap.ISO8859_4, "iso-8859-4"}, + "iso_8859-4:1988": {charmap.ISO8859_4, "iso-8859-4"}, + "l4": {charmap.ISO8859_4, "iso-8859-4"}, + "latin4": {charmap.ISO8859_4, "iso-8859-4"}, + "csisolatincyrillic": {charmap.ISO8859_5, "iso-8859-5"}, + "cyrillic": {charmap.ISO8859_5, "iso-8859-5"}, + "iso-8859-5": {charmap.ISO8859_5, "iso-8859-5"}, + "iso-ir-144": {charmap.ISO8859_5, "iso-8859-5"}, + "iso8859-5": {charmap.ISO8859_5, "iso-8859-5"}, + "iso88595": {charmap.ISO8859_5, "iso-8859-5"}, + "iso_8859-5": {charmap.ISO8859_5, "iso-8859-5"}, + "iso_8859-5:1988": {charmap.ISO8859_5, "iso-8859-5"}, + "arabic": {charmap.ISO8859_6, "iso-8859-6"}, + "asmo-708": {charmap.ISO8859_6, "iso-8859-6"}, + "csiso88596e": {charmap.ISO8859_6, "iso-8859-6"}, + "csiso88596i": {charmap.ISO8859_6, "iso-8859-6"}, + "csisolatinarabic": {charmap.ISO8859_6, "iso-8859-6"}, + "ecma-114": {charmap.ISO8859_6, "iso-8859-6"}, + "iso-8859-6": {charmap.ISO8859_6, "iso-8859-6"}, + "iso-8859-6-e": {charmap.ISO8859_6, "iso-8859-6"}, + "iso-8859-6-i": {charmap.ISO8859_6, "iso-8859-6"}, + "iso-ir-127": {charmap.ISO8859_6, "iso-8859-6"}, + "iso8859-6": {charmap.ISO8859_6, "iso-8859-6"}, + "iso88596": {charmap.ISO8859_6, "iso-8859-6"}, + "iso_8859-6": {charmap.ISO8859_6, "iso-8859-6"}, + "iso_8859-6:1987": {charmap.ISO8859_6, "iso-8859-6"}, + "csisolatingreek": {charmap.ISO8859_7, "iso-8859-7"}, + "ecma-118": {charmap.ISO8859_7, "iso-8859-7"}, + "elot_928": {charmap.ISO8859_7, "iso-8859-7"}, + "greek": {charmap.ISO8859_7, "iso-8859-7"}, + "greek8": {charmap.ISO8859_7, "iso-8859-7"}, + "iso-8859-7": {charmap.ISO8859_7, "iso-8859-7"}, + "iso-ir-126": {charmap.ISO8859_7, "iso-8859-7"}, + "iso8859-7": {charmap.ISO8859_7, "iso-8859-7"}, + "iso88597": {charmap.ISO8859_7, "iso-8859-7"}, + "iso_8859-7": {charmap.ISO8859_7, "iso-8859-7"}, + "iso_8859-7:1987": {charmap.ISO8859_7, "iso-8859-7"}, + "sun_eu_greek": {charmap.ISO8859_7, "iso-8859-7"}, + "csiso88598e": {charmap.ISO8859_8, "iso-8859-8"}, + "csisolatinhebrew": {charmap.ISO8859_8, "iso-8859-8"}, + "hebrew": {charmap.ISO8859_8, "iso-8859-8"}, + "iso-8859-8": {charmap.ISO8859_8, "iso-8859-8"}, + "iso-8859-8-e": {charmap.ISO8859_8, "iso-8859-8"}, + "iso-ir-138": {charmap.ISO8859_8, "iso-8859-8"}, + "iso8859-8": {charmap.ISO8859_8, "iso-8859-8"}, + "iso88598": {charmap.ISO8859_8, "iso-8859-8"}, + "iso_8859-8": {charmap.ISO8859_8, "iso-8859-8"}, + "iso_8859-8:1988": {charmap.ISO8859_8, "iso-8859-8"}, + "visual": {charmap.ISO8859_8, "iso-8859-8"}, + "csiso88598i": {charmap.ISO8859_8, "iso-8859-8-i"}, + "iso-8859-8-i": {charmap.ISO8859_8, "iso-8859-8-i"}, + "logical": {charmap.ISO8859_8, "iso-8859-8-i"}, + "csisolatin6": {charmap.ISO8859_10, "iso-8859-10"}, + "iso-8859-10": {charmap.ISO8859_10, "iso-8859-10"}, + "iso-ir-157": {charmap.ISO8859_10, "iso-8859-10"}, + "iso8859-10": {charmap.ISO8859_10, "iso-8859-10"}, + "iso885910": {charmap.ISO8859_10, "iso-8859-10"}, + "l6": {charmap.ISO8859_10, "iso-8859-10"}, + "latin6": {charmap.ISO8859_10, "iso-8859-10"}, + "iso-8859-13": {charmap.ISO8859_13, "iso-8859-13"}, + "iso8859-13": {charmap.ISO8859_13, "iso-8859-13"}, + "iso885913": {charmap.ISO8859_13, "iso-8859-13"}, + "iso-8859-14": {charmap.ISO8859_14, "iso-8859-14"}, + "iso8859-14": {charmap.ISO8859_14, "iso-8859-14"}, + "iso885914": {charmap.ISO8859_14, "iso-8859-14"}, + "csisolatin9": {charmap.ISO8859_15, "iso-8859-15"}, + "iso-8859-15": {charmap.ISO8859_15, "iso-8859-15"}, + "iso8859-15": {charmap.ISO8859_15, "iso-8859-15"}, + "iso885915": {charmap.ISO8859_15, "iso-8859-15"}, + "iso_8859-15": {charmap.ISO8859_15, "iso-8859-15"}, + "l9": {charmap.ISO8859_15, "iso-8859-15"}, + "iso-8859-16": {charmap.ISO8859_16, "iso-8859-16"}, + "cskoi8r": {charmap.KOI8R, "koi8-r"}, + "koi": {charmap.KOI8R, "koi8-r"}, + "koi8": {charmap.KOI8R, "koi8-r"}, + "koi8-r": {charmap.KOI8R, "koi8-r"}, + "koi8_r": {charmap.KOI8R, "koi8-r"}, + "koi8-u": {charmap.KOI8U, "koi8-u"}, + "csmacintosh": {charmap.Macintosh, "macintosh"}, + "mac": {charmap.Macintosh, "macintosh"}, + "macintosh": {charmap.Macintosh, "macintosh"}, + "x-mac-roman": {charmap.Macintosh, "macintosh"}, + "dos-874": {charmap.Windows874, "windows-874"}, + "iso-8859-11": {charmap.Windows874, "windows-874"}, + "iso8859-11": {charmap.Windows874, "windows-874"}, + "iso885911": {charmap.Windows874, "windows-874"}, + "tis-620": {charmap.Windows874, "windows-874"}, + "windows-874": {charmap.Windows874, "windows-874"}, + "cp1250": {charmap.Windows1250, "windows-1250"}, + "windows-1250": {charmap.Windows1250, "windows-1250"}, + "x-cp1250": {charmap.Windows1250, "windows-1250"}, + "cp1251": {charmap.Windows1251, "windows-1251"}, + "windows-1251": {charmap.Windows1251, "windows-1251"}, + "x-cp1251": {charmap.Windows1251, "windows-1251"}, + "ansi_x3.4-1968": {charmap.Windows1252, "windows-1252"}, + "ascii": {charmap.Windows1252, "windows-1252"}, + "cp1252": {charmap.Windows1252, "windows-1252"}, + "cp819": {charmap.Windows1252, "windows-1252"}, + "csisolatin1": {charmap.Windows1252, "windows-1252"}, + "ibm819": {charmap.Windows1252, "windows-1252"}, + "iso-8859-1": {charmap.Windows1252, "windows-1252"}, + "iso-ir-100": {charmap.Windows1252, "windows-1252"}, + "iso8859-1": {charmap.Windows1252, "windows-1252"}, + "iso88591": {charmap.Windows1252, "windows-1252"}, + "iso_8859-1": {charmap.Windows1252, "windows-1252"}, + "iso_8859-1:1987": {charmap.Windows1252, "windows-1252"}, + "l1": {charmap.Windows1252, "windows-1252"}, + "latin1": {charmap.Windows1252, "windows-1252"}, + "us-ascii": {charmap.Windows1252, "windows-1252"}, + "windows-1252": {charmap.Windows1252, "windows-1252"}, + "x-cp1252": {charmap.Windows1252, "windows-1252"}, + "cp1253": {charmap.Windows1253, "windows-1253"}, + "windows-1253": {charmap.Windows1253, "windows-1253"}, + "x-cp1253": {charmap.Windows1253, "windows-1253"}, + "cp1254": {charmap.Windows1254, "windows-1254"}, + "csisolatin5": {charmap.Windows1254, "windows-1254"}, + "iso-8859-9": {charmap.Windows1254, "windows-1254"}, + "iso-ir-148": {charmap.Windows1254, "windows-1254"}, + "iso8859-9": {charmap.Windows1254, "windows-1254"}, + "iso88599": {charmap.Windows1254, "windows-1254"}, + "iso_8859-9": {charmap.Windows1254, "windows-1254"}, + "iso_8859-9:1989": {charmap.Windows1254, "windows-1254"}, + "l5": {charmap.Windows1254, "windows-1254"}, + "latin5": {charmap.Windows1254, "windows-1254"}, + "windows-1254": {charmap.Windows1254, "windows-1254"}, + "x-cp1254": {charmap.Windows1254, "windows-1254"}, + "cp1255": {charmap.Windows1255, "windows-1255"}, + "windows-1255": {charmap.Windows1255, "windows-1255"}, + "x-cp1255": {charmap.Windows1255, "windows-1255"}, + "cp1256": {charmap.Windows1256, "windows-1256"}, + "windows-1256": {charmap.Windows1256, "windows-1256"}, + "x-cp1256": {charmap.Windows1256, "windows-1256"}, + "cp1257": {charmap.Windows1257, "windows-1257"}, + "windows-1257": {charmap.Windows1257, "windows-1257"}, + "x-cp1257": {charmap.Windows1257, "windows-1257"}, + "cp1258": {charmap.Windows1258, "windows-1258"}, + "windows-1258": {charmap.Windows1258, "windows-1258"}, + "x-cp1258": {charmap.Windows1258, "windows-1258"}, + "x-mac-cyrillic": {charmap.MacintoshCyrillic, "x-mac-cyrillic"}, + "x-mac-ukrainian": {charmap.MacintoshCyrillic, "x-mac-cyrillic"}, + "chinese": {simplifiedchinese.GBK, "gbk"}, + "csgb2312": {simplifiedchinese.GBK, "gbk"}, + "csiso58gb231280": {simplifiedchinese.GBK, "gbk"}, + "gb2312": {simplifiedchinese.GBK, "gbk"}, + "gb_2312": {simplifiedchinese.GBK, "gbk"}, + "gb_2312-80": {simplifiedchinese.GBK, "gbk"}, + "gbk": {simplifiedchinese.GBK, "gbk"}, + "iso-ir-58": {simplifiedchinese.GBK, "gbk"}, + "x-gbk": {simplifiedchinese.GBK, "gbk"}, + "gb18030": {simplifiedchinese.GB18030, "gb18030"}, + "hz-gb-2312": {simplifiedchinese.HZGB2312, "hz-gb-2312"}, + "big5": {traditionalchinese.Big5, "big5"}, + "big5-hkscs": {traditionalchinese.Big5, "big5"}, + "cn-big5": {traditionalchinese.Big5, "big5"}, + "csbig5": {traditionalchinese.Big5, "big5"}, + "x-x-big5": {traditionalchinese.Big5, "big5"}, + "cseucpkdfmtjapanese": {japanese.EUCJP, "euc-jp"}, + "euc-jp": {japanese.EUCJP, "euc-jp"}, + "x-euc-jp": {japanese.EUCJP, "euc-jp"}, + "csiso2022jp": {japanese.ISO2022JP, "iso-2022-jp"}, + "iso-2022-jp": {japanese.ISO2022JP, "iso-2022-jp"}, + "csshiftjis": {japanese.ShiftJIS, "shift_jis"}, + "ms_kanji": {japanese.ShiftJIS, "shift_jis"}, + "shift-jis": {japanese.ShiftJIS, "shift_jis"}, + "shift_jis": {japanese.ShiftJIS, "shift_jis"}, + "sjis": {japanese.ShiftJIS, "shift_jis"}, + "windows-31j": {japanese.ShiftJIS, "shift_jis"}, + "x-sjis": {japanese.ShiftJIS, "shift_jis"}, + "cseuckr": {korean.EUCKR, "euc-kr"}, + "csksc56011987": {korean.EUCKR, "euc-kr"}, + "euc-kr": {korean.EUCKR, "euc-kr"}, + "iso-ir-149": {korean.EUCKR, "euc-kr"}, + "korean": {korean.EUCKR, "euc-kr"}, + "ks_c_5601-1987": {korean.EUCKR, "euc-kr"}, + "ks_c_5601-1989": {korean.EUCKR, "euc-kr"}, + "ksc5601": {korean.EUCKR, "euc-kr"}, + "ksc_5601": {korean.EUCKR, "euc-kr"}, + "windows-949": {korean.EUCKR, "euc-kr"}, + "csiso2022kr": {encoding.Replacement, "replacement"}, + "iso-2022-kr": {encoding.Replacement, "replacement"}, + "iso-2022-cn": {encoding.Replacement, "replacement"}, + "iso-2022-cn-ext": {encoding.Replacement, "replacement"}, + "utf-16be": {unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM), "utf-16be"}, + "utf-16": {unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM), "utf-16le"}, + "utf-16le": {unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM), "utf-16le"}, + "x-user-defined": {charmap.XUserDefined, "x-user-defined"}, +} diff --git a/vendor/github.com/pingcap/parser/circle.yml b/vendor/github.com/pingcap/parser/circle.yml new file mode 100644 index 0000000000000000000000000000000000000000..22d0a9e3705a7704f6e5b27a9cb485366753fbfd --- /dev/null +++ b/vendor/github.com/pingcap/parser/circle.yml @@ -0,0 +1,18 @@ +version: 2 + +jobs: + build: + docker: + - image: golang:1.11 + working_directory: /go/src/github.com/pingcap/parser + steps: + - checkout + - run: + name: "Verify parser.go is up-to-date" + command: | + mv parser.go parser.go.committed + make parser + diff -u parser.go.committed parser.go + - run: + name: "Build & Test" + command: make test diff --git a/vendor/github.com/pingcap/parser/format/format.go b/vendor/github.com/pingcap/parser/format/format.go new file mode 100644 index 0000000000000000000000000000000000000000..0a14a6d3626502fae93b1923621e834d82eede24 --- /dev/null +++ b/vendor/github.com/pingcap/parser/format/format.go @@ -0,0 +1,195 @@ +// Copyright (c) 2014 The sortutil Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/STRUTIL-LICENSE file. + +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package format + +import ( + "bytes" + "fmt" + "io" +) + +const ( + st0 = iota + stBOL + stPERC + stBOLPERC +) + +// Formatter is an io.Writer extended formatter by a fmt.Printf like function Format. +type Formatter interface { + io.Writer + Format(format string, args ...interface{}) (n int, errno error) +} + +type indentFormatter struct { + io.Writer + indent []byte + indentLevel int + state int +} + +var replace = map[rune]string{ + '\000': "\\0", + '\'': "''", + '\n': "\\n", + '\r': "\\r", +} + +// IndentFormatter returns a new Formatter which interprets %i and %u in the +// Format() formats string as indent and unindent commands. The commands can +// nest. The Formatter writes to io.Writer 'w' and inserts one 'indent' +// string per current indent level value. +// Behaviour of commands reaching negative indent levels is undefined. +// IndentFormatter(os.Stdout, "\t").Format("abc%d%%e%i\nx\ny\n%uz\n", 3) +// output: +// abc3%e +// x +// y +// z +// The Go quoted string literal form of the above is: +// "abc%%e\n\tx\n\tx\nz\n" +// The commands can be scattered between separate invocations of Format(), +// i.e. the formatter keeps track of the indent level and knows if it is +// positioned on start of a line and should emit indentation(s). +// The same output as above can be produced by e.g.: +// f := IndentFormatter(os.Stdout, " ") +// f.Format("abc%d%%e%i\nx\n", 3) +// f.Format("y\n%uz\n") +func IndentFormatter(w io.Writer, indent string) Formatter { + return &indentFormatter{w, []byte(indent), 0, stBOL} +} + +func (f *indentFormatter) format(flat bool, format string, args ...interface{}) (n int, errno error) { + var buf = make([]byte, 0) + for i := 0; i < len(format); i++ { + c := format[i] + switch f.state { + case st0: + switch c { + case '\n': + cc := c + if flat && f.indentLevel != 0 { + cc = ' ' + } + buf = append(buf, cc) + f.state = stBOL + case '%': + f.state = stPERC + default: + buf = append(buf, c) + } + case stBOL: + switch c { + case '\n': + cc := c + if flat && f.indentLevel != 0 { + cc = ' ' + } + buf = append(buf, cc) + case '%': + f.state = stBOLPERC + default: + if !flat { + for i := 0; i < f.indentLevel; i++ { + buf = append(buf, f.indent...) + } + } + buf = append(buf, c) + f.state = st0 + } + case stBOLPERC: + switch c { + case 'i': + f.indentLevel++ + f.state = stBOL + case 'u': + f.indentLevel-- + f.state = stBOL + default: + if !flat { + for i := 0; i < f.indentLevel; i++ { + buf = append(buf, f.indent...) + } + } + buf = append(buf, '%', c) + f.state = st0 + } + case stPERC: + switch c { + case 'i': + f.indentLevel++ + f.state = st0 + case 'u': + f.indentLevel-- + f.state = st0 + default: + buf = append(buf, '%', c) + f.state = st0 + } + default: + panic("unexpected state") + } + } + switch f.state { + case stPERC, stBOLPERC: + buf = append(buf, '%') + } + return f.Write([]byte(fmt.Sprintf(string(buf), args...))) +} + +// Format implements Format interface. +func (f *indentFormatter) Format(format string, args ...interface{}) (n int, errno error) { + return f.format(false, format, args...) +} + +type flatFormatter indentFormatter + +// FlatFormatter returns a newly created Formatter with the same functionality as the one returned +// by IndentFormatter except it allows a newline in the 'format' string argument of Format +// to pass through if the indent level is current zero. +// +// If the indent level is non-zero then such new lines are changed to a space character. +// There is no indent string, the %i and %u format verbs are used solely to determine the indent level. +// +// The FlatFormatter is intended for flattening of normally nested structure textual representation to +// a one top level structure per line form. +// FlatFormatter(os.Stdout, " ").Format("abc%d%%e%i\nx\ny\n%uz\n", 3) +// output in the form of a Go quoted string literal: +// "abc3%%e x y z\n" +func FlatFormatter(w io.Writer) Formatter { + return (*flatFormatter)(IndentFormatter(w, "").(*indentFormatter)) +} + +// Format implements Format interface. +func (f *flatFormatter) Format(format string, args ...interface{}) (n int, errno error) { + return (*indentFormatter)(f).format(true, format, args...) +} + +// OutputFormat output escape character with backslash. +func OutputFormat(s string) string { + var buf bytes.Buffer + for _, old := range s { + if newVal, ok := replace[old]; ok { + buf.WriteString(newVal) + continue + } + buf.WriteRune(old) + } + + return buf.String() +} diff --git a/vendor/github.com/pingcap/parser/go.mod1 b/vendor/github.com/pingcap/parser/go.mod1 new file mode 100644 index 0000000000000000000000000000000000000000..3afbad54b186a233f95135d23f0b7de401a87ac8 --- /dev/null +++ b/vendor/github.com/pingcap/parser/go.mod1 @@ -0,0 +1,16 @@ +module github.com/pingcap/parser + +require ( + github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 + github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 + github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 + github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 + github.com/cznic/y v0.0.0-20170802143616-045f81c6662a + github.com/pingcap/check v0.0.0-20171206051426-1c287c953996 + github.com/pingcap/errors v0.11.0 + github.com/pingcap/tidb v0.0.0-20181109062255-f547869f4933 + github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 + github.com/sirupsen/logrus v1.2.0 + golang.org/x/net v0.0.0-20181029044818-c44066c5c816 + golang.org/x/text v0.3.0 +) diff --git a/vendor/github.com/pingcap/parser/go.sum1 b/vendor/github.com/pingcap/parser/go.sum1 new file mode 100644 index 0000000000000000000000000000000000000000..a6c916ca9caf98959440a54c200569be1a2ccfb7 --- /dev/null +++ b/vendor/github.com/pingcap/parser/go.sum1 @@ -0,0 +1,257 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.3+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/blacktear23/go-proxyprotocol v0.0.0-20171102103907-62e368e1c470/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU= +github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292/go.mod h1:qRiX68mZX1lGBkTWyp3CLcenw9I94W2dLeRvMzcn9N4= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible h1:KjVWqrZ5U0wa3CxY2AxlH6/UcB+PK2td1DcsYhA+HRs= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 h1:3jFq2xL4ZajGK4aZY8jz+DAF0FHjI51BXjjSwCzS1Dk= +github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4 h1:CVAqftqbj+exlab+8KJQrE+kNIVlQfJt58j4GxCMF1s= +github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= +github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 h1:y+DH9ARrWiiNBV+6waYP2IPcsRbxdU1qsnycPfShF4c= +github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 h1:uWcWCkSP+E1w1z8r082miT+c+9vzg+5UdrgGCo15lMo= +github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM= +github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 h1:hxuZop6tSoOi0sxFzoGGYdRqNrPubyaIf9KoBG9tPiE= +github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= +github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 h1:0rkFMAbn5KBKNpJyHQ6Prb95vIKanmAe62KxsrN+sqA= +github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= +github.com/cznic/y v0.0.0-20170802143616-045f81c6662a h1:N2rDAvHuM46OGscJkGX4Dw4BBqZgg6mGNGLYs5utVVo= +github.com/cznic/y v0.0.0-20170802143616-045f81c6662a/go.mod h1:1rk5VM7oSnA4vjp+hrLQ3HWHa+Y4yPCa3/CsJrcNnvs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v0.0.0-20180227141424-093482f3f8ce/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/etcd-io/gofail v0.0.0-20180808172546-51ce9a71510a h1:QNEenQIsGDEEfFNSnN+h6hE1OwnHqTg7Dl9gEk1Cko4= +github.com/etcd-io/gofail v0.0.0-20180808172546-51ce9a71510a/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-sql-driver/mysql v0.0.0-20170715192408-3955978caca4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff h1:kOkM9whyQYodu09SJ6W3NCsHG7crFaJILQ22Gozp3lg= +github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= +github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:BWIsLfhgKhV5g/oF34aRjniBHLTZe5DNekSjbAjIS6c= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/IwvnDIZ0LHJK1nk= +github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea h1:g2k+8WR7cHch4g0tBDhfiEvAp7fXxTNBiD1oC1Oxj3E= +github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8= +github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 h1:WQM1NildKThwdP7qWrNAFGzp4ijNLw8RlgENkaI4MJs= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/montanaflynn/stats v0.0.0-20180911141734-db72e6cae808 h1:pmpDGKLw4n82EtrNiLqB+xSz/JQwFOaZuMALYUHwX5s= +github.com/montanaflynn/stats v0.0.0-20180911141734-db72e6cae808/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/myesui/uuid v1.0.0 h1:xCBmH4l5KuvLYc5L7AS7SZg9/jKdIFubM7OVoLqaQUI= +github.com/myesui/uuid v1.0.0/go.mod h1:2CDfNgU0LR8mIdO8vdWd8i9gWWxLlcoIGGpSNgafq84= +github.com/ngaut/log v0.0.0-20180314031856-b8e36e7ba5ac/go.mod h1:ueVCjKQllPmX7uEvCYnZD5b8qjidGf1TCH61arVe4SU= +github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7 h1:7KAv7KMGTTqSmYZtNdcNTgsos+vFzULLwyElndwn+5c= +github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7/go.mod h1:iWMfgwqYW+e8n5lC/jjNEhwcjbRDpl5NT7n2h+4UNcI= +github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef h1:K0Fn+DoFqNqktdZtdV3bPQ/0cuYh2H4rkg0tytX/07k= +github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef/go.mod h1:7WjlapSfwQyo6LNmIvEWzsW1hbBQfpUO4JWnuQRmva8= +github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/xxHash v0.1.1/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I= +github.com/pingcap/check v0.0.0-20171206051426-1c287c953996 h1:ZBdiJCMan6GSo/aPAM7gywcUKa0z58gczVrnG6TQnAQ= +github.com/pingcap/check v0.0.0-20171206051426-1c287c953996/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= +github.com/pingcap/errcode v0.0.0-20180921232412-a1a7271709d9/go.mod h1:4b2X8xSqxIroj/IZ9MX/VGZhAwc11wB9wRIzHvz6SeM= +github.com/pingcap/errors v0.11.0 h1:DCJQB8jrHbQ1VVlMFIrbj2ApScNNotVmkSNplu2yUt4= +github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e h1:P73/4dPCL96rGrobssy1nVy2VaVpNCuLpCbr+FEaTA8= +github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= +github.com/pingcap/kvproto v0.0.0-20181028030329-855d2192cdc7 h1:CYssSnPvf90ZSbFdZpsZGSI7y+drG1EfKxqTOnKnHb0= +github.com/pingcap/kvproto v0.0.0-20181028030329-855d2192cdc7/go.mod h1:0gwbe1F2iBIjuQ9AH0DbQhL+Dpr5GofU8fgYyXk+ykk= +github.com/pingcap/kvproto v0.0.0-20181105061835-1b5d69cd1d26/go.mod h1:0gwbe1F2iBIjuQ9AH0DbQhL+Dpr5GofU8fgYyXk+ykk= +github.com/pingcap/parser v0.0.0-20181102070703-4acd198f5092/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE= +github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= +github.com/pingcap/tidb v0.0.0-20181105182855-379ee5b1915a h1:Qd8qbDnsmAIXxefGBgFrWh4y0GDO6froUNFqZYmC568= +github.com/pingcap/tidb v0.0.0-20181105182855-379ee5b1915a/go.mod h1:tq1TVnaDUrh46KbB+oJA34Ob3eMbinTopWVzhX5Rj94= +github.com/pingcap/tidb v0.0.0-20181106092750-bb6d0a935d70 h1:a71Zzbf3hautypbfreDgnT+NWtTTJATGGcssArxl/WQ= +github.com/pingcap/tidb v0.0.0-20181106092750-bb6d0a935d70/go.mod h1:tq1TVnaDUrh46KbB+oJA34Ob3eMbinTopWVzhX5Rj94= +github.com/pingcap/tidb v0.0.0-20181109062255-f547869f4933 h1:YwXtZpzgqq6LymXQXHBpneC7yQpxeXpAO5cuafuFgMQ= +github.com/pingcap/tidb v0.0.0-20181109062255-f547869f4933/go.mod h1:GJ1YwdkgaTo6oaWlg9K8nKZ3RaYaP5qXJl/lCywOQ5I= +github.com/pingcap/tidb v2.0.8+incompatible h1:4G85C71eFTQRJ0Icwul/z3gJfR0u0aWXq1t/f4O8R40= +github.com/pingcap/tidb v2.0.8+incompatible/go.mod h1:I8C6jrPINP2rrVunTRd7C9fRRhQrtR43S1/CL5ix/yQ= +github.com/pingcap/tidb-tools v0.0.0-20181101090416-cfac1096162e h1:LKGiK9RwOntq4kniQdGM9q1Cg4AGeIyHBeiFc2OIlpo= +github.com/pingcap/tidb-tools v0.0.0-20181101090416-cfac1096162e/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= +github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 h1:mRKKzRjDNaUNPnAkPAHnRqpNmwNWBX1iA+hxlmvQ93I= +github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.0 h1:tXuTFVHC03mW0D+Ua1Q2d1EAVqLTuggX50V0VLICCzY= +github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 h1:Cto4X6SVMWRPBkJ/3YHn1iDGDGc/Z+sW+AEMKHMVvN4= +github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/syndtr/goleveldb v0.0.0-20180815032940-ae2bd5eed72d/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 h1:lYIiVDtZnyTWlNwiAxLj0bbpTcx1BWCFhXjfsvmPdNc= +github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk= +github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY= +github.com/uber-go/atomic v1.3.2 h1:Azu9lPBWRNKzYXSIwRfgRuDuS0YKsK4NFhiQv98gkxo= +github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/uber/jaeger-client-go v2.15.0+incompatible h1:NP3qsSqNxh8VYr956ur1N/1C1PjvOJnJykCzcD5QHbk= +github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v1.5.0 h1:OHbgr8l656Ub3Fw5k9SWnBfIEwvoHQ+W2y+Aa9D1Uyo= +github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go v1.1.1 h1:gmervu+jDMvXTbcHQ0pd2wee85nEoE0BsVyEuzkfK8w= +github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/unrolled/render v0.0.0-20180914162206-b9786414de4d h1:ggUgChAeyge4NZ4QUw6lhHsVymzwSDJOZcE0s2X8S20= +github.com/unrolled/render v0.0.0-20180914162206-b9786414de4d/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 h1:MPPkRncZLN9Kh4MEFmbnK4h3BD7AUmskWv2+EeZJCCs= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.8.0 h1:r6Za1Rii8+EGOYRDLvpooNOF6kP3iyDnkpzbw67gCQ8= +go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816 h1:mVFkLpejdFLXVUv9E42f3XJVfMdqd0IVLVIVLjZWn5o= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181031022657-8527f56f7107/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc h1:SdCq5U4J+PpbSDIl9bM0V1e1Ug1jsnBkAFvTs1htn7U= +golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2 h1:67iHsV9djwGdZpdZNbLuQj6FOzCaZe3w+vhLjn5AcFA= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M= +gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/pingcap/parser/lexer.go b/vendor/github.com/pingcap/parser/lexer.go new file mode 100644 index 0000000000000000000000000000000000000000..56498d153aa060fa651181ea9dfc83fb6812d9f2 --- /dev/null +++ b/vendor/github.com/pingcap/parser/lexer.go @@ -0,0 +1,795 @@ +// Copyright 2016 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "bytes" + "fmt" + "strings" + "unicode" + "unicode/utf8" + + "github.com/pingcap/parser/mysql" +) + +var _ = yyLexer(&Scanner{}) + +// Pos represents the position of a token. +type Pos struct { + Line int + Col int + Offset int +} + +// Scanner implements the yyLexer interface. +type Scanner struct { + r reader + buf bytes.Buffer + + errs []error + stmtStartPos int + + // For scanning such kind of comment: /*! MySQL-specific code */ or /*+ optimizer hint */ + specialComment specialCommentScanner + + sqlMode mysql.SQLMode + + // If the lexer should recognize keywords for window function. + // It may break the compatibility when support those keywords, + // because some application may already use them as identifiers. + supportWindowFunc bool +} + +type specialCommentScanner interface { + scan() (tok int, pos Pos, lit string) +} + +type mysqlSpecificCodeScanner struct { + *Scanner + Pos +} + +func (s *mysqlSpecificCodeScanner) scan() (tok int, pos Pos, lit string) { + tok, pos, lit = s.Scanner.scan() + pos.Line += s.Pos.Line + pos.Col += s.Pos.Col + pos.Offset += s.Pos.Offset + return +} + +type optimizerHintScanner struct { + *Scanner + Pos + end bool +} + +func (s *optimizerHintScanner) scan() (tok int, pos Pos, lit string) { + tok, pos, lit = s.Scanner.scan() + pos.Line += s.Pos.Line + pos.Col += s.Pos.Col + pos.Offset += s.Pos.Offset + if tok == 0 { + if !s.end { + tok = hintEnd + s.end = true + } + } + return +} + +// Errors returns the errors during a scan. +func (s *Scanner) Errors() []error { + return s.errs +} + +// reset resets the sql string to be scanned. +func (s *Scanner) reset(sql string) { + s.r = reader{s: sql, p: Pos{Line: 1}} + s.buf.Reset() + s.errs = s.errs[:0] + s.stmtStartPos = 0 + s.specialComment = nil +} + +func (s *Scanner) stmtText() string { + endPos := s.r.pos().Offset + if s.r.s[endPos-1] == '\n' { + endPos = endPos - 1 // trim new line + } + if s.r.s[s.stmtStartPos] == '\n' { + s.stmtStartPos++ + } + + text := s.r.s[s.stmtStartPos:endPos] + + s.stmtStartPos = endPos + return text +} + +// Errorf tells scanner something is wrong. +// Scanner satisfies yyLexer interface which need this function. +func (s *Scanner) Errorf(format string, a ...interface{}) { + str := fmt.Sprintf(format, a...) + val := s.r.s[s.r.pos().Offset:] + if len(val) > 2048 { + val = val[:2048] + } + err := fmt.Errorf("line %d column %d near \"%s\"%s (total length %d)", s.r.p.Line, s.r.p.Col, val, str, len(s.r.s)) + s.errs = append(s.errs, err) +} + +// Lex returns a token and store the token value in v. +// Scanner satisfies yyLexer interface. +// 0 and invalid are special token id this function would return: +// return 0 tells parser that scanner meets EOF, +// return invalid tells parser that scanner meets illegal character. +func (s *Scanner) Lex(v *yySymType) int { + tok, pos, lit := s.scan() + v.offset = pos.Offset + v.ident = lit + if tok == identifier { + tok = handleIdent(v) + } + if tok == identifier { + if tok1 := s.isTokenIdentifier(lit, pos.Offset); tok1 != 0 { + tok = tok1 + } + } + if s.sqlMode.HasANSIQuotesMode() && + tok == stringLit && + s.r.s[v.offset] == '"' { + tok = identifier + } + + if tok == pipes && !(s.sqlMode.HasPipesAsConcatMode()) { + return pipesAsOr + } + + if tok == not && s.sqlMode.HasHighNotPrecedenceMode() { + return not2 + } + + switch tok { + case intLit: + return toInt(s, v, lit) + case floatLit: + return toFloat(s, v, lit) + case decLit: + return toDecimal(s, v, lit) + case hexLit: + return toHex(s, v, lit) + case bitLit: + return toBit(s, v, lit) + case singleAtIdentifier, doubleAtIdentifier, cast, extract: + v.item = lit + return tok + case null: + v.item = nil + case quotedIdentifier: + tok = identifier + } + if tok == unicode.ReplacementChar && s.r.eof() { + return 0 + } + return tok +} + +// SetSQLMode sets the SQL mode for scanner. +func (s *Scanner) SetSQLMode(mode mysql.SQLMode) { + s.sqlMode = mode +} + +// GetSQLMode return the SQL mode of scanner. +func (s *Scanner) GetSQLMode() mysql.SQLMode { + return s.sqlMode +} + +// EnableWindowFunc enables the scanner to recognize the keywords of window function. +func (s *Scanner) EnableWindowFunc() { + s.supportWindowFunc = true +} + +// NewScanner returns a new scanner object. +func NewScanner(s string) *Scanner { + return &Scanner{r: reader{s: s}} +} + +func (s *Scanner) skipWhitespace() rune { + return s.r.incAsLongAs(unicode.IsSpace) +} + +func (s *Scanner) scan() (tok int, pos Pos, lit string) { + if s.specialComment != nil { + // Enter specialComment scan mode. + // for scanning such kind of comment: /*! MySQL-specific code */ + specialComment := s.specialComment + tok, pos, lit = specialComment.scan() + if tok != 0 { + // return the specialComment scan result as the result + return + } + // leave specialComment scan mode after all stream consumed. + s.specialComment = nil + } + + ch0 := s.r.peek() + if unicode.IsSpace(ch0) { + ch0 = s.skipWhitespace() + } + pos = s.r.pos() + if s.r.eof() { + // when scanner meets EOF, the returned token should be 0, + // because 0 is a special token id to remind the parser that stream is end. + return 0, pos, "" + } + + if !s.r.eof() && isIdentExtend(ch0) { + return scanIdentifier(s) + } + + // search a trie to get a token. + node := &ruleTable + for ch0 >= 0 && ch0 <= 255 { + if node.childs[ch0] == nil || s.r.eof() { + break + } + node = node.childs[ch0] + if node.fn != nil { + return node.fn(s) + } + s.r.inc() + ch0 = s.r.peek() + } + + tok, lit = node.token, s.r.data(&pos) + return +} + +func startWithXx(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + s.r.inc() + if s.r.peek() == '\'' { + s.r.inc() + s.scanHex() + if s.r.peek() == '\'' { + s.r.inc() + tok, lit = hexLit, s.r.data(&pos) + } else { + tok = unicode.ReplacementChar + } + return + } + s.r.incAsLongAs(isIdentChar) + tok, lit = identifier, s.r.data(&pos) + return +} + +func startWithNn(s *Scanner) (tok int, pos Pos, lit string) { + tok, pos, lit = scanIdentifier(s) + // The National Character Set, N'some text' or n'some test'. + // See https://dev.mysql.com/doc/refman/5.7/en/string-literals.html + // and https://dev.mysql.com/doc/refman/5.7/en/charset-national.html + if lit == "N" || lit == "n" { + if s.r.peek() == '\'' { + tok = underscoreCS + lit = "utf8" + } + } + return +} + +func startWithBb(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + s.r.inc() + if s.r.peek() == '\'' { + s.r.inc() + s.scanBit() + if s.r.peek() == '\'' { + s.r.inc() + tok, lit = bitLit, s.r.data(&pos) + } else { + tok = unicode.ReplacementChar + } + return + } + s.r.incAsLongAs(isIdentChar) + tok, lit = identifier, s.r.data(&pos) + return +} + +func startWithSharp(s *Scanner) (tok int, pos Pos, lit string) { + s.r.incAsLongAs(func(ch rune) bool { + return ch != '\n' + }) + return s.scan() +} + +func startWithDash(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + if strings.HasPrefix(s.r.s[pos.Offset:], "--") { + remainLen := len(s.r.s[pos.Offset:]) + if remainLen == 2 || (remainLen > 2 && unicode.IsSpace(rune(s.r.s[pos.Offset+2]))) { + s.r.incAsLongAs(func(ch rune) bool { + return ch != '\n' + }) + return s.scan() + } + } + if strings.HasPrefix(s.r.s[pos.Offset:], "->>") { + tok = juss + s.r.incN(3) + return + } + if strings.HasPrefix(s.r.s[pos.Offset:], "->") { + tok = jss + s.r.incN(2) + return + } + tok = int('-') + s.r.inc() + return +} + +func startWithSlash(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + s.r.inc() + ch0 := s.r.peek() + if ch0 == '*' { + s.r.inc() + startWithAsterisk := false + for { + ch0 = s.r.readByte() + if startWithAsterisk && ch0 == '/' { + // Meets */, means comment end. + break + } else if ch0 == '*' { + startWithAsterisk = true + } else { + startWithAsterisk = false + } + + if ch0 == unicode.ReplacementChar && s.r.eof() { + // unclosed comment + s.errs = append(s.errs, ParseErrorWith(s.r.data(&pos), s.r.p.Line)) + return + } + + } + + comment := s.r.data(&pos) + + // See https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html + if strings.HasPrefix(comment, "/*+") { + begin := sqlOffsetInComment(comment) + end := len(comment) - 2 + sql := comment[begin:end] + s.specialComment = &optimizerHintScanner{ + Scanner: NewScanner(sql), + Pos: Pos{ + pos.Line, + pos.Col, + pos.Offset + begin, + }, + } + + tok = hintBegin + return + } + + // See http://dev.mysql.com/doc/refman/5.7/en/comments.html + // Convert "/*!VersionNumber MySQL-specific-code */" to "MySQL-specific-code". + if strings.HasPrefix(comment, "/*!") { + sql := specCodePattern.ReplaceAllStringFunc(comment, TrimComment) + s.specialComment = &mysqlSpecificCodeScanner{ + Scanner: NewScanner(sql), + Pos: Pos{ + pos.Line, + pos.Col, + pos.Offset + sqlOffsetInComment(comment), + }, + } + } + + return s.scan() + } + tok = int('/') + return +} + +func sqlOffsetInComment(comment string) int { + // find the first SQL token offset in pattern like "/*!40101 mysql specific code */" + offset := 0 + for i := 0; i < len(comment); i++ { + if unicode.IsSpace(rune(comment[i])) { + offset = i + break + } + } + for offset < len(comment) { + offset++ + if !unicode.IsSpace(rune(comment[offset])) { + break + } + } + return offset +} + +func startWithAt(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + s.r.inc() + ch1 := s.r.peek() + if ch1 == '\'' || ch1 == '"' { + nTok, nPos, nLit := startString(s) + if nTok == stringLit { + tok = singleAtIdentifier + pos = nPos + lit = nLit + } else { + tok = int('@') + } + } else if ch1 == '`' { + nTok, nPos, nLit := scanQuotedIdent(s) + if nTok == quotedIdentifier { + tok = singleAtIdentifier + pos = nPos + lit = nLit + } else { + tok = int('@') + } + } else if isUserVarChar(ch1) { + s.r.incAsLongAs(isUserVarChar) + tok, lit = singleAtIdentifier, s.r.data(&pos) + } else if ch1 == '@' { + s.r.inc() + stream := s.r.s[pos.Offset+2:] + for _, v := range []string{"global.", "session.", "local."} { + if len(v) > len(stream) { + continue + } + if strings.EqualFold(stream[:len(v)], v) { + s.r.incN(len(v)) + break + } + } + s.r.incAsLongAs(isIdentChar) + tok, lit = doubleAtIdentifier, s.r.data(&pos) + } else { + tok, lit = singleAtIdentifier, s.r.data(&pos) + } + return +} + +func scanIdentifier(s *Scanner) (int, Pos, string) { + pos := s.r.pos() + s.r.inc() + s.r.incAsLongAs(isIdentChar) + return identifier, pos, s.r.data(&pos) +} + +var ( + quotedIdentifier = -identifier +) + +func scanQuotedIdent(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + s.r.inc() + s.buf.Reset() + for { + ch := s.r.readByte() + if ch == unicode.ReplacementChar && s.r.eof() { + tok = unicode.ReplacementChar + return + } + if ch == '`' { + if s.r.peek() != '`' { + // don't return identifier in case that it's interpreted as keyword token later. + tok, lit = quotedIdentifier, s.buf.String() + return + } + s.r.inc() + } + s.buf.WriteRune(ch) + } +} + +func startString(s *Scanner) (tok int, pos Pos, lit string) { + return s.scanString() +} + +// lazyBuf is used to avoid allocation if possible. +// it has a useBuf field indicates whether bytes.Buffer is necessary. if +// useBuf is false, we can avoid calling bytes.Buffer.String(), which +// make a copy of data and cause allocation. +type lazyBuf struct { + useBuf bool + r *reader + b *bytes.Buffer + p *Pos +} + +func (mb *lazyBuf) setUseBuf(str string) { + if !mb.useBuf { + mb.useBuf = true + mb.b.Reset() + mb.b.WriteString(str) + } +} + +func (mb *lazyBuf) writeRune(r rune, w int) { + if mb.useBuf { + if w > 1 { + mb.b.WriteRune(r) + } else { + mb.b.WriteByte(byte(r)) + } + } +} + +func (mb *lazyBuf) data() string { + var lit string + if mb.useBuf { + lit = mb.b.String() + } else { + lit = mb.r.data(mb.p) + lit = lit[1 : len(lit)-1] + } + return lit +} + +func (s *Scanner) scanString() (tok int, pos Pos, lit string) { + tok, pos = stringLit, s.r.pos() + mb := lazyBuf{false, &s.r, &s.buf, &pos} + ending := s.r.readByte() + ch0 := s.r.peek() + for !s.r.eof() { + if ch0 == ending { + s.r.inc() + if s.r.peek() != ending { + lit = mb.data() + return + } + str := mb.r.data(&pos) + mb.setUseBuf(str[1 : len(str)-1]) + } else if ch0 == '\\' && !s.sqlMode.HasNoBackslashEscapesMode() { + mb.setUseBuf(mb.r.data(&pos)[1:]) + ch0 = handleEscape(s) + } + mb.writeRune(ch0, s.r.w) + if !s.r.eof() { + s.r.inc() + ch0 = s.r.peek() + } + } + + tok = unicode.ReplacementChar + return +} + +// handleEscape handles the case in scanString when previous char is '\'. +func handleEscape(s *Scanner) rune { + s.r.inc() + ch0 := s.r.peek() + /* + \" \' \\ \n \0 \b \Z \r \t ==> escape to one char + \% \_ ==> preserve both char + other ==> remove \ + */ + switch ch0 { + case 'n': + ch0 = '\n' + case '0': + ch0 = 0 + case 'b': + ch0 = 8 + case 'Z': + ch0 = 26 + case 'r': + ch0 = '\r' + case 't': + ch0 = '\t' + case '%', '_': + s.buf.WriteByte('\\') + } + return ch0 +} + +func startWithNumber(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + tok = intLit + ch0 := s.r.readByte() + if ch0 == '0' { + tok = intLit + ch1 := s.r.peek() + switch { + case ch1 >= '0' && ch1 <= '7': + s.r.inc() + s.scanOct() + case ch1 == 'x' || ch1 == 'X': + s.r.inc() + s.scanHex() + tok = hexLit + case ch1 == 'b': + s.r.inc() + s.scanBit() + tok = bitLit + case ch1 == '.': + return s.scanFloat(&pos) + case ch1 == 'B': + tok = unicode.ReplacementChar + return + } + } + + s.scanDigits() + ch0 = s.r.peek() + if ch0 == '.' || ch0 == 'e' || ch0 == 'E' { + return s.scanFloat(&pos) + } + + // Identifiers may begin with a digit but unless quoted may not consist solely of digits. + if !s.r.eof() && isIdentChar(ch0) { + s.r.incAsLongAs(isIdentChar) + return identifier, pos, s.r.data(&pos) + } + lit = s.r.data(&pos) + return +} + +func startWithDot(s *Scanner) (tok int, pos Pos, lit string) { + pos = s.r.pos() + s.r.inc() + save := s.r.pos() + if isDigit(s.r.peek()) { + tok, _, lit = s.scanFloat(&pos) + if s.r.eof() || !isIdentChar(s.r.peek()) { + return + } + // Fail to parse a float, reset to dot. + s.r.p = save + } + tok, lit = int('.'), "." + return +} + +func (s *Scanner) scanOct() { + s.r.incAsLongAs(func(ch rune) bool { + return ch >= '0' && ch <= '7' + }) +} + +func (s *Scanner) scanHex() { + s.r.incAsLongAs(func(ch rune) bool { + return ch >= '0' && ch <= '9' || + ch >= 'a' && ch <= 'f' || + ch >= 'A' && ch <= 'F' + }) +} + +func (s *Scanner) scanBit() { + s.r.incAsLongAs(func(ch rune) bool { + return ch == '0' || ch == '1' + }) +} + +func (s *Scanner) scanFloat(beg *Pos) (tok int, pos Pos, lit string) { + s.r.p = *beg + // float = D1 . D2 e D3 + s.scanDigits() + ch0 := s.r.peek() + if ch0 == '.' { + s.r.inc() + s.scanDigits() + ch0 = s.r.peek() + } + if ch0 == 'e' || ch0 == 'E' { + s.r.inc() + ch0 = s.r.peek() + if ch0 == '-' || ch0 == '+' { + s.r.inc() + } + s.scanDigits() + tok = floatLit + } else { + tok = decLit + } + pos, lit = *beg, s.r.data(beg) + return +} + +func (s *Scanner) scanDigits() string { + pos := s.r.pos() + s.r.incAsLongAs(isDigit) + return s.r.data(&pos) +} + +type reader struct { + s string + p Pos + w int +} + +var eof = Pos{-1, -1, -1} + +func (r *reader) eof() bool { + return r.p.Offset >= len(r.s) +} + +// peek() peeks a rune from underlying reader. +// if reader meets EOF, it will return unicode.ReplacementChar. to distinguish from +// the real unicode.ReplacementChar, the caller should call r.eof() again to check. +func (r *reader) peek() rune { + if r.eof() { + return unicode.ReplacementChar + } + v, w := rune(r.s[r.p.Offset]), 1 + switch { + case v == 0: + r.w = w + return v // illegal UTF-8 encoding + case v >= 0x80: + v, w = utf8.DecodeRuneInString(r.s[r.p.Offset:]) + if v == utf8.RuneError && w == 1 { + v = rune(r.s[r.p.Offset]) // illegal UTF-8 encoding + } + } + r.w = w + return v +} + +// inc increase the position offset of the reader. +// peek must be called before calling inc! +func (r *reader) inc() { + if r.s[r.p.Offset] == '\n' { + r.p.Line++ + r.p.Col = 0 + } + r.p.Offset += r.w + r.p.Col++ +} + +func (r *reader) incN(n int) { + for i := 0; i < n; i++ { + r.inc() + } +} + +func (r *reader) readByte() (ch rune) { + ch = r.peek() + if ch == unicode.ReplacementChar && r.eof() { + return + } + r.inc() + return +} + +func (r *reader) pos() Pos { + return r.p +} + +func (r *reader) data(from *Pos) string { + return r.s[from.Offset:r.p.Offset] +} + +func (r *reader) incAsLongAs(fn func(rune) bool) rune { + for { + ch := r.peek() + if !fn(ch) { + return ch + } + if ch == unicode.ReplacementChar && r.eof() { + return 0 + } + r.inc() + } +} diff --git a/vendor/github.com/pingcap/parser/misc.go b/vendor/github.com/pingcap/parser/misc.go new file mode 100644 index 0000000000000000000000000000000000000000..c990dbd12d260d5ae0688d2fc542c145786c111c --- /dev/null +++ b/vendor/github.com/pingcap/parser/misc.go @@ -0,0 +1,652 @@ +// Copyright 2016 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "strings" + + "github.com/pingcap/parser/charset" + "github.com/pingcap/tidb/util/hack" +) + +func isLetter(ch rune) bool { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') +} + +func isDigit(ch rune) bool { + return ch >= '0' && ch <= '9' +} + +func isIdentChar(ch rune) bool { + return isLetter(ch) || isDigit(ch) || ch == '_' || ch == '$' || isIdentExtend(ch) +} + +func isIdentExtend(ch rune) bool { + return ch >= 0x80 && ch <= '\uffff' +} + +func isUserVarChar(ch rune) bool { + return isLetter(ch) || isDigit(ch) || ch == '_' || ch == '$' || ch == '.' || isIdentExtend(ch) +} + +type trieNode struct { + childs [256]*trieNode + token int + fn func(s *Scanner) (int, Pos, string) +} + +var ruleTable trieNode + +func initTokenByte(c byte, tok int) { + if ruleTable.childs[c] == nil { + ruleTable.childs[c] = &trieNode{} + } + ruleTable.childs[c].token = tok +} + +func initTokenString(str string, tok int) { + node := &ruleTable + for _, c := range str { + if node.childs[c] == nil { + node.childs[c] = &trieNode{} + } + node = node.childs[c] + } + node.token = tok +} + +func initTokenFunc(str string, fn func(s *Scanner) (int, Pos, string)) { + for i := 0; i < len(str); i++ { + c := str[i] + if ruleTable.childs[c] == nil { + ruleTable.childs[c] = &trieNode{} + } + ruleTable.childs[c].fn = fn + } + return +} + +func init() { + // invalid is a special token defined in parser.y, when parser meet + // this token, it will throw an error. + // set root trie node's token to invalid, so when input match nothing + // in the trie, invalid will be the default return token. + ruleTable.token = invalid + initTokenByte('*', int('*')) + initTokenByte('/', int('/')) + initTokenByte('+', int('+')) + initTokenByte('>', int('>')) + initTokenByte('<', int('<')) + initTokenByte('(', int('(')) + initTokenByte(')', int(')')) + initTokenByte(';', int(';')) + initTokenByte(',', int(',')) + initTokenByte('&', int('&')) + initTokenByte('%', int('%')) + initTokenByte(':', int(':')) + initTokenByte('|', int('|')) + initTokenByte('!', int('!')) + initTokenByte('^', int('^')) + initTokenByte('~', int('~')) + initTokenByte('\\', int('\\')) + initTokenByte('?', paramMarker) + initTokenByte('=', eq) + initTokenByte('{', int('{')) + initTokenByte('}', int('}')) + + initTokenString("||", pipes) + initTokenString("&&", andand) + initTokenString("&^", andnot) + initTokenString(":=", assignmentEq) + initTokenString("<=>", nulleq) + initTokenString(">=", ge) + initTokenString("<=", le) + initTokenString("!=", neq) + initTokenString("<>", neqSynonym) + initTokenString("<<", lsh) + initTokenString(">>", rsh) + initTokenString("\\N", null) + + initTokenFunc("@", startWithAt) + initTokenFunc("/", startWithSlash) + initTokenFunc("-", startWithDash) + initTokenFunc("#", startWithSharp) + initTokenFunc("Xx", startWithXx) + initTokenFunc("Nn", startWithNn) + initTokenFunc("Bb", startWithBb) + initTokenFunc(".", startWithDot) + initTokenFunc("_$ACDEFGHIJKLMOPQRSTUVWYZacdefghijklmopqrstuvwyz", scanIdentifier) + initTokenFunc("`", scanQuotedIdent) + initTokenFunc("0123456789", startWithNumber) + initTokenFunc("'\"", startString) +} + +var tokenMap = map[string]int{ + "ACTION": action, + "ADD": add, + "ADDDATE": addDate, + "ADMIN": admin, + "AFTER": after, + "ALL": all, + "ALGORITHM": algorithm, + "ALTER": alter, + "ALWAYS": always, + "ANALYZE": analyze, + "AND": and, + "ANY": any, + "AS": as, + "ASC": asc, + "ASCII": ascii, + "AUTO_INCREMENT": autoIncrement, + "AVG": avg, + "AVG_ROW_LENGTH": avgRowLength, + "BEGIN": begin, + "BETWEEN": between, + "BIGINT": bigIntType, + "BINARY": binaryType, + "BINLOG": binlog, + "BIT": bitType, + "BIT_AND": bitAnd, + "BIT_OR": bitOr, + "BIT_XOR": bitXor, + "BLOB": blobType, + "BOOL": boolType, + "BOOLEAN": booleanType, + "BOTH": both, + "BTREE": btree, + "BUCKETS": buckets, + "BY": by, + "BYTE": byteType, + "CANCEL": cancel, + "CASCADE": cascade, + "CASCADED": cascaded, + "CASE": caseKwd, + "CAST": cast, + "CHANGE": change, + "CHAR": charType, + "CHARACTER": character, + "CHARSET": charsetKwd, + "CHECK": check, + "CHECKSUM": checksum, + "CLEANUP": cleanup, + "CLIENT": client, + "COALESCE": coalesce, + "COLLATE": collate, + "COLLATION": collation, + "COLUMN": column, + "COLUMNS": columns, + "COMMENT": comment, + "COMMIT": commit, + "COMMITTED": committed, + "COMPACT": compact, + "COMPRESSED": compressed, + "COMPRESSION": compression, + "CONNECTION": connection, + "CONSISTENT": consistent, + "CONSTRAINT": constraint, + "CONVERT": convert, + "COPY": copyKwd, + "COUNT": count, + "CREATE": create, + "CROSS": cross, + "CURRENT": current, + "CURRENT_DATE": currentDate, + "CURRENT_TIME": currentTime, + "CURRENT_TIMESTAMP": currentTs, + "CURRENT_USER": currentUser, + "CURTIME": curTime, + "DATA": data, + "DATABASE": database, + "DATABASES": databases, + "DATE": dateType, + "DATE_ADD": dateAdd, + "DATE_SUB": dateSub, + "DATETIME": datetimeType, + "DAY": day, + "DAY_HOUR": dayHour, + "DAY_MICROSECOND": dayMicrosecond, + "DAY_MINUTE": dayMinute, + "DAY_SECOND": daySecond, + "DDL": ddl, + "DEALLOCATE": deallocate, + "DEC": decimalType, + "DECIMAL": decimalType, + "DEFAULT": defaultKwd, + "DEFINER": definer, + "DELAY_KEY_WRITE": delayKeyWrite, + "DELAYED": delayed, + "DELETE": deleteKwd, + "DESC": desc, + "DESCRIBE": describe, + "DISABLE": disable, + "DISTINCT": distinct, + "DISTINCTROW": distinct, + "DIV": div, + "DO": do, + "DOUBLE": doubleType, + "DROP": drop, + "DUAL": dual, + "DUPLICATE": duplicate, + "DYNAMIC": dynamic, + "ELSE": elseKwd, + "ENABLE": enable, + "ENCLOSED": enclosed, + "END": end, + "ENGINE": engine, + "ENGINES": engines, + "ENUM": enum, + "ESCAPE": escape, + "ESCAPED": escaped, + "EVENT": event, + "EVENTS": events, + "EXCLUSIVE": exclusive, + "EXECUTE": execute, + "EXISTS": exists, + "EXPLAIN": explain, + "EXTRACT": extract, + "FALSE": falseKwd, + "FIELDS": fields, + "FIRST": first, + "FIXED": fixed, + "FLOAT": floatType, + "FLUSH": flush, + "FOLLOWING": following, + "FOR": forKwd, + "FORCE": force, + "FOREIGN": foreign, + "FORMAT": format, + "FROM": from, + "FULL": full, + "FULLTEXT": fulltext, + "FUNCTION": function, + "GENERATED": generated, + "GET_FORMAT": getFormat, + "GLOBAL": global, + "GRANT": grant, + "GRANTS": grants, + "GROUP": group, + "GROUP_CONCAT": groupConcat, + "HASH": hash, + "HAVING": having, + "HIGH_PRIORITY": highPriority, + "HOUR": hour, + "HOUR_MICROSECOND": hourMicrosecond, + "HOUR_MINUTE": hourMinute, + "HOUR_SECOND": hourSecond, + "IDENTIFIED": identified, + "IF": ifKwd, + "IGNORE": ignore, + "IN": in, + "INDEX": index, + "INDEXES": indexes, + "INFILE": infile, + "INNER": inner, + "INPLACE": inplace, + "INSERT": insert, + "INT": intType, + "INT1": int1Type, + "INT2": int2Type, + "INT3": int3Type, + "INT4": int4Type, + "INT8": int8Type, + "INTEGER": integerType, + "INTERVAL": interval, + "INTERNAL": internal, + "INTO": into, + "INVOKER": invoker, + "IS": is, + "ISOLATION": isolation, + "JOBS": jobs, + "JOB": job, + "JOIN": join, + "JSON": jsonType, + "KEY": key, + "KEY_BLOCK_SIZE": keyBlockSize, + "KEYS": keys, + "KILL": kill, + "LAST": last, + "LEADING": leading, + "LEFT": left, + "LESS": less, + "LEVEL": level, + "LIKE": like, + "LIMIT": limit, + "LINES": lines, + "LOAD": load, + "LOCAL": local, + "LOCALTIME": localTime, + "LOCALTIMESTAMP": localTs, + "LOCK": lock, + "LONG": long, + "LONGBLOB": longblobType, + "LONGTEXT": longtextType, + "LOW_PRIORITY": lowPriority, + "MASTER": master, + "MAX": max, + "MAX_CONNECTIONS_PER_HOUR": maxConnectionsPerHour, + "MAX_EXECUTION_TIME": maxExecutionTime, + "MAX_QUERIES_PER_HOUR": maxQueriesPerHour, + "MAX_ROWS": maxRows, + "MAX_UPDATES_PER_HOUR": maxUpdatesPerHour, + "MAX_USER_CONNECTIONS": maxUserConnections, + "MAXVALUE": maxValue, + "MEDIUMBLOB": mediumblobType, + "MEDIUMINT": mediumIntType, + "MEDIUMTEXT": mediumtextType, + "MERGE": merge, + "MICROSECOND": microsecond, + "MIN": min, + "MIN_ROWS": minRows, + "MINUTE": minute, + "MINUTE_MICROSECOND": minuteMicrosecond, + "MINUTE_SECOND": minuteSecond, + "MOD": mod, + "MODE": mode, + "MODIFY": modify, + "MONTH": month, + "NAMES": names, + "NATIONAL": national, + "NATURAL": natural, + "NEXT_ROW_ID": next_row_id, + "NO": no, + "NO_WRITE_TO_BINLOG": noWriteToBinLog, + "NONE": none, + "NOT": not, + "NOW": now, + "NULL": null, + "NULLS": nulls, + "NUMERIC": numericType, + "NVARCHAR": nvarcharType, + "OFFSET": offset, + "ON": on, + "ONLY": only, + "OPTION": option, + "OR": or, + "ORDER": order, + "OUTER": outer, + "PACK_KEYS": packKeys, + "PARTITION": partition, + "PARTITIONS": partitions, + "PASSWORD": password, + "PLUGINS": plugins, + "POSITION": position, + "PRECEDING": preceding, + "PRECISION": precisionType, + "PREPARE": prepare, + "PRIMARY": primary, + "PRIVILEGES": privileges, + "PROCEDURE": procedure, + "PROCESS": process, + "PROCESSLIST": processlist, + "PROFILES": profiles, + "QUARTER": quarter, + "QUERY": query, + "QUERIES": queries, + "QUICK": quick, + "SHARD_ROW_ID_BITS": shardRowIDBits, + "RANGE": rangeKwd, + "RECOVER": recover, + "READ": read, + "REAL": realType, + "RECENT": recent, + "REDUNDANT": redundant, + "REFERENCES": references, + "REGEXP": regexpKwd, + "RELOAD": reload, + "RENAME": rename, + "REPEAT": repeat, + "REPEATABLE": repeatable, + "REPLACE": replace, + "RESPECT": respect, + "REPLICATION": replication, + "RESTRICT": restrict, + "REVERSE": reverse, + "REVOKE": revoke, + "RIGHT": right, + "RLIKE": rlike, + "ROLLBACK": rollback, + "ROUTINE": routine, + "ROW": row, + "ROW_COUNT": rowCount, + "ROW_FORMAT": rowFormat, + "SCHEMA": database, + "SCHEMAS": databases, + "SECOND": second, + "SECOND_MICROSECOND": secondMicrosecond, + "SECURITY": security, + "SELECT": selectKwd, + "SERIALIZABLE": serializable, + "SESSION": session, + "SET": set, + "SEPARATOR": separator, + "SHARE": share, + "SHARED": shared, + "SHOW": show, + "SIGNED": signed, + "SLAVE": slave, + "SLOW": slow, + "SMALLINT": smallIntType, + "SNAPSHOT": snapshot, + "SOME": some, + "SQL": sql, + "SQL_CACHE": sqlCache, + "SQL_CALC_FOUND_ROWS": sqlCalcFoundRows, + "SQL_NO_CACHE": sqlNoCache, + "START": start, + "STARTING": starting, + "STATS": stats, + "STATS_BUCKETS": statsBuckets, + "STATS_HISTOGRAMS": statsHistograms, + "STATS_HEALTHY": statsHealthy, + "STATS_META": statsMeta, + "STATS_PERSISTENT": statsPersistent, + "STATUS": status, + "STD": stddevPop, + "STDDEV": stddevPop, + "STDDEV_POP": stddevPop, + "STDDEV_SAMP": stddevSamp, + "STORED": stored, + "STRAIGHT_JOIN": straightJoin, + "SUBDATE": subDate, + "SUBPARTITION": subpartition, + "SUBPARTITIONS": subpartitions, + "SUBSTR": substring, + "SUBSTRING": substring, + "SUM": sum, + "SUPER": super, + "TABLE": tableKwd, + "TABLES": tables, + "TABLESPACE": tablespace, + "TEMPORARY": temporary, + "TEMPTABLE": temptable, + "TERMINATED": terminated, + "TEXT": textType, + "THAN": than, + "THEN": then, + "TIDB": tidb, + "TIDB_HJ": tidbHJ, + "TIDB_INLJ": tidbINLJ, + "TIDB_SMJ": tidbSMJ, + "TIME": timeType, + "TIMESTAMP": timestampType, + "TIMESTAMPADD": timestampAdd, + "TIMESTAMPDIFF": timestampDiff, + "TINYBLOB": tinyblobType, + "TINYINT": tinyIntType, + "TINYTEXT": tinytextType, + "TO": to, + "TOP": top, + "TRACE": trace, + "TRAILING": trailing, + "TRANSACTION": transaction, + "TRIGGER": trigger, + "TRIGGERS": triggers, + "TRIM": trim, + "TRUE": trueKwd, + "TRUNCATE": truncate, + "UNBOUNDED": unbounded, + "UNCOMMITTED": uncommitted, + "UNDEFINED": undefined, + "UNION": union, + "UNIQUE": unique, + "UNKNOWN": unknown, + "UNLOCK": unlock, + "UNSIGNED": unsigned, + "UPDATE": update, + "USAGE": usage, + "USE": use, + "USER": user, + "USING": using, + "UTC_DATE": utcDate, + "UTC_TIME": utcTime, + "UTC_TIMESTAMP": utcTimestamp, + "VALUE": value, + "VALUES": values, + "VARBINARY": varbinaryType, + "VARCHAR": varcharType, + "VARIABLES": variables, + "VIEW": view, + "VIRTUAL": virtual, + "WARNINGS": warnings, + "ERRORS": identSQLErrors, + "WEEK": week, + "WHEN": when, + "WHERE": where, + "WITH": with, + "WRITE": write, + "XOR": xor, + "YEAR": yearType, + "YEAR_MONTH": yearMonth, + "ZEROFILL": zerofill, +} + +// See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details +var btFuncTokenMap = map[string]int{ + "ADDDATE": builtinAddDate, + "BIT_AND": builtinBitAnd, + "BIT_OR": builtinBitOr, + "BIT_XOR": builtinBitXor, + "CAST": builtinCast, + "COUNT": builtinCount, + "CURDATE": builtinCurDate, + "CURTIME": builtinCurTime, + "DATE_ADD": builtinDateAdd, + "DATE_SUB": builtinDateSub, + "EXTRACT": builtinExtract, + "GROUP_CONCAT": builtinGroupConcat, + "MAX": builtinMax, + "MID": builtinSubstring, + "MIN": builtinMin, + "NOW": builtinNow, + "POSITION": builtinPosition, + "SESSION_USER": builtinUser, + "STD": builtinStddevPop, + "STDDEV": builtinStddevPop, + "STDDEV_POP": builtinStddevPop, + "STDDEV_SAMP": builtinStddevSamp, + "SUBDATE": builtinSubDate, + "SUBSTR": builtinSubstring, + "SUBSTRING": builtinSubstring, + "SUM": builtinSum, + "SYSDATE": builtinSysDate, + "SYSTEM_USER": builtinUser, + "TRIM": builtinTrim, + "VARIANCE": builtinVarPop, + "VAR_POP": builtinVarPop, + "VAR_SAMP": builtinVarSamp, +} + +var windowFuncTokenMap = map[string]int{ + "CUME_DIST": cumeDist, + "DENSE_RANK": denseRank, + "FIRST_VALUE": firstValue, + "GROUPS": groups, + "LAG": lag, + "LAST_VALUE": lastValue, + "LEAD": lead, + "NTH_VALUE": nthValue, + "NTILE": ntile, + "OVER": over, + "PERCENT_RANK": percentRank, + "RANK": rank, + "ROWS": rows, + "ROW_NUMBER": rowNumber, + "WINDOW": window, +} + +// aliases are strings directly map to another string and use the same token. +var aliases = map[string]string{ + "SCHEMA": "DATABASE", + "SCHEMAS": "DATABASES", + "DEC": "DECIMAL", + "SUBSTR": "SUBSTRING", +} + +func (s *Scanner) isTokenIdentifier(lit string, offset int) int { + // An identifier before or after '.' means it is part of a qualified identifier. + // We do not parse it as keyword. + if s.r.peek() == '.' { + return 0 + } + if offset > 0 && s.r.s[offset-1] == '.' { + return 0 + } + buf := &s.buf + buf.Reset() + buf.Grow(len(lit)) + data := buf.Bytes()[:len(lit)] + for i := 0; i < len(lit); i++ { + if lit[i] >= 'a' && lit[i] <= 'z' { + data[i] = lit[i] + 'A' - 'a' + } else { + data[i] = lit[i] + } + } + + checkBtFuncToken, tokenStr := false, string(data) + if s.r.peek() == '(' { + checkBtFuncToken = true + } else if s.sqlMode.HasIgnoreSpaceMode() { + s.skipWhitespace() + if s.r.peek() == '(' { + checkBtFuncToken = true + } + } + if checkBtFuncToken { + if tok := btFuncTokenMap[tokenStr]; tok != 0 { + return tok + } + } + tok, ok := tokenMap[hack.String(data)] + if !ok && s.supportWindowFunc { + tok = windowFuncTokenMap[hack.String(data)] + } + return tok +} + +func handleIdent(lval *yySymType) int { + s := lval.ident + // A character string literal may have an optional character set introducer and COLLATE clause: + // [_charset_name]'string' [COLLATE collation_name] + // See https://dev.mysql.com/doc/refman/5.7/en/charset-literal.html + if !strings.HasPrefix(s, "_") { + return identifier + } + cs, _, err := charset.GetCharsetInfo(s[1:]) + if err != nil { + return identifier + } + lval.ident = cs + return underscoreCS +} diff --git a/vendor/github.com/pingcap/parser/model/ddl.go b/vendor/github.com/pingcap/parser/model/ddl.go new file mode 100644 index 0000000000000000000000000000000000000000..fa7e9887ec0634e0849c32cdf3c7983f4a03c069 --- /dev/null +++ b/vendor/github.com/pingcap/parser/model/ddl.go @@ -0,0 +1,384 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" + "math" + "sync" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/terror" +) + +// ActionType is the type for DDL action. +type ActionType byte + +// List DDL actions. +const ( + ActionNone ActionType = 0 + ActionCreateSchema ActionType = 1 + ActionDropSchema ActionType = 2 + ActionCreateTable ActionType = 3 + ActionDropTable ActionType = 4 + ActionAddColumn ActionType = 5 + ActionDropColumn ActionType = 6 + ActionAddIndex ActionType = 7 + ActionDropIndex ActionType = 8 + ActionAddForeignKey ActionType = 9 + ActionDropForeignKey ActionType = 10 + ActionTruncateTable ActionType = 11 + ActionModifyColumn ActionType = 12 + ActionRebaseAutoID ActionType = 13 + ActionRenameTable ActionType = 14 + ActionSetDefaultValue ActionType = 15 + ActionShardRowID ActionType = 16 + ActionModifyTableComment ActionType = 17 + ActionRenameIndex ActionType = 18 + ActionAddTablePartition ActionType = 19 + ActionDropTablePartition ActionType = 20 +) + +// AddIndexStr is a string related to the operation of "add index". +const AddIndexStr = "add index" + +var actionMap = map[ActionType]string{ + ActionCreateSchema: "create schema", + ActionDropSchema: "drop schema", + ActionCreateTable: "create table", + ActionDropTable: "drop table", + ActionAddColumn: "add column", + ActionDropColumn: "drop column", + ActionAddIndex: AddIndexStr, + ActionDropIndex: "drop index", + ActionAddForeignKey: "add foreign key", + ActionDropForeignKey: "drop foreign key", + ActionTruncateTable: "truncate table", + ActionModifyColumn: "modify column", + ActionRebaseAutoID: "rebase auto_increment ID", + ActionRenameTable: "rename table", + ActionSetDefaultValue: "set default value", + ActionShardRowID: "shard row ID", + ActionModifyTableComment: "modify table comment", + ActionRenameIndex: "rename index", + ActionAddTablePartition: "add partition", + ActionDropTablePartition: "drop table partition", +} + +// String return current ddl action in string +func (action ActionType) String() string { + if v, ok := actionMap[action]; ok { + return v + } + return "none" +} + +// HistoryInfo is used for binlog. +type HistoryInfo struct { + SchemaVersion int64 + DBInfo *DBInfo + TableInfo *TableInfo + FinishedTS uint64 +} + +// AddDBInfo adds schema version and schema information that are used for binlog. +// dbInfo is added in the following operations: create database, drop database. +func (h *HistoryInfo) AddDBInfo(schemaVer int64, dbInfo *DBInfo) { + h.SchemaVersion = schemaVer + h.DBInfo = dbInfo +} + +// AddTableInfo adds schema version and table information that are used for binlog. +// tblInfo is added except for the following operations: create database, drop database. +func (h *HistoryInfo) AddTableInfo(schemaVer int64, tblInfo *TableInfo) { + h.SchemaVersion = schemaVer + h.TableInfo = tblInfo +} + +// Clean cleans history information. +func (h *HistoryInfo) Clean() { + h.SchemaVersion = 0 + h.DBInfo = nil + h.TableInfo = nil +} + +// DDLReorgMeta is meta info of DDL reorganization. +type DDLReorgMeta struct { + // EndHandle is the last handle of the adding indices table. + // We should only backfill indices in the range [startHandle, EndHandle]. + EndHandle int64 `json:"end_handle"` +} + +// NewDDLReorgMeta new a DDLReorgMeta. +func NewDDLReorgMeta() *DDLReorgMeta { + return &DDLReorgMeta{ + EndHandle: math.MaxInt64, + } +} + +// Job is for a DDL operation. +type Job struct { + ID int64 `json:"id"` + Type ActionType `json:"type"` + SchemaID int64 `json:"schema_id"` + TableID int64 `json:"table_id"` + State JobState `json:"state"` + Error *terror.Error `json:"err"` + // ErrorCount will be increased, every time we meet an error when running job. + ErrorCount int64 `json:"err_count"` + // RowCount means the number of rows that are processed. + RowCount int64 `json:"row_count"` + Mu sync.Mutex `json:"-"` + Args []interface{} `json:"-"` + // RawArgs : We must use json raw message to delay parsing special args. + RawArgs json.RawMessage `json:"raw_args"` + SchemaState SchemaState `json:"schema_state"` + // SnapshotVer means snapshot version for this job. + SnapshotVer uint64 `json:"snapshot_ver"` + // StartTS uses timestamp allocated by TSO. + // Now it's the TS when we put the job to TiKV queue. + StartTS uint64 `json:"start_ts"` + // DependencyID is the job's ID that the current job depends on. + DependencyID int64 `json:"dependency_id"` + // Query string of the ddl job. + Query string `json:"query"` + BinlogInfo *HistoryInfo `json:"binlog"` + + // Version indicates the DDL job version. For old jobs, it will be 0. + Version int64 `json:"version"` + + // ReorgMeta is meta info of ddl reorganization. + // This field is depreciated. + ReorgMeta *DDLReorgMeta `json:"reorg_meta"` + + // Priority is only used to set the operation priority of adding indices. + Priority int `json:"priority"` +} + +// FinishTableJob is called when a job is finished. +// It updates the job's state information and adds tblInfo to the binlog. +func (job *Job) FinishTableJob(jobState JobState, schemaState SchemaState, ver int64, tblInfo *TableInfo) { + job.State = jobState + job.SchemaState = schemaState + job.BinlogInfo.AddTableInfo(ver, tblInfo) +} + +// FinishDBJob is called when a job is finished. +// It updates the job's state information and adds dbInfo the binlog. +func (job *Job) FinishDBJob(jobState JobState, schemaState SchemaState, ver int64, dbInfo *DBInfo) { + job.State = jobState + job.SchemaState = schemaState + job.BinlogInfo.AddDBInfo(ver, dbInfo) +} + +// TSConvert2Time converts timestamp to time. +func TSConvert2Time(ts uint64) time.Time { + t := int64(ts >> 18) // 18 is for the logical time. + return time.Unix(t/1e3, (t%1e3)*1e6) +} + +// SetRowCount sets the number of rows. Make sure it can pass `make race`. +func (job *Job) SetRowCount(count int64) { + job.Mu.Lock() + defer job.Mu.Unlock() + + job.RowCount = count +} + +// GetRowCount gets the number of rows. Make sure it can pass `make race`. +func (job *Job) GetRowCount() int64 { + job.Mu.Lock() + defer job.Mu.Unlock() + + return job.RowCount +} + +// Encode encodes job with json format. +// updateRawArgs is used to determine whether to update the raw args. +func (job *Job) Encode(updateRawArgs bool) ([]byte, error) { + var err error + if updateRawArgs { + job.RawArgs, err = json.Marshal(job.Args) + if err != nil { + return nil, errors.Trace(err) + } + } + + var b []byte + job.Mu.Lock() + defer job.Mu.Unlock() + b, err = json.Marshal(job) + + return b, errors.Trace(err) +} + +// Decode decodes job from the json buffer, we must use DecodeArgs later to +// decode special args for this job. +func (job *Job) Decode(b []byte) error { + err := json.Unmarshal(b, job) + return errors.Trace(err) +} + +// DecodeArgs decodes job args. +func (job *Job) DecodeArgs(args ...interface{}) error { + job.Args = args + err := json.Unmarshal(job.RawArgs, &job.Args) + return errors.Trace(err) +} + +// String implements fmt.Stringer interface. +func (job *Job) String() string { + rowCount := job.GetRowCount() + return fmt.Sprintf("ID:%d, Type:%s, State:%s, SchemaState:%s, SchemaID:%d, TableID:%d, RowCount:%d, ArgLen:%d, start time: %v, Err:%v, ErrCount:%d, SnapshotVersion:%v", + job.ID, job.Type, job.State, job.SchemaState, job.SchemaID, job.TableID, rowCount, len(job.Args), TSConvert2Time(job.StartTS), job.Error, job.ErrorCount, job.SnapshotVer) +} + +func (job *Job) hasDependentSchema(other *Job) (bool, error) { + if other.Type == ActionDropSchema || other.Type == ActionCreateSchema { + if other.SchemaID == job.SchemaID { + return true, nil + } + if job.Type == ActionRenameTable { + var oldSchemaID int64 + if err := job.DecodeArgs(&oldSchemaID); err != nil { + return false, errors.Trace(err) + } + if other.SchemaID == oldSchemaID { + return true, nil + } + } + } + return false, nil +} + +// IsDependentOn returns whether the job depends on "other". +// How to check the job depends on "other"? +// 1. The two jobs handle the same database when one of the two jobs is an ActionDropSchema or ActionCreateSchema type. +// 2. Or the two jobs handle the same table. +func (job *Job) IsDependentOn(other *Job) (bool, error) { + isDependent, err := job.hasDependentSchema(other) + if err != nil || isDependent { + return isDependent, errors.Trace(err) + } + isDependent, err = other.hasDependentSchema(job) + if err != nil || isDependent { + return isDependent, errors.Trace(err) + } + + // TODO: If a job is ActionRenameTable, we need to check table name. + if other.TableID == job.TableID { + return true, nil + } + return false, nil +} + +// IsFinished returns whether job is finished or not. +// If the job state is Done or Cancelled, it is finished. +func (job *Job) IsFinished() bool { + return job.State == JobStateDone || job.State == JobStateRollbackDone || job.State == JobStateCancelled +} + +// IsCancelled returns whether the job is cancelled or not. +func (job *Job) IsCancelled() bool { + return job.State == JobStateCancelled +} + +// IsRollbackDone returns whether the job is rolled back or not. +func (job *Job) IsRollbackDone() bool { + return job.State == JobStateRollbackDone +} + +// IsRollingback returns whether the job is rolling back or not. +func (job *Job) IsRollingback() bool { + return job.State == JobStateRollingback +} + +// IsCancelling returns whether the job is cancelling or not. +func (job *Job) IsCancelling() bool { + return job.State == JobStateCancelling +} + +// IsSynced returns whether the DDL modification is synced among all TiDB servers. +func (job *Job) IsSynced() bool { + return job.State == JobStateSynced +} + +// IsDone returns whether job is done. +func (job *Job) IsDone() bool { + return job.State == JobStateDone +} + +// IsRunning returns whether job is still running or not. +func (job *Job) IsRunning() bool { + return job.State == JobStateRunning +} + +// JobState is for job state. +type JobState byte + +// List job states. +const ( + JobStateNone JobState = 0 + JobStateRunning JobState = 1 + // When DDL encountered an unrecoverable error at reorganization state, + // some keys has been added already, we need to remove them. + // JobStateRollingback is the state to do the rolling back job. + JobStateRollingback JobState = 2 + JobStateRollbackDone JobState = 3 + JobStateDone JobState = 4 + JobStateCancelled JobState = 5 + // JobStateSynced is used to mark the information about the completion of this job + // has been synchronized to all servers. + JobStateSynced JobState = 6 + // JobStateCancelling is used to mark the DDL job is cancelled by the client, but the DDL work hasn't handle it. + JobStateCancelling JobState = 7 +) + +// String implements fmt.Stringer interface. +func (s JobState) String() string { + switch s { + case JobStateRunning: + return "running" + case JobStateRollingback: + return "rollingback" + case JobStateRollbackDone: + return "rollback done" + case JobStateDone: + return "done" + case JobStateCancelled: + return "cancelled" + case JobStateCancelling: + return "cancelling" + case JobStateSynced: + return "synced" + default: + return "none" + } +} + +// SchemaDiff contains the schema modification at a particular schema version. +// It is used to reduce schema reload cost. +type SchemaDiff struct { + Version int64 `json:"version"` + Type ActionType `json:"type"` + SchemaID int64 `json:"schema_id"` + TableID int64 `json:"table_id"` + + // OldTableID is the table ID before truncate, only used by truncate table DDL. + OldTableID int64 `json:"old_table_id"` + // OldSchemaID is the schema ID before rename table, only used by rename table DDL. + OldSchemaID int64 `json:"old_schema_id"` +} diff --git a/vendor/github.com/pingcap/parser/model/flags.go b/vendor/github.com/pingcap/parser/model/flags.go new file mode 100644 index 0000000000000000000000000000000000000000..33b040edfe42c0e859ac19d941285c52fe52f31f --- /dev/null +++ b/vendor/github.com/pingcap/parser/model/flags.go @@ -0,0 +1,43 @@ +// Copyright 2018 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +// Flags are used by tipb.SelectRequest.Flags to handle execution mode, like how to handle truncate error. +const ( + // FlagIgnoreTruncate indicates if truncate error should be ignored. + // Read-only statements should ignore truncate error, write statements should not ignore truncate error. + FlagIgnoreTruncate uint64 = 1 + // FlagTruncateAsWarning indicates if truncate error should be returned as warning. + // This flag only matters if FlagIgnoreTruncate is not set, in strict sql mode, truncate error should + // be returned as error, in non-strict sql mode, truncate error should be saved as warning. + FlagTruncateAsWarning = 1 << 1 + // FlagPadCharToFullLength indicates if sql_mode 'PAD_CHAR_TO_FULL_LENGTH' is set. + FlagPadCharToFullLength = 1 << 2 + // FlagInInsertStmt indicates if this is a INSERT statement. + FlagInInsertStmt = 1 << 3 + // FlagInUpdateOrDeleteStmt indicates if this is a UPDATE statement or a DELETE statement. + FlagInUpdateOrDeleteStmt = 1 << 4 + // FlagInSelectStmt indicates if this is a SELECT statement. + FlagInSelectStmt = 1 << 5 + // FlagOverflowAsWarning indicates if overflow error should be returned as warning. + // In strict sql mode, overflow error should be returned as error, + // in non-strict sql mode, overflow error should be saved as warning. + FlagOverflowAsWarning = 1 << 6 + // FlagIgnoreZeroInDate indicates if ZeroInDate error should be ignored. + // Read-only statements should ignore ZeroInDate error. + // Write statements should not ignore ZeroInDate error in strict sql mode. + FlagIgnoreZeroInDate = 1 << 7 + // FlagDividedByZeroAsWarning indicates if DividedByZero should be returned as warning. + FlagDividedByZeroAsWarning = 1 << 8 +) diff --git a/vendor/github.com/pingcap/parser/model/model.go b/vendor/github.com/pingcap/parser/model/model.go new file mode 100644 index 0000000000000000000000000000000000000000..01bb261b685bf725335fb7ce61ad77803bab6096 --- /dev/null +++ b/vendor/github.com/pingcap/parser/model/model.go @@ -0,0 +1,582 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "strings" + "time" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/types" + "github.com/pingcap/tipb/go-tipb" +) + +// SchemaState is the state for schema elements. +type SchemaState byte + +const ( + // StateNone means this schema element is absent and can't be used. + StateNone SchemaState = iota + // StateDeleteOnly means we can only delete items for this schema element. + StateDeleteOnly + // StateWriteOnly means we can use any write operation on this schema element, + // but outer can't read the changed data. + StateWriteOnly + // StateWriteReorganization means we are re-organizing whole data after write only state. + StateWriteReorganization + // StateDeleteReorganization means we are re-organizing whole data after delete only state. + StateDeleteReorganization + // StatePublic means this schema element is ok for all write and read operations. + StatePublic +) + +// String implements fmt.Stringer interface. +func (s SchemaState) String() string { + switch s { + case StateDeleteOnly: + return "delete only" + case StateWriteOnly: + return "write only" + case StateWriteReorganization: + return "write reorganization" + case StateDeleteReorganization: + return "delete reorganization" + case StatePublic: + return "public" + default: + return "none" + } +} + +// ColumnInfo provides meta data describing of a table column. +type ColumnInfo struct { + ID int64 `json:"id"` + Name CIStr `json:"name"` + Offset int `json:"offset"` + OriginDefaultValue interface{} `json:"origin_default"` + DefaultValue interface{} `json:"default"` + DefaultValueBit []byte `json:"default_bit"` + GeneratedExprString string `json:"generated_expr_string"` + GeneratedStored bool `json:"generated_stored"` + Dependences map[string]struct{} `json:"dependences"` + types.FieldType `json:"type"` + State SchemaState `json:"state"` + Comment string `json:"comment"` +} + +// Clone clones ColumnInfo. +func (c *ColumnInfo) Clone() *ColumnInfo { + nc := *c + return &nc +} + +// IsGenerated returns true if the column is generated column. +func (c *ColumnInfo) IsGenerated() bool { + return len(c.GeneratedExprString) != 0 +} + +// SetDefaultValue sets the default value. +func (c *ColumnInfo) SetDefaultValue(value interface{}) error { + c.DefaultValue = value + if c.Tp == mysql.TypeBit { + // For mysql.TypeBit type, the default value storage format must be a string. + // Other value such as int must convert to string format first. + // The mysql.TypeBit type supports the null default value. + if value == nil { + return nil + } + if v, ok := value.(string); ok { + c.DefaultValueBit = []byte(v) + return nil + } + return types.ErrInvalidDefault.GenWithStackByArgs(c.Name) + } + return nil +} + +// GetDefaultValue gets the default value of the column. +// Default value use to stored in DefaultValue field, but now, +// bit type default value will store in DefaultValueBit for fix bit default value decode/encode bug. +func (c *ColumnInfo) GetDefaultValue() interface{} { + if c.Tp == mysql.TypeBit && c.DefaultValueBit != nil { + return string(c.DefaultValueBit) + } + return c.DefaultValue +} + +// FindColumnInfo finds ColumnInfo in cols by name. +func FindColumnInfo(cols []*ColumnInfo, name string) *ColumnInfo { + name = strings.ToLower(name) + for _, col := range cols { + if col.Name.L == name { + return col + } + } + + return nil +} + +// ExtraHandleID is the column ID of column which we need to append to schema to occupy the handle's position +// for use of execution phase. +const ExtraHandleID = -1 + +// ExtraHandleName is the name of ExtraHandle Column. +var ExtraHandleName = NewCIStr("_tidb_rowid") + +// TableInfo provides meta data describing a DB table. +type TableInfo struct { + ID int64 `json:"id"` + Name CIStr `json:"name"` + Charset string `json:"charset"` + Collate string `json:"collate"` + // Columns are listed in the order in which they appear in the schema. + Columns []*ColumnInfo `json:"cols"` + Indices []*IndexInfo `json:"index_info"` + ForeignKeys []*FKInfo `json:"fk_info"` + State SchemaState `json:"state"` + PKIsHandle bool `json:"pk_is_handle"` + Comment string `json:"comment"` + AutoIncID int64 `json:"auto_inc_id"` + MaxColumnID int64 `json:"max_col_id"` + MaxIndexID int64 `json:"max_idx_id"` + // UpdateTS is used to record the timestamp of updating the table's schema information. + // These changing schema operations don't include 'truncate table' and 'rename table'. + UpdateTS uint64 `json:"update_timestamp"` + // OldSchemaID : + // Because auto increment ID has schemaID as prefix, + // We need to save original schemaID to keep autoID unchanged + // while renaming a table from one database to another. + // TODO: Remove it. + // Now it only uses for compatibility with the old version that already uses this field. + OldSchemaID int64 `json:"old_schema_id,omitempty"` + + // ShardRowIDBits specify if the implicit row ID is sharded. + ShardRowIDBits uint64 + + Partition *PartitionInfo `json:"partition"` + + Compression string `json:"compression"` +} + +// GetPartitionInfo returns the partition information. +func (t *TableInfo) GetPartitionInfo() *PartitionInfo { + if t.Partition != nil && t.Partition.Enable { + return t.Partition + } + return nil +} + +// GetUpdateTime gets the table's updating time. +func (t *TableInfo) GetUpdateTime() time.Time { + return TSConvert2Time(t.UpdateTS) +} + +// GetDBID returns the schema ID that is used to create an allocator. +// TODO: Remove it after removing OldSchemaID. +func (t *TableInfo) GetDBID(dbID int64) int64 { + if t.OldSchemaID != 0 { + return t.OldSchemaID + } + return dbID +} + +// Clone clones TableInfo. +func (t *TableInfo) Clone() *TableInfo { + nt := *t + nt.Columns = make([]*ColumnInfo, len(t.Columns)) + nt.Indices = make([]*IndexInfo, len(t.Indices)) + nt.ForeignKeys = make([]*FKInfo, len(t.ForeignKeys)) + + for i := range t.Columns { + nt.Columns[i] = t.Columns[i].Clone() + } + + for i := range t.Indices { + nt.Indices[i] = t.Indices[i].Clone() + } + + for i := range t.ForeignKeys { + nt.ForeignKeys[i] = t.ForeignKeys[i].Clone() + } + + return &nt +} + +// GetPkName will return the pk name if pk exists. +func (t *TableInfo) GetPkName() CIStr { + if t.PKIsHandle { + for _, colInfo := range t.Columns { + if mysql.HasPriKeyFlag(colInfo.Flag) { + return colInfo.Name + } + } + } + return CIStr{} +} + +// GetPkColInfo gets the ColumnInfo of pk if exists. +// Make sure PkIsHandle checked before call this method. +func (t *TableInfo) GetPkColInfo() *ColumnInfo { + for _, colInfo := range t.Columns { + if mysql.HasPriKeyFlag(colInfo.Flag) { + return colInfo + } + } + return nil +} + +func (t *TableInfo) GetAutoIncrementColInfo() *ColumnInfo { + for _, colInfo := range t.Columns { + if mysql.HasAutoIncrementFlag(colInfo.Flag) { + return colInfo + } + } + return nil +} + +// Cols returns the columns of the table in public state. +func (t *TableInfo) Cols() []*ColumnInfo { + publicColumns := make([]*ColumnInfo, len(t.Columns)) + maxOffset := -1 + for _, col := range t.Columns { + if col.State != StatePublic { + continue + } + publicColumns[col.Offset] = col + if maxOffset < col.Offset { + maxOffset = col.Offset + } + } + return publicColumns[0 : maxOffset+1] +} + +// NewExtraHandleColInfo mocks a column info for extra handle column. +func NewExtraHandleColInfo() *ColumnInfo { + colInfo := &ColumnInfo{ + ID: ExtraHandleID, + Name: ExtraHandleName, + } + colInfo.Flag = mysql.PriKeyFlag + colInfo.Tp = mysql.TypeLonglong + colInfo.Flen, colInfo.Decimal = mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeLonglong) + return colInfo +} + +// ColumnIsInIndex checks whether c is included in any indices of t. +func (t *TableInfo) ColumnIsInIndex(c *ColumnInfo) bool { + for _, index := range t.Indices { + for _, column := range index.Columns { + if column.Name.L == c.Name.L { + return true + } + } + } + return false +} + +// PartitionType is the type for PartitionInfo +type PartitionType int + +// Partition types. +const ( + PartitionTypeRange PartitionType = 1 + PartitionTypeHash PartitionType = 2 + PartitionTypeList PartitionType = 3 +) + +func (p PartitionType) String() string { + switch p { + case PartitionTypeRange: + return "RANGE" + case PartitionTypeHash: + return "HASH" + case PartitionTypeList: + return "LIST" + default: + return "" + } + +} + +// PartitionInfo provides table partition info. +type PartitionInfo struct { + Type PartitionType `json:"type"` + Expr string `json:"expr"` + Columns []CIStr `json:"columns"` + + // User may already creates table with partition but table partition is not + // yet supported back then. When Enable is true, write/read need use tid + // rather than pid. + Enable bool `json:"enable"` + + Definitions []PartitionDefinition `json:"definitions"` + Num uint64 `json:"num"` +} + +// GetNameByID gets the partition name by ID. +func (pi *PartitionInfo) GetNameByID(id int64) string { + for _, def := range pi.Definitions { + if id == def.ID { + return def.Name.L + } + } + return "" +} + +// PartitionDefinition defines a single partition. +type PartitionDefinition struct { + ID int64 `json:"id"` + Name CIStr `json:"name"` + LessThan []string `json:"less_than"` + Comment string `json:"comment,omitempty"` +} + +// IndexColumn provides index column info. +type IndexColumn struct { + Name CIStr `json:"name"` // Index name + Offset int `json:"offset"` // Index offset + // Length of prefix when using column prefix + // for indexing; + // UnspecifedLength if not using prefix indexing + Length int `json:"length"` +} + +// Clone clones IndexColumn. +func (i *IndexColumn) Clone() *IndexColumn { + ni := *i + return &ni +} + +// IndexType is the type of index +type IndexType int + +// String implements Stringer interface. +func (t IndexType) String() string { + switch t { + case IndexTypeBtree: + return "BTREE" + case IndexTypeHash: + return "HASH" + default: + return "" + } +} + +// IndexTypes +const ( + IndexTypeInvalid IndexType = iota + IndexTypeBtree + IndexTypeHash +) + +// IndexInfo provides meta data describing a DB index. +// It corresponds to the statement `CREATE INDEX Name ON Table (Column);` +// See https://dev.mysql.com/doc/refman/5.7/en/create-index.html +type IndexInfo struct { + ID int64 `json:"id"` + Name CIStr `json:"idx_name"` // Index name. + Table CIStr `json:"tbl_name"` // Table name. + Columns []*IndexColumn `json:"idx_cols"` // Index columns. + Unique bool `json:"is_unique"` // Whether the index is unique. + Primary bool `json:"is_primary"` // Whether the index is primary key. + State SchemaState `json:"state"` + Comment string `json:"comment"` // Comment + Tp IndexType `json:"index_type"` // Index type: Btree or Hash +} + +// Clone clones IndexInfo. +func (index *IndexInfo) Clone() *IndexInfo { + ni := *index + ni.Columns = make([]*IndexColumn, len(index.Columns)) + for i := range index.Columns { + ni.Columns[i] = index.Columns[i].Clone() + } + return &ni +} + +// HasPrefixIndex returns whether any columns of this index uses prefix length. +func (index *IndexInfo) HasPrefixIndex() bool { + for _, ic := range index.Columns { + if ic.Length != types.UnspecifiedLength { + return true + } + } + return false +} + +// FKInfo provides meta data describing a foreign key constraint. +type FKInfo struct { + ID int64 `json:"id"` + Name CIStr `json:"fk_name"` + RefTable CIStr `json:"ref_table"` + RefCols []CIStr `json:"ref_cols"` + Cols []CIStr `json:"cols"` + OnDelete int `json:"on_delete"` + OnUpdate int `json:"on_update"` + State SchemaState `json:"state"` +} + +// Clone clones FKInfo. +func (fk *FKInfo) Clone() *FKInfo { + nfk := *fk + + nfk.RefCols = make([]CIStr, len(fk.RefCols)) + nfk.Cols = make([]CIStr, len(fk.Cols)) + copy(nfk.RefCols, fk.RefCols) + copy(nfk.Cols, fk.Cols) + + return &nfk +} + +// DBInfo provides meta data describing a DB. +type DBInfo struct { + ID int64 `json:"id"` // Database ID + Name CIStr `json:"db_name"` // DB name. + Charset string `json:"charset"` + Collate string `json:"collate"` + Tables []*TableInfo `json:"-"` // Tables in the DB. + State SchemaState `json:"state"` +} + +// Clone clones DBInfo. +func (db *DBInfo) Clone() *DBInfo { + newInfo := *db + newInfo.Tables = make([]*TableInfo, len(db.Tables)) + for i := range db.Tables { + newInfo.Tables[i] = db.Tables[i].Clone() + } + return &newInfo +} + +// Copy shallow copies DBInfo. +func (db *DBInfo) Copy() *DBInfo { + newInfo := *db + newInfo.Tables = make([]*TableInfo, len(db.Tables)) + copy(newInfo.Tables, db.Tables) + return &newInfo +} + +// CIStr is case insensitive string. +type CIStr struct { + O string `json:"O"` // Original string. + L string `json:"L"` // Lower case string. +} + +// String implements fmt.Stringer interface. +func (cis CIStr) String() string { + return cis.O +} + +// NewCIStr creates a new CIStr. +func NewCIStr(s string) (cs CIStr) { + cs.O = s + cs.L = strings.ToLower(s) + return +} + +// UnmarshalJSON implements the user defined unmarshal method. +// CIStr can be unmarshaled from a single string, so PartitionDefinition.Name +// in this change https://github.com/pingcap/tidb/pull/6460/files would be +// compatible during TiDB upgrading. +func (cis *CIStr) UnmarshalJSON(b []byte) error { + type T CIStr + if err := json.Unmarshal(b, (*T)(cis)); err == nil { + return nil + } + + // Unmarshal CIStr from a single string. + err := json.Unmarshal(b, &cis.O) + if err != nil { + return errors.Trace(err) + } + cis.L = strings.ToLower(cis.O) + return nil +} + +// ColumnsToProto converts a slice of model.ColumnInfo to a slice of tipb.ColumnInfo. +func ColumnsToProto(columns []*ColumnInfo, pkIsHandle bool) []*tipb.ColumnInfo { + cols := make([]*tipb.ColumnInfo, 0, len(columns)) + for _, c := range columns { + col := ColumnToProto(c) + // TODO: Here `PkHandle`'s meaning is changed, we will change it to `IsHandle` when tikv's old select logic + // is abandoned. + if (pkIsHandle && mysql.HasPriKeyFlag(c.Flag)) || c.ID == ExtraHandleID { + col.PkHandle = true + } else { + col.PkHandle = false + } + cols = append(cols, col) + } + return cols +} + +// IndexToProto converts a model.IndexInfo to a tipb.IndexInfo. +func IndexToProto(t *TableInfo, idx *IndexInfo) *tipb.IndexInfo { + pi := &tipb.IndexInfo{ + TableId: t.ID, + IndexId: idx.ID, + Unique: idx.Unique, + } + cols := make([]*tipb.ColumnInfo, 0, len(idx.Columns)+1) + for _, c := range idx.Columns { + cols = append(cols, ColumnToProto(t.Columns[c.Offset])) + } + if t.PKIsHandle { + // Coprocessor needs to know PKHandle column info, so we need to append it. + for _, col := range t.Columns { + if mysql.HasPriKeyFlag(col.Flag) { + colPB := ColumnToProto(col) + colPB.PkHandle = true + cols = append(cols, colPB) + break + } + } + } + pi.Columns = cols + return pi +} + +// ColumnToProto converts model.ColumnInfo to tipb.ColumnInfo. +func ColumnToProto(c *ColumnInfo) *tipb.ColumnInfo { + pc := &tipb.ColumnInfo{ + ColumnId: c.ID, + Collation: collationToProto(c.FieldType.Collate), + ColumnLen: int32(c.FieldType.Flen), + Decimal: int32(c.FieldType.Decimal), + Flag: int32(c.Flag), + Elems: c.Elems, + } + pc.Tp = int32(c.FieldType.Tp) + return pc +} + +// TODO: update it when more collate is supported. +func collationToProto(c string) int32 { + v := mysql.CollationNames[c] + if v == mysql.BinaryCollationID { + return int32(mysql.BinaryCollationID) + } + // We only support binary and utf8_bin collation. + // Setting other collations to utf8_bin for old data compatibility. + // For the data created when we didn't enforce utf8_bin collation in create table. + return int32(mysql.DefaultCollationID) +} + +// TableColumnID is composed by table ID and column ID. +type TableColumnID struct { + TableID int64 + ColumnID int64 +} diff --git a/vendor/github.com/pingcap/parser/mysql/charset.go b/vendor/github.com/pingcap/parser/mysql/charset.go new file mode 100644 index 0000000000000000000000000000000000000000..f2e99a43765ef53442eed4775a643b4ee2106567 --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/charset.go @@ -0,0 +1,610 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +import "unicode" + +// CharsetIDs maps charset name to its default collation ID. +var CharsetIDs = map[string]uint8{ + "big5": 1, + "dec8": 3, + "cp850": 4, + "hp8": 6, + "koi8r": 7, + "latin1": 8, + "latin2": 9, + "swe7": 10, + "ascii": 11, + "ujis": 12, + "sjis": 13, + "hebrew": 16, + "tis620": 18, + "euckr": 19, + "koi8u": 22, + "gb2312": 24, + "greek": 25, + "cp1250": 26, + "gbk": 28, + "latin5": 30, + "armscii8": 32, + "utf8": 33, + "ucs2": 35, + "cp866": 36, + "keybcs2": 37, + "macce": 38, + "macroman": 39, + "cp852": 40, + "latin7": 41, + "utf8mb4": 45, + "cp1251": 51, + "utf16": 54, + "utf16le": 56, + "cp1256": 57, + "cp1257": 59, + "utf32": 60, + "binary": 63, + "geostd8": 92, + "cp932": 95, + "eucjpms": 97, +} + +// Charsets maps charset name to its default collation name. +var Charsets = map[string]string{ + "big5": "big5_chinese_ci", + "dec8": "dec8_swedish_ci", + "cp850": "cp850_general_ci", + "hp8": "hp8_english_ci", + "koi8r": "koi8r_general_ci", + "latin1": "latin1_swedish_ci", + "latin2": "latin2_general_ci", + "swe7": "swe7_swedish_ci", + "ascii": "ascii_general_ci", + "ujis": "ujis_japanese_ci", + "sjis": "sjis_japanese_ci", + "hebrew": "hebrew_general_ci", + "tis620": "tis620_thai_ci", + "euckr": "euckr_korean_ci", + "koi8u": "koi8u_general_ci", + "gb2312": "gb2312_chinese_ci", + "greek": "greek_general_ci", + "cp1250": "cp1250_general_ci", + "gbk": "gbk_chinese_ci", + "latin5": "latin5_turkish_ci", + "armscii8": "armscii8_general_ci", + "utf8": "utf8_general_ci", + "ucs2": "ucs2_general_ci", + "cp866": "cp866_general_ci", + "keybcs2": "keybcs2_general_ci", + "macce": "macce_general_ci", + "macroman": "macroman_general_ci", + "cp852": "cp852_general_ci", + "latin7": "latin7_general_ci", + "utf8mb4": "utf8mb4_general_ci", + "cp1251": "cp1251_general_ci", + "utf16": "utf16_general_ci", + "utf16le": "utf16le_general_ci", + "cp1256": "cp1256_general_ci", + "cp1257": "cp1257_general_ci", + "utf32": "utf32_general_ci", + "binary": "binary", + "geostd8": "geostd8_general_ci", + "cp932": "cp932_japanese_ci", + "eucjpms": "eucjpms_japanese_ci", +} + +// Collations maps MySQL default collation ID to its name. +var Collations = map[uint8]string{ + 1: "big5_chinese_ci", + 2: "latin2_czech_cs", + 3: "dec8_swedish_ci", + 4: "cp850_general_ci", + 5: "latin1_german1_ci", + 6: "hp8_english_ci", + 7: "koi8r_general_ci", + 8: "latin1_swedish_ci", + 9: "latin2_general_ci", + 10: "swe7_swedish_ci", + 11: "ascii_general_ci", + 12: "ujis_japanese_ci", + 13: "sjis_japanese_ci", + 14: "cp1251_bulgarian_ci", + 15: "latin1_danish_ci", + 16: "hebrew_general_ci", + 18: "tis620_thai_ci", + 19: "euckr_korean_ci", + 20: "latin7_estonian_cs", + 21: "latin2_hungarian_ci", + 22: "koi8u_general_ci", + 23: "cp1251_ukrainian_ci", + 24: "gb2312_chinese_ci", + 25: "greek_general_ci", + 26: "cp1250_general_ci", + 27: "latin2_croatian_ci", + 28: "gbk_chinese_ci", + 29: "cp1257_lithuanian_ci", + 30: "latin5_turkish_ci", + 31: "latin1_german2_ci", + 32: "armscii8_general_ci", + 33: "utf8_general_ci", + 34: "cp1250_czech_cs", + 35: "ucs2_general_ci", + 36: "cp866_general_ci", + 37: "keybcs2_general_ci", + 38: "macce_general_ci", + 39: "macroman_general_ci", + 40: "cp852_general_ci", + 41: "latin7_general_ci", + 42: "latin7_general_cs", + 43: "macce_bin", + 44: "cp1250_croatian_ci", + 45: "utf8mb4_general_ci", + 46: "utf8mb4_bin", + 47: "latin1_bin", + 48: "latin1_general_ci", + 49: "latin1_general_cs", + 50: "cp1251_bin", + 51: "cp1251_general_ci", + 52: "cp1251_general_cs", + 53: "macroman_bin", + 54: "utf16_general_ci", + 55: "utf16_bin", + 56: "utf16le_general_ci", + 57: "cp1256_general_ci", + 58: "cp1257_bin", + 59: "cp1257_general_ci", + 60: "utf32_general_ci", + 61: "utf32_bin", + 62: "utf16le_bin", + 63: "binary", + 64: "armscii8_bin", + 65: "ascii_bin", + 66: "cp1250_bin", + 67: "cp1256_bin", + 68: "cp866_bin", + 69: "dec8_bin", + 70: "greek_bin", + 71: "hebrew_bin", + 72: "hp8_bin", + 73: "keybcs2_bin", + 74: "koi8r_bin", + 75: "koi8u_bin", + 77: "latin2_bin", + 78: "latin5_bin", + 79: "latin7_bin", + 80: "cp850_bin", + 81: "cp852_bin", + 82: "swe7_bin", + 83: "utf8_bin", + 84: "big5_bin", + 85: "euckr_bin", + 86: "gb2312_bin", + 87: "gbk_bin", + 88: "sjis_bin", + 89: "tis620_bin", + 90: "ucs2_bin", + 91: "ujis_bin", + 92: "geostd8_general_ci", + 93: "geostd8_bin", + 94: "latin1_spanish_ci", + 95: "cp932_japanese_ci", + 96: "cp932_bin", + 97: "eucjpms_japanese_ci", + 98: "eucjpms_bin", + 99: "cp1250_polish_ci", + 101: "utf16_unicode_ci", + 102: "utf16_icelandic_ci", + 103: "utf16_latvian_ci", + 104: "utf16_romanian_ci", + 105: "utf16_slovenian_ci", + 106: "utf16_polish_ci", + 107: "utf16_estonian_ci", + 108: "utf16_spanish_ci", + 109: "utf16_swedish_ci", + 110: "utf16_turkish_ci", + 111: "utf16_czech_ci", + 112: "utf16_danish_ci", + 113: "utf16_lithuanian_ci", + 114: "utf16_slovak_ci", + 115: "utf16_spanish2_ci", + 116: "utf16_roman_ci", + 117: "utf16_persian_ci", + 118: "utf16_esperanto_ci", + 119: "utf16_hungarian_ci", + 120: "utf16_sinhala_ci", + 121: "utf16_german2_ci", + 122: "utf16_croatian_ci", + 123: "utf16_unicode_520_ci", + 124: "utf16_vietnamese_ci", + 128: "ucs2_unicode_ci", + 129: "ucs2_icelandic_ci", + 130: "ucs2_latvian_ci", + 131: "ucs2_romanian_ci", + 132: "ucs2_slovenian_ci", + 133: "ucs2_polish_ci", + 134: "ucs2_estonian_ci", + 135: "ucs2_spanish_ci", + 136: "ucs2_swedish_ci", + 137: "ucs2_turkish_ci", + 138: "ucs2_czech_ci", + 139: "ucs2_danish_ci", + 140: "ucs2_lithuanian_ci", + 141: "ucs2_slovak_ci", + 142: "ucs2_spanish2_ci", + 143: "ucs2_roman_ci", + 144: "ucs2_persian_ci", + 145: "ucs2_esperanto_ci", + 146: "ucs2_hungarian_ci", + 147: "ucs2_sinhala_ci", + 148: "ucs2_german2_ci", + 149: "ucs2_croatian_ci", + 150: "ucs2_unicode_520_ci", + 151: "ucs2_vietnamese_ci", + 159: "ucs2_general_mysql500_ci", + 160: "utf32_unicode_ci", + 161: "utf32_icelandic_ci", + 162: "utf32_latvian_ci", + 163: "utf32_romanian_ci", + 164: "utf32_slovenian_ci", + 165: "utf32_polish_ci", + 166: "utf32_estonian_ci", + 167: "utf32_spanish_ci", + 168: "utf32_swedish_ci", + 169: "utf32_turkish_ci", + 170: "utf32_czech_ci", + 171: "utf32_danish_ci", + 172: "utf32_lithuanian_ci", + 173: "utf32_slovak_ci", + 174: "utf32_spanish2_ci", + 175: "utf32_roman_ci", + 176: "utf32_persian_ci", + 177: "utf32_esperanto_ci", + 178: "utf32_hungarian_ci", + 179: "utf32_sinhala_ci", + 180: "utf32_german2_ci", + 181: "utf32_croatian_ci", + 182: "utf32_unicode_520_ci", + 183: "utf32_vietnamese_ci", + 192: "utf8_unicode_ci", + 193: "utf8_icelandic_ci", + 194: "utf8_latvian_ci", + 195: "utf8_romanian_ci", + 196: "utf8_slovenian_ci", + 197: "utf8_polish_ci", + 198: "utf8_estonian_ci", + 199: "utf8_spanish_ci", + 200: "utf8_swedish_ci", + 201: "utf8_turkish_ci", + 202: "utf8_czech_ci", + 203: "utf8_danish_ci", + 204: "utf8_lithuanian_ci", + 205: "utf8_slovak_ci", + 206: "utf8_spanish2_ci", + 207: "utf8_roman_ci", + 208: "utf8_persian_ci", + 209: "utf8_esperanto_ci", + 210: "utf8_hungarian_ci", + 211: "utf8_sinhala_ci", + 212: "utf8_german2_ci", + 213: "utf8_croatian_ci", + 214: "utf8_unicode_520_ci", + 215: "utf8_vietnamese_ci", + 223: "utf8_general_mysql500_ci", + 224: "utf8mb4_unicode_ci", + 225: "utf8mb4_icelandic_ci", + 226: "utf8mb4_latvian_ci", + 227: "utf8mb4_romanian_ci", + 228: "utf8mb4_slovenian_ci", + 229: "utf8mb4_polish_ci", + 230: "utf8mb4_estonian_ci", + 231: "utf8mb4_spanish_ci", + 232: "utf8mb4_swedish_ci", + 233: "utf8mb4_turkish_ci", + 234: "utf8mb4_czech_ci", + 235: "utf8mb4_danish_ci", + 236: "utf8mb4_lithuanian_ci", + 237: "utf8mb4_slovak_ci", + 238: "utf8mb4_spanish2_ci", + 239: "utf8mb4_roman_ci", + 240: "utf8mb4_persian_ci", + 241: "utf8mb4_esperanto_ci", + 242: "utf8mb4_hungarian_ci", + 243: "utf8mb4_sinhala_ci", + 244: "utf8mb4_german2_ci", + 245: "utf8mb4_croatian_ci", + 246: "utf8mb4_unicode_520_ci", + 247: "utf8mb4_vietnamese_ci", +} + +// CollationNames maps MySQL default collation name to its ID +var CollationNames = map[string]uint8{ + "big5_chinese_ci": 1, + "latin2_czech_cs": 2, + "dec8_swedish_ci": 3, + "cp850_general_ci": 4, + "latin1_german1_ci": 5, + "hp8_english_ci": 6, + "koi8r_general_ci": 7, + "latin1_swedish_ci": 8, + "latin2_general_ci": 9, + "swe7_swedish_ci": 10, + "ascii_general_ci": 11, + "ujis_japanese_ci": 12, + "sjis_japanese_ci": 13, + "cp1251_bulgarian_ci": 14, + "latin1_danish_ci": 15, + "hebrew_general_ci": 16, + "tis620_thai_ci": 18, + "euckr_korean_ci": 19, + "latin7_estonian_cs": 20, + "latin2_hungarian_ci": 21, + "koi8u_general_ci": 22, + "cp1251_ukrainian_ci": 23, + "gb2312_chinese_ci": 24, + "greek_general_ci": 25, + "cp1250_general_ci": 26, + "latin2_croatian_ci": 27, + "gbk_chinese_ci": 28, + "cp1257_lithuanian_ci": 29, + "latin5_turkish_ci": 30, + "latin1_german2_ci": 31, + "armscii8_general_ci": 32, + "utf8_general_ci": 33, + "cp1250_czech_cs": 34, + "ucs2_general_ci": 35, + "cp866_general_ci": 36, + "keybcs2_general_ci": 37, + "macce_general_ci": 38, + "macroman_general_ci": 39, + "cp852_general_ci": 40, + "latin7_general_ci": 41, + "latin7_general_cs": 42, + "macce_bin": 43, + "cp1250_croatian_ci": 44, + "utf8mb4_general_ci": 45, + "utf8mb4_bin": 46, + "latin1_bin": 47, + "latin1_general_ci": 48, + "latin1_general_cs": 49, + "cp1251_bin": 50, + "cp1251_general_ci": 51, + "cp1251_general_cs": 52, + "macroman_bin": 53, + "utf16_general_ci": 54, + "utf16_bin": 55, + "utf16le_general_ci": 56, + "cp1256_general_ci": 57, + "cp1257_bin": 58, + "cp1257_general_ci": 59, + "utf32_general_ci": 60, + "utf32_bin": 61, + "utf16le_bin": 62, + "binary": 63, + "armscii8_bin": 64, + "ascii_bin": 65, + "cp1250_bin": 66, + "cp1256_bin": 67, + "cp866_bin": 68, + "dec8_bin": 69, + "greek_bin": 70, + "hebrew_bin": 71, + "hp8_bin": 72, + "keybcs2_bin": 73, + "koi8r_bin": 74, + "koi8u_bin": 75, + "latin2_bin": 77, + "latin5_bin": 78, + "latin7_bin": 79, + "cp850_bin": 80, + "cp852_bin": 81, + "swe7_bin": 82, + "utf8_bin": 83, + "big5_bin": 84, + "euckr_bin": 85, + "gb2312_bin": 86, + "gbk_bin": 87, + "sjis_bin": 88, + "tis620_bin": 89, + "ucs2_bin": 90, + "ujis_bin": 91, + "geostd8_general_ci": 92, + "geostd8_bin": 93, + "latin1_spanish_ci": 94, + "cp932_japanese_ci": 95, + "cp932_bin": 96, + "eucjpms_japanese_ci": 97, + "eucjpms_bin": 98, + "cp1250_polish_ci": 99, + "utf16_unicode_ci": 101, + "utf16_icelandic_ci": 102, + "utf16_latvian_ci": 103, + "utf16_romanian_ci": 104, + "utf16_slovenian_ci": 105, + "utf16_polish_ci": 106, + "utf16_estonian_ci": 107, + "utf16_spanish_ci": 108, + "utf16_swedish_ci": 109, + "utf16_turkish_ci": 110, + "utf16_czech_ci": 111, + "utf16_danish_ci": 112, + "utf16_lithuanian_ci": 113, + "utf16_slovak_ci": 114, + "utf16_spanish2_ci": 115, + "utf16_roman_ci": 116, + "utf16_persian_ci": 117, + "utf16_esperanto_ci": 118, + "utf16_hungarian_ci": 119, + "utf16_sinhala_ci": 120, + "utf16_german2_ci": 121, + "utf16_croatian_ci": 122, + "utf16_unicode_520_ci": 123, + "utf16_vietnamese_ci": 124, + "ucs2_unicode_ci": 128, + "ucs2_icelandic_ci": 129, + "ucs2_latvian_ci": 130, + "ucs2_romanian_ci": 131, + "ucs2_slovenian_ci": 132, + "ucs2_polish_ci": 133, + "ucs2_estonian_ci": 134, + "ucs2_spanish_ci": 135, + "ucs2_swedish_ci": 136, + "ucs2_turkish_ci": 137, + "ucs2_czech_ci": 138, + "ucs2_danish_ci": 139, + "ucs2_lithuanian_ci": 140, + "ucs2_slovak_ci": 141, + "ucs2_spanish2_ci": 142, + "ucs2_roman_ci": 143, + "ucs2_persian_ci": 144, + "ucs2_esperanto_ci": 145, + "ucs2_hungarian_ci": 146, + "ucs2_sinhala_ci": 147, + "ucs2_german2_ci": 148, + "ucs2_croatian_ci": 149, + "ucs2_unicode_520_ci": 150, + "ucs2_vietnamese_ci": 151, + "ucs2_general_mysql500_ci": 159, + "utf32_unicode_ci": 160, + "utf32_icelandic_ci": 161, + "utf32_latvian_ci": 162, + "utf32_romanian_ci": 163, + "utf32_slovenian_ci": 164, + "utf32_polish_ci": 165, + "utf32_estonian_ci": 166, + "utf32_spanish_ci": 167, + "utf32_swedish_ci": 168, + "utf32_turkish_ci": 169, + "utf32_czech_ci": 170, + "utf32_danish_ci": 171, + "utf32_lithuanian_ci": 172, + "utf32_slovak_ci": 173, + "utf32_spanish2_ci": 174, + "utf32_roman_ci": 175, + "utf32_persian_ci": 176, + "utf32_esperanto_ci": 177, + "utf32_hungarian_ci": 178, + "utf32_sinhala_ci": 179, + "utf32_german2_ci": 180, + "utf32_croatian_ci": 181, + "utf32_unicode_520_ci": 182, + "utf32_vietnamese_ci": 183, + "utf8_unicode_ci": 192, + "utf8_icelandic_ci": 193, + "utf8_latvian_ci": 194, + "utf8_romanian_ci": 195, + "utf8_slovenian_ci": 196, + "utf8_polish_ci": 197, + "utf8_estonian_ci": 198, + "utf8_spanish_ci": 199, + "utf8_swedish_ci": 200, + "utf8_turkish_ci": 201, + "utf8_czech_ci": 202, + "utf8_danish_ci": 203, + "utf8_lithuanian_ci": 204, + "utf8_slovak_ci": 205, + "utf8_spanish2_ci": 206, + "utf8_roman_ci": 207, + "utf8_persian_ci": 208, + "utf8_esperanto_ci": 209, + "utf8_hungarian_ci": 210, + "utf8_sinhala_ci": 211, + "utf8_german2_ci": 212, + "utf8_croatian_ci": 213, + "utf8_unicode_520_ci": 214, + "utf8_vietnamese_ci": 215, + "utf8_general_mysql500_ci": 223, + "utf8mb4_unicode_ci": 224, + "utf8mb4_icelandic_ci": 225, + "utf8mb4_latvian_ci": 226, + "utf8mb4_romanian_ci": 227, + "utf8mb4_slovenian_ci": 228, + "utf8mb4_polish_ci": 229, + "utf8mb4_estonian_ci": 230, + "utf8mb4_spanish_ci": 231, + "utf8mb4_swedish_ci": 232, + "utf8mb4_turkish_ci": 233, + "utf8mb4_czech_ci": 234, + "utf8mb4_danish_ci": 235, + "utf8mb4_lithuanian_ci": 236, + "utf8mb4_slovak_ci": 237, + "utf8mb4_spanish2_ci": 238, + "utf8mb4_roman_ci": 239, + "utf8mb4_persian_ci": 240, + "utf8mb4_esperanto_ci": 241, + "utf8mb4_hungarian_ci": 242, + "utf8mb4_sinhala_ci": 243, + "utf8mb4_german2_ci": 244, + "utf8mb4_croatian_ci": 245, + "utf8mb4_unicode_520_ci": 246, + "utf8mb4_vietnamese_ci": 247, +} + +// MySQL collation information. +const ( + UTF8Charset = "utf8" + UTF8MB4Charset = "utf8mb4" + DefaultCharset = UTF8MB4Charset + // DefaultCollationID is utf8mb4_bin(46) + DefaultCollationID = 46 + BinaryCollationID = 63 + UTF8DefaultCollation = "utf8_bin" + UTF8MB4DefaultCollation = "utf8mb4_bin" + DefaultCollationName = UTF8MB4DefaultCollation + + // MaxBytesOfCharacter, is the max bytes length of a character, + // refer to RFC3629, in UTF-8, characters from the U+0000..U+10FFFF range + // (the UTF-16 accessible range) are encoded using sequences of 1 to 4 octets. + MaxBytesOfCharacter = 4 +) + +// IsUTF8Charset checks if charset is utf8 or utf8mb4 +func IsUTF8Charset(charset string) bool { + return charset == UTF8Charset || charset == UTF8MB4Charset +} + +// RangeGraph defines valid unicode characters to use in column names. It strictly follows MySQL's definition. +// See #3994. +var RangeGraph = []*unicode.RangeTable{ + // _MY_PNT + unicode.No, + unicode.Mn, + unicode.Me, + unicode.Pc, + unicode.Pd, + unicode.Pd, + unicode.Ps, + unicode.Pe, + unicode.Pi, + unicode.Pf, + unicode.Po, + unicode.Sm, + unicode.Sc, + unicode.Sk, + unicode.So, + // _MY_U + unicode.Lu, + unicode.Lt, + unicode.Nl, + // _MY_L + unicode.Ll, + unicode.Lm, + unicode.Lo, + unicode.Nl, + unicode.Mn, + unicode.Mc, + unicode.Me, + // _MY_NMR + unicode.Nd, + unicode.Nl, + unicode.No, +} diff --git a/vendor/github.com/pingcap/parser/mysql/const.go b/vendor/github.com/pingcap/parser/mysql/const.go new file mode 100644 index 0000000000000000000000000000000000000000..0c1876b6a2283190054d4485d6550a431f214337 --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/const.go @@ -0,0 +1,700 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +import ( + "fmt" + "strings" +) + +func newInvalidModeErr(s string) error { + return NewErr(ErrWrongValueForVar, "sql_mode", s) +} + +// Version information. +var ( + // TiDBReleaseVersion is initialized by (git describe --tags) in Makefile. + TiDBReleaseVersion = "None" + + // ServerVersion is the version information of this tidb-server in MySQL's format. + ServerVersion = fmt.Sprintf("5.7.10-TiDB-%s", TiDBReleaseVersion) +) + +// Header information. +const ( + OKHeader byte = 0x00 + ErrHeader byte = 0xff + EOFHeader byte = 0xfe + LocalInFileHeader byte = 0xfb +) + +// Server information. +const ( + ServerStatusInTrans uint16 = 0x0001 + ServerStatusAutocommit uint16 = 0x0002 + ServerMoreResultsExists uint16 = 0x0008 + ServerStatusNoGoodIndexUsed uint16 = 0x0010 + ServerStatusNoIndexUsed uint16 = 0x0020 + ServerStatusCursorExists uint16 = 0x0040 + ServerStatusLastRowSend uint16 = 0x0080 + ServerStatusDBDropped uint16 = 0x0100 + ServerStatusNoBackslashEscaped uint16 = 0x0200 + ServerStatusMetadataChanged uint16 = 0x0400 + ServerStatusWasSlow uint16 = 0x0800 + ServerPSOutParams uint16 = 0x1000 +) + +// HasCursorExistsFlag return true if cursor exists indicated by server status. +func HasCursorExistsFlag(serverStatus uint16) bool { + return serverStatus&ServerStatusCursorExists > 0 +} + +// Identifier length limitations. +// See https://dev.mysql.com/doc/refman/5.7/en/identifiers.html +const ( + // MaxPayloadLen is the max packet payload length. + MaxPayloadLen = 1<<24 - 1 + // MaxTableNameLength is max length of table name identifier. + MaxTableNameLength = 64 + // MaxDatabaseNameLength is max length of database name identifier. + MaxDatabaseNameLength = 64 + // MaxColumnNameLength is max length of column name identifier. + MaxColumnNameLength = 64 + // MaxKeyParts is max length of key parts. + MaxKeyParts = 16 + // MaxIndexIdentifierLen is max length of index identifier. + MaxIndexIdentifierLen = 64 + // MaxConstraintIdentifierLen is max length of constrain identifier. + MaxConstraintIdentifierLen = 64 + // MaxViewIdentifierLen is max length of view identifier. + MaxViewIdentifierLen = 64 + // MaxAliasIdentifierLen is max length of alias identifier. + MaxAliasIdentifierLen = 256 + // MaxUserDefinedVariableLen is max length of user-defined variable. + MaxUserDefinedVariableLen = 64 +) + +// ErrTextLength error text length limit. +const ErrTextLength = 80 + +// Command information. +const ( + ComSleep byte = iota + ComQuit + ComInitDB + ComQuery + ComFieldList + ComCreateDB + ComDropDB + ComRefresh + ComShutdown + ComStatistics + ComProcessInfo + ComConnect + ComProcessKill + ComDebug + ComPing + ComTime + ComDelayedInsert + ComChangeUser + ComBinlogDump + ComTableDump + ComConnectOut + ComRegisterSlave + ComStmtPrepare + ComStmtExecute + ComStmtSendLongData + ComStmtClose + ComStmtReset + ComSetOption + ComStmtFetch + ComDaemon + ComBinlogDumpGtid + ComResetConnection + ComEnd +) + +// Client information. +const ( + ClientLongPassword uint32 = 1 << iota + ClientFoundRows + ClientLongFlag + ClientConnectWithDB + ClientNoSchema + ClientCompress + ClientODBC + ClientLocalFiles + ClientIgnoreSpace + ClientProtocol41 + ClientInteractive + ClientSSL + ClientIgnoreSigpipe + ClientTransactions + ClientReserved + ClientSecureConnection + ClientMultiStatements + ClientMultiResults + ClientPSMultiResults + ClientPluginAuth + ClientConnectAtts + ClientPluginAuthLenencClientData +) + +// Cache type information. +const ( + TypeNoCache byte = 0xff +) + +// Auth name information. +const ( + AuthName = "mysql_native_password" +) + +// MySQL database and tables. +const ( + // SystemDB is the name of system database. + SystemDB = "mysql" + // UserTable is the table in system db contains user info. + UserTable = "User" + // DBTable is the table in system db contains db scope privilege info. + DBTable = "DB" + // TablePrivTable is the table in system db contains table scope privilege info. + TablePrivTable = "Tables_priv" + // ColumnPrivTable is the table in system db contains column scope privilege info. + ColumnPrivTable = "Columns_priv" + // GlobalVariablesTable is the table contains global system variables. + GlobalVariablesTable = "GLOBAL_VARIABLES" + // GlobalStatusTable is the table contains global status variables. + GlobalStatusTable = "GLOBAL_STATUS" + // TiDBTable is the table contains tidb info. + TiDBTable = "tidb" +) + +// PrivilegeType privilege +type PrivilegeType uint32 + +const ( + _ PrivilegeType = 1 << iota + // CreatePriv is the privilege to create schema/table. + CreatePriv + // SelectPriv is the privilege to read from table. + SelectPriv + // InsertPriv is the privilege to insert data into table. + InsertPriv + // UpdatePriv is the privilege to update data in table. + UpdatePriv + // DeletePriv is the privilege to delete data from table. + DeletePriv + // ShowDBPriv is the privilege to run show databases statement. + ShowDBPriv + // SuperPriv enables many operations and server behaviors. + SuperPriv + // CreateUserPriv is the privilege to create user. + CreateUserPriv + // TriggerPriv is not checked yet. + TriggerPriv + // DropPriv is the privilege to drop schema/table. + DropPriv + // ProcessPriv pertains to display of information about the threads executing within the server. + ProcessPriv + // GrantPriv is the privilege to grant privilege to user. + GrantPriv + // ReferencesPriv is not checked yet. + ReferencesPriv + // AlterPriv is the privilege to run alter statement. + AlterPriv + // ExecutePriv is the privilege to run execute statement. + ExecutePriv + // IndexPriv is the privilege to create/drop index. + IndexPriv + // AllPriv is the privilege for all actions. + AllPriv +) + +// AllPrivMask is the mask for PrivilegeType with all bits set to 1. +// If it's passed to RequestVerification, it means any privilege would be OK. +const AllPrivMask = AllPriv - 1 + +// MySQL type maximum length. +const ( + // For arguments that have no fixed number of decimals, the decimals value is set to 31, + // which is 1 more than the maximum number of decimals permitted for the DECIMAL, FLOAT, and DOUBLE data types. + NotFixedDec = 31 + + MaxIntWidth = 20 + MaxRealWidth = 23 + MaxFloatingTypeScale = 30 + MaxFloatingTypeWidth = 255 + MaxDecimalScale = 30 + MaxDecimalWidth = 65 + MaxDateWidth = 10 // YYYY-MM-DD. + MaxDatetimeWidthNoFsp = 19 // YYYY-MM-DD HH:MM:SS + MaxDatetimeWidthWithFsp = 26 // YYYY-MM-DD HH:MM:SS[.fraction] + MaxDatetimeFullWidth = 29 // YYYY-MM-DD HH:MM:SS.###### AM + MaxDurationWidthNoFsp = 10 // HH:MM:SS + MaxDurationWidthWithFsp = 15 // HH:MM:SS[.fraction] + MaxBlobWidth = 16777216 +) + +// MySQL max type field length. +const ( + MaxFieldCharLength = 255 + MaxFieldVarCharLength = 65535 +) + +// MaxTypeSetMembers is the number of set members. +const MaxTypeSetMembers = 64 + +// PWDHashLen is the length of password's hash. +const PWDHashLen = 40 + +// Priv2UserCol is the privilege to mysql.user table column name. +var Priv2UserCol = map[PrivilegeType]string{ + CreatePriv: "Create_priv", + SelectPriv: "Select_priv", + InsertPriv: "Insert_priv", + UpdatePriv: "Update_priv", + DeletePriv: "Delete_priv", + ShowDBPriv: "Show_db_priv", + SuperPriv: "Super_priv", + CreateUserPriv: "Create_user_priv", + TriggerPriv: "Trigger_priv", + DropPriv: "Drop_priv", + ProcessPriv: "Process_priv", + GrantPriv: "Grant_priv", + ReferencesPriv: "References_priv", + AlterPriv: "Alter_priv", + ExecutePriv: "Execute_priv", + IndexPriv: "Index_priv", +} + +// Command2Str is the command information to command name. +var Command2Str = map[byte]string{ + ComSleep: "Sleep", + ComQuit: "Quit", + ComInitDB: "Init DB", + ComQuery: "Query", + ComFieldList: "Field List", + ComCreateDB: "Create DB", + ComDropDB: "Drop DB", + ComRefresh: "Refresh", + ComShutdown: "Shutdown", + ComStatistics: "Statistics", + ComProcessInfo: "Processlist", + ComConnect: "Connect", + ComProcessKill: "Kill", + ComDebug: "Debug", + ComPing: "Ping", + ComTime: "Time", + ComDelayedInsert: "Delayed Insert", + ComChangeUser: "Change User", + ComBinlogDump: "Binlog Dump", + ComTableDump: "Table Dump", + ComConnectOut: "Connect out", + ComRegisterSlave: "Register Slave", + ComStmtPrepare: "Prepare", + ComStmtExecute: "Execute", + ComStmtSendLongData: "Long Data", + ComStmtClose: "Close stmt", + ComStmtReset: "Reset stmt", + ComSetOption: "Set option", + ComStmtFetch: "Fetch", + ComDaemon: "Daemon", + ComBinlogDumpGtid: "Binlog Dump", + ComResetConnection: "Reset connect", +} + +// Col2PrivType is the privilege tables column name to privilege type. +var Col2PrivType = map[string]PrivilegeType{ + "Create_priv": CreatePriv, + "Select_priv": SelectPriv, + "Insert_priv": InsertPriv, + "Update_priv": UpdatePriv, + "Delete_priv": DeletePriv, + "Show_db_priv": ShowDBPriv, + "Super_priv": SuperPriv, + "Create_user_priv": CreateUserPriv, + "Trigger_priv": TriggerPriv, + "Drop_priv": DropPriv, + "Process_priv": ProcessPriv, + "Grant_priv": GrantPriv, + "References_priv": ReferencesPriv, + "Alter_priv": AlterPriv, + "Execute_priv": ExecutePriv, + "Index_priv": IndexPriv, +} + +// AllGlobalPrivs is all the privileges in global scope. +var AllGlobalPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, ProcessPriv, GrantPriv, ReferencesPriv, AlterPriv, ShowDBPriv, SuperPriv, ExecutePriv, IndexPriv, CreateUserPriv, TriggerPriv} + +// Priv2Str is the map for privilege to string. +var Priv2Str = map[PrivilegeType]string{ + CreatePriv: "Create", + SelectPriv: "Select", + InsertPriv: "Insert", + UpdatePriv: "Update", + DeletePriv: "Delete", + ShowDBPriv: "Show Databases", + SuperPriv: "Super", + CreateUserPriv: "Create User", + TriggerPriv: "Trigger", + DropPriv: "Drop", + ProcessPriv: "Process", + GrantPriv: "Grant Option", + ReferencesPriv: "References", + AlterPriv: "Alter", + ExecutePriv: "Execute", + IndexPriv: "Index", +} + +// Priv2SetStr is the map for privilege to string. +var Priv2SetStr = map[PrivilegeType]string{ + CreatePriv: "Create", + SelectPriv: "Select", + InsertPriv: "Insert", + UpdatePriv: "Update", + DeletePriv: "Delete", + DropPriv: "Drop", + GrantPriv: "Grant", + AlterPriv: "Alter", + ExecutePriv: "Execute", + IndexPriv: "Index", +} + +// SetStr2Priv is the map for privilege set string to privilege type. +var SetStr2Priv = map[string]PrivilegeType{ + "Create": CreatePriv, + "Select": SelectPriv, + "Insert": InsertPriv, + "Update": UpdatePriv, + "Delete": DeletePriv, + "Drop": DropPriv, + "Grant": GrantPriv, + "Alter": AlterPriv, + "Execute": ExecutePriv, + "Index": IndexPriv, +} + +// AllDBPrivs is all the privileges in database scope. +var AllDBPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, ExecutePriv, IndexPriv} + +// AllTablePrivs is all the privileges in table scope. +var AllTablePrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, IndexPriv} + +// AllColumnPrivs is all the privileges in column scope. +var AllColumnPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv} + +// AllPrivilegeLiteral is the string literal for All Privilege. +const AllPrivilegeLiteral = "ALL PRIVILEGES" + +// DefaultSQLMode for GLOBAL_VARIABLES +const DefaultSQLMode = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" + +// DefaultLengthOfMysqlTypes is the map for default physical length of MySQL data types. +// See http://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html +var DefaultLengthOfMysqlTypes = map[byte]int{ + TypeYear: 1, + TypeDate: 3, + TypeDuration: 3, + TypeDatetime: 8, + TypeTimestamp: 4, + + TypeTiny: 1, + TypeShort: 2, + TypeInt24: 3, + TypeLong: 4, + TypeLonglong: 8, + TypeFloat: 4, + TypeDouble: 8, + + TypeEnum: 2, + TypeString: 1, + TypeSet: 8, +} + +// DefaultLengthOfTimeFraction is the map for default physical length of time fractions. +var DefaultLengthOfTimeFraction = map[int]int{ + 0: 0, + + 1: 1, + 2: 1, + + 3: 2, + 4: 2, + + 5: 3, + 6: 3, +} + +// SQLMode is the type for MySQL sql_mode. +// See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html +type SQLMode int + +// HasNoZeroDateMode detects if 'NO_ZERO_DATE' mode is set in SQLMode +func (m SQLMode) HasNoZeroDateMode() bool { + return m&ModeNoZeroDate == ModeNoZeroDate +} + +// HasNoZeroInDateMode detects if 'NO_ZERO_IN_DATE' mode is set in SQLMode +func (m SQLMode) HasNoZeroInDateMode() bool { + return m&ModeNoZeroInDate == ModeNoZeroInDate +} + +// HasErrorForDivisionByZeroMode detects if 'ERROR_FOR_DIVISION_BY_ZERO' mode is set in SQLMode +func (m SQLMode) HasErrorForDivisionByZeroMode() bool { + return m&ModeErrorForDivisionByZero == ModeErrorForDivisionByZero +} + +// HasOnlyFullGroupBy detects if 'ONLY_FULL_GROUP_BY' mode is set in SQLMode +func (m SQLMode) HasOnlyFullGroupBy() bool { + return m&ModeOnlyFullGroupBy == ModeOnlyFullGroupBy +} + +// HasStrictMode detects if 'STRICT_TRANS_TABLES' or 'STRICT_ALL_TABLES' mode is set in SQLMode +func (m SQLMode) HasStrictMode() bool { + return m&ModeStrictTransTables == ModeStrictTransTables || m&ModeStrictAllTables == ModeStrictAllTables +} + +// HasPipesAsConcatMode detects if 'PIPES_AS_CONCAT' mode is set in SQLMode +func (m SQLMode) HasPipesAsConcatMode() bool { + return m&ModePipesAsConcat == ModePipesAsConcat +} + +// HasNoUnsignedSubtractionMode detects if 'NO_UNSIGNED_SUBTRACTION' mode is set in SQLMode +func (m SQLMode) HasNoUnsignedSubtractionMode() bool { + return m&ModeNoUnsignedSubtraction == ModeNoUnsignedSubtraction +} + +// HasHighNotPrecedenceMode detects if 'HIGH_NOT_PRECEDENCE' mode is set in SQLMode +func (m SQLMode) HasHighNotPrecedenceMode() bool { + return m&ModeHighNotPrecedence == ModeHighNotPrecedence +} + +// HasANSIQuotesMode detects if 'ANSI_QUOTES' mode is set in SQLMode +func (m SQLMode) HasANSIQuotesMode() bool { + return m&ModeANSIQuotes == ModeANSIQuotes +} + +// HasRealAsFloatMode detects if 'REAL_AS_FLOAT' mode is set in SQLMode +func (m SQLMode) HasRealAsFloatMode() bool { + return m&ModeRealAsFloat == ModeRealAsFloat +} + +// HasPadCharToFullLengthMode detects if 'PAD_CHAR_TO_FULL_LENGTH' mode is set in SQLMode +func (m SQLMode) HasPadCharToFullLengthMode() bool { + return m&ModePadCharToFullLength == ModePadCharToFullLength +} + +// HasNoBackslashEscapesMode detects if 'NO_BACKSLASH_ESCAPES' mode is set in SQLMode +func (m SQLMode) HasNoBackslashEscapesMode() bool { + return m&ModeNoBackslashEscapes == ModeNoBackslashEscapes +} + +// HasIgnoreSpaceMode detects if 'IGNORE_SPACE' mode is set in SQLMode +func (m SQLMode) HasIgnoreSpaceMode() bool { + return m&ModeIgnoreSpace == ModeIgnoreSpace +} + +// HasNoAutoCreateUserMode detects if 'NO_AUTO_CREATE_USER' mode is set in SQLMode +func (m SQLMode) HasNoAutoCreateUserMode() bool { + return m&ModeNoAutoCreateUser == ModeNoAutoCreateUser +} + +// consts for sql modes. +const ( + ModeNone SQLMode = 0 + ModeRealAsFloat SQLMode = 1 << iota + ModePipesAsConcat + ModeANSIQuotes + ModeIgnoreSpace + ModeNotUsed + ModeOnlyFullGroupBy + ModeNoUnsignedSubtraction + ModeNoDirInCreate + ModePostgreSQL + ModeOracle + ModeMsSQL + ModeDb2 + ModeMaxdb + ModeNoKeyOptions + ModeNoTableOptions + ModeNoFieldOptions + ModeMySQL323 + ModeMySQL40 + ModeANSI + ModeNoAutoValueOnZero + ModeNoBackslashEscapes + ModeStrictTransTables + ModeStrictAllTables + ModeNoZeroInDate + ModeNoZeroDate + ModeInvalidDates + ModeErrorForDivisionByZero + ModeTraditional + ModeNoAutoCreateUser + ModeHighNotPrecedence + ModeNoEngineSubstitution + ModePadCharToFullLength +) + +// FormatSQLModeStr re-format 'SQL_MODE' variable. +func FormatSQLModeStr(s string) string { + s = strings.ToUpper(strings.TrimRight(s, " ")) + parts := strings.Split(s, ",") + var nonEmptyParts []string + existParts := make(map[string]string) + for _, part := range parts { + if len(part) == 0 { + continue + } + if modeParts, ok := CombinationSQLMode[part]; ok { + for _, modePart := range modeParts { + if _, exist := existParts[modePart]; !exist { + nonEmptyParts = append(nonEmptyParts, modePart) + existParts[modePart] = modePart + } + } + } + if _, exist := existParts[part]; !exist { + nonEmptyParts = append(nonEmptyParts, part) + existParts[part] = part + } + } + return strings.Join(nonEmptyParts, ",") +} + +// GetSQLMode gets the sql mode for string literal. SQL_mode is a list of different modes separated by commas. +// The input string must be formatted by 'FormatSQLModeStr' +func GetSQLMode(s string) (SQLMode, error) { + strs := strings.Split(s, ",") + var sqlMode SQLMode + for i, length := 0, len(strs); i < length; i++ { + mode, ok := Str2SQLMode[strs[i]] + if !ok && strs[i] != "" { + return sqlMode, newInvalidModeErr(strs[i]) + } + sqlMode = sqlMode | mode + } + return sqlMode, nil +} + +// Str2SQLMode is the string represent of sql_mode to sql_mode map. +var Str2SQLMode = map[string]SQLMode{ + "REAL_AS_FLOAT": ModeRealAsFloat, + "PIPES_AS_CONCAT": ModePipesAsConcat, + "ANSI_QUOTES": ModeANSIQuotes, + "IGNORE_SPACE": ModeIgnoreSpace, + "NOT_USED": ModeNotUsed, + "ONLY_FULL_GROUP_BY": ModeOnlyFullGroupBy, + "NO_UNSIGNED_SUBTRACTION": ModeNoUnsignedSubtraction, + "NO_DIR_IN_CREATE": ModeNoDirInCreate, + "POSTGRESQL": ModePostgreSQL, + "ORACLE": ModeOracle, + "MSSQL": ModeMsSQL, + "DB2": ModeDb2, + "MAXDB": ModeMaxdb, + "NO_KEY_OPTIONS": ModeNoKeyOptions, + "NO_TABLE_OPTIONS": ModeNoTableOptions, + "NO_FIELD_OPTIONS": ModeNoFieldOptions, + "MYSQL323": ModeMySQL323, + "MYSQL40": ModeMySQL40, + "ANSI": ModeANSI, + "NO_AUTO_VALUE_ON_ZERO": ModeNoAutoValueOnZero, + "NO_BACKSLASH_ESCAPES": ModeNoBackslashEscapes, + "STRICT_TRANS_TABLES": ModeStrictTransTables, + "STRICT_ALL_TABLES": ModeStrictAllTables, + "NO_ZERO_IN_DATE": ModeNoZeroInDate, + "NO_ZERO_DATE": ModeNoZeroDate, + "INVALID_DATES": ModeInvalidDates, + "ERROR_FOR_DIVISION_BY_ZERO": ModeErrorForDivisionByZero, + "TRADITIONAL": ModeTraditional, + "NO_AUTO_CREATE_USER": ModeNoAutoCreateUser, + "HIGH_NOT_PRECEDENCE": ModeHighNotPrecedence, + "NO_ENGINE_SUBSTITUTION": ModeNoEngineSubstitution, + "PAD_CHAR_TO_FULL_LENGTH": ModePadCharToFullLength, +} + +// CombinationSQLMode is the special modes that provided as shorthand for combinations of mode values. +// See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-combo. +var CombinationSQLMode = map[string][]string{ + "ANSI": {"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "ONLY_FULL_GROUP_BY"}, + "DB2": {"PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS"}, + "MAXDB": {"PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "NO_AUTO_CREATE_USER"}, + "MSSQL": {"PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS"}, + "MYSQL323": {"MYSQL323", "HIGH_NOT_PRECEDENCE"}, + "MYSQL40": {"MYSQL40", "HIGH_NOT_PRECEDENCE"}, + "ORACLE": {"PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "NO_AUTO_CREATE_USER"}, + "POSTGRESQL": {"PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS"}, + "TRADITIONAL": {"STRICT_TRANS_TABLES", "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ERROR_FOR_DIVISION_BY_ZERO", "NO_AUTO_CREATE_USER", "NO_ENGINE_SUBSTITUTION"}, +} + +// FormatFunc is the locale format function signature. +type FormatFunc func(string, string) (string, error) + +// GetLocaleFormatFunction get the format function for sepcific locale. +func GetLocaleFormatFunction(loc string) FormatFunc { + locale, exist := locale2FormatFunction[loc] + if !exist { + return formatNotSupport + } + return locale +} + +// locale2FormatFunction is the string represent of locale format function. +var locale2FormatFunction = map[string]FormatFunc{ + "en_US": formatENUS, + "zh_CN": formatZHCN, +} + +// PriorityEnum is defined for Priority const values. +type PriorityEnum int + +// Priority const values. +// See https://dev.mysql.com/doc/refman/5.7/en/insert.html +const ( + NoPriority PriorityEnum = iota + LowPriority + HighPriority + DelayedPriority +) + +// Priority2Str is used to convert the statement priority to string. +var Priority2Str = map[PriorityEnum]string{ + NoPriority: "NO_PRIORITY", + LowPriority: "LOW_PRIORITY", + HighPriority: "HIGH_PRIORITY", + DelayedPriority: "DELAYED", +} + +// Str2Priority is used to convert a string to a priority. +func Str2Priority(val string) PriorityEnum { + val = strings.ToUpper(val) + switch val { + case "NO_PRIORITY": + return NoPriority + case "HIGH_PRIORITY": + return HighPriority + case "LOW_PRIORITY": + return LowPriority + case "DELAYED": + return DelayedPriority + default: + return NoPriority + } +} + +// PrimaryKeyName defines primary key name. +const ( + PrimaryKeyName = "PRIMARY" +) diff --git a/vendor/github.com/pingcap/parser/mysql/errcode.go b/vendor/github.com/pingcap/parser/mysql/errcode.go new file mode 100644 index 0000000000000000000000000000000000000000..79c6999498d4d59270ebe199a0a2153d085d0d9e --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/errcode.go @@ -0,0 +1,910 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +// MySQL error code. +// This value is numeric. It is not portable to other database systems. +const ( + ErrErrorFirst uint16 = 1000 + ErrHashchk = 1000 + ErrNisamchk = 1001 + ErrNo = 1002 + ErrYes = 1003 + ErrCantCreateFile = 1004 + ErrCantCreateTable = 1005 + ErrCantCreateDB = 1006 + ErrDBCreateExists = 1007 + ErrDBDropExists = 1008 + ErrDBDropDelete = 1009 + ErrDBDropRmdir = 1010 + ErrCantDeleteFile = 1011 + ErrCantFindSystemRec = 1012 + ErrCantGetStat = 1013 + ErrCantGetWd = 1014 + ErrCantLock = 1015 + ErrCantOpenFile = 1016 + ErrFileNotFound = 1017 + ErrCantReadDir = 1018 + ErrCantSetWd = 1019 + ErrCheckread = 1020 + ErrDiskFull = 1021 + ErrDupKey = 1022 + ErrErrorOnClose = 1023 + ErrErrorOnRead = 1024 + ErrErrorOnRename = 1025 + ErrErrorOnWrite = 1026 + ErrFileUsed = 1027 + ErrFilsortAbort = 1028 + ErrFormNotFound = 1029 + ErrGetErrno = 1030 + ErrIllegalHa = 1031 + ErrKeyNotFound = 1032 + ErrNotFormFile = 1033 + ErrNotKeyFile = 1034 + ErrOldKeyFile = 1035 + ErrOpenAsReadonly = 1036 + ErrOutofMemory = 1037 + ErrOutOfSortMemory = 1038 + ErrUnexpectedEOF = 1039 + ErrConCount = 1040 + ErrOutOfResources = 1041 + ErrBadHost = 1042 + ErrHandshake = 1043 + ErrDBaccessDenied = 1044 + ErrAccessDenied = 1045 + ErrNoDB = 1046 + ErrUnknownCom = 1047 + ErrBadNull = 1048 + ErrBadDB = 1049 + ErrTableExists = 1050 + ErrBadTable = 1051 + ErrNonUniq = 1052 + ErrServerShutdown = 1053 + ErrBadField = 1054 + ErrFieldNotInGroupBy = 1055 + ErrWrongGroupField = 1056 + ErrWrongSumSelect = 1057 + ErrWrongValueCount = 1058 + ErrTooLongIdent = 1059 + ErrDupFieldName = 1060 + ErrDupKeyName = 1061 + ErrDupEntry = 1062 + ErrWrongFieldSpec = 1063 + ErrParse = 1064 + ErrEmptyQuery = 1065 + ErrNonuniqTable = 1066 + ErrInvalidDefault = 1067 + ErrMultiplePriKey = 1068 + ErrTooManyKeys = 1069 + ErrTooManyKeyParts = 1070 + ErrTooLongKey = 1071 + ErrKeyColumnDoesNotExits = 1072 + ErrBlobUsedAsKey = 1073 + ErrTooBigFieldlength = 1074 + ErrWrongAutoKey = 1075 + ErrReady = 1076 + ErrNormalShutdown = 1077 + ErrGotSignal = 1078 + ErrShutdownComplete = 1079 + ErrForcingClose = 1080 + ErrIpsock = 1081 + ErrNoSuchIndex = 1082 + ErrWrongFieldTerminators = 1083 + ErrBlobsAndNoTerminated = 1084 + ErrTextFileNotReadable = 1085 + ErrFileExists = 1086 + ErrLoadInfo = 1087 + ErrAlterInfo = 1088 + ErrWrongSubKey = 1089 + ErrCantRemoveAllFields = 1090 + ErrCantDropFieldOrKey = 1091 + ErrInsertInfo = 1092 + ErrUpdateTableUsed = 1093 + ErrNoSuchThread = 1094 + ErrKillDenied = 1095 + ErrNoTablesUsed = 1096 + ErrTooBigSet = 1097 + ErrNoUniqueLogFile = 1098 + ErrTableNotLockedForWrite = 1099 + ErrTableNotLocked = 1100 + ErrBlobCantHaveDefault = 1101 + ErrWrongDBName = 1102 + ErrWrongTableName = 1103 + ErrTooBigSelect = 1104 + ErrUnknown = 1105 + ErrUnknownProcedure = 1106 + ErrWrongParamcountToProcedure = 1107 + ErrWrongParametersToProcedure = 1108 + ErrUnknownTable = 1109 + ErrFieldSpecifiedTwice = 1110 + ErrInvalidGroupFuncUse = 1111 + ErrUnsupportedExtension = 1112 + ErrTableMustHaveColumns = 1113 + ErrRecordFileFull = 1114 + ErrUnknownCharacterSet = 1115 + ErrTooManyTables = 1116 + ErrTooManyFields = 1117 + ErrTooBigRowsize = 1118 + ErrStackOverrun = 1119 + ErrWrongOuterJoin = 1120 + ErrNullColumnInIndex = 1121 + ErrCantFindUdf = 1122 + ErrCantInitializeUdf = 1123 + ErrUdfNoPaths = 1124 + ErrUdfExists = 1125 + ErrCantOpenLibrary = 1126 + ErrCantFindDlEntry = 1127 + ErrFunctionNotDefined = 1128 + ErrHostIsBlocked = 1129 + ErrHostNotPrivileged = 1130 + ErrPasswordAnonymousUser = 1131 + ErrPasswordNotAllowed = 1132 + ErrPasswordNoMatch = 1133 + ErrUpdateInfo = 1134 + ErrCantCreateThread = 1135 + ErrWrongValueCountOnRow = 1136 + ErrCantReopenTable = 1137 + ErrInvalidUseOfNull = 1138 + ErrRegexp = 1139 + ErrMixOfGroupFuncAndFields = 1140 + ErrNonexistingGrant = 1141 + ErrTableaccessDenied = 1142 + ErrColumnaccessDenied = 1143 + ErrIllegalGrantForTable = 1144 + ErrGrantWrongHostOrUser = 1145 + ErrNoSuchTable = 1146 + ErrNonexistingTableGrant = 1147 + ErrNotAllowedCommand = 1148 + ErrSyntax = 1149 + ErrDelayedCantChangeLock = 1150 + ErrTooManyDelayedThreads = 1151 + ErrAbortingConnection = 1152 + ErrNetPacketTooLarge = 1153 + ErrNetReadErrorFromPipe = 1154 + ErrNetFcntl = 1155 + ErrNetPacketsOutOfOrder = 1156 + ErrNetUncompress = 1157 + ErrNetRead = 1158 + ErrNetReadInterrupted = 1159 + ErrNetErrorOnWrite = 1160 + ErrNetWriteInterrupted = 1161 + ErrTooLongString = 1162 + ErrTableCantHandleBlob = 1163 + ErrTableCantHandleAutoIncrement = 1164 + ErrDelayedInsertTableLocked = 1165 + ErrWrongColumnName = 1166 + ErrWrongKeyColumn = 1167 + ErrWrongMrgTable = 1168 + ErrDupUnique = 1169 + ErrBlobKeyWithoutLength = 1170 + ErrPrimaryCantHaveNull = 1171 + ErrTooManyRows = 1172 + ErrRequiresPrimaryKey = 1173 + ErrNoRaidCompiled = 1174 + ErrUpdateWithoutKeyInSafeMode = 1175 + ErrKeyDoesNotExist = 1176 + ErrCheckNoSuchTable = 1177 + ErrCheckNotImplemented = 1178 + ErrCantDoThisDuringAnTransaction = 1179 + ErrErrorDuringCommit = 1180 + ErrErrorDuringRollback = 1181 + ErrErrorDuringFlushLogs = 1182 + ErrErrorDuringCheckpoint = 1183 + ErrNewAbortingConnection = 1184 + ErrDumpNotImplemented = 1185 + ErrFlushMasterBinlogClosed = 1186 + ErrIndexRebuild = 1187 + ErrMaster = 1188 + ErrMasterNetRead = 1189 + ErrMasterNetWrite = 1190 + ErrFtMatchingKeyNotFound = 1191 + ErrLockOrActiveTransaction = 1192 + ErrUnknownSystemVariable = 1193 + ErrCrashedOnUsage = 1194 + ErrCrashedOnRepair = 1195 + ErrWarningNotCompleteRollback = 1196 + ErrTransCacheFull = 1197 + ErrSlaveMustStop = 1198 + ErrSlaveNotRunning = 1199 + ErrBadSlave = 1200 + ErrMasterInfo = 1201 + ErrSlaveThread = 1202 + ErrTooManyUserConnections = 1203 + ErrSetConstantsOnly = 1204 + ErrLockWaitTimeout = 1205 + ErrLockTableFull = 1206 + ErrReadOnlyTransaction = 1207 + ErrDropDBWithReadLock = 1208 + ErrCreateDBWithReadLock = 1209 + ErrWrongArguments = 1210 + ErrNoPermissionToCreateUser = 1211 + ErrUnionTablesInDifferentDir = 1212 + ErrLockDeadlock = 1213 + ErrTableCantHandleFt = 1214 + ErrCannotAddForeign = 1215 + ErrNoReferencedRow = 1216 + ErrRowIsReferenced = 1217 + ErrConnectToMaster = 1218 + ErrQueryOnMaster = 1219 + ErrErrorWhenExecutingCommand = 1220 + ErrWrongUsage = 1221 + ErrWrongNumberOfColumnsInSelect = 1222 + ErrCantUpdateWithReadlock = 1223 + ErrMixingNotAllowed = 1224 + ErrDupArgument = 1225 + ErrUserLimitReached = 1226 + ErrSpecificAccessDenied = 1227 + ErrLocalVariable = 1228 + ErrGlobalVariable = 1229 + ErrNoDefault = 1230 + ErrWrongValueForVar = 1231 + ErrWrongTypeForVar = 1232 + ErrVarCantBeRead = 1233 + ErrCantUseOptionHere = 1234 + ErrNotSupportedYet = 1235 + ErrMasterFatalErrorReadingBinlog = 1236 + ErrSlaveIgnoredTable = 1237 + ErrIncorrectGlobalLocalVar = 1238 + ErrWrongFkDef = 1239 + ErrKeyRefDoNotMatchTableRef = 1240 + ErrOperandColumns = 1241 + ErrSubqueryNo1Row = 1242 + ErrUnknownStmtHandler = 1243 + ErrCorruptHelpDB = 1244 + ErrCyclicReference = 1245 + ErrAutoConvert = 1246 + ErrIllegalReference = 1247 + ErrDerivedMustHaveAlias = 1248 + ErrSelectReduced = 1249 + ErrTablenameNotAllowedHere = 1250 + ErrNotSupportedAuthMode = 1251 + ErrSpatialCantHaveNull = 1252 + ErrCollationCharsetMismatch = 1253 + ErrSlaveWasRunning = 1254 + ErrSlaveWasNotRunning = 1255 + ErrTooBigForUncompress = 1256 + ErrZlibZMem = 1257 + ErrZlibZBuf = 1258 + ErrZlibZData = 1259 + ErrCutValueGroupConcat = 1260 + ErrWarnTooFewRecords = 1261 + ErrWarnTooManyRecords = 1262 + ErrWarnNullToNotnull = 1263 + ErrWarnDataOutOfRange = 1264 + WarnDataTruncated = 1265 + ErrWarnUsingOtherHandler = 1266 + ErrCantAggregate2collations = 1267 + ErrDropUser = 1268 + ErrRevokeGrants = 1269 + ErrCantAggregate3collations = 1270 + ErrCantAggregateNcollations = 1271 + ErrVariableIsNotStruct = 1272 + ErrUnknownCollation = 1273 + ErrSlaveIgnoredSslParams = 1274 + ErrServerIsInSecureAuthMode = 1275 + ErrWarnFieldResolved = 1276 + ErrBadSlaveUntilCond = 1277 + ErrMissingSkipSlave = 1278 + ErrUntilCondIgnored = 1279 + ErrWrongNameForIndex = 1280 + ErrWrongNameForCatalog = 1281 + ErrWarnQcResize = 1282 + ErrBadFtColumn = 1283 + ErrUnknownKeyCache = 1284 + ErrWarnHostnameWontWork = 1285 + ErrUnknownStorageEngine = 1286 + ErrWarnDeprecatedSyntax = 1287 + ErrNonUpdatableTable = 1288 + ErrFeatureDisabled = 1289 + ErrOptionPreventsStatement = 1290 + ErrDuplicatedValueInType = 1291 + ErrTruncatedWrongValue = 1292 + ErrTooMuchAutoTimestampCols = 1293 + ErrInvalidOnUpdate = 1294 + ErrUnsupportedPs = 1295 + ErrGetErrmsg = 1296 + ErrGetTemporaryErrmsg = 1297 + ErrUnknownTimeZone = 1298 + ErrWarnInvalidTimestamp = 1299 + ErrInvalidCharacterString = 1300 + ErrWarnAllowedPacketOverflowed = 1301 + ErrConflictingDeclarations = 1302 + ErrSpNoRecursiveCreate = 1303 + ErrSpAlreadyExists = 1304 + ErrSpDoesNotExist = 1305 + ErrSpDropFailed = 1306 + ErrSpStoreFailed = 1307 + ErrSpLilabelMismatch = 1308 + ErrSpLabelRedefine = 1309 + ErrSpLabelMismatch = 1310 + ErrSpUninitVar = 1311 + ErrSpBadselect = 1312 + ErrSpBadreturn = 1313 + ErrSpBadstatement = 1314 + ErrUpdateLogDeprecatedIgnored = 1315 + ErrUpdateLogDeprecatedTranslated = 1316 + ErrQueryInterrupted = 1317 + ErrSpWrongNoOfArgs = 1318 + ErrSpCondMismatch = 1319 + ErrSpNoreturn = 1320 + ErrSpNoreturnend = 1321 + ErrSpBadCursorQuery = 1322 + ErrSpBadCursorSelect = 1323 + ErrSpCursorMismatch = 1324 + ErrSpCursorAlreadyOpen = 1325 + ErrSpCursorNotOpen = 1326 + ErrSpUndeclaredVar = 1327 + ErrSpWrongNoOfFetchArgs = 1328 + ErrSpFetchNoData = 1329 + ErrSpDupParam = 1330 + ErrSpDupVar = 1331 + ErrSpDupCond = 1332 + ErrSpDupCurs = 1333 + ErrSpCantAlter = 1334 + ErrSpSubselectNyi = 1335 + ErrStmtNotAllowedInSfOrTrg = 1336 + ErrSpVarcondAfterCurshndlr = 1337 + ErrSpCursorAfterHandler = 1338 + ErrSpCaseNotFound = 1339 + ErrFparserTooBigFile = 1340 + ErrFparserBadHeader = 1341 + ErrFparserEOFInComment = 1342 + ErrFparserErrorInParameter = 1343 + ErrFparserEOFInUnknownParameter = 1344 + ErrViewNoExplain = 1345 + ErrFrmUnknownType = 1346 + ErrWrongObject = 1347 + ErrNonupdateableColumn = 1348 + ErrViewSelectDerived = 1349 + ErrViewSelectClause = 1350 + ErrViewSelectVariable = 1351 + ErrViewSelectTmptable = 1352 + ErrViewWrongList = 1353 + ErrWarnViewMerge = 1354 + ErrWarnViewWithoutKey = 1355 + ErrViewInvalid = 1356 + ErrSpNoDropSp = 1357 + ErrSpGotoInHndlr = 1358 + ErrTrgAlreadyExists = 1359 + ErrTrgDoesNotExist = 1360 + ErrTrgOnViewOrTempTable = 1361 + ErrTrgCantChangeRow = 1362 + ErrTrgNoSuchRowInTrg = 1363 + ErrNoDefaultForField = 1364 + ErrDivisionByZero = 1365 + ErrTruncatedWrongValueForField = 1366 + ErrIllegalValueForType = 1367 + ErrViewNonupdCheck = 1368 + ErrViewCheckFailed = 1369 + ErrProcaccessDenied = 1370 + ErrRelayLogFail = 1371 + ErrPasswdLength = 1372 + ErrUnknownTargetBinlog = 1373 + ErrIoErrLogIndexRead = 1374 + ErrBinlogPurgeProhibited = 1375 + ErrFseekFail = 1376 + ErrBinlogPurgeFatalErr = 1377 + ErrLogInUse = 1378 + ErrLogPurgeUnknownErr = 1379 + ErrRelayLogInit = 1380 + ErrNoBinaryLogging = 1381 + ErrReservedSyntax = 1382 + ErrWsasFailed = 1383 + ErrDiffGroupsProc = 1384 + ErrNoGroupForProc = 1385 + ErrOrderWithProc = 1386 + ErrLoggingProhibitChangingOf = 1387 + ErrNoFileMapping = 1388 + ErrWrongMagic = 1389 + ErrPsManyParam = 1390 + ErrKeyPart0 = 1391 + ErrViewChecksum = 1392 + ErrViewMultiupdate = 1393 + ErrViewNoInsertFieldList = 1394 + ErrViewDeleteMergeView = 1395 + ErrCannotUser = 1396 + ErrXaerNota = 1397 + ErrXaerInval = 1398 + ErrXaerRmfail = 1399 + ErrXaerOutside = 1400 + ErrXaerRmerr = 1401 + ErrXaRbrollback = 1402 + ErrNonexistingProcGrant = 1403 + ErrProcAutoGrantFail = 1404 + ErrProcAutoRevokeFail = 1405 + ErrDataTooLong = 1406 + ErrSpBadSQLstate = 1407 + ErrStartup = 1408 + ErrLoadFromFixedSizeRowsToVar = 1409 + ErrCantCreateUserWithGrant = 1410 + ErrWrongValueForType = 1411 + ErrTableDefChanged = 1412 + ErrSpDupHandler = 1413 + ErrSpNotVarArg = 1414 + ErrSpNoRetset = 1415 + ErrCantCreateGeometryObject = 1416 + ErrFailedRoutineBreakBinlog = 1417 + ErrBinlogUnsafeRoutine = 1418 + ErrBinlogCreateRoutineNeedSuper = 1419 + ErrExecStmtWithOpenCursor = 1420 + ErrStmtHasNoOpenCursor = 1421 + ErrCommitNotAllowedInSfOrTrg = 1422 + ErrNoDefaultForViewField = 1423 + ErrSpNoRecursion = 1424 + ErrTooBigScale = 1425 + ErrTooBigPrecision = 1426 + ErrMBiggerThanD = 1427 + ErrWrongLockOfSystemTable = 1428 + ErrConnectToForeignDataSource = 1429 + ErrQueryOnForeignDataSource = 1430 + ErrForeignDataSourceDoesntExist = 1431 + ErrForeignDataStringInvalidCantCreate = 1432 + ErrForeignDataStringInvalid = 1433 + ErrCantCreateFederatedTable = 1434 + ErrTrgInWrongSchema = 1435 + ErrStackOverrunNeedMore = 1436 + ErrTooLongBody = 1437 + ErrWarnCantDropDefaultKeycache = 1438 + ErrTooBigDisplaywidth = 1439 + ErrXaerDupid = 1440 + ErrDatetimeFunctionOverflow = 1441 + ErrCantUpdateUsedTableInSfOrTrg = 1442 + ErrViewPreventUpdate = 1443 + ErrPsNoRecursion = 1444 + ErrSpCantSetAutocommit = 1445 + ErrMalformedDefiner = 1446 + ErrViewFrmNoUser = 1447 + ErrViewOtherUser = 1448 + ErrNoSuchUser = 1449 + ErrForbidSchemaChange = 1450 + ErrRowIsReferenced2 = 1451 + ErrNoReferencedRow2 = 1452 + ErrSpBadVarShadow = 1453 + ErrTrgNoDefiner = 1454 + ErrOldFileFormat = 1455 + ErrSpRecursionLimit = 1456 + ErrSpProcTableCorrupt = 1457 + ErrSpWrongName = 1458 + ErrTableNeedsUpgrade = 1459 + ErrSpNoAggregate = 1460 + ErrMaxPreparedStmtCountReached = 1461 + ErrViewRecursive = 1462 + ErrNonGroupingFieldUsed = 1463 + ErrTableCantHandleSpkeys = 1464 + ErrNoTriggersOnSystemSchema = 1465 + ErrRemovedSpaces = 1466 + ErrAutoincReadFailed = 1467 + ErrUsername = 1468 + ErrHostname = 1469 + ErrWrongStringLength = 1470 + ErrNonInsertableTable = 1471 + ErrAdminWrongMrgTable = 1472 + ErrTooHighLevelOfNestingForSelect = 1473 + ErrNameBecomesEmpty = 1474 + ErrAmbiguousFieldTerm = 1475 + ErrForeignServerExists = 1476 + ErrForeignServerDoesntExist = 1477 + ErrIllegalHaCreateOption = 1478 + ErrPartitionRequiresValues = 1479 + ErrPartitionWrongValues = 1480 + ErrPartitionMaxvalue = 1481 + ErrPartitionSubpartition = 1482 + ErrPartitionSubpartMix = 1483 + ErrPartitionWrongNoPart = 1484 + ErrPartitionWrongNoSubpart = 1485 + ErrWrongExprInPartitionFunc = 1486 + ErrNoConstExprInRangeOrList = 1487 + ErrFieldNotFoundPart = 1488 + ErrListOfFieldsOnlyInHash = 1489 + ErrInconsistentPartitionInfo = 1490 + ErrPartitionFuncNotAllowed = 1491 + ErrPartitionsMustBeDefined = 1492 + ErrRangeNotIncreasing = 1493 + ErrInconsistentTypeOfFunctions = 1494 + ErrMultipleDefConstInListPart = 1495 + ErrPartitionEntry = 1496 + ErrMixHandler = 1497 + ErrPartitionNotDefined = 1498 + ErrTooManyPartitions = 1499 + ErrSubpartition = 1500 + ErrCantCreateHandlerFile = 1501 + ErrBlobFieldInPartFunc = 1502 + ErrUniqueKeyNeedAllFieldsInPf = 1503 + ErrNoParts = 1504 + ErrPartitionMgmtOnNonpartitioned = 1505 + ErrForeignKeyOnPartitioned = 1506 + ErrDropPartitionNonExistent = 1507 + ErrDropLastPartition = 1508 + ErrCoalesceOnlyOnHashPartition = 1509 + ErrReorgHashOnlyOnSameNo = 1510 + ErrReorgNoParam = 1511 + ErrOnlyOnRangeListPartition = 1512 + ErrAddPartitionSubpart = 1513 + ErrAddPartitionNoNewPartition = 1514 + ErrCoalescePartitionNoPartition = 1515 + ErrReorgPartitionNotExist = 1516 + ErrSameNamePartition = 1517 + ErrNoBinlog = 1518 + ErrConsecutiveReorgPartitions = 1519 + ErrReorgOutsideRange = 1520 + ErrPartitionFunctionFailure = 1521 + ErrPartState = 1522 + ErrLimitedPartRange = 1523 + ErrPluginIsNotLoaded = 1524 + ErrWrongValue = 1525 + ErrNoPartitionForGivenValue = 1526 + ErrFilegroupOptionOnlyOnce = 1527 + ErrCreateFilegroupFailed = 1528 + ErrDropFilegroupFailed = 1529 + ErrTablespaceAutoExtend = 1530 + ErrWrongSizeNumber = 1531 + ErrSizeOverflow = 1532 + ErrAlterFilegroupFailed = 1533 + ErrBinlogRowLoggingFailed = 1534 + ErrBinlogRowWrongTableDef = 1535 + ErrBinlogRowRbrToSbr = 1536 + ErrEventAlreadyExists = 1537 + ErrEventStoreFailed = 1538 + ErrEventDoesNotExist = 1539 + ErrEventCantAlter = 1540 + ErrEventDropFailed = 1541 + ErrEventIntervalNotPositiveOrTooBig = 1542 + ErrEventEndsBeforeStarts = 1543 + ErrEventExecTimeInThePast = 1544 + ErrEventOpenTableFailed = 1545 + ErrEventNeitherMExprNorMAt = 1546 + ErrObsoleteColCountDoesntMatchCorrupted = 1547 + ErrObsoleteCannotLoadFromTable = 1548 + ErrEventCannotDelete = 1549 + ErrEventCompile = 1550 + ErrEventSameName = 1551 + ErrEventDataTooLong = 1552 + ErrDropIndexFk = 1553 + ErrWarnDeprecatedSyntaxWithVer = 1554 + ErrCantWriteLockLogTable = 1555 + ErrCantLockLogTable = 1556 + ErrForeignDuplicateKeyOldUnused = 1557 + ErrColCountDoesntMatchPleaseUpdate = 1558 + ErrTempTablePreventsSwitchOutOfRbr = 1559 + ErrStoredFunctionPreventsSwitchBinlogFormat = 1560 + ErrNdbCantSwitchBinlogFormat = 1561 + ErrPartitionNoTemporary = 1562 + ErrPartitionConstDomain = 1563 + ErrPartitionFunctionIsNotAllowed = 1564 + ErrDdlLog = 1565 + ErrNullInValuesLessThan = 1566 + ErrWrongPartitionName = 1567 + ErrCantChangeTxCharacteristics = 1568 + ErrDupEntryAutoincrementCase = 1569 + ErrEventModifyQueue = 1570 + ErrEventSetVar = 1571 + ErrPartitionMerge = 1572 + ErrCantActivateLog = 1573 + ErrRbrNotAvailable = 1574 + ErrBase64Decode = 1575 + ErrEventRecursionForbidden = 1576 + ErrEventsDB = 1577 + ErrOnlyIntegersAllowed = 1578 + ErrUnsuportedLogEngine = 1579 + ErrBadLogStatement = 1580 + ErrCantRenameLogTable = 1581 + ErrWrongParamcountToNativeFct = 1582 + ErrWrongParametersToNativeFct = 1583 + ErrWrongParametersToStoredFct = 1584 + ErrNativeFctNameCollision = 1585 + ErrDupEntryWithKeyName = 1586 + ErrBinlogPurgeEmFile = 1587 + ErrEventCannotCreateInThePast = 1588 + ErrEventCannotAlterInThePast = 1589 + ErrSlaveIncident = 1590 + ErrNoPartitionForGivenValueSilent = 1591 + ErrBinlogUnsafeStatement = 1592 + ErrSlaveFatal = 1593 + ErrSlaveRelayLogReadFailure = 1594 + ErrSlaveRelayLogWriteFailure = 1595 + ErrSlaveCreateEventFailure = 1596 + ErrSlaveMasterComFailure = 1597 + ErrBinlogLoggingImpossible = 1598 + ErrViewNoCreationCtx = 1599 + ErrViewInvalidCreationCtx = 1600 + ErrSrInvalidCreationCtx = 1601 + ErrTrgCorruptedFile = 1602 + ErrTrgNoCreationCtx = 1603 + ErrTrgInvalidCreationCtx = 1604 + ErrEventInvalidCreationCtx = 1605 + ErrTrgCantOpenTable = 1606 + ErrCantCreateSroutine = 1607 + ErrNeverUsed = 1608 + ErrNoFormatDescriptionEventBeforeBinlogStatement = 1609 + ErrSlaveCorruptEvent = 1610 + ErrLoadDataInvalidColumn = 1611 + ErrLogPurgeNoFile = 1612 + ErrXaRbtimeout = 1613 + ErrXaRbdeadlock = 1614 + ErrNeedReprepare = 1615 + ErrDelayedNotSupported = 1616 + WarnNoMasterInfo = 1617 + WarnOptionIgnored = 1618 + WarnPluginDeleteBuiltin = 1619 + WarnPluginBusy = 1620 + ErrVariableIsReadonly = 1621 + ErrWarnEngineTransactionRollback = 1622 + ErrSlaveHeartbeatFailure = 1623 + ErrSlaveHeartbeatValueOutOfRange = 1624 + ErrNdbReplicationSchema = 1625 + ErrConflictFnParse = 1626 + ErrExceptionsWrite = 1627 + ErrTooLongTableComment = 1628 + ErrTooLongFieldComment = 1629 + ErrFuncInexistentNameCollision = 1630 + ErrDatabaseName = 1631 + ErrTableName = 1632 + ErrPartitionName = 1633 + ErrSubpartitionName = 1634 + ErrTemporaryName = 1635 + ErrRenamedName = 1636 + ErrTooManyConcurrentTrxs = 1637 + WarnNonASCIISeparatorNotImplemented = 1638 + ErrDebugSyncTimeout = 1639 + ErrDebugSyncHitLimit = 1640 + ErrDupSignalSet = 1641 + ErrSignalWarn = 1642 + ErrSignalNotFound = 1643 + ErrSignalException = 1644 + ErrResignalWithoutActiveHandler = 1645 + ErrSignalBadConditionType = 1646 + WarnCondItemTruncated = 1647 + ErrCondItemTooLong = 1648 + ErrUnknownLocale = 1649 + ErrSlaveIgnoreServerIds = 1650 + ErrQueryCacheDisabled = 1651 + ErrSameNamePartitionField = 1652 + ErrPartitionColumnList = 1653 + ErrWrongTypeColumnValue = 1654 + ErrTooManyPartitionFuncFields = 1655 + ErrMaxvalueInValuesIn = 1656 + ErrTooManyValues = 1657 + ErrRowSinglePartitionField = 1658 + ErrFieldTypeNotAllowedAsPartitionField = 1659 + ErrPartitionFieldsTooLong = 1660 + ErrBinlogRowEngineAndStmtEngine = 1661 + ErrBinlogRowModeAndStmtEngine = 1662 + ErrBinlogUnsafeAndStmtEngine = 1663 + ErrBinlogRowInjectionAndStmtEngine = 1664 + ErrBinlogStmtModeAndRowEngine = 1665 + ErrBinlogRowInjectionAndStmtMode = 1666 + ErrBinlogMultipleEnginesAndSelfLoggingEngine = 1667 + ErrBinlogUnsafeLimit = 1668 + ErrBinlogUnsafeInsertDelayed = 1669 + ErrBinlogUnsafeSystemTable = 1670 + ErrBinlogUnsafeAutoincColumns = 1671 + ErrBinlogUnsafeUdf = 1672 + ErrBinlogUnsafeSystemVariable = 1673 + ErrBinlogUnsafeSystemFunction = 1674 + ErrBinlogUnsafeNontransAfterTrans = 1675 + ErrMessageAndStatement = 1676 + ErrSlaveConversionFailed = 1677 + ErrSlaveCantCreateConversion = 1678 + ErrInsideTransactionPreventsSwitchBinlogFormat = 1679 + ErrPathLength = 1680 + ErrWarnDeprecatedSyntaxNoReplacement = 1681 + ErrWrongNativeTableStructure = 1682 + ErrWrongPerfSchemaUsage = 1683 + ErrWarnISSkippedTable = 1684 + ErrInsideTransactionPreventsSwitchBinlogDirect = 1685 + ErrStoredFunctionPreventsSwitchBinlogDirect = 1686 + ErrSpatialMustHaveGeomCol = 1687 + ErrTooLongIndexComment = 1688 + ErrLockAborted = 1689 + ErrDataOutOfRange = 1690 + ErrWrongSpvarTypeInLimit = 1691 + ErrBinlogUnsafeMultipleEnginesAndSelfLoggingEngine = 1692 + ErrBinlogUnsafeMixedStatement = 1693 + ErrInsideTransactionPreventsSwitchSQLLogBin = 1694 + ErrStoredFunctionPreventsSwitchSQLLogBin = 1695 + ErrFailedReadFromParFile = 1696 + ErrValuesIsNotIntType = 1697 + ErrAccessDeniedNoPassword = 1698 + ErrSetPasswordAuthPlugin = 1699 + ErrGrantPluginUserExists = 1700 + ErrTruncateIllegalFk = 1701 + ErrPluginIsPermanent = 1702 + ErrSlaveHeartbeatValueOutOfRangeMin = 1703 + ErrSlaveHeartbeatValueOutOfRangeMax = 1704 + ErrStmtCacheFull = 1705 + ErrMultiUpdateKeyConflict = 1706 + ErrTableNeedsRebuild = 1707 + WarnOptionBelowLimit = 1708 + ErrIndexColumnTooLong = 1709 + ErrErrorInTriggerBody = 1710 + ErrErrorInUnknownTriggerBody = 1711 + ErrIndexCorrupt = 1712 + ErrUndoRecordTooBig = 1713 + ErrBinlogUnsafeInsertIgnoreSelect = 1714 + ErrBinlogUnsafeInsertSelectUpdate = 1715 + ErrBinlogUnsafeReplaceSelect = 1716 + ErrBinlogUnsafeCreateIgnoreSelect = 1717 + ErrBinlogUnsafeCreateReplaceSelect = 1718 + ErrBinlogUnsafeUpdateIgnore = 1719 + ErrPluginNoUninstall = 1720 + ErrPluginNoInstall = 1721 + ErrBinlogUnsafeWriteAutoincSelect = 1722 + ErrBinlogUnsafeCreateSelectAutoinc = 1723 + ErrBinlogUnsafeInsertTwoKeys = 1724 + ErrTableInFkCheck = 1725 + ErrUnsupportedEngine = 1726 + ErrBinlogUnsafeAutoincNotFirst = 1727 + ErrCannotLoadFromTableV2 = 1728 + ErrMasterDelayValueOutOfRange = 1729 + ErrOnlyFdAndRbrEventsAllowedInBinlogStatement = 1730 + ErrPartitionExchangeDifferentOption = 1731 + ErrPartitionExchangePartTable = 1732 + ErrPartitionExchangeTempTable = 1733 + ErrPartitionInsteadOfSubpartition = 1734 + ErrUnknownPartition = 1735 + ErrTablesDifferentMetadata = 1736 + ErrRowDoesNotMatchPartition = 1737 + ErrBinlogCacheSizeGreaterThanMax = 1738 + ErrWarnIndexNotApplicable = 1739 + ErrPartitionExchangeForeignKey = 1740 + ErrNoSuchKeyValue = 1741 + ErrRplInfoDataTooLong = 1742 + ErrNetworkReadEventChecksumFailure = 1743 + ErrBinlogReadEventChecksumFailure = 1744 + ErrBinlogStmtCacheSizeGreaterThanMax = 1745 + ErrCantUpdateTableInCreateTableSelect = 1746 + ErrPartitionClauseOnNonpartitioned = 1747 + ErrRowDoesNotMatchGivenPartitionSet = 1748 + ErrNoSuchPartitionunused = 1749 + ErrChangeRplInfoRepositoryFailure = 1750 + ErrWarningNotCompleteRollbackWithCreatedTempTable = 1751 + ErrWarningNotCompleteRollbackWithDroppedTempTable = 1752 + ErrMtsFeatureIsNotSupported = 1753 + ErrMtsUpdatedDBsGreaterMax = 1754 + ErrMtsCantParallel = 1755 + ErrMtsInconsistentData = 1756 + ErrFulltextNotSupportedWithPartitioning = 1757 + ErrDaInvalidConditionNumber = 1758 + ErrInsecurePlainText = 1759 + ErrInsecureChangeMaster = 1760 + ErrForeignDuplicateKeyWithChildInfo = 1761 + ErrForeignDuplicateKeyWithoutChildInfo = 1762 + ErrSQLthreadWithSecureSlave = 1763 + ErrTableHasNoFt = 1764 + ErrVariableNotSettableInSfOrTrigger = 1765 + ErrVariableNotSettableInTransaction = 1766 + ErrGtidNextIsNotInGtidNextList = 1767 + ErrCantChangeGtidNextInTransactionWhenGtidNextListIsNull = 1768 + ErrSetStatementCannotInvokeFunction = 1769 + ErrGtidNextCantBeAutomaticIfGtidNextListIsNonNull = 1770 + ErrSkippingLoggedTransaction = 1771 + ErrMalformedGtidSetSpecification = 1772 + ErrMalformedGtidSetEncoding = 1773 + ErrMalformedGtidSpecification = 1774 + ErrGnoExhausted = 1775 + ErrBadSlaveAutoPosition = 1776 + ErrAutoPositionRequiresGtidModeOn = 1777 + ErrCantDoImplicitCommitInTrxWhenGtidNextIsSet = 1778 + ErrGtidMode2Or3RequiresEnforceGtidConsistencyOn = 1779 + ErrGtidModeRequiresBinlog = 1780 + ErrCantSetGtidNextToGtidWhenGtidModeIsOff = 1781 + ErrCantSetGtidNextToAnonymousWhenGtidModeIsOn = 1782 + ErrCantSetGtidNextListToNonNullWhenGtidModeIsOff = 1783 + ErrFoundGtidEventWhenGtidModeIsOff = 1784 + ErrGtidUnsafeNonTransactionalTable = 1785 + ErrGtidUnsafeCreateSelect = 1786 + ErrGtidUnsafeCreateDropTemporaryTableInTransaction = 1787 + ErrGtidModeCanOnlyChangeOneStepAtATime = 1788 + ErrMasterHasPurgedRequiredGtids = 1789 + ErrCantSetGtidNextWhenOwningGtid = 1790 + ErrUnknownExplainFormat = 1791 + ErrCantExecuteInReadOnlyTransaction = 1792 + ErrTooLongTablePartitionComment = 1793 + ErrSlaveConfiguration = 1794 + ErrInnodbFtLimit = 1795 + ErrInnodbNoFtTempTable = 1796 + ErrInnodbFtWrongDocidColumn = 1797 + ErrInnodbFtWrongDocidIndex = 1798 + ErrInnodbOnlineLogTooBig = 1799 + ErrUnknownAlterAlgorithm = 1800 + ErrUnknownAlterLock = 1801 + ErrMtsChangeMasterCantRunWithGaps = 1802 + ErrMtsRecoveryFailure = 1803 + ErrMtsResetWorkers = 1804 + ErrColCountDoesntMatchCorruptedV2 = 1805 + ErrSlaveSilentRetryTransaction = 1806 + ErrDiscardFkChecksRunning = 1807 + ErrTableSchemaMismatch = 1808 + ErrTableInSystemTablespace = 1809 + ErrIoRead = 1810 + ErrIoWrite = 1811 + ErrTablespaceMissing = 1812 + ErrTablespaceExists = 1813 + ErrTablespaceDiscarded = 1814 + ErrInternal = 1815 + ErrInnodbImport = 1816 + ErrInnodbIndexCorrupt = 1817 + ErrInvalidYearColumnLength = 1818 + ErrNotValidPassword = 1819 + ErrMustChangePassword = 1820 + ErrFkNoIndexChild = 1821 + ErrFkNoIndexParent = 1822 + ErrFkFailAddSystem = 1823 + ErrFkCannotOpenParent = 1824 + ErrFkIncorrectOption = 1825 + ErrFkDupName = 1826 + ErrPasswordFormat = 1827 + ErrFkColumnCannotDrop = 1828 + ErrFkColumnCannotDropChild = 1829 + ErrFkColumnNotNull = 1830 + ErrDupIndex = 1831 + ErrFkColumnCannotChange = 1832 + ErrFkColumnCannotChangeChild = 1833 + ErrFkCannotDeleteParent = 1834 + ErrMalformedPacket = 1835 + ErrReadOnlyMode = 1836 + ErrGtidNextTypeUndefinedGroup = 1837 + ErrVariableNotSettableInSp = 1838 + ErrCantSetGtidPurgedWhenGtidModeIsOff = 1839 + ErrCantSetGtidPurgedWhenGtidExecutedIsNotEmpty = 1840 + ErrCantSetGtidPurgedWhenOwnedGtidsIsNotEmpty = 1841 + ErrGtidPurgedWasChanged = 1842 + ErrGtidExecutedWasChanged = 1843 + ErrBinlogStmtModeAndNoReplTables = 1844 + ErrAlterOperationNotSupported = 1845 + ErrAlterOperationNotSupportedReason = 1846 + ErrAlterOperationNotSupportedReasonCopy = 1847 + ErrAlterOperationNotSupportedReasonPartition = 1848 + ErrAlterOperationNotSupportedReasonFkRename = 1849 + ErrAlterOperationNotSupportedReasonColumnType = 1850 + ErrAlterOperationNotSupportedReasonFkCheck = 1851 + ErrAlterOperationNotSupportedReasonIgnore = 1852 + ErrAlterOperationNotSupportedReasonNopk = 1853 + ErrAlterOperationNotSupportedReasonAutoinc = 1854 + ErrAlterOperationNotSupportedReasonHiddenFts = 1855 + ErrAlterOperationNotSupportedReasonChangeFts = 1856 + ErrAlterOperationNotSupportedReasonFts = 1857 + ErrSQLSlaveSkipCounterNotSettableInGtidMode = 1858 + ErrDupUnknownInIndex = 1859 + ErrIdentCausesTooLongPath = 1860 + ErrAlterOperationNotSupportedReasonNotNull = 1861 + ErrMustChangePasswordLogin = 1862 + ErrRowInWrongPartition = 1863 + ErrErrorLast = 1863 + ErrBadGeneratedColumn = 3105 + ErrUnsupportedOnGeneratedColumn = 3106 + ErrGeneratedColumnNonPrior = 3107 + ErrDependentByGeneratedColumn = 3108 + ErrInvalidJSONText = 3140 + ErrInvalidJSONPath = 3143 + ErrInvalidJSONData = 3146 + ErrInvalidJSONPathWildcard = 3149 + ErrInvalidJSONContainsPathType = 3150 + ErrJSONUsedAsKey = 3152 + + // TiDB self-defined errors. + ErrMemExceedThreshold = 8001 + ErrForUpdateCantRetry = 8002 + ErrAdminCheckTable = 8003 + + // TiKV/PD errors. + ErrPDServerTimeout = 9001 + ErrTiKVServerTimeout = 9002 + ErrTiKVServerBusy = 9003 + ErrResolveLockTimeout = 9004 + ErrRegionUnavailable = 9005 + ErrGCTooEarly = 9006 + + ErrTxnTooLarge = 9500 +) diff --git a/vendor/github.com/pingcap/parser/mysql/errname.go b/vendor/github.com/pingcap/parser/mysql/errname.go new file mode 100644 index 0000000000000000000000000000000000000000..2607f95003ab49988a24ba53abd2489d896bff57 --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/errname.go @@ -0,0 +1,907 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +// MySQLErrName maps error code to MySQL error messages. +var MySQLErrName = map[uint16]string{ + ErrHashchk: "hashchk", + ErrNisamchk: "isamchk", + ErrNo: "NO", + ErrYes: "YES", + ErrCantCreateFile: "Can't create file '%-.200s' (errno: %d - %s)", + ErrCantCreateTable: "Can't create table '%-.200s' (errno: %d)", + ErrCantCreateDB: "Can't create database '%-.192s' (errno: %d)", + ErrDBCreateExists: "Can't create database '%-.192s'; database exists", + ErrDBDropExists: "Can't drop database '%-.192s'; database doesn't exist", + ErrDBDropDelete: "Error dropping database (can't delete '%-.192s', errno: %d)", + ErrDBDropRmdir: "Error dropping database (can't rmdir '%-.192s', errno: %d)", + ErrCantDeleteFile: "Error on delete of '%-.192s' (errno: %d - %s)", + ErrCantFindSystemRec: "Can't read record in system table", + ErrCantGetStat: "Can't get status of '%-.200s' (errno: %d - %s)", + ErrCantGetWd: "Can't get working directory (errno: %d - %s)", + ErrCantLock: "Can't lock file (errno: %d - %s)", + ErrCantOpenFile: "Can't open file: '%-.200s' (errno: %d - %s)", + ErrFileNotFound: "Can't find file: '%-.200s' (errno: %d - %s)", + ErrCantReadDir: "Can't read dir of '%-.192s' (errno: %d - %s)", + ErrCantSetWd: "Can't change dir to '%-.192s' (errno: %d - %s)", + ErrCheckread: "Record has changed since last read in table '%-.192s'", + ErrDiskFull: "Disk full (%s); waiting for someone to free some space... (errno: %d - %s)", + ErrDupKey: "Can't write; duplicate key in table '%-.192s'", + ErrErrorOnClose: "Error on close of '%-.192s' (errno: %d - %s)", + ErrErrorOnRead: "Error reading file '%-.200s' (errno: %d - %s)", + ErrErrorOnRename: "Error on rename of '%-.210s' to '%-.210s' (errno: %d - %s)", + ErrErrorOnWrite: "Error writing file '%-.200s' (errno: %d - %s)", + ErrFileUsed: "'%-.192s' is locked against change", + ErrFilsortAbort: "Sort aborted", + ErrFormNotFound: "View '%-.192s' doesn't exist for '%-.192s'", + ErrGetErrno: "Got error %d from storage engine", + ErrIllegalHa: "Table storage engine for '%-.192s' doesn't have this option", + ErrKeyNotFound: "Can't find record in '%-.192s'", + ErrNotFormFile: "Incorrect information in file: '%-.200s'", + ErrNotKeyFile: "Incorrect key file for table '%-.200s'; try to repair it", + ErrOldKeyFile: "Old key file for table '%-.192s'; repair it!", + ErrOpenAsReadonly: "Table '%-.192s' is read only", + ErrOutofMemory: "Out of memory; restart server and try again (needed %d bytes)", + ErrOutOfSortMemory: "Out of sort memory, consider increasing server sort buffer size", + ErrUnexpectedEOF: "Unexpected EOF found when reading file '%-.192s' (errno: %d - %s)", + ErrConCount: "Too many connections", + ErrOutOfResources: "Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space", + ErrBadHost: "Can't get hostname for your address", + ErrHandshake: "Bad handshake", + ErrDBaccessDenied: "Access denied for user '%-.48s'@'%-.64s' to database '%-.192s'", + ErrAccessDenied: "Access denied for user '%-.48s'@'%-.64s' (using password: %s)", + ErrNoDB: "No database selected", + ErrUnknownCom: "Unknown command", + ErrBadNull: "Column '%-.192s' cannot be null", + ErrBadDB: "Unknown database '%-.192s'", + ErrTableExists: "Table '%-.192s' already exists", + ErrBadTable: "Unknown table '%-.100s'", + ErrNonUniq: "Column '%-.192s' in %-.192s is ambiguous", + ErrServerShutdown: "Server shutdown in progress", + ErrBadField: "Unknown column '%-.192s' in '%-.192s'", + ErrFieldNotInGroupBy: "Expression #%d of %s is not in GROUP BY clause and contains nonaggregated column '%s' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by", + ErrWrongGroupField: "Can't group on '%-.192s'", + ErrWrongSumSelect: "Statement has sum functions and columns in same statement", + ErrWrongValueCount: "Column count doesn't match value count", + ErrTooLongIdent: "Identifier name '%-.100s' is too long", + ErrDupFieldName: "Duplicate column name '%-.192s'", + ErrDupKeyName: "Duplicate key name '%-.192s'", + ErrDupEntry: "Duplicate entry '%-.192s' for key %d", + ErrWrongFieldSpec: "Incorrect column specifier for column '%-.192s'", + ErrParse: "%s near '%-.80s' at line %d", + ErrEmptyQuery: "Query was empty", + ErrNonuniqTable: "Not unique table/alias: '%-.192s'", + ErrInvalidDefault: "Invalid default value for '%-.192s'", + ErrMultiplePriKey: "Multiple primary key defined", + ErrTooManyKeys: "Too many keys specified; max %d keys allowed", + ErrTooManyKeyParts: "Too many key parts specified; max %d parts allowed", + ErrTooLongKey: "Specified key was too long; max key length is %d bytes", + ErrKeyColumnDoesNotExits: "Key column '%-.192s' doesn't exist in table", + ErrBlobUsedAsKey: "BLOB column '%-.192s' can't be used in key specification with the used table type", + ErrTooBigFieldlength: "Column length too big for column '%-.192s' (max = %d); use BLOB or TEXT instead", + ErrWrongAutoKey: "Incorrect table definition; there can be only one auto column and it must be defined as a key", + ErrReady: "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d", + ErrNormalShutdown: "%s: Normal shutdown\n", + ErrGotSignal: "%s: Got signal %d. Aborting!\n", + ErrShutdownComplete: "%s: Shutdown complete\n", + ErrForcingClose: "%s: Forcing close of thread %d user: '%-.48s'\n", + ErrIpsock: "Can't create IP socket", + ErrNoSuchIndex: "Table '%-.192s' has no index like the one used in CREATE INDEX; recreate the table", + ErrWrongFieldTerminators: "Field separator argument is not what is expected; check the manual", + ErrBlobsAndNoTerminated: "You can't use fixed rowlength with BLOBs; please use 'fields terminated by'", + ErrTextFileNotReadable: "The file '%-.128s' must be in the database directory or be readable by all", + ErrFileExists: "File '%-.200s' already exists", + ErrLoadInfo: "Records: %d Deleted: %d Skipped: %d Warnings: %d", + ErrAlterInfo: "Records: %d Duplicates: %d", + ErrWrongSubKey: "Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys", + ErrCantRemoveAllFields: "You can't delete all columns with ALTER TABLE; use DROP TABLE instead", + ErrCantDropFieldOrKey: "Can't DROP '%-.192s'; check that column/key exists", + ErrInsertInfo: "Records: %d Duplicates: %d Warnings: %d", + ErrUpdateTableUsed: "You can't specify target table '%-.192s' for update in FROM clause", + ErrNoSuchThread: "Unknown thread id: %d", + ErrKillDenied: "You are not owner of thread %d", + ErrNoTablesUsed: "No tables used", + ErrTooBigSet: "Too many strings for column %-.192s and SET", + ErrNoUniqueLogFile: "Can't generate a unique log-filename %-.200s.(1-999)\n", + ErrTableNotLockedForWrite: "Table '%-.192s' was locked with a READ lock and can't be updated", + ErrTableNotLocked: "Table '%-.192s' was not locked with LOCK TABLES", + ErrBlobCantHaveDefault: "BLOB/TEXT/JSON column '%-.192s' can't have a default value", + ErrWrongDBName: "Incorrect database name '%-.100s'", + ErrWrongTableName: "Incorrect table name '%-.100s'", + ErrTooBigSelect: "The SELECT would examine more than MAXJOINSIZE rows; check your WHERE and use SET SQLBIGSELECTS=1 or SET MAXJOINSIZE=# if the SELECT is okay", + ErrUnknown: "Unknown error", + ErrUnknownProcedure: "Unknown procedure '%-.192s'", + ErrWrongParamcountToProcedure: "Incorrect parameter count to procedure '%-.192s'", + ErrWrongParametersToProcedure: "Incorrect parameters to procedure '%-.192s'", + ErrUnknownTable: "Unknown table '%-.192s' in %-.32s", + ErrFieldSpecifiedTwice: "Column '%-.192s' specified twice", + ErrInvalidGroupFuncUse: "Invalid use of group function", + ErrUnsupportedExtension: "Table '%-.192s' uses an extension that doesn't exist in this MySQL version", + ErrTableMustHaveColumns: "A table must have at least 1 column", + ErrRecordFileFull: "The table '%-.192s' is full", + ErrUnknownCharacterSet: "Unknown character set: '%-.64s'", + ErrTooManyTables: "Too many tables; MySQL can only use %d tables in a join", + ErrTooManyFields: "Too many columns", + ErrTooBigRowsize: "Row size too large. The maximum row size for the used table type, not counting BLOBs, is %d. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs", + ErrStackOverrun: "Thread stack overrun: Used: %d of a %d stack. Use 'mysqld --threadStack=#' to specify a bigger stack if needed", + ErrWrongOuterJoin: "Cross dependency found in OUTER JOIN; examine your ON conditions", + ErrNullColumnInIndex: "Table handler doesn't support NULL in given index. Please change column '%-.192s' to be NOT NULL or use another handler", + ErrCantFindUdf: "Can't load function '%-.192s'", + ErrCantInitializeUdf: "Can't initialize function '%-.192s'; %-.80s", + ErrUdfNoPaths: "No paths allowed for shared library", + ErrUdfExists: "Function '%-.192s' already exists", + ErrCantOpenLibrary: "Can't open shared library '%-.192s' (errno: %d %-.128s)", + ErrCantFindDlEntry: "Can't find symbol '%-.128s' in library", + ErrFunctionNotDefined: "Function '%-.192s' is not defined", + ErrHostIsBlocked: "Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'", + ErrHostNotPrivileged: "Host '%-.64s' is not allowed to connect to this MySQL server", + ErrPasswordAnonymousUser: "You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords", + ErrPasswordNotAllowed: "You must have privileges to update tables in the mysql database to be able to change passwords for others", + ErrPasswordNoMatch: "Can't find any matching row in the user table", + ErrUpdateInfo: "Rows matched: %d Changed: %d Warnings: %d", + ErrCantCreateThread: "Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug", + ErrWrongValueCountOnRow: "Column count doesn't match value count at row %d", + ErrCantReopenTable: "Can't reopen table: '%-.192s'", + ErrInvalidUseOfNull: "Invalid use of NULL value", + ErrRegexp: "Got error '%-.64s' from regexp", + ErrMixOfGroupFuncAndFields: "Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause", + ErrNonexistingGrant: "There is no such grant defined for user '%-.48s' on host '%-.64s'", + ErrTableaccessDenied: "%-.128s command denied to user '%-.48s'@'%-.64s' for table '%-.64s'", + ErrColumnaccessDenied: "%-.16s command denied to user '%-.48s'@'%-.64s' for column '%-.192s' in table '%-.192s'", + ErrIllegalGrantForTable: "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used", + ErrGrantWrongHostOrUser: "The host or user argument to GRANT is too long", + ErrNoSuchTable: "Table '%-.192s.%-.192s' doesn't exist", + ErrNonexistingTableGrant: "There is no such grant defined for user '%-.48s' on host '%-.64s' on table '%-.192s'", + ErrNotAllowedCommand: "The used command is not allowed with this MySQL version", + ErrSyntax: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use", + ErrDelayedCantChangeLock: "Delayed insert thread couldn't get requested lock for table %-.192s", + ErrTooManyDelayedThreads: "Too many delayed threads in use", + ErrAbortingConnection: "Aborted connection %d to db: '%-.192s' user: '%-.48s' (%-.64s)", + ErrNetPacketTooLarge: "Got a packet bigger than 'maxAllowedPacket' bytes", + ErrNetReadErrorFromPipe: "Got a read error from the connection pipe", + ErrNetFcntl: "Got an error from fcntl()", + ErrNetPacketsOutOfOrder: "Got packets out of order", + ErrNetUncompress: "Couldn't uncompress communication packet", + ErrNetRead: "Got an error reading communication packets", + ErrNetReadInterrupted: "Got timeout reading communication packets", + ErrNetErrorOnWrite: "Got an error writing communication packets", + ErrNetWriteInterrupted: "Got timeout writing communication packets", + ErrTooLongString: "Result string is longer than 'maxAllowedPacket' bytes", + ErrTableCantHandleBlob: "The used table type doesn't support BLOB/TEXT columns", + ErrTableCantHandleAutoIncrement: "The used table type doesn't support AUTOINCREMENT columns", + ErrDelayedInsertTableLocked: "INSERT DELAYED can't be used with table '%-.192s' because it is locked with LOCK TABLES", + ErrWrongColumnName: "Incorrect column name '%-.100s'", + ErrWrongKeyColumn: "The used storage engine can't index column '%-.192s'", + ErrWrongMrgTable: "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist", + ErrDupUnique: "Can't write, because of unique constraint, to table '%-.192s'", + ErrBlobKeyWithoutLength: "BLOB/TEXT column '%-.192s' used in key specification without a key length", + ErrPrimaryCantHaveNull: "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead", + ErrTooManyRows: "Result consisted of more than one row", + ErrRequiresPrimaryKey: "This table type requires a primary key", + ErrNoRaidCompiled: "This version of MySQL is not compiled with RAID support", + ErrUpdateWithoutKeyInSafeMode: "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column", + ErrKeyDoesNotExist: "Key '%-.192s' doesn't exist in table '%-.192s'", + ErrCheckNoSuchTable: "Can't open table", + ErrCheckNotImplemented: "The storage engine for the table doesn't support %s", + ErrCantDoThisDuringAnTransaction: "You are not allowed to execute this command in a transaction", + ErrErrorDuringCommit: "Got error %d during COMMIT", + ErrErrorDuringRollback: "Got error %d during ROLLBACK", + ErrErrorDuringFlushLogs: "Got error %d during FLUSHLOGS", + ErrErrorDuringCheckpoint: "Got error %d during CHECKPOINT", + ErrNewAbortingConnection: "Aborted connection %d to db: '%-.192s' user: '%-.48s' host: '%-.64s' (%-.64s)", + ErrDumpNotImplemented: "The storage engine for the table does not support binary table dump", + ErrFlushMasterBinlogClosed: "Binlog closed, cannot RESET MASTER", + ErrIndexRebuild: "Failed rebuilding the index of dumped table '%-.192s'", + ErrMaster: "Error from master: '%-.64s'", + ErrMasterNetRead: "Net error reading from master", + ErrMasterNetWrite: "Net error writing to master", + ErrFtMatchingKeyNotFound: "Can't find FULLTEXT index matching the column list", + ErrLockOrActiveTransaction: "Can't execute the given command because you have active locked tables or an active transaction", + ErrUnknownSystemVariable: "Unknown system variable '%-.64s'", + ErrCrashedOnUsage: "Table '%-.192s' is marked as crashed and should be repaired", + ErrCrashedOnRepair: "Table '%-.192s' is marked as crashed and last (automatic?) repair failed", + ErrWarningNotCompleteRollback: "Some non-transactional changed tables couldn't be rolled back", + ErrTransCacheFull: "Multi-statement transaction required more than 'maxBinlogCacheSize' bytes of storage; increase this mysqld variable and try again", + ErrSlaveMustStop: "This operation cannot be performed with a running slave; run STOP SLAVE first", + ErrSlaveNotRunning: "This operation requires a running slave; configure slave and do START SLAVE", + ErrBadSlave: "The server is not configured as slave; fix in config file or with CHANGE MASTER TO", + ErrMasterInfo: "Could not initialize master info structure; more error messages can be found in the MySQL error log", + ErrSlaveThread: "Could not create slave thread; check system resources", + ErrTooManyUserConnections: "User %-.64s already has more than 'maxUserConnections' active connections", + ErrSetConstantsOnly: "You may only use constant expressions with SET", + ErrLockWaitTimeout: "Lock wait timeout exceeded; try restarting transaction", + ErrLockTableFull: "The total number of locks exceeds the lock table size", + ErrReadOnlyTransaction: "Update locks cannot be acquired during a READ UNCOMMITTED transaction", + ErrDropDBWithReadLock: "DROP DATABASE not allowed while thread is holding global read lock", + ErrCreateDBWithReadLock: "CREATE DATABASE not allowed while thread is holding global read lock", + ErrWrongArguments: "Incorrect arguments to %s", + ErrNoPermissionToCreateUser: "'%-.48s'@'%-.64s' is not allowed to create new users", + ErrUnionTablesInDifferentDir: "Incorrect table definition; all MERGE tables must be in the same database", + ErrLockDeadlock: "Deadlock found when trying to get lock; try restarting transaction", + ErrTableCantHandleFt: "The used table type doesn't support FULLTEXT indexes", + ErrCannotAddForeign: "Cannot add foreign key constraint", + ErrNoReferencedRow: "Cannot add or update a child row: a foreign key constraint fails", + ErrRowIsReferenced: "Cannot delete or update a parent row: a foreign key constraint fails", + ErrConnectToMaster: "Error connecting to master: %-.128s", + ErrQueryOnMaster: "Error running query on master: %-.128s", + ErrErrorWhenExecutingCommand: "Error when executing command %s: %-.128s", + ErrWrongUsage: "Incorrect usage of %s and %s", + ErrWrongNumberOfColumnsInSelect: "The used SELECT statements have a different number of columns", + ErrCantUpdateWithReadlock: "Can't execute the query because you have a conflicting read lock", + ErrMixingNotAllowed: "Mixing of transactional and non-transactional tables is disabled", + ErrDupArgument: "Option '%s' used twice in statement", + ErrUserLimitReached: "User '%-.64s' has exceeded the '%s' resource (current value: %d)", + ErrSpecificAccessDenied: "Access denied; you need (at least one of) the %-.128s privilege(s) for this operation", + ErrLocalVariable: "Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL", + ErrGlobalVariable: "Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL", + ErrNoDefault: "Variable '%-.64s' doesn't have a default value", + ErrWrongValueForVar: "Variable '%-.64s' can't be set to the value of '%-.200s'", + ErrWrongTypeForVar: "Incorrect argument type to variable '%-.64s'", + ErrVarCantBeRead: "Variable '%-.64s' can only be set, not read", + ErrCantUseOptionHere: "Incorrect usage/placement of '%s'", + ErrNotSupportedYet: "This version of MySQL doesn't yet support '%s'", + ErrMasterFatalErrorReadingBinlog: "Got fatal error %d from master when reading data from binary log: '%-.320s'", + ErrSlaveIgnoredTable: "Slave SQL thread ignored the query because of replicate-*-table rules", + ErrIncorrectGlobalLocalVar: "Variable '%-.192s' is a %s variable", + ErrWrongFkDef: "Incorrect foreign key definition for '%-.192s': %s", + ErrKeyRefDoNotMatchTableRef: "Key reference and table reference don't match", + ErrOperandColumns: "Operand should contain %d column(s)", + ErrSubqueryNo1Row: "Subquery returns more than 1 row", + ErrUnknownStmtHandler: "Unknown prepared statement handler (%.*s) given to %s", + ErrCorruptHelpDB: "Help database is corrupt or does not exist", + ErrCyclicReference: "Cyclic reference on subqueries", + ErrAutoConvert: "Converting column '%s' from %s to %s", + ErrIllegalReference: "Reference '%-.64s' not supported (%s)", + ErrDerivedMustHaveAlias: "Every derived table must have its own alias", + ErrSelectReduced: "Select %d was reduced during optimization", + ErrTablenameNotAllowedHere: "Table '%-.192s' from one of the SELECTs cannot be used in %-.32s", + ErrNotSupportedAuthMode: "Client does not support authentication protocol requested by server; consider upgrading MySQL client", + ErrSpatialCantHaveNull: "All parts of a SPATIAL index must be NOT NULL", + ErrCollationCharsetMismatch: "COLLATION '%s' is not valid for CHARACTER SET '%s'", + ErrSlaveWasRunning: "Slave is already running", + ErrSlaveWasNotRunning: "Slave already has been stopped", + ErrTooBigForUncompress: "Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)", + ErrZlibZMem: "ZLIB: Not enough memory", + ErrZlibZBuf: "ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)", + ErrZlibZData: "ZLIB: Input data corrupted", + ErrCutValueGroupConcat: "Some rows were cut by GROUPCONCAT(%s)", + ErrWarnTooFewRecords: "Row %d doesn't contain data for all columns", + ErrWarnTooManyRecords: "Row %d was truncated; it contained more data than there were input columns", + ErrWarnNullToNotnull: "Column set to default value; NULL supplied to NOT NULL column '%s' at row %d", + ErrWarnDataOutOfRange: "Out of range value for column '%s' at row %d", + WarnDataTruncated: "Data truncated for column '%s' at row %d", + ErrWarnUsingOtherHandler: "Using storage engine %s for table '%s'", + ErrCantAggregate2collations: "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", + ErrDropUser: "Cannot drop one or more of the requested users", + ErrRevokeGrants: "Can't revoke all privileges for one or more of the requested users", + ErrCantAggregate3collations: "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", + ErrCantAggregateNcollations: "Illegal mix of collations for operation '%s'", + ErrVariableIsNotStruct: "Variable '%-.64s' is not a variable component (can't be used as XXXX.variableName)", + ErrUnknownCollation: "Unknown collation: '%-.64s'", + ErrSlaveIgnoredSslParams: "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started", + ErrServerIsInSecureAuthMode: "Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format", + ErrWarnFieldResolved: "Field or reference '%-.192s%s%-.192s%s%-.192s' of SELECT #%d was resolved in SELECT #%d", + ErrBadSlaveUntilCond: "Incorrect parameter or combination of parameters for START SLAVE UNTIL", + ErrMissingSkipSlave: "It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart", + ErrUntilCondIgnored: "SQL thread is not to be started so UNTIL options are ignored", + ErrWrongNameForIndex: "Incorrect index name '%-.100s'", + ErrWrongNameForCatalog: "Incorrect catalog name '%-.100s'", + ErrWarnQcResize: "Query cache failed to set size %d; new query cache size is %d", + ErrBadFtColumn: "Column '%-.192s' cannot be part of FULLTEXT index", + ErrUnknownKeyCache: "Unknown key cache '%-.100s'", + ErrWarnHostnameWontWork: "MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work", + ErrUnknownStorageEngine: "Unknown storage engine '%s'", + ErrWarnDeprecatedSyntax: "'%s' is deprecated and will be removed in a future release. Please use %s instead", + ErrNonUpdatableTable: "The target table %-.100s of the %s is not updatable", + ErrFeatureDisabled: "The '%s' feature is disabled; you need MySQL built with '%s' to have it working", + ErrOptionPreventsStatement: "The MySQL server is running with the %s option so it cannot execute this statement", + ErrDuplicatedValueInType: "Column '%-.100s' has duplicated value '%-.64s' in %s", + ErrTruncatedWrongValue: "Truncated incorrect %-.64s value: '%-.128s'", + ErrTooMuchAutoTimestampCols: "Incorrect table definition; there can be only one TIMESTAMP column with CURRENTTIMESTAMP in DEFAULT or ON UPDATE clause", + ErrInvalidOnUpdate: "Invalid ON UPDATE clause for '%-.192s' column", + ErrUnsupportedPs: "This command is not supported in the prepared statement protocol yet", + ErrGetErrmsg: "Got error %d '%-.100s' from %s", + ErrGetTemporaryErrmsg: "Got temporary error %d '%-.100s' from %s", + ErrUnknownTimeZone: "Unknown or incorrect time zone: '%-.64s'", + ErrWarnInvalidTimestamp: "Invalid TIMESTAMP value in column '%s' at row %d", + ErrInvalidCharacterString: "Invalid %s character string: '%.64s'", + ErrWarnAllowedPacketOverflowed: "Result of %s() was larger than max_allowed_packet (%d) - truncated", + ErrConflictingDeclarations: "Conflicting declarations: '%s%s' and '%s%s'", + ErrSpNoRecursiveCreate: "Can't create a %s from within another stored routine", + ErrSpAlreadyExists: "%s %s already exists", + ErrSpDoesNotExist: "%s %s does not exist", + ErrSpDropFailed: "Failed to DROP %s %s", + ErrSpStoreFailed: "Failed to CREATE %s %s", + ErrSpLilabelMismatch: "%s with no matching label: %s", + ErrSpLabelRedefine: "Redefining label %s", + ErrSpLabelMismatch: "End-label %s without match", + ErrSpUninitVar: "Referring to uninitialized variable %s", + ErrSpBadselect: "PROCEDURE %s can't return a result set in the given context", + ErrSpBadreturn: "RETURN is only allowed in a FUNCTION", + ErrSpBadstatement: "%s is not allowed in stored procedures", + ErrUpdateLogDeprecatedIgnored: "The update log is deprecated and replaced by the binary log; SET SQLLOGUPDATE has been ignored.", + ErrUpdateLogDeprecatedTranslated: "The update log is deprecated and replaced by the binary log; SET SQLLOGUPDATE has been translated to SET SQLLOGBIN.", + ErrQueryInterrupted: "Query execution was interrupted", + ErrSpWrongNoOfArgs: "Incorrect number of arguments for %s %s; expected %d, got %d", + ErrSpCondMismatch: "Undefined CONDITION: %s", + ErrSpNoreturn: "No RETURN found in FUNCTION %s", + ErrSpNoreturnend: "FUNCTION %s ended without RETURN", + ErrSpBadCursorQuery: "Cursor statement must be a SELECT", + ErrSpBadCursorSelect: "Cursor SELECT must not have INTO", + ErrSpCursorMismatch: "Undefined CURSOR: %s", + ErrSpCursorAlreadyOpen: "Cursor is already open", + ErrSpCursorNotOpen: "Cursor is not open", + ErrSpUndeclaredVar: "Undeclared variable: %s", + ErrSpWrongNoOfFetchArgs: "Incorrect number of FETCH variables", + ErrSpFetchNoData: "No data - zero rows fetched, selected, or processed", + ErrSpDupParam: "Duplicate parameter: %s", + ErrSpDupVar: "Duplicate variable: %s", + ErrSpDupCond: "Duplicate condition: %s", + ErrSpDupCurs: "Duplicate cursor: %s", + ErrSpCantAlter: "Failed to ALTER %s %s", + ErrSpSubselectNyi: "Subquery value not supported", + ErrStmtNotAllowedInSfOrTrg: "%s is not allowed in stored function or trigger", + ErrSpVarcondAfterCurshndlr: "Variable or condition declaration after cursor or handler declaration", + ErrSpCursorAfterHandler: "Cursor declaration after handler declaration", + ErrSpCaseNotFound: "Case not found for CASE statement", + ErrFparserTooBigFile: "Configuration file '%-.192s' is too big", + ErrFparserBadHeader: "Malformed file type header in file '%-.192s'", + ErrFparserEOFInComment: "Unexpected end of file while parsing comment '%-.200s'", + ErrFparserErrorInParameter: "Error while parsing parameter '%-.192s' (line: '%-.192s')", + ErrFparserEOFInUnknownParameter: "Unexpected end of file while skipping unknown parameter '%-.192s'", + ErrViewNoExplain: "EXPLAIN/SHOW can not be issued; lacking privileges for underlying table", + ErrFrmUnknownType: "File '%-.192s' has unknown type '%-.64s' in its header", + ErrWrongObject: "'%-.192s.%-.192s' is not %s", + ErrNonupdateableColumn: "Column '%-.192s' is not updatable", + ErrViewSelectDerived: "View's SELECT contains a subquery in the FROM clause", + ErrViewSelectClause: "View's SELECT contains a '%s' clause", + ErrViewSelectVariable: "View's SELECT contains a variable or parameter", + ErrViewSelectTmptable: "View's SELECT refers to a temporary table '%-.192s'", + ErrViewWrongList: "View's SELECT and view's field list have different column counts", + ErrWarnViewMerge: "View merge algorithm can't be used here for now (assumed undefined algorithm)", + ErrWarnViewWithoutKey: "View being updated does not have complete key of underlying table in it", + ErrViewInvalid: "View '%-.192s.%-.192s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them", + ErrSpNoDropSp: "Can't drop or alter a %s from within another stored routine", + ErrSpGotoInHndlr: "GOTO is not allowed in a stored procedure handler", + ErrTrgAlreadyExists: "Trigger already exists", + ErrTrgDoesNotExist: "Trigger does not exist", + ErrTrgOnViewOrTempTable: "Trigger's '%-.192s' is view or temporary table", + ErrTrgCantChangeRow: "Updating of %s row is not allowed in %strigger", + ErrTrgNoSuchRowInTrg: "There is no %s row in %s trigger", + ErrNoDefaultForField: "Field '%-.192s' doesn't have a default value", + ErrDivisionByZero: "Division by 0", + ErrTruncatedWrongValueForField: "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %d", + ErrIllegalValueForType: "Illegal %s '%-.192s' value found during parsing", + ErrViewNonupdCheck: "CHECK OPTION on non-updatable view '%-.192s.%-.192s'", + ErrViewCheckFailed: "CHECK OPTION failed '%-.192s.%-.192s'", + ErrProcaccessDenied: "%-.16s command denied to user '%-.48s'@'%-.64s' for routine '%-.192s'", + ErrRelayLogFail: "Failed purging old relay logs: %s", + ErrPasswdLength: "Password hash should be a %d-digit hexadecimal number", + ErrUnknownTargetBinlog: "Target log not found in binlog index", + ErrIoErrLogIndexRead: "I/O error reading log index file", + ErrBinlogPurgeProhibited: "Server configuration does not permit binlog purge", + ErrFseekFail: "Failed on fseek()", + ErrBinlogPurgeFatalErr: "Fatal error during log purge", + ErrLogInUse: "A purgeable log is in use, will not purge", + ErrLogPurgeUnknownErr: "Unknown error during log purge", + ErrRelayLogInit: "Failed initializing relay log position: %s", + ErrNoBinaryLogging: "You are not using binary logging", + ErrReservedSyntax: "The '%-.64s' syntax is reserved for purposes internal to the MySQL server", + ErrWsasFailed: "WSAStartup Failed", + ErrDiffGroupsProc: "Can't handle procedures with different groups yet", + ErrNoGroupForProc: "Select must have a group with this procedure", + ErrOrderWithProc: "Can't use ORDER clause with this procedure", + ErrLoggingProhibitChangingOf: "Binary logging and replication forbid changing the global server %s", + ErrNoFileMapping: "Can't map file: %-.200s, errno: %d", + ErrWrongMagic: "Wrong magic in %-.64s", + ErrPsManyParam: "Prepared statement contains too many placeholders", + ErrKeyPart0: "Key part '%-.192s' length cannot be 0", + ErrViewChecksum: "View text checksum failed", + ErrViewMultiupdate: "Can not modify more than one base table through a join view '%-.192s.%-.192s'", + ErrViewNoInsertFieldList: "Can not insert into join view '%-.192s.%-.192s' without fields list", + ErrViewDeleteMergeView: "Can not delete from join view '%-.192s.%-.192s'", + ErrCannotUser: "Operation %s failed for %.256s", + ErrXaerNota: "XAERNOTA: Unknown XID", + ErrXaerInval: "XAERINVAL: Invalid arguments (or unsupported command)", + ErrXaerRmfail: "XAERRMFAIL: The command cannot be executed when global transaction is in the %.64s state", + ErrXaerOutside: "XAEROUTSIDE: Some work is done outside global transaction", + ErrXaerRmerr: "XAERRMERR: Fatal error occurred in the transaction branch - check your data for consistency", + ErrXaRbrollback: "XARBROLLBACK: Transaction branch was rolled back", + ErrNonexistingProcGrant: "There is no such grant defined for user '%-.48s' on host '%-.64s' on routine '%-.192s'", + ErrProcAutoGrantFail: "Failed to grant EXECUTE and ALTER ROUTINE privileges", + ErrProcAutoRevokeFail: "Failed to revoke all privileges to dropped routine", + ErrDataTooLong: "Data too long for column '%s' at row %d", + ErrSpBadSQLstate: "Bad SQLSTATE: '%s'", + ErrStartup: "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s", + ErrLoadFromFixedSizeRowsToVar: "Can't load value from file with fixed size rows to variable", + ErrCantCreateUserWithGrant: "You are not allowed to create a user with GRANT", + ErrWrongValueForType: "Incorrect %-.32s value: '%-.128s' for function %-.32s", + ErrTableDefChanged: "Table definition has changed, please retry transaction", + ErrSpDupHandler: "Duplicate handler declared in the same block", + ErrSpNotVarArg: "OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger", + ErrSpNoRetset: "Not allowed to return a result set from a %s", + ErrCantCreateGeometryObject: "Cannot get geometry object from data you send to the GEOMETRY field", + ErrFailedRoutineBreakBinlog: "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes", + ErrBinlogUnsafeRoutine: "This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe logBinTrustFunctionCreators variable)", + ErrBinlogCreateRoutineNeedSuper: "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe logBinTrustFunctionCreators variable)", + ErrExecStmtWithOpenCursor: "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it.", + ErrStmtHasNoOpenCursor: "The statement (%d) has no open cursor.", + ErrCommitNotAllowedInSfOrTrg: "Explicit or implicit commit is not allowed in stored function or trigger.", + ErrNoDefaultForViewField: "Field of view '%-.192s.%-.192s' underlying table doesn't have a default value", + ErrSpNoRecursion: "Recursive stored functions and triggers are not allowed.", + ErrTooBigScale: "Too big scale %d specified for column '%-.192s'. Maximum is %d.", + ErrTooBigPrecision: "Too big precision %d specified for column '%-.192s'. Maximum is %d.", + ErrMBiggerThanD: "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%-.192s').", + ErrWrongLockOfSystemTable: "You can't combine write-locking of system tables with other tables or lock types", + ErrConnectToForeignDataSource: "Unable to connect to foreign data source: %.64s", + ErrQueryOnForeignDataSource: "There was a problem processing the query on the foreign data source. Data source : %-.64s", + ErrForeignDataSourceDoesntExist: "The foreign data source you are trying to reference does not exist. Data source : %-.64s", + ErrForeignDataStringInvalidCantCreate: "Can't create federated table. The data source connection string '%-.64s' is not in the correct format", + ErrForeignDataStringInvalid: "The data source connection string '%-.64s' is not in the correct format", + ErrCantCreateFederatedTable: "Can't create federated table. Foreign data src : %-.64s", + ErrTrgInWrongSchema: "Trigger in wrong schema", + ErrStackOverrunNeedMore: "Thread stack overrun: %d bytes used of a %d byte stack, and %d bytes needed. Use 'mysqld --threadStack=#' to specify a bigger stack.", + ErrTooLongBody: "Routine body for '%-.100s' is too long", + ErrWarnCantDropDefaultKeycache: "Cannot drop default keycache", + ErrTooBigDisplaywidth: "Display width out of range for column '%-.192s' (max = %d)", + ErrXaerDupid: "XAERDUPID: The XID already exists", + ErrDatetimeFunctionOverflow: "Datetime function: %-.32s field overflow", + ErrCantUpdateUsedTableInSfOrTrg: "Can't update table '%-.192s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.", + ErrViewPreventUpdate: "The definition of table '%-.192s' prevents operation %.192s on table '%-.192s'.", + ErrPsNoRecursion: "The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner", + ErrSpCantSetAutocommit: "Not allowed to set autocommit from a stored function or trigger", + ErrMalformedDefiner: "Definer is not fully qualified", + ErrViewFrmNoUser: "View '%-.192s'.'%-.192s' has no definer information (old table format). Current user is used as definer. Please recreate the view!", + ErrViewOtherUser: "You need the SUPER privilege for creation view with '%-.192s'@'%-.192s' definer", + ErrNoSuchUser: "The user specified as a definer ('%-.64s'@'%-.64s') does not exist", + ErrForbidSchemaChange: "Changing schema from '%-.192s' to '%-.192s' is not allowed.", + ErrRowIsReferenced2: "Cannot delete or update a parent row: a foreign key constraint fails (%.192s)", + ErrNoReferencedRow2: "Cannot add or update a child row: a foreign key constraint fails (%.192s)", + ErrSpBadVarShadow: "Variable '%-.64s' must be quoted with `...`, or renamed", + ErrTrgNoDefiner: "No definer attribute for trigger '%-.192s'.'%-.192s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.", + ErrOldFileFormat: "'%-.192s' has an old format, you should re-create the '%s' object(s)", + ErrSpRecursionLimit: "Recursive limit %d (as set by the maxSpRecursionDepth variable) was exceeded for routine %.192s", + ErrSpProcTableCorrupt: "Failed to load routine %-.192s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)", + ErrSpWrongName: "Incorrect routine name '%-.192s'", + ErrTableNeedsUpgrade: "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\"", + ErrSpNoAggregate: "AGGREGATE is not supported for stored functions", + ErrMaxPreparedStmtCountReached: "Can't create more than maxPreparedStmtCount statements (current value: %d)", + ErrViewRecursive: "`%-.192s`.`%-.192s` contains view recursion", + ErrNonGroupingFieldUsed: "Non-grouping field '%-.192s' is used in %-.64s clause", + ErrTableCantHandleSpkeys: "The used table type doesn't support SPATIAL indexes", + ErrNoTriggersOnSystemSchema: "Triggers can not be created on system tables", + ErrRemovedSpaces: "Leading spaces are removed from name '%s'", + ErrAutoincReadFailed: "Failed to read auto-increment value from storage engine", + ErrUsername: "user name", + ErrHostname: "host name", + ErrWrongStringLength: "String '%-.70s' is too long for %s (should be no longer than %d)", + ErrNonInsertableTable: "The target table %-.100s of the %s is not insertable-into", + ErrAdminWrongMrgTable: "Table '%-.64s' is differently defined or of non-MyISAM type or doesn't exist", + ErrTooHighLevelOfNestingForSelect: "Too high level of nesting for select", + ErrNameBecomesEmpty: "Name '%-.64s' has become ''", + ErrAmbiguousFieldTerm: "First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY", + ErrForeignServerExists: "The foreign server, %s, you are trying to create already exists.", + ErrForeignServerDoesntExist: "The foreign server name you are trying to reference does not exist. Data source : %-.64s", + ErrIllegalHaCreateOption: "Table storage engine '%-.64s' does not support the create option '%.64s'", + ErrPartitionRequiresValues: "Syntax : %-.64s PARTITIONING requires definition of VALUES %-.64s for each partition", + ErrPartitionWrongValues: "Only %-.64s PARTITIONING can use VALUES %-.64s in partition definition", + ErrPartitionMaxvalue: "MAXVALUE can only be used in last partition definition", + ErrPartitionSubpartition: "Subpartitions can only be hash partitions and by key", + ErrPartitionSubpartMix: "Must define subpartitions on all partitions if on one partition", + ErrPartitionWrongNoPart: "Wrong number of partitions defined, mismatch with previous setting", + ErrPartitionWrongNoSubpart: "Wrong number of subpartitions defined, mismatch with previous setting", + ErrWrongExprInPartitionFunc: "Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed", + ErrNoConstExprInRangeOrList: "Expression in RANGE/LIST VALUES must be constant", + ErrFieldNotFoundPart: "Field in list of fields for partition function not found in table", + ErrListOfFieldsOnlyInHash: "List of fields is only allowed in KEY partitions", + ErrInconsistentPartitionInfo: "The partition info in the frm file is not consistent with what can be written into the frm file", + ErrPartitionFuncNotAllowed: "The %-.192s function returns the wrong type", + ErrPartitionsMustBeDefined: "For %-.64s partitions each partition must be defined", + ErrRangeNotIncreasing: "VALUES LESS THAN value must be strictly increasing for each partition", + ErrInconsistentTypeOfFunctions: "VALUES value must be of same type as partition function", + ErrMultipleDefConstInListPart: "Multiple definition of same constant in list partitioning", + ErrPartitionEntry: "Partitioning can not be used stand-alone in query", + ErrMixHandler: "The mix of handlers in the partitions is not allowed in this version of MySQL", + ErrPartitionNotDefined: "For the partitioned engine it is necessary to define all %-.64s", + ErrTooManyPartitions: "Too many partitions (including subpartitions) were defined", + ErrSubpartition: "It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning", + ErrCantCreateHandlerFile: "Failed to create specific handler file", + ErrBlobFieldInPartFunc: "A BLOB field is not allowed in partition function", + ErrUniqueKeyNeedAllFieldsInPf: "A %-.192s must include all columns in the table's partitioning function", + ErrNoParts: "Number of %-.64s = 0 is not an allowed value", + ErrPartitionMgmtOnNonpartitioned: "Partition management on a not partitioned table is not possible", + ErrForeignKeyOnPartitioned: "Foreign key clause is not yet supported in conjunction with partitioning", + ErrDropPartitionNonExistent: "Error in list of partitions to %-.64s", + ErrDropLastPartition: "Cannot remove all partitions, use DROP TABLE instead", + ErrCoalesceOnlyOnHashPartition: "COALESCE PARTITION can only be used on HASH/KEY partitions", + ErrReorgHashOnlyOnSameNo: "REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers", + ErrReorgNoParam: "REORGANIZE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs", + ErrOnlyOnRangeListPartition: "%-.64s PARTITION can only be used on RANGE/LIST partitions", + ErrAddPartitionSubpart: "Trying to Add partition(s) with wrong number of subpartitions", + ErrAddPartitionNoNewPartition: "At least one partition must be added", + ErrCoalescePartitionNoPartition: "At least one partition must be coalesced", + ErrReorgPartitionNotExist: "More partitions to reorganize than there are partitions", + ErrSameNamePartition: "Duplicate partition name %-.192s", + ErrNoBinlog: "It is not allowed to shut off binlog on this command", + ErrConsecutiveReorgPartitions: "When reorganizing a set of partitions they must be in consecutive order", + ErrReorgOutsideRange: "Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range", + ErrPartitionFunctionFailure: "Partition function not supported in this version for this handler", + ErrPartState: "Partition state cannot be defined from CREATE/ALTER TABLE", + ErrLimitedPartRange: "The %-.64s handler only supports 32 bit integers in VALUES", + ErrPluginIsNotLoaded: "Plugin '%-.192s' is not loaded", + ErrWrongValue: "Incorrect %-.32s value: '%-.128s'", + ErrNoPartitionForGivenValue: "Table has no partition for value %-.64s", + ErrFilegroupOptionOnlyOnce: "It is not allowed to specify %s more than once", + ErrCreateFilegroupFailed: "Failed to create %s", + ErrDropFilegroupFailed: "Failed to drop %s", + ErrTablespaceAutoExtend: "The handler doesn't support autoextend of tablespaces", + ErrWrongSizeNumber: "A size parameter was incorrectly specified, either number or on the form 10M", + ErrSizeOverflow: "The size number was correct but we don't allow the digit part to be more than 2 billion", + ErrAlterFilegroupFailed: "Failed to alter: %s", + ErrBinlogRowLoggingFailed: "Writing one row to the row-based binary log failed", + ErrBinlogRowWrongTableDef: "Table definition on master and slave does not match: %s", + ErrBinlogRowRbrToSbr: "Slave running with --log-slave-updates must use row-based binary logging to be able to replicate row-based binary log events", + ErrEventAlreadyExists: "Event '%-.192s' already exists", + ErrEventStoreFailed: "Failed to store event %s. Error code %d from storage engine.", + ErrEventDoesNotExist: "Unknown event '%-.192s'", + ErrEventCantAlter: "Failed to alter event '%-.192s'", + ErrEventDropFailed: "Failed to drop %s", + ErrEventIntervalNotPositiveOrTooBig: "INTERVAL is either not positive or too big", + ErrEventEndsBeforeStarts: "ENDS is either invalid or before STARTS", + ErrEventExecTimeInThePast: "Event execution time is in the past. Event has been disabled", + ErrEventOpenTableFailed: "Failed to open mysql.event", + ErrEventNeitherMExprNorMAt: "No datetime expression provided", + ErrObsoleteColCountDoesntMatchCorrupted: "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted", + ErrObsoleteCannotLoadFromTable: "Cannot load from mysql.%s. The table is probably corrupted", + ErrEventCannotDelete: "Failed to delete the event from mysql.event", + ErrEventCompile: "Error during compilation of event's body", + ErrEventSameName: "Same old and new event name", + ErrEventDataTooLong: "Data for column '%s' too long", + ErrDropIndexFk: "Cannot drop index '%-.192s': needed in a foreign key constraint", + ErrWarnDeprecatedSyntaxWithVer: "The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead", + ErrCantWriteLockLogTable: "You can't write-lock a log table. Only read access is possible", + ErrCantLockLogTable: "You can't use locks with log tables.", + ErrForeignDuplicateKeyOldUnused: "Upholding foreign key constraints for table '%.192s', entry '%-.192s', key %d would lead to a duplicate entry", + ErrColCountDoesntMatchPleaseUpdate: "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysqlUpgrade to fix this error.", + ErrTempTablePreventsSwitchOutOfRbr: "Cannot switch out of the row-based binary log format when the session has open temporary tables", + ErrStoredFunctionPreventsSwitchBinlogFormat: "Cannot change the binary logging format inside a stored function or trigger", + ErrNdbCantSwitchBinlogFormat: "The NDB cluster engine does not support changing the binlog format on the fly yet", + ErrPartitionNoTemporary: "Cannot create temporary table with partitions", + ErrPartitionConstDomain: "Partition constant is out of partition function domain", + ErrPartitionFunctionIsNotAllowed: "This partition function is not allowed", + ErrDdlLog: "Error in DDL log", + ErrNullInValuesLessThan: "Not allowed to use NULL value in VALUES LESS THAN", + ErrWrongPartitionName: "Incorrect partition name", + ErrCantChangeTxCharacteristics: "Transaction characteristics can't be changed while a transaction is in progress", + ErrDupEntryAutoincrementCase: "ALTER TABLE causes autoIncrement resequencing, resulting in duplicate entry '%-.192s' for key '%-.192s'", + ErrEventModifyQueue: "Internal scheduler error %d", + ErrEventSetVar: "Error during starting/stopping of the scheduler. Error code %d", + ErrPartitionMerge: "Engine cannot be used in partitioned tables", + ErrCantActivateLog: "Cannot activate '%-.64s' log", + ErrRbrNotAvailable: "The server was not built with row-based replication", + ErrBase64Decode: "Decoding of base64 string failed", + ErrEventRecursionForbidden: "Recursion of EVENT DDL statements is forbidden when body is present", + ErrEventsDB: "Cannot proceed because system tables used by Event Scheduler were found damaged at server start", + ErrOnlyIntegersAllowed: "Only integers allowed as number here", + ErrUnsuportedLogEngine: "This storage engine cannot be used for log tables\"", + ErrBadLogStatement: "You cannot '%s' a log table if logging is enabled", + ErrCantRenameLogTable: "Cannot rename '%s'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to '%s'", + ErrWrongParamcountToNativeFct: "Incorrect parameter count in the call to native function '%-.192s'", + ErrWrongParametersToNativeFct: "Incorrect parameters in the call to native function '%-.192s'", + ErrWrongParametersToStoredFct: "Incorrect parameters in the call to stored function '%-.192s'", + ErrNativeFctNameCollision: "This function '%-.192s' has the same name as a native function", + ErrDupEntryWithKeyName: "Duplicate entry '%-.64s' for key '%-.192s'", + ErrBinlogPurgeEmFile: "Too many files opened, please execute the command again", + ErrEventCannotCreateInThePast: "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.", + ErrEventCannotAlterInThePast: "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was not changed. Specify a time in the future.", + ErrSlaveIncident: "The incident %s occurred on the master. Message: %-.64s", + ErrNoPartitionForGivenValueSilent: "Table has no partition for some existing values", + ErrBinlogUnsafeStatement: "Unsafe statement written to the binary log using statement format since BINLOGFORMAT = STATEMENT. %s", + ErrSlaveFatal: "Fatal : %s", + ErrSlaveRelayLogReadFailure: "Relay log read failure: %s", + ErrSlaveRelayLogWriteFailure: "Relay log write failure: %s", + ErrSlaveCreateEventFailure: "Failed to create %s", + ErrSlaveMasterComFailure: "Master command %s failed: %s", + ErrBinlogLoggingImpossible: "Binary logging not possible. Message: %s", + ErrViewNoCreationCtx: "View `%-.64s`.`%-.64s` has no creation context", + ErrViewInvalidCreationCtx: "Creation context of view `%-.64s`.`%-.64s' is invalid", + ErrSrInvalidCreationCtx: "Creation context of stored routine `%-.64s`.`%-.64s` is invalid", + ErrTrgCorruptedFile: "Corrupted TRG file for table `%-.64s`.`%-.64s`", + ErrTrgNoCreationCtx: "Triggers for table `%-.64s`.`%-.64s` have no creation context", + ErrTrgInvalidCreationCtx: "Trigger creation context of table `%-.64s`.`%-.64s` is invalid", + ErrEventInvalidCreationCtx: "Creation context of event `%-.64s`.`%-.64s` is invalid", + ErrTrgCantOpenTable: "Cannot open table for trigger `%-.64s`.`%-.64s`", + ErrCantCreateSroutine: "Cannot create stored routine `%-.64s`. Check warnings", + ErrNeverUsed: "Ambiguous slave modes combination. %s", + ErrNoFormatDescriptionEventBeforeBinlogStatement: "The BINLOG statement of type `%s` was not preceded by a format description BINLOG statement.", + ErrSlaveCorruptEvent: "Corrupted replication event was detected", + ErrLoadDataInvalidColumn: "Invalid column reference (%-.64s) in LOAD DATA", + ErrLogPurgeNoFile: "Being purged log %s was not found", + ErrXaRbtimeout: "XARBTIMEOUT: Transaction branch was rolled back: took too long", + ErrXaRbdeadlock: "XARBDEADLOCK: Transaction branch was rolled back: deadlock was detected", + ErrNeedReprepare: "Prepared statement needs to be re-prepared", + ErrDelayedNotSupported: "DELAYED option not supported for table '%-.192s'", + WarnNoMasterInfo: "The master info structure does not exist", + WarnOptionIgnored: "<%-.64s> option ignored", + WarnPluginDeleteBuiltin: "Built-in plugins cannot be deleted", + WarnPluginBusy: "Plugin is busy and will be uninstalled on shutdown", + ErrVariableIsReadonly: "%s variable '%s' is read-only. Use SET %s to assign the value", + ErrWarnEngineTransactionRollback: "Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted", + ErrSlaveHeartbeatFailure: "Unexpected master's heartbeat data: %s", + ErrSlaveHeartbeatValueOutOfRange: "The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%s seconds).", + ErrNdbReplicationSchema: "Bad schema for mysql.ndbReplication table. Message: %-.64s", + ErrConflictFnParse: "Error in parsing conflict function. Message: %-.64s", + ErrExceptionsWrite: "Write to exceptions table failed. Message: %-.128s\"", + ErrTooLongTableComment: "Comment for table '%-.64s' is too long (max = %d)", + ErrTooLongFieldComment: "Comment for field '%-.64s' is too long (max = %d)", + ErrFuncInexistentNameCollision: "FUNCTION %s does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual", + ErrDatabaseName: "Database", + ErrTableName: "Table", + ErrPartitionName: "Partition", + ErrSubpartitionName: "Subpartition", + ErrTemporaryName: "Temporary", + ErrRenamedName: "Renamed", + ErrTooManyConcurrentTrxs: "Too many active concurrent transactions", + WarnNonASCIISeparatorNotImplemented: "Non-ASCII separator arguments are not fully supported", + ErrDebugSyncTimeout: "debug sync point wait timed out", + ErrDebugSyncHitLimit: "debug sync point hit limit reached", + ErrDupSignalSet: "Duplicate condition information item '%s'", + ErrSignalWarn: "Unhandled user-defined warning condition", + ErrSignalNotFound: "Unhandled user-defined not found condition", + ErrSignalException: "Unhandled user-defined exception condition", + ErrResignalWithoutActiveHandler: "RESIGNAL when handler not active", + ErrSignalBadConditionType: "SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE", + WarnCondItemTruncated: "Data truncated for condition item '%s'", + ErrCondItemTooLong: "Data too long for condition item '%s'", + ErrUnknownLocale: "Unknown locale: '%-.64s'", + ErrSlaveIgnoreServerIds: "The requested server id %d clashes with the slave startup option --replicate-same-server-id", + ErrQueryCacheDisabled: "Query cache is disabled; restart the server with queryCacheType=1 to enable it", + ErrSameNamePartitionField: "Duplicate partition field name '%-.192s'", + ErrPartitionColumnList: "Inconsistency in usage of column lists for partitioning", + ErrWrongTypeColumnValue: "Partition column values of incorrect type", + ErrTooManyPartitionFuncFields: "Too many fields in '%-.192s'", + ErrMaxvalueInValuesIn: "Cannot use MAXVALUE as value in VALUES IN", + ErrTooManyValues: "Cannot have more than one value for this type of %-.64s partitioning", + ErrRowSinglePartitionField: "Row expressions in VALUES IN only allowed for multi-field column partitioning", + ErrFieldTypeNotAllowedAsPartitionField: "Field '%-.192s' is of a not allowed type for this type of partitioning", + ErrPartitionFieldsTooLong: "The total length of the partitioning fields is too large", + ErrBinlogRowEngineAndStmtEngine: "Cannot execute statement: impossible to write to binary log since both row-incapable engines and statement-incapable engines are involved.", + ErrBinlogRowModeAndStmtEngine: "Cannot execute statement: impossible to write to binary log since BINLOGFORMAT = ROW and at least one table uses a storage engine limited to statement-based logging.", + ErrBinlogUnsafeAndStmtEngine: "Cannot execute statement: impossible to write to binary log since statement is unsafe, storage engine is limited to statement-based logging, and BINLOGFORMAT = MIXED. %s", + ErrBinlogRowInjectionAndStmtEngine: "Cannot execute statement: impossible to write to binary log since statement is in row format and at least one table uses a storage engine limited to statement-based logging.", + ErrBinlogStmtModeAndRowEngine: "Cannot execute statement: impossible to write to binary log since BINLOGFORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.%s", + ErrBinlogRowInjectionAndStmtMode: "Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOGFORMAT = STATEMENT.", + ErrBinlogMultipleEnginesAndSelfLoggingEngine: "Cannot execute statement: impossible to write to binary log since more than one engine is involved and at least one engine is self-logging.", + ErrBinlogUnsafeLimit: "The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.", + ErrBinlogUnsafeInsertDelayed: "The statement is unsafe because it uses INSERT DELAYED. This is unsafe because the times when rows are inserted cannot be predicted.", + ErrBinlogUnsafeSystemTable: "The statement is unsafe because it uses the general log, slow query log, or performanceSchema table(s). This is unsafe because system tables may differ on slaves.", + ErrBinlogUnsafeAutoincColumns: "Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTOINCREMENT column. Inserted values cannot be logged correctly.", + ErrBinlogUnsafeUdf: "Statement is unsafe because it uses a UDF which may not return the same value on the slave.", + ErrBinlogUnsafeSystemVariable: "Statement is unsafe because it uses a system variable that may have a different value on the slave.", + ErrBinlogUnsafeSystemFunction: "Statement is unsafe because it uses a system function that may return a different value on the slave.", + ErrBinlogUnsafeNontransAfterTrans: "Statement is unsafe because it accesses a non-transactional table after accessing a transactional table within the same transaction.", + ErrMessageAndStatement: "%s Statement: %s", + ErrSlaveConversionFailed: "Column %d of table '%-.192s.%-.192s' cannot be converted from type '%-.32s' to type '%-.32s'", + ErrSlaveCantCreateConversion: "Can't create conversion table for table '%-.192s.%-.192s'", + ErrInsideTransactionPreventsSwitchBinlogFormat: "Cannot modify @@session.binlogFormat inside a transaction", + ErrPathLength: "The path specified for %.64s is too long.", + ErrWarnDeprecatedSyntaxNoReplacement: "'%s' is deprecated and will be removed in a future release.", + ErrWrongNativeTableStructure: "Native table '%-.64s'.'%-.64s' has the wrong structure", + ErrWrongPerfSchemaUsage: "Invalid performanceSchema usage.", + ErrWarnISSkippedTable: "Table '%s'.'%s' was skipped since its definition is being modified by concurrent DDL statement", + ErrInsideTransactionPreventsSwitchBinlogDirect: "Cannot modify @@session.binlogDirectNonTransactionalUpdates inside a transaction", + ErrStoredFunctionPreventsSwitchBinlogDirect: "Cannot change the binlog direct flag inside a stored function or trigger", + ErrSpatialMustHaveGeomCol: "A SPATIAL index may only contain a geometrical type column", + ErrTooLongIndexComment: "Comment for index '%-.64s' is too long (max = %d)", + ErrLockAborted: "Wait on a lock was aborted due to a pending exclusive lock", + ErrDataOutOfRange: "%s value is out of range in '%s'", + ErrWrongSpvarTypeInLimit: "A variable of a non-integer based type in LIMIT clause", + ErrBinlogUnsafeMultipleEnginesAndSelfLoggingEngine: "Mixing self-logging and non-self-logging engines in a statement is unsafe.", + ErrBinlogUnsafeMixedStatement: "Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them.", + ErrInsideTransactionPreventsSwitchSQLLogBin: "Cannot modify @@session.sqlLogBin inside a transaction", + ErrStoredFunctionPreventsSwitchSQLLogBin: "Cannot change the sqlLogBin inside a stored function or trigger", + ErrFailedReadFromParFile: "Failed to read from the .par file", + ErrValuesIsNotIntType: "VALUES value for partition '%-.64s' must have type INT", + ErrAccessDeniedNoPassword: "Access denied for user '%-.48s'@'%-.64s'", + ErrSetPasswordAuthPlugin: "SET PASSWORD has no significance for users authenticating via plugins", + ErrGrantPluginUserExists: "GRANT with IDENTIFIED WITH is illegal because the user %-.*s already exists", + ErrTruncateIllegalFk: "Cannot truncate a table referenced in a foreign key constraint (%.192s)", + ErrPluginIsPermanent: "Plugin '%s' is forcePlusPermanent and can not be unloaded", + ErrSlaveHeartbeatValueOutOfRangeMin: "The requested value for the heartbeat period is less than 1 millisecond. The value is reset to 0, meaning that heartbeating will effectively be disabled.", + ErrSlaveHeartbeatValueOutOfRangeMax: "The requested value for the heartbeat period exceeds the value of `slaveNetTimeout' seconds. A sensible value for the period should be less than the timeout.", + ErrStmtCacheFull: "Multi-row statements required more than 'maxBinlogStmtCacheSize' bytes of storage; increase this mysqld variable and try again", + ErrMultiUpdateKeyConflict: "Primary key/partition key update is not allowed since the table is updated both as '%-.192s' and '%-.192s'.", + ErrTableNeedsRebuild: "Table rebuild required. Please do \"ALTER TABLE `%-.32s` FORCE\" or dump/reload to fix it!", + WarnOptionBelowLimit: "The value of '%s' should be no less than the value of '%s'", + ErrIndexColumnTooLong: "Index column size too large. The maximum column size is %d bytes.", + ErrErrorInTriggerBody: "Trigger '%-.64s' has an error in its body: '%-.256s'", + ErrErrorInUnknownTriggerBody: "Unknown trigger has an error in its body: '%-.256s'", + ErrIndexCorrupt: "Index %s is corrupted", + ErrUndoRecordTooBig: "Undo log record is too big.", + ErrBinlogUnsafeInsertIgnoreSelect: "INSERT IGNORE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeInsertSelectUpdate: "INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeReplaceSelect: "REPLACE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeCreateIgnoreSelect: "CREATE... IGNORE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeCreateReplaceSelect: "CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeUpdateIgnore: "UPDATE IGNORE is unsafe because the order in which rows are updated determines which (if any) rows are ignored. This order cannot be predicted and may differ on master and the slave.", + ErrPluginNoUninstall: "Plugin '%s' is marked as not dynamically uninstallable. You have to stop the server to uninstall it.", + ErrPluginNoInstall: "Plugin '%s' is marked as not dynamically installable. You have to stop the server to install it.", + ErrBinlogUnsafeWriteAutoincSelect: "Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeCreateSelectAutoinc: "CREATE TABLE... SELECT... on a table with an auto-increment column is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are inserted. This order cannot be predicted and may differ on master and the slave.", + ErrBinlogUnsafeInsertTwoKeys: "INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe", + ErrTableInFkCheck: "Table is being used in foreign key check.", + ErrUnsupportedEngine: "Storage engine '%s' does not support system tables. [%s.%s]", + ErrBinlogUnsafeAutoincNotFirst: "INSERT into autoincrement field which is not the first part in the composed primary key is unsafe.", + ErrCannotLoadFromTableV2: "Cannot load from %s.%s. The table is probably corrupted", + ErrMasterDelayValueOutOfRange: "The requested value %d for the master delay exceeds the maximum %d", + ErrOnlyFdAndRbrEventsAllowedInBinlogStatement: "Only FormatDescriptionLogEvent and row events are allowed in BINLOG statements (but %s was provided)", + ErrPartitionExchangeDifferentOption: "Non matching attribute '%-.64s' between partition and table", + ErrPartitionExchangePartTable: "Table to exchange with partition is partitioned: '%-.64s'", + ErrPartitionExchangeTempTable: "Table to exchange with partition is temporary: '%-.64s'", + ErrPartitionInsteadOfSubpartition: "Subpartitioned table, use subpartition instead of partition", + ErrUnknownPartition: "Unknown partition '%-.64s' in table '%-.64s'", + ErrTablesDifferentMetadata: "Tables have different definitions", + ErrRowDoesNotMatchPartition: "Found a row that does not match the partition", + ErrBinlogCacheSizeGreaterThanMax: "Option binlogCacheSize (%d) is greater than maxBinlogCacheSize (%d); setting binlogCacheSize equal to maxBinlogCacheSize.", + ErrWarnIndexNotApplicable: "Cannot use %-.64s access on index '%-.64s' due to type or collation conversion on field '%-.64s'", + ErrPartitionExchangeForeignKey: "Table to exchange with partition has foreign key references: '%-.64s'", + ErrNoSuchKeyValue: "Key value '%-.192s' was not found in table '%-.192s.%-.192s'", + ErrRplInfoDataTooLong: "Data for column '%s' too long", + ErrNetworkReadEventChecksumFailure: "Replication event checksum verification failed while reading from network.", + ErrBinlogReadEventChecksumFailure: "Replication event checksum verification failed while reading from a log file.", + ErrBinlogStmtCacheSizeGreaterThanMax: "Option binlogStmtCacheSize (%d) is greater than maxBinlogStmtCacheSize (%d); setting binlogStmtCacheSize equal to maxBinlogStmtCacheSize.", + ErrCantUpdateTableInCreateTableSelect: "Can't update table '%-.192s' while '%-.192s' is being created.", + ErrPartitionClauseOnNonpartitioned: "PARTITION () clause on non partitioned table", + ErrRowDoesNotMatchGivenPartitionSet: "Found a row not matching the given partition set", + ErrNoSuchPartitionunused: "partition '%-.64s' doesn't exist", + ErrChangeRplInfoRepositoryFailure: "Failure while changing the type of replication repository: %s.", + ErrWarningNotCompleteRollbackWithCreatedTempTable: "The creation of some temporary tables could not be rolled back.", + ErrWarningNotCompleteRollbackWithDroppedTempTable: "Some temporary tables were dropped, but these operations could not be rolled back.", + ErrMtsFeatureIsNotSupported: "%s is not supported in multi-threaded slave mode. %s", + ErrMtsUpdatedDBsGreaterMax: "The number of modified databases exceeds the maximum %d; the database names will not be included in the replication event metadata.", + ErrMtsCantParallel: "Cannot execute the current event group in the parallel mode. Encountered event %s, relay-log name %s, position %s which prevents execution of this event group in parallel mode. Reason: %s.", + ErrMtsInconsistentData: "%s", + ErrFulltextNotSupportedWithPartitioning: "FULLTEXT index is not supported for partitioned tables.", + ErrDaInvalidConditionNumber: "Invalid condition number", + ErrInsecurePlainText: "Sending passwords in plain text without SSL/TLS is extremely insecure.", + ErrInsecureChangeMaster: "Storing MySQL user name or password information in the master.info repository is not secure and is therefore not recommended. Please see the MySQL Manual for more about this issue and possible alternatives.", + ErrForeignDuplicateKeyWithChildInfo: "Foreign key constraint for table '%.192s', record '%-.192s' would lead to a duplicate entry in table '%.192s', key '%.192s'", + ErrForeignDuplicateKeyWithoutChildInfo: "Foreign key constraint for table '%.192s', record '%-.192s' would lead to a duplicate entry in a child table", + ErrSQLthreadWithSecureSlave: "Setting authentication options is not possible when only the Slave SQL Thread is being started.", + ErrTableHasNoFt: "The table does not have FULLTEXT index to support this query", + ErrVariableNotSettableInSfOrTrigger: "The system variable %.200s cannot be set in stored functions or triggers.", + ErrVariableNotSettableInTransaction: "The system variable %.200s cannot be set when there is an ongoing transaction.", + ErrGtidNextIsNotInGtidNextList: "The system variable @@SESSION.GTIDNEXT has the value %.200s, which is not listed in @@SESSION.GTIDNEXTLIST.", + ErrCantChangeGtidNextInTransactionWhenGtidNextListIsNull: "When @@SESSION.GTIDNEXTLIST == NULL, the system variable @@SESSION.GTIDNEXT cannot change inside a transaction.", + ErrSetStatementCannotInvokeFunction: "The statement 'SET %.200s' cannot invoke a stored function.", + ErrGtidNextCantBeAutomaticIfGtidNextListIsNonNull: "The system variable @@SESSION.GTIDNEXT cannot be 'AUTOMATIC' when @@SESSION.GTIDNEXTLIST is non-NULL.", + ErrSkippingLoggedTransaction: "Skipping transaction %.200s because it has already been executed and logged.", + ErrMalformedGtidSetSpecification: "Malformed GTID set specification '%.200s'.", + ErrMalformedGtidSetEncoding: "Malformed GTID set encoding.", + ErrMalformedGtidSpecification: "Malformed GTID specification '%.200s'.", + ErrGnoExhausted: "Impossible to generate Global Transaction Identifier: the integer component reached the maximal value. Restart the server with a new serverUuid.", + ErrBadSlaveAutoPosition: "Parameters MASTERLOGFILE, MASTERLOGPOS, RELAYLOGFILE and RELAYLOGPOS cannot be set when MASTERAUTOPOSITION is active.", + ErrAutoPositionRequiresGtidModeOn: "CHANGE MASTER TO MASTERAUTOPOSITION = 1 can only be executed when @@GLOBAL.GTIDMODE = ON.", + ErrCantDoImplicitCommitInTrxWhenGtidNextIsSet: "Cannot execute statements with implicit commit inside a transaction when @@SESSION.GTIDNEXT != AUTOMATIC or @@SESSION.GTIDNEXTLIST != NULL.", + ErrGtidMode2Or3RequiresEnforceGtidConsistencyOn: "@@GLOBAL.GTIDMODE = ON or UPGRADESTEP2 requires @@GLOBAL.ENFORCEGTIDCONSISTENCY = 1.", + ErrGtidModeRequiresBinlog: "@@GLOBAL.GTIDMODE = ON or UPGRADESTEP1 or UPGRADESTEP2 requires --log-bin and --log-slave-updates.", + ErrCantSetGtidNextToGtidWhenGtidModeIsOff: "@@SESSION.GTIDNEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTIDMODE = OFF.", + ErrCantSetGtidNextToAnonymousWhenGtidModeIsOn: "@@SESSION.GTIDNEXT cannot be set to ANONYMOUS when @@GLOBAL.GTIDMODE = ON.", + ErrCantSetGtidNextListToNonNullWhenGtidModeIsOff: "@@SESSION.GTIDNEXTLIST cannot be set to a non-NULL value when @@GLOBAL.GTIDMODE = OFF.", + ErrFoundGtidEventWhenGtidModeIsOff: "Found a GtidLogEvent or PreviousGtidsLogEvent when @@GLOBAL.GTIDMODE = OFF.", + ErrGtidUnsafeNonTransactionalTable: "When @@GLOBAL.ENFORCEGTIDCONSISTENCY = 1, updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables.", + ErrGtidUnsafeCreateSelect: "CREATE TABLE ... SELECT is forbidden when @@GLOBAL.ENFORCEGTIDCONSISTENCY = 1.", + ErrGtidUnsafeCreateDropTemporaryTableInTransaction: "When @@GLOBAL.ENFORCEGTIDCONSISTENCY = 1, the statements CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE can be executed in a non-transactional context only, and require that AUTOCOMMIT = 1.", + ErrGtidModeCanOnlyChangeOneStepAtATime: "The value of @@GLOBAL.GTIDMODE can only change one step at a time: OFF <-> UPGRADESTEP1 <-> UPGRADESTEP2 <-> ON. Also note that this value must be stepped up or down simultaneously on all servers; see the Manual for instructions.", + ErrMasterHasPurgedRequiredGtids: "The slave is connecting using CHANGE MASTER TO MASTERAUTOPOSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.", + ErrCantSetGtidNextWhenOwningGtid: "@@SESSION.GTIDNEXT cannot be changed by a client that owns a GTID. The client owns %s. Ownership is released on COMMIT or ROLLBACK.", + ErrUnknownExplainFormat: "Unknown EXPLAIN format name: '%s'", + ErrCantExecuteInReadOnlyTransaction: "Cannot execute statement in a READ ONLY transaction.", + ErrTooLongTablePartitionComment: "Comment for table partition '%-.64s' is too long (max = %d)", + ErrSlaveConfiguration: "Slave is not configured or failed to initialize properly. You must at least set --server-id to enable either a master or a slave. Additional error messages can be found in the MySQL error log.", + ErrInnodbFtLimit: "InnoDB presently supports one FULLTEXT index creation at a time", + ErrInnodbNoFtTempTable: "Cannot create FULLTEXT index on temporary InnoDB table", + ErrInnodbFtWrongDocidColumn: "Column '%-.192s' is of wrong type for an InnoDB FULLTEXT index", + ErrInnodbFtWrongDocidIndex: "Index '%-.192s' is of wrong type for an InnoDB FULLTEXT index", + ErrInnodbOnlineLogTooBig: "Creating index '%-.192s' required more than 'innodbOnlineAlterLogMaxSize' bytes of modification log. Please try again.", + ErrUnknownAlterAlgorithm: "Unknown ALGORITHM '%s'", + ErrUnknownAlterLock: "Unknown LOCK type '%s'", + ErrMtsChangeMasterCantRunWithGaps: "CHANGE MASTER cannot be executed when the slave was stopped with an error or killed in MTS mode. Consider using RESET SLAVE or START SLAVE UNTIL.", + ErrMtsRecoveryFailure: "Cannot recover after SLAVE errored out in parallel execution mode. Additional error messages can be found in the MySQL error log.", + ErrMtsResetWorkers: "Cannot clean up worker info tables. Additional error messages can be found in the MySQL error log.", + ErrColCountDoesntMatchCorruptedV2: "Column count of %s.%s is wrong. Expected %d, found %d. The table is probably corrupted", + ErrSlaveSilentRetryTransaction: "Slave must silently retry current transaction", + ErrDiscardFkChecksRunning: "There is a foreign key check running on table '%-.192s'. Cannot discard the table.", + ErrTableSchemaMismatch: "Schema mismatch (%s)", + ErrTableInSystemTablespace: "Table '%-.192s' in system tablespace", + ErrIoRead: "IO Read : (%d, %s) %s", + ErrIoWrite: "IO Write : (%d, %s) %s", + ErrTablespaceMissing: "Tablespace is missing for table '%-.192s'", + ErrTablespaceExists: "Tablespace for table '%-.192s' exists. Please DISCARD the tablespace before IMPORT.", + ErrTablespaceDiscarded: "Tablespace has been discarded for table '%-.192s'", + ErrInternal: "Internal : %s", + ErrInnodbImport: "ALTER TABLE '%-.192s' IMPORT TABLESPACE failed with error %d : '%s'", + ErrInnodbIndexCorrupt: "Index corrupt: %s", + ErrInvalidYearColumnLength: "YEAR(%d) column type is deprecated. Creating YEAR(4) column instead.", + ErrNotValidPassword: "Your password does not satisfy the current policy requirements", + ErrMustChangePassword: "You must SET PASSWORD before executing this statement", + ErrFkNoIndexChild: "Failed to add the foreign key constaint. Missing index for constraint '%s' in the foreign table '%s'", + ErrFkNoIndexParent: "Failed to add the foreign key constaint. Missing index for constraint '%s' in the referenced table '%s'", + ErrFkFailAddSystem: "Failed to add the foreign key constraint '%s' to system tables", + ErrFkCannotOpenParent: "Failed to open the referenced table '%s'", + ErrFkIncorrectOption: "Failed to add the foreign key constraint on table '%s'. Incorrect options in FOREIGN KEY constraint '%s'", + ErrFkDupName: "Duplicate foreign key constraint name '%s'", + ErrPasswordFormat: "The password hash doesn't have the expected format. Check if the correct password algorithm is being used with the PASSWORD() function.", + ErrFkColumnCannotDrop: "Cannot drop column '%-.192s': needed in a foreign key constraint '%-.192s'", + ErrFkColumnCannotDropChild: "Cannot drop column '%-.192s': needed in a foreign key constraint '%-.192s' of table '%-.192s'", + ErrFkColumnNotNull: "Column '%-.192s' cannot be NOT NULL: needed in a foreign key constraint '%-.192s' SET NULL", + ErrDupIndex: "Duplicate index '%-.64s' defined on the table '%-.64s.%-.64s'. This is deprecated and will be disallowed in a future release.", + ErrFkColumnCannotChange: "Cannot change column '%-.192s': used in a foreign key constraint '%-.192s'", + ErrFkColumnCannotChangeChild: "Cannot change column '%-.192s': used in a foreign key constraint '%-.192s' of table '%-.192s'", + ErrFkCannotDeleteParent: "Cannot delete rows from table which is parent in a foreign key constraint '%-.192s' of table '%-.192s'", + ErrMalformedPacket: "Malformed communication packet.", + ErrReadOnlyMode: "Running in read-only mode", + ErrGtidNextTypeUndefinedGroup: "When @@SESSION.GTIDNEXT is set to a GTID, you must explicitly set it again after a COMMIT or ROLLBACK. If you see this error message in the slave SQL thread, it means that a table in the current transaction is transactional on the master and non-transactional on the slave. In a client connection, it means that you executed SET @@SESSION.GTIDNEXT before a transaction and forgot to set @@SESSION.GTIDNEXT to a different identifier or to 'AUTOMATIC' after COMMIT or ROLLBACK. Current @@SESSION.GTIDNEXT is '%s'.", + ErrVariableNotSettableInSp: "The system variable %.200s cannot be set in stored procedures.", + ErrCantSetGtidPurgedWhenGtidModeIsOff: "@@GLOBAL.GTIDPURGED can only be set when @@GLOBAL.GTIDMODE = ON.", + ErrCantSetGtidPurgedWhenGtidExecutedIsNotEmpty: "@@GLOBAL.GTIDPURGED can only be set when @@GLOBAL.GTIDEXECUTED is empty.", + ErrCantSetGtidPurgedWhenOwnedGtidsIsNotEmpty: "@@GLOBAL.GTIDPURGED can only be set when there are no ongoing transactions (not even in other clients).", + ErrGtidPurgedWasChanged: "@@GLOBAL.GTIDPURGED was changed from '%s' to '%s'.", + ErrGtidExecutedWasChanged: "@@GLOBAL.GTIDEXECUTED was changed from '%s' to '%s'.", + ErrBinlogStmtModeAndNoReplTables: "Cannot execute statement: impossible to write to binary log since BINLOGFORMAT = STATEMENT, and both replicated and non replicated tables are written to.", + ErrAlterOperationNotSupported: "%s is not supported for this operation. Try %s.", + ErrAlterOperationNotSupportedReason: "%s is not supported. Reason: %s. Try %s.", + ErrAlterOperationNotSupportedReasonCopy: "COPY algorithm requires a lock", + ErrAlterOperationNotSupportedReasonPartition: "Partition specific operations do not yet support LOCK/ALGORITHM", + ErrAlterOperationNotSupportedReasonFkRename: "Columns participating in a foreign key are renamed", + ErrAlterOperationNotSupportedReasonColumnType: "Cannot change column type INPLACE", + ErrAlterOperationNotSupportedReasonFkCheck: "Adding foreign keys needs foreignKeyChecks=OFF", + ErrAlterOperationNotSupportedReasonIgnore: "Creating unique indexes with IGNORE requires COPY algorithm to remove duplicate rows", + ErrAlterOperationNotSupportedReasonNopk: "Dropping a primary key is not allowed without also adding a new primary key", + ErrAlterOperationNotSupportedReasonAutoinc: "Adding an auto-increment column requires a lock", + ErrAlterOperationNotSupportedReasonHiddenFts: "Cannot replace hidden FTSDOCID with a user-visible one", + ErrAlterOperationNotSupportedReasonChangeFts: "Cannot drop or rename FTSDOCID", + ErrAlterOperationNotSupportedReasonFts: "Fulltext index creation requires a lock", + ErrSQLSlaveSkipCounterNotSettableInGtidMode: "sqlSlaveSkipCounter can not be set when the server is running with @@GLOBAL.GTIDMODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction", + ErrDupUnknownInIndex: "Duplicate entry for key '%-.192s'", + ErrIdentCausesTooLongPath: "Long database name and identifier for object resulted in path length exceeding %d characters. Path: '%s'.", + ErrAlterOperationNotSupportedReasonNotNull: "cannot silently convert NULL values, as required in this SQLMODE", + ErrMustChangePasswordLogin: "Your password has expired. To log in you must change it using a client that supports expired passwords.", + ErrRowInWrongPartition: "Found a row in wrong partition %s", + ErrBadGeneratedColumn: "The value specified for generated column '%s' in table '%s' is not allowed.", + ErrUnsupportedOnGeneratedColumn: "'%s' is not supported for generated columns.", + ErrGeneratedColumnNonPrior: "Generated column can refer only to generated columns defined prior to it.", + ErrDependentByGeneratedColumn: "Column '%s' has a generated column dependency.", + ErrInvalidJSONText: "Invalid JSON text: %-.192s", + ErrInvalidJSONPath: "Invalid JSON path expression %s.", + ErrInvalidJSONData: "Invalid data type for JSON data", + ErrInvalidJSONPathWildcard: "In this situation, path expressions may not contain the * and ** tokens.", + ErrInvalidJSONContainsPathType: "The second argument can only be either 'one' or 'all'.", + ErrJSONUsedAsKey: "JSON column '%-.192s' cannot be used in key specification.", + + // TiDB errors. + ErrMemExceedThreshold: "%s holds %dB memory, exceeds threshold %dB.%s", + ErrForUpdateCantRetry: "[%d] can not retry select for update statement", + ErrAdminCheckTable: "TiDB admin check table failed.", + + // TiKV/PD errors. + ErrPDServerTimeout: "PD server timeout", + ErrTiKVServerTimeout: "TiKV server timeout", + ErrTiKVServerBusy: "TiKV server is busy", + ErrResolveLockTimeout: "Resolve lock timeout", + ErrRegionUnavailable: "Region is unavailable", + ErrGCTooEarly: "GC life time is shorter than transaction duration, transaction starts at %v, GC safe point is %v", + + ErrTxnTooLarge: "Transaction is too large", +} diff --git a/vendor/github.com/pingcap/parser/mysql/error.go b/vendor/github.com/pingcap/parser/mysql/error.go new file mode 100644 index 0000000000000000000000000000000000000000..fd6316ca21f7d15bcd86c054d3d0dd06a7dc7bf5 --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/error.go @@ -0,0 +1,71 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +import ( + "errors" + "fmt" +) + +// Portable analogs of some common call errors. +var ( + ErrBadConn = errors.New("connection was bad") + ErrMalformPacket = errors.New("malform packet error") +) + +// SQLError records an error information, from executing SQL. +type SQLError struct { + Code uint16 + Message string + State string +} + +// Error prints errors, with a formatted string. +func (e *SQLError) Error() string { + return fmt.Sprintf("ERROR %d (%s): %s", e.Code, e.State, e.Message) +} + +// NewErr generates a SQL error, with an error code and default format specifier defined in MySQLErrName. +func NewErr(errCode uint16, args ...interface{}) *SQLError { + e := &SQLError{Code: errCode} + + if s, ok := MySQLState[errCode]; ok { + e.State = s + } else { + e.State = DefaultMySQLState + } + + if format, ok := MySQLErrName[errCode]; ok { + e.Message = fmt.Sprintf(format, args...) + } else { + e.Message = fmt.Sprint(args...) + } + + return e +} + +// NewErrf creates a SQL error, with an error code and a format specifier. +func NewErrf(errCode uint16, format string, args ...interface{}) *SQLError { + e := &SQLError{Code: errCode} + + if s, ok := MySQLState[errCode]; ok { + e.State = s + } else { + e.State = DefaultMySQLState + } + + e.Message = fmt.Sprintf(format, args...) + + return e +} diff --git a/vendor/github.com/pingcap/parser/mysql/locale_format.go b/vendor/github.com/pingcap/parser/mysql/locale_format.go new file mode 100644 index 0000000000000000000000000000000000000000..b483f94fc189ff4c68d80c1b69056a7de510bbbd --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/locale_format.go @@ -0,0 +1,98 @@ +package mysql + +import ( + "bytes" + "strconv" + "strings" + "unicode" + + "github.com/pingcap/errors" +) + +func formatENUS(number string, precision string) (string, error) { + var buffer bytes.Buffer + if unicode.IsDigit(rune(precision[0])) { + for i, v := range precision { + if unicode.IsDigit(v) { + continue + } + precision = precision[:i] + break + } + } else { + precision = "0" + } + if number[0] == '-' && number[1] == '.' { + number = strings.Replace(number, "-", "-0", 1) + } else if number[0] == '.' { + number = strings.Replace(number, ".", "0.", 1) + } + + if (number[:1] == "-" && !unicode.IsDigit(rune(number[1]))) || + (!unicode.IsDigit(rune(number[0])) && number[:1] != "-") { + buffer.Write([]byte{'0'}) + position, err := strconv.ParseUint(precision, 10, 64) + if err == nil && position > 0 { + buffer.Write([]byte{'.'}) + buffer.WriteString(strings.Repeat("0", int(position))) + } + return buffer.String(), nil + } else if number[:1] == "-" { + buffer.Write([]byte{'-'}) + number = number[1:] + } + + for i, v := range number { + if unicode.IsDigit(v) { + continue + } else if i == 1 && number[1] == '.' { + continue + } else if v == '.' && number[1] != '.' { + continue + } else { + number = number[:i] + break + } + } + + comma := []byte{','} + parts := strings.Split(number, ".") + pos := 0 + if len(parts[0])%3 != 0 { + pos += len(parts[0]) % 3 + buffer.WriteString(parts[0][:pos]) + buffer.Write(comma) + } + for ; pos < len(parts[0]); pos += 3 { + buffer.WriteString(parts[0][pos : pos+3]) + buffer.Write(comma) + } + buffer.Truncate(buffer.Len() - 1) + + position, err := strconv.ParseUint(precision, 10, 64) + if err == nil { + if position > 0 { + buffer.Write([]byte{'.'}) + if len(parts) == 2 { + if uint64(len(parts[1])) >= position { + buffer.WriteString(parts[1][:position]) + } else { + buffer.WriteString(parts[1]) + buffer.WriteString(strings.Repeat("0", int(position)-len(parts[1]))) + } + } else { + buffer.WriteString(strings.Repeat("0", int(position))) + } + } + } + + return buffer.String(), nil +} + +func formatZHCN(number string, precision string) (string, error) { + return "", errors.New("not implemented") +} + +func formatNotSupport(number string, precision string) (string, error) { + return "", errors.New("not support for the specific locale") +} diff --git a/vendor/github.com/pingcap/parser/mysql/state.go b/vendor/github.com/pingcap/parser/mysql/state.go new file mode 100644 index 0000000000000000000000000000000000000000..a31f61c01fdc095c062dfcefa4edfde33396327d --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/state.go @@ -0,0 +1,258 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +const ( + // DefaultMySQLState is default state of the mySQL + DefaultMySQLState = "HY000" +) + +// MySQLState maps error code to MySQL SQLSTATE value. +// The values are taken from ANSI SQL and ODBC and are more standardized. +var MySQLState = map[uint16]string{ + ErrDupKey: "23000", + ErrOutofMemory: "HY001", + ErrOutOfSortMemory: "HY001", + ErrConCount: "08004", + ErrBadHost: "08S01", + ErrHandshake: "08S01", + ErrDBaccessDenied: "42000", + ErrAccessDenied: "28000", + ErrNoDB: "3D000", + ErrUnknownCom: "08S01", + ErrBadNull: "23000", + ErrBadDB: "42000", + ErrTableExists: "42S01", + ErrBadTable: "42S02", + ErrNonUniq: "23000", + ErrServerShutdown: "08S01", + ErrBadField: "42S22", + ErrFieldNotInGroupBy: "42000", + ErrWrongSumSelect: "42000", + ErrWrongGroupField: "42000", + ErrWrongValueCount: "21S01", + ErrTooLongIdent: "42000", + ErrDupFieldName: "42S21", + ErrDupKeyName: "42000", + ErrDupEntry: "23000", + ErrWrongFieldSpec: "42000", + ErrParse: "42000", + ErrEmptyQuery: "42000", + ErrNonuniqTable: "42000", + ErrInvalidDefault: "42000", + ErrMultiplePriKey: "42000", + ErrTooManyKeys: "42000", + ErrTooManyKeyParts: "42000", + ErrTooLongKey: "42000", + ErrKeyColumnDoesNotExits: "42000", + ErrBlobUsedAsKey: "42000", + ErrTooBigFieldlength: "42000", + ErrWrongAutoKey: "42000", + ErrForcingClose: "08S01", + ErrIpsock: "08S01", + ErrNoSuchIndex: "42S12", + ErrWrongFieldTerminators: "42000", + ErrBlobsAndNoTerminated: "42000", + ErrCantRemoveAllFields: "42000", + ErrCantDropFieldOrKey: "42000", + ErrBlobCantHaveDefault: "42000", + ErrWrongDBName: "42000", + ErrWrongTableName: "42000", + ErrTooBigSelect: "42000", + ErrUnknownProcedure: "42000", + ErrWrongParamcountToProcedure: "42000", + ErrUnknownTable: "42S02", + ErrFieldSpecifiedTwice: "42000", + ErrUnsupportedExtension: "42000", + ErrTableMustHaveColumns: "42000", + ErrUnknownCharacterSet: "42000", + ErrTooBigRowsize: "42000", + ErrWrongOuterJoin: "42000", + ErrNullColumnInIndex: "42000", + ErrPasswordAnonymousUser: "42000", + ErrPasswordNotAllowed: "42000", + ErrPasswordNoMatch: "42000", + ErrWrongValueCountOnRow: "21S01", + ErrInvalidUseOfNull: "22004", + ErrRegexp: "42000", + ErrMixOfGroupFuncAndFields: "42000", + ErrNonexistingGrant: "42000", + ErrTableaccessDenied: "42000", + ErrColumnaccessDenied: "42000", + ErrIllegalGrantForTable: "42000", + ErrGrantWrongHostOrUser: "42000", + ErrNoSuchTable: "42S02", + ErrNonexistingTableGrant: "42000", + ErrNotAllowedCommand: "42000", + ErrSyntax: "42000", + ErrAbortingConnection: "08S01", + ErrNetPacketTooLarge: "08S01", + ErrNetReadErrorFromPipe: "08S01", + ErrNetFcntl: "08S01", + ErrNetPacketsOutOfOrder: "08S01", + ErrNetUncompress: "08S01", + ErrNetRead: "08S01", + ErrNetReadInterrupted: "08S01", + ErrNetErrorOnWrite: "08S01", + ErrNetWriteInterrupted: "08S01", + ErrTooLongString: "42000", + ErrTableCantHandleBlob: "42000", + ErrTableCantHandleAutoIncrement: "42000", + ErrWrongColumnName: "42000", + ErrWrongKeyColumn: "42000", + ErrDupUnique: "23000", + ErrBlobKeyWithoutLength: "42000", + ErrPrimaryCantHaveNull: "42000", + ErrTooManyRows: "42000", + ErrRequiresPrimaryKey: "42000", + ErrKeyDoesNotExist: "42000", + ErrCheckNoSuchTable: "42000", + ErrCheckNotImplemented: "42000", + ErrCantDoThisDuringAnTransaction: "25000", + ErrNewAbortingConnection: "08S01", + ErrMasterNetRead: "08S01", + ErrMasterNetWrite: "08S01", + ErrTooManyUserConnections: "42000", + ErrReadOnlyTransaction: "25000", + ErrNoPermissionToCreateUser: "42000", + ErrLockDeadlock: "40001", + ErrNoReferencedRow: "23000", + ErrRowIsReferenced: "23000", + ErrConnectToMaster: "08S01", + ErrWrongNumberOfColumnsInSelect: "21000", + ErrUserLimitReached: "42000", + ErrSpecificAccessDenied: "42000", + ErrNoDefault: "42000", + ErrWrongValueForVar: "42000", + ErrWrongTypeForVar: "42000", + ErrCantUseOptionHere: "42000", + ErrNotSupportedYet: "42000", + ErrWrongFkDef: "42000", + ErrOperandColumns: "21000", + ErrSubqueryNo1Row: "21000", + ErrIllegalReference: "42S22", + ErrDerivedMustHaveAlias: "42000", + ErrSelectReduced: "01000", + ErrTablenameNotAllowedHere: "42000", + ErrNotSupportedAuthMode: "08004", + ErrSpatialCantHaveNull: "42000", + ErrCollationCharsetMismatch: "42000", + ErrWarnTooFewRecords: "01000", + ErrWarnTooManyRecords: "01000", + ErrWarnNullToNotnull: "22004", + ErrWarnDataOutOfRange: "22003", + WarnDataTruncated: "01000", + ErrWrongNameForIndex: "42000", + ErrWrongNameForCatalog: "42000", + ErrUnknownStorageEngine: "42000", + ErrTruncatedWrongValue: "22007", + ErrSpNoRecursiveCreate: "2F003", + ErrSpAlreadyExists: "42000", + ErrSpDoesNotExist: "42000", + ErrSpLilabelMismatch: "42000", + ErrSpLabelRedefine: "42000", + ErrSpLabelMismatch: "42000", + ErrSpUninitVar: "01000", + ErrSpBadselect: "0A000", + ErrSpBadreturn: "42000", + ErrSpBadstatement: "0A000", + ErrUpdateLogDeprecatedIgnored: "42000", + ErrUpdateLogDeprecatedTranslated: "42000", + ErrQueryInterrupted: "70100", + ErrSpWrongNoOfArgs: "42000", + ErrSpCondMismatch: "42000", + ErrSpNoreturn: "42000", + ErrSpNoreturnend: "2F005", + ErrSpBadCursorQuery: "42000", + ErrSpBadCursorSelect: "42000", + ErrSpCursorMismatch: "42000", + ErrSpCursorAlreadyOpen: "24000", + ErrSpCursorNotOpen: "24000", + ErrSpUndeclaredVar: "42000", + ErrSpFetchNoData: "02000", + ErrSpDupParam: "42000", + ErrSpDupVar: "42000", + ErrSpDupCond: "42000", + ErrSpDupCurs: "42000", + ErrSpSubselectNyi: "0A000", + ErrStmtNotAllowedInSfOrTrg: "0A000", + ErrSpVarcondAfterCurshndlr: "42000", + ErrSpCursorAfterHandler: "42000", + ErrSpCaseNotFound: "20000", + ErrDivisionByZero: "22012", + ErrIllegalValueForType: "22007", + ErrProcaccessDenied: "42000", + ErrXaerNota: "XAE04", + ErrXaerInval: "XAE05", + ErrXaerRmfail: "XAE07", + ErrXaerOutside: "XAE09", + ErrXaerRmerr: "XAE03", + ErrXaRbrollback: "XA100", + ErrNonexistingProcGrant: "42000", + ErrDataTooLong: "22001", + ErrSpBadSQLstate: "42000", + ErrCantCreateUserWithGrant: "42000", + ErrSpDupHandler: "42000", + ErrSpNotVarArg: "42000", + ErrSpNoRetset: "0A000", + ErrCantCreateGeometryObject: "22003", + ErrTooBigScale: "42000", + ErrTooBigPrecision: "42000", + ErrMBiggerThanD: "42000", + ErrTooLongBody: "42000", + ErrTooBigDisplaywidth: "42000", + ErrXaerDupid: "XAE08", + ErrDatetimeFunctionOverflow: "22008", + ErrRowIsReferenced2: "23000", + ErrNoReferencedRow2: "23000", + ErrSpBadVarShadow: "42000", + ErrSpWrongName: "42000", + ErrSpNoAggregate: "42000", + ErrMaxPreparedStmtCountReached: "42000", + ErrNonGroupingFieldUsed: "42000", + ErrForeignDuplicateKeyOldUnused: "23000", + ErrCantChangeTxCharacteristics: "25001", + ErrWrongParamcountToNativeFct: "42000", + ErrWrongParametersToNativeFct: "42000", + ErrWrongParametersToStoredFct: "42000", + ErrDupEntryWithKeyName: "23000", + ErrXaRbtimeout: "XA106", + ErrXaRbdeadlock: "XA102", + ErrFuncInexistentNameCollision: "42000", + ErrDupSignalSet: "42000", + ErrSignalWarn: "01000", + ErrSignalNotFound: "02000", + ErrSignalException: "HY000", + ErrResignalWithoutActiveHandler: "0K000", + ErrSpatialMustHaveGeomCol: "42000", + ErrDataOutOfRange: "22003", + ErrAccessDeniedNoPassword: "28000", + ErrTruncateIllegalFk: "42000", + ErrDaInvalidConditionNumber: "35000", + ErrForeignDuplicateKeyWithChildInfo: "23000", + ErrForeignDuplicateKeyWithoutChildInfo: "23000", + ErrCantExecuteInReadOnlyTransaction: "25006", + ErrAlterOperationNotSupported: "0A000", + ErrAlterOperationNotSupportedReason: "0A000", + ErrDupUnknownInIndex: "23000", + ErrBadGeneratedColumn: "HY000", + ErrUnsupportedOnGeneratedColumn: "HY000", + ErrGeneratedColumnNonPrior: "HY000", + ErrDependentByGeneratedColumn: "HY000", + ErrInvalidJSONText: "22032", + ErrInvalidJSONPath: "42000", + ErrInvalidJSONData: "22032", + ErrInvalidJSONPathWildcard: "42000", + ErrJSONUsedAsKey: "42000", +} diff --git a/vendor/github.com/pingcap/parser/mysql/type.go b/vendor/github.com/pingcap/parser/mysql/type.go new file mode 100644 index 0000000000000000000000000000000000000000..9ea32f90dd34ebd0a0315c88389f44ab49a00ad7 --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/type.go @@ -0,0 +1,155 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +// MySQL type information. +const ( + TypeDecimal byte = 0 + TypeTiny byte = 1 + TypeShort byte = 2 + TypeLong byte = 3 + TypeFloat byte = 4 + TypeDouble byte = 5 + TypeNull byte = 6 + TypeTimestamp byte = 7 + TypeLonglong byte = 8 + TypeInt24 byte = 9 + TypeDate byte = 10 + /* TypeDuration original name was TypeTime, renamed to TypeDuration to resolve the conflict with Go type Time.*/ + TypeDuration byte = 11 + TypeDatetime byte = 12 + TypeYear byte = 13 + TypeNewDate byte = 14 + TypeVarchar byte = 15 + TypeBit byte = 16 + + TypeJSON byte = 0xf5 + TypeNewDecimal byte = 0xf6 + TypeEnum byte = 0xf7 + TypeSet byte = 0xf8 + TypeTinyBlob byte = 0xf9 + TypeMediumBlob byte = 0xfa + TypeLongBlob byte = 0xfb + TypeBlob byte = 0xfc + TypeVarString byte = 0xfd + TypeString byte = 0xfe + TypeGeometry byte = 0xff +) + +// TypeUnspecified is an uninitialized type. TypeDecimal is not used in MySQL. +const TypeUnspecified = TypeDecimal + +// Flag information. +const ( + NotNullFlag uint = 1 << 0 /* Field can't be NULL */ + PriKeyFlag uint = 1 << 1 /* Field is part of a primary key */ + UniqueKeyFlag uint = 1 << 2 /* Field is part of a unique key */ + MultipleKeyFlag uint = 1 << 3 /* Field is part of a key */ + BlobFlag uint = 1 << 4 /* Field is a blob */ + UnsignedFlag uint = 1 << 5 /* Field is unsigned */ + ZerofillFlag uint = 1 << 6 /* Field is zerofill */ + BinaryFlag uint = 1 << 7 /* Field is binary */ + EnumFlag uint = 1 << 8 /* Field is an enum */ + AutoIncrementFlag uint = 1 << 9 /* Field is an auto increment field */ + TimestampFlag uint = 1 << 10 /* Field is a timestamp */ + SetFlag uint = 1 << 11 /* Field is a set */ + NoDefaultValueFlag uint = 1 << 12 /* Field doesn't have a default value */ + OnUpdateNowFlag uint = 1 << 13 /* Field is set to NOW on UPDATE */ + PartKeyFlag uint = 1 << 14 /* Intern: Part of some keys */ + NumFlag uint = 1 << 15 /* Field is a num (for clients) */ + + GroupFlag uint = 1 << 15 /* Internal: Group field */ + UniqueFlag uint = 1 << 16 /* Internal: Used by sql_yacc */ + BinCmpFlag uint = 1 << 17 /* Internal: Used by sql_yacc */ + ParseToJSONFlag uint = 1 << 18 /* Internal: Used when we want to parse string to JSON in CAST */ + IsBooleanFlag uint = 1 << 19 /* Internal: Used for telling boolean literal from integer */ + PreventNullInsertFlag uint = 1 << 20 /* Prevent this Field from inserting NULL values */ +) + +// TypeInt24 bounds. +const ( + MaxUint24 = 1<<24 - 1 + MaxInt24 = 1<<23 - 1 + MinInt24 = -1 << 23 +) + +// HasNotNullFlag checks if NotNullFlag is set. +func HasNotNullFlag(flag uint) bool { + return (flag & NotNullFlag) > 0 +} + +// HasNoDefaultValueFlag checks if NoDefaultValueFlag is set. +func HasNoDefaultValueFlag(flag uint) bool { + return (flag & NoDefaultValueFlag) > 0 +} + +// HasAutoIncrementFlag checks if AutoIncrementFlag is set. +func HasAutoIncrementFlag(flag uint) bool { + return (flag & AutoIncrementFlag) > 0 +} + +// HasUnsignedFlag checks if UnsignedFlag is set. +func HasUnsignedFlag(flag uint) bool { + return (flag & UnsignedFlag) > 0 +} + +// HasZerofillFlag checks if ZerofillFlag is set. +func HasZerofillFlag(flag uint) bool { + return (flag & ZerofillFlag) > 0 +} + +// HasBinaryFlag checks if BinaryFlag is set. +func HasBinaryFlag(flag uint) bool { + return (flag & BinaryFlag) > 0 +} + +// HasPriKeyFlag checks if PriKeyFlag is set. +func HasPriKeyFlag(flag uint) bool { + return (flag & PriKeyFlag) > 0 +} + +// HasUniKeyFlag checks if UniqueKeyFlag is set. +func HasUniKeyFlag(flag uint) bool { + return (flag & UniqueKeyFlag) > 0 +} + +// HasMultipleKeyFlag checks if MultipleKeyFlag is set. +func HasMultipleKeyFlag(flag uint) bool { + return (flag & MultipleKeyFlag) > 0 +} + +// HasTimestampFlag checks if HasTimestampFlag is set. +func HasTimestampFlag(flag uint) bool { + return (flag & TimestampFlag) > 0 +} + +// HasOnUpdateNowFlag checks if OnUpdateNowFlag is set. +func HasOnUpdateNowFlag(flag uint) bool { + return (flag & OnUpdateNowFlag) > 0 +} + +// HasParseToJSONFlag checks if ParseToJSONFlag is set. +func HasParseToJSONFlag(flag uint) bool { + return (flag & ParseToJSONFlag) > 0 +} + +// HasIsBooleanFlag checks if IsBooleanFlag is set. +func HasIsBooleanFlag(flag uint) bool { + return (flag & IsBooleanFlag) > 0 +} + +// HasPreventNullInsertFlag checks if PreventNullInsertFlag is set. +func HasPreventNullInsertFlag(flag uint) bool { + return (flag & PreventNullInsertFlag) > 0 +} diff --git a/vendor/github.com/pingcap/parser/mysql/util.go b/vendor/github.com/pingcap/parser/mysql/util.go new file mode 100644 index 0000000000000000000000000000000000000000..312161c4ce90d339660d0a1d73b9bb34f2dca2a9 --- /dev/null +++ b/vendor/github.com/pingcap/parser/mysql/util.go @@ -0,0 +1,93 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package mysql + +type lengthAndDecimal struct { + length int + decimal int +} + +// defaultLengthAndDecimal provides default Flen and Decimal for fields +// from CREATE TABLE when they are unspecified. +var defaultLengthAndDecimal = map[byte]lengthAndDecimal{ + TypeBit: {1, 0}, + TypeTiny: {4, 0}, + TypeShort: {6, 0}, + TypeInt24: {9, 0}, + TypeLong: {11, 0}, + TypeLonglong: {20, 0}, + TypeDouble: {22, -1}, + TypeFloat: {12, -1}, + TypeNewDecimal: {11, 0}, + TypeDuration: {10, 0}, + TypeDate: {10, 0}, + TypeTimestamp: {19, 0}, + TypeDatetime: {19, 0}, + TypeYear: {4, 0}, + TypeString: {1, 0}, + TypeVarchar: {5, 0}, + TypeVarString: {5, 0}, + TypeTinyBlob: {255, 0}, + TypeBlob: {65535, 0}, + TypeMediumBlob: {16777215, 0}, + TypeLongBlob: {4294967295, 0}, + TypeJSON: {4294967295, 0}, + TypeNull: {0, 0}, + TypeSet: {-1, 0}, + TypeEnum: {-1, 0}, +} + +// IsIntegerType indicate whether tp is an integer type. +func IsIntegerType(tp byte) bool { + switch tp { + case TypeTiny, TypeShort, TypeInt24, TypeLong, TypeLonglong: + return true + } + return false +} + +// GetDefaultFieldLengthAndDecimal returns the default display length (flen) and decimal length for column. +// Call this when no Flen assigned in ddl. +// or column value is calculated from an expression. +// For example: "select count(*) from t;", the column type is int64 and Flen in ResultField will be 21. +// See https://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html +func GetDefaultFieldLengthAndDecimal(tp byte) (flen int, decimal int) { + val, ok := defaultLengthAndDecimal[tp] + if ok { + return val.length, val.decimal + } + return -1, -1 +} + +// defaultLengthAndDecimal provides default Flen and Decimal for fields +// from CAST when they are unspecified. +var defaultLengthAndDecimalForCast = map[byte]lengthAndDecimal{ + TypeString: {0, -1}, // Flen & Decimal differs. + TypeDate: {10, 0}, + TypeDatetime: {19, 0}, + TypeNewDecimal: {11, 0}, + TypeDuration: {10, 0}, + TypeLonglong: {22, 0}, + TypeJSON: {4194304, 0}, // Flen differs. +} + +// GetDefaultFieldLengthAndDecimalForCast returns the default display length (flen) and decimal length for casted column +// when flen or decimal is not specified. +func GetDefaultFieldLengthAndDecimalForCast(tp byte) (flen int, decimal int) { + val, ok := defaultLengthAndDecimalForCast[tp] + if ok { + return val.length, val.decimal + } + return -1, -1 +} diff --git a/vendor/github.com/pingcap/parser/opcode/opcode.go b/vendor/github.com/pingcap/parser/opcode/opcode.go new file mode 100644 index 0000000000000000000000000000000000000000..670fb2b883bd14afd87ded2fb3c21ad3d4348d17 --- /dev/null +++ b/vendor/github.com/pingcap/parser/opcode/opcode.go @@ -0,0 +1,138 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package opcode + +import ( + "fmt" + "io" +) + +// Op is opcode type. +type Op int + +// List operators. +const ( + LogicAnd Op = iota + 1 + LeftShift + RightShift + LogicOr + GE + LE + EQ + NE + LT + GT + Plus + Minus + And + Or + Mod + Xor + Div + Mul + Not + BitNeg + IntDiv + LogicXor + NullEQ + In + Like + Case + Regexp + IsNull + IsTruth + IsFalsity +) + +// Ops maps opcode to string. +var Ops = map[Op]string{ + LogicAnd: "and", + LogicOr: "or", + LogicXor: "xor", + LeftShift: "leftshift", + RightShift: "rightshift", + GE: "ge", + LE: "le", + EQ: "eq", + NE: "ne", + LT: "lt", + GT: "gt", + Plus: "plus", + Minus: "minus", + And: "bitand", + Or: "bitor", + Mod: "mod", + Xor: "bitxor", + Div: "div", + Mul: "mul", + Not: "not", + BitNeg: "bitneg", + IntDiv: "intdiv", + NullEQ: "nulleq", + In: "in", + Like: "like", + Case: "case", + Regexp: "regexp", + IsNull: "isnull", + IsTruth: "istrue", + IsFalsity: "isfalse", +} + +// String implements Stringer interface. +func (o Op) String() string { + str, ok := Ops[o] + if !ok { + panic(fmt.Sprintf("%d", o)) + } + + return str +} + +var opsLiteral = map[Op]string{ + LogicAnd: "&&", + LogicOr: "||", + LogicXor: "^", + LeftShift: "<<", + RightShift: ">>", + GE: ">=", + LE: "<=", + EQ: "==", + NE: "!=", + LT: "<", + GT: ">", + Plus: "+", + Minus: "-", + And: "&", + Or: "|", + Mod: "%", + Xor: "^", + Div: "/", + Mul: "*", + Not: "!", + BitNeg: "~", + IntDiv: "DIV", + NullEQ: "<=>", + In: "IN", + Like: "LIKE", + Case: "CASE", + Regexp: "REGEXP", + IsNull: "IS NULL", + IsTruth: "IS TRUE", + IsFalsity: "IS FALSE", +} + +// Format the ExprNode into a Writer. +func (o Op) Format(w io.Writer) { + fmt.Fprintf(w, "%s", opsLiteral[o]) +} diff --git a/vendor/github.com/pingcap/parser/parser.go b/vendor/github.com/pingcap/parser/parser.go new file mode 100644 index 0000000000000000000000000000000000000000..0eeafaccc8d9e87d52a3958d821fd985849b010f --- /dev/null +++ b/vendor/github.com/pingcap/parser/parser.go @@ -0,0 +1,12561 @@ +// Code generated by goyacc DO NOT EDIT. +// CAUTION: Generated file - DO NOT EDIT. + +// Copyright 2013 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Initial yacc source generated by ebnf2y[1] +// at 2013-10-04 23:10:47.861401015 +0200 CEST +// +// $ ebnf2y -o ql.y -oe ql.ebnf -start StatementList -pkg ql -p _ +// +// [1]: http://github.com/cznic/ebnf2y + +package parser + +import __yyfmt__ "fmt" + +import ( + "strings" + + "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/auth" + "github.com/pingcap/parser/charset" + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/opcode" + "github.com/pingcap/parser/types" +) + +type yySymType struct { + yys int + offset int // offset + item interface{} + ident string + expr ast.ExprNode + statement ast.StmtNode +} + +type yyXError struct { + state, xsym int +} + +const ( + yyDefault = 57827 + yyEOFCode = 57344 + action = 57554 + add = 57359 + addDate = 57719 + admin = 57752 + after = 57555 + algorithm = 57557 + all = 57360 + alter = 57361 + always = 57556 + analyze = 57362 + and = 57363 + andand = 57354 + andnot = 57798 + any = 57558 + as = 57364 + asc = 57365 + ascii = 57559 + assignmentEq = 57799 + autoIncrement = 57560 + avg = 57562 + avgRowLength = 57561 + begin = 57563 + between = 57366 + bigIntType = 57367 + binaryType = 57368 + binlog = 57564 + bitAnd = 57720 + bitLit = 57797 + bitOr = 57721 + bitType = 57565 + bitXor = 57722 + blobType = 57369 + boolType = 57567 + booleanType = 57566 + both = 57370 + btree = 57568 + buckets = 57753 + builtinAddDate = 57767 + builtinBitAnd = 57768 + builtinBitOr = 57769 + builtinBitXor = 57770 + builtinCast = 57771 + builtinCount = 57772 + builtinCurDate = 57773 + builtinCurTime = 57774 + builtinDateAdd = 57775 + builtinDateSub = 57776 + builtinExtract = 57777 + builtinGroupConcat = 57778 + builtinMax = 57779 + builtinMin = 57780 + builtinNow = 57781 + builtinPosition = 57782 + builtinStddevPop = 57787 + builtinStddevSamp = 57788 + builtinSubDate = 57783 + builtinSubstring = 57784 + builtinSum = 57785 + builtinSysDate = 57786 + builtinTrim = 57789 + builtinUser = 57790 + builtinVarPop = 57791 + builtinVarSamp = 57792 + by = 57371 + byteType = 57569 + cancel = 57754 + cascade = 57372 + cascaded = 57570 + caseKwd = 57373 + cast = 57723 + change = 57374 + charType = 57376 + character = 57375 + charsetKwd = 57571 + check = 57377 + checksum = 57572 + cleanup = 57573 + client = 57574 + coalesce = 57575 + collate = 57378 + collation = 57576 + column = 57379 + columns = 57577 + comment = 57578 + commit = 57579 + committed = 57580 + compact = 57581 + compressed = 57582 + compression = 57583 + connection = 57584 + consistent = 57585 + constraint = 57380 + convert = 57381 + copyKwd = 57724 + count = 57725 + create = 57382 + createTableSelect = 57819 + cross = 57383 + cumeDist = 57384 + curTime = 57726 + current = 57586 + currentDate = 57385 + currentTime = 57386 + currentTs = 57387 + currentUser = 57388 + data = 57588 + database = 57389 + databases = 57390 + dateAdd = 57727 + dateSub = 57728 + dateType = 57589 + datetimeType = 57590 + day = 57587 + dayHour = 57391 + dayMicrosecond = 57392 + dayMinute = 57393 + daySecond = 57394 + ddl = 57755 + deallocate = 57591 + decLit = 57794 + decimalType = 57395 + defaultKwd = 57396 + definer = 57592 + delayKeyWrite = 57593 + delayed = 57397 + deleteKwd = 57398 + denseRank = 57399 + desc = 57400 + describe = 57401 + disable = 57594 + distinct = 57402 + distinctRow = 57403 + div = 57404 + do = 57595 + doubleAtIdentifier = 57350 + doubleType = 57405 + drop = 57406 + dual = 57407 + duplicate = 57596 + dynamic = 57597 + elseKwd = 57408 + empty = 57812 + enable = 57598 + enclosed = 57409 + end = 57599 + engine = 57600 + engines = 57601 + enum = 57602 + eq = 57800 + yyErrCode = 57345 + escape = 57605 + escaped = 57410 + event = 57603 + events = 57604 + exclusive = 57606 + execute = 57607 + exists = 57411 + explain = 57412 + extract = 57729 + falseKwd = 57413 + fields = 57608 + first = 57609 + firstValue = 57414 + fixed = 57610 + floatLit = 57793 + floatType = 57415 + flush = 57611 + following = 57612 + forKwd = 57416 + force = 57417 + foreign = 57418 + format = 57613 + from = 57419 + full = 57614 + fulltext = 57420 + function = 57615 + ge = 57801 + generated = 57421 + getFormat = 57730 + global = 57694 + grant = 57422 + grants = 57616 + group = 57423 + groupConcat = 57731 + groups = 57424 + hash = 57617 + having = 57425 + hexLit = 57796 + highPriority = 57426 + higherThanComma = 57826 + hintBegin = 57352 + hintEnd = 57353 + hour = 57618 + hourMicrosecond = 57427 + hourMinute = 57428 + hourSecond = 57429 + identSQLErrors = 57716 + identified = 57619 + identifier = 57346 + ifKwd = 57430 + ignore = 57431 + in = 57432 + index = 57433 + indexes = 57621 + infile = 57434 + inner = 57435 + inplace = 57733 + insert = 57440 + insertValues = 57817 + int1Type = 57442 + int2Type = 57443 + int3Type = 57444 + int4Type = 57445 + int8Type = 57446 + intLit = 57795 + intType = 57441 + integerType = 57436 + internal = 57734 + interval = 57437 + into = 57438 + invalid = 57351 + invoker = 57622 + is = 57439 + isolation = 57620 + job = 57757 + jobs = 57756 + join = 57447 + jsonType = 57623 + jss = 57803 + juss = 57804 + key = 57448 + keyBlockSize = 57624 + keys = 57449 + kill = 57450 + lag = 57451 + last = 57626 + lastValue = 57452 + le = 57802 + lead = 57453 + leading = 57454 + left = 57455 + less = 57627 + level = 57628 + like = 57456 + limit = 57457 + lines = 57458 + load = 57459 + local = 57625 + localTime = 57460 + localTs = 57461 + lock = 57462 + long = 57541 + longblobType = 57463 + longtextType = 57464 + lowPriority = 57465 + lowerThanComma = 57825 + lowerThanCreateTableSelect = 57818 + lowerThanEq = 57823 + lowerThanInsertValues = 57816 + lowerThanIntervalKeyword = 57813 + lowerThanKey = 57820 + lowerThanOn = 57822 + lowerThanSetKeyword = 57815 + lowerThanStringLitToken = 57814 + lsh = 57805 + master = 57629 + max = 57736 + maxConnectionsPerHour = 57636 + maxExecutionTime = 57737 + maxQueriesPerHour = 57637 + maxRows = 57635 + maxUpdatesPerHour = 57638 + maxUserConnections = 57639 + maxValue = 57466 + mediumIntType = 57468 + mediumblobType = 57467 + mediumtextType = 57469 + merge = 57640 + microsecond = 57630 + min = 57735 + minRows = 57641 + minute = 57631 + minuteMicrosecond = 57470 + minuteSecond = 57471 + mod = 57472 + mode = 57632 + modify = 57633 + month = 57634 + names = 57642 + national = 57643 + natural = 57553 + neg = 57824 + neq = 57806 + neqSynonym = 57807 + next_row_id = 57732 + no = 57644 + noWriteToBinLog = 57474 + none = 57645 + not = 57473 + not2 = 57811 + now = 57738 + nthValue = 57475 + ntile = 57476 + null = 57477 + nulleq = 57808 + nulls = 57646 + numericType = 57478 + nvarcharType = 57479 + odbcDateType = 57356 + odbcTimeType = 57357 + odbcTimestampType = 57358 + offset = 57647 + on = 57480 + only = 57648 + option = 57481 + or = 57482 + order = 57483 + outer = 57484 + over = 57485 + packKeys = 57486 + paramMarker = 57809 + partition = 57487 + partitions = 57650 + password = 57649 + percentRank = 57488 + pipes = 57355 + pipesAsOr = 57651 + plugins = 57652 + position = 57739 + preceding = 57653 + precisionType = 57489 + prepare = 57654 + primary = 57490 + privileges = 57655 + procedure = 57491 + process = 57656 + processlist = 57657 + profiles = 57658 + quarter = 57659 + queries = 57661 + query = 57660 + quick = 57662 + rangeKwd = 57493 + rank = 57494 + read = 57495 + realType = 57496 + recent = 57740 + recover = 57663 + redundant = 57664 + references = 57497 + regexpKwd = 57498 + reload = 57665 + rename = 57499 + repeat = 57500 + repeatable = 57666 + replace = 57501 + replication = 57668 + respect = 57667 + restrict = 57502 + reverse = 57669 + revoke = 57503 + right = 57504 + rlike = 57505 + rollback = 57670 + routine = 57671 + row = 57506 + rowCount = 57672 + rowFormat = 57673 + rowNumber = 57508 + rows = 57507 + rsh = 57810 + second = 57674 + secondMicrosecond = 57509 + security = 57675 + selectKwd = 57510 + separator = 57676 + serializable = 57677 + session = 57678 + set = 57511 + shardRowIDBits = 57492 + share = 57679 + shared = 57680 + show = 57512 + signed = 57681 + singleAtIdentifier = 57349 + slave = 57682 + slow = 57683 + smallIntType = 57513 + snapshot = 57684 + some = 57693 + sql = 57514 + sqlCache = 57685 + sqlCalcFoundRows = 57515 + sqlNoCache = 57686 + start = 57687 + starting = 57516 + stats = 57758 + statsBuckets = 57761 + statsHealthy = 57762 + statsHistograms = 57760 + statsMeta = 57759 + statsPersistent = 57688 + status = 57689 + std = 57741 + stddev = 57742 + stddevPop = 57743 + stddevSamp = 57744 + stored = 57519 + straightJoin = 57517 + stringLit = 57348 + subDate = 57745 + subpartition = 57690 + subpartitions = 57691 + substring = 57747 + sum = 57746 + super = 57692 + tableKwd = 57518 + tableRefPriority = 57821 + tables = 57695 + tablespace = 57696 + temporary = 57697 + temptable = 57698 + terminated = 57520 + textType = 57699 + than = 57700 + then = 57521 + tidb = 57763 + tidbHJ = 57764 + tidbINLJ = 57766 + tidbSMJ = 57765 + timeType = 57701 + timestampAdd = 57748 + timestampDiff = 57749 + timestampType = 57702 + tinyIntType = 57523 + tinyblobType = 57522 + tinytextType = 57524 + to = 57525 + top = 57750 + trace = 57703 + trailing = 57526 + transaction = 57704 + trigger = 57527 + triggers = 57705 + trim = 57751 + trueKwd = 57528 + truncate = 57706 + unbounded = 57707 + uncommitted = 57708 + undefined = 57711 + underscoreCS = 57347 + union = 57530 + unique = 57529 + unknown = 57709 + unlock = 57531 + unsigned = 57532 + update = 57533 + usage = 57534 + use = 57535 + user = 57710 + using = 57536 + utcDate = 57537 + utcTime = 57539 + utcTimestamp = 57538 + value = 57712 + values = 57540 + varbinaryType = 57543 + varcharType = 57542 + variables = 57713 + view = 57714 + virtual = 57544 + warnings = 57715 + week = 57717 + when = 57545 + where = 57546 + window = 57548 + with = 57549 + write = 57547 + xor = 57550 + yearMonth = 57551 + yearType = 57718 + zerofill = 57552 + + yyMaxDepth = 200 + yyTabOfs = -1431 +) + +var ( + yyXLAT = map[int]int{ + 57344: 0, // $end (1213x) + 59: 1, // ';' (1212x) + 57578: 2, // comment (1116x) + 57560: 3, // autoIncrement (1090x) + 57609: 4, // first (1055x) + 57555: 5, // after (1054x) + 44: 6, // ',' (1037x) + 57571: 7, // charsetKwd (979x) + 57624: 8, // keyBlockSize (965x) + 41: 9, // ')' (964x) + 57600: 10, // engine (959x) + 57584: 11, // connection (952x) + 57649: 12, // password (952x) + 57681: 13, // signed (951x) + 57572: 14, // checksum (950x) + 57561: 15, // avgRowLength (949x) + 57583: 16, // compression (949x) + 57593: 17, // delayKeyWrite (949x) + 57635: 18, // maxRows (949x) + 57641: 19, // minRows (949x) + 57673: 20, // rowFormat (949x) + 57688: 21, // statsPersistent (949x) + 57714: 22, // view (927x) + 57676: 23, // separator (919x) + 57689: 24, // status (919x) + 57695: 25, // tables (919x) + 57653: 26, // preceding (918x) + 57696: 27, // tablespace (917x) + 57718: 28, // yearType (917x) + 57577: 29, // columns (916x) + 57587: 30, // day (916x) + 57618: 31, // hour (916x) + 57630: 32, // microsecond (916x) + 57631: 33, // minute (916x) + 57634: 34, // month (916x) + 57659: 35, // quarter (916x) + 57674: 36, // second (916x) + 57717: 37, // week (916x) + 57592: 38, // definer (915x) + 57608: 39, // fields (915x) + 57619: 40, // identified (915x) + 57737: 41, // maxExecutionTime (915x) + 57667: 42, // respect (915x) + 57764: 43, // tidbHJ (915x) + 57766: 44, // tidbINLJ (915x) + 57765: 45, // tidbSMJ (915x) + 57612: 46, // following (914x) + 57586: 47, // current (913x) + 57599: 48, // end (913x) + 57655: 49, // privileges (913x) + 57707: 50, // unbounded (913x) + 57557: 51, // algorithm (912x) + 57607: 52, // execute (912x) + 57647: 53, // offset (912x) + 57650: 54, // partitions (912x) + 57654: 55, // prepare (912x) + 57590: 56, // datetimeType (911x) + 57589: 57, // dateType (911x) + 57620: 58, // isolation (911x) + 57625: 59, // local (911x) + 57690: 60, // subpartition (911x) + 57701: 61, // timeType (911x) + 57710: 62, // user (911x) + 57713: 63, // variables (911x) + 57603: 64, // event (910x) + 57617: 65, // hash (910x) + 57623: 66, // jsonType (910x) + 57732: 67, // next_row_id (910x) + 57656: 68, // process (910x) + 57657: 69, // processlist (910x) + 57660: 70, // query (910x) + 57665: 71, // reload (910x) + 57668: 72, // replication (910x) + 57692: 73, // super (910x) + 57709: 74, // unknown (910x) + 57712: 75, // value (910x) + 57752: 76, // admin (909x) + 57563: 77, // begin (909x) + 57564: 78, // binlog (909x) + 57753: 79, // buckets (909x) + 57575: 80, // coalesce (909x) + 57579: 81, // commit (909x) + 57581: 82, // compact (909x) + 57582: 83, // compressed (909x) + 57724: 84, // copyKwd (909x) + 57591: 85, // deallocate (909x) + 57594: 86, // disable (909x) + 57595: 87, // do (909x) + 57597: 88, // dynamic (909x) + 57598: 89, // enable (909x) + 57610: 90, // fixed (909x) + 57611: 91, // flush (909x) + 57733: 92, // inplace (909x) + 57756: 93, // jobs (909x) + 57633: 94, // modify (909x) + 57644: 95, // no (909x) + 57646: 96, // nulls (909x) + 57664: 97, // redundant (909x) + 57670: 98, // rollback (909x) + 57671: 99, // routine (909x) + 57687: 100, // start (909x) + 57758: 101, // stats (909x) + 57691: 102, // subpartitions (909x) + 57702: 103, // timestampType (909x) + 57703: 104, // trace (909x) + 57706: 105, // truncate (909x) + 57554: 106, // action (908x) + 57556: 107, // always (908x) + 57565: 108, // bitType (908x) + 57566: 109, // booleanType (908x) + 57567: 110, // boolType (908x) + 57568: 111, // btree (908x) + 57754: 112, // cancel (908x) + 57570: 113, // cascaded (908x) + 57573: 114, // cleanup (908x) + 57574: 115, // client (908x) + 57576: 116, // collation (908x) + 57580: 117, // committed (908x) + 57585: 118, // consistent (908x) + 57588: 119, // data (908x) + 57755: 120, // ddl (908x) + 57596: 121, // duplicate (908x) + 57601: 122, // engines (908x) + 57602: 123, // enum (908x) + 57604: 124, // events (908x) + 57606: 125, // exclusive (908x) + 57613: 126, // format (908x) + 57614: 127, // full (908x) + 57615: 128, // function (908x) + 57694: 129, // global (908x) + 57616: 130, // grants (908x) + 57716: 131, // identSQLErrors (908x) + 57621: 132, // indexes (908x) + 57734: 133, // internal (908x) + 57622: 134, // invoker (908x) + 57757: 135, // job (908x) + 57626: 136, // last (908x) + 57627: 137, // less (908x) + 57628: 138, // level (908x) + 57629: 139, // master (908x) + 57636: 140, // maxConnectionsPerHour (908x) + 57637: 141, // maxQueriesPerHour (908x) + 57638: 142, // maxUpdatesPerHour (908x) + 57639: 143, // maxUserConnections (908x) + 57640: 144, // merge (908x) + 57632: 145, // mode (908x) + 57643: 146, // national (908x) + 57645: 147, // none (908x) + 57648: 148, // only (908x) + 57652: 149, // plugins (908x) + 57658: 150, // profiles (908x) + 57661: 151, // queries (908x) + 57740: 152, // recent (908x) + 57663: 153, // recover (908x) + 57666: 154, // repeatable (908x) + 57675: 155, // security (908x) + 57677: 156, // serializable (908x) + 57678: 157, // session (908x) + 57679: 158, // share (908x) + 57680: 159, // shared (908x) + 57682: 160, // slave (908x) + 57684: 161, // snapshot (908x) + 57761: 162, // statsBuckets (908x) + 57762: 163, // statsHealthy (908x) + 57760: 164, // statsHistograms (908x) + 57759: 165, // statsMeta (908x) + 57697: 166, // temporary (908x) + 57698: 167, // temptable (908x) + 57699: 168, // textType (908x) + 57700: 169, // than (908x) + 57763: 170, // tidb (908x) + 57750: 171, // top (908x) + 57704: 172, // transaction (908x) + 57705: 173, // triggers (908x) + 57708: 174, // uncommitted (908x) + 57711: 175, // undefined (908x) + 57715: 176, // warnings (908x) + 57719: 177, // addDate (907x) + 57558: 178, // any (907x) + 57559: 179, // ascii (907x) + 57562: 180, // avg (907x) + 57720: 181, // bitAnd (907x) + 57721: 182, // bitOr (907x) + 57722: 183, // bitXor (907x) + 57569: 184, // byteType (907x) + 57723: 185, // cast (907x) + 57725: 186, // count (907x) + 57726: 187, // curTime (907x) + 57727: 188, // dateAdd (907x) + 57728: 189, // dateSub (907x) + 57605: 190, // escape (907x) + 57729: 191, // extract (907x) + 57730: 192, // getFormat (907x) + 57731: 193, // groupConcat (907x) + 57346: 194, // identifier (907x) + 57736: 195, // max (907x) + 57735: 196, // min (907x) + 57642: 197, // names (907x) + 57738: 198, // now (907x) + 57739: 199, // position (907x) + 57662: 200, // quick (907x) + 57669: 201, // reverse (907x) + 57672: 202, // rowCount (907x) + 57683: 203, // slow (907x) + 57693: 204, // some (907x) + 57685: 205, // sqlCache (907x) + 57686: 206, // sqlNoCache (907x) + 57741: 207, // std (907x) + 57742: 208, // stddev (907x) + 57743: 209, // stddevPop (907x) + 57744: 210, // stddevSamp (907x) + 57745: 211, // subDate (907x) + 57747: 212, // substring (907x) + 57746: 213, // sum (907x) + 57748: 214, // timestampAdd (907x) + 57749: 215, // timestampDiff (907x) + 57751: 216, // trim (907x) + 40: 217, // '(' (780x) + 57480: 218, // on (770x) + 57348: 219, // stringLit (736x) + 57473: 220, // not (724x) + 57364: 221, // as (677x) + 57455: 222, // left (675x) + 57504: 223, // right (675x) + 43: 224, // '+' (632x) + 45: 225, // '-' (632x) + 57472: 226, // mod (630x) + 57396: 227, // defaultKwd (625x) + 57549: 228, // with (591x) + 57530: 229, // union (581x) + 57477: 230, // null (570x) + 57462: 231, // lock (569x) + 57416: 232, // forKwd (562x) + 57457: 233, // limit (552x) + 57483: 234, // order (550x) + 57363: 235, // and (548x) + 57482: 236, // or (537x) + 57354: 237, // andand (536x) + 57651: 238, // pipesAsOr (536x) + 57550: 239, // xor (536x) + 57546: 240, // where (533x) + 57419: 241, // from (520x) + 57536: 242, // using (519x) + 57800: 243, // eq (509x) + 57517: 244, // straightJoin (502x) + 57548: 245, // window (500x) + 57511: 246, // set (499x) + 57425: 247, // having (498x) + 57447: 248, // join (495x) + 57378: 249, // collate (490x) + 57423: 250, // group (490x) + 57383: 251, // cross (484x) + 57435: 252, // inner (484x) + 57553: 253, // natural (484x) + 125: 254, // '}' (483x) + 57501: 255, // replace (480x) + 57795: 256, // intLit (477x) + 57456: 257, // like (477x) + 42: 258, // '*' (472x) + 57493: 259, // rangeKwd (468x) + 57424: 260, // groups (467x) + 57507: 261, // rows (467x) + 57400: 262, // desc (464x) + 57365: 263, // asc (462x) + 57391: 264, // dayHour (461x) + 57392: 265, // dayMicrosecond (461x) + 57393: 266, // dayMinute (461x) + 57394: 267, // daySecond (461x) + 57427: 268, // hourMicrosecond (461x) + 57428: 269, // hourMinute (461x) + 57429: 270, // hourSecond (461x) + 57470: 271, // minuteMicrosecond (461x) + 57471: 272, // minuteSecond (461x) + 57509: 273, // secondMicrosecond (461x) + 57545: 274, // when (461x) + 57551: 275, // yearMonth (461x) + 57408: 276, // elseKwd (458x) + 57432: 277, // in (455x) + 57521: 278, // then (455x) + 46: 279, // '.' (451x) + 60: 280, // '<' (449x) + 62: 281, // '>' (449x) + 57801: 282, // ge (449x) + 57439: 283, // is (449x) + 57802: 284, // le (449x) + 57806: 285, // neq (449x) + 57807: 286, // neqSynonym (449x) + 57808: 287, // nulleq (449x) + 57368: 288, // binaryType (446x) + 57366: 289, // between (441x) + 37: 290, // '%' (440x) + 38: 291, // '&' (440x) + 47: 292, // '/' (440x) + 94: 293, // '^' (440x) + 124: 294, // '|' (440x) + 57404: 295, // div (440x) + 57805: 296, // lsh (440x) + 57810: 297, // rsh (440x) + 57498: 298, // regexpKwd (437x) + 57505: 299, // rlike (437x) + 57388: 300, // currentUser (421x) + 57440: 301, // insert (419x) + 57430: 302, // ifKwd (418x) + 123: 303, // '{' (417x) + 57794: 304, // decLit (417x) + 57793: 305, // floatLit (417x) + 57809: 306, // paramMarker (417x) + 57349: 307, // singleAtIdentifier (415x) + 57376: 308, // charType (414x) + 57437: 309, // interval (413x) + 57540: 310, // values (412x) + 57411: 311, // exists (411x) + 57413: 312, // falseKwd (411x) + 57528: 313, // trueKwd (411x) + 57381: 314, // convert (410x) + 57389: 315, // database (409x) + 57797: 316, // bitLit (408x) + 57781: 317, // builtinNow (408x) + 57387: 318, // currentTs (408x) + 57350: 319, // doubleAtIdentifier (408x) + 57796: 320, // hexLit (408x) + 57460: 321, // localTime (408x) + 57461: 322, // localTs (408x) + 57347: 323, // underscoreCS (408x) + 57506: 324, // row (407x) + 33: 325, // '!' (406x) + 126: 326, // '~' (406x) + 57767: 327, // builtinAddDate (406x) + 57768: 328, // builtinBitAnd (406x) + 57769: 329, // builtinBitOr (406x) + 57770: 330, // builtinBitXor (406x) + 57771: 331, // builtinCast (406x) + 57772: 332, // builtinCount (406x) + 57773: 333, // builtinCurDate (406x) + 57774: 334, // builtinCurTime (406x) + 57775: 335, // builtinDateAdd (406x) + 57776: 336, // builtinDateSub (406x) + 57777: 337, // builtinExtract (406x) + 57778: 338, // builtinGroupConcat (406x) + 57779: 339, // builtinMax (406x) + 57780: 340, // builtinMin (406x) + 57782: 341, // builtinPosition (406x) + 57787: 342, // builtinStddevPop (406x) + 57788: 343, // builtinStddevSamp (406x) + 57783: 344, // builtinSubDate (406x) + 57784: 345, // builtinSubstring (406x) + 57785: 346, // builtinSum (406x) + 57786: 347, // builtinSysDate (406x) + 57789: 348, // builtinTrim (406x) + 57790: 349, // builtinUser (406x) + 57373: 350, // caseKwd (406x) + 57384: 351, // cumeDist (406x) + 57385: 352, // currentDate (406x) + 57386: 353, // currentTime (406x) + 57399: 354, // denseRank (406x) + 57414: 355, // firstValue (406x) + 57451: 356, // lag (406x) + 57452: 357, // lastValue (406x) + 57453: 358, // lead (406x) + 57811: 359, // not2 (406x) + 57475: 360, // nthValue (406x) + 57476: 361, // ntile (406x) + 57488: 362, // percentRank (406x) + 57355: 363, // pipes (406x) + 57494: 364, // rank (406x) + 57500: 365, // repeat (406x) + 57508: 366, // rowNumber (406x) + 57537: 367, // utcDate (406x) + 57539: 368, // utcTime (406x) + 57538: 369, // utcTimestamp (406x) + 57448: 370, // key (396x) + 57490: 371, // primary (385x) + 57529: 372, // unique (381x) + 57377: 373, // check (378x) + 57497: 374, // references (377x) + 57421: 375, // generated (373x) + 57964: 376, // Identifier (331x) + 57431: 377, // ignore (331x) + 58017: 378, // NotKeywordToken (331x) + 58148: 379, // TiDBKeyword (331x) + 58158: 380, // UnReservedKeyword (331x) + 57510: 381, // selectKwd (320x) + 57375: 382, // character (296x) + 57487: 383, // partition (270x) + 57486: 384, // packKeys (262x) + 57492: 385, // shardRowIDBits (262x) + 57803: 386, // jss (252x) + 57804: 387, // juss (252x) + 57433: 388, // index (248x) + 57458: 389, // lines (237x) + 57371: 390, // by (234x) + 57514: 391, // sql (233x) + 57417: 392, // force (230x) + 57535: 393, // use (230x) + 57406: 394, // drop (229x) + 57372: 395, // cascade (228x) + 57502: 396, // restrict (228x) + 57525: 397, // to (228x) + 57495: 398, // read (226x) + 57361: 399, // alter (225x) + 57362: 400, // analyze (225x) + 57418: 401, // foreign (224x) + 57420: 402, // fulltext (223x) + 57395: 403, // decimalType (222x) + 57436: 404, // integerType (222x) + 57441: 405, // intType (222x) + 57499: 406, // rename (222x) + 57542: 407, // varcharType (222x) + 64: 408, // '@' (220x) + 57359: 409, // add (220x) + 57367: 410, // bigIntType (220x) + 57369: 411, // blobType (220x) + 57374: 412, // change (220x) + 57405: 413, // doubleType (220x) + 57415: 414, // floatType (220x) + 57442: 415, // int1Type (220x) + 57443: 416, // int2Type (220x) + 57444: 417, // int3Type (220x) + 57445: 418, // int4Type (220x) + 57446: 419, // int8Type (220x) + 57541: 420, // long (220x) + 57463: 421, // longblobType (220x) + 57464: 422, // longtextType (220x) + 57467: 423, // mediumblobType (220x) + 57468: 424, // mediumIntType (220x) + 57469: 425, // mediumtextType (220x) + 57478: 426, // numericType (220x) + 57479: 427, // nvarcharType (220x) + 57496: 428, // realType (220x) + 57513: 429, // smallIntType (220x) + 57522: 430, // tinyblobType (220x) + 57523: 431, // tinyIntType (220x) + 57524: 432, // tinytextType (220x) + 57543: 433, // varbinaryType (220x) + 57547: 434, // write (220x) + 58120: 435, // SubSelect (143x) + 58168: 436, // UserVariable (140x) + 58003: 437, // Literal (139x) + 58108: 438, // SimpleIdent (139x) + 58115: 439, // StringLiteral (139x) + 57946: 440, // FunctionCallGeneric (137x) + 57947: 441, // FunctionCallKeyword (137x) + 57948: 442, // FunctionCallNonKeyword (137x) + 57949: 443, // FunctionNameConflict (137x) + 57950: 444, // FunctionNameDateArith (137x) + 57951: 445, // FunctionNameDateArithMultiForms (137x) + 57952: 446, // FunctionNameDatetimePrecision (137x) + 57953: 447, // FunctionNameOptionalBraces (137x) + 58107: 448, // SimpleExpr (137x) + 58121: 449, // SumExpr (137x) + 58123: 450, // SystemVariable (137x) + 58177: 451, // Variable (137x) + 58199: 452, // WindowFuncCall (137x) + 57847: 453, // BitExpr (125x) + 58065: 454, // PredicateExpr (109x) + 57850: 455, // BoolPri (106x) + 57922: 456, // Expression (106x) + 58207: 457, // logAnd (84x) + 58208: 458, // logOr (84x) + 58132: 459, // TableName (52x) + 57532: 460, // unsigned (44x) + 58014: 461, // NUM (43x) + 57552: 462, // zerofill (42x) + 57485: 463, // over (36x) + 57863: 464, // ColumnName (35x) + 57360: 465, // all (31x) + 58116: 466, // StringName (30x) + 58204: 467, // WindowingClause (26x) + 57914: 468, // EqOpt (24x) + 58087: 469, // SelectStmt (24x) + 58088: 470, // SelectStmtBasic (24x) + 58091: 471, // SelectStmtFromDualTable (24x) + 58092: 472, // SelectStmtFromTable (24x) + 57929: 473, // FieldLen (21x) + 57518: 474, // tableKwd (21x) + 58161: 475, // UnionSelect (19x) + 57995: 476, // LengthNum (18x) + 58159: 477, // UnionClauseList (18x) + 58162: 478, // UnionStmt (18x) + 57533: 479, // update (17x) + 57515: 480, // sqlCalcFoundRows (16x) + 57856: 481, // CharsetKw (15x) + 57397: 482, // delayed (15x) + 57426: 483, // highPriority (15x) + 57465: 484, // lowPriority (15x) + 58046: 485, // OptWindowingClause (15x) + 57398: 486, // deleteKwd (14x) + 58034: 487, // OptFieldLen (14x) + 57923: 488, // ExpressionList (13x) + 57989: 489, // JoinTable (13x) + 58129: 490, // TableFactor (13x) + 58141: 491, // TableRef (13x) + 57402: 492, // distinct (12x) + 57403: 493, // distinctRow (12x) + 58170: 494, // Username (11x) + 57901: 495, // DistinctKwd (10x) + 57942: 496, // FromOrIn (10x) + 57438: 497, // into (10x) + 58050: 498, // OrderBy (10x) + 58051: 499, // OrderByOptional (10x) + 57902: 500, // DistinctOpt (9x) + 57981: 501, // IndexType (9x) + 57990: 502, // JoinType (9x) + 58133: 503, // TableNameList (9x) + 57857: 504, // CharsetName (8x) + 57864: 505, // ColumnNameList (8x) + 57887: 506, // CrossOpt (8x) + 57896: 507, // DefaultFalseDistinctOpt (8x) + 57897: 508, // DefaultKwdOpt (8x) + 57970: 509, // IndexColName (8x) + 57991: 510, // KeyOrIndex (8x) + 58032: 511, // OptCollate (8x) + 57852: 512, // BuggyDefaultFalseDistinctOpt (7x) + 57859: 513, // ColumnDef (7x) + 57900: 514, // DeleteFromStmt (7x) + 57410: 515, // escaped (7x) + 57916: 516, // EscapedTableRef (7x) + 57353: 517, // hintEnd (7x) + 57971: 518, // IndexColNameList (7x) + 57983: 519, // InsertIntoStmt (7x) + 58080: 520, // ReplaceIntoStmt (7x) + 58094: 521, // SelectStmtLimit (7x) + 58149: 522, // TimeUnit (7x) + 58164: 523, // UpdateStmt (7x) + 58189: 524, // WhereClause (7x) + 58190: 525, // WhereClauseOptional (7x) + 57382: 526, // create (6x) + 57921: 527, // ExprOrDefault (6x) + 57422: 528, // grant (6x) + 58011: 529, // MaxNumBuckets (6x) + 58022: 530, // NumLiteral (6x) + 58030: 531, // OptBinary (6x) + 58084: 532, // RowFormat (6x) + 58086: 533, // SelectLockOpt (6x) + 57512: 534, // show (6x) + 58100: 535, // ShowDatabaseNameOpt (6x) + 58138: 536, // TableOption (6x) + 58142: 537, // TableRefs (6x) + 57520: 538, // terminated (6x) + 57853: 539, // ByItem (5x) + 57379: 540, // column (5x) + 57861: 541, // ColumnKeywordOpt (5x) + 57888: 542, // DBName (5x) + 57409: 543, // enclosed (5x) + 57924: 544, // ExpressionListOpt (5x) + 57931: 545, // FieldOpt (5x) + 57932: 546, // FieldOpts (5x) + 57977: 547, // IndexName (5x) + 57979: 548, // IndexOption (5x) + 57980: 549, // IndexOptionList (5x) + 58041: 550, // OptNullTreatment (5x) + 58069: 551, // PriorityOpt (5x) + 58102: 552, // ShowLikeOrWhereOpt (5x) + 58166: 553, // UserSpec (5x) + 57839: 554, // Assignment (4x) + 57843: 555, // AuthString (4x) + 57854: 556, // ByList (4x) + 57968: 557, // IgnoreOptional (4x) + 57978: 558, // IndexNameList (4x) + 57982: 559, // IndexTypeOpt (4x) + 58000: 560, // LimitOption (4x) + 57481: 561, // option (4x) + 57484: 562, // outer (4x) + 58059: 563, // PartitionDefinitionListOpt (4x) + 58061: 564, // PartitionNumOpt (4x) + 58098: 565, // SetExpr (4x) + 58124: 566, // TableAsName (4x) + 58153: 567, // TransactionChar (4x) + 58167: 568, // UserSpecList (4x) + 58200: 569, // WindowName (4x) + 57799: 570, // assignmentEq (3x) + 57840: 571, // AssignmentList (3x) + 57870: 572, // ColumnPosition (3x) + 57876: 573, // Constraint (3x) + 57380: 574, // constraint (3x) + 57878: 575, // ConstraintKeywordOpt (3x) + 57920: 576, // ExplainableStmt (3x) + 57937: 577, // FloatOpt (3x) + 57352: 578, // hintBegin (3x) + 57963: 579, // HintTableList (3x) + 57965: 580, // IfExists (3x) + 57966: 581, // IfNotExists (3x) + 57972: 582, // IndexHint (3x) + 57976: 583, // IndexHintType (3x) + 57434: 584, // infile (3x) + 57449: 585, // keys (3x) + 58007: 586, // LockClause (3x) + 57466: 587, // maxValue (3x) + 58031: 588, // OptCharset (3x) + 58064: 589, // Precision (3x) + 58070: 590, // PrivElem (3x) + 58073: 591, // PrivType (3x) + 58075: 592, // ReferDef (3x) + 58081: 593, // RestrictOrCascadeOpt (3x) + 58085: 594, // RowValue (3x) + 58137: 595, // TableOptimizerHints (3x) + 58139: 596, // TableOptionList (3x) + 58154: 597, // TransactionChars (3x) + 57527: 598, // trigger (3x) + 57534: 599, // usage (3x) + 58172: 600, // ValueSym (3x) + 58197: 601, // WindowFrameStart (3x) + 57829: 602, // AdminStmt (2x) + 57831: 603, // AlterTableOptionListOpt (2x) + 57832: 604, // AlterTableSpec (2x) + 57834: 605, // AlterTableStmt (2x) + 57835: 606, // AlterUserStmt (2x) + 57836: 607, // AnalyzeTableStmt (2x) + 57844: 608, // BeginTransactionStmt (2x) + 57846: 609, // BinlogStmt (2x) + 57855: 610, // CastType (2x) + 57865: 611, // ColumnNameListOpt (2x) + 57867: 612, // ColumnOption (2x) + 57871: 613, // ColumnSetValue (2x) + 57874: 614, // CommitStmt (2x) + 57879: 615, // CreateDatabaseStmt (2x) + 57880: 616, // CreateIndexStmt (2x) + 57884: 617, // CreateTableStmt (2x) + 57885: 618, // CreateUserStmt (2x) + 57886: 619, // CreateViewStmt (2x) + 57889: 620, // DatabaseOption (2x) + 57390: 621, // databases (2x) + 57892: 622, // DatabaseSym (2x) + 57894: 623, // DeallocateStmt (2x) + 57895: 624, // DeallocateSym (2x) + 57401: 625, // describe (2x) + 57903: 626, // DoStmt (2x) + 57904: 627, // DropDatabaseStmt (2x) + 57905: 628, // DropIndexStmt (2x) + 57906: 629, // DropStatsStmt (2x) + 57907: 630, // DropTableStmt (2x) + 57908: 631, // DropUserStmt (2x) + 57909: 632, // DropViewStmt (2x) + 57912: 633, // EmptyStmt (2x) + 57917: 634, // ExecuteStmt (2x) + 57412: 635, // explain (2x) + 57918: 636, // ExplainStmt (2x) + 57919: 637, // ExplainSym (2x) + 57926: 638, // Field (2x) + 57927: 639, // FieldAsName (2x) + 57928: 640, // FieldAsNameOpt (2x) + 57940: 641, // FlushStmt (2x) + 57941: 642, // FromDual (2x) + 57944: 643, // FuncDatetimePrecList (2x) + 57945: 644, // FuncDatetimePrecListOpt (2x) + 57954: 645, // GeneratedAlways (2x) + 57957: 646, // GrantStmt (2x) + 57959: 647, // HandleRange (2x) + 57961: 648, // HashString (2x) + 57973: 649, // IndexHintList (2x) + 57974: 650, // IndexHintListOpt (2x) + 57984: 651, // InsertValues (2x) + 57986: 652, // IntoOpt (2x) + 57450: 653, // kill (2x) + 57993: 654, // KillOrKillTiDB (2x) + 57994: 655, // KillStmt (2x) + 57999: 656, // LimitClause (2x) + 57459: 657, // load (2x) + 58004: 658, // LoadDataStmt (2x) + 58005: 659, // LoadStatsStmt (2x) + 58009: 660, // LockTablesStmt (2x) + 58012: 661, // MaxValueOrExpression (2x) + 58018: 662, // NowSym (2x) + 58019: 663, // NowSymFunc (2x) + 58020: 664, // NowSymOptionFraction (2x) + 58021: 665, // NumList (2x) + 58025: 666, // ObjectType (2x) + 58024: 667, // ODBCDateTimeType (2x) + 57356: 668, // odbcDateType (2x) + 57358: 669, // odbcTimestampType (2x) + 57357: 670, // odbcTimeType (2x) + 58038: 671, // OptInteger (2x) + 58047: 672, // OptionalBraces (2x) + 58040: 673, // OptLeadLagInfo (2x) + 58039: 674, // OptLLDefault (2x) + 58049: 675, // Order (2x) + 58052: 676, // OuterOpt (2x) + 58053: 677, // PartDefOption (2x) + 58057: 678, // PartitionDefinition (2x) + 58060: 679, // PartitionNameList (2x) + 58063: 680, // PasswordOpt (2x) + 58067: 681, // PreparedStmt (2x) + 58068: 682, // PrimaryOpt (2x) + 58071: 683, // PrivElemList (2x) + 58072: 684, // PrivLevel (2x) + 58076: 685, // ReferOpt (2x) + 58078: 686, // RegexpSym (2x) + 58079: 687, // RenameTableStmt (2x) + 57503: 688, // revoke (2x) + 58082: 689, // RevokeStmt (2x) + 58083: 690, // RollbackStmt (2x) + 58099: 691, // SetStmt (2x) + 58103: 692, // ShowStmt (2x) + 58104: 693, // ShowTableAliasOpt (2x) + 58106: 694, // SignedLiteral (2x) + 58111: 695, // Statement (2x) + 58113: 696, // StatsPersistentVal (2x) + 58114: 697, // StringList (2x) + 58118: 698, // SubPartitionNumOpt (2x) + 58122: 699, // Symbol (2x) + 58126: 700, // TableElement (2x) + 58130: 701, // TableLock (2x) + 58136: 702, // TableOptimizerHintOpt (2x) + 58140: 703, // TableOrTables (2x) + 58146: 704, // TablesTerminalSym (2x) + 58144: 705, // TableToTable (2x) + 58150: 706, // TimestampUnit (2x) + 58152: 707, // TraceableStmt (2x) + 58151: 708, // TraceStmt (2x) + 58156: 709, // TruncateTableStmt (2x) + 57531: 710, // unlock (2x) + 58163: 711, // UnlockTablesStmt (2x) + 58171: 712, // UsernameList (2x) + 58165: 713, // UseStmt (2x) + 58174: 714, // ValuesList (2x) + 58178: 715, // VariableAssignment (2x) + 58187: 716, // WhenClause (2x) + 58192: 717, // WindowDefinition (2x) + 58195: 718, // WindowFrameBound (2x) + 58202: 719, // WindowSpec (2x) + 57828: 720, // AdminShowSlow (1x) + 57830: 721, // AlterAlgorithm (1x) + 57833: 722, // AlterTableSpecList (1x) + 57837: 723, // AnyOrAll (1x) + 57838: 724, // AsOpt (1x) + 57842: 725, // AuthOption (1x) + 57845: 726, // BetweenOrNotOp (1x) + 57848: 727, // BitValueType (1x) + 57849: 728, // BlobType (1x) + 57851: 729, // BooleanType (1x) + 57370: 730, // both (1x) + 57858: 731, // CharsetOpt (1x) + 57860: 732, // ColumnDefList (1x) + 57862: 733, // ColumnList (1x) + 57866: 734, // ColumnNameListOptWithBrackets (1x) + 57868: 735, // ColumnOptionList (1x) + 57869: 736, // ColumnOptionListOpt (1x) + 57872: 737, // ColumnSetValueList (1x) + 57875: 738, // CompareOp (1x) + 57877: 739, // ConstraintElem (1x) + 57881: 740, // CreateIndexStmtUnique (1x) + 57882: 741, // CreateTableOptionListOpt (1x) + 57883: 742, // CreateTableSelectOpt (1x) + 57890: 743, // DatabaseOptionList (1x) + 57891: 744, // DatabaseOptionListOpt (1x) + 57893: 745, // DateAndTimeType (1x) + 57898: 746, // DefaultTrueDistinctOpt (1x) + 57899: 747, // DefaultValueExpr (1x) + 57407: 748, // dual (1x) + 57910: 749, // DuplicateOpt (1x) + 57911: 750, // ElseOpt (1x) + 57913: 751, // Enclosed (1x) + 57915: 752, // Escaped (1x) + 57925: 753, // ExpressionOpt (1x) + 57930: 754, // FieldList (1x) + 57933: 755, // Fields (1x) + 57934: 756, // FieldsOrColumns (1x) + 57935: 757, // FieldsTerminated (1x) + 57936: 758, // FixedPointType (1x) + 57938: 759, // FloatingPointType (1x) + 57939: 760, // FlushOption (1x) + 57943: 761, // FuncDatetimePrec (1x) + 57955: 762, // GetFormatSelector (1x) + 57956: 763, // GlobalScope (1x) + 57958: 764, // GroupByClause (1x) + 57960: 765, // HandleRangeList (1x) + 57962: 766, // HavingClause (1x) + 57967: 767, // IgnoreLines (1x) + 57975: 768, // IndexHintScope (1x) + 57969: 769, // InOrNotOp (1x) + 57985: 770, // IntegerType (1x) + 57988: 771, // IsolationLevel (1x) + 57987: 772, // IsOrNotOp (1x) + 57992: 773, // KeyOrIndexOpt (1x) + 57454: 774, // leading (1x) + 57996: 775, // LikeEscapeOpt (1x) + 57997: 776, // LikeOrNotOp (1x) + 57998: 777, // LikeTableWithOrWithoutParen (1x) + 58001: 778, // Lines (1x) + 58002: 779, // LinesTerminated (1x) + 58006: 780, // LocalOpt (1x) + 58008: 781, // LockClauseOpt (1x) + 58010: 782, // LockType (1x) + 58013: 783, // MaxValueOrExpressionList (1x) + 58015: 784, // NationalOpt (1x) + 57474: 785, // noWriteToBinLog (1x) + 58016: 786, // NoWriteToBinLogAliasOpt (1x) + 58023: 787, // NumericType (1x) + 58026: 788, // OnDeleteOpt (1x) + 58027: 789, // OnDuplicateKeyUpdate (1x) + 58028: 790, // OnUpdateOpt (1x) + 58029: 791, // OptBinMod (1x) + 58033: 792, // OptExistingWindowName (1x) + 58035: 793, // OptFromFirstLast (1x) + 58036: 794, // OptFull (1x) + 58037: 795, // OptGConcatSeparator (1x) + 58042: 796, // OptPartitionClause (1x) + 58043: 797, // OptTable (1x) + 58044: 798, // OptWindowFrameClause (1x) + 58045: 799, // OptWindowOrderByClause (1x) + 58048: 800, // OrReplace (1x) + 58054: 801, // PartDefOptionList (1x) + 58055: 802, // PartDefOptionsOpt (1x) + 58056: 803, // PartDefValuesOpt (1x) + 58058: 804, // PartitionDefinitionList (1x) + 58062: 805, // PartitionOpt (1x) + 57489: 806, // precisionType (1x) + 58066: 807, // PrepareSQL (1x) + 57491: 808, // procedure (1x) + 58074: 809, // QuickOptional (1x) + 58077: 810, // RegexpOrNotOp (1x) + 58089: 811, // SelectStmtCalcFoundRows (1x) + 58090: 812, // SelectStmtFieldList (1x) + 58093: 813, // SelectStmtGroup (1x) + 58095: 814, // SelectStmtOpts (1x) + 58096: 815, // SelectStmtSQLCache (1x) + 58097: 816, // SelectStmtStraightJoin (1x) + 58101: 817, // ShowIndexKwd (1x) + 58105: 818, // ShowTargetFilterable (1x) + 58109: 819, // Start (1x) + 58110: 820, // Starting (1x) + 57516: 821, // starting (1x) + 58112: 822, // StatementList (1x) + 57519: 823, // stored (1x) + 58117: 824, // StringType (1x) + 58119: 825, // SubPartitionOpt (1x) + 58125: 826, // TableAsNameOpt (1x) + 58127: 827, // TableElementList (1x) + 58128: 828, // TableElementListOpt (1x) + 58131: 829, // TableLockList (1x) + 58134: 830, // TableNameListOpt (1x) + 58135: 831, // TableOptimizerHintList (1x) + 58143: 832, // TableRefsClause (1x) + 58145: 833, // TableToTableList (1x) + 58147: 834, // TextType (1x) + 57526: 835, // trailing (1x) + 58155: 836, // TrimDirection (1x) + 58157: 837, // Type (1x) + 58160: 838, // UnionOpt (1x) + 58169: 839, // UserVariableList (1x) + 58173: 840, // Values (1x) + 58175: 841, // ValuesOpt (1x) + 58176: 842, // Varchar (1x) + 58179: 843, // VariableAssignmentList (1x) + 58180: 844, // ViewAlgorithm (1x) + 58181: 845, // ViewCheckOption (1x) + 58182: 846, // ViewDefiner (1x) + 58183: 847, // ViewFieldList (1x) + 58184: 848, // ViewName (1x) + 58185: 849, // ViewSQLSecurity (1x) + 57544: 850, // virtual (1x) + 58186: 851, // VirtualOrStored (1x) + 58188: 852, // WhenClauseList (1x) + 58191: 853, // WindowClauseOptional (1x) + 58193: 854, // WindowDefinitionList (1x) + 58194: 855, // WindowFrameBetween (1x) + 58196: 856, // WindowFrameExtent (1x) + 58198: 857, // WindowFrameUnits (1x) + 58201: 858, // WindowNameOrSpec (1x) + 58203: 859, // WindowSpecDetails (1x) + 58205: 860, // WithGrantOptionOpt (1x) + 58206: 861, // WithReadLockOpt (1x) + 57827: 862, // $default (0x) + 57798: 863, // andnot (0x) + 57841: 864, // AssignmentListOpt (0x) + 57791: 865, // builtinVarPop (0x) + 57792: 866, // builtinVarSamp (0x) + 57873: 867, // CommaOpt (0x) + 57819: 868, // createTableSelect (0x) + 57812: 869, // empty (0x) + 57345: 870, // error (0x) + 57826: 871, // higherThanComma (0x) + 57817: 872, // insertValues (0x) + 57351: 873, // invalid (0x) + 57825: 874, // lowerThanComma (0x) + 57818: 875, // lowerThanCreateTableSelect (0x) + 57823: 876, // lowerThanEq (0x) + 57816: 877, // lowerThanInsertValues (0x) + 57813: 878, // lowerThanIntervalKeyword (0x) + 57820: 879, // lowerThanKey (0x) + 57822: 880, // lowerThanOn (0x) + 57815: 881, // lowerThanSetKeyword (0x) + 57814: 882, // lowerThanStringLitToken (0x) + 57824: 883, // neg (0x) + 57821: 884, // tableRefPriority (0x) + } + + yySymNames = []string{ + "$end", + "';'", + "comment", + "autoIncrement", + "first", + "after", + "','", + "charsetKwd", + "keyBlockSize", + "')'", + "engine", + "connection", + "password", + "signed", + "checksum", + "avgRowLength", + "compression", + "delayKeyWrite", + "maxRows", + "minRows", + "rowFormat", + "statsPersistent", + "view", + "separator", + "status", + "tables", + "preceding", + "tablespace", + "yearType", + "columns", + "day", + "hour", + "microsecond", + "minute", + "month", + "quarter", + "second", + "week", + "definer", + "fields", + "identified", + "maxExecutionTime", + "respect", + "tidbHJ", + "tidbINLJ", + "tidbSMJ", + "following", + "current", + "end", + "privileges", + "unbounded", + "algorithm", + "execute", + "offset", + "partitions", + "prepare", + "datetimeType", + "dateType", + "isolation", + "local", + "subpartition", + "timeType", + "user", + "variables", + "event", + "hash", + "jsonType", + "next_row_id", + "process", + "processlist", + "query", + "reload", + "replication", + "super", + "unknown", + "value", + "admin", + "begin", + "binlog", + "buckets", + "coalesce", + "commit", + "compact", + "compressed", + "copyKwd", + "deallocate", + "disable", + "do", + "dynamic", + "enable", + "fixed", + "flush", + "inplace", + "jobs", + "modify", + "no", + "nulls", + "redundant", + "rollback", + "routine", + "start", + "stats", + "subpartitions", + "timestampType", + "trace", + "truncate", + "action", + "always", + "bitType", + "booleanType", + "boolType", + "btree", + "cancel", + "cascaded", + "cleanup", + "client", + "collation", + "committed", + "consistent", + "data", + "ddl", + "duplicate", + "engines", + "enum", + "events", + "exclusive", + "format", + "full", + "function", + "global", + "grants", + "identSQLErrors", + "indexes", + "internal", + "invoker", + "job", + "last", + "less", + "level", + "master", + "maxConnectionsPerHour", + "maxQueriesPerHour", + "maxUpdatesPerHour", + "maxUserConnections", + "merge", + "mode", + "national", + "none", + "only", + "plugins", + "profiles", + "queries", + "recent", + "recover", + "repeatable", + "security", + "serializable", + "session", + "share", + "shared", + "slave", + "snapshot", + "statsBuckets", + "statsHealthy", + "statsHistograms", + "statsMeta", + "temporary", + "temptable", + "textType", + "than", + "tidb", + "top", + "transaction", + "triggers", + "uncommitted", + "undefined", + "warnings", + "addDate", + "any", + "ascii", + "avg", + "bitAnd", + "bitOr", + "bitXor", + "byteType", + "cast", + "count", + "curTime", + "dateAdd", + "dateSub", + "escape", + "extract", + "getFormat", + "groupConcat", + "identifier", + "max", + "min", + "names", + "now", + "position", + "quick", + "reverse", + "rowCount", + "slow", + "some", + "sqlCache", + "sqlNoCache", + "std", + "stddev", + "stddevPop", + "stddevSamp", + "subDate", + "substring", + "sum", + "timestampAdd", + "timestampDiff", + "trim", + "'('", + "on", + "stringLit", + "not", + "as", + "left", + "right", + "'+'", + "'-'", + "mod", + "defaultKwd", + "with", + "union", + "null", + "lock", + "forKwd", + "limit", + "order", + "and", + "or", + "andand", + "pipesAsOr", + "xor", + "where", + "from", + "using", + "eq", + "straightJoin", + "window", + "set", + "having", + "join", + "collate", + "group", + "cross", + "inner", + "natural", + "'}'", + "replace", + "intLit", + "like", + "'*'", + "rangeKwd", + "groups", + "rows", + "desc", + "asc", + "dayHour", + "dayMicrosecond", + "dayMinute", + "daySecond", + "hourMicrosecond", + "hourMinute", + "hourSecond", + "minuteMicrosecond", + "minuteSecond", + "secondMicrosecond", + "when", + "yearMonth", + "elseKwd", + "in", + "then", + "'.'", + "'<'", + "'>'", + "ge", + "is", + "le", + "neq", + "neqSynonym", + "nulleq", + "binaryType", + "between", + "'%'", + "'&'", + "'/'", + "'^'", + "'|'", + "div", + "lsh", + "rsh", + "regexpKwd", + "rlike", + "currentUser", + "insert", + "ifKwd", + "'{'", + "decLit", + "floatLit", + "paramMarker", + "singleAtIdentifier", + "charType", + "interval", + "values", + "exists", + "falseKwd", + "trueKwd", + "convert", + "database", + "bitLit", + "builtinNow", + "currentTs", + "doubleAtIdentifier", + "hexLit", + "localTime", + "localTs", + "underscoreCS", + "row", + "'!'", + "'~'", + "builtinAddDate", + "builtinBitAnd", + "builtinBitOr", + "builtinBitXor", + "builtinCast", + "builtinCount", + "builtinCurDate", + "builtinCurTime", + "builtinDateAdd", + "builtinDateSub", + "builtinExtract", + "builtinGroupConcat", + "builtinMax", + "builtinMin", + "builtinPosition", + "builtinStddevPop", + "builtinStddevSamp", + "builtinSubDate", + "builtinSubstring", + "builtinSum", + "builtinSysDate", + "builtinTrim", + "builtinUser", + "caseKwd", + "cumeDist", + "currentDate", + "currentTime", + "denseRank", + "firstValue", + "lag", + "lastValue", + "lead", + "not2", + "nthValue", + "ntile", + "percentRank", + "pipes", + "rank", + "repeat", + "rowNumber", + "utcDate", + "utcTime", + "utcTimestamp", + "key", + "primary", + "unique", + "check", + "references", + "generated", + "Identifier", + "ignore", + "NotKeywordToken", + "TiDBKeyword", + "UnReservedKeyword", + "selectKwd", + "character", + "partition", + "packKeys", + "shardRowIDBits", + "jss", + "juss", + "index", + "lines", + "by", + "sql", + "force", + "use", + "drop", + "cascade", + "restrict", + "to", + "read", + "alter", + "analyze", + "foreign", + "fulltext", + "decimalType", + "integerType", + "intType", + "rename", + "varcharType", + "'@'", + "add", + "bigIntType", + "blobType", + "change", + "doubleType", + "floatType", + "int1Type", + "int2Type", + "int3Type", + "int4Type", + "int8Type", + "long", + "longblobType", + "longtextType", + "mediumblobType", + "mediumIntType", + "mediumtextType", + "numericType", + "nvarcharType", + "realType", + "smallIntType", + "tinyblobType", + "tinyIntType", + "tinytextType", + "varbinaryType", + "write", + "SubSelect", + "UserVariable", + "Literal", + "SimpleIdent", + "StringLiteral", + "FunctionCallGeneric", + "FunctionCallKeyword", + "FunctionCallNonKeyword", + "FunctionNameConflict", + "FunctionNameDateArith", + "FunctionNameDateArithMultiForms", + "FunctionNameDatetimePrecision", + "FunctionNameOptionalBraces", + "SimpleExpr", + "SumExpr", + "SystemVariable", + "Variable", + "WindowFuncCall", + "BitExpr", + "PredicateExpr", + "BoolPri", + "Expression", + "logAnd", + "logOr", + "TableName", + "unsigned", + "NUM", + "zerofill", + "over", + "ColumnName", + "all", + "StringName", + "WindowingClause", + "EqOpt", + "SelectStmt", + "SelectStmtBasic", + "SelectStmtFromDualTable", + "SelectStmtFromTable", + "FieldLen", + "tableKwd", + "UnionSelect", + "LengthNum", + "UnionClauseList", + "UnionStmt", + "update", + "sqlCalcFoundRows", + "CharsetKw", + "delayed", + "highPriority", + "lowPriority", + "OptWindowingClause", + "deleteKwd", + "OptFieldLen", + "ExpressionList", + "JoinTable", + "TableFactor", + "TableRef", + "distinct", + "distinctRow", + "Username", + "DistinctKwd", + "FromOrIn", + "into", + "OrderBy", + "OrderByOptional", + "DistinctOpt", + "IndexType", + "JoinType", + "TableNameList", + "CharsetName", + "ColumnNameList", + "CrossOpt", + "DefaultFalseDistinctOpt", + "DefaultKwdOpt", + "IndexColName", + "KeyOrIndex", + "OptCollate", + "BuggyDefaultFalseDistinctOpt", + "ColumnDef", + "DeleteFromStmt", + "escaped", + "EscapedTableRef", + "hintEnd", + "IndexColNameList", + "InsertIntoStmt", + "ReplaceIntoStmt", + "SelectStmtLimit", + "TimeUnit", + "UpdateStmt", + "WhereClause", + "WhereClauseOptional", + "create", + "ExprOrDefault", + "grant", + "MaxNumBuckets", + "NumLiteral", + "OptBinary", + "RowFormat", + "SelectLockOpt", + "show", + "ShowDatabaseNameOpt", + "TableOption", + "TableRefs", + "terminated", + "ByItem", + "column", + "ColumnKeywordOpt", + "DBName", + "enclosed", + "ExpressionListOpt", + "FieldOpt", + "FieldOpts", + "IndexName", + "IndexOption", + "IndexOptionList", + "OptNullTreatment", + "PriorityOpt", + "ShowLikeOrWhereOpt", + "UserSpec", + "Assignment", + "AuthString", + "ByList", + "IgnoreOptional", + "IndexNameList", + "IndexTypeOpt", + "LimitOption", + "option", + "outer", + "PartitionDefinitionListOpt", + "PartitionNumOpt", + "SetExpr", + "TableAsName", + "TransactionChar", + "UserSpecList", + "WindowName", + "assignmentEq", + "AssignmentList", + "ColumnPosition", + "Constraint", + "constraint", + "ConstraintKeywordOpt", + "ExplainableStmt", + "FloatOpt", + "hintBegin", + "HintTableList", + "IfExists", + "IfNotExists", + "IndexHint", + "IndexHintType", + "infile", + "keys", + "LockClause", + "maxValue", + "OptCharset", + "Precision", + "PrivElem", + "PrivType", + "ReferDef", + "RestrictOrCascadeOpt", + "RowValue", + "TableOptimizerHints", + "TableOptionList", + "TransactionChars", + "trigger", + "usage", + "ValueSym", + "WindowFrameStart", + "AdminStmt", + "AlterTableOptionListOpt", + "AlterTableSpec", + "AlterTableStmt", + "AlterUserStmt", + "AnalyzeTableStmt", + "BeginTransactionStmt", + "BinlogStmt", + "CastType", + "ColumnNameListOpt", + "ColumnOption", + "ColumnSetValue", + "CommitStmt", + "CreateDatabaseStmt", + "CreateIndexStmt", + "CreateTableStmt", + "CreateUserStmt", + "CreateViewStmt", + "DatabaseOption", + "databases", + "DatabaseSym", + "DeallocateStmt", + "DeallocateSym", + "describe", + "DoStmt", + "DropDatabaseStmt", + "DropIndexStmt", + "DropStatsStmt", + "DropTableStmt", + "DropUserStmt", + "DropViewStmt", + "EmptyStmt", + "ExecuteStmt", + "explain", + "ExplainStmt", + "ExplainSym", + "Field", + "FieldAsName", + "FieldAsNameOpt", + "FlushStmt", + "FromDual", + "FuncDatetimePrecList", + "FuncDatetimePrecListOpt", + "GeneratedAlways", + "GrantStmt", + "HandleRange", + "HashString", + "IndexHintList", + "IndexHintListOpt", + "InsertValues", + "IntoOpt", + "kill", + "KillOrKillTiDB", + "KillStmt", + "LimitClause", + "load", + "LoadDataStmt", + "LoadStatsStmt", + "LockTablesStmt", + "MaxValueOrExpression", + "NowSym", + "NowSymFunc", + "NowSymOptionFraction", + "NumList", + "ObjectType", + "ODBCDateTimeType", + "odbcDateType", + "odbcTimestampType", + "odbcTimeType", + "OptInteger", + "OptionalBraces", + "OptLeadLagInfo", + "OptLLDefault", + "Order", + "OuterOpt", + "PartDefOption", + "PartitionDefinition", + "PartitionNameList", + "PasswordOpt", + "PreparedStmt", + "PrimaryOpt", + "PrivElemList", + "PrivLevel", + "ReferOpt", + "RegexpSym", + "RenameTableStmt", + "revoke", + "RevokeStmt", + "RollbackStmt", + "SetStmt", + "ShowStmt", + "ShowTableAliasOpt", + "SignedLiteral", + "Statement", + "StatsPersistentVal", + "StringList", + "SubPartitionNumOpt", + "Symbol", + "TableElement", + "TableLock", + "TableOptimizerHintOpt", + "TableOrTables", + "TablesTerminalSym", + "TableToTable", + "TimestampUnit", + "TraceableStmt", + "TraceStmt", + "TruncateTableStmt", + "unlock", + "UnlockTablesStmt", + "UsernameList", + "UseStmt", + "ValuesList", + "VariableAssignment", + "WhenClause", + "WindowDefinition", + "WindowFrameBound", + "WindowSpec", + "AdminShowSlow", + "AlterAlgorithm", + "AlterTableSpecList", + "AnyOrAll", + "AsOpt", + "AuthOption", + "BetweenOrNotOp", + "BitValueType", + "BlobType", + "BooleanType", + "both", + "CharsetOpt", + "ColumnDefList", + "ColumnList", + "ColumnNameListOptWithBrackets", + "ColumnOptionList", + "ColumnOptionListOpt", + "ColumnSetValueList", + "CompareOp", + "ConstraintElem", + "CreateIndexStmtUnique", + "CreateTableOptionListOpt", + "CreateTableSelectOpt", + "DatabaseOptionList", + "DatabaseOptionListOpt", + "DateAndTimeType", + "DefaultTrueDistinctOpt", + "DefaultValueExpr", + "dual", + "DuplicateOpt", + "ElseOpt", + "Enclosed", + "Escaped", + "ExpressionOpt", + "FieldList", + "Fields", + "FieldsOrColumns", + "FieldsTerminated", + "FixedPointType", + "FloatingPointType", + "FlushOption", + "FuncDatetimePrec", + "GetFormatSelector", + "GlobalScope", + "GroupByClause", + "HandleRangeList", + "HavingClause", + "IgnoreLines", + "IndexHintScope", + "InOrNotOp", + "IntegerType", + "IsolationLevel", + "IsOrNotOp", + "KeyOrIndexOpt", + "leading", + "LikeEscapeOpt", + "LikeOrNotOp", + "LikeTableWithOrWithoutParen", + "Lines", + "LinesTerminated", + "LocalOpt", + "LockClauseOpt", + "LockType", + "MaxValueOrExpressionList", + "NationalOpt", + "noWriteToBinLog", + "NoWriteToBinLogAliasOpt", + "NumericType", + "OnDeleteOpt", + "OnDuplicateKeyUpdate", + "OnUpdateOpt", + "OptBinMod", + "OptExistingWindowName", + "OptFromFirstLast", + "OptFull", + "OptGConcatSeparator", + "OptPartitionClause", + "OptTable", + "OptWindowFrameClause", + "OptWindowOrderByClause", + "OrReplace", + "PartDefOptionList", + "PartDefOptionsOpt", + "PartDefValuesOpt", + "PartitionDefinitionList", + "PartitionOpt", + "precisionType", + "PrepareSQL", + "procedure", + "QuickOptional", + "RegexpOrNotOp", + "SelectStmtCalcFoundRows", + "SelectStmtFieldList", + "SelectStmtGroup", + "SelectStmtOpts", + "SelectStmtSQLCache", + "SelectStmtStraightJoin", + "ShowIndexKwd", + "ShowTargetFilterable", + "Start", + "Starting", + "starting", + "StatementList", + "stored", + "StringType", + "SubPartitionOpt", + "TableAsNameOpt", + "TableElementList", + "TableElementListOpt", + "TableLockList", + "TableNameListOpt", + "TableOptimizerHintList", + "TableRefsClause", + "TableToTableList", + "TextType", + "trailing", + "TrimDirection", + "Type", + "UnionOpt", + "UserVariableList", + "Values", + "ValuesOpt", + "Varchar", + "VariableAssignmentList", + "ViewAlgorithm", + "ViewCheckOption", + "ViewDefiner", + "ViewFieldList", + "ViewName", + "ViewSQLSecurity", + "virtual", + "VirtualOrStored", + "WhenClauseList", + "WindowClauseOptional", + "WindowDefinitionList", + "WindowFrameBetween", + "WindowFrameExtent", + "WindowFrameUnits", + "WindowNameOrSpec", + "WindowSpecDetails", + "WithGrantOptionOpt", + "WithReadLockOpt", + "$default", + "andnot", + "AssignmentListOpt", + "builtinVarPop", + "builtinVarSamp", + "CommaOpt", + "createTableSelect", + "empty", + "error", + "higherThanComma", + "insertValues", + "invalid", + "lowerThanComma", + "lowerThanCreateTableSelect", + "lowerThanEq", + "lowerThanInsertValues", + "lowerThanIntervalKeyword", + "lowerThanKey", + "lowerThanOn", + "lowerThanSetKeyword", + "lowerThanStringLitToken", + "neg", + "tableRefPriority", + } + + yyReductions = []struct{ xsym, components int }{ + {0, 1}, + {819, 1}, + {605, 5}, + {605, 8}, + {605, 10}, + {604, 1}, + {604, 5}, + {604, 4}, + {604, 5}, + {604, 2}, + {604, 3}, + {604, 4}, + {604, 3}, + {604, 4}, + {604, 3}, + {604, 3}, + {604, 3}, + {604, 4}, + {604, 2}, + {604, 2}, + {604, 4}, + {604, 5}, + {604, 6}, + {604, 5}, + {604, 3}, + {604, 2}, + {604, 3}, + {604, 5}, + {604, 1}, + {604, 3}, + {604, 1}, + {721, 1}, + {721, 1}, + {721, 1}, + {781, 0}, + {781, 1}, + {586, 3}, + {586, 3}, + {586, 3}, + {586, 3}, + {510, 1}, + {510, 1}, + {773, 0}, + {773, 1}, + {541, 0}, + {541, 1}, + {572, 0}, + {572, 1}, + {572, 2}, + {722, 1}, + {722, 3}, + {679, 1}, + {679, 3}, + {575, 0}, + {575, 1}, + {575, 2}, + {699, 1}, + {687, 3}, + {833, 1}, + {833, 3}, + {705, 3}, + {607, 4}, + {607, 6}, + {607, 6}, + {607, 8}, + {529, 0}, + {529, 3}, + {554, 3}, + {571, 1}, + {571, 3}, + {864, 0}, + {864, 1}, + {608, 1}, + {608, 2}, + {608, 5}, + {609, 2}, + {732, 1}, + {732, 3}, + {513, 3}, + {464, 1}, + {464, 3}, + {464, 5}, + {505, 1}, + {505, 3}, + {611, 0}, + {611, 1}, + {734, 0}, + {734, 3}, + {614, 1}, + {682, 0}, + {682, 1}, + {612, 2}, + {612, 1}, + {612, 1}, + {612, 2}, + {612, 1}, + {612, 2}, + {612, 2}, + {612, 3}, + {612, 2}, + {612, 4}, + {612, 6}, + {612, 1}, + {645, 0}, + {645, 2}, + {851, 0}, + {851, 1}, + {851, 1}, + {735, 1}, + {735, 2}, + {736, 0}, + {736, 1}, + {739, 8}, + {739, 7}, + {739, 7}, + {739, 8}, + {739, 7}, + {592, 7}, + {788, 0}, + {788, 3}, + {790, 0}, + {790, 3}, + {685, 1}, + {685, 1}, + {685, 2}, + {685, 2}, + {747, 1}, + {747, 1}, + {664, 1}, + {664, 3}, + {664, 4}, + {663, 1}, + {663, 1}, + {663, 1}, + {663, 1}, + {662, 1}, + {662, 1}, + {662, 1}, + {694, 1}, + {694, 2}, + {694, 2}, + {530, 1}, + {530, 1}, + {530, 1}, + {616, 12}, + {740, 0}, + {740, 1}, + {509, 3}, + {518, 1}, + {518, 3}, + {615, 5}, + {542, 1}, + {620, 4}, + {620, 4}, + {744, 0}, + {744, 1}, + {743, 1}, + {743, 2}, + {617, 10}, + {617, 5}, + {508, 0}, + {508, 1}, + {805, 0}, + {805, 8}, + {805, 7}, + {805, 9}, + {805, 9}, + {825, 0}, + {825, 7}, + {825, 7}, + {698, 0}, + {698, 2}, + {564, 0}, + {564, 2}, + {563, 0}, + {563, 3}, + {804, 1}, + {804, 3}, + {678, 4}, + {802, 0}, + {802, 1}, + {801, 1}, + {801, 2}, + {677, 3}, + {677, 3}, + {677, 3}, + {803, 0}, + {803, 4}, + {803, 6}, + {749, 0}, + {749, 1}, + {749, 1}, + {724, 0}, + {724, 1}, + {742, 0}, + {742, 1}, + {742, 1}, + {742, 1}, + {777, 2}, + {777, 4}, + {619, 11}, + {800, 0}, + {800, 2}, + {844, 0}, + {844, 3}, + {844, 3}, + {844, 3}, + {846, 0}, + {846, 3}, + {849, 0}, + {849, 3}, + {849, 3}, + {848, 1}, + {847, 0}, + {847, 3}, + {733, 1}, + {733, 3}, + {845, 0}, + {845, 4}, + {845, 4}, + {626, 2}, + {514, 11}, + {514, 9}, + {514, 10}, + {622, 1}, + {627, 4}, + {628, 6}, + {630, 4}, + {630, 6}, + {632, 5}, + {631, 3}, + {631, 5}, + {629, 3}, + {593, 0}, + {593, 1}, + {593, 1}, + {703, 1}, + {703, 1}, + {468, 0}, + {468, 1}, + {633, 0}, + {708, 2}, + {708, 5}, + {637, 1}, + {637, 1}, + {637, 1}, + {636, 2}, + {636, 3}, + {636, 2}, + {636, 5}, + {636, 3}, + {476, 1}, + {461, 1}, + {456, 3}, + {456, 3}, + {456, 3}, + {456, 3}, + {456, 2}, + {456, 3}, + {456, 3}, + {456, 3}, + {456, 1}, + {661, 1}, + {661, 1}, + {458, 1}, + {458, 1}, + {457, 1}, + {457, 1}, + {488, 1}, + {488, 3}, + {783, 1}, + {783, 3}, + {544, 0}, + {544, 1}, + {644, 0}, + {644, 1}, + {643, 1}, + {455, 3}, + {455, 3}, + {455, 4}, + {455, 5}, + {455, 1}, + {738, 1}, + {738, 1}, + {738, 1}, + {738, 1}, + {738, 1}, + {738, 1}, + {738, 1}, + {738, 1}, + {726, 1}, + {726, 2}, + {772, 1}, + {772, 2}, + {769, 1}, + {769, 2}, + {776, 1}, + {776, 2}, + {810, 1}, + {810, 2}, + {723, 1}, + {723, 1}, + {723, 1}, + {454, 5}, + {454, 3}, + {454, 5}, + {454, 4}, + {454, 3}, + {454, 1}, + {686, 1}, + {686, 1}, + {775, 0}, + {775, 2}, + {638, 1}, + {638, 3}, + {638, 5}, + {638, 2}, + {638, 5}, + {640, 0}, + {640, 1}, + {639, 1}, + {639, 2}, + {639, 1}, + {639, 2}, + {754, 1}, + {754, 3}, + {764, 3}, + {766, 0}, + {766, 2}, + {580, 0}, + {580, 2}, + {581, 0}, + {581, 3}, + {557, 0}, + {557, 1}, + {547, 0}, + {547, 1}, + {549, 0}, + {549, 2}, + {548, 3}, + {548, 1}, + {548, 2}, + {501, 2}, + {501, 2}, + {559, 0}, + {559, 1}, + {376, 1}, + {376, 1}, + {376, 1}, + {376, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {380, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {379, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {378, 1}, + {519, 7}, + {652, 0}, + {652, 1}, + {651, 5}, + {651, 4}, + {651, 6}, + {651, 4}, + {651, 2}, + {651, 3}, + {651, 1}, + {651, 1}, + {651, 2}, + {600, 1}, + {600, 1}, + {714, 1}, + {714, 3}, + {594, 3}, + {841, 0}, + {841, 1}, + {840, 3}, + {840, 1}, + {527, 1}, + {527, 1}, + {613, 3}, + {737, 0}, + {737, 1}, + {737, 3}, + {789, 0}, + {789, 5}, + {520, 5}, + {667, 1}, + {667, 1}, + {667, 1}, + {437, 1}, + {437, 1}, + {437, 1}, + {437, 1}, + {437, 1}, + {437, 1}, + {437, 1}, + {437, 2}, + {437, 1}, + {437, 1}, + {439, 1}, + {439, 2}, + {498, 3}, + {556, 1}, + {556, 3}, + {539, 2}, + {675, 0}, + {675, 1}, + {675, 1}, + {499, 0}, + {499, 1}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 5}, + {453, 5}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 3}, + {453, 1}, + {438, 1}, + {438, 3}, + {438, 4}, + {438, 5}, + {448, 1}, + {448, 1}, + {448, 1}, + {448, 1}, + {448, 3}, + {448, 1}, + {448, 1}, + {448, 1}, + {448, 1}, + {448, 1}, + {448, 2}, + {448, 2}, + {448, 2}, + {448, 2}, + {448, 3}, + {448, 2}, + {448, 1}, + {448, 3}, + {448, 5}, + {448, 6}, + {448, 2}, + {448, 2}, + {448, 6}, + {448, 5}, + {448, 6}, + {448, 6}, + {448, 4}, + {448, 4}, + {448, 3}, + {448, 3}, + {495, 1}, + {495, 1}, + {500, 1}, + {500, 1}, + {507, 0}, + {507, 1}, + {746, 0}, + {746, 1}, + {512, 1}, + {512, 2}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {443, 1}, + {672, 0}, + {672, 2}, + {447, 1}, + {447, 1}, + {447, 1}, + {446, 1}, + {446, 1}, + {446, 1}, + {446, 1}, + {446, 1}, + {446, 1}, + {441, 4}, + {441, 4}, + {441, 2}, + {441, 3}, + {441, 2}, + {441, 4}, + {441, 6}, + {441, 2}, + {441, 2}, + {441, 2}, + {441, 4}, + {441, 6}, + {441, 4}, + {441, 4}, + {442, 4}, + {442, 4}, + {442, 6}, + {442, 8}, + {442, 8}, + {442, 6}, + {442, 6}, + {442, 6}, + {442, 6}, + {442, 6}, + {442, 8}, + {442, 8}, + {442, 8}, + {442, 8}, + {442, 4}, + {442, 6}, + {442, 6}, + {442, 7}, + {762, 1}, + {762, 1}, + {762, 1}, + {762, 1}, + {444, 1}, + {444, 1}, + {445, 1}, + {445, 1}, + {836, 1}, + {836, 1}, + {836, 1}, + {449, 6}, + {449, 5}, + {449, 6}, + {449, 5}, + {449, 6}, + {449, 5}, + {449, 6}, + {449, 5}, + {449, 6}, + {449, 5}, + {449, 5}, + {449, 7}, + {449, 6}, + {449, 6}, + {449, 6}, + {449, 6}, + {449, 6}, + {795, 0}, + {795, 2}, + {440, 4}, + {761, 0}, + {761, 2}, + {761, 3}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {522, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {706, 1}, + {753, 0}, + {753, 1}, + {852, 1}, + {852, 2}, + {716, 4}, + {750, 0}, + {750, 2}, + {610, 2}, + {610, 3}, + {610, 1}, + {610, 2}, + {610, 2}, + {610, 2}, + {610, 2}, + {610, 2}, + {610, 1}, + {551, 0}, + {551, 1}, + {551, 1}, + {551, 1}, + {459, 1}, + {459, 3}, + {503, 1}, + {503, 3}, + {809, 0}, + {809, 1}, + {681, 4}, + {807, 1}, + {807, 1}, + {634, 2}, + {634, 4}, + {839, 1}, + {839, 3}, + {623, 3}, + {624, 1}, + {624, 1}, + {690, 1}, + {470, 3}, + {471, 3}, + {472, 7}, + {469, 4}, + {469, 4}, + {469, 4}, + {642, 2}, + {853, 0}, + {853, 2}, + {854, 1}, + {854, 3}, + {717, 3}, + {569, 1}, + {719, 3}, + {859, 4}, + {792, 0}, + {792, 1}, + {796, 0}, + {796, 3}, + {799, 0}, + {799, 3}, + {798, 0}, + {798, 2}, + {857, 1}, + {857, 1}, + {857, 1}, + {856, 1}, + {856, 1}, + {601, 2}, + {601, 2}, + {601, 2}, + {601, 4}, + {601, 2}, + {855, 4}, + {718, 1}, + {718, 2}, + {718, 2}, + {718, 2}, + {718, 4}, + {485, 0}, + {485, 1}, + {467, 2}, + {858, 1}, + {858, 1}, + {452, 4}, + {452, 4}, + {452, 4}, + {452, 4}, + {452, 4}, + {452, 5}, + {452, 7}, + {452, 7}, + {452, 6}, + {452, 6}, + {452, 9}, + {673, 0}, + {673, 3}, + {673, 3}, + {674, 0}, + {674, 2}, + {550, 0}, + {550, 2}, + {550, 2}, + {793, 0}, + {793, 2}, + {793, 2}, + {832, 1}, + {537, 1}, + {537, 3}, + {516, 1}, + {516, 4}, + {491, 1}, + {491, 1}, + {490, 3}, + {490, 4}, + {490, 4}, + {490, 3}, + {826, 0}, + {826, 1}, + {566, 1}, + {566, 2}, + {583, 2}, + {583, 2}, + {583, 2}, + {768, 0}, + {768, 2}, + {768, 3}, + {768, 3}, + {582, 5}, + {558, 0}, + {558, 1}, + {558, 3}, + {558, 1}, + {649, 1}, + {649, 2}, + {650, 0}, + {650, 1}, + {489, 3}, + {489, 5}, + {489, 7}, + {489, 7}, + {489, 9}, + {489, 4}, + {489, 6}, + {489, 3}, + {489, 5}, + {502, 1}, + {502, 1}, + {676, 0}, + {676, 1}, + {506, 1}, + {506, 2}, + {506, 2}, + {656, 0}, + {656, 2}, + {560, 1}, + {560, 1}, + {521, 0}, + {521, 2}, + {521, 4}, + {521, 4}, + {814, 6}, + {595, 0}, + {595, 3}, + {579, 1}, + {579, 3}, + {831, 1}, + {831, 2}, + {702, 4}, + {702, 4}, + {702, 4}, + {702, 4}, + {811, 0}, + {811, 1}, + {815, 0}, + {815, 1}, + {815, 1}, + {816, 0}, + {816, 1}, + {812, 1}, + {813, 0}, + {813, 1}, + {435, 3}, + {435, 3}, + {533, 0}, + {533, 2}, + {533, 4}, + {478, 7}, + {478, 7}, + {478, 7}, + {478, 8}, + {477, 1}, + {477, 4}, + {475, 1}, + {475, 3}, + {838, 1}, + {691, 2}, + {691, 4}, + {691, 6}, + {691, 4}, + {691, 4}, + {691, 3}, + {597, 1}, + {597, 3}, + {567, 3}, + {567, 2}, + {567, 2}, + {771, 2}, + {771, 2}, + {771, 2}, + {771, 1}, + {565, 1}, + {565, 1}, + {715, 3}, + {715, 4}, + {715, 4}, + {715, 4}, + {715, 3}, + {715, 3}, + {715, 3}, + {715, 2}, + {715, 4}, + {715, 4}, + {715, 2}, + {504, 1}, + {504, 1}, + {843, 0}, + {843, 1}, + {843, 3}, + {451, 1}, + {451, 1}, + {450, 1}, + {436, 1}, + {494, 1}, + {494, 3}, + {494, 2}, + {494, 2}, + {712, 1}, + {712, 3}, + {680, 1}, + {680, 4}, + {555, 1}, + {602, 3}, + {602, 4}, + {602, 5}, + {602, 4}, + {602, 4}, + {602, 5}, + {602, 5}, + {602, 5}, + {602, 6}, + {602, 4}, + {602, 5}, + {602, 6}, + {602, 4}, + {720, 2}, + {720, 2}, + {720, 3}, + {720, 3}, + {765, 1}, + {765, 3}, + {647, 5}, + {665, 1}, + {665, 3}, + {692, 3}, + {692, 4}, + {692, 4}, + {692, 2}, + {692, 4}, + {692, 3}, + {692, 3}, + {692, 3}, + {692, 3}, + {692, 3}, + {692, 3}, + {692, 2}, + {692, 2}, + {817, 1}, + {817, 1}, + {817, 1}, + {496, 1}, + {496, 1}, + {818, 1}, + {818, 1}, + {818, 1}, + {818, 3}, + {818, 3}, + {818, 3}, + {818, 5}, + {818, 4}, + {818, 4}, + {818, 1}, + {818, 1}, + {818, 2}, + {818, 2}, + {818, 1}, + {818, 2}, + {818, 2}, + {818, 2}, + {818, 2}, + {818, 1}, + {552, 0}, + {552, 2}, + {552, 2}, + {763, 0}, + {763, 1}, + {763, 1}, + {794, 0}, + {794, 1}, + {535, 0}, + {535, 2}, + {693, 2}, + {641, 3}, + {760, 1}, + {760, 1}, + {760, 3}, + {786, 0}, + {786, 1}, + {786, 1}, + {830, 0}, + {830, 1}, + {861, 0}, + {861, 3}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {695, 1}, + {707, 1}, + {707, 1}, + {707, 1}, + {707, 1}, + {707, 1}, + {707, 1}, + {576, 1}, + {576, 1}, + {576, 1}, + {576, 1}, + {576, 1}, + {576, 1}, + {822, 1}, + {822, 3}, + {573, 2}, + {700, 1}, + {700, 1}, + {700, 4}, + {827, 1}, + {827, 3}, + {828, 0}, + {828, 3}, + {536, 2}, + {536, 3}, + {536, 4}, + {536, 4}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 3}, + {536, 1}, + {536, 3}, + {536, 3}, + {536, 3}, + {696, 1}, + {696, 1}, + {603, 0}, + {603, 1}, + {741, 0}, + {741, 1}, + {596, 1}, + {596, 2}, + {596, 3}, + {797, 0}, + {797, 1}, + {709, 3}, + {532, 3}, + {532, 3}, + {532, 3}, + {532, 3}, + {532, 3}, + {532, 3}, + {837, 1}, + {837, 1}, + {837, 1}, + {787, 3}, + {787, 2}, + {787, 3}, + {787, 3}, + {787, 2}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {770, 1}, + {729, 1}, + {729, 1}, + {671, 0}, + {671, 1}, + {671, 1}, + {758, 1}, + {758, 1}, + {759, 1}, + {759, 1}, + {759, 1}, + {759, 2}, + {727, 1}, + {824, 5}, + {824, 4}, + {824, 5}, + {824, 4}, + {824, 2}, + {824, 2}, + {824, 1}, + {824, 3}, + {824, 6}, + {824, 6}, + {824, 1}, + {784, 0}, + {784, 1}, + {842, 2}, + {842, 1}, + {842, 1}, + {728, 1}, + {728, 2}, + {728, 1}, + {728, 1}, + {834, 1}, + {834, 2}, + {834, 1}, + {834, 1}, + {834, 2}, + {745, 1}, + {745, 2}, + {745, 2}, + {745, 2}, + {745, 3}, + {473, 3}, + {487, 0}, + {487, 1}, + {545, 1}, + {545, 1}, + {545, 1}, + {546, 0}, + {546, 2}, + {577, 0}, + {577, 1}, + {577, 1}, + {589, 5}, + {791, 0}, + {791, 1}, + {531, 0}, + {531, 2}, + {531, 3}, + {588, 0}, + {588, 2}, + {481, 2}, + {481, 1}, + {511, 0}, + {511, 2}, + {697, 1}, + {697, 3}, + {466, 1}, + {466, 1}, + {523, 10}, + {523, 8}, + {713, 2}, + {524, 2}, + {525, 0}, + {525, 1}, + {867, 0}, + {867, 1}, + {618, 4}, + {606, 4}, + {606, 9}, + {553, 2}, + {568, 1}, + {568, 3}, + {725, 0}, + {725, 3}, + {725, 3}, + {725, 5}, + {725, 5}, + {725, 4}, + {648, 1}, + {646, 8}, + {860, 0}, + {860, 3}, + {860, 3}, + {860, 3}, + {860, 3}, + {860, 3}, + {590, 1}, + {590, 4}, + {683, 1}, + {683, 3}, + {591, 1}, + {591, 2}, + {591, 1}, + {591, 1}, + {591, 2}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 1}, + {591, 2}, + {591, 1}, + {591, 2}, + {591, 1}, + {591, 2}, + {591, 2}, + {591, 1}, + {591, 1}, + {591, 3}, + {591, 2}, + {591, 2}, + {591, 2}, + {591, 2}, + {591, 2}, + {591, 1}, + {666, 0}, + {666, 1}, + {684, 1}, + {684, 3}, + {684, 3}, + {684, 3}, + {684, 1}, + {689, 7}, + {658, 13}, + {767, 0}, + {767, 3}, + {731, 0}, + {731, 3}, + {780, 0}, + {780, 1}, + {755, 0}, + {755, 4}, + {756, 1}, + {756, 1}, + {757, 0}, + {757, 3}, + {751, 0}, + {751, 3}, + {752, 0}, + {752, 3}, + {778, 0}, + {778, 3}, + {820, 0}, + {820, 3}, + {779, 0}, + {779, 3}, + {711, 2}, + {660, 3}, + {704, 1}, + {704, 1}, + {701, 2}, + {782, 1}, + {782, 2}, + {782, 1}, + {829, 1}, + {829, 3}, + {655, 2}, + {655, 3}, + {655, 3}, + {654, 1}, + {654, 2}, + {659, 3}, + } + + yyXErrors = map[yyXError]string{} + + yyParseTab = [2475][]uint16{ + // 0 + {1191, 1191, 52: 1453, 55: 1452, 76: 1466, 1437, 1439, 81: 1440, 85: 1455, 87: 1442, 91: 1468, 98: 1456, 100: 1438, 104: 1445, 1515, 217: 1461, 231: 1522, 246: 1465, 255: 1451, 262: 1448, 301: 1450, 381: 1457, 393: 1517, 1444, 399: 1434, 1436, 406: 1435, 435: 1507, 469: 1464, 1458, 1459, 1460, 475: 1463, 477: 1462, 1504, 1516, 486: 1443, 514: 1478, 519: 1495, 1502, 523: 1510, 526: 1441, 528: 1518, 534: 1467, 602: 1470, 605: 1471, 1472, 1473, 1474, 1475, 614: 1476, 1481, 1482, 1483, 1485, 1484, 623: 1477, 1454, 1447, 1486, 1487, 1488, 1492, 1489, 1491, 1490, 1469, 1479, 1446, 1480, 1449, 641: 1493, 646: 1494, 653: 1524, 1523, 1496, 657: 1520, 1497, 1498, 1513, 681: 1499, 687: 1501, 1519, 1503, 1500, 1505, 1506, 695: 1514, 708: 1508, 1509, 1521, 1512, 713: 1511, 819: 1432, 822: 1433}, + {1431}, + {1430, 3904}, + {62: 3801, 377: 1932, 474: 1098, 557: 3800}, + {474: 3792}, + // 5 + {474: 3773}, + {1359, 1359}, + {172: 3769}, + {219: 3768}, + {1343, 1343}, + // 10 + {22: 1230, 38: 1230, 51: 1230, 62: 3276, 236: 3275, 315: 3216, 372: 3271, 388: 1286, 391: 1230, 474: 3273, 622: 3272, 740: 3270, 800: 3274}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 3269}, + {2: 462, 462, 462, 462, 7: 462, 462, 10: 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 241: 462, 377: 462, 482: 462, 462, 462, 578: 1926, 595: 3250}, + {22: 3220, 25: 2805, 55: 586, 62: 3221, 101: 3222, 315: 3216, 388: 3218, 474: 2804, 622: 3217, 703: 3219}, + {126: 3206, 217: 2558, 255: 1451, 301: 1450, 381: 1457, 469: 3207, 1458, 1459, 1460, 475: 1463, 477: 1462, 3212, 1516, 486: 1443, 514: 3208, 519: 3210, 3211, 523: 3209, 707: 3205}, + // 15 + {2: 1188, 1188, 1188, 1188, 7: 1188, 1188, 10: 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1188, 255: 1188, 301: 1188, 381: 1188, 400: 1188, 479: 1188, 486: 1188}, + {2: 1187, 1187, 1187, 1187, 7: 1187, 1187, 10: 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 255: 1187, 301: 1187, 381: 1187, 400: 1187, 479: 1187, 486: 1187}, + {2: 1186, 1186, 1186, 1186, 7: 1186, 1186, 10: 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 255: 1186, 301: 1186, 381: 1186, 400: 1186, 479: 1186, 486: 1186}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 3192, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 2558, 255: 1451, 301: 1450, 376: 1751, 378: 1537, 1538, 1536, 1457, 400: 3193, 459: 3190, 469: 3194, 1458, 1459, 1460, 475: 1463, 477: 1462, 3199, 1516, 486: 1443, 514: 3195, 519: 3197, 3198, 523: 3196, 576: 3191}, + {2: 605, 605, 605, 605, 7: 605, 605, 10: 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 377: 605, 482: 1930, 1929, 1928, 497: 605, 551: 3179}, + // 20 + {2: 605, 605, 605, 605, 7: 605, 605, 10: 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 482: 1930, 1929, 1928, 497: 605, 551: 3138}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3133, 378: 1537, 1538, 1536}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3127, 378: 1537, 1538, 1536}, + {55: 3125}, + {55: 587}, + // 25 + {585, 585}, + {2: 462, 462, 462, 462, 7: 462, 462, 10: 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 219: 462, 462, 222: 462, 462, 462, 462, 462, 462, 230: 462, 244: 462, 255: 462, 462, 258: 462, 279: 462, 288: 462, 300: 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 364: 462, 462, 462, 462, 462, 462, 465: 462, 480: 462, 482: 462, 462, 462, 492: 462, 462, 578: 1926, 595: 3090, 814: 3089}, + {817, 817, 9: 817, 218: 817, 228: 817, 817, 231: 817, 817, 817, 2301, 241: 3054, 498: 2302, 3086, 642: 3053}, + {817, 817, 9: 817, 218: 817, 228: 817, 817, 231: 817, 817, 817, 2301, 498: 2302, 3083}, + {817, 817, 9: 817, 218: 817, 228: 817, 817, 231: 817, 817, 817, 2301, 498: 2302, 3080}, + // 30 + {217: 2558, 381: 1457, 469: 2571, 1458, 1459, 1460, 475: 1463, 477: 1462, 2557}, + {229: 3020}, + {229: 433}, + {266, 266, 229: 431}, + {398, 398, 1622, 1541, 1575, 1542, 398, 2946, 1627, 10: 1568, 1624, 2950, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 2948, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 2947, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 2951, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 2952, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 2949, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 307: 2956, 319: 2955, 376: 2954, 378: 1537, 1538, 1536, 382: 2524, 481: 2957, 715: 2958, 843: 2953}, + // 35 + {14: 2898, 112: 2899, 114: 2897, 153: 2896, 373: 2895, 534: 2894}, + {7: 2525, 24: 320, 317, 29: 317, 39: 317, 49: 2829, 63: 320, 69: 317, 116: 2841, 122: 2833, 124: 2845, 127: 2849, 2844, 2847, 2821, 2839, 2831, 139: 2822, 149: 2846, 2828, 157: 2848, 162: 2826, 2827, 2825, 2824, 173: 2842, 176: 2838, 382: 2524, 388: 2830, 474: 2836, 481: 2835, 526: 2820, 585: 2832, 621: 2834, 763: 2840, 794: 2823, 808: 2843, 817: 2837, 2819}, + {24: 308, 308, 49: 308, 59: 2803, 474: 308, 785: 2802, 2801}, + {301, 301}, + {300, 300}, + // 40 + {299, 299}, + {298, 298}, + {297, 297}, + {296, 296}, + {295, 295}, + // 45 + {294, 294}, + {293, 293}, + {292, 292}, + {291, 291}, + {290, 290}, + // 50 + {289, 289}, + {288, 288}, + {287, 287}, + {286, 286}, + {285, 285}, + // 55 + {284, 284}, + {283, 283}, + {282, 282}, + {281, 281}, + {280, 280}, + // 60 + {279, 279}, + {278, 278}, + {277, 277}, + {276, 276}, + {275, 275}, + // 65 + {274, 274}, + {273, 273}, + {272, 272}, + {271, 271}, + {270, 270}, + // 70 + {269, 269}, + {268, 268}, + {267, 267}, + {265, 265}, + {264, 264}, + // 75 + {263, 263}, + {262, 262}, + {261, 261}, + {260, 260}, + {259, 259}, + // 80 + {258, 258}, + {257, 257}, + {256, 256}, + {243, 243}, + {2: 205, 205, 205, 205, 7: 205, 205, 10: 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 474: 2798, 797: 2799}, + // 85 + {2: 462, 462, 462, 462, 7: 462, 462, 10: 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 462, 303: 462, 377: 462, 482: 462, 462, 462, 578: 1926, 595: 1927}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1924, 378: 1537, 1538, 1536, 542: 1925}, + {52: 1835, 64: 1848, 68: 1834, 71: 1846, 1844, 1839, 231: 1847, 301: 1837, 374: 1843, 381: 1838, 388: 1836, 394: 1833, 399: 1829, 465: 1828, 479: 1841, 486: 1832, 526: 1830, 528: 1842, 534: 1840, 590: 1826, 1825, 598: 1831, 1845, 683: 1906}, + {52: 1835, 64: 1848, 68: 1834, 71: 1846, 1844, 1839, 231: 1847, 301: 1837, 374: 1843, 381: 1838, 388: 1836, 394: 1833, 399: 1829, 465: 1828, 479: 1841, 486: 1832, 526: 1830, 528: 1842, 534: 1840, 590: 1826, 1825, 598: 1831, 1845, 683: 1827}, + {101: 1765, 119: 1764}, + // 90 + {25: 1533, 474: 1534, 704: 1763}, + {25: 1533, 474: 1534, 704: 1532}, + {11: 1528, 70: 1529, 256: 1526, 461: 1527}, + {11: 3, 70: 3, 170: 1525, 256: 3}, + {11: 2, 70: 2, 256: 2}, + // 95 + {1179, 1179, 1179, 1179, 6: 1179, 1179, 1179, 1179, 1179, 1179, 1179, 14: 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 53: 1179, 60: 1179, 79: 1179, 217: 1179, 1179, 221: 1179, 227: 1179, 1179, 1179, 231: 1179, 1179, 242: 1179, 249: 1179, 255: 1179, 377: 1179, 381: 1179, 1179, 1179, 1179, 1179, 389: 1179}, + {6, 6}, + {256: 1526, 461: 1531}, + {256: 1526, 461: 1530}, + {4, 4}, + // 100 + {5, 5}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 1753, 701: 1754, 829: 1752}, + {14, 14, 14, 14, 14, 14, 7: 14, 14, 10: 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}, + {13, 13, 13, 13, 13, 13, 7: 13, 13, 10: 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}, + {1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 377: 1085, 381: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085}, + // 105 + {1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 377: 1084, 381: 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084}, + {1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 377: 1083, 381: 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083}, + {1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 377: 1082, 381: 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082, 1082}, + {1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 377: 1081, 381: 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081, 1081}, + {1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 377: 1080, 381: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080}, + // 110 + {1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 377: 1079, 381: 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079}, + {1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 377: 1078, 381: 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078}, + {1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 377: 1077, 381: 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077}, + {1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 377: 1076, 381: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076}, + {1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 377: 1075, 381: 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075}, + // 115 + {1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 377: 1074, 381: 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074}, + {1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 377: 1073, 381: 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073}, + {1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 377: 1072, 381: 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072}, + {1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 377: 1071, 381: 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071, 1071}, + {1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 377: 1070, 381: 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070}, + // 120 + {1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 377: 1069, 381: 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069}, + {1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 377: 1068, 381: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068}, + {1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 377: 1067, 381: 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067}, + {1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 377: 1066, 381: 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066, 1066}, + {1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 377: 1065, 381: 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1065}, + // 125 + {1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 377: 1064, 381: 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064}, + {1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 377: 1063, 381: 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063}, + {1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 377: 1062, 381: 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062}, + {1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 377: 1061, 381: 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061, 1061}, + {1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 377: 1060, 381: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060}, + // 130 + {1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 377: 1059, 381: 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059}, + {1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 377: 1058, 381: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058}, + {1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 377: 1057, 381: 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057}, + {1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 377: 1056, 381: 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056}, + {1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 377: 1055, 381: 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055, 1055}, + // 135 + {1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 377: 1054, 381: 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054}, + {1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 377: 1053, 381: 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053}, + {1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 377: 1052, 381: 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1052}, + {1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 377: 1051, 381: 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051}, + {1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 377: 1050, 381: 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050}, + // 140 + {1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 377: 1049, 381: 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049}, + {1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 377: 1048, 381: 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048}, + {1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 377: 1047, 381: 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047}, + {1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 377: 1046, 381: 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046}, + {1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 377: 1045, 381: 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045}, + // 145 + {1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 377: 1044, 381: 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044}, + {1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 377: 1043, 381: 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043}, + {1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 377: 1042, 381: 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042}, + {1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 377: 1041, 381: 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041}, + {1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 377: 1040, 381: 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040}, + // 150 + {1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 377: 1039, 381: 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039}, + {1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 377: 1038, 381: 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038, 1038}, + {1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 377: 1037, 381: 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037}, + {1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 377: 1036, 381: 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036}, + {1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 377: 1035, 381: 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035}, + // 155 + {1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 377: 1034, 381: 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034}, + {1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 377: 1033, 381: 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1033}, + {1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 377: 1032, 381: 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032}, + {1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 377: 1031, 381: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031}, + {1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 377: 1030, 381: 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030}, + // 160 + {1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 377: 1029, 381: 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029}, + {1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 377: 1028, 381: 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028}, + {1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 377: 1027, 381: 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027}, + {1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 377: 1026, 381: 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026}, + {1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 377: 1025, 381: 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025}, + // 165 + {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 377: 1024, 381: 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024}, + {1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 377: 1023, 381: 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023}, + {1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 377: 1022, 381: 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022}, + {1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 377: 1021, 381: 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021}, + {1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 377: 1020, 381: 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020}, + // 170 + {1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 377: 1019, 381: 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019}, + {1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 377: 1018, 381: 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018}, + {1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 377: 1017, 381: 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017}, + {1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 377: 1016, 381: 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016}, + {1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 377: 1015, 381: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015}, + // 175 + {1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 377: 1014, 381: 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014}, + {1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 377: 1013, 381: 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013}, + {1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 377: 1012, 381: 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012}, + {1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 377: 1011, 381: 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011}, + {1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 377: 1010, 381: 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010}, + // 180 + {1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 377: 1009, 381: 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009}, + {1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 377: 1008, 381: 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008}, + {1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 377: 1007, 381: 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007}, + {1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 377: 1006, 381: 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006}, + {1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 377: 1005, 381: 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005}, + // 185 + {1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 377: 1004, 381: 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004}, + {1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 377: 1003, 381: 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003}, + {1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 377: 1002, 381: 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002}, + {1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 377: 1001, 381: 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001}, + {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 377: 1000, 381: 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000}, + // 190 + {999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 377: 999, 381: 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999}, + {998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 377: 998, 381: 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998, 998}, + {997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 377: 997, 381: 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997}, + {996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 377: 996, 381: 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996, 996}, + {995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 377: 995, 381: 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995, 995}, + // 195 + {994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 377: 994, 381: 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994, 994}, + {993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 377: 993, 381: 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993, 993}, + {992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 377: 992, 381: 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992, 992}, + {991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 377: 991, 381: 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991, 991}, + {990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 377: 990, 381: 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990, 990}, + // 200 + {989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 377: 989, 381: 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989, 989}, + {988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 377: 988, 381: 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988, 988}, + {987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 377: 987, 381: 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987}, + {986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 377: 986, 381: 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986, 986}, + {985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 377: 985, 381: 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985}, + // 205 + {984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 377: 984, 381: 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, 984}, + {983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 377: 983, 381: 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, 983}, + {982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 377: 982, 381: 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982}, + {981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 377: 981, 381: 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981}, + {980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 377: 980, 381: 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, 980}, + // 210 + {979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 377: 979, 381: 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979}, + {978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 377: 978, 381: 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, 978}, + {977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 377: 977, 381: 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977}, + {976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 377: 976, 381: 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, 976}, + {975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 377: 975, 381: 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975}, + // 215 + {974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 377: 974, 381: 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974, 974}, + {973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 377: 973, 381: 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973, 973}, + {972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 377: 972, 381: 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972, 972}, + {971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 377: 971, 381: 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971, 971}, + {970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 377: 970, 381: 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970, 970}, + // 220 + {969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 377: 969, 381: 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969, 969}, + {968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 377: 968, 381: 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968, 968}, + {967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 377: 967, 381: 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967}, + {966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 377: 966, 381: 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966}, + {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 377: 965, 381: 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965}, + // 225 + {964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 377: 964, 381: 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964, 964}, + {963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 377: 963, 381: 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963}, + {962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 377: 962, 381: 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962, 962}, + {961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 377: 961, 381: 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961}, + {960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 377: 960, 381: 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, 960}, + // 230 + {959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 377: 959, 381: 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, 959}, + {958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 377: 958, 381: 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958, 958}, + {957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 377: 957, 381: 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, 957}, + {956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 377: 956, 381: 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956, 956}, + {955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 377: 955, 381: 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955, 955}, + // 235 + {954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 377: 954, 381: 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, 954}, + {953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 377: 953, 381: 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953}, + {952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 377: 952, 381: 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952}, + {951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 377: 951, 381: 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951}, + {950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 377: 950, 381: 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950, 950}, + // 240 + {949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 377: 949, 381: 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, 949}, + {948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 377: 948, 381: 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948}, + {947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 377: 947, 381: 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947}, + {946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 377: 946, 381: 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, 946}, + {945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 377: 945, 381: 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945, 945}, + // 245 + {944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 377: 944, 381: 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944, 944}, + {943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 377: 943, 381: 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943, 943}, + {942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 377: 942, 381: 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942}, + {941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 377: 941, 381: 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941, 941}, + {940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 377: 940, 381: 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940, 940}, + // 250 + {939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 377: 939, 381: 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939}, + {938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 377: 938, 381: 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938, 938}, + {937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 377: 937, 381: 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937}, + {936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 377: 936, 381: 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936}, + {935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 377: 935, 381: 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935, 935}, + // 255 + {934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 377: 934, 381: 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934}, + {933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 377: 933, 381: 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933, 933}, + {932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 377: 932, 381: 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, 932}, + {931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 377: 931, 381: 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, 931}, + {930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 377: 930, 381: 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930, 930}, + // 260 + {929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 377: 929, 381: 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929, 929}, + {928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 377: 928, 381: 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928, 928}, + {927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 377: 927, 381: 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927, 927}, + {926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 377: 926, 381: 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, 926}, + {925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 377: 925, 381: 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925}, + // 265 + {924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 377: 924, 381: 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, 924}, + {923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 377: 923, 381: 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923}, + {922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 377: 922, 381: 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922, 922}, + {921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 377: 921, 381: 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921, 921}, + {920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 377: 920, 381: 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920, 920}, + // 270 + {919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 377: 919, 381: 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919}, + {918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 377: 918, 381: 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918, 918}, + {917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 377: 917, 381: 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917}, + {916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 377: 916, 381: 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, 916}, + {915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 377: 915, 381: 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915, 915}, + // 275 + {914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 377: 914, 381: 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914, 914}, + {913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 377: 913, 381: 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913, 913}, + {912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 377: 912, 381: 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, 912}, + {911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 377: 911, 381: 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911, 911}, + {910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 377: 910, 381: 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910, 910}, + // 280 + {909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 377: 909, 381: 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909, 909}, + {908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 377: 908, 381: 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908}, + {907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 377: 907, 381: 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907, 907}, + {906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 377: 906, 381: 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906, 906}, + {905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 377: 905, 381: 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905, 905}, + // 285 + {904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 377: 904, 381: 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904}, + {903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 377: 903, 381: 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903}, + {902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 377: 902, 381: 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902}, + {901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 377: 901, 381: 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901}, + {900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 377: 900, 381: 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900}, + // 290 + {899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 377: 899, 381: 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899}, + {898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 377: 898, 381: 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898}, + {897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 377: 897, 381: 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, 897}, + {896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 377: 896, 381: 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896, 896}, + {895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 377: 895, 381: 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895, 895}, + // 295 + {894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 377: 894, 381: 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894, 894}, + {893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 377: 893, 381: 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893}, + {892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 377: 892, 381: 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, 892}, + {891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 377: 891, 381: 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891}, + {890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 377: 890, 381: 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890, 890}, + // 300 + {889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 377: 889, 381: 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889, 889}, + {888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 377: 888, 381: 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888}, + {887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 377: 887, 381: 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887, 887}, + {886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 377: 886, 381: 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886}, + {885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 377: 885, 381: 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885}, + // 305 + {884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 377: 884, 381: 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884, 884}, + {883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 377: 883, 381: 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883, 883}, + {882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 377: 882, 381: 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882, 882}, + {881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 377: 881, 381: 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881, 881}, + {880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 377: 880, 381: 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880, 880}, + // 310 + {879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 377: 879, 381: 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879, 879}, + {878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 377: 878, 381: 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878, 878}, + {877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 377: 877, 381: 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877}, + {876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 377: 876, 381: 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876, 876}, + {875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 377: 875, 381: 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875, 875}, + // 315 + {874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 377: 874, 381: 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874}, + {873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 377: 873, 381: 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873}, + {872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 377: 872, 381: 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872, 872}, + {871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 377: 871, 381: 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871}, + {870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 377: 870, 381: 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, 870}, + // 320 + {601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 221: 601, 601, 601, 227: 601, 601, 601, 231: 601, 601, 601, 601, 240: 601, 601, 601, 244: 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 601, 257: 601, 277: 601, 279: 1761, 310: 601, 314: 601, 377: 601, 381: 601, 601, 601, 601, 601, 388: 601, 601, 392: 601, 601, 601, 601, 601, 601, 601, 601, 601, 406: 601, 409: 601, 412: 601, 434: 601}, + {15, 15, 6: 1759}, + {398: 1756, 434: 1757, 782: 1755}, + {8, 8, 6: 8}, + {12, 12, 6: 12}, + // 325 + {11, 11, 6: 11, 59: 1758}, + {9, 9, 6: 9}, + {10, 10, 6: 10}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 1753, 701: 1760}, + {7, 7, 6: 7}, + // 330 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1762, 378: 1537, 1538, 1536}, + {600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 221: 600, 600, 600, 227: 600, 600, 600, 231: 600, 600, 600, 600, 240: 600, 600, 600, 244: 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 257: 600, 277: 600, 310: 600, 314: 600, 377: 600, 381: 600, 600, 600, 600, 600, 388: 600, 600, 392: 600, 600, 600, 600, 600, 600, 600, 600, 600, 406: 600, 409: 600, 412: 600, 434: 600}, + {16, 16}, + {59: 1768, 584: 34, 780: 1767}, + {219: 1766}, + // 335 + {1, 1}, + {584: 1769}, + {584: 33}, + {219: 1770}, + {497: 1771}, + // 340 + {474: 1772}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 1773}, + {36, 36, 29: 36, 39: 36, 217: 36, 377: 36, 382: 1775, 389: 36, 731: 1774}, + {32, 32, 29: 1785, 39: 1784, 217: 32, 377: 32, 389: 32, 755: 1782, 1783}, + {246: 1776}, + // 345 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 1781}, + {400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 14: 400, 400, 400, 400, 400, 400, 400, 400, 29: 400, 39: 400, 217: 400, 400, 220: 400, 400, 227: 400, 230: 400, 249: 400, 255: 400, 288: 400, 370: 400, 400, 400, 400, 400, 400, 377: 400, 381: 400, 400, 400, 400, 400, 389: 400}, + {399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 14: 399, 399, 399, 399, 399, 399, 399, 399, 29: 399, 39: 399, 217: 399, 399, 220: 399, 399, 227: 399, 230: 399, 249: 399, 255: 399, 288: 399, 370: 399, 399, 399, 399, 399, 399, 377: 399, 381: 399, 399, 399, 399, 399, 389: 399}, + {110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 257: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 280: 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 307: 110, 363: 110, 370: 110, 110, 110, 110, 110, 110, 377: 110, 381: 110, 110, 110, 110, 110, 389: 110, 110, 110, 408: 110}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 257: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 280: 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 307: 109, 363: 109, 370: 109, 109, 109, 109, 109, 109, 377: 109, 381: 109, 109, 109, 109, 109, 389: 109, 109, 109, 408: 109}, + // 350 + {35, 35, 29: 35, 39: 35, 217: 35, 377: 35, 389: 35}, + {22, 22, 217: 22, 377: 22, 389: 1799, 778: 1798}, + {28, 28, 217: 28, 377: 28, 389: 28, 515: 28, 538: 1787, 543: 28, 757: 1786}, + {30, 30, 217: 30, 377: 30, 389: 30, 515: 30, 538: 30, 543: 30}, + {29, 29, 217: 29, 377: 29, 389: 29, 515: 29, 538: 29, 543: 29}, + // 355 + {26, 26, 217: 26, 377: 26, 389: 26, 515: 26, 543: 1791, 751: 1790}, + {390: 1788}, + {219: 1789}, + {27, 27, 217: 27, 377: 27, 389: 27, 515: 27, 543: 27}, + {24, 24, 217: 24, 377: 24, 389: 24, 515: 1795, 752: 1794}, + // 360 + {390: 1792}, + {219: 1793}, + {25, 25, 217: 25, 377: 25, 389: 25, 515: 25}, + {31, 31, 217: 31, 377: 31, 389: 31}, + {390: 1796}, + // 365 + {219: 1797}, + {23, 23, 217: 23, 377: 23, 389: 23}, + {38, 38, 217: 38, 377: 1809, 767: 1808}, + {20, 20, 217: 20, 377: 20, 538: 20, 820: 1800, 1801}, + {18, 18, 217: 18, 377: 18, 538: 1805, 779: 1804}, + // 370 + {390: 1802}, + {219: 1803}, + {19, 19, 217: 19, 377: 19, 538: 19}, + {21, 21, 217: 21, 377: 21}, + {390: 1806}, + // 375 + {219: 1807}, + {17, 17, 217: 17, 377: 17}, + {1345, 1345, 217: 1812, 734: 1813}, + {256: 1526, 461: 1810}, + {389: 1811}, + // 380 + {37, 37, 217: 37}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 1347, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 1816, 611: 1817}, + {39, 39}, + {1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 243: 1352, 246: 1352, 262: 1352, 1352, 279: 1821, 288: 1352, 308: 1352, 394: 1352, 1352, 1352, 403: 1352, 1352, 1352, 407: 1352, 410: 1352, 1352, 413: 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352}, + {6: 1349, 9: 1349}, + // 385 + {6: 1819, 9: 1346}, + {9: 1818}, + {1344, 1344}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1820}, + {6: 1348, 9: 1348}, + // 390 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1822, 378: 1537, 1538, 1536}, + {1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 243: 1351, 246: 1351, 262: 1351, 1351, 279: 1823, 288: 1351, 308: 1351, 394: 1351, 1351, 1351, 403: 1351, 1351, 1351, 407: 1351, 410: 1351, 1351, 413: 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351, 1351}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1824, 378: 1537, 1538, 1536}, + {1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 243: 1350, 246: 1350, 262: 1350, 1350, 288: 1350, 308: 1350, 394: 1350, 1350, 1350, 403: 1350, 1350, 1350, 407: 1350, 410: 1350, 1350, 413: 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350, 1350}, + {6: 80, 217: 1903, 80}, + // 395 + {6: 78, 218: 78}, + {6: 1862, 218: 1863}, + {6: 76, 49: 1861, 217: 76, 76}, + {6: 74, 99: 1860, 217: 74, 74}, + {6: 73, 22: 1857, 62: 1855, 99: 1858, 166: 1856, 217: 73, 73}, + // 400 + {6: 71, 217: 71, 71}, + {6: 70, 217: 70, 70}, + {6: 69, 217: 69, 69}, + {6: 68, 217: 68, 68}, + {6: 67, 217: 67, 67}, + // 405 + {6: 66, 217: 66, 66}, + {6: 65, 217: 65, 65}, + {6: 64, 217: 64, 64}, + {6: 63, 217: 63, 63}, + {22: 1854, 621: 1853}, + // 410 + {6: 61, 217: 61, 61}, + {561: 1852}, + {6: 59, 217: 59, 59}, + {115: 1851, 160: 1850}, + {6: 56, 217: 56, 56}, + // 415 + {6: 55, 217: 55, 55}, + {25: 1849}, + {6: 48, 217: 48, 48}, + {6: 53, 217: 53, 53}, + {6: 58, 217: 58, 58}, + // 420 + {6: 57, 217: 57, 57}, + {6: 60, 217: 60, 60}, + {6: 62, 217: 62, 62}, + {6: 51, 217: 51, 51}, + {6: 72, 217: 72, 72}, + // 425 + {25: 1859}, + {6: 52, 217: 52, 52}, + {6: 50, 217: 50, 50}, + {6: 54, 217: 54, 54}, + {6: 49, 217: 49, 49}, + // 430 + {6: 75, 217: 75, 75}, + {52: 1835, 64: 1848, 68: 1834, 71: 1846, 1844, 1839, 231: 1847, 301: 1837, 374: 1843, 381: 1838, 388: 1836, 394: 1833, 399: 1829, 465: 1828, 479: 1841, 486: 1832, 526: 1830, 528: 1842, 534: 1840, 590: 1902, 1825, 598: 1831, 1845}, + {2: 47, 47, 47, 47, 7: 47, 47, 10: 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 258: 47, 474: 1864, 666: 1865}, + {2: 46, 46, 46, 46, 7: 46, 46, 10: 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 258: 46}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 258: 1866, 376: 1867, 378: 1537, 1538, 1536, 684: 1868}, + // 435 + {241: 45, 279: 1900, 397: 45}, + {241: 41, 279: 1897, 397: 41}, + {241: 1869}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 1872, 553: 1873, 568: 1874}, + {391, 391, 6: 391, 22: 391, 40: 391, 228: 391, 243: 391, 307: 1895, 391: 391, 408: 1894}, + // 440 + {727, 727, 6: 727, 22: 727, 40: 727, 217: 1891, 228: 727, 243: 727, 391: 727, 672: 1892}, + {94, 94, 6: 94, 40: 1878, 228: 94, 725: 1877}, + {96, 96, 6: 96, 228: 96}, + {40, 40, 6: 1875}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 1872, 553: 1876}, + // 445 + {95, 95, 6: 95, 228: 95}, + {97, 97, 6: 97, 228: 97}, + {228: 1880, 390: 1879}, + {12: 1889, 219: 1886, 555: 1888}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 1881}, + // 450 + {92, 92, 6: 92, 221: 1883, 228: 92, 390: 1882}, + {219: 1886, 555: 1887}, + {219: 1885, 648: 1884}, + {90, 90, 6: 90, 228: 90}, + {88, 88, 6: 88, 228: 88}, + // 455 + {383, 383, 6: 383, 9: 383, 228: 383}, + {91, 91, 6: 91, 228: 91}, + {93, 93, 6: 93, 228: 93}, + {219: 1885, 648: 1890}, + {89, 89, 6: 89, 228: 89}, + // 460 + {9: 1893}, + {388, 388, 6: 388, 22: 388, 40: 388, 228: 388, 243: 388, 391: 388}, + {726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 218: 726, 726, 726, 726, 726, 726, 726, 726, 726, 228: 726, 726, 231: 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 257: 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 280: 726, 726, 726, 726, 726, 726, 726, 726, 289: 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, 363: 726, 391: 726}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 1896}, + {389, 389, 6: 389, 22: 389, 40: 389, 228: 389, 243: 389, 391: 389}, + // 465 + {390, 390, 6: 390, 22: 390, 40: 390, 228: 390, 243: 390, 391: 390}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 258: 1898, 376: 1899, 378: 1537, 1538, 1536}, + {241: 43, 397: 43}, + {241: 42, 397: 42}, + {258: 1901}, + // 470 + {241: 44, 397: 44}, + {6: 77, 218: 77}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 1904}, + {6: 1819, 9: 1905}, + {6: 79, 218: 79}, + // 475 + {6: 1862, 218: 1907}, + {2: 47, 47, 47, 47, 7: 47, 47, 10: 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 258: 47, 474: 1864, 666: 1908}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 258: 1866, 376: 1867, 378: 1537, 1538, 1536, 684: 1909}, + {397: 1910}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 1872, 553: 1873, 568: 1911}, + // 480 + {86, 86, 6: 1875, 228: 1913, 860: 1912}, + {87, 87}, + {140: 1917, 1915, 1916, 1918, 528: 1914}, + {561: 1923}, + {256: 1526, 461: 1922}, + // 485 + {256: 1526, 461: 1921}, + {256: 1526, 461: 1920}, + {256: 1526, 461: 1919}, + {81, 81}, + {82, 82}, + // 490 + {83, 83}, + {84, 84}, + {85, 85}, + {1280, 1280, 7: 1280, 227: 1280, 240: 1280, 249: 1280, 257: 1280, 382: 1280}, + {106, 106}, + // 495 + {41: 2780, 43: 2779, 2778, 2777, 702: 2776, 831: 2775}, + {2: 605, 605, 605, 605, 7: 605, 605, 10: 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 303: 605, 377: 605, 482: 1930, 1929, 1928, 551: 1931}, + {2: 604, 604, 604, 604, 7: 604, 604, 10: 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 219: 604, 604, 222: 604, 604, 604, 604, 604, 604, 230: 604, 241: 604, 244: 604, 255: 604, 604, 258: 604, 279: 604, 288: 604, 300: 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, 364: 604, 604, 604, 604, 604, 604, 377: 604, 480: 604, 497: 604}, + {2: 603, 603, 603, 603, 7: 603, 603, 10: 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 219: 603, 603, 222: 603, 603, 603, 603, 603, 603, 230: 603, 241: 603, 244: 603, 255: 603, 603, 258: 603, 279: 603, 288: 603, 300: 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 603, 364: 603, 603, 603, 603, 603, 603, 377: 603, 480: 603, 497: 603}, + {2: 602, 602, 602, 602, 7: 602, 602, 10: 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 219: 602, 602, 222: 602, 602, 602, 602, 602, 602, 230: 602, 241: 602, 244: 602, 255: 602, 602, 258: 602, 279: 602, 288: 602, 300: 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 364: 602, 602, 602, 602, 602, 602, 377: 602, 480: 602, 497: 602}, + // 500 + {2: 1098, 1098, 1098, 1098, 7: 1098, 1098, 10: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 303: 1098, 377: 1932, 557: 1933}, + {2: 1097, 1097, 1097, 1097, 7: 1097, 1097, 10: 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 241: 1097, 303: 1097, 474: 1097, 497: 1097}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 1936, 516: 1934, 537: 1935}, + {517, 517, 6: 517, 9: 517, 218: 517, 228: 517, 517, 231: 517, 517, 517, 517, 240: 517, 245: 517, 517, 517, 250: 517}, + {6: 2719, 246: 2772}, + // 505 + {6: 515, 222: 1960, 1961, 244: 1959, 246: 2754, 248: 1962, 251: 1963, 1964, 1958, 502: 1957, 506: 1956}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2751, 378: 1537, 1538, 1536}, + {513, 513, 6: 513, 9: 513, 218: 513, 222: 513, 513, 228: 513, 513, 231: 513, 513, 513, 513, 240: 513, 242: 513, 244: 513, 513, 513, 513, 513, 250: 513, 513, 513, 513, 513}, + {512, 512, 6: 512, 9: 512, 218: 512, 222: 512, 512, 228: 512, 512, 231: 512, 512, 512, 512, 240: 512, 242: 512, 244: 512, 512, 512, 512, 512, 250: 512, 512, 512, 512, 512}, + {507, 507, 1622, 1541, 1575, 1542, 507, 1552, 1627, 507, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 218: 507, 221: 1950, 507, 507, 228: 507, 507, 231: 507, 507, 507, 507, 240: 507, 242: 507, 244: 507, 507, 507, 507, 507, 250: 507, 507, 507, 507, 507, 376: 1949, 507, 1537, 1538, 1536, 392: 507, 507, 566: 2723, 826: 2722}, + // 510 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1944, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 1457, 459: 1940, 469: 1945, 1458, 1459, 1460, 475: 1463, 477: 1462, 1946, 489: 1939, 1938, 1943, 516: 1934, 537: 1942}, + {6: 2719, 9: 2720}, + {515, 515, 6: 515, 9: 515, 218: 515, 222: 1960, 1961, 228: 515, 515, 231: 515, 515, 515, 515, 240: 515, 244: 1959, 515, 515, 515, 1962, 250: 515, 1963, 1964, 1958, 502: 1957, 506: 1956}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1944, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 1457, 459: 1940, 469: 1954, 1458, 1459, 1460, 475: 1463, 477: 1462, 1946, 489: 1939, 1938, 1943, 516: 1934, 537: 1942}, + {9: 1952, 229: 431}, + // 515 + {9: 1947}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 221: 1950, 376: 1949, 378: 1537, 1538, 1536, 566: 1948}, + {509, 509, 6: 509, 9: 509, 218: 509, 222: 509, 509, 228: 509, 509, 231: 509, 509, 509, 509, 240: 509, 242: 509, 244: 509, 509, 509, 509, 509, 250: 509, 509, 509, 509, 509}, + {505, 505, 6: 505, 9: 505, 218: 505, 222: 505, 505, 228: 505, 505, 231: 505, 505, 505, 505, 240: 505, 242: 505, 244: 505, 505, 505, 505, 505, 250: 505, 505, 505, 505, 505, 377: 505, 392: 505, 505}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1951, 378: 1537, 1538, 1536}, + // 520 + {504, 504, 6: 504, 9: 504, 218: 504, 222: 504, 504, 228: 504, 504, 231: 504, 504, 504, 504, 240: 504, 242: 504, 244: 504, 504, 504, 504, 504, 250: 504, 504, 504, 504, 504, 377: 504, 392: 504, 504}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 221: 1950, 376: 1949, 378: 1537, 1538, 1536, 566: 1953}, + {510, 510, 6: 510, 9: 510, 218: 510, 222: 510, 510, 228: 510, 510, 231: 510, 510, 510, 510, 240: 510, 242: 510, 244: 510, 510, 510, 510, 510, 250: 510, 510, 510, 510, 510}, + {9: 1955, 229: 431}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 221: 1950, 229: 430, 376: 1949, 378: 1537, 1538, 1536, 566: 1953}, + // 525 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 2712}, + {248: 476, 562: 2699, 676: 2703}, + {222: 1960, 1961, 248: 2696, 502: 2697}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 1967}, + {248: 478, 562: 478}, + // 530 + {248: 477, 562: 477}, + {2: 474, 474, 474, 474, 7: 474, 474, 10: 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474}, + {248: 1966}, + {248: 1965}, + {2: 472, 472, 472, 472, 7: 472, 472, 10: 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472}, + // 535 + {2: 473, 473, 473, 473, 7: 473, 473, 10: 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473}, + {480, 480, 6: 480, 9: 480, 218: 1968, 222: 480, 480, 228: 480, 480, 231: 480, 480, 480, 480, 240: 480, 242: 480, 244: 480, 480, 480, 480, 480, 250: 480, 480, 480, 480, 480, 502: 1957, 506: 1956}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 1970}, + {392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 218: 392, 392, 392, 392, 392, 392, 392, 392, 392, 228: 392, 392, 231: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 257: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 280: 392, 392, 392, 392, 392, 392, 392, 392, 289: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 363: 392, 570: 2694}, + {479, 479, 6: 479, 9: 479, 218: 479, 222: 479, 479, 228: 479, 479, 231: 479, 479, 479, 479, 2110, 2108, 2109, 2107, 2105, 479, 242: 479, 244: 479, 479, 479, 479, 479, 250: 479, 479, 479, 479, 479, 457: 2106, 2104}, + // 540 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2693}, + {1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 218: 1170, 1170, 221: 1170, 1170, 1170, 228: 1170, 1170, 231: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 2676, 1170, 1170, 1170, 1170, 1170, 250: 1170, 1170, 1170, 1170, 1170, 259: 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 278: 1170, 280: 2673, 2671, 2670, 2678, 2672, 2674, 2675, 2677, 738: 2669, 772: 2668}, + {1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 218: 1150, 1150, 221: 1150, 1150, 1150, 228: 1150, 1150, 231: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 250: 1150, 1150, 1150, 1150, 1150, 259: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150, 278: 1150, 280: 1150, 1150, 1150, 1150, 1150, 1150, 1150, 1150}, + {1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 218: 1123, 1123, 2642, 1123, 1123, 1123, 2386, 2387, 2392, 228: 1123, 1123, 231: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 250: 1123, 1123, 1123, 1123, 1123, 257: 2644, 2388, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 2643, 1123, 280: 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 289: 2641, 2390, 2383, 2389, 2393, 2382, 2391, 2384, 2385, 2650, 2651, 686: 2645, 726: 2647, 769: 2646, 776: 2648, 810: 2649}, + {1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 2638, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 228: 1085, 1085, 231: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 257: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 289: 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 363: 1085, 386: 1085, 1085}, + // 545 + {1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 756, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 228: 1080, 1080, 231: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 257: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 289: 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1080, 363: 1080, 386: 1080, 1080}, + {1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 2633, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 228: 1076, 1076, 231: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 257: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 289: 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 363: 1076, 386: 1076, 1076}, + {1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 755, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 228: 1068, 1068, 231: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 257: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 289: 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 363: 1068, 386: 1068, 1068}, + {1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 752, 1060, 2632, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 228: 1060, 1060, 231: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 257: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 289: 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 363: 1060, 386: 1060, 1060}, + {1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 750, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 228: 1058, 1058, 231: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 257: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 289: 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 363: 1058, 386: 1058, 1058}, + // 550 + {1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 746, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 228: 1041, 1041, 231: 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 257: 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 289: 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 363: 1041, 386: 1041, 1041}, + {1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 749, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 228: 1037, 1037, 231: 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 257: 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 289: 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 363: 1037, 386: 1037, 1037}, + {1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 2629, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 228: 1031, 1031, 231: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 257: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 289: 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 363: 1031, 386: 1031, 1031}, + {1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 733, 1015, 2628, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 228: 1015, 1015, 231: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 257: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 289: 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 363: 1015, 386: 1015, 1015}, + {1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 732, 1014, 2627, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 228: 1014, 1014, 231: 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 257: 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 289: 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 363: 1014, 386: 1014, 1014}, + // 555 + {1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 731, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 228: 1011, 1011, 231: 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 257: 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 289: 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 363: 1011, 386: 1011, 1011}, + {1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 728, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 228: 1006, 1006, 231: 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 257: 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 289: 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 363: 1006, 386: 1006, 1006}, + {1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 729, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 228: 1004, 1004, 231: 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 257: 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 289: 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 1004, 363: 1004, 386: 1004, 1004}, + {1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 730, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 228: 1001, 1001, 231: 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 257: 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 289: 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 363: 1001, 386: 1001, 1001}, + {999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 753, 999, 999, 999, 999, 999, 999, 999, 999, 999, 228: 999, 999, 231: 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 257: 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 289: 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 363: 999, 386: 999, 999}, + // 560 + {987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 740, 987, 987, 987, 987, 987, 987, 987, 987, 987, 228: 987, 987, 231: 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 257: 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 289: 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 987, 363: 987, 386: 987, 987}, + {967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 737, 967, 967, 967, 967, 967, 967, 967, 967, 967, 228: 967, 967, 231: 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 257: 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 289: 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 967, 363: 967, 386: 967, 967}, + {953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 735, 953, 953, 953, 953, 953, 953, 953, 953, 953, 228: 953, 953, 231: 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 257: 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 289: 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 953, 363: 953, 386: 953, 953}, + {952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 754, 952, 952, 952, 952, 952, 952, 952, 952, 952, 228: 952, 952, 231: 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 257: 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 289: 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 952, 363: 952, 386: 952, 952}, + {951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 742, 951, 951, 951, 951, 951, 951, 951, 951, 951, 228: 951, 951, 231: 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 257: 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 289: 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 951, 363: 951, 386: 951, 951}, + // 565 + {948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 744, 948, 948, 948, 948, 948, 948, 948, 948, 948, 228: 948, 948, 231: 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 257: 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 289: 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, 363: 948, 386: 948, 948}, + {947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 743, 947, 947, 947, 947, 947, 947, 947, 947, 947, 228: 947, 947, 231: 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 257: 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 289: 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 947, 363: 947, 386: 947, 947}, + {942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 734, 942, 942, 942, 942, 942, 942, 942, 942, 942, 228: 942, 942, 231: 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 257: 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 289: 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 942, 363: 942, 386: 942, 942}, + {891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 2618, 891, 891, 891, 891, 891, 891, 891, 891, 891, 228: 891, 891, 231: 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 257: 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 289: 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, 363: 891, 386: 891, 891}, + {874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 2611, 874, 874, 874, 874, 874, 874, 874, 874, 874, 228: 874, 874, 231: 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 257: 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 289: 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 874, 363: 874, 386: 874, 874}, + // 570 + {873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 2595, 873, 873, 873, 873, 873, 873, 873, 873, 873, 228: 873, 873, 231: 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 257: 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 289: 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 873, 363: 873, 386: 873, 873}, + {836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 218: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 257: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 280: 836, 836, 836, 836, 836, 836, 836, 836, 289: 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 836, 363: 836, 370: 836, 836, 836, 836, 836, 836}, + {835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 218: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 257: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 280: 835, 835, 835, 835, 835, 835, 835, 835, 289: 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 835, 363: 835, 370: 835, 835, 835, 835, 835, 835}, + {834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 218: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 257: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 280: 834, 834, 834, 834, 834, 834, 834, 834, 289: 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 834, 363: 834, 370: 834, 834, 834, 834, 834, 834}, + {833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 218: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 257: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 280: 833, 833, 833, 833, 833, 833, 833, 833, 289: 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 833, 363: 833, 370: 833, 833, 833, 833, 833, 833}, + // 575 + {832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 218: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 257: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 280: 832, 832, 832, 832, 832, 832, 832, 832, 289: 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 363: 832, 370: 832, 832, 832, 832, 832, 832}, + {831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 218: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 257: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 280: 831, 831, 831, 831, 831, 831, 831, 831, 289: 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 831, 363: 831, 370: 831, 831, 831, 831, 831, 831}, + {830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 218: 830, 2594, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 257: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 280: 830, 830, 830, 830, 830, 830, 830, 830, 289: 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 830, 363: 830, 370: 830, 830, 830, 830, 830, 830}, + {219: 2593}, + {828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 218: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 257: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 280: 828, 828, 828, 828, 828, 828, 828, 828, 289: 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 363: 828, 370: 828, 828, 828, 828, 828, 828}, + // 580 + {827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 218: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 257: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 280: 827, 827, 827, 827, 827, 827, 827, 827, 289: 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 827, 363: 827, 370: 827, 827, 827, 827, 827, 827}, + {826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 218: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 257: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 280: 826, 826, 826, 826, 826, 826, 826, 826, 289: 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 826, 363: 826, 370: 826, 826, 826, 826, 826, 826}, + {801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 218: 801, 801, 801, 801, 801, 801, 801, 801, 801, 228: 801, 801, 231: 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 2114, 801, 801, 801, 801, 801, 257: 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 280: 801, 801, 801, 801, 801, 801, 801, 801, 289: 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 801, 363: 2115}, + {800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 218: 800, 800, 800, 800, 800, 800, 800, 800, 800, 228: 800, 800, 231: 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 257: 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 2589, 800, 800, 800, 800, 800, 800, 800, 800, 289: 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 363: 800, 386: 800, 800}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2586, 378: 1537, 1538, 1536}, + // 585 + {796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 218: 796, 796, 796, 796, 796, 796, 796, 796, 796, 228: 796, 796, 231: 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 257: 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 280: 796, 796, 796, 796, 796, 796, 796, 796, 289: 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 796, 363: 796, 386: 2582, 2583}, + {795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 218: 795, 795, 795, 795, 795, 795, 795, 795, 795, 228: 795, 795, 231: 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 257: 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 280: 795, 795, 795, 795, 795, 795, 795, 795, 289: 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, 363: 795}, + {794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 218: 794, 794, 794, 794, 794, 794, 794, 794, 794, 228: 794, 794, 231: 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 257: 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 280: 794, 794, 794, 794, 794, 794, 794, 794, 289: 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 794, 363: 794}, + {793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 218: 793, 793, 793, 793, 793, 793, 793, 793, 793, 228: 793, 793, 231: 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 257: 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 280: 793, 793, 793, 793, 793, 793, 793, 793, 289: 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 793, 363: 793}, + {791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 218: 791, 791, 791, 791, 791, 791, 791, 791, 791, 228: 791, 791, 231: 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 257: 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 280: 791, 791, 791, 791, 791, 791, 791, 791, 289: 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 363: 791}, + // 590 + {790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 218: 790, 790, 790, 790, 790, 790, 790, 790, 790, 228: 790, 790, 231: 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 257: 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 280: 790, 790, 790, 790, 790, 790, 790, 790, 289: 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 790, 363: 790}, + {789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 218: 789, 789, 789, 789, 789, 789, 789, 789, 789, 228: 789, 789, 231: 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 257: 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 280: 789, 789, 789, 789, 789, 789, 789, 789, 289: 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 363: 789}, + {788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 218: 788, 788, 788, 788, 788, 788, 788, 788, 788, 228: 788, 788, 231: 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 257: 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 280: 788, 788, 788, 788, 788, 788, 788, 788, 289: 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 363: 788}, + {787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 218: 787, 787, 787, 787, 787, 787, 787, 787, 787, 228: 787, 787, 231: 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 257: 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 280: 787, 787, 787, 787, 787, 787, 787, 787, 289: 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 363: 787}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2581, 2024, 2099, 2023, 2020}, + // 595 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2580, 2024, 2099, 2023, 2020}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2579, 2024, 2099, 2023, 2020}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2578, 2024, 2099, 2023, 2020}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2577, 2024, 2099, 2023, 2020}, + {780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 218: 780, 780, 780, 780, 780, 780, 780, 780, 780, 228: 780, 780, 231: 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 257: 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 280: 780, 780, 780, 780, 780, 780, 780, 780, 289: 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 780, 363: 780}, + // 600 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2570, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 1457, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2568, 469: 2556, 1458, 1459, 1460, 475: 1463, 477: 1462, 2557, 488: 2569}, + {217: 2563}, + {217: 2555, 435: 2554}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2553, 2024, 2099, 2023, 2020}, + {217: 2548}, + // 605 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 274: 621, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2535, 753: 2536}, + {217: 2485}, + {217: 2482}, + {217: 2479}, + {217: 751}, + // 610 + {217: 748}, + {217: 747}, + {217: 745}, + {217: 741}, + {217: 739}, + // 615 + {217: 738}, + {217: 736}, + {725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 228: 725, 725, 231: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 257: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 280: 725, 725, 725, 725, 725, 725, 725, 725, 289: 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 363: 725}, + {724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 228: 724, 724, 231: 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 257: 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 280: 724, 724, 724, 724, 724, 724, 724, 724, 289: 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 724, 363: 724}, + {723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 228: 723, 723, 231: 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 257: 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 280: 723, 723, 723, 723, 723, 723, 723, 723, 289: 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 723, 363: 723}, + // 620 + {722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 228: 722, 722, 231: 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 257: 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 280: 722, 722, 722, 722, 722, 722, 722, 722, 289: 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 722, 363: 722}, + {721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 228: 721, 721, 231: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 257: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 280: 721, 721, 721, 721, 721, 721, 721, 721, 289: 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 721, 363: 721}, + {720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 228: 720, 720, 231: 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 257: 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 280: 720, 720, 720, 720, 720, 720, 720, 720, 289: 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 720, 363: 720}, + {719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 228: 719, 719, 231: 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 257: 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 280: 719, 719, 719, 719, 719, 719, 719, 719, 289: 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 719, 363: 719}, + {718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 228: 718, 718, 231: 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 257: 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 280: 718, 718, 718, 718, 718, 718, 718, 718, 289: 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 718, 363: 718}, + // 625 + {717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 228: 717, 717, 231: 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 257: 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 280: 717, 717, 717, 717, 717, 717, 717, 717, 289: 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 717, 363: 717}, + {217: 2476}, + {217: 2473}, + {727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 1891, 727, 727, 727, 727, 727, 727, 727, 727, 727, 228: 727, 727, 231: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 257: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 280: 727, 727, 727, 727, 727, 727, 727, 727, 289: 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 363: 727, 672: 2472}, + {217: 2470}, + // 630 + {653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 2466, 653, 653, 653, 653, 653, 653, 653, 653, 653, 228: 653, 653, 231: 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 257: 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 280: 653, 653, 653, 653, 653, 653, 653, 653, 289: 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, 363: 653, 761: 2465}, + {217: 2459}, + {217: 2455}, + {217: 2450}, + {667: 2447, 2444, 2446, 2445}, + // 635 + {217: 2441}, + {217: 2436}, + {217: 2427}, + {217: 2420}, + {217: 2415}, + // 640 + {217: 2380}, + {217: 2366}, + {217: 2349}, + {217: 680}, + {217: 679}, + // 645 + {217: 678}, + {217: 677}, + {217: 2341}, + {217: 2333}, + {217: 2325}, + // 650 + {217: 2311}, + {217: 2296}, + {217: 2291}, + {217: 2286}, + {217: 2281}, + // 655 + {217: 2276}, + {217: 2263}, + {217: 2260}, + {217: 2257}, + {217: 2254}, + // 660 + {217: 2251}, + {217: 2248}, + {217: 2244}, + {217: 2238}, + {217: 2225}, + // 665 + {217: 2220}, + {217: 2215}, + {217: 2102}, + {395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 218: 395, 395, 395, 395, 395, 395, 395, 395, 395, 228: 395, 395, 231: 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 257: 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 280: 395, 395, 395, 395, 395, 395, 395, 395, 289: 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 363: 395}, + {394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 218: 394, 394, 394, 394, 394, 394, 394, 394, 394, 228: 394, 394, 231: 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 257: 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 280: 394, 394, 394, 394, 394, 394, 394, 394, 289: 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 363: 394}, + // 670 + {393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 218: 393, 393, 393, 393, 393, 393, 393, 393, 393, 228: 393, 393, 231: 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 257: 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 280: 393, 393, 393, 393, 393, 393, 393, 393, 289: 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, 363: 393}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2103}, + {6: 2111, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2214}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2213}, + // 675 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2212}, + {2: 1167, 1167, 1167, 1167, 7: 1167, 1167, 10: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 219: 1167, 1167, 222: 1167, 1167, 1167, 1167, 1167, 1167, 230: 1167, 255: 1167, 1167, 279: 1167, 288: 1167, 300: 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 364: 1167, 1167, 1167, 1167, 1167, 1167}, + {2: 1166, 1166, 1166, 1166, 7: 1166, 1166, 10: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 219: 1166, 1166, 222: 1166, 1166, 1166, 1166, 1166, 1166, 230: 1166, 255: 1166, 1166, 279: 1166, 288: 1166, 300: 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 364: 1166, 1166, 1166, 1166, 1166, 1166}, + {2: 1165, 1165, 1165, 1165, 7: 1165, 1165, 10: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 219: 1165, 1165, 222: 1165, 1165, 1165, 1165, 1165, 1165, 230: 1165, 255: 1165, 1165, 279: 1165, 288: 1165, 300: 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 364: 1165, 1165, 1165, 1165, 1165, 1165}, + {2: 1164, 1164, 1164, 1164, 7: 1164, 1164, 10: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 219: 1164, 1164, 222: 1164, 1164, 1164, 1164, 1164, 1164, 230: 1164, 255: 1164, 1164, 279: 1164, 288: 1164, 300: 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 364: 1164, 1164, 1164, 1164, 1164, 1164}, + // 680 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2112, 2024, 2099, 2023, 2020}, + {9: 2116, 249: 2114, 363: 2115}, + {392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 218: 392, 392, 392, 392, 392, 392, 392, 392, 392, 228: 392, 392, 231: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 257: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 280: 392, 392, 392, 392, 392, 392, 392, 392, 289: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 363: 392}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 2211}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2210, 2024, 2099, 2023, 2020}, + // 685 + {42: 521, 241: 2118, 377: 521, 463: 521, 793: 2117}, + {42: 2122, 377: 2123, 463: 524, 550: 2121}, + {4: 2119, 136: 2120}, + {42: 520, 377: 520, 463: 520}, + {42: 519, 377: 519, 463: 519}, + // 690 + {463: 2126, 467: 2127}, + {96: 2125}, + {96: 2124}, + {463: 522}, + {463: 523}, + // 695 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 2129, 376: 2128, 378: 1537, 1538, 1536, 569: 2131, 719: 2132, 858: 2130}, + {530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 218: 530, 530, 530, 530, 530, 530, 530, 530, 530, 228: 530, 530, 231: 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 257: 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 280: 530, 530, 530, 530, 530, 530, 530, 530, 289: 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 363: 530}, + {572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 218: 572, 572, 572, 572, 572, 572, 572, 572, 572, 228: 572, 572, 231: 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 257: 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 280: 572, 572, 572, 572, 572, 572, 572, 572, 289: 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 363: 572, 383: 572}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 569, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 234: 569, 259: 569, 569, 569, 376: 2128, 378: 1537, 1538, 1536, 383: 569, 569: 2135, 792: 2134, 859: 2133}, + {543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 218: 543, 543, 543, 543, 543, 543, 543, 543, 543, 228: 543, 543, 231: 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 257: 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 280: 543, 543, 543, 543, 543, 543, 543, 543, 289: 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 363: 543}, + // 700 + {542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 218: 542, 542, 542, 542, 542, 542, 542, 542, 542, 228: 542, 542, 231: 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 257: 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 280: 542, 542, 542, 542, 542, 542, 542, 542, 289: 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 363: 542}, + {541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 218: 541, 541, 541, 541, 541, 541, 541, 541, 541, 228: 541, 541, 231: 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 257: 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 280: 541, 541, 541, 541, 541, 541, 541, 541, 289: 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 363: 541}, + {9: 2209}, + {9: 567, 234: 567, 259: 567, 567, 567, 383: 2137, 796: 2136}, + {9: 568, 234: 568, 259: 568, 568, 568, 383: 568}, + // 705 + {9: 565, 234: 2148, 259: 565, 565, 565, 799: 2147}, + {390: 2138}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2139, 539: 2140, 556: 2141}, + {820, 820, 6: 820, 9: 820, 23: 820, 218: 820, 228: 820, 820, 231: 820, 820, 820, 820, 2110, 2108, 2109, 2107, 2105, 245: 820, 247: 820, 259: 820, 820, 820, 2146, 2145, 457: 2106, 2104, 675: 2144}, + {823, 823, 6: 823, 9: 823, 23: 823, 218: 823, 228: 823, 823, 231: 823, 823, 823, 823, 245: 823, 247: 823, 259: 823, 823, 823}, + // 710 + {6: 2142, 9: 566, 234: 566, 259: 566, 566, 566}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2139, 539: 2143}, + {822, 822, 6: 822, 9: 822, 23: 822, 218: 822, 228: 822, 822, 231: 822, 822, 822, 822, 245: 822, 247: 822, 259: 822, 822, 822}, + {821, 821, 6: 821, 9: 821, 23: 821, 218: 821, 228: 821, 821, 231: 821, 821, 821, 821, 245: 821, 247: 821, 259: 821, 821, 821}, + {819, 819, 6: 819, 9: 819, 23: 819, 218: 819, 228: 819, 819, 231: 819, 819, 819, 819, 245: 819, 247: 819, 259: 819, 819, 819}, + // 715 + {818, 818, 6: 818, 9: 818, 23: 818, 218: 818, 228: 818, 818, 231: 818, 818, 818, 818, 245: 818, 247: 818, 259: 818, 818, 818}, + {9: 563, 259: 2154, 2155, 2153, 798: 2151, 857: 2152}, + {390: 2149}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2139, 539: 2140, 556: 2150}, + {6: 2142, 9: 564, 259: 564, 564, 564}, + // 720 + {9: 570}, + {47: 2166, 50: 2162, 256: 2156, 289: 2167, 304: 2158, 2157, 2164, 309: 2165, 530: 2163, 601: 2160, 855: 2161, 2159}, + {47: 561, 50: 561, 256: 561, 289: 561, 304: 561, 561, 561, 309: 561}, + {47: 560, 50: 560, 256: 560, 289: 560, 304: 560, 560, 560, 309: 560}, + {47: 559, 50: 559, 256: 559, 289: 559, 304: 559, 559, 559, 309: 559}, + // 725 + {1290, 1290, 1290, 1290, 1290, 1290, 1290, 9: 1290, 26: 1290, 46: 1290, 218: 1290, 220: 1290, 1290, 227: 1290, 230: 1290, 370: 1290, 1290, 1290, 1290, 1290, 1290}, + {1289, 1289, 1289, 1289, 1289, 1289, 1289, 9: 1289, 26: 1289, 46: 1289, 218: 1289, 220: 1289, 1289, 227: 1289, 230: 1289, 370: 1289, 1289, 1289, 1289, 1289, 1289}, + {1288, 1288, 1288, 1288, 1288, 1288, 1288, 9: 1288, 26: 1288, 46: 1288, 218: 1288, 220: 1288, 1288, 227: 1288, 230: 1288, 370: 1288, 1288, 1288, 1288, 1288, 1288}, + {9: 562}, + {9: 558}, + // 730 + {9: 557}, + {26: 2204}, + {26: 2202}, + {26: 2200}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2207}, + // 735 + {324: 2206}, + {47: 2166, 50: 2168, 256: 2156, 304: 2158, 2157, 2170, 309: 2171, 530: 2169, 601: 2173, 718: 2172}, + {26: 2204, 46: 2205}, + {26: 2202, 46: 2203}, + {26: 2200, 46: 2201}, + // 740 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2176}, + {235: 2174}, + {9: 550, 235: 550}, + {47: 2166, 50: 2168, 256: 2156, 304: 2158, 2157, 2170, 309: 2171, 530: 2169, 601: 2173, 718: 2175}, + {9: 551}, + // 745 + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 235: 2110, 2108, 2109, 2107, 2105, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 457: 2106, 2104, 522: 2197}, + {650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 218: 650, 650, 650, 650, 650, 650, 650, 650, 650, 228: 650, 650, 231: 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 250: 650, 650, 650, 650, 650, 257: 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 280: 650, 650, 650, 650, 650, 650, 650, 650, 289: 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, 650}, + {649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 218: 649, 649, 649, 649, 649, 649, 649, 649, 649, 228: 649, 649, 231: 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 250: 649, 649, 649, 649, 649, 257: 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 280: 649, 649, 649, 649, 649, 649, 649, 649, 289: 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649}, + {648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 218: 648, 648, 648, 648, 648, 648, 648, 648, 648, 228: 648, 648, 231: 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 250: 648, 648, 648, 648, 648, 257: 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 280: 648, 648, 648, 648, 648, 648, 648, 648, 289: 648, 648, 648, 648, 648, 648, 648, 648, 648, 648, 648}, + {647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 218: 647, 647, 647, 647, 647, 647, 647, 647, 647, 228: 647, 647, 231: 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 250: 647, 647, 647, 647, 647, 257: 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 280: 647, 647, 647, 647, 647, 647, 647, 647, 289: 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, 647}, + // 750 + {646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 218: 646, 646, 646, 646, 646, 646, 646, 646, 646, 228: 646, 646, 231: 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 250: 646, 646, 646, 646, 646, 257: 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 280: 646, 646, 646, 646, 646, 646, 646, 646, 289: 646, 646, 646, 646, 646, 646, 646, 646, 646, 646, 646}, + {645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 218: 645, 645, 645, 645, 645, 645, 645, 645, 645, 228: 645, 645, 231: 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 250: 645, 645, 645, 645, 645, 257: 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 280: 645, 645, 645, 645, 645, 645, 645, 645, 289: 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645}, + {644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 218: 644, 644, 644, 644, 644, 644, 644, 644, 644, 228: 644, 644, 231: 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 250: 644, 644, 644, 644, 644, 257: 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 280: 644, 644, 644, 644, 644, 644, 644, 644, 289: 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, 644}, + {643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 218: 643, 643, 643, 643, 643, 643, 643, 643, 643, 228: 643, 643, 231: 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 250: 643, 643, 643, 643, 643, 257: 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 280: 643, 643, 643, 643, 643, 643, 643, 643, 289: 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, 643}, + {642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 218: 642, 642, 642, 642, 642, 642, 642, 642, 642, 228: 642, 642, 231: 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 250: 642, 642, 642, 642, 642, 257: 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 280: 642, 642, 642, 642, 642, 642, 642, 642, 289: 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, 642}, + // 755 + {641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 218: 641, 641, 641, 641, 641, 641, 641, 641, 641, 228: 641, 641, 231: 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 250: 641, 641, 641, 641, 641, 257: 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 280: 641, 641, 641, 641, 641, 641, 641, 641, 289: 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, 641}, + {640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 218: 640, 640, 640, 640, 640, 640, 640, 640, 640, 228: 640, 640, 231: 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 250: 640, 640, 640, 640, 640, 257: 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 280: 640, 640, 640, 640, 640, 640, 640, 640, 289: 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640}, + {639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 218: 639, 639, 639, 639, 639, 639, 639, 639, 639, 228: 639, 639, 231: 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 250: 639, 639, 639, 639, 639, 257: 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 280: 639, 639, 639, 639, 639, 639, 639, 639, 289: 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639}, + {638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 218: 638, 638, 638, 638, 638, 638, 638, 638, 638, 228: 638, 638, 231: 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 250: 638, 638, 638, 638, 638, 257: 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 280: 638, 638, 638, 638, 638, 638, 638, 638, 289: 638, 638, 638, 638, 638, 638, 638, 638, 638, 638, 638}, + {637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 218: 637, 637, 637, 637, 637, 637, 637, 637, 637, 228: 637, 637, 231: 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 250: 637, 637, 637, 637, 637, 257: 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 280: 637, 637, 637, 637, 637, 637, 637, 637, 289: 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637}, + // 760 + {636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 218: 636, 636, 636, 636, 636, 636, 636, 636, 636, 228: 636, 636, 231: 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 250: 636, 636, 636, 636, 636, 257: 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 280: 636, 636, 636, 636, 636, 636, 636, 636, 289: 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636}, + {635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 218: 635, 635, 635, 635, 635, 635, 635, 635, 635, 228: 635, 635, 231: 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 250: 635, 635, 635, 635, 635, 257: 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 280: 635, 635, 635, 635, 635, 635, 635, 635, 289: 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, 635}, + {634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 218: 634, 634, 634, 634, 634, 634, 634, 634, 634, 228: 634, 634, 231: 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 250: 634, 634, 634, 634, 634, 257: 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 280: 634, 634, 634, 634, 634, 634, 634, 634, 289: 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634}, + {633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 218: 633, 633, 633, 633, 633, 633, 633, 633, 633, 228: 633, 633, 231: 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 250: 633, 633, 633, 633, 633, 257: 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 280: 633, 633, 633, 633, 633, 633, 633, 633, 289: 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, 633}, + {632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 218: 632, 632, 632, 632, 632, 632, 632, 632, 632, 228: 632, 632, 231: 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 250: 632, 632, 632, 632, 632, 257: 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 280: 632, 632, 632, 632, 632, 632, 632, 632, 289: 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, 632}, + // 765 + {631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 218: 631, 631, 631, 631, 631, 631, 631, 631, 631, 228: 631, 631, 231: 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 250: 631, 631, 631, 631, 631, 257: 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 280: 631, 631, 631, 631, 631, 631, 631, 631, 289: 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631}, + {26: 2198, 46: 2199}, + {9: 553, 235: 553}, + {9: 546, 235: 546}, + {9: 554, 235: 554}, + // 770 + {9: 547, 235: 547}, + {9: 555, 235: 555}, + {9: 548, 235: 548}, + {9: 556, 235: 556}, + {9: 549, 235: 549}, + // 775 + {9: 552, 235: 552}, + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 235: 2110, 2108, 2109, 2107, 2105, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 457: 2106, 2104, 522: 2208}, + {26: 2198}, + {571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 218: 571, 571, 571, 571, 571, 571, 571, 571, 571, 228: 571, 571, 231: 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 257: 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 280: 571, 571, 571, 571, 571, 571, 571, 571, 289: 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 363: 571}, + {782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 218: 782, 782, 782, 782, 782, 782, 782, 782, 782, 228: 782, 782, 231: 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 2114, 782, 782, 782, 782, 782, 257: 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 280: 782, 782, 782, 782, 782, 782, 782, 782, 289: 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 782, 363: 782}, + // 780 + {792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 218: 792, 792, 792, 792, 792, 792, 792, 792, 792, 228: 792, 792, 231: 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 257: 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 280: 792, 792, 792, 792, 792, 792, 792, 792, 289: 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, 363: 792}, + {1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 218: 1175, 1175, 221: 1175, 1175, 1175, 228: 1175, 1175, 231: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 244: 1175, 1175, 1175, 1175, 1175, 250: 1175, 1175, 1175, 1175, 1175, 259: 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 278: 1175, 457: 2106, 2104}, + {1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 218: 1176, 1176, 221: 1176, 1176, 1176, 228: 1176, 1176, 231: 1176, 1176, 1176, 1176, 2110, 1176, 2109, 1176, 1176, 1176, 1176, 1176, 244: 1176, 1176, 1176, 1176, 1176, 250: 1176, 1176, 1176, 1176, 1176, 259: 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 278: 1176, 457: 2106, 2104}, + {1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 218: 1177, 1177, 221: 1177, 1177, 1177, 228: 1177, 1177, 231: 1177, 1177, 1177, 1177, 2110, 1177, 2109, 1177, 2105, 1177, 1177, 1177, 244: 1177, 1177, 1177, 1177, 1177, 250: 1177, 1177, 1177, 1177, 1177, 259: 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 278: 1177, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2216}, + // 785 + {9: 2217, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {42: 2122, 377: 2123, 463: 524, 550: 2218}, + {463: 2126, 467: 2219}, + {531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 218: 531, 531, 531, 531, 531, 531, 531, 531, 531, 228: 531, 531, 231: 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 257: 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 280: 531, 531, 531, 531, 531, 531, 531, 531, 289: 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 363: 531}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2221}, + // 790 + {9: 2222, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {42: 2122, 377: 2123, 463: 524, 550: 2223}, + {463: 2126, 467: 2224}, + {532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 218: 532, 532, 532, 532, 532, 532, 532, 532, 532, 228: 532, 532, 231: 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 257: 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 280: 532, 532, 532, 532, 532, 532, 532, 532, 289: 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 532, 363: 532}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2226}, + // 795 + {6: 2228, 9: 529, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104, 673: 2227}, + {9: 2235}, + {256: 2156, 304: 2158, 2157, 2230, 530: 2229}, + {6: 2232, 9: 526, 674: 2234}, + {6: 2232, 9: 526, 674: 2231}, + // 800 + {9: 527}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2233}, + {9: 525, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {9: 528}, + {42: 2122, 377: 2123, 463: 524, 550: 2236}, + // 805 + {463: 2126, 467: 2237}, + {533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 218: 533, 533, 533, 533, 533, 533, 533, 533, 533, 228: 533, 533, 231: 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 257: 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 280: 533, 533, 533, 533, 533, 533, 533, 533, 289: 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 363: 533}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2239}, + {6: 2228, 9: 529, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104, 673: 2240}, + {9: 2241}, + // 810 + {42: 2122, 377: 2123, 463: 524, 550: 2242}, + {463: 2126, 467: 2243}, + {534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 218: 534, 534, 534, 534, 534, 534, 534, 534, 534, 228: 534, 534, 231: 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 257: 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 280: 534, 534, 534, 534, 534, 534, 534, 534, 289: 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 363: 534}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2245, 2024, 2099, 2023, 2020}, + {9: 2246, 249: 2114, 363: 2115}, + // 815 + {463: 2126, 467: 2247}, + {535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 218: 535, 535, 535, 535, 535, 535, 535, 535, 535, 228: 535, 535, 231: 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 257: 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 280: 535, 535, 535, 535, 535, 535, 535, 535, 289: 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 535, 363: 535}, + {9: 2249}, + {463: 2126, 467: 2250}, + {536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 218: 536, 536, 536, 536, 536, 536, 536, 536, 536, 228: 536, 536, 231: 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 257: 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 280: 536, 536, 536, 536, 536, 536, 536, 536, 289: 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 536, 363: 536}, + // 820 + {9: 2252}, + {463: 2126, 467: 2253}, + {537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 218: 537, 537, 537, 537, 537, 537, 537, 537, 537, 228: 537, 537, 231: 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 257: 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 280: 537, 537, 537, 537, 537, 537, 537, 537, 289: 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 537, 363: 537}, + {9: 2255}, + {463: 2126, 467: 2256}, + // 825 + {538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 218: 538, 538, 538, 538, 538, 538, 538, 538, 538, 228: 538, 538, 231: 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 257: 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 280: 538, 538, 538, 538, 538, 538, 538, 538, 289: 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 363: 538}, + {9: 2258}, + {463: 2126, 467: 2259}, + {539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 218: 539, 539, 539, 539, 539, 539, 539, 539, 539, 228: 539, 539, 231: 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 257: 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 280: 539, 539, 539, 539, 539, 539, 539, 539, 289: 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 539, 363: 539}, + {9: 2261}, + // 830 + {463: 2126, 467: 2262}, + {540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 218: 540, 540, 540, 540, 540, 540, 540, 540, 540, 228: 540, 540, 231: 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 257: 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 280: 540, 540, 540, 540, 540, 540, 540, 540, 289: 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 363: 540}, + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2270}, + {2: 766, 766, 766, 766, 7: 766, 766, 10: 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 219: 766, 766, 222: 766, 766, 766, 766, 766, 766, 230: 766, 244: 766, 255: 766, 766, 258: 766, 279: 766, 288: 766, 300: 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 766, 364: 766, 766, 766, 766, 766, 766, 381: 766, 465: 766, 480: 766, 482: 766, 766, 766}, + {2: 765, 765, 765, 765, 7: 765, 765, 10: 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 219: 765, 765, 222: 765, 765, 765, 765, 765, 765, 230: 765, 244: 765, 255: 765, 765, 258: 765, 279: 765, 288: 765, 300: 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 765, 364: 765, 765, 765, 765, 765, 765, 381: 765, 465: 765, 480: 765, 482: 765, 765, 765}, + // 835 + {2: 764, 764, 764, 764, 7: 764, 764, 10: 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 219: 764, 764, 222: 764, 764, 764, 764, 764, 764, 230: 764, 244: 764, 255: 764, 764, 258: 764, 279: 764, 288: 764, 300: 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 764, 364: 764, 764, 764, 764, 764, 764, 381: 764, 480: 764, 482: 764, 764, 764}, + {2: 763, 763, 763, 763, 7: 763, 763, 10: 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 219: 763, 763, 222: 763, 763, 763, 763, 763, 763, 230: 763, 255: 763, 763, 279: 763, 288: 763, 300: 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 364: 763, 763, 763, 763, 763, 763, 465: 2275}, + {2: 761, 761, 761, 761, 7: 761, 761, 10: 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 219: 761, 761, 222: 761, 761, 761, 761, 761, 761, 230: 761, 244: 761, 255: 761, 761, 258: 761, 279: 761, 288: 761, 300: 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 364: 761, 761, 761, 761, 761, 761, 480: 761, 482: 761, 761, 761}, + {2: 758, 758, 758, 758, 7: 758, 758, 10: 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 219: 758, 758, 222: 758, 758, 758, 758, 758, 758, 230: 758, 255: 758, 758, 279: 758, 288: 758, 300: 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 758, 364: 758, 758, 758, 758, 758, 758}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2271}, + // 840 + {9: 2272, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2273}, + {657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 218: 657, 657, 657, 657, 657, 657, 657, 657, 657, 228: 657, 657, 231: 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 257: 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 280: 657, 657, 657, 657, 657, 657, 657, 657, 289: 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 363: 657}, + {544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 218: 544, 544, 544, 544, 544, 544, 544, 544, 544, 228: 544, 544, 231: 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 257: 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 280: 544, 544, 544, 544, 544, 544, 544, 544, 289: 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 363: 544}, + {2: 757, 757, 757, 757, 7: 757, 757, 10: 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 219: 757, 757, 222: 757, 757, 757, 757, 757, 757, 230: 757, 255: 757, 757, 279: 757, 288: 757, 300: 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 757, 364: 757, 757, 757, 757, 757, 757}, + // 845 + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2277}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2278}, + {9: 2279, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2280}, + {658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 218: 658, 658, 658, 658, 658, 658, 658, 658, 658, 228: 658, 658, 231: 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 257: 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 280: 658, 658, 658, 658, 658, 658, 658, 658, 289: 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 363: 658}, + // 850 + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2282}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2283}, + {9: 2284, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2285}, + {659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 218: 659, 659, 659, 659, 659, 659, 659, 659, 659, 228: 659, 659, 231: 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 257: 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 280: 659, 659, 659, 659, 659, 659, 659, 659, 289: 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 659, 363: 659}, + // 855 + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2287}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2288}, + {9: 2289, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2290}, + {660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 218: 660, 660, 660, 660, 660, 660, 660, 660, 660, 228: 660, 660, 231: 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 257: 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 280: 660, 660, 660, 660, 660, 660, 660, 660, 289: 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 363: 660}, + // 860 + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2292}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2293}, + {9: 2294, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2295}, + {661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 218: 661, 661, 661, 661, 661, 661, 661, 661, 661, 228: 661, 661, 231: 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 257: 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 280: 661, 661, 661, 661, 661, 661, 661, 661, 289: 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 661, 363: 661}, + // 865 + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2297}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2299}, + {1163, 1163, 6: 1163, 9: 1163, 23: 1163, 234: 1163, 2110, 2108, 2109, 2107, 2105, 242: 1163, 457: 2106, 2104}, + {6: 2300, 9: 817, 23: 817, 234: 2301, 498: 2302, 2303}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2310}, + // 870 + {390: 2308}, + {816, 816, 9: 816, 23: 816, 218: 816, 228: 816, 816, 231: 816, 816, 816}, + {9: 656, 23: 2305, 795: 2304}, + {9: 2307}, + {219: 2306}, + // 875 + {9: 655}, + {662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 218: 662, 662, 662, 662, 662, 662, 662, 662, 662, 228: 662, 662, 231: 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 257: 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 280: 662, 662, 662, 662, 662, 662, 662, 662, 289: 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, 363: 662}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2139, 539: 2140, 556: 2309}, + {824, 824, 6: 2142, 9: 824, 23: 824, 218: 824, 228: 824, 824, 231: 824, 824, 824}, + {1162, 1162, 6: 1162, 9: 1162, 23: 1162, 234: 1162, 2110, 2108, 2109, 2107, 2105, 242: 1162, 457: 2106, 2104}, + // 880 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 258: 2315, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2312, 465: 2314, 492: 2264, 2265, 495: 2313}, + {9: 2323, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2321}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2318}, + {9: 2316}, + // 885 + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2317}, + {663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 218: 663, 663, 663, 663, 663, 663, 663, 663, 663, 228: 663, 663, 231: 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 257: 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 280: 663, 663, 663, 663, 663, 663, 663, 663, 289: 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 363: 663}, + {9: 2319, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2320}, + {665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 218: 665, 665, 665, 665, 665, 665, 665, 665, 665, 228: 665, 665, 231: 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 257: 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 280: 665, 665, 665, 665, 665, 665, 665, 665, 289: 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 363: 665}, + // 890 + {6: 2300, 9: 2322}, + {666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 218: 666, 666, 666, 666, 666, 666, 666, 666, 666, 228: 666, 666, 231: 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 257: 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 280: 666, 666, 666, 666, 666, 666, 666, 666, 289: 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 363: 666}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2324}, + {664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 218: 664, 664, 664, 664, 664, 664, 664, 664, 664, 228: 664, 664, 231: 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 257: 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 280: 664, 664, 664, 664, 664, 664, 664, 664, 289: 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, 363: 664}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2326, 465: 2327}, + // 895 + {9: 2331, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2328}, + {9: 2329, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2330}, + {667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 218: 667, 667, 667, 667, 667, 667, 667, 667, 667, 228: 667, 667, 231: 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 257: 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 280: 667, 667, 667, 667, 667, 667, 667, 667, 289: 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, 363: 667}, + // 900 + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2332}, + {668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 218: 668, 668, 668, 668, 668, 668, 668, 668, 668, 228: 668, 668, 231: 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 257: 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 280: 668, 668, 668, 668, 668, 668, 668, 668, 289: 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 668, 363: 668}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2334, 465: 2335}, + {9: 2339, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2336}, + // 905 + {9: 2337, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2338}, + {669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 218: 669, 669, 669, 669, 669, 669, 669, 669, 669, 228: 669, 669, 231: 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 257: 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 280: 669, 669, 669, 669, 669, 669, 669, 669, 289: 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 363: 669}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2340}, + {670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 218: 670, 670, 670, 670, 670, 670, 670, 670, 670, 228: 670, 670, 231: 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 257: 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 280: 670, 670, 670, 670, 670, 670, 670, 670, 289: 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, 363: 670}, + // 910 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2342, 465: 2343}, + {9: 2347, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2344}, + {9: 2345, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2346}, + // 915 + {671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 218: 671, 671, 671, 671, 671, 671, 671, 671, 671, 228: 671, 671, 231: 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 257: 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 280: 671, 671, 671, 671, 671, 671, 671, 671, 289: 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, 363: 671}, + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2348}, + {672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 218: 672, 672, 672, 672, 672, 672, 672, 672, 672, 228: 672, 672, 231: 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 257: 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 280: 672, 672, 672, 672, 672, 672, 672, 672, 289: 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 672, 363: 672}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2350, 730: 2352, 774: 2353, 835: 2354, 2351}, + {9: 2362, 235: 2110, 2108, 2109, 2107, 2105, 241: 2363, 457: 2106, 2104}, + // 920 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 241: 2356, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2355}, + {2: 676, 676, 676, 676, 7: 676, 676, 10: 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 219: 676, 676, 222: 676, 676, 676, 676, 676, 676, 230: 676, 241: 676, 255: 676, 676, 279: 676, 288: 676, 300: 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 364: 676, 676, 676, 676, 676, 676}, + {2: 675, 675, 675, 675, 7: 675, 675, 10: 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 219: 675, 675, 222: 675, 675, 675, 675, 675, 675, 230: 675, 241: 675, 255: 675, 675, 279: 675, 288: 675, 300: 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 364: 675, 675, 675, 675, 675, 675}, + {2: 674, 674, 674, 674, 7: 674, 674, 10: 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 219: 674, 674, 222: 674, 674, 674, 674, 674, 674, 230: 674, 241: 674, 255: 674, 674, 279: 674, 288: 674, 300: 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 674, 364: 674, 674, 674, 674, 674, 674}, + {235: 2110, 2108, 2109, 2107, 2105, 241: 2359, 457: 2106, 2104}, + // 925 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2357}, + {9: 2358, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 218: 686, 686, 686, 686, 686, 686, 686, 686, 686, 228: 686, 686, 231: 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 257: 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 280: 686, 686, 686, 686, 686, 686, 686, 686, 289: 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, 363: 686}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2360}, + {9: 2361, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 930 + {685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 218: 685, 685, 685, 685, 685, 685, 685, 685, 685, 228: 685, 685, 231: 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 257: 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 280: 685, 685, 685, 685, 685, 685, 685, 685, 289: 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 685, 363: 685}, + {688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 218: 688, 688, 688, 688, 688, 688, 688, 688, 688, 228: 688, 688, 231: 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 257: 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 280: 688, 688, 688, 688, 688, 688, 688, 688, 289: 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 688, 363: 688}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2364}, + {9: 2365, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 218: 687, 687, 687, 687, 687, 687, 687, 687, 687, 228: 687, 687, 231: 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 257: 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 280: 687, 687, 687, 687, 687, 687, 687, 687, 289: 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 687, 363: 687}, + // 935 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2367}, + {6: 2368, 235: 2110, 2108, 2109, 2107, 2105, 241: 2369, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2375}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2370}, + {9: 2371, 232: 2372, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 940 + {693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 218: 693, 693, 693, 693, 693, 693, 693, 693, 693, 228: 693, 693, 231: 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 257: 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 280: 693, 693, 693, 693, 693, 693, 693, 693, 289: 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 693, 363: 693}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2373}, + {9: 2374, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 218: 691, 691, 691, 691, 691, 691, 691, 691, 691, 228: 691, 691, 231: 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 257: 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 280: 691, 691, 691, 691, 691, 691, 691, 691, 289: 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 691, 363: 691}, + {6: 2377, 9: 2376, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 945 + {694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 218: 694, 694, 694, 694, 694, 694, 694, 694, 694, 228: 694, 694, 231: 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 257: 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 280: 694, 694, 694, 694, 694, 694, 694, 694, 289: 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 694, 363: 694}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2378}, + {9: 2379, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 218: 692, 692, 692, 692, 692, 692, 692, 692, 692, 228: 692, 692, 231: 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 257: 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 280: 692, 692, 692, 692, 692, 692, 692, 692, 289: 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 692, 363: 692}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2381}, + // 950 + {224: 2386, 2387, 2392, 258: 2388, 277: 2394, 290: 2390, 2383, 2389, 2393, 2382, 2391, 2384, 2385}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2414}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2413}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2412}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2411}, + // 955 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2408, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2407}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2404, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2403}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2402}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2401}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2400}, + // 960 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2399}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2398}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2397}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2395}, + {9: 2396, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 965 + {695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 218: 695, 695, 695, 695, 695, 695, 695, 695, 695, 228: 695, 695, 231: 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 257: 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 280: 695, 695, 695, 695, 695, 695, 695, 695, 289: 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 695, 363: 695}, + {802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 218: 802, 802, 802, 802, 802, 802, 802, 802, 802, 228: 802, 802, 231: 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 250: 802, 802, 802, 802, 802, 257: 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 280: 802, 802, 802, 802, 802, 802, 802, 802, 289: 802, 802, 802, 802, 802, 802, 802, 802, 802, 802, 802}, + {803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 218: 803, 803, 803, 803, 803, 803, 803, 803, 803, 228: 803, 803, 231: 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 250: 803, 803, 803, 803, 803, 257: 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 803, 280: 803, 803, 803, 803, 803, 803, 803, 803, 289: 803, 803, 803, 803, 2393, 803, 803, 803, 803, 803, 803}, + {804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 218: 804, 804, 804, 804, 804, 804, 804, 804, 804, 228: 804, 804, 231: 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 250: 804, 804, 804, 804, 804, 257: 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 804, 280: 804, 804, 804, 804, 804, 804, 804, 804, 289: 804, 804, 804, 804, 2393, 804, 804, 804, 804, 804, 804}, + {805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 218: 805, 805, 805, 805, 805, 805, 805, 805, 805, 228: 805, 805, 231: 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 250: 805, 805, 805, 805, 805, 257: 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 280: 805, 805, 805, 805, 805, 805, 805, 805, 289: 805, 805, 805, 805, 2393, 805, 805, 805, 805, 805, 805}, + // 970 + {806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 218: 806, 806, 806, 806, 806, 806, 806, 806, 806, 228: 806, 806, 231: 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 250: 806, 806, 806, 806, 806, 257: 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 806, 280: 806, 806, 806, 806, 806, 806, 806, 806, 289: 806, 806, 806, 806, 2393, 806, 806, 806, 806, 806, 806}, + {807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 218: 807, 807, 807, 807, 807, 807, 807, 807, 807, 228: 807, 807, 231: 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 250: 807, 807, 807, 807, 807, 257: 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 807, 280: 807, 807, 807, 807, 807, 807, 807, 807, 289: 807, 807, 807, 807, 2393, 807, 807, 807, 807, 807, 807}, + {810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 218: 810, 810, 810, 810, 810, 810, 810, 810, 2392, 228: 810, 810, 231: 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 250: 810, 810, 810, 810, 810, 257: 810, 2388, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, 280: 810, 810, 810, 810, 810, 810, 810, 810, 289: 810, 2390, 810, 2389, 2393, 810, 2391, 810, 810, 810, 810}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2405}, + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 235: 2110, 2108, 2109, 2107, 2105, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 457: 2106, 2104, 522: 2406}, + // 975 + {808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 218: 808, 808, 808, 808, 808, 808, 808, 808, 808, 228: 808, 808, 231: 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 250: 808, 808, 808, 808, 808, 257: 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 280: 808, 808, 808, 808, 808, 808, 808, 808, 289: 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, 808}, + {811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 218: 811, 811, 811, 811, 811, 811, 811, 811, 2392, 228: 811, 811, 231: 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 250: 811, 811, 811, 811, 811, 257: 811, 2388, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 811, 280: 811, 811, 811, 811, 811, 811, 811, 811, 289: 811, 2390, 811, 2389, 2393, 811, 2391, 811, 811, 811, 811}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2409}, + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 235: 2110, 2108, 2109, 2107, 2105, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 457: 2106, 2104, 522: 2410}, + {809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 218: 809, 809, 809, 809, 809, 809, 809, 809, 809, 228: 809, 809, 231: 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 250: 809, 809, 809, 809, 809, 257: 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 280: 809, 809, 809, 809, 809, 809, 809, 809, 289: 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, 809}, + // 980 + {812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 218: 812, 812, 812, 812, 812, 812, 2386, 2387, 2392, 228: 812, 812, 231: 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 250: 812, 812, 812, 812, 812, 257: 812, 2388, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 812, 280: 812, 812, 812, 812, 812, 812, 812, 812, 289: 812, 2390, 812, 2389, 2393, 812, 2391, 812, 812, 812, 812}, + {813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 218: 813, 813, 813, 813, 813, 813, 2386, 2387, 2392, 228: 813, 813, 231: 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 250: 813, 813, 813, 813, 813, 257: 813, 2388, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 280: 813, 813, 813, 813, 813, 813, 813, 813, 289: 813, 2390, 813, 2389, 2393, 813, 2391, 813, 813, 813, 813}, + {814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 218: 814, 814, 814, 814, 814, 814, 2386, 2387, 2392, 228: 814, 814, 231: 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 250: 814, 814, 814, 814, 814, 257: 814, 2388, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, 280: 814, 814, 814, 814, 814, 814, 814, 814, 289: 814, 2390, 814, 2389, 2393, 814, 2391, 2384, 2385, 814, 814}, + {815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 218: 815, 815, 815, 815, 815, 815, 2386, 2387, 2392, 228: 815, 815, 231: 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 250: 815, 815, 815, 815, 815, 257: 815, 2388, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 815, 280: 815, 815, 815, 815, 815, 815, 815, 815, 289: 815, 2390, 2383, 2389, 2393, 815, 2391, 2384, 2385, 815, 815}, + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 522: 2416}, + // 985 + {241: 2417}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2418}, + {9: 2419, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 218: 697, 697, 697, 697, 697, 697, 697, 697, 697, 228: 697, 697, 231: 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 257: 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 280: 697, 697, 697, 697, 697, 697, 697, 697, 289: 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 697, 363: 697}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2421}, + // 990 + {6: 2422, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {309: 2423}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2424}, + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 235: 2110, 2108, 2109, 2107, 2105, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 457: 2106, 2104, 522: 2425}, + {9: 2426}, + // 995 + {698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 218: 698, 698, 698, 698, 698, 698, 698, 698, 698, 228: 698, 698, 231: 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 257: 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 280: 698, 698, 698, 698, 698, 698, 698, 698, 289: 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 698, 363: 698}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2428}, + {6: 2429, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2431, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2430}, + {9: 2435, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 1000 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2432}, + {28: 2185, 30: 2181, 2180, 2177, 2179, 2183, 2184, 2178, 2182, 235: 2110, 2108, 2109, 2107, 2105, 264: 2195, 2192, 2194, 2193, 2189, 2191, 2190, 2187, 2188, 2186, 275: 2196, 457: 2106, 2104, 522: 2433}, + {9: 2434}, + {699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 218: 699, 699, 699, 699, 699, 699, 699, 699, 699, 228: 699, 699, 231: 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 257: 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 280: 699, 699, 699, 699, 699, 699, 699, 699, 289: 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, 363: 699}, + {700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 218: 700, 700, 700, 700, 700, 700, 700, 700, 700, 228: 700, 700, 231: 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 257: 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 280: 700, 700, 700, 700, 700, 700, 700, 700, 289: 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 363: 700}, + // 1005 + {9: 1157, 256: 2438, 643: 2437, 2439}, + {9: 1156}, + {9: 1155}, + {9: 2440}, + {701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 218: 701, 701, 701, 701, 701, 701, 701, 701, 701, 228: 701, 701, 231: 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 257: 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 280: 701, 701, 701, 701, 701, 701, 701, 701, 289: 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 701, 363: 701}, + // 1010 + {9: 1157, 256: 2438, 643: 2437, 2442}, + {9: 2443}, + {702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 218: 702, 702, 702, 702, 702, 702, 702, 702, 702, 228: 702, 702, 231: 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 257: 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 280: 702, 702, 702, 702, 702, 702, 702, 702, 289: 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 363: 702}, + {219: 839}, + {219: 838}, + // 1015 + {219: 837}, + {219: 2448}, + {254: 2449}, + {703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 218: 703, 703, 703, 703, 703, 703, 703, 703, 703, 228: 703, 703, 231: 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 257: 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 280: 703, 703, 703, 703, 703, 703, 703, 703, 289: 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, 363: 703}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2451}, + // 1020 + {6: 2452, 224: 2386, 2387, 2392, 258: 2388, 290: 2390, 2383, 2389, 2393, 2382, 2391, 2384, 2385}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2453}, + {9: 2454, 224: 2386, 2387, 2392, 258: 2388, 290: 2390, 2383, 2389, 2393, 2382, 2391, 2384, 2385}, + {705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 218: 705, 705, 705, 705, 705, 705, 705, 705, 705, 228: 705, 705, 231: 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 257: 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 280: 705, 705, 705, 705, 705, 705, 705, 705, 289: 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 705, 363: 705}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 1159, 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2456, 544: 2457}, + // 1025 + {6: 2300, 9: 1158}, + {9: 2458}, + {706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 218: 706, 706, 706, 706, 706, 706, 706, 706, 706, 228: 706, 706, 231: 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 257: 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 280: 706, 706, 706, 706, 706, 706, 706, 706, 289: 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 706, 363: 706}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2460}, + {6: 2300, 9: 2461, 242: 2462}, + // 1030 + {711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 218: 711, 711, 711, 711, 711, 711, 711, 711, 711, 228: 711, 711, 231: 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 257: 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 280: 711, 711, 711, 711, 711, 711, 711, 711, 289: 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 711, 363: 711}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 2463}, + {9: 2464}, + {710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 218: 710, 710, 710, 710, 710, 710, 710, 710, 710, 228: 710, 710, 231: 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 257: 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 280: 710, 710, 710, 710, 710, 710, 710, 710, 289: 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 710, 363: 710}, + {712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 218: 712, 712, 712, 712, 712, 712, 712, 712, 712, 228: 712, 712, 231: 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 257: 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 280: 712, 712, 712, 712, 712, 712, 712, 712, 289: 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 363: 712}, + // 1035 + {9: 2467, 256: 2468}, + {652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 218: 652, 652, 652, 652, 652, 652, 652, 652, 652, 228: 652, 652, 231: 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 257: 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 280: 652, 652, 652, 652, 652, 652, 652, 652, 289: 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 652, 363: 652}, + {9: 2469}, + {651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 218: 651, 651, 651, 651, 651, 651, 651, 651, 651, 228: 651, 651, 231: 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 257: 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 280: 651, 651, 651, 651, 651, 651, 651, 651, 289: 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 651, 363: 651}, + {9: 2471}, + // 1040 + {713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 218: 713, 713, 713, 713, 713, 713, 713, 713, 713, 228: 713, 713, 231: 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 257: 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 280: 713, 713, 713, 713, 713, 713, 713, 713, 289: 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 713, 363: 713}, + {714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 218: 714, 714, 714, 714, 714, 714, 714, 714, 714, 228: 714, 714, 231: 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 257: 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 280: 714, 714, 714, 714, 714, 714, 714, 714, 289: 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 714, 363: 714}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 1159, 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2456, 544: 2474}, + {9: 2475}, + {715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 218: 715, 715, 715, 715, 715, 715, 715, 715, 715, 228: 715, 715, 231: 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 257: 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 280: 715, 715, 715, 715, 715, 715, 715, 715, 289: 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 715, 363: 715}, + // 1045 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 1159, 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2456, 544: 2477}, + {9: 2478}, + {716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 218: 716, 716, 716, 716, 716, 716, 716, 716, 716, 228: 716, 716, 231: 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 257: 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 280: 716, 716, 716, 716, 716, 716, 716, 716, 289: 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 363: 716}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 279: 2015, 376: 2014, 378: 1537, 1538, 1536, 438: 2480}, + {9: 2481}, + // 1050 + {769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 218: 769, 769, 769, 769, 769, 769, 769, 769, 769, 228: 769, 769, 231: 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 257: 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 280: 769, 769, 769, 769, 769, 769, 769, 769, 289: 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 769, 363: 769}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 279: 2015, 376: 2014, 378: 1537, 1538, 1536, 438: 2483}, + {9: 2484}, + {770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 218: 770, 770, 770, 770, 770, 770, 770, 770, 770, 228: 770, 770, 231: 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 257: 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 280: 770, 770, 770, 770, 770, 770, 770, 770, 289: 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 770, 363: 770}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2486}, + // 1055 + {6: 2487, 235: 2110, 2108, 2109, 2107, 2105, 242: 2488, 457: 2106, 2104}, + {13: 2498, 56: 2495, 2494, 61: 2497, 66: 2500, 288: 2492, 308: 2493, 403: 2496, 460: 2499, 610: 2491}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 2489}, + {9: 2490}, + {771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 218: 771, 771, 771, 771, 771, 771, 771, 771, 771, 228: 771, 771, 231: 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 257: 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 280: 771, 771, 771, 771, 771, 771, 771, 771, 289: 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, 363: 771}, + // 1060 + {9: 2534}, + {9: 134, 217: 2506, 473: 2507, 487: 2533}, + {7: 134, 9: 134, 217: 2506, 288: 134, 382: 134, 473: 2507, 487: 2520}, + {9: 612}, + {9: 134, 217: 2506, 473: 2507, 487: 2519}, + // 1065 + {9: 127, 217: 2512, 473: 2513, 577: 2511, 589: 2514}, + {9: 134, 217: 2506, 473: 2507, 487: 2505}, + {9: 175, 404: 2502, 2503, 671: 2504}, + {9: 175, 404: 2502, 2503, 671: 2501}, + {9: 606}, + // 1070 + {9: 607}, + {9: 174}, + {9: 173}, + {9: 608}, + {9: 609}, + // 1075 + {256: 1526, 461: 2508, 476: 2509}, + {133, 133, 133, 133, 133, 133, 133, 133, 9: 133, 13: 133, 218: 133, 220: 133, 133, 227: 133, 230: 133, 249: 133, 262: 133, 133, 288: 133, 370: 133, 133, 133, 133, 133, 133, 382: 133, 460: 133, 462: 133}, + {1180, 1180, 1180, 1180, 6: 1180, 1180, 1180, 1180, 1180, 1180, 1180, 14: 1180, 1180, 1180, 1180, 1180, 1180, 1180, 1180, 53: 1180, 217: 1180, 1180, 221: 1180, 227: 1180, 1180, 1180, 231: 1180, 1180, 242: 1180, 249: 1180, 255: 1180, 377: 1180, 381: 1180, 1180, 1180, 1180, 1180}, + {9: 2510}, + {135, 135, 135, 135, 135, 135, 135, 135, 9: 135, 13: 135, 218: 135, 220: 135, 135, 227: 135, 230: 135, 249: 135, 262: 135, 135, 288: 135, 370: 135, 135, 135, 135, 135, 135, 382: 135, 460: 135, 462: 135}, + // 1080 + {9: 610}, + {256: 1526, 461: 2508, 476: 2515}, + {126, 126, 126, 126, 126, 126, 126, 9: 126, 13: 126, 218: 126, 220: 126, 126, 227: 126, 230: 126, 370: 126, 126, 126, 126, 126, 126, 460: 126, 462: 126}, + {125, 125, 125, 125, 125, 125, 125, 9: 125, 13: 125, 218: 125, 220: 125, 125, 227: 125, 230: 125, 370: 125, 125, 125, 125, 125, 125, 460: 125, 462: 125}, + {6: 2516, 9: 2510}, + // 1085 + {256: 1526, 461: 2508, 476: 2517}, + {9: 2518}, + {124, 124, 124, 124, 124, 124, 124, 9: 124, 13: 124, 218: 124, 220: 124, 124, 227: 124, 230: 124, 370: 124, 124, 124, 124, 124, 124, 460: 124, 462: 124}, + {9: 611}, + {7: 2525, 9: 121, 288: 2522, 382: 2524, 481: 2523, 531: 2521}, + // 1090 + {9: 613}, + {118, 118, 118, 118, 118, 118, 118, 2525, 9: 118, 218: 118, 220: 118, 118, 227: 118, 230: 118, 249: 118, 370: 118, 118, 118, 118, 118, 118, 382: 2524, 481: 2531, 588: 2530}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 2527}, + {246: 2526}, + {115, 115, 115, 115, 115, 115, 7: 115, 115, 10: 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 219: 115, 240: 115, 243: 115, 257: 115, 288: 115}, + // 1095 + {116, 116, 116, 116, 116, 116, 7: 116, 116, 10: 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 219: 116, 240: 116, 243: 116, 257: 116, 288: 116}, + {123, 123, 123, 123, 123, 123, 123, 9: 123, 218: 123, 220: 123, 123, 227: 123, 230: 123, 249: 123, 288: 2528, 370: 123, 123, 123, 123, 123, 123, 791: 2529}, + {122, 122, 122, 122, 122, 122, 122, 9: 122, 218: 122, 220: 122, 122, 227: 122, 230: 122, 249: 122, 370: 122, 122, 122, 122, 122, 122}, + {119, 119, 119, 119, 119, 119, 119, 9: 119, 218: 119, 220: 119, 119, 227: 119, 230: 119, 249: 119, 370: 119, 119, 119, 119, 119, 119}, + {120, 120, 120, 120, 120, 120, 120, 9: 120, 218: 120, 220: 120, 120, 227: 120, 230: 120, 249: 120, 370: 120, 120, 120, 120, 120, 120}, + // 1100 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 2532}, + {117, 117, 117, 117, 117, 117, 117, 9: 117, 218: 117, 220: 117, 117, 227: 117, 230: 117, 249: 117, 370: 117, 117, 117, 117, 117, 117}, + {9: 614}, + {772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 218: 772, 772, 772, 772, 772, 772, 772, 772, 772, 228: 772, 772, 231: 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 257: 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 280: 772, 772, 772, 772, 772, 772, 772, 772, 289: 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 772, 363: 772}, + {235: 2110, 2108, 2109, 2107, 2105, 274: 620, 457: 2106, 2104}, + // 1105 + {274: 2539, 716: 2538, 852: 2537}, + {48: 616, 274: 2539, 276: 2545, 716: 2544, 750: 2543}, + {48: 619, 274: 619, 276: 619}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2540}, + {235: 2110, 2108, 2109, 2107, 2105, 278: 2541, 457: 2106, 2104}, + // 1110 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2542}, + {48: 617, 235: 2110, 2108, 2109, 2107, 2105, 274: 617, 276: 617, 457: 2106, 2104}, + {48: 2547}, + {48: 618, 274: 618, 276: 618}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2546}, + // 1115 + {48: 615, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 218: 773, 773, 773, 773, 773, 773, 773, 773, 773, 228: 773, 773, 231: 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 257: 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 280: 773, 773, 773, 773, 773, 773, 773, 773, 289: 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 363: 773}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2549}, + {221: 2550, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {13: 2498, 56: 2495, 2494, 61: 2497, 66: 2500, 288: 2492, 308: 2493, 403: 2496, 460: 2499, 610: 2551}, + // 1120 + {9: 2552}, + {774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 218: 774, 774, 774, 774, 774, 774, 774, 774, 774, 228: 774, 774, 231: 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 257: 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 280: 774, 774, 774, 774, 774, 774, 774, 774, 289: 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, 363: 774}, + {775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 218: 775, 775, 775, 775, 775, 775, 775, 775, 775, 228: 775, 775, 231: 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 2114, 775, 775, 775, 775, 775, 257: 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 280: 775, 775, 775, 775, 775, 775, 775, 775, 289: 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 363: 775}, + {776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 218: 776, 776, 776, 776, 776, 776, 776, 776, 776, 228: 776, 776, 231: 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 257: 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 280: 776, 776, 776, 776, 776, 776, 776, 776, 289: 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 363: 776}, + {217: 2558, 381: 1457, 469: 2556, 1458, 1459, 1460, 475: 1463, 477: 1462, 2557}, + // 1125 + {9: 2562, 229: 431}, + {9: 2561}, + {381: 1457, 469: 2559, 1458, 1459, 1460}, + {9: 2560}, + {229: 430}, + // 1130 + {441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 218: 441, 441, 441, 441, 441, 441, 441, 441, 441, 228: 441, 441, 231: 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 257: 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 280: 441, 441, 441, 441, 441, 441, 441, 441, 289: 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 363: 441}, + {442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 218: 442, 442, 442, 442, 442, 442, 442, 442, 442, 228: 442, 442, 231: 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 257: 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 280: 442, 442, 442, 442, 442, 442, 442, 442, 289: 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 363: 442}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2564}, + {6: 2565}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2566}, + // 1135 + {6: 1162, 9: 2567, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 218: 777, 777, 777, 777, 777, 777, 777, 777, 777, 228: 777, 777, 231: 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 257: 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 280: 777, 777, 777, 777, 777, 777, 777, 777, 289: 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 363: 777}, + {6: 1163, 9: 2576, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {6: 2573}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2570, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 1457, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2568, 469: 2571, 1458, 1459, 1460, 475: 1463, 477: 1462, 2557, 488: 2569}, + // 1140 + {9: 2572, 229: 431}, + {442, 442, 6: 442, 9: 442, 220: 442, 224: 442, 442, 442, 229: 430, 235: 442, 442, 442, 442, 442, 243: 442, 249: 442, 257: 442, 442, 277: 442, 280: 442, 442, 442, 442, 442, 442, 442, 442, 289: 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 442, 363: 442}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2574}, + {6: 1162, 9: 2575, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 218: 778, 778, 778, 778, 778, 778, 778, 778, 778, 228: 778, 778, 231: 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 257: 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 280: 778, 778, 778, 778, 778, 778, 778, 778, 289: 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 778, 363: 778}, + // 1145 + {779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 218: 779, 779, 779, 779, 779, 779, 779, 779, 779, 228: 779, 779, 231: 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 257: 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 280: 779, 779, 779, 779, 779, 779, 779, 779, 289: 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 779, 363: 779}, + {781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 218: 781, 781, 781, 781, 781, 781, 781, 781, 781, 228: 781, 781, 231: 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 2114, 781, 781, 781, 781, 781, 257: 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 280: 781, 781, 781, 781, 781, 781, 781, 781, 289: 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 781, 363: 781}, + {783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 218: 783, 783, 783, 783, 783, 783, 783, 783, 783, 228: 783, 783, 231: 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 2114, 783, 783, 783, 783, 783, 257: 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 280: 783, 783, 783, 783, 783, 783, 783, 783, 289: 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, 363: 783}, + {784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 218: 784, 784, 784, 784, 784, 784, 784, 784, 784, 228: 784, 784, 231: 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 2114, 784, 784, 784, 784, 784, 257: 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 280: 784, 784, 784, 784, 784, 784, 784, 784, 289: 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 784, 363: 784}, + {785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 218: 785, 785, 785, 785, 785, 785, 785, 785, 785, 228: 785, 785, 231: 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 2114, 785, 785, 785, 785, 785, 257: 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 280: 785, 785, 785, 785, 785, 785, 785, 785, 289: 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 785, 363: 785}, + // 1150 + {786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 218: 786, 786, 786, 786, 786, 786, 786, 786, 786, 228: 786, 786, 231: 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 2114, 786, 786, 786, 786, 786, 257: 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 280: 786, 786, 786, 786, 786, 786, 786, 786, 289: 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 786, 363: 786}, + {219: 2585}, + {219: 2584}, + {767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 218: 767, 767, 767, 767, 767, 767, 767, 767, 767, 228: 767, 767, 231: 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 257: 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 280: 767, 767, 767, 767, 767, 767, 767, 767, 289: 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 767, 363: 767}, + {768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 218: 768, 768, 768, 768, 768, 768, 768, 768, 768, 228: 768, 768, 231: 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 257: 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 280: 768, 768, 768, 768, 768, 768, 768, 768, 289: 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 768, 363: 768}, + // 1155 + {279: 2587}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2588, 378: 1537, 1538, 1536}, + {798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 218: 798, 798, 798, 798, 798, 798, 798, 798, 798, 228: 798, 798, 231: 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 257: 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 280: 798, 798, 798, 798, 798, 798, 798, 798, 289: 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 798, 363: 798, 386: 798, 798}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2590, 378: 1537, 1538, 1536}, + {799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 218: 799, 799, 799, 799, 799, 799, 799, 799, 799, 228: 799, 799, 231: 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 257: 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 2591, 799, 799, 799, 799, 799, 799, 799, 799, 289: 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 363: 799, 386: 799, 799}, + // 1160 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2592, 378: 1537, 1538, 1536}, + {797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 218: 797, 797, 797, 797, 797, 797, 797, 797, 797, 228: 797, 797, 231: 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 257: 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 280: 797, 797, 797, 797, 797, 797, 797, 797, 289: 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 797, 363: 797, 386: 797, 797}, + {829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 218: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 257: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 280: 829, 829, 829, 829, 829, 829, 829, 829, 289: 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 363: 829, 370: 829, 829, 829, 829, 829, 829}, + {825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 218: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 257: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 280: 825, 825, 825, 825, 825, 825, 825, 825, 289: 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 363: 825, 370: 825, 825, 825, 825, 825, 825}, + {28: 2605, 30: 2601, 2600, 2597, 2599, 2603, 2604, 2598, 2602, 706: 2596}, + // 1165 + {6: 2606}, + {6: 630}, + {6: 629}, + {6: 628}, + {6: 627}, + // 1170 + {6: 626}, + {6: 625}, + {6: 624}, + {6: 623}, + {6: 622}, + // 1175 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2607}, + {6: 2608, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2609}, + {9: 2610, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 218: 689, 689, 689, 689, 689, 689, 689, 689, 689, 228: 689, 689, 231: 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 257: 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 280: 689, 689, 689, 689, 689, 689, 689, 689, 289: 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 689, 363: 689}, + // 1180 + {28: 2605, 30: 2601, 2600, 2597, 2599, 2603, 2604, 2598, 2602, 706: 2612}, + {6: 2613}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2614}, + {6: 2615, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2616}, + // 1185 + {9: 2617, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 218: 690, 690, 690, 690, 690, 690, 690, 690, 690, 228: 690, 690, 231: 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 257: 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 280: 690, 690, 690, 690, 690, 690, 690, 690, 289: 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 363: 690}, + {56: 2621, 2620, 61: 2622, 103: 2623, 762: 2619}, + {6: 2624}, + {6: 684}, + // 1190 + {6: 683}, + {6: 682}, + {6: 681}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2625}, + {9: 2626, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 1195 + {696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 218: 696, 696, 696, 696, 696, 696, 696, 696, 696, 228: 696, 696, 231: 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 257: 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 280: 696, 696, 696, 696, 696, 696, 696, 696, 289: 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, 363: 696}, + {707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 218: 707, 707, 707, 707, 707, 707, 707, 707, 707, 228: 707, 707, 231: 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 257: 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 280: 707, 707, 707, 707, 707, 707, 707, 707, 289: 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 707, 363: 707}, + {708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 218: 708, 708, 708, 708, 708, 708, 708, 708, 708, 228: 708, 708, 231: 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 257: 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 280: 708, 708, 708, 708, 708, 708, 708, 708, 289: 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 363: 708}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 1159, 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2456, 544: 2630}, + {9: 2631}, + // 1200 + {704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 218: 704, 704, 704, 704, 704, 704, 704, 704, 704, 228: 704, 704, 231: 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 257: 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 280: 704, 704, 704, 704, 704, 704, 704, 704, 289: 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 704, 363: 704}, + {709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 218: 709, 709, 709, 709, 709, 709, 709, 709, 709, 228: 709, 709, 231: 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 257: 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 280: 709, 709, 709, 709, 709, 709, 709, 709, 289: 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 709, 363: 709}, + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 255: 762, 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 492: 2264, 2265, 495: 2267, 500: 2268, 507: 2269, 512: 2634}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2635}, + {9: 2636, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 1205 + {545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 218: 545, 545, 545, 545, 545, 545, 545, 545, 545, 228: 545, 545, 231: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 257: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 280: 545, 545, 545, 545, 545, 545, 545, 545, 289: 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 363: 545, 463: 2126, 467: 2274, 485: 2637}, + {673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 218: 673, 673, 673, 673, 673, 673, 673, 673, 673, 228: 673, 673, 231: 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 257: 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 280: 673, 673, 673, 673, 673, 673, 673, 673, 289: 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 363: 673}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 1159, 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 488: 2456, 544: 2639}, + {9: 2640}, + {654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 218: 654, 654, 654, 654, 654, 654, 654, 654, 654, 228: 654, 654, 231: 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 257: 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 280: 654, 654, 654, 654, 654, 654, 654, 654, 289: 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 654, 363: 654}, + // 1210 + {2: 1141, 1141, 1141, 1141, 7: 1141, 1141, 10: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 219: 1141, 222: 1141, 1141, 1141, 1141, 1141, 1141, 230: 1141, 255: 1141, 1141, 279: 1141, 288: 1141, 300: 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 364: 1141, 1141, 1141, 1141, 1141, 1141}, + {257: 2666, 277: 2665, 289: 2664, 298: 2650, 2651, 686: 2667}, + {217: 1137}, + {2: 1135, 1135, 1135, 1135, 7: 1135, 1135, 10: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 219: 1135, 222: 1135, 1135, 1135, 1135, 1135, 1135, 230: 1135, 255: 1135, 1135, 279: 1135, 288: 1135, 300: 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 364: 1135, 1135, 1135, 1135, 1135, 1135}, + {2: 1133, 1133, 1133, 1133, 7: 1133, 1133, 10: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 219: 1133, 222: 1133, 1133, 1133, 1133, 1133, 1133, 230: 1133, 255: 1133, 1133, 279: 1133, 288: 1133, 300: 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 364: 1133, 1133, 1133, 1133, 1133, 1133}, + // 1215 + {217: 2660, 435: 2661}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 2657}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2653, 2024, 2099, 2023, 2020}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2652, 2024, 2099, 2023, 2020}, + {2: 1122, 1122, 1122, 1122, 7: 1122, 1122, 10: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 219: 1122, 222: 1122, 1122, 1122, 1122, 1122, 1122, 230: 1122, 255: 1122, 1122, 279: 1122, 288: 1122, 300: 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 364: 1122, 1122, 1122, 1122, 1122, 1122}, + // 1220 + {2: 1121, 1121, 1121, 1121, 7: 1121, 1121, 10: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 219: 1121, 222: 1121, 1121, 1121, 1121, 1121, 1121, 230: 1121, 255: 1121, 1121, 279: 1121, 288: 1121, 300: 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 364: 1121, 1121, 1121, 1121, 1121, 1121}, + {1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 218: 1124, 1124, 221: 1124, 1124, 1124, 228: 1124, 1124, 231: 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 2114, 1124, 1124, 1124, 1124, 1124, 259: 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 278: 1124, 280: 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 363: 2115}, + {1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 2655, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 218: 1120, 1120, 221: 1120, 1120, 1120, 228: 1120, 1120, 231: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 2114, 1120, 1120, 1120, 1120, 1120, 259: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 278: 1120, 280: 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 363: 2115, 775: 2654}, + {1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 218: 1125, 1125, 221: 1125, 1125, 1125, 228: 1125, 1125, 231: 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 250: 1125, 1125, 1125, 1125, 1125, 259: 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 278: 1125, 280: 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125}, + {219: 2656}, + // 1225 + {1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 218: 1119, 1119, 221: 1119, 1119, 1119, 228: 1119, 1119, 231: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 250: 1119, 1119, 1119, 1119, 1119, 259: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 278: 1119, 280: 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119}, + {224: 2386, 2387, 2392, 235: 2658, 258: 2388, 290: 2390, 2383, 2389, 2393, 2382, 2391, 2384, 2385}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 2659}, + {1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 218: 1126, 1126, 221: 1126, 1126, 1126, 228: 1126, 1126, 231: 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 250: 1126, 1126, 1126, 1126, 1126, 259: 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 278: 1126, 280: 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2570, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 1457, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2298, 469: 2556, 1458, 1459, 1460, 475: 1463, 477: 1462, 2557, 488: 2662}, + // 1230 + {1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 218: 1127, 1127, 221: 1127, 1127, 1127, 228: 1127, 1127, 231: 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 250: 1127, 1127, 1127, 1127, 1127, 259: 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 278: 1127, 280: 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127}, + {6: 2300, 9: 2663}, + {1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 218: 1128, 1128, 221: 1128, 1128, 1128, 228: 1128, 1128, 231: 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 250: 1128, 1128, 1128, 1128, 1128, 259: 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 278: 1128, 280: 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128}, + {2: 1140, 1140, 1140, 1140, 7: 1140, 1140, 10: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 219: 1140, 222: 1140, 1140, 1140, 1140, 1140, 1140, 230: 1140, 255: 1140, 1140, 279: 1140, 288: 1140, 300: 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 364: 1140, 1140, 1140, 1140, 1140, 1140}, + {217: 1136}, + // 1235 + {2: 1134, 1134, 1134, 1134, 7: 1134, 1134, 10: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 219: 1134, 222: 1134, 1134, 1134, 1134, 1134, 1134, 230: 1134, 255: 1134, 1134, 279: 1134, 288: 1134, 300: 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 364: 1134, 1134, 1134, 1134, 1134, 1134}, + {2: 1132, 1132, 1132, 1132, 7: 1132, 1132, 10: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 219: 1132, 222: 1132, 1132, 1132, 1132, 1132, 1132, 230: 1132, 255: 1132, 1132, 279: 1132, 288: 1132, 300: 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 364: 1132, 1132, 1132, 1132, 1132, 1132}, + {74: 2691, 230: 2692, 312: 2690, 2689}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 2683, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 2684, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2682, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 2680, 465: 2685, 723: 2681}, + {2: 1149, 1149, 1149, 1149, 7: 1149, 1149, 10: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 219: 1149, 222: 1149, 1149, 1149, 1149, 1149, 1149, 230: 1149, 255: 1149, 1149, 279: 1149, 288: 1149, 300: 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 364: 1149, 1149, 1149, 1149, 1149, 1149, 465: 1149}, + // 1240 + {2: 1148, 1148, 1148, 1148, 7: 1148, 1148, 10: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 219: 1148, 222: 1148, 1148, 1148, 1148, 1148, 1148, 230: 1148, 255: 1148, 1148, 279: 1148, 288: 1148, 300: 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 1148, 364: 1148, 1148, 1148, 1148, 1148, 1148, 465: 1148}, + {2: 1147, 1147, 1147, 1147, 7: 1147, 1147, 10: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 219: 1147, 222: 1147, 1147, 1147, 1147, 1147, 1147, 230: 1147, 255: 1147, 1147, 279: 1147, 288: 1147, 300: 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 364: 1147, 1147, 1147, 1147, 1147, 1147, 465: 1147}, + {2: 1146, 1146, 1146, 1146, 7: 1146, 1146, 10: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 219: 1146, 222: 1146, 1146, 1146, 1146, 1146, 1146, 230: 1146, 255: 1146, 1146, 279: 1146, 288: 1146, 300: 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 364: 1146, 1146, 1146, 1146, 1146, 1146, 465: 1146}, + {2: 1145, 1145, 1145, 1145, 7: 1145, 1145, 10: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 219: 1145, 222: 1145, 1145, 1145, 1145, 1145, 1145, 230: 1145, 255: 1145, 1145, 279: 1145, 288: 1145, 300: 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 1145, 364: 1145, 1145, 1145, 1145, 1145, 1145, 465: 1145}, + {2: 1144, 1144, 1144, 1144, 7: 1144, 1144, 10: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 219: 1144, 222: 1144, 1144, 1144, 1144, 1144, 1144, 230: 1144, 255: 1144, 1144, 279: 1144, 288: 1144, 300: 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 364: 1144, 1144, 1144, 1144, 1144, 1144, 465: 1144}, + // 1245 + {2: 1143, 1143, 1143, 1143, 7: 1143, 1143, 10: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 219: 1143, 222: 1143, 1143, 1143, 1143, 1143, 1143, 230: 1143, 255: 1143, 1143, 279: 1143, 288: 1143, 300: 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 364: 1143, 1143, 1143, 1143, 1143, 1143, 465: 1143}, + {2: 1142, 1142, 1142, 1142, 7: 1142, 1142, 10: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 219: 1142, 222: 1142, 1142, 1142, 1142, 1142, 1142, 230: 1142, 255: 1142, 1142, 279: 1142, 288: 1142, 300: 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 364: 1142, 1142, 1142, 1142, 1142, 1142, 465: 1142}, + {74: 1139, 220: 2679, 230: 1139, 312: 1139, 1139}, + {74: 1138, 230: 1138, 312: 1138, 1138}, + {1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 218: 1153, 1153, 221: 1153, 1153, 1153, 228: 1153, 1153, 231: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 250: 1153, 1153, 1153, 1153, 1153, 259: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 278: 1153, 280: 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153}, + // 1250 + {217: 2555, 435: 2688}, + {392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 218: 392, 392, 392, 392, 392, 392, 392, 392, 392, 228: 392, 392, 231: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 257: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 280: 392, 392, 392, 392, 392, 392, 392, 392, 289: 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, 363: 392, 570: 2686}, + {1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1131, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 228: 1003, 1003, 231: 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 257: 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 289: 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 363: 1003, 386: 1003, 1003}, + {1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1130, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 228: 1002, 1002, 231: 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 257: 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 289: 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 363: 1002, 386: 1002, 1002}, + {217: 1129}, + // 1255 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 2687}, + {1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 218: 1151, 1151, 221: 1151, 1151, 1151, 228: 1151, 1151, 231: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 250: 1151, 1151, 1151, 1151, 1151, 259: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 278: 1151, 280: 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151}, + {1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 218: 1152, 1152, 221: 1152, 1152, 1152, 228: 1152, 1152, 231: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 250: 1152, 1152, 1152, 1152, 1152, 259: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 278: 1152, 280: 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152}, + {1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 218: 1173, 1173, 221: 1173, 1173, 1173, 228: 1173, 1173, 231: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 244: 1173, 1173, 1173, 1173, 1173, 250: 1173, 1173, 1173, 1173, 1173, 259: 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 278: 1173}, + {1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 218: 1172, 1172, 221: 1172, 1172, 1172, 228: 1172, 1172, 231: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 244: 1172, 1172, 1172, 1172, 1172, 250: 1172, 1172, 1172, 1172, 1172, 259: 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 278: 1172}, + // 1260 + {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 218: 1171, 1171, 221: 1171, 1171, 1171, 228: 1171, 1171, 231: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 244: 1171, 1171, 1171, 1171, 1171, 250: 1171, 1171, 1171, 1171, 1171, 259: 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 278: 1171}, + {1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 218: 1154, 1154, 221: 1154, 1154, 1154, 228: 1154, 1154, 231: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 250: 1154, 1154, 1154, 1154, 1154, 259: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 278: 1154, 280: 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154}, + {1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 218: 1174, 1174, 221: 1174, 1174, 1174, 228: 1174, 1174, 231: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 244: 1174, 1174, 1174, 1174, 1174, 250: 1174, 1174, 1174, 1174, 1174, 259: 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 278: 1174, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2695}, + {1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 218: 1178, 1178, 221: 1178, 1178, 1178, 228: 1178, 1178, 231: 1178, 1178, 1178, 1178, 2110, 2108, 2109, 2107, 2105, 1178, 1178, 1178, 244: 1178, 1178, 1178, 1178, 1178, 250: 1178, 1178, 1178, 1178, 1178, 259: 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 278: 1178, 457: 2106, 2104}, + // 1265 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 2702}, + {248: 476, 562: 2699, 676: 2698}, + {248: 2700}, + {248: 475}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 2701}, + // 1270 + {481, 481, 6: 481, 9: 481, 218: 481, 222: 481, 481, 228: 481, 481, 231: 481, 481, 481, 481, 240: 481, 242: 481, 244: 481, 481, 481, 481, 481, 250: 481, 481, 481, 481, 481, 502: 1957, 506: 1956}, + {482, 482, 6: 482, 9: 482, 218: 482, 222: 482, 482, 228: 482, 482, 231: 482, 482, 482, 482, 240: 482, 242: 482, 244: 482, 482, 482, 482, 482, 250: 482, 482, 482, 482, 482, 502: 1957, 506: 1956}, + {248: 2704}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 2705}, + {218: 2706, 222: 1960, 1961, 242: 2707, 244: 1959, 248: 1962, 251: 1963, 1964, 1958, 502: 1957, 506: 1956}, + // 1275 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2711}, + {217: 2708}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 2709}, + {6: 1819, 9: 2710}, + {483, 483, 6: 483, 9: 483, 218: 483, 222: 483, 483, 228: 483, 483, 231: 483, 483, 483, 483, 240: 483, 242: 483, 244: 483, 483, 483, 483, 483, 250: 483, 483, 483, 483, 483}, + // 1280 + {484, 484, 6: 484, 9: 484, 218: 484, 222: 484, 484, 228: 484, 484, 231: 484, 484, 484, 484, 2110, 2108, 2109, 2107, 2105, 484, 242: 484, 244: 484, 484, 484, 484, 484, 250: 484, 484, 484, 484, 484, 457: 2106, 2104}, + {487, 487, 6: 487, 9: 487, 218: 2713, 222: 487, 487, 228: 487, 487, 231: 487, 487, 487, 487, 240: 487, 242: 2714, 244: 487, 487, 487, 487, 487, 250: 487, 487, 487, 487, 487, 502: 1957, 506: 1956}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2718}, + {217: 2715}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 2716}, + // 1285 + {6: 1819, 9: 2717}, + {485, 485, 6: 485, 9: 485, 218: 485, 222: 485, 485, 228: 485, 485, 231: 485, 485, 485, 485, 240: 485, 242: 485, 244: 485, 485, 485, 485, 485, 250: 485, 485, 485, 485, 485}, + {486, 486, 6: 486, 9: 486, 218: 486, 222: 486, 486, 228: 486, 486, 231: 486, 486, 486, 486, 2110, 2108, 2109, 2107, 2105, 486, 242: 486, 244: 486, 486, 486, 486, 486, 250: 486, 486, 486, 486, 486, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 1943, 516: 2721}, + {508, 508, 6: 508, 9: 508, 218: 508, 222: 508, 508, 228: 508, 508, 231: 508, 508, 508, 508, 240: 508, 242: 508, 244: 508, 508, 508, 508, 508, 250: 508, 508, 508, 508, 508}, + // 1290 + {516, 516, 6: 516, 9: 516, 218: 516, 228: 516, 516, 231: 516, 516, 516, 516, 240: 516, 245: 516, 516, 516, 250: 516}, + {489, 489, 6: 489, 9: 489, 218: 489, 222: 489, 489, 228: 489, 489, 231: 489, 489, 489, 489, 240: 489, 242: 489, 244: 489, 489, 489, 489, 489, 250: 489, 489, 489, 489, 489, 377: 2726, 392: 2727, 2725, 582: 2729, 2728, 649: 2730, 2724}, + {506, 506, 6: 506, 9: 506, 218: 506, 222: 506, 506, 228: 506, 506, 231: 506, 506, 506, 506, 240: 506, 242: 506, 244: 506, 506, 506, 506, 506, 250: 506, 506, 506, 506, 506, 377: 506, 392: 506, 506}, + {511, 511, 6: 511, 9: 511, 218: 511, 222: 511, 511, 228: 511, 511, 231: 511, 511, 511, 511, 240: 511, 242: 511, 244: 511, 511, 511, 511, 511, 250: 511, 511, 511, 511, 511}, + {370: 2746, 388: 2747, 510: 2750}, + // 1295 + {370: 2746, 388: 2747, 510: 2749}, + {370: 2746, 388: 2747, 510: 2748}, + {217: 500, 232: 2732, 768: 2733}, + {491, 491, 6: 491, 9: 491, 218: 491, 222: 491, 491, 228: 491, 491, 231: 491, 491, 491, 491, 240: 491, 242: 491, 244: 491, 491, 491, 491, 491, 250: 491, 491, 491, 491, 491, 377: 491, 392: 491, 491}, + {488, 488, 6: 488, 9: 488, 218: 488, 222: 488, 488, 228: 488, 488, 231: 488, 488, 488, 488, 240: 488, 242: 488, 244: 488, 488, 488, 488, 488, 250: 488, 488, 488, 488, 488, 377: 2726, 392: 2727, 2725, 582: 2731, 2728}, + // 1300 + {490, 490, 6: 490, 9: 490, 218: 490, 222: 490, 490, 228: 490, 490, 231: 490, 490, 490, 490, 240: 490, 242: 490, 244: 490, 490, 490, 490, 490, 250: 490, 490, 490, 490, 490, 377: 490, 392: 490, 490}, + {234: 2742, 248: 2741, 250: 2743}, + {217: 2734}, + {2: 1622, 1541, 1575, 1542, 495, 1552, 1627, 495, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 371: 2737, 376: 2736, 378: 1537, 1538, 1536, 558: 2735}, + {6: 2739, 9: 2738}, + // 1305 + {494, 494, 6: 494, 9: 494, 228: 494}, + {492, 492, 6: 492, 9: 492, 228: 492}, + {496, 496, 6: 496, 9: 496, 218: 496, 222: 496, 496, 228: 496, 496, 231: 496, 496, 496, 496, 240: 496, 242: 496, 244: 496, 496, 496, 496, 496, 250: 496, 496, 496, 496, 496, 377: 496, 392: 496, 496}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2740, 378: 1537, 1538, 1536}, + {493, 493, 6: 493, 9: 493, 228: 493}, + // 1310 + {217: 499}, + {390: 2745}, + {390: 2744}, + {217: 497}, + {217: 498}, + // 1315 + {2: 1391, 1391, 1391, 1391, 7: 1391, 1391, 10: 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 1391, 232: 1391, 242: 1391}, + {2: 1390, 1390, 1390, 1390, 7: 1390, 1390, 10: 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 232: 1390, 242: 1390}, + {217: 501, 232: 501}, + {217: 502, 232: 502}, + {217: 503, 232: 503}, + // 1320 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 2752}, + {222: 1960, 1961, 244: 1959, 248: 1962, 251: 1963, 1964, 1958, 2753, 502: 1957, 506: 1956}, + {514, 514, 6: 514, 9: 514, 218: 514, 228: 514, 514, 231: 514, 514, 514, 514, 240: 514, 245: 514, 514, 514, 250: 514}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 2755, 554: 2756, 571: 2757}, + {243: 2770}, + // 1325 + {1363, 1363, 6: 1363, 233: 1363, 1363, 240: 1363}, + {104, 104, 6: 2758, 233: 104, 104, 240: 2760, 524: 2761, 2759}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 2755, 554: 2769}, + {817, 817, 233: 817, 2301, 498: 2302, 2763}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2762}, + // 1330 + {103, 103, 9: 103, 218: 103, 228: 103, 103, 231: 103, 103, 103, 103, 245: 103, 247: 103, 250: 103}, + {105, 105, 9: 105, 218: 105, 228: 105, 105, 231: 105, 105, 105, 105, 2110, 2108, 2109, 2107, 2105, 245: 105, 247: 105, 250: 105, 457: 2106, 2104}, + {471, 471, 233: 2764, 656: 2765}, + {256: 1526, 306: 2768, 461: 2508, 476: 2767, 560: 2766}, + {108, 108}, + // 1335 + {470, 470}, + {469, 469, 6: 469, 9: 469, 53: 469, 218: 469, 228: 469, 469, 231: 469, 469}, + {468, 468, 6: 468, 9: 468, 53: 468, 218: 468, 228: 468, 468, 231: 468, 468}, + {1362, 1362, 6: 1362, 233: 1362, 1362, 240: 1362}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2771}, + // 1340 + {1364, 1364, 6: 1364, 233: 1364, 1364, 2110, 2108, 2109, 2107, 2105, 1364, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 2755, 554: 2756, 571: 2773}, + {104, 104, 6: 2758, 240: 2760, 524: 2761, 2774}, + {107, 107}, + {41: 2780, 43: 2779, 2778, 2777, 517: 2796, 702: 2797}, + // 1345 + {41: 458, 43: 458, 458, 458, 517: 458}, + {217: 2793}, + {217: 2790}, + {217: 2784}, + {217: 2781}, + // 1350 + {256: 1526, 461: 2782}, + {9: 2783}, + {41: 453, 43: 453, 453, 453, 517: 453}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2785, 378: 1537, 1538, 1536, 579: 2786}, + {6: 460, 9: 460}, + // 1355 + {6: 2787, 9: 2788}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2789, 378: 1537, 1538, 1536}, + {41: 454, 43: 454, 454, 454, 517: 454}, + {6: 459, 9: 459}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2785, 378: 1537, 1538, 1536, 579: 2791}, + // 1360 + {6: 2787, 9: 2792}, + {41: 455, 43: 455, 455, 455, 517: 455}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2785, 378: 1537, 1538, 1536, 579: 2794}, + {6: 2787, 9: 2795}, + {41: 456, 43: 456, 456, 456, 517: 456}, + // 1365 + {2: 461, 461, 461, 461, 7: 461, 461, 10: 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 219: 461, 461, 222: 461, 461, 461, 461, 461, 461, 230: 461, 241: 461, 244: 461, 255: 461, 461, 258: 461, 279: 461, 288: 461, 300: 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, 364: 461, 461, 461, 461, 461, 461, 377: 461, 465: 461, 480: 461, 482: 461, 461, 461, 492: 461, 461}, + {41: 457, 43: 457, 457, 457, 517: 457}, + {2: 204, 204, 204, 204, 7: 204, 204, 10: 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2800}, + {203, 203}, + // 1370 + {24: 2808, 2805, 49: 2807, 474: 2804, 703: 2809, 760: 2806}, + {24: 307, 307, 49: 307, 474: 307}, + {24: 306, 306, 49: 306, 474: 306}, + {1195, 1195, 1195, 1195, 1195, 1195, 7: 1195, 1195, 10: 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 228: 1195, 302: 1195}, + {1194, 1194, 1194, 1194, 1194, 1194, 7: 1194, 1194, 10: 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 228: 1194, 302: 1194}, + // 1375 + {312, 312}, + {311, 311}, + {310, 310}, + {305, 305, 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 228: 305, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 2811, 830: 2812}, + {599, 599, 6: 599, 228: 599, 241: 599, 395: 599, 599}, + // 1380 + {304, 304, 6: 2817, 228: 304}, + {303, 303, 228: 2814, 861: 2813}, + {309, 309}, + {398: 2815}, + {231: 2816}, + // 1385 + {302, 302}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2818}, + {598, 598, 6: 598, 228: 598, 241: 598, 598, 395: 598, 598}, + {323, 323, 240: 2869, 257: 2868, 552: 2893}, + {315: 2890, 474: 2889}, + // 1390 + {357, 357, 232: 2887}, + {24: 2886}, + {25: 2876, 29: 2877, 39: 2878, 69: 2875}, + {323, 323, 240: 2869, 257: 2868, 552: 2874}, + {323, 323, 240: 2869, 257: 2868, 552: 2873}, + // 1395 + {323, 323, 240: 2869, 257: 2868, 552: 2872}, + {323, 323, 240: 2869, 257: 2868, 552: 2867}, + {349, 349}, + {348, 348}, + {241: 347, 277: 347}, + // 1400 + {241: 346, 277: 346}, + {241: 345, 277: 345}, + {342, 342, 240: 342, 257: 342}, + {341, 341, 240: 341, 257: 341}, + {340, 340, 240: 340, 257: 340}, + // 1405 + {24: 2865}, + {241: 2850, 277: 2851, 496: 2860}, + {333, 333, 240: 333, 257: 333}, + {332, 332, 240: 332, 257: 332}, + {24: 2859, 63: 2858}, + // 1410 + {329, 329, 240: 329, 257: 329}, + {315, 315, 240: 315, 2850, 257: 315, 277: 2851, 496: 2853, 535: 2857}, + {24: 2856}, + {24: 2855}, + {315, 315, 240: 315, 2850, 257: 315, 277: 2851, 496: 2853, 535: 2852}, + // 1415 + {324, 324, 240: 324, 257: 324}, + {24: 319, 63: 319}, + {24: 318, 63: 318}, + {25: 316, 29: 316, 39: 316, 69: 316}, + {2: 344, 344, 344, 344, 7: 344, 344, 10: 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344, 344}, + // 1420 + {2: 343, 343, 343, 343, 7: 343, 343, 10: 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, 343}, + {325, 325, 240: 325, 257: 325}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1924, 378: 1537, 1538, 1536, 542: 2854}, + {314, 314, 240: 314, 257: 314}, + {326, 326, 240: 326, 257: 326}, + // 1425 + {327, 327, 240: 327, 257: 327}, + {328, 328, 240: 328, 257: 328}, + {331, 331, 240: 331, 257: 331}, + {330, 330, 240: 330, 257: 330}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2861, 378: 1537, 1538, 1536, 459: 2862}, + // 1430 + {601, 601, 240: 601, 2850, 257: 601, 277: 2851, 279: 1761, 496: 2863}, + {337, 337, 240: 337, 257: 337}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2864, 378: 1537, 1538, 1536}, + {336, 336, 240: 336, 257: 336}, + {315, 315, 240: 315, 2850, 257: 315, 277: 2851, 496: 2853, 535: 2866}, + // 1435 + {338, 338, 240: 338, 257: 338}, + {350, 350}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 2113, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2871, 2024, 2099, 2023, 2020}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2870}, + {321, 321, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 1440 + {322, 322, 249: 2114, 363: 2115}, + {351, 351}, + {352, 352}, + {353, 353}, + {354, 354}, + // 1445 + {315, 315, 240: 315, 2850, 257: 315, 277: 2851, 496: 2853, 535: 2885}, + {241: 2850, 277: 2851, 496: 2880, 693: 2883}, + {241: 2850, 277: 2851, 496: 2880, 693: 2879}, + {315, 315, 240: 315, 2850, 257: 315, 277: 2851, 496: 2853, 535: 2882}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2881}, + // 1450 + {313, 313, 240: 313, 313, 257: 313, 277: 313}, + {334, 334, 240: 334, 257: 334}, + {315, 315, 240: 315, 2850, 257: 315, 277: 2851, 496: 2853, 535: 2884}, + {335, 335, 240: 335, 257: 335}, + {339, 339, 240: 339, 257: 339}, + // 1455 + {355, 355}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 2888}, + {356, 356}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2892}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1924, 378: 1537, 1538, 1536, 542: 2891}, + // 1460 + {358, 358}, + {359, 359}, + {360, 360}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 2929, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 2928, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2930}, + {388: 2915, 474: 2914}, + // 1465 + {388: 2911}, + {388: 2908}, + {474: 2906}, + {120: 2900}, + {93: 2901}, + // 1470 + {256: 1526, 461: 2903, 665: 2902}, + {372, 372, 6: 2904}, + {362, 362, 6: 362}, + {256: 1526, 461: 2905}, + {361, 361, 6: 361}, + // 1475 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 2907}, + {373, 373, 6: 2817}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2909}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2910, 378: 1537, 1538, 1536}, + {375, 375}, + // 1480 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2912}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2913, 378: 1537, 1538, 1536}, + {376, 376}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 2927}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2916}, + // 1485 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2917, 378: 1537, 1538, 1536}, + {377, 377, 217: 2920, 647: 2919, 765: 2918}, + {374, 374, 6: 2925}, + {365, 365, 6: 365}, + {256: 1526, 461: 2921}, + // 1490 + {6: 2922}, + {256: 1526, 461: 2923}, + {9: 2924}, + {363, 363, 6: 363}, + {217: 2920, 647: 2926}, + // 1495 + {364, 364, 6: 364}, + {378, 378, 6: 2817}, + {67: 938, 152: 2938, 171: 2939, 279: 938, 720: 2937}, + {382, 382, 67: 914, 93: 2932, 135: 2933, 279: 914}, + {67: 2931}, + // 1500 + {379, 379}, + {381, 381, 256: 1526, 461: 2936}, + {151: 2934}, + {256: 1526, 461: 2903, 665: 2935}, + {371, 371, 6: 2904}, + // 1505 + {380, 380}, + {370, 370}, + {256: 1526, 461: 2945}, + {133: 2941, 256: 1526, 461: 2940, 465: 2942}, + {368, 368}, + // 1510 + {256: 1526, 461: 2944}, + {256: 1526, 461: 2943}, + {366, 366}, + {367, 367}, + {369, 369}, + // 1515 + {2: 115, 115, 115, 115, 7: 115, 115, 10: 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 219: 115, 243: 1068, 288: 115}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 3018, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 243: 1039, 376: 2979, 378: 1537, 1538, 1536}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 243: 1035, 376: 3015, 378: 1537, 1538, 1536}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 243: 1033, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 3011}, + {232: 3001, 243: 3000}, + // 1520 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 2998, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 243: 1026, 376: 2976, 378: 1537, 1538, 1536}, + {58: 2984, 243: 1012, 398: 2985, 567: 2983, 597: 2982}, + {428, 428, 6: 2972}, + {243: 2970}, + {243: 2964}, + // 1525 + {243: 2960, 570: 2961}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 2959}, + {397, 397, 6: 397}, + {401, 401, 6: 401}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2963}, + // 1530 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2962}, + {405, 405, 6: 405, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {406, 406, 6: 406, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 2967, 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2966, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2965, 527: 2968, 565: 2969}, + {848, 848, 6: 848, 9: 848, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + // 1535 + {847, 847, 6: 847, 9: 847, 217: 2482}, + {413, 413, 6: 413}, + {412, 412, 6: 412}, + {407, 407, 6: 407}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 2967, 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2966, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2965, 527: 2968, 565: 2971}, + // 1540 + {411, 411, 6: 411}, + {2: 1622, 1541, 1575, 1542, 7: 2946, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 2948, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 2973, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 2974, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 2949, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 307: 2956, 319: 2955, 376: 2954, 378: 1537, 1538, 1536, 382: 2524, 481: 2957, 715: 2975}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 243: 1039, 376: 2979, 378: 1537, 1538, 1536}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 243: 1026, 376: 2976, 378: 1537, 1538, 1536}, + {396, 396, 6: 396}, + // 1545 + {243: 2977}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 2967, 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2966, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2965, 527: 2968, 565: 2978}, + {409, 409, 6: 409}, + {243: 2980}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 2967, 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2966, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2965, 527: 2968, 565: 2981}, + // 1550 + {410, 410, 6: 410}, + {423, 423, 6: 2996}, + {422, 422, 6: 422}, + {138: 2988}, + {148: 2987, 434: 2986}, + // 1555 + {419, 419, 6: 419}, + {418, 418, 6: 418}, + {154: 2990, 156: 2992, 398: 2991, 771: 2989}, + {420, 420, 6: 420}, + {398: 2995}, + // 1560 + {117: 2993, 174: 2994}, + {414, 414, 6: 414}, + {416, 416, 6: 416}, + {415, 415, 6: 415}, + {417, 417, 6: 417}, + // 1565 + {58: 2984, 398: 2985, 567: 2997}, + {421, 421, 6: 421}, + {58: 2984, 243: 1012, 398: 2985, 567: 2983, 597: 2999}, + {424, 424, 6: 2996}, + {12: 3006, 219: 3005, 680: 3010}, + // 1570 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 3002}, + {243: 3003}, + {12: 3006, 219: 3005, 680: 3004}, + {426, 426}, + {385, 385}, + // 1575 + {217: 3007}, + {219: 1886, 555: 3008}, + {9: 3009}, + {384, 384}, + {427, 427}, + // 1580 + {404, 404, 6: 404, 249: 3012}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 227: 3013, 376: 1780, 378: 1537, 1538, 1536, 466: 3014}, + {403, 403, 6: 403}, + {402, 402, 6: 402}, + {243: 3016}, + // 1585 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3017}, + {408, 408, 6: 408, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {58: 2984, 243: 1012, 398: 2985, 567: 2983, 597: 3019}, + {425, 425, 6: 2996}, + {217: 760, 381: 760, 465: 2266, 492: 2264, 2265, 495: 3021, 500: 3022, 746: 3024, 838: 3023}, + // 1590 + {2: 763, 763, 763, 763, 7: 763, 763, 10: 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 219: 763, 763, 222: 763, 763, 763, 763, 763, 763, 230: 763, 244: 763, 255: 763, 763, 258: 763, 279: 763, 288: 763, 300: 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 763, 364: 763, 763, 763, 763, 763, 763, 381: 763, 480: 763, 482: 763, 763, 763}, + {217: 759, 381: 759}, + {217: 3028, 381: 1457, 469: 3030, 3025, 3026, 3027, 475: 3029}, + {217: 429, 381: 429}, + {817, 817, 9: 817, 218: 817, 229: 817, 231: 817, 817, 817, 2301, 241: 3054, 498: 2302, 3055, 642: 3053}, + // 1595 + {817, 817, 9: 817, 218: 817, 229: 817, 231: 817, 817, 817, 2301, 498: 2302, 3050}, + {817, 817, 9: 817, 218: 817, 229: 817, 231: 817, 817, 817, 2301, 498: 2302, 3041}, + {381: 1457, 469: 3031, 1458, 1459, 1460}, + {229: 432}, + {229: 431}, + // 1600 + {9: 3032}, + {817, 817, 9: 817, 218: 817, 229: 430, 233: 817, 2301, 498: 2302, 3033}, + {467, 467, 9: 467, 218: 467, 233: 3034, 521: 3035}, + {256: 1526, 306: 2768, 461: 2508, 476: 2767, 560: 3036}, + {434, 434, 9: 434, 218: 434}, + // 1605 + {466, 466, 6: 3037, 9: 466, 53: 3038, 218: 466, 228: 466, 466, 231: 466, 466}, + {256: 1526, 306: 2768, 461: 2508, 476: 2767, 560: 3040}, + {256: 1526, 306: 2768, 461: 2508, 476: 2767, 560: 3039}, + {464, 464, 9: 464, 218: 464, 228: 464, 464, 231: 464, 464}, + {465, 465, 9: 465, 218: 465, 228: 465, 465, 231: 465, 465}, + // 1610 + {467, 467, 9: 467, 218: 467, 229: 467, 231: 467, 467, 3034, 521: 3042}, + {440, 440, 9: 440, 218: 440, 229: 440, 231: 3045, 3044, 533: 3043}, + {435, 435, 9: 435, 218: 435, 229: 579}, + {479: 3049}, + {277: 3046}, + // 1615 + {158: 3047}, + {145: 3048}, + {438, 438, 9: 438, 218: 438, 228: 438, 438}, + {439, 439, 9: 439, 218: 439, 228: 439, 439}, + {467, 467, 9: 467, 218: 467, 229: 467, 231: 467, 467, 3034, 521: 3051}, + // 1620 + {440, 440, 9: 440, 218: 440, 229: 440, 231: 3045, 3044, 533: 3052}, + {436, 436, 9: 436, 218: 436, 229: 580}, + {104, 104, 9: 104, 218: 104, 228: 104, 104, 231: 104, 104, 104, 104, 240: 2760, 524: 2761, 3079}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 1943, 516: 1934, 537: 3060, 748: 3059, 832: 3058}, + {467, 467, 9: 467, 218: 467, 229: 467, 231: 467, 467, 3034, 521: 3056}, + // 1625 + {440, 440, 9: 440, 218: 440, 229: 440, 231: 3045, 3044, 533: 3057}, + {437, 437, 9: 437, 218: 437, 229: 581}, + {104, 104, 9: 104, 218: 104, 228: 104, 104, 231: 104, 104, 104, 104, 240: 2760, 245: 104, 247: 104, 250: 104, 524: 2761, 3061}, + {578, 578, 9: 578, 218: 578, 228: 578, 578, 231: 578, 578, 578, 578, 240: 578}, + {518, 518, 6: 2719, 9: 518, 218: 518, 228: 518, 518, 231: 518, 518, 518, 518, 240: 518, 245: 518, 247: 518, 250: 518}, + // 1630 + {444, 444, 9: 444, 218: 444, 228: 444, 444, 231: 444, 444, 444, 444, 245: 444, 247: 444, 250: 3062, 764: 3064, 813: 3063}, + {390: 3077}, + {1104, 1104, 9: 1104, 218: 1104, 228: 1104, 1104, 231: 1104, 1104, 1104, 1104, 245: 1104, 247: 3065, 766: 3066}, + {443, 443, 9: 443, 218: 443, 228: 443, 443, 231: 443, 443, 443, 443, 245: 443, 247: 443}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3076}, + // 1635 + {577, 577, 9: 577, 218: 577, 228: 577, 577, 231: 577, 577, 577, 577, 245: 3068, 853: 3067}, + {582, 582, 9: 582, 218: 582, 228: 582, 582, 231: 582, 582, 582, 582}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2128, 378: 1537, 1538, 1536, 569: 3071, 717: 3070, 854: 3069}, + {576, 576, 6: 3074, 9: 576, 218: 576, 228: 576, 576, 231: 576, 576, 576, 576}, + {575, 575, 6: 575, 9: 575, 218: 575, 228: 575, 575, 231: 575, 575, 575, 575}, + // 1640 + {221: 3072}, + {217: 2129, 719: 3073}, + {573, 573, 6: 573, 9: 573, 218: 573, 228: 573, 573, 231: 573, 573, 573, 573}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 2128, 378: 1537, 1538, 1536, 569: 3071, 717: 3075}, + {574, 574, 6: 574, 9: 574, 218: 574, 228: 574, 574, 231: 574, 574, 574, 574}, + // 1645 + {1103, 1103, 9: 1103, 218: 1103, 228: 1103, 1103, 231: 1103, 1103, 1103, 1103, 2110, 2108, 2109, 2107, 2105, 245: 1103, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2139, 539: 2140, 556: 3078}, + {1105, 1105, 6: 2142, 9: 1105, 218: 1105, 228: 1105, 1105, 231: 1105, 1105, 1105, 1105, 245: 1105, 247: 1105}, + {583, 583, 9: 583, 218: 583, 228: 583, 583, 231: 583, 583, 583, 583}, + {467, 467, 9: 467, 218: 467, 228: 467, 467, 231: 467, 467, 3034, 521: 3081}, + // 1650 + {440, 440, 9: 440, 218: 440, 228: 440, 440, 231: 3045, 3044, 533: 3082}, + {579, 579, 9: 579, 218: 579, 228: 579, 579}, + {467, 467, 9: 467, 218: 467, 228: 467, 467, 231: 467, 467, 3034, 521: 3084}, + {440, 440, 9: 440, 218: 440, 228: 440, 440, 231: 3045, 3044, 533: 3085}, + {580, 580, 9: 580, 218: 580, 228: 580, 580}, + // 1655 + {467, 467, 9: 467, 218: 467, 228: 467, 467, 231: 467, 467, 3034, 521: 3087}, + {440, 440, 9: 440, 218: 440, 228: 440, 440, 231: 3045, 3044, 533: 3088}, + {581, 581, 9: 581, 218: 581, 228: 581, 581}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 258: 3101, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 3103, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 3102, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3100, 638: 3104, 754: 3105, 812: 3106}, + {2: 762, 762, 762, 762, 7: 762, 762, 10: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 219: 762, 762, 222: 762, 762, 762, 762, 762, 762, 230: 762, 244: 762, 255: 762, 762, 258: 762, 279: 762, 288: 762, 300: 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 762, 364: 762, 762, 762, 762, 762, 762, 465: 2266, 480: 762, 482: 762, 762, 762, 492: 2264, 2265, 495: 3021, 500: 2268, 507: 3091}, + // 1660 + {2: 605, 605, 605, 605, 7: 605, 605, 10: 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 219: 605, 605, 222: 605, 605, 605, 605, 605, 605, 230: 605, 244: 605, 255: 605, 605, 258: 605, 279: 605, 288: 605, 300: 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 364: 605, 605, 605, 605, 605, 605, 480: 605, 482: 1930, 1929, 1928, 551: 3092}, + {2: 450, 450, 450, 450, 7: 450, 450, 10: 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 3094, 3095, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 219: 450, 450, 222: 450, 450, 450, 450, 450, 450, 230: 450, 244: 450, 255: 450, 450, 258: 450, 279: 450, 288: 450, 300: 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 364: 450, 450, 450, 450, 450, 450, 480: 450, 815: 3093}, + {2: 452, 452, 452, 452, 7: 452, 452, 10: 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 219: 452, 452, 222: 452, 452, 452, 452, 452, 452, 230: 452, 244: 452, 255: 452, 452, 258: 452, 279: 452, 288: 452, 300: 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 452, 364: 452, 452, 452, 452, 452, 452, 480: 3097, 811: 3096}, + {2: 449, 449, 449, 449, 7: 449, 449, 10: 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 219: 449, 449, 222: 449, 449, 449, 449, 449, 449, 230: 449, 244: 449, 255: 449, 449, 258: 449, 279: 449, 288: 449, 300: 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 364: 449, 449, 449, 449, 449, 449, 480: 449}, + {2: 448, 448, 448, 448, 7: 448, 448, 10: 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 219: 448, 448, 222: 448, 448, 448, 448, 448, 448, 230: 448, 244: 448, 255: 448, 448, 258: 448, 279: 448, 288: 448, 300: 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 448, 364: 448, 448, 448, 448, 448, 448, 480: 448}, + // 1665 + {2: 447, 447, 447, 447, 7: 447, 447, 10: 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 219: 447, 447, 222: 447, 447, 447, 447, 447, 447, 230: 447, 244: 3099, 255: 447, 447, 258: 447, 279: 447, 288: 447, 300: 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 364: 447, 447, 447, 447, 447, 447, 816: 3098}, + {2: 451, 451, 451, 451, 7: 451, 451, 10: 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 219: 451, 451, 222: 451, 451, 451, 451, 451, 451, 230: 451, 244: 451, 255: 451, 451, 258: 451, 279: 451, 288: 451, 300: 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 451, 364: 451, 451, 451, 451, 451, 451}, + {2: 463, 463, 463, 463, 7: 463, 463, 10: 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 219: 463, 463, 222: 463, 463, 463, 463, 463, 463, 230: 463, 255: 463, 463, 258: 463, 279: 463, 288: 463, 300: 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, 364: 463, 463, 463, 463, 463, 463}, + {2: 446, 446, 446, 446, 7: 446, 446, 10: 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 219: 446, 446, 222: 446, 446, 446, 446, 446, 446, 230: 446, 255: 446, 446, 258: 446, 279: 446, 288: 446, 300: 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, 364: 446, 446, 446, 446, 446, 446}, + {1113, 1113, 1622, 1541, 1575, 1542, 1113, 1552, 1627, 1113, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 218: 1113, 3116, 221: 3115, 228: 1113, 1113, 231: 1113, 1113, 1113, 1113, 2110, 2108, 2109, 2107, 2105, 241: 1113, 376: 3114, 378: 1537, 1538, 1536, 457: 2106, 2104, 639: 3113, 3124}, + // 1670 + {1118, 1118, 6: 1118, 9: 1118, 218: 1118, 228: 1118, 1118, 231: 1118, 1118, 1118, 1118, 241: 1118}, + {800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 218: 800, 800, 800, 800, 224: 800, 800, 800, 228: 800, 800, 231: 800, 800, 800, 800, 800, 800, 800, 800, 800, 241: 800, 243: 800, 249: 800, 257: 800, 800, 277: 800, 279: 3119, 800, 800, 800, 800, 800, 800, 800, 800, 289: 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 363: 800, 386: 800, 800}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3109, 378: 1537, 1538, 1536, 667: 2447, 2444, 2446, 2445}, + {1107, 1107, 6: 1107, 9: 1107, 218: 1107, 228: 1107, 1107, 231: 1107, 1107, 1107, 1107, 241: 1107}, + {445, 445, 6: 3107, 9: 445, 218: 445, 228: 445, 445, 231: 445, 445, 445, 445, 241: 445}, + // 1675 + {584, 584, 9: 584, 218: 584, 228: 584, 584, 231: 584, 584, 584, 584, 241: 584}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 258: 3101, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 3103, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 3102, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3100, 638: 3108}, + {1106, 1106, 6: 1106, 9: 1106, 218: 1106, 228: 1106, 1106, 231: 1106, 1106, 1106, 1106, 241: 1106}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3110}, + {235: 2110, 2108, 2109, 2107, 2105, 254: 3111, 457: 2106, 2104}, + // 1680 + {1113, 1113, 1622, 1541, 1575, 1542, 1113, 1552, 1627, 1113, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 218: 1113, 3116, 221: 3115, 228: 1113, 1113, 231: 1113, 1113, 1113, 1113, 241: 1113, 376: 3114, 378: 1537, 1538, 1536, 639: 3113, 3112}, + {1114, 1114, 6: 1114, 9: 1114, 218: 1114, 228: 1114, 1114, 231: 1114, 1114, 1114, 1114, 241: 1114}, + {1112, 1112, 6: 1112, 9: 1112, 218: 1112, 228: 1112, 1112, 231: 1112, 1112, 1112, 1112, 241: 1112}, + {1111, 1111, 6: 1111, 9: 1111, 218: 1111, 228: 1111, 1111, 231: 1111, 1111, 1111, 1111, 241: 1111}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 3118, 376: 3117, 378: 1537, 1538, 1536}, + // 1685 + {1109, 1109, 6: 1109, 9: 1109, 218: 1109, 228: 1109, 1109, 231: 1109, 1109, 1109, 1109, 241: 1109}, + {1110, 1110, 6: 1110, 9: 1110, 218: 1110, 228: 1110, 1110, 231: 1110, 1110, 1110, 1110, 241: 1110}, + {1108, 1108, 6: 1108, 9: 1108, 218: 1108, 228: 1108, 1108, 231: 1108, 1108, 1108, 1108, 241: 1108}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 258: 3120, 376: 3121, 378: 1537, 1538, 1536}, + {1117, 1117, 6: 1117, 9: 1117, 218: 1117, 228: 1117, 1117, 231: 1117, 1117, 1117, 1117, 241: 1117}, + // 1690 + {799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 218: 799, 799, 799, 799, 224: 799, 799, 799, 228: 799, 799, 231: 799, 799, 799, 799, 799, 799, 799, 799, 799, 241: 799, 243: 799, 249: 799, 257: 799, 799, 277: 799, 279: 3122, 799, 799, 799, 799, 799, 799, 799, 799, 289: 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 799, 363: 799, 386: 799, 799}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 258: 3123, 376: 2592, 378: 1537, 1538, 1536}, + {1116, 1116, 6: 1116, 9: 1116, 218: 1116, 228: 1116, 1116, 231: 1116, 1116, 1116, 1116, 241: 1116}, + {1115, 1115, 6: 1115, 9: 1115, 218: 1115, 228: 1115, 1115, 231: 1115, 1115, 1115, 1115, 241: 1115}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3126, 378: 1537, 1538, 1536}, + // 1695 + {588, 588}, + {592, 592, 242: 3128}, + {307: 2113, 436: 3130, 839: 3129}, + {591, 591, 6: 3131}, + {590, 590, 6: 590}, + // 1700 + {307: 2113, 436: 3132}, + {589, 589, 6: 589}, + {241: 3134}, + {219: 3136, 307: 2113, 436: 3137, 807: 3135}, + {595, 595}, + // 1705 + {594, 594}, + {593, 593}, + {2: 868, 868, 868, 868, 7: 868, 868, 10: 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 497: 3139, 652: 3140}, + {2: 867, 867, 867, 867, 7: 867, 867, 10: 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3141}, + // 1710 + {75: 3147, 217: 3142, 246: 3146, 310: 3148, 381: 1457, 469: 3144, 1458, 1459, 1460, 475: 1463, 477: 1462, 3145, 600: 3143, 651: 3149}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 1347, 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 1457, 464: 1815, 469: 3169, 1458, 1459, 1460, 505: 1816, 611: 3168}, + {217: 3159, 594: 3158, 714: 3157}, + {860, 860, 218: 860, 229: 431}, + {859, 859, 218: 859}, + // 1715 + {845, 845, 1622, 1541, 1575, 1542, 845, 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 218: 845, 376: 1814, 378: 1537, 1538, 1536, 464: 3151, 613: 3152, 737: 3150}, + {217: 857}, + {217: 856}, + {840, 840}, + {858, 858, 6: 3155, 218: 858}, + // 1720 + {243: 3153}, + {844, 844, 6: 844, 218: 844}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3154}, + {846, 846, 6: 846, 218: 846, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3151, 613: 3156}, + // 1725 + {843, 843, 6: 843, 218: 843}, + {862, 862, 6: 3166, 218: 862}, + {855, 855, 6: 855, 218: 855}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 852, 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2966, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2965, 527: 3162, 840: 3161, 3160}, + {9: 3165}, + // 1730 + {6: 3163, 9: 851}, + {6: 849, 9: 849}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2966, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 2965, 527: 3164}, + {6: 850, 9: 850}, + {853, 853, 6: 853, 218: 853}, + // 1735 + {217: 3159, 594: 3167}, + {854, 854, 6: 854, 218: 854}, + {9: 3171}, + {9: 3170}, + {861, 861, 218: 861, 229: 430}, + // 1740 + {75: 3147, 217: 3174, 310: 3148, 381: 1457, 469: 3173, 1458, 1459, 1460, 475: 1463, 477: 1462, 3175, 600: 3172}, + {217: 3159, 594: 3158, 714: 3178}, + {865, 865, 218: 865, 229: 431}, + {381: 1457, 469: 3176, 1458, 1459, 1460}, + {863, 863, 218: 863}, + // 1745 + {9: 3177}, + {864, 864, 218: 864, 229: 430}, + {866, 866, 6: 3166, 218: 866}, + {2: 1098, 1098, 1098, 1098, 7: 1098, 1098, 10: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 377: 1932, 497: 1098, 557: 3180}, + {2: 868, 868, 868, 868, 7: 868, 868, 10: 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 497: 3139, 652: 3181}, + // 1750 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3182}, + {75: 3147, 217: 3142, 246: 3146, 310: 3148, 381: 1457, 469: 3144, 1458, 1459, 1460, 475: 1463, 477: 1462, 3145, 600: 3143, 651: 3183}, + {842, 842, 218: 3185, 789: 3184}, + {869, 869}, + {121: 3186}, + // 1755 + {370: 3187}, + {479: 3188}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 2755, 554: 2756, 571: 3189}, + {841, 841, 6: 2758}, + {1185, 1185, 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3204}, + // 1760 + {1183, 1183}, + {1041, 1041, 1041, 1041, 1041, 1041, 7: 1041, 1041, 10: 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 243: 3201, 279: 1041}, + {217: 2558, 255: 1451, 301: 1450, 381: 1457, 469: 3194, 1458, 1459, 1460, 475: 1463, 477: 1462, 3199, 1516, 486: 1443, 514: 3195, 519: 3197, 3198, 523: 3196, 576: 3200}, + {249, 249, 229: 431}, + {248, 248}, + // 1765 + {247, 247}, + {246, 246}, + {245, 245}, + {244, 244}, + {1181, 1181}, + // 1770 + {219: 3202}, + {217: 2558, 255: 1451, 301: 1450, 381: 1457, 469: 3194, 1458, 1459, 1460, 475: 1463, 477: 1462, 3199, 1516, 486: 1443, 514: 3195, 519: 3197, 3198, 523: 3196, 576: 3203}, + {1182, 1182}, + {1184, 1184}, + {1190, 1190}, + // 1775 + {243: 3213}, + {255, 255, 229: 431}, + {254, 254}, + {253, 253}, + {252, 252}, + // 1780 + {251, 251}, + {250, 250}, + {219: 3214}, + {217: 2558, 255: 1451, 301: 1450, 381: 1457, 469: 3207, 1458, 1459, 1460, 475: 1463, 477: 1462, 3212, 1516, 486: 1443, 514: 3208, 519: 3210, 3211, 523: 3209, 707: 3215}, + {1189, 1189}, + // 1785 + {2: 1207, 1207, 1207, 1207, 7: 1207, 1207, 10: 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 1207, 302: 1207}, + {2: 1102, 1102, 1102, 1102, 7: 1102, 1102, 10: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 302: 3243, 580: 3248}, + {2: 1102, 1102, 1102, 1102, 7: 1102, 1102, 10: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 302: 3243, 580: 3242}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 302: 3235, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 3234}, + {302: 3231}, + // 1790 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 302: 3225, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 3226, 712: 3224}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3223}, + {1199, 1199}, + {1201, 1201, 6: 3229}, + {311: 3227}, + // 1795 + {387, 387, 6: 387}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 3226, 712: 3228}, + {1200, 1200, 6: 3229}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 3230}, + {386, 386, 6: 386}, + // 1800 + {311: 3232}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 3233}, + {1202, 1202, 6: 2817}, + {1198, 1198, 6: 2817, 395: 3240, 3239, 593: 3241}, + {311: 3236}, + // 1805 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 3237}, + {1198, 1198, 6: 2817, 395: 3240, 3239, 593: 3238}, + {1203, 1203}, + {1197, 1197, 6: 1197}, + {1196, 1196, 6: 1196}, + // 1810 + {1204, 1204}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3245, 378: 1537, 1538, 1536}, + {311: 3244}, + {2: 1101, 1101, 1101, 1101, 7: 1101, 1101, 10: 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 1101, 219: 1101, 300: 1101}, + {218: 3246}, + // 1815 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3247}, + {1205, 1205}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1924, 378: 1537, 1538, 1536, 542: 3249}, + {1206, 1206}, + {2: 605, 605, 605, 605, 7: 605, 605, 10: 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, 241: 605, 377: 605, 482: 1930, 1929, 1928, 551: 3251}, + // 1820 + {2: 597, 597, 597, 597, 7: 597, 597, 10: 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 3253, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 241: 597, 377: 597, 809: 3252}, + {2: 1098, 1098, 1098, 1098, 7: 1098, 1098, 10: 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 241: 1098, 377: 1932, 557: 3254}, + {2: 596, 596, 596, 596, 7: 596, 596, 10: 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 241: 596, 377: 596}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 241: 3255, 376: 1751, 378: 1537, 1538, 1536, 459: 2810, 503: 3256}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3260, 503: 3261}, + // 1825 + {6: 2817, 241: 3257}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 1943, 516: 1934, 537: 3258}, + {104, 104, 6: 2719, 240: 2760, 524: 2761, 3259}, + {1209, 1209}, + {489, 489, 6: 599, 233: 489, 489, 240: 489, 242: 599, 377: 2726, 392: 2727, 2725, 582: 2729, 2728, 649: 2730, 3265}, + // 1830 + {6: 2817, 242: 3262}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1941, 303: 1937, 376: 1751, 378: 1537, 1538, 1536, 459: 1940, 489: 1939, 1938, 1943, 516: 1934, 537: 3263}, + {104, 104, 6: 2719, 240: 2760, 524: 2761, 3264}, + {1208, 1208}, + {104, 104, 233: 104, 104, 240: 2760, 524: 2761, 3266}, + // 1835 + {817, 817, 233: 817, 2301, 498: 2302, 3267}, + {471, 471, 233: 2764, 656: 3268}, + {1210, 1210}, + {1211, 1211, 6: 2300}, + {388: 3751}, + // 1840 + {388: 1285}, + {2: 1100, 1100, 1100, 1100, 7: 1100, 1100, 10: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 302: 3277, 581: 3738}, + {2: 1100, 1100, 1100, 1100, 7: 1100, 1100, 10: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 302: 3277, 581: 3318}, + {22: 1228, 38: 1228, 51: 3284, 391: 1228, 844: 3283}, + {255: 3282}, + // 1845 + {2: 1100, 1100, 1100, 1100, 7: 1100, 1100, 10: 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 219: 1100, 300: 1100, 302: 3277, 581: 3278}, + {220: 3280}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 1872, 553: 1873, 568: 3279}, + {100, 100, 6: 1875}, + {311: 3281}, + // 1850 + {2: 1099, 1099, 1099, 1099, 7: 1099, 1099, 10: 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 1099, 219: 1099, 300: 1099}, + {22: 1229, 38: 1229, 51: 1229, 391: 1229}, + {22: 1224, 38: 3290, 391: 1224, 846: 3289}, + {243: 3285}, + {144: 3287, 167: 3288, 175: 3286}, + // 1855 + {22: 1227, 38: 1227, 391: 1227}, + {22: 1226, 38: 1226, 391: 1226}, + {22: 1225, 38: 1225, 391: 1225}, + {22: 1222, 391: 3294, 849: 3293}, + {243: 3291}, + // 1860 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 3292}, + {22: 1223, 391: 1223}, + {22: 3298}, + {155: 3295}, + {38: 3296, 134: 3297}, + // 1865 + {22: 1221}, + {22: 1220}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3300, 848: 3299}, + {217: 3302, 221: 1218, 847: 3301}, + {217: 1219, 221: 1219}, + // 1870 + {221: 3308}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3304, 378: 1537, 1538, 1536, 733: 3303}, + {6: 3306, 9: 3305}, + {6: 1216, 9: 1216}, + {221: 1217}, + // 1875 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3307, 378: 1537, 1538, 1536}, + {6: 1215, 9: 1215}, + {381: 1457, 469: 3309, 1458, 1459, 1460}, + {1214, 1214, 228: 3311, 845: 3310}, + {1231, 1231}, + // 1880 + {59: 3313, 113: 3312}, + {373: 3316}, + {373: 3314}, + {561: 3315}, + {1212, 1212}, + // 1885 + {561: 3317}, + {1213, 1213}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3319}, + {235, 235, 235, 235, 7: 235, 235, 10: 235, 235, 235, 14: 235, 235, 235, 235, 235, 235, 235, 235, 217: 3323, 221: 235, 227: 235, 249: 235, 255: 235, 257: 3322, 377: 235, 381: 235, 235, 235, 235, 235, 777: 3321, 828: 3320}, + {210, 210, 3586, 3585, 7: 1271, 3592, 10: 3583, 3588, 3590, 14: 3589, 3587, 3591, 3595, 3593, 3594, 3602, 3597, 217: 210, 221: 210, 227: 3582, 249: 1271, 255: 210, 377: 210, 381: 210, 1271, 210, 3599, 3598, 508: 3584, 532: 3596, 536: 3601, 596: 3600, 741: 3581}, + // 1890 + {1272, 1272}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3580}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 257: 3326, 370: 1378, 1378, 1378, 3330, 376: 1814, 378: 1537, 1538, 1536, 388: 1378, 401: 1378, 1378, 464: 3325, 513: 3328, 573: 3329, 3324, 3327, 700: 3331, 827: 3332}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 370: 1377, 1377, 1377, 376: 3579, 378: 1537, 1538, 1536, 388: 1377, 401: 1377, 1377, 699: 3578}, + {28: 3471, 56: 3468, 3467, 61: 3470, 66: 3455, 103: 3469, 108: 3445, 3439, 3438, 123: 3453, 146: 3447, 168: 3463, 246: 3454, 288: 3449, 308: 154, 403: 3440, 3436, 3430, 407: 3456, 410: 3437, 3459, 413: 3444, 3442, 3431, 3432, 3433, 3434, 3435, 3466, 3461, 3465, 3460, 3429, 3464, 3441, 3457, 3443, 3428, 3458, 3427, 3462, 3450, 727: 3426, 3451, 3423, 745: 3421, 758: 3424, 3425, 770: 3422, 784: 3446, 787: 3419, 824: 3420, 834: 3452, 837: 3418, 842: 3448}, + // 1895 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3416}, + {370: 2746, 3339, 3342, 388: 2747, 401: 3343, 3340, 510: 3341, 739: 3344}, + {6: 240, 9: 240}, + {6: 239, 9: 239}, + {217: 3336}, + // 1900 + {6: 237, 9: 237}, + {6: 3333, 9: 3334}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 370: 1378, 1378, 1378, 3330, 376: 1814, 378: 1537, 1538, 1536, 388: 1378, 401: 1378, 1378, 464: 3325, 513: 3328, 573: 3329, 3324, 3327, 700: 3335}, + {234, 234, 234, 234, 7: 234, 234, 10: 234, 234, 234, 14: 234, 234, 234, 234, 234, 234, 234, 234, 217: 234, 221: 234, 227: 234, 249: 234, 255: 234, 377: 234, 381: 234, 234, 234, 234, 234}, + {6: 236, 9: 236}, + // 1905 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3337}, + {9: 3338, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {6: 238, 9: 238}, + {370: 3409}, + {370: 2746, 388: 2747, 510: 3403}, + // 1910 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1096, 242: 1096, 376: 3347, 378: 1537, 1538, 1536, 547: 3397}, + {2: 1389, 1389, 1389, 1389, 7: 1389, 1389, 10: 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 242: 1389, 370: 2746, 388: 2747, 510: 3377, 773: 3378}, + {370: 3345}, + {241, 241, 6: 241, 9: 241}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1096, 376: 3347, 378: 1537, 1538, 1536, 547: 3346}, + // 1915 + {217: 3348}, + {217: 1095, 242: 1095}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3349}, + {6: 3355, 9: 3354}, + {6: 134, 9: 134, 217: 2506, 262: 134, 134, 473: 2507, 487: 3352}, + // 1920 + {6: 1283, 9: 1283}, + {6: 820, 9: 820, 262: 2146, 2145, 675: 3353}, + {6: 1284, 9: 1284}, + {374: 3358, 592: 3357}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3356}, + // 1925 + {6: 1282, 9: 1282}, + {1315, 1315, 6: 1315, 9: 1315}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3359}, + {217: 3360}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3361}, + // 1930 + {6: 3355, 9: 3362}, + {1313, 1313, 1313, 1313, 1313, 1313, 1313, 9: 1313, 218: 3364, 220: 1313, 1313, 227: 1313, 230: 1313, 370: 1313, 1313, 1313, 1313, 1313, 1313, 788: 3363}, + {1311, 1311, 1311, 1311, 1311, 1311, 1311, 9: 1311, 218: 3374, 220: 1311, 1311, 227: 1311, 230: 1311, 370: 1311, 1311, 1311, 1311, 1311, 1311, 790: 3373}, + {486: 3365}, + {95: 3370, 246: 3369, 395: 3368, 3367, 685: 3366}, + // 1935 + {1312, 1312, 1312, 1312, 1312, 1312, 1312, 9: 1312, 218: 1312, 220: 1312, 1312, 227: 1312, 230: 1312, 370: 1312, 1312, 1312, 1312, 1312, 1312}, + {1309, 1309, 1309, 1309, 1309, 1309, 1309, 9: 1309, 218: 1309, 220: 1309, 1309, 227: 1309, 230: 1309, 370: 1309, 1309, 1309, 1309, 1309, 1309}, + {1308, 1308, 1308, 1308, 1308, 1308, 1308, 9: 1308, 218: 1308, 220: 1308, 1308, 227: 1308, 230: 1308, 370: 1308, 1308, 1308, 1308, 1308, 1308}, + {230: 3372}, + {106: 3371}, + // 1940 + {1306, 1306, 1306, 1306, 1306, 1306, 1306, 9: 1306, 218: 1306, 220: 1306, 1306, 227: 1306, 230: 1306, 370: 1306, 1306, 1306, 1306, 1306, 1306}, + {1307, 1307, 1307, 1307, 1307, 1307, 1307, 9: 1307, 218: 1307, 220: 1307, 1307, 227: 1307, 230: 1307, 370: 1307, 1307, 1307, 1307, 1307, 1307}, + {1314, 1314, 1314, 1314, 1314, 1314, 1314, 9: 1314, 218: 1314, 220: 1314, 1314, 227: 1314, 230: 1314, 370: 1314, 1314, 1314, 1314, 1314, 1314}, + {479: 3375}, + {95: 3370, 246: 3369, 395: 3368, 3367, 685: 3376}, + // 1945 + {1310, 1310, 1310, 1310, 1310, 1310, 1310, 9: 1310, 218: 1310, 220: 1310, 1310, 227: 1310, 230: 1310, 370: 1310, 1310, 1310, 1310, 1310, 1310}, + {2: 1388, 1388, 1388, 1388, 7: 1388, 1388, 10: 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 1388, 242: 1388}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1096, 242: 1096, 376: 3347, 378: 1537, 1538, 1536, 547: 3379}, + {217: 1087, 242: 3381, 501: 3382, 559: 3380}, + {217: 3385}, + // 1950 + {65: 3384, 111: 3383}, + {217: 1086, 1086}, + {1089, 1089, 1089, 6: 1089, 8: 1089, 1089, 217: 1089, 1089, 231: 1089, 242: 1089}, + {1088, 1088, 1088, 6: 1088, 8: 1088, 1088, 217: 1088, 1088, 231: 1088, 242: 1088}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3386}, + // 1955 + {6: 3355, 9: 3387}, + {1094, 1094, 1094, 6: 1094, 8: 1094, 1094, 242: 1094, 549: 3388}, + {1316, 1316, 3392, 6: 1316, 8: 3390, 1316, 242: 3381, 501: 3391, 548: 3389}, + {1093, 1093, 1093, 6: 1093, 8: 1093, 1093, 231: 1093, 242: 1093}, + {243: 3394, 256: 1193, 468: 3395}, + // 1960 + {1091, 1091, 1091, 6: 1091, 8: 1091, 1091, 231: 1091, 242: 1091}, + {219: 3393}, + {1090, 1090, 1090, 6: 1090, 8: 1090, 1090, 231: 1090, 242: 1090}, + {2: 1192, 1192, 1192, 1192, 7: 1192, 1192, 10: 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 219: 1192, 227: 1192, 256: 1192, 288: 1192}, + {256: 1526, 461: 2508, 476: 3396}, + // 1965 + {1092, 1092, 1092, 6: 1092, 8: 1092, 1092, 231: 1092, 242: 1092}, + {217: 1087, 242: 3381, 501: 3382, 559: 3398}, + {217: 3399}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3400}, + {6: 3355, 9: 3401}, + // 1970 + {1094, 1094, 1094, 6: 1094, 8: 1094, 1094, 242: 1094, 549: 3402}, + {1317, 1317, 3392, 6: 1317, 8: 3390, 1317, 242: 3381, 501: 3391, 548: 3389}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1096, 376: 3347, 378: 1537, 1538, 1536, 547: 3404}, + {217: 3405}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3406}, + // 1975 + {6: 3355, 9: 3407}, + {1094, 1094, 1094, 6: 1094, 8: 1094, 1094, 242: 1094, 549: 3408}, + {1318, 1318, 3392, 6: 1318, 8: 3390, 1318, 242: 3381, 501: 3391, 548: 3389}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 1096, 242: 1096, 376: 3347, 378: 1537, 1538, 1536, 547: 3410}, + {217: 1087, 242: 3381, 501: 3382, 559: 3411}, + // 1980 + {217: 3412}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3413}, + {6: 3355, 9: 3414}, + {1094, 1094, 1094, 6: 1094, 8: 1094, 1094, 242: 1094, 549: 3415}, + {1319, 1319, 3392, 6: 1319, 8: 3390, 1319, 242: 3381, 501: 3391, 548: 3389}, + // 1985 + {9: 3417}, + {1232, 1232}, + {1321, 1321, 3535, 3530, 1321, 1321, 1321, 9: 1321, 218: 3534, 220: 3528, 1328, 227: 3533, 230: 3529, 370: 1342, 3527, 3532, 3536, 3358, 3539, 592: 3538, 612: 3540, 645: 3537, 682: 3531, 735: 3541, 3526}, + {196, 196, 196, 196, 196, 196, 196, 9: 196, 218: 196, 220: 196, 196, 227: 196, 230: 196, 370: 196, 196, 196, 196, 196, 196}, + {195, 195, 195, 195, 195, 195, 195, 9: 195, 218: 195, 220: 195, 195, 227: 195, 230: 195, 370: 195, 195, 195, 195, 195, 195}, + // 1990 + {194, 194, 194, 194, 194, 194, 194, 9: 194, 218: 194, 220: 194, 194, 227: 194, 230: 194, 370: 194, 194, 194, 194, 194, 194}, + {134, 134, 134, 134, 134, 134, 134, 9: 134, 13: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 460: 134, 462: 134, 473: 2507, 487: 3524}, + {129, 129, 129, 129, 129, 129, 129, 9: 129, 13: 129, 218: 129, 220: 129, 129, 227: 129, 230: 129, 370: 129, 129, 129, 129, 129, 129, 460: 129, 462: 129, 546: 3523}, + {127, 127, 127, 127, 127, 127, 127, 9: 127, 13: 127, 217: 2512, 127, 220: 127, 127, 227: 127, 230: 127, 370: 127, 127, 127, 127, 127, 127, 460: 127, 462: 127, 473: 2513, 577: 3521, 589: 2514}, + {127, 127, 127, 127, 127, 127, 127, 9: 127, 13: 127, 217: 2512, 127, 220: 127, 127, 227: 127, 230: 127, 370: 127, 127, 127, 127, 127, 127, 460: 127, 462: 127, 473: 2513, 577: 3519, 589: 2514}, + // 1995 + {134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 473: 2507, 487: 3518}, + {188, 188, 188, 188, 188, 188, 188, 9: 188, 13: 188, 217: 188, 188, 220: 188, 188, 227: 188, 230: 188, 370: 188, 188, 188, 188, 188, 188, 460: 188, 462: 188}, + {187, 187, 187, 187, 187, 187, 187, 9: 187, 13: 187, 217: 187, 187, 220: 187, 187, 227: 187, 230: 187, 370: 187, 187, 187, 187, 187, 187, 460: 187, 462: 187}, + {186, 186, 186, 186, 186, 186, 186, 9: 186, 13: 186, 217: 186, 186, 220: 186, 186, 227: 186, 230: 186, 370: 186, 186, 186, 186, 186, 186, 460: 186, 462: 186}, + {185, 185, 185, 185, 185, 185, 185, 9: 185, 13: 185, 217: 185, 185, 220: 185, 185, 227: 185, 230: 185, 370: 185, 185, 185, 185, 185, 185, 460: 185, 462: 185}, + // 2000 + {184, 184, 184, 184, 184, 184, 184, 9: 184, 13: 184, 217: 184, 184, 220: 184, 184, 227: 184, 230: 184, 370: 184, 184, 184, 184, 184, 184, 460: 184, 462: 184}, + {183, 183, 183, 183, 183, 183, 183, 9: 183, 13: 183, 217: 183, 183, 220: 183, 183, 227: 183, 230: 183, 370: 183, 183, 183, 183, 183, 183, 460: 183, 462: 183}, + {182, 182, 182, 182, 182, 182, 182, 9: 182, 13: 182, 217: 182, 182, 220: 182, 182, 227: 182, 230: 182, 370: 182, 182, 182, 182, 182, 182, 460: 182, 462: 182}, + {181, 181, 181, 181, 181, 181, 181, 9: 181, 13: 181, 217: 181, 181, 220: 181, 181, 227: 181, 230: 181, 370: 181, 181, 181, 181, 181, 181, 460: 181, 462: 181}, + {180, 180, 180, 180, 180, 180, 180, 9: 180, 13: 180, 217: 180, 180, 220: 180, 180, 227: 180, 230: 180, 370: 180, 180, 180, 180, 180, 180, 460: 180, 462: 180}, + // 2005 + {179, 179, 179, 179, 179, 179, 179, 9: 179, 13: 179, 217: 179, 179, 220: 179, 179, 227: 179, 230: 179, 370: 179, 179, 179, 179, 179, 179, 460: 179, 462: 179}, + {178, 178, 178, 178, 178, 178, 178, 9: 178, 13: 178, 217: 178, 178, 220: 178, 178, 227: 178, 230: 178, 370: 178, 178, 178, 178, 178, 178, 460: 178, 462: 178}, + {177, 177, 177, 177, 177, 177, 177, 9: 177, 13: 177, 218: 177, 220: 177, 177, 227: 177, 230: 177, 370: 177, 177, 177, 177, 177, 177, 460: 177, 462: 177}, + {176, 176, 176, 176, 176, 176, 176, 9: 176, 13: 176, 218: 176, 220: 176, 176, 227: 176, 230: 176, 370: 176, 176, 176, 176, 176, 176, 460: 176, 462: 176}, + {172, 172, 172, 172, 172, 172, 172, 9: 172, 13: 172, 217: 172, 172, 220: 172, 172, 227: 172, 230: 172, 370: 172, 172, 172, 172, 172, 172, 460: 172, 462: 172}, + // 2010 + {171, 171, 171, 171, 171, 171, 171, 9: 171, 13: 171, 217: 171, 171, 220: 171, 171, 227: 171, 230: 171, 370: 171, 171, 171, 171, 171, 171, 460: 171, 462: 171}, + {170, 170, 170, 170, 170, 170, 170, 9: 170, 13: 170, 217: 170, 170, 220: 170, 170, 227: 170, 230: 170, 370: 170, 170, 170, 170, 170, 170, 460: 170, 462: 170}, + {169, 169, 169, 169, 169, 169, 169, 9: 169, 13: 169, 217: 169, 169, 220: 169, 169, 227: 169, 230: 169, 370: 169, 169, 169, 169, 169, 169, 460: 169, 462: 169}, + {168, 168, 168, 168, 168, 168, 168, 9: 168, 13: 168, 217: 168, 168, 220: 168, 168, 227: 168, 230: 168, 370: 168, 168, 168, 168, 168, 168, 460: 168, 462: 168, 806: 3517}, + {166, 166, 166, 166, 166, 166, 166, 9: 166, 217: 166, 166, 220: 166, 166, 227: 166, 230: 166, 370: 166, 166, 166, 166, 166, 166}, + // 2015 + {308: 3511}, + {308: 153, 382: 3506, 407: 3507}, + {217: 2506, 473: 3503}, + {134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 473: 2507, 487: 3502}, + {217: 2506, 473: 3501}, + // 2020 + {159, 159, 159, 159, 159, 159, 159, 9: 159, 218: 159, 220: 159, 159, 227: 159, 230: 159, 370: 159, 159, 159, 159, 159, 159}, + {121, 121, 121, 121, 121, 121, 121, 2525, 9: 121, 218: 121, 220: 121, 121, 227: 121, 230: 121, 249: 121, 288: 2522, 370: 121, 121, 121, 121, 121, 121, 382: 2524, 481: 2523, 531: 3499}, + {217: 3494}, + {217: 3484}, + {155, 155, 155, 155, 155, 155, 155, 9: 155, 218: 155, 220: 155, 155, 227: 155, 230: 155, 370: 155, 155, 155, 155, 155, 155}, + // 2025 + {217: 151}, + {217: 150}, + {149, 149, 149, 149, 149, 149, 149, 9: 149, 218: 149, 220: 149, 149, 227: 149, 230: 149, 370: 149, 149, 149, 149, 149, 149}, + {134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 473: 2507, 487: 3483}, + {147, 147, 147, 147, 147, 147, 147, 9: 147, 218: 147, 220: 147, 147, 227: 147, 230: 147, 370: 147, 147, 147, 147, 147, 147}, + // 2030 + {146, 146, 146, 146, 146, 146, 146, 9: 146, 218: 146, 220: 146, 146, 227: 146, 230: 146, 370: 146, 146, 146, 146, 146, 146}, + {145, 145, 145, 145, 145, 145, 145, 145, 9: 145, 218: 145, 220: 145, 145, 227: 145, 230: 145, 249: 145, 288: 145, 370: 145, 145, 145, 145, 145, 145, 382: 145}, + {134, 134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 249: 134, 288: 134, 370: 134, 134, 134, 134, 134, 134, 382: 134, 473: 2507, 487: 3482}, + {143, 143, 143, 143, 143, 143, 143, 143, 9: 143, 218: 143, 220: 143, 143, 227: 143, 230: 143, 249: 143, 288: 143, 370: 143, 143, 143, 143, 143, 143, 382: 143}, + {142, 142, 142, 142, 142, 142, 142, 142, 9: 142, 218: 142, 220: 142, 142, 227: 142, 230: 142, 249: 142, 288: 142, 370: 142, 142, 142, 142, 142, 142, 382: 142}, + // 2035 + {407: 3481}, + {140, 140, 140, 140, 140, 140, 140, 9: 140, 218: 140, 220: 140, 140, 227: 140, 230: 140, 370: 140, 140, 140, 140, 140, 140}, + {134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 473: 2507, 487: 3480}, + {134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 473: 2507, 487: 3479}, + {134, 134, 134, 134, 134, 134, 134, 9: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 473: 2507, 487: 3478}, + // 2040 + {134, 134, 134, 134, 134, 134, 134, 9: 134, 13: 134, 217: 2506, 134, 220: 134, 134, 227: 134, 230: 134, 370: 134, 134, 134, 134, 134, 134, 460: 134, 462: 134, 473: 2507, 487: 3472}, + {129, 129, 129, 129, 129, 129, 129, 9: 129, 13: 129, 218: 129, 220: 129, 129, 227: 129, 230: 129, 370: 129, 129, 129, 129, 129, 129, 460: 129, 462: 129, 546: 3473}, + {136, 136, 136, 136, 136, 136, 136, 9: 136, 13: 3475, 218: 136, 220: 136, 136, 227: 136, 230: 136, 370: 136, 136, 136, 136, 136, 136, 460: 3474, 462: 3476, 545: 3477}, + {132, 132, 132, 132, 132, 132, 132, 9: 132, 13: 132, 218: 132, 220: 132, 132, 227: 132, 230: 132, 370: 132, 132, 132, 132, 132, 132, 460: 132, 462: 132}, + {131, 131, 131, 131, 131, 131, 131, 9: 131, 13: 131, 218: 131, 220: 131, 131, 227: 131, 230: 131, 370: 131, 131, 131, 131, 131, 131, 460: 131, 462: 131}, + // 2045 + {130, 130, 130, 130, 130, 130, 130, 9: 130, 13: 130, 218: 130, 220: 130, 130, 227: 130, 230: 130, 370: 130, 130, 130, 130, 130, 130, 460: 130, 462: 130}, + {128, 128, 128, 128, 128, 128, 128, 9: 128, 13: 128, 218: 128, 220: 128, 128, 227: 128, 230: 128, 370: 128, 128, 128, 128, 128, 128, 460: 128, 462: 128}, + {137, 137, 137, 137, 137, 137, 137, 9: 137, 218: 137, 220: 137, 137, 227: 137, 230: 137, 370: 137, 137, 137, 137, 137, 137}, + {138, 138, 138, 138, 138, 138, 138, 9: 138, 218: 138, 220: 138, 138, 227: 138, 230: 138, 370: 138, 138, 138, 138, 138, 138}, + {139, 139, 139, 139, 139, 139, 139, 9: 139, 218: 139, 220: 139, 139, 227: 139, 230: 139, 370: 139, 139, 139, 139, 139, 139}, + // 2050 + {141, 141, 141, 141, 141, 141, 141, 141, 9: 141, 218: 141, 220: 141, 141, 227: 141, 230: 141, 249: 141, 288: 141, 370: 141, 141, 141, 141, 141, 141, 382: 141}, + {144, 144, 144, 144, 144, 144, 144, 144, 9: 144, 218: 144, 220: 144, 144, 227: 144, 230: 144, 249: 144, 288: 144, 370: 144, 144, 144, 144, 144, 144, 382: 144}, + {148, 148, 148, 148, 148, 148, 148, 9: 148, 218: 148, 220: 148, 148, 227: 148, 230: 148, 370: 148, 148, 148, 148, 148, 148}, + {219: 3486, 697: 3485}, + {6: 3488, 9: 3487}, + // 2055 + {6: 112, 9: 112}, + {118, 118, 118, 118, 118, 118, 118, 2525, 9: 118, 218: 118, 220: 118, 118, 227: 118, 230: 118, 249: 118, 370: 118, 118, 118, 118, 118, 118, 382: 2524, 481: 2531, 588: 3490}, + {219: 3489}, + {6: 111, 9: 111}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3491}, + // 2060 + {156, 156, 156, 156, 156, 156, 156, 9: 156, 218: 156, 220: 156, 156, 227: 156, 230: 156, 370: 156, 156, 156, 156, 156, 156}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 3493}, + {113, 113, 113, 113, 113, 113, 113, 9: 113, 218: 113, 220: 113, 113, 227: 113, 230: 113, 370: 113, 113, 113, 113, 113, 113}, + {219: 3486, 697: 3495}, + {6: 3488, 9: 3496}, + // 2065 + {118, 118, 118, 118, 118, 118, 118, 2525, 9: 118, 218: 118, 220: 118, 118, 227: 118, 230: 118, 249: 118, 370: 118, 118, 118, 118, 118, 118, 382: 2524, 481: 2531, 588: 3497}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3498}, + {157, 157, 157, 157, 157, 157, 157, 9: 157, 218: 157, 220: 157, 157, 227: 157, 230: 157, 370: 157, 157, 157, 157, 157, 157}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3500}, + {158, 158, 158, 158, 158, 158, 158, 9: 158, 218: 158, 220: 158, 158, 227: 158, 230: 158, 370: 158, 158, 158, 158, 158, 158}, + // 2070 + {160, 160, 160, 160, 160, 160, 160, 9: 160, 218: 160, 220: 160, 160, 227: 160, 230: 160, 370: 160, 160, 160, 160, 160, 160}, + {161, 161, 161, 161, 161, 161, 161, 9: 161, 218: 161, 220: 161, 161, 227: 161, 230: 161, 370: 161, 161, 161, 161, 161, 161}, + {121, 121, 121, 121, 121, 121, 121, 2525, 9: 121, 218: 121, 220: 121, 121, 227: 121, 230: 121, 249: 121, 288: 2522, 370: 121, 121, 121, 121, 121, 121, 382: 2524, 481: 2523, 531: 3504}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3505}, + {162, 162, 162, 162, 162, 162, 162, 9: 162, 218: 162, 220: 162, 162, 227: 162, 230: 162, 370: 162, 162, 162, 162, 162, 162}, + // 2075 + {217: 2506, 473: 3508}, + {217: 152}, + {121, 121, 121, 121, 121, 121, 121, 2525, 9: 121, 218: 121, 220: 121, 121, 227: 121, 230: 121, 249: 121, 288: 2522, 370: 121, 121, 121, 121, 121, 121, 382: 2524, 481: 2523, 531: 3509}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3510}, + {163, 163, 163, 163, 163, 163, 163, 9: 163, 218: 163, 220: 163, 163, 227: 163, 230: 163, 370: 163, 163, 163, 163, 163, 163}, + // 2080 + {121, 121, 121, 121, 121, 121, 121, 2525, 9: 121, 217: 2506, 121, 220: 121, 121, 227: 121, 230: 121, 249: 121, 288: 2522, 370: 121, 121, 121, 121, 121, 121, 382: 2524, 473: 3512, 481: 2523, 531: 3513}, + {121, 121, 121, 121, 121, 121, 121, 2525, 9: 121, 218: 121, 220: 121, 121, 227: 121, 230: 121, 249: 121, 288: 2522, 370: 121, 121, 121, 121, 121, 121, 382: 2524, 481: 2523, 531: 3515}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3514}, + {164, 164, 164, 164, 164, 164, 164, 9: 164, 218: 164, 220: 164, 164, 227: 164, 230: 164, 370: 164, 164, 164, 164, 164, 164}, + {114, 114, 114, 114, 114, 114, 114, 9: 114, 218: 114, 220: 114, 114, 227: 114, 230: 114, 249: 3492, 370: 114, 114, 114, 114, 114, 114, 511: 3516}, + // 2085 + {165, 165, 165, 165, 165, 165, 165, 9: 165, 218: 165, 220: 165, 165, 227: 165, 230: 165, 370: 165, 165, 165, 165, 165, 165}, + {167, 167, 167, 167, 167, 167, 167, 9: 167, 13: 167, 217: 167, 167, 220: 167, 167, 227: 167, 230: 167, 370: 167, 167, 167, 167, 167, 167, 460: 167, 462: 167}, + {189, 189, 189, 189, 189, 189, 189, 9: 189, 218: 189, 220: 189, 189, 227: 189, 230: 189, 370: 189, 189, 189, 189, 189, 189}, + {129, 129, 129, 129, 129, 129, 129, 9: 129, 13: 129, 218: 129, 220: 129, 129, 227: 129, 230: 129, 370: 129, 129, 129, 129, 129, 129, 460: 129, 462: 129, 546: 3520}, + {190, 190, 190, 190, 190, 190, 190, 9: 190, 13: 3475, 218: 190, 220: 190, 190, 227: 190, 230: 190, 370: 190, 190, 190, 190, 190, 190, 460: 3474, 462: 3476, 545: 3477}, + // 2090 + {129, 129, 129, 129, 129, 129, 129, 9: 129, 13: 129, 218: 129, 220: 129, 129, 227: 129, 230: 129, 370: 129, 129, 129, 129, 129, 129, 460: 129, 462: 129, 546: 3522}, + {191, 191, 191, 191, 191, 191, 191, 9: 191, 13: 3475, 218: 191, 220: 191, 191, 227: 191, 230: 191, 370: 191, 191, 191, 191, 191, 191, 460: 3474, 462: 3476, 545: 3477}, + {192, 192, 192, 192, 192, 192, 192, 9: 192, 13: 3475, 218: 192, 220: 192, 192, 227: 192, 230: 192, 370: 192, 192, 192, 192, 192, 192, 460: 3474, 462: 3476, 545: 3477}, + {129, 129, 129, 129, 129, 129, 129, 9: 129, 13: 129, 218: 129, 220: 129, 129, 227: 129, 230: 129, 370: 129, 129, 129, 129, 129, 129, 460: 129, 462: 129, 546: 3525}, + {193, 193, 193, 193, 193, 193, 193, 9: 193, 13: 3475, 218: 193, 220: 193, 193, 227: 193, 230: 193, 370: 193, 193, 193, 193, 193, 193, 460: 3474, 462: 3476, 545: 3477}, + // 2095 + {1353, 1353, 4: 1353, 1353, 1353, 9: 1353}, + {370: 1341}, + {230: 3577}, + {1339, 1339, 1339, 1339, 1339, 1339, 1339, 9: 1339, 218: 1339, 220: 1339, 1339, 227: 1339, 230: 1339, 370: 1339, 1339, 1339, 1339, 1339, 1339}, + {1338, 1338, 1338, 1338, 1338, 1338, 1338, 9: 1338, 218: 1338, 220: 1338, 1338, 227: 1338, 230: 1338, 370: 1338, 1338, 1338, 1338, 1338, 1338}, + // 2100 + {370: 3576}, + {1336, 1336, 1336, 1336, 1336, 1336, 1336, 9: 1336, 218: 1336, 220: 1336, 1336, 227: 1336, 230: 1336, 370: 3575, 1336, 1336, 1336, 1336, 1336}, + {219: 2012, 224: 3571, 3572, 230: 2003, 256: 2007, 304: 2006, 2005, 312: 2002, 2004, 316: 2011, 3562, 3559, 320: 2010, 3560, 3561, 2009, 437: 3570, 439: 2008, 662: 3557, 3558, 3568, 694: 3569, 747: 3567}, + {479: 3555}, + {219: 3554}, + // 2105 + {217: 3551}, + {221: 3544}, + {1329, 1329, 1329, 1329, 1329, 1329, 1329, 9: 1329, 218: 1329, 220: 1329, 1329, 227: 1329, 230: 1329, 370: 1329, 1329, 1329, 1329, 1329, 1329}, + {107: 3543}, + {1323, 1323, 1323, 1323, 1323, 1323, 1323, 9: 1323, 218: 1323, 220: 1323, 1323, 227: 1323, 230: 1323, 370: 1323, 1323, 1323, 1323, 1323, 1323}, + // 2110 + {1320, 1320, 3535, 3530, 1320, 1320, 1320, 9: 1320, 218: 3534, 220: 3528, 1328, 227: 3533, 230: 3529, 370: 1342, 3527, 3532, 3536, 3358, 3539, 592: 3538, 612: 3542, 645: 3537, 682: 3531}, + {1322, 1322, 1322, 1322, 1322, 1322, 1322, 9: 1322, 218: 1322, 220: 1322, 1322, 227: 1322, 230: 1322, 370: 1322, 1322, 1322, 1322, 1322, 1322}, + {221: 1327}, + {217: 3545}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3546}, + // 2115 + {9: 3547, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {1326, 1326, 1326, 1326, 1326, 1326, 1326, 9: 1326, 218: 1326, 220: 1326, 1326, 227: 1326, 230: 1326, 370: 1326, 1326, 1326, 1326, 1326, 1326, 823: 3550, 850: 3549, 3548}, + {1330, 1330, 1330, 1330, 1330, 1330, 1330, 9: 1330, 218: 1330, 220: 1330, 1330, 227: 1330, 230: 1330, 370: 1330, 1330, 1330, 1330, 1330, 1330}, + {1325, 1325, 1325, 1325, 1325, 1325, 1325, 9: 1325, 218: 1325, 220: 1325, 1325, 227: 1325, 230: 1325, 370: 1325, 1325, 1325, 1325, 1325, 1325}, + {1324, 1324, 1324, 1324, 1324, 1324, 1324, 9: 1324, 218: 1324, 220: 1324, 1324, 227: 1324, 230: 1324, 370: 1324, 1324, 1324, 1324, 1324, 1324}, + // 2120 + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3552}, + {9: 3553, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {1331, 1331, 1331, 1331, 1331, 1331, 1331, 9: 1331, 218: 1331, 220: 1331, 1331, 227: 1331, 230: 1331, 370: 1331, 1331, 1331, 1331, 1331, 1331}, + {1332, 1332, 1332, 1332, 1332, 1332, 1332, 9: 1332, 218: 1332, 220: 1332, 1332, 227: 1332, 230: 1332, 370: 1332, 1332, 1332, 1332, 1332, 1332}, + {317: 3562, 3559, 321: 3560, 3561, 662: 3557, 3558, 3556}, + // 2125 + {1333, 1333, 1333, 1333, 1333, 1333, 1333, 9: 1333, 218: 1333, 220: 1333, 1333, 227: 1333, 230: 1333, 370: 1333, 1333, 1333, 1333, 1333, 1333}, + {1303, 1303, 1303, 1303, 1303, 1303, 1303, 9: 1303, 218: 1303, 220: 1303, 1303, 227: 1303, 230: 1303, 370: 1303, 1303, 1303, 1303, 1303, 1303}, + {217: 3563}, + {1296, 1296, 1296, 1296, 1296, 1296, 1296, 9: 1296, 217: 1300, 1296, 220: 1296, 1296, 227: 1296, 230: 1296, 370: 1296, 1296, 1296, 1296, 1296, 1296}, + {1295, 1295, 1295, 1295, 1295, 1295, 1295, 9: 1295, 217: 1299, 1295, 220: 1295, 1295, 227: 1295, 230: 1295, 370: 1295, 1295, 1295, 1295, 1295, 1295}, + // 2130 + {1294, 1294, 1294, 1294, 1294, 1294, 1294, 9: 1294, 217: 1298, 1294, 220: 1294, 1294, 227: 1294, 230: 1294, 370: 1294, 1294, 1294, 1294, 1294, 1294}, + {217: 1297}, + {9: 3564, 256: 1526, 461: 3565}, + {1302, 1302, 1302, 1302, 1302, 1302, 1302, 9: 1302, 218: 1302, 220: 1302, 1302, 227: 1302, 230: 1302, 370: 1302, 1302, 1302, 1302, 1302, 1302}, + {9: 3566}, + // 2135 + {1301, 1301, 1301, 1301, 1301, 1301, 1301, 9: 1301, 218: 1301, 220: 1301, 1301, 227: 1301, 230: 1301, 370: 1301, 1301, 1301, 1301, 1301, 1301}, + {1334, 1334, 1334, 1334, 1334, 1334, 1334, 9: 1334, 218: 1334, 220: 1334, 1334, 227: 1334, 230: 1334, 370: 1334, 1334, 1334, 1334, 1334, 1334}, + {1305, 1305, 1305, 1305, 1305, 1305, 1305, 9: 1305, 218: 1305, 220: 1305, 1305, 227: 1305, 230: 1305, 370: 1305, 1305, 1305, 1305, 1305, 1305}, + {1304, 1304, 1304, 1304, 1304, 1304, 1304, 9: 1304, 218: 1304, 220: 1304, 1304, 227: 1304, 230: 1304, 370: 1304, 1304, 1304, 1304, 1304, 1304}, + {1293, 1293, 1293, 1293, 1293, 1293, 1293, 9: 1293, 218: 1293, 220: 1293, 1293, 227: 1293, 230: 1293, 370: 1293, 1293, 1293, 1293, 1293, 1293}, + // 2140 + {256: 2156, 304: 2158, 2157, 530: 3574}, + {256: 2156, 304: 2158, 2157, 530: 3573}, + {1291, 1291, 1291, 1291, 1291, 1291, 1291, 9: 1291, 218: 1291, 220: 1291, 1291, 227: 1291, 230: 1291, 370: 1291, 1291, 1291, 1291, 1291, 1291}, + {1292, 1292, 1292, 1292, 1292, 1292, 1292, 9: 1292, 218: 1292, 220: 1292, 1292, 227: 1292, 230: 1292, 370: 1292, 1292, 1292, 1292, 1292, 1292}, + {1335, 1335, 1335, 1335, 1335, 1335, 1335, 9: 1335, 218: 1335, 220: 1335, 1335, 227: 1335, 230: 1335, 370: 1335, 1335, 1335, 1335, 1335, 1335}, + // 2145 + {1337, 1337, 1337, 1337, 1337, 1337, 1337, 9: 1337, 218: 1337, 220: 1337, 1337, 227: 1337, 230: 1337, 370: 1337, 1337, 1337, 1337, 1337, 1337}, + {1340, 1340, 1340, 1340, 1340, 1340, 1340, 9: 1340, 218: 1340, 220: 1340, 1340, 227: 1340, 230: 1340, 370: 1340, 1340, 1340, 1340, 1340, 1340}, + {370: 1376, 1376, 1376, 388: 1376, 401: 1376, 1376}, + {1375, 1375, 6: 1375, 370: 1375, 1375, 1375, 388: 1375, 401: 1375, 1375}, + {1233, 1233}, + // 2150 + {1269, 1269, 217: 1269, 221: 1269, 255: 1269, 377: 1269, 381: 1269, 383: 3653, 805: 3652}, + {7: 1270, 249: 1270, 382: 1270}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 243: 3650, 376: 1780, 378: 1537, 1538, 1536, 466: 3649}, + {7: 2525, 249: 3644, 382: 2524, 481: 3643}, + {243: 3394, 256: 1193, 468: 3641}, + // 2155 + {219: 1193, 243: 3394, 468: 3639}, + {243: 3394, 256: 1193, 468: 3637}, + {219: 1193, 243: 3394, 468: 3635}, + {243: 3394, 256: 1193, 468: 3633}, + {219: 1193, 243: 3394, 468: 3631}, + // 2160 + {219: 1193, 243: 3394, 468: 3629}, + {243: 3394, 256: 1193, 468: 3627}, + {243: 3394, 256: 1193, 468: 3625}, + {243: 3394, 256: 1193, 468: 3623}, + {243: 3394, 256: 1193, 468: 3621}, + // 2165 + {218, 218, 218, 218, 6: 218, 218, 218, 10: 218, 218, 218, 14: 218, 218, 218, 218, 218, 218, 218, 218, 217: 218, 221: 218, 227: 218, 249: 218, 255: 218, 377: 218, 381: 218, 218, 218, 218, 218}, + {227: 1193, 243: 3394, 256: 1193, 468: 3619}, + {243: 3394, 256: 1193, 468: 3617}, + {227: 1193, 243: 3394, 256: 1193, 468: 3613}, + {209, 209, 3586, 3585, 6: 3611, 1271, 3592, 10: 3583, 3588, 3590, 14: 3589, 3587, 3591, 3595, 3593, 3594, 3602, 3597, 217: 209, 221: 209, 227: 3582, 249: 1271, 255: 209, 377: 209, 381: 209, 1271, 209, 3599, 3598, 508: 3584, 532: 3596, 536: 3610}, + // 2170 + {208, 208, 208, 208, 6: 208, 208, 208, 10: 208, 208, 208, 14: 208, 208, 208, 208, 208, 208, 208, 208, 217: 208, 221: 208, 227: 208, 249: 208, 255: 208, 377: 208, 381: 208, 208, 208, 208, 208}, + {82: 1193, 1193, 88: 1193, 90: 1193, 97: 1193, 227: 1193, 243: 3394, 468: 3603}, + {82: 3609, 3607, 88: 3605, 90: 3606, 97: 3608, 227: 3604}, + {202, 202, 202, 202, 6: 202, 202, 202, 10: 202, 202, 202, 14: 202, 202, 202, 202, 202, 202, 202, 202, 217: 202, 221: 202, 227: 202, 249: 202, 255: 202, 377: 202, 381: 202, 202, 202, 202, 202}, + {201, 201, 201, 201, 6: 201, 201, 201, 10: 201, 201, 201, 14: 201, 201, 201, 201, 201, 201, 201, 201, 217: 201, 221: 201, 227: 201, 249: 201, 255: 201, 377: 201, 381: 201, 201, 201, 201, 201}, + // 2175 + {200, 200, 200, 200, 6: 200, 200, 200, 10: 200, 200, 200, 14: 200, 200, 200, 200, 200, 200, 200, 200, 217: 200, 221: 200, 227: 200, 249: 200, 255: 200, 377: 200, 381: 200, 200, 200, 200, 200}, + {199, 199, 199, 199, 6: 199, 199, 199, 10: 199, 199, 199, 14: 199, 199, 199, 199, 199, 199, 199, 199, 217: 199, 221: 199, 227: 199, 249: 199, 255: 199, 377: 199, 381: 199, 199, 199, 199, 199}, + {198, 198, 198, 198, 6: 198, 198, 198, 10: 198, 198, 198, 14: 198, 198, 198, 198, 198, 198, 198, 198, 217: 198, 221: 198, 227: 198, 249: 198, 255: 198, 377: 198, 381: 198, 198, 198, 198, 198}, + {197, 197, 197, 197, 6: 197, 197, 197, 10: 197, 197, 197, 14: 197, 197, 197, 197, 197, 197, 197, 197, 217: 197, 221: 197, 227: 197, 249: 197, 255: 197, 377: 197, 381: 197, 197, 197, 197, 197}, + {207, 207, 207, 207, 6: 207, 207, 207, 10: 207, 207, 207, 14: 207, 207, 207, 207, 207, 207, 207, 207, 217: 207, 221: 207, 227: 207, 249: 207, 255: 207, 377: 207, 381: 207, 207, 207, 207, 207}, + // 2180 + {2: 3586, 3585, 7: 1271, 3592, 10: 3583, 3588, 3590, 14: 3589, 3587, 3591, 3595, 3593, 3594, 3602, 3597, 227: 3582, 249: 1271, 382: 1271, 384: 3599, 3598, 508: 3584, 532: 3596, 536: 3612}, + {206, 206, 206, 206, 6: 206, 206, 206, 10: 206, 206, 206, 14: 206, 206, 206, 206, 206, 206, 206, 206, 217: 206, 221: 206, 227: 206, 249: 206, 255: 206, 377: 206, 381: 206, 206, 206, 206, 206}, + {227: 3615, 256: 1526, 461: 2508, 476: 3616, 696: 3614}, + {215, 215, 215, 215, 6: 215, 215, 215, 10: 215, 215, 215, 14: 215, 215, 215, 215, 215, 215, 215, 215, 217: 215, 221: 215, 227: 215, 249: 215, 255: 215, 377: 215, 381: 215, 215, 215, 215, 215}, + {214, 214, 214, 214, 6: 214, 214, 214, 10: 214, 214, 214, 14: 214, 214, 214, 214, 214, 214, 214, 214, 217: 214, 221: 214, 227: 214, 249: 214, 255: 214, 377: 214, 381: 214, 214, 214, 214, 214}, + // 2185 + {213, 213, 213, 213, 6: 213, 213, 213, 10: 213, 213, 213, 14: 213, 213, 213, 213, 213, 213, 213, 213, 217: 213, 221: 213, 227: 213, 249: 213, 255: 213, 377: 213, 381: 213, 213, 213, 213, 213}, + {256: 1526, 461: 2508, 476: 3618}, + {216, 216, 216, 216, 6: 216, 216, 216, 10: 216, 216, 216, 14: 216, 216, 216, 216, 216, 216, 216, 216, 217: 216, 221: 216, 227: 216, 249: 216, 255: 216, 377: 216, 381: 216, 216, 216, 216, 216}, + {227: 3615, 256: 1526, 461: 2508, 476: 3616, 696: 3620}, + {217, 217, 217, 217, 6: 217, 217, 217, 10: 217, 217, 217, 14: 217, 217, 217, 217, 217, 217, 217, 217, 217: 217, 221: 217, 227: 217, 249: 217, 255: 217, 377: 217, 381: 217, 217, 217, 217, 217}, + // 2190 + {256: 1526, 461: 2508, 476: 3622}, + {219, 219, 219, 219, 6: 219, 219, 219, 10: 219, 219, 219, 14: 219, 219, 219, 219, 219, 219, 219, 219, 217: 219, 221: 219, 227: 219, 249: 219, 255: 219, 377: 219, 381: 219, 219, 219, 219, 219}, + {256: 1526, 461: 2508, 476: 3624}, + {220, 220, 220, 220, 6: 220, 220, 220, 10: 220, 220, 220, 14: 220, 220, 220, 220, 220, 220, 220, 220, 217: 220, 221: 220, 227: 220, 249: 220, 255: 220, 377: 220, 381: 220, 220, 220, 220, 220}, + {256: 1526, 461: 2508, 476: 3626}, + // 2195 + {221, 221, 221, 221, 6: 221, 221, 221, 10: 221, 221, 221, 14: 221, 221, 221, 221, 221, 221, 221, 221, 217: 221, 221: 221, 227: 221, 249: 221, 255: 221, 377: 221, 381: 221, 221, 221, 221, 221}, + {256: 1526, 461: 2508, 476: 3628}, + {222, 222, 222, 222, 6: 222, 222, 222, 10: 222, 222, 222, 14: 222, 222, 222, 222, 222, 222, 222, 222, 217: 222, 221: 222, 227: 222, 249: 222, 255: 222, 377: 222, 381: 222, 222, 222, 222, 222}, + {219: 3630}, + {223, 223, 223, 223, 6: 223, 223, 223, 10: 223, 223, 223, 14: 223, 223, 223, 223, 223, 223, 223, 223, 217: 223, 221: 223, 227: 223, 249: 223, 255: 223, 377: 223, 381: 223, 223, 223, 223, 223}, + // 2200 + {219: 3632}, + {224, 224, 224, 224, 6: 224, 224, 224, 10: 224, 224, 224, 14: 224, 224, 224, 224, 224, 224, 224, 224, 217: 224, 221: 224, 227: 224, 249: 224, 255: 224, 377: 224, 381: 224, 224, 224, 224, 224}, + {256: 1526, 461: 2508, 476: 3634}, + {225, 225, 225, 225, 6: 225, 225, 225, 10: 225, 225, 225, 14: 225, 225, 225, 225, 225, 225, 225, 225, 217: 225, 221: 225, 227: 225, 249: 225, 255: 225, 377: 225, 381: 225, 225, 225, 225, 225}, + {219: 3636}, + // 2205 + {226, 226, 226, 226, 6: 226, 226, 226, 10: 226, 226, 226, 14: 226, 226, 226, 226, 226, 226, 226, 226, 217: 226, 221: 226, 227: 226, 249: 226, 255: 226, 377: 226, 381: 226, 226, 226, 226, 226}, + {256: 1526, 461: 2508, 476: 3638}, + {227, 227, 227, 227, 6: 227, 227, 227, 10: 227, 227, 227, 14: 227, 227, 227, 227, 227, 227, 227, 227, 217: 227, 221: 227, 227: 227, 249: 227, 255: 227, 377: 227, 381: 227, 227, 227, 227, 227}, + {219: 3640}, + {228, 228, 228, 228, 6: 228, 228, 228, 10: 228, 228, 228, 14: 228, 228, 228, 228, 228, 228, 228, 228, 217: 228, 221: 228, 227: 228, 249: 228, 255: 228, 377: 228, 381: 228, 228, 228, 228, 228}, + // 2210 + {256: 1526, 461: 2508, 476: 3642}, + {229, 229, 229, 229, 6: 229, 229, 229, 10: 229, 229, 229, 14: 229, 229, 229, 229, 229, 229, 229, 229, 217: 229, 221: 229, 227: 229, 249: 229, 255: 229, 377: 229, 381: 229, 229, 229, 229, 229}, + {2: 1193, 1193, 1193, 1193, 7: 1193, 1193, 10: 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 219: 1193, 243: 3394, 288: 1193, 468: 3647}, + {2: 1193, 1193, 1193, 1193, 7: 1193, 1193, 10: 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 219: 1193, 243: 3394, 468: 3645}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 3646}, + // 2215 + {230, 230, 230, 230, 6: 230, 230, 230, 10: 230, 230, 230, 14: 230, 230, 230, 230, 230, 230, 230, 230, 217: 230, 221: 230, 227: 230, 249: 230, 255: 230, 377: 230, 381: 230, 230, 230, 230, 230}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 3648}, + {231, 231, 231, 231, 6: 231, 231, 231, 10: 231, 231, 231, 14: 231, 231, 231, 231, 231, 231, 231, 231, 217: 231, 221: 231, 227: 231, 249: 231, 255: 231, 377: 231, 381: 231, 231, 231, 231, 231}, + {233, 233, 233, 233, 6: 233, 233, 233, 10: 233, 233, 233, 14: 233, 233, 233, 233, 233, 233, 233, 233, 217: 233, 221: 233, 227: 233, 249: 233, 255: 233, 377: 233, 381: 233, 233, 233, 233, 233}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 3651}, + // 2220 + {232, 232, 232, 232, 6: 232, 232, 232, 10: 232, 232, 232, 14: 232, 232, 232, 232, 232, 232, 232, 232, 217: 232, 221: 232, 227: 232, 249: 232, 255: 232, 377: 232, 381: 232, 232, 232, 232, 232}, + {1242, 1242, 217: 1242, 221: 1242, 255: 3731, 377: 3730, 381: 1242, 749: 3729}, + {390: 3654}, + {65: 3656, 259: 3657, 370: 3655}, + {217: 3724}, + // 2225 + {217: 3720}, + {29: 3659, 217: 3658}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3701}, + {217: 3660}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 3661}, + // 2230 + {6: 1819, 9: 3662}, + {1259, 1259, 54: 3664, 217: 1259, 221: 1259, 255: 1259, 377: 1259, 381: 1259, 564: 3663}, + {1257, 1257, 217: 3667, 221: 1257, 255: 1257, 377: 1257, 381: 1257, 563: 3666}, + {256: 1526, 461: 3665}, + {1258, 1258, 60: 1258, 217: 1258, 221: 1258, 255: 1258, 377: 1258, 381: 1258}, + // 2235 + {1265, 1265, 217: 1265, 221: 1265, 255: 1265, 377: 1265, 381: 1265}, + {383: 3670, 678: 3669, 804: 3668}, + {6: 3699, 9: 3698}, + {6: 1255, 9: 1255}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3671, 378: 1537, 1538, 1536}, + // 2240 + {2: 1245, 6: 1245, 9: 1245, 1245, 27: 1245, 310: 3673, 803: 3672}, + {2: 3688, 6: 1252, 9: 1252, 3689, 27: 3690, 677: 3687, 801: 3686, 3685}, + {137: 3674}, + {169: 3675}, + {217: 3677, 587: 3676}, + // 2245 + {2: 1244, 6: 1244, 9: 1244, 1244, 27: 1244}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3679, 587: 3680, 661: 3681, 783: 3678}, + {6: 3683, 9: 3682}, + {6: 1168, 9: 1168, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {6: 1169, 9: 1169}, + // 2250 + {6: 1161, 9: 1161}, + {2: 1243, 6: 1243, 9: 1243, 1243, 27: 1243}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3679, 587: 3680, 661: 3684}, + {6: 1160, 9: 1160}, + {6: 1253, 9: 1253}, + // 2255 + {2: 3688, 6: 1251, 9: 1251, 3689, 27: 3690, 677: 3697}, + {2: 1250, 6: 1250, 9: 1250, 1250, 27: 1250}, + {219: 1193, 243: 3394, 468: 3695}, + {2: 1193, 1193, 1193, 1193, 7: 1193, 1193, 10: 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 243: 3394, 468: 3693}, + {2: 1193, 1193, 1193, 1193, 7: 1193, 1193, 10: 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 243: 3394, 468: 3691}, + // 2260 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3692, 378: 1537, 1538, 1536}, + {2: 1246, 6: 1246, 9: 1246, 1246, 27: 1246}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3694, 378: 1537, 1538, 1536}, + {2: 1247, 6: 1247, 9: 1247, 1247, 27: 1247}, + {219: 3696}, + // 2265 + {2: 1248, 6: 1248, 9: 1248, 1248, 27: 1248}, + {2: 1249, 6: 1249, 9: 1249, 1249, 27: 1249}, + {1256, 1256, 6: 1256, 217: 1256, 221: 1256, 255: 1256, 377: 1256, 381: 1256}, + {383: 3670, 678: 3700}, + {6: 1254, 9: 1254}, + // 2270 + {9: 3702, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {1259, 1259, 54: 3664, 60: 1259, 217: 1259, 221: 1259, 255: 1259, 377: 1259, 381: 1259, 564: 3703}, + {1264, 1264, 60: 3705, 217: 1264, 221: 1264, 255: 1264, 377: 1264, 381: 1264, 825: 3704}, + {1257, 1257, 217: 3667, 221: 1257, 255: 1257, 377: 1257, 381: 1257, 563: 3719}, + {390: 3706}, + // 2275 + {65: 3707, 370: 3708}, + {217: 3715}, + {217: 3709}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 3710}, + {6: 1819, 9: 3711}, + // 2280 + {1261, 1261, 102: 3713, 217: 1261, 221: 1261, 255: 1261, 377: 1261, 381: 1261, 698: 3712}, + {1262, 1262, 217: 1262, 221: 1262, 255: 1262, 377: 1262, 381: 1262}, + {256: 1526, 461: 3714}, + {1260, 1260, 217: 1260, 221: 1260, 255: 1260, 377: 1260, 381: 1260}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3716}, + // 2285 + {9: 3717, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {1261, 1261, 102: 3713, 217: 1261, 221: 1261, 255: 1261, 377: 1261, 381: 1261, 698: 3718}, + {1263, 1263, 217: 1263, 221: 1263, 255: 1263, 377: 1263, 381: 1263}, + {1266, 1266, 217: 1266, 221: 1266, 255: 1266, 377: 1266, 381: 1266}, + {2: 1622, 1541, 1575, 1542, 7: 1978, 1627, 10: 1568, 1624, 1983, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1987, 1553, 1980, 1982, 1996, 1997, 1995, 1991, 1998, 1988, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1979, 1637, 1585, 1600, 1984, 1989, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1994, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1985, 1607, 1986, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1990, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1981, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1976, 1977, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1999, 1730, 1975, 1734, 1733, 1587, 1736, 1738, 1591, 1992, 1993, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 2000, 2001, 1749, 2031, 219: 2012, 1971, 222: 2043, 2047, 2028, 2027, 2064, 2038, 230: 2003, 255: 2046, 2007, 279: 2015, 288: 2034, 300: 2048, 2063, 2041, 2065, 2006, 2005, 2022, 1969, 2062, 2042, 2039, 2033, 2002, 2004, 2037, 2040, 2011, 2044, 2052, 2101, 2010, 2053, 2054, 2009, 2032, 2025, 2026, 2076, 2078, 2079, 2080, 2035, 2081, 2060, 2066, 2074, 2075, 2070, 2082, 2083, 2084, 2071, 2086, 2087, 2077, 2072, 2085, 2067, 2073, 2058, 2036, 2091, 2049, 2051, 2090, 2096, 2095, 2097, 2094, 2029, 2098, 2093, 2092, 364: 2089, 2045, 2088, 2050, 2055, 2056, 376: 2014, 378: 1537, 1538, 1536, 435: 2030, 2100, 2021, 2016, 2008, 2019, 2017, 2018, 2057, 2069, 2068, 2061, 2059, 2013, 2024, 2099, 2023, 2020, 1974, 1973, 1972, 3721}, + // 2290 + {9: 3722, 235: 2110, 2108, 2109, 2107, 2105, 457: 2106, 2104}, + {1259, 1259, 54: 3664, 217: 1259, 221: 1259, 255: 1259, 377: 1259, 381: 1259, 564: 3723}, + {1267, 1267, 217: 1267, 221: 1267, 255: 1267, 377: 1267, 381: 1267}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 1815, 505: 3725}, + {6: 1819, 9: 3726}, + // 2295 + {1259, 1259, 54: 3664, 217: 1259, 221: 1259, 255: 1259, 377: 1259, 381: 1259, 564: 3727}, + {1257, 1257, 217: 3667, 221: 1257, 255: 1257, 377: 1257, 381: 1257, 563: 3728}, + {1268, 1268, 217: 1268, 221: 1268, 255: 1268, 377: 1268, 381: 1268}, + {1239, 1239, 217: 1239, 221: 3733, 381: 1239, 724: 3732}, + {1241, 1241, 217: 1241, 221: 1241, 381: 1241}, + // 2300 + {1240, 1240, 217: 1240, 221: 1240, 381: 1240}, + {1237, 1237, 217: 1461, 381: 1457, 435: 3737, 469: 3735, 1458, 1459, 1460, 475: 1463, 477: 1462, 3736, 742: 3734}, + {1238, 1238, 217: 1238, 381: 1238}, + {1273, 1273}, + {1236, 1236, 229: 431}, + // 2305 + {1235, 1235}, + {1234, 1234}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1924, 378: 1537, 1538, 1536, 542: 3739}, + {1277, 1277, 7: 1271, 227: 3582, 249: 1271, 382: 1271, 508: 3741, 620: 3743, 743: 3742, 3740}, + {1281, 1281}, + // 2310 + {7: 2525, 249: 3746, 382: 2524, 481: 3745}, + {1276, 1276, 7: 1271, 227: 3582, 249: 1271, 382: 1271, 508: 3741, 620: 3744}, + {1275, 1275, 7: 1275, 227: 1275, 249: 1275, 382: 1275}, + {1274, 1274, 7: 1274, 227: 1274, 249: 1274, 382: 1274}, + {2: 1193, 1193, 1193, 1193, 7: 1193, 1193, 10: 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 219: 1193, 243: 3394, 288: 1193, 468: 3749}, + // 2315 + {2: 1193, 1193, 1193, 1193, 7: 1193, 1193, 10: 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 219: 1193, 243: 3394, 468: 3747}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 376: 1780, 378: 1537, 1538, 1536, 466: 3748}, + {1278, 1278, 7: 1278, 227: 1278, 249: 1278, 382: 1278}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 3750}, + {1279, 1279, 7: 1279, 227: 1279, 249: 1279, 382: 1279}, + // 2320 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3752, 378: 1537, 1538, 1536}, + {218: 1087, 242: 3381, 501: 3382, 559: 3753}, + {218: 3754}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3755}, + {217: 3756}, + // 2325 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3350, 509: 3351, 518: 3757}, + {6: 3355, 9: 3758}, + {1094, 1094, 1094, 8: 1094, 231: 1094, 242: 1094, 549: 3759}, + {1397, 1397, 3392, 8: 3390, 231: 3761, 242: 3381, 501: 3391, 548: 3389, 586: 3760, 781: 3762}, + {1396, 1396}, + // 2330 + {243: 3763}, + {1287, 1287}, + {125: 3767, 147: 3764, 159: 3766, 227: 3765}, + {1395, 1395, 6: 1395}, + {1394, 1394, 6: 1394}, + // 2335 + {1393, 1393, 6: 1393}, + {1392, 1392, 6: 1392}, + {1356, 1356}, + {1358, 1358, 228: 3770}, + {118: 3771}, + // 2340 + {161: 3772}, + {1357, 1357}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3775, 503: 3774}, + {1366, 1366, 6: 2817, 228: 3783, 529: 3791}, + {599, 599, 6: 599, 228: 599, 383: 3777, 388: 3776}, + // 2345 + {495, 495, 1622, 1541, 1575, 1542, 495, 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 228: 495, 371: 2737, 376: 2736, 378: 1537, 1538, 1536, 558: 3789}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3778, 378: 1537, 1538, 1536, 679: 3779}, + {1380, 1380, 6: 1380, 228: 1380, 388: 1380}, + {1366, 1366, 6: 3780, 228: 3783, 388: 3782, 529: 3781}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3788, 378: 1537, 1538, 1536}, + // 2350 + {1368, 1368}, + {495, 495, 1622, 1541, 1575, 1542, 495, 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 228: 495, 371: 2737, 376: 2736, 378: 1537, 1538, 1536, 558: 3786}, + {256: 1526, 461: 3784}, + {79: 3785}, + {1365, 1365}, + // 2355 + {1366, 1366, 6: 2739, 228: 3783, 529: 3787}, + {1367, 1367}, + {1379, 1379, 6: 1379, 228: 1379, 388: 1379}, + {1366, 1366, 6: 2739, 228: 3783, 529: 3790}, + {1369, 1369}, + // 2360 + {1370, 1370}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3795, 705: 3794, 833: 3793}, + {1374, 1374, 6: 3798}, + {1373, 1373, 6: 1373}, + {397: 3796}, + // 2365 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3797}, + {1371, 1371, 6: 1371}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3795, 705: 3799}, + {1372, 1372, 6: 1372}, + {474: 3810}, + // 2370 + {2: 1102, 1102, 1102, 1102, 7: 1102, 1102, 10: 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 219: 1102, 300: 1102, 302: 3243, 580: 3802}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 3803, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 300: 1871, 376: 1780, 378: 1537, 1538, 1536, 466: 1870, 494: 1872, 553: 1873, 568: 3804}, + {1001, 1001, 6: 1001, 40: 1001, 217: 3805, 307: 1001, 408: 1001}, + {99, 99, 6: 1875}, + {9: 3806}, + // 2375 + {40: 3807}, + {390: 3808}, + {219: 1886, 555: 3809}, + {98, 98}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3811}, + // 2380 + {212, 212, 3586, 3585, 6: 212, 1271, 3592, 10: 3583, 3588, 3590, 14: 3589, 3587, 3591, 3595, 3593, 3594, 3602, 3597, 51: 3826, 80: 3817, 86: 3819, 89: 3820, 94: 3821, 227: 3582, 231: 3761, 249: 1271, 314: 3815, 382: 1271, 384: 3599, 3598, 392: 3827, 394: 3818, 399: 3823, 3813, 406: 3824, 409: 3816, 412: 3822, 508: 3584, 532: 3596, 536: 3601, 586: 3825, 596: 3829, 603: 3814, 3828, 722: 3812}, + {1429, 1429, 6: 3902}, + {383: 3896}, + {1426, 1426, 6: 1426}, + {397: 3892}, + // 2385 + {2: 1387, 1387, 1387, 1387, 7: 1387, 1387, 10: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 370: 1378, 1378, 1378, 383: 3880, 388: 1378, 401: 1378, 1378, 540: 3845, 3878, 573: 3879, 3324, 3327}, + {383: 3876}, + {2: 1387, 1387, 1387, 1387, 7: 1387, 1387, 10: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 370: 2746, 3865, 383: 3866, 388: 2747, 401: 3868, 510: 3867, 540: 3845, 3864}, + {585: 3863}, + {585: 3862}, + // 2390 + {2: 1387, 1387, 1387, 1387, 7: 1387, 1387, 10: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 540: 3845, 3859}, + {2: 1387, 1387, 1387, 1387, 7: 1387, 1387, 10: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 540: 3845, 3852}, + {2: 1387, 1387, 1387, 1387, 7: 1387, 1387, 10: 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 1387, 540: 3845, 3844}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 221: 3837, 370: 2746, 376: 1751, 378: 1537, 1538, 1536, 388: 2747, 397: 3835, 459: 3836, 510: 3838}, + {1403, 1403, 6: 1403}, + // 2395 + {84: 1193, 92: 1193, 227: 1193, 243: 3394, 468: 3830}, + {1401, 1401, 6: 1401}, + {1382, 1382, 6: 1382}, + {211, 211, 3586, 3585, 6: 211, 1271, 3592, 10: 3583, 3588, 3590, 14: 3589, 3587, 3591, 3595, 3593, 3594, 3602, 3597, 227: 3582, 249: 1271, 382: 1271, 384: 3599, 3598, 508: 3584, 532: 3596, 536: 3610}, + {84: 3834, 92: 3833, 227: 3832, 721: 3831}, + // 2400 + {1402, 1402, 6: 1402}, + {1400, 1400, 6: 1400}, + {1399, 1399, 6: 1399}, + {1398, 1398, 6: 1398}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3843}, + // 2405 + {1406, 1406, 6: 1406}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1751, 378: 1537, 1538, 1536, 459: 3842}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3839, 378: 1537, 1538, 1536}, + {397: 3840}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3841, 378: 1537, 1538, 1536}, + // 2410 + {1404, 1404, 6: 1404}, + {1405, 1405, 6: 1405}, + {1407, 1407, 6: 1407}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3846}, + {2: 1386, 1386, 1386, 1386, 7: 1386, 1386, 10: 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386}, + // 2415 + {246: 3847, 394: 3848}, + {227: 3850}, + {227: 3849}, + {1408, 1408, 6: 1408}, + {219: 2012, 224: 3571, 3572, 230: 2003, 256: 2007, 304: 2006, 2005, 312: 2002, 2004, 316: 2011, 320: 2010, 323: 2009, 437: 3570, 439: 2008, 694: 3851}, + // 2420 + {1409, 1409, 6: 1409}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3853}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3325, 513: 3854}, + {1385, 1385, 4: 3856, 3857, 1385, 572: 3855}, + {1410, 1410, 6: 1410}, + // 2425 + {1384, 1384, 6: 1384}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3858}, + {1383, 1383, 6: 1383}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3325, 513: 3860}, + {1385, 1385, 4: 3856, 3857, 1385, 572: 3861}, + // 2430 + {1411, 1411, 6: 1411}, + {1412, 1412, 6: 1412}, + {1413, 1413, 6: 1413}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3874}, + {370: 3873}, + // 2435 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3872, 378: 1537, 1538, 1536}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3871, 378: 1537, 1538, 1536}, + {370: 3869}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3579, 378: 1537, 1538, 1536, 699: 3870}, + {1414, 1414, 6: 1414}, + // 2440 + {1415, 1415, 6: 1415}, + {1416, 1416, 6: 1416}, + {1417, 1417, 6: 1417}, + {1198, 1198, 6: 1198, 395: 3240, 3239, 593: 3875}, + {1418, 1418, 6: 1418}, + // 2445 + {256: 1526, 461: 3877}, + {1419, 1419, 6: 1419}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 3885, 376: 1814, 378: 1537, 1538, 1536, 464: 3325, 513: 3884}, + {1422, 1422, 6: 1422}, + {1257, 1257, 6: 1257, 54: 3882, 217: 3667, 563: 3881}, + // 2450 + {1421, 1421, 6: 1421}, + {256: 1526, 461: 3883}, + {1420, 1420, 6: 1420}, + {1385, 1385, 4: 3856, 3857, 1385, 572: 3891}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3325, 513: 3887, 732: 3886}, + // 2455 + {6: 3889, 9: 3888}, + {6: 1355, 9: 1355}, + {1423, 1423, 6: 1423}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 1814, 378: 1537, 1538, 1536, 464: 3325, 513: 3890}, + {6: 1354, 9: 1354}, + // 2460 + {1424, 1424, 6: 1424}, + {7: 2525, 382: 2524, 481: 3893}, + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 219: 1779, 288: 1778, 376: 1780, 378: 1537, 1538, 1536, 466: 1777, 504: 3894}, + {114, 114, 6: 114, 249: 3492, 511: 3895}, + {1425, 1425, 6: 1425}, + // 2465 + {2: 1622, 1541, 1575, 1542, 7: 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 376: 3778, 378: 1537, 1538, 1536, 679: 3897}, + {1366, 1366, 6: 3780, 228: 3783, 388: 3899, 529: 3898}, + {1428, 1428}, + {495, 495, 1622, 1541, 1575, 1542, 495, 1552, 1627, 10: 1568, 1624, 1589, 1595, 1625, 1623, 1626, 1636, 1629, 1630, 1632, 1666, 1658, 1679, 1598, 1601, 1675, 1602, 1614, 1553, 1562, 1583, 1672, 1673, 1669, 1633, 1678, 1616, 1695, 1574, 1620, 1735, 1640, 1715, 1717, 1716, 1578, 1558, 1567, 1654, 1610, 1694, 1573, 1588, 1661, 1590, 1561, 1560, 1637, 1585, 1600, 1605, 1619, 1646, 1693, 1582, 1638, 1750, 1670, 1649, 1676, 1690, 1687, 1664, 1611, 1612, 1703, 1545, 1656, 1704, 1668, 1554, 1555, 1556, 1723, 1563, 1651, 1564, 1566, 1652, 1576, 1577, 1731, 1707, 1659, 1655, 1663, 1592, 1593, 1692, 1597, 1709, 1599, 1606, 1607, 1609, 1539, 1543, 1546, 1548, 1547, 1549, 1705, 1701, 1551, 1688, 1621, 1641, 1557, 1559, 1706, 1565, 1569, 1570, 1660, 1665, 1579, 1580, 1657, 1581, 1634, 1571, 1648, 1732, 1696, 1708, 1586, 1584, 1645, 1628, 1683, 1684, 1685, 1686, 1697, 1615, 1631, 1662, 1643, 1674, 1671, 1677, 1737, 1702, 1639, 1700, 1644, 1594, 1680, 1681, 1689, 1596, 1712, 1713, 1711, 1710, 1691, 1698, 1603, 1604, 1714, 1748, 1608, 1635, 1642, 1699, 1613, 1718, 1617, 1540, 1544, 1719, 1720, 1721, 1550, 1722, 1724, 1725, 1726, 1727, 1572, 1728, 1729, 1730, 1535, 1734, 1733, 1587, 1736, 1738, 1591, 1653, 1667, 1682, 1618, 1647, 1650, 1742, 1743, 1744, 1745, 1739, 1740, 1741, 1746, 1747, 1749, 228: 495, 371: 2737, 376: 2736, 378: 1537, 1538, 1536, 558: 3900}, + {1366, 1366, 6: 2739, 228: 3783, 529: 3901}, + // 2470 + {1427, 1427}, + {212, 212, 3586, 3585, 6: 212, 1271, 3592, 10: 3583, 3588, 3590, 14: 3589, 3587, 3591, 3595, 3593, 3594, 3602, 3597, 51: 3826, 80: 3817, 86: 3819, 89: 3820, 94: 3821, 227: 3582, 231: 3761, 249: 1271, 314: 3815, 382: 1271, 384: 3599, 3598, 392: 3827, 394: 3818, 399: 3823, 406: 3824, 409: 3816, 412: 3822, 508: 3584, 532: 3596, 536: 3601, 586: 3825, 596: 3829, 603: 3814, 3903}, + {1381, 1381, 6: 1381}, + {1191, 1191, 52: 1453, 55: 1452, 76: 1466, 1437, 1439, 81: 1440, 85: 1455, 87: 1442, 91: 1468, 98: 1456, 100: 1438, 104: 1445, 1515, 217: 1461, 231: 1522, 246: 1465, 255: 1451, 262: 1448, 301: 1450, 381: 1457, 393: 1517, 1444, 399: 1434, 1436, 406: 1435, 435: 1507, 469: 1464, 1458, 1459, 1460, 475: 1463, 477: 1462, 1504, 1516, 486: 1443, 514: 1478, 519: 1495, 1502, 523: 1510, 526: 1441, 528: 1518, 534: 1467, 602: 1470, 605: 1471, 1472, 1473, 1474, 1475, 614: 1476, 1481, 1482, 1483, 1485, 1484, 623: 1477, 1454, 1447, 1486, 1487, 1488, 1492, 1489, 1491, 1490, 1469, 1479, 1446, 1480, 1449, 641: 1493, 646: 1494, 653: 1524, 1523, 1496, 657: 1520, 1497, 1498, 1513, 681: 1499, 687: 1501, 1519, 1503, 1500, 1505, 1506, 695: 3905, 708: 1508, 1509, 1521, 1512, 713: 1511}, + {242, 242}, + } +) + +var yyDebug = 0 + +type yyLexer interface { + Lex(lval *yySymType) int + Errorf(format string, a ...interface{}) + Errors() []error +} + +type yyLexerEx interface { + yyLexer + Reduced(rule, state int, lval *yySymType) bool +} + +func yySymName(c int) (s string) { + x, ok := yyXLAT[c] + if ok { + return yySymNames[x] + } + + return __yyfmt__.Sprintf("%d", c) +} + +func yylex1(yylex yyLexer, lval *yySymType) (n int) { + n = yylex.Lex(lval) + if n <= 0 { + n = yyEOFCode + } + if yyDebug >= 3 { + __yyfmt__.Printf("\nlex %s(%#x %d), lval: %+v\n", yySymName(n), n, n, lval) + } + return n +} + +func yyParse(yylex yyLexer, parser *Parser) int { + const yyError = 870 + + yyEx, _ := yylex.(yyLexerEx) + var yyn int + parser.yylval = yySymType{} + parser.yyVAL = yySymType{} + yyS := parser.cache + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + yyerrok := func() { + if yyDebug >= 2 { + __yyfmt__.Printf("yyerrok()\n") + } + Errflag = 0 + } + _ = yyerrok + yystate := 0 + yychar := -1 + var yyxchar int + var yyshift int + yyp := -1 + goto yystack + +ret0: + return 0 + +ret1: + return 1 + +yystack: + /* put a state and value onto the stack */ + yyp++ + if yyp >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + parser.cache = yyS + } + yyS[yyp] = parser.yyVAL + yyS[yyp].yys = yystate + +yynewstate: + if yychar < 0 { + yychar = yylex1(yylex, &parser.yylval) + var ok bool + if yyxchar, ok = yyXLAT[yychar]; !ok { + yyxchar = len(yySymNames) // > tab width + } + } + if yyDebug >= 4 { + var a []int + for _, v := range yyS[:yyp+1] { + a = append(a, v.yys) + } + __yyfmt__.Printf("state stack %v\n", a) + } + row := yyParseTab[yystate] + yyn = 0 + if yyxchar < len(row) { + if yyn = int(row[yyxchar]); yyn != 0 { + yyn += yyTabOfs + } + } + switch { + case yyn > 0: // shift + yychar = -1 + parser.yyVAL = parser.yylval + yystate = yyn + yyshift = yyn + if yyDebug >= 2 { + __yyfmt__.Printf("shift, and goto state %d\n", yystate) + } + if Errflag > 0 { + Errflag-- + } + goto yystack + case yyn < 0: // reduce + case yystate == 1: // accept + if yyDebug >= 2 { + __yyfmt__.Println("accept") + } + goto ret0 + } + + if yyn == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + if yyDebug >= 1 { + __yyfmt__.Printf("no action for %s in state %d\n", yySymName(yychar), yystate) + } + msg, ok := yyXErrors[yyXError{yystate, yyxchar}] + if !ok { + msg, ok = yyXErrors[yyXError{yystate, -1}] + } + if !ok && yyshift != 0 { + msg, ok = yyXErrors[yyXError{yyshift, yyxchar}] + } + if !ok { + msg, ok = yyXErrors[yyXError{yyshift, -1}] + } + if !ok || msg == "" { + msg = "syntax error" + } + // ignore goyacc error message + yylex.Errorf("") + Nerrs++ + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for yyp >= 0 { + row := yyParseTab[yyS[yyp].yys] + if yyError < len(row) { + yyn = int(row[yyError]) + yyTabOfs + if yyn > 0 { // hit + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery found error shift in state %d\n", yyS[yyp].yys) + } + yystate = yyn /* simulate a shift of "error" */ + goto yystack + } + } + + /* the current p has no shift on "error", pop stack */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) + } + yyp-- + } + /* there is no state on the stack with an error shift ... abort */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery failed\n") + } + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", yySymName(yychar)) + } + if yychar == yyEOFCode { + goto ret1 + } + + yychar = -1 + goto yynewstate /* try again in the same state */ + } + } + + r := -yyn + x0 := yyReductions[r] + x, n := x0.xsym, x0.components + yypt := yyp + _ = yypt // guard against "declared and not used" + + yyp -= n + if yyp+1 >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + parser.cache = yyS + } + parser.yyVAL = yyS[yyp+1] + + /* consult goto table to find next state */ + exState := yystate + yystate = int(yyParseTab[yyS[yyp].yys][x]) + yyTabOfs + /* reduction by production r */ + if yyDebug >= 2 { + __yyfmt__.Printf("reduce using rule %v (%s), and goto state %d\n", r, yySymNames[x], yystate) + } + + switch r { + case 2: + { + parser.yyVAL.statement = &ast.AlterTableStmt{ + Table: yyS[yypt-1].item.(*ast.TableName), + Specs: yyS[yypt-0].item.([]*ast.AlterTableSpec), + } + } + case 3: + { + parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{yyS[yypt-4].item.(*ast.TableName)}, PartitionNames: yyS[yypt-1].item.([]model.CIStr), MaxNumBuckets: yyS[yypt-0].item.(uint64)} + } + case 4: + { + parser.yyVAL.statement = &ast.AnalyzeTableStmt{ + TableNames: []*ast.TableName{yyS[yypt-6].item.(*ast.TableName)}, + PartitionNames: yyS[yypt-3].item.([]model.CIStr), + IndexNames: yyS[yypt-1].item.([]model.CIStr), + IndexFlag: true, + MaxNumBuckets: yyS[yypt-0].item.(uint64), + } + } + case 5: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableOption, + Options: yyS[yypt-0].item.([]*ast.TableOption), + } + } + case 6: + { + op := &ast.AlterTableSpec{ + Tp: ast.AlterTableOption, + Options: []*ast.TableOption{{Tp: ast.TableOptionCharset, StrValue: yyS[yypt-1].item.(string)}}, + } + if yyS[yypt-0].item != "" { + op.Options = append(op.Options, &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: yyS[yypt-0].item.(string)}) + } + parser.yyVAL.item = op + } + case 7: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddColumns, + NewColumns: []*ast.ColumnDef{yyS[yypt-1].item.(*ast.ColumnDef)}, + Position: yyS[yypt-0].item.(*ast.ColumnPosition), + } + } + case 8: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddColumns, + NewColumns: yyS[yypt-1].item.([]*ast.ColumnDef), + } + } + case 9: + { + constraint := yyS[yypt-0].item.(*ast.Constraint) + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddConstraint, + Constraint: constraint, + } + } + case 10: + { + var defs []*ast.PartitionDefinition + if yyS[yypt-0].item != nil { + defs = yyS[yypt-0].item.([]*ast.PartitionDefinition) + } + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddPartitions, + PartDefinitions: defs, + } + } + case 11: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddPartitions, + Num: getUint64FromNUM(yyS[yypt-0].item), + } + } + case 12: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableCoalescePartitions, + Num: getUint64FromNUM(yyS[yypt-0].item), + } + } + case 13: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropColumn, + OldColumnName: yyS[yypt-1].item.(*ast.ColumnName), + } + } + case 14: + { + parser.yyVAL.item = &ast.AlterTableSpec{Tp: ast.AlterTableDropPrimaryKey} + } + case 15: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropPartition, + Name: yyS[yypt-0].ident, + } + } + case 16: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropIndex, + Name: yyS[yypt-0].ident, + } + } + case 17: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropForeignKey, + Name: yyS[yypt-0].item.(string), + } + } + case 18: + { + parser.yyVAL.item = &ast.AlterTableSpec{} + } + case 19: + { + parser.yyVAL.item = &ast.AlterTableSpec{} + } + case 20: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableModifyColumn, + NewColumns: []*ast.ColumnDef{yyS[yypt-1].item.(*ast.ColumnDef)}, + Position: yyS[yypt-0].item.(*ast.ColumnPosition), + } + } + case 21: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableChangeColumn, + OldColumnName: yyS[yypt-2].item.(*ast.ColumnName), + NewColumns: []*ast.ColumnDef{yyS[yypt-1].item.(*ast.ColumnDef)}, + Position: yyS[yypt-0].item.(*ast.ColumnPosition), + } + } + case 22: + { + option := &ast.ColumnOption{Expr: yyS[yypt-0].expr} + colDef := &ast.ColumnDef{ + Name: yyS[yypt-3].item.(*ast.ColumnName), + Options: []*ast.ColumnOption{option}, + } + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAlterColumn, + NewColumns: []*ast.ColumnDef{colDef}, + } + } + case 23: + { + colDef := &ast.ColumnDef{ + Name: yyS[yypt-2].item.(*ast.ColumnName), + } + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAlterColumn, + NewColumns: []*ast.ColumnDef{colDef}, + } + } + case 24: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameTable, + NewTable: yyS[yypt-0].item.(*ast.TableName), + } + } + case 25: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameTable, + NewTable: yyS[yypt-0].item.(*ast.TableName), + } + } + case 26: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameTable, + NewTable: yyS[yypt-0].item.(*ast.TableName), + } + } + case 27: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameIndex, + FromKey: model.NewCIStr(yyS[yypt-2].ident), + ToKey: model.NewCIStr(yyS[yypt-0].ident), + } + } + case 28: + { + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableLock, + LockType: yyS[yypt-0].item.(ast.LockType), + } + } + case 29: + { + // Parse it and ignore it. Just for compatibility. + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableAlgorithm, + } + } + case 30: + { + // Parse it and ignore it. Just for compatibility. + parser.yyVAL.item = &ast.AlterTableSpec{ + Tp: ast.AlterTableForce, + } + } + case 36: + { + parser.yyVAL.item = ast.LockTypeNone + } + case 37: + { + parser.yyVAL.item = ast.LockTypeDefault + } + case 38: + { + parser.yyVAL.item = ast.LockTypeShared + } + case 39: + { + parser.yyVAL.item = ast.LockTypeExclusive + } + case 46: + { + parser.yyVAL.item = &ast.ColumnPosition{Tp: ast.ColumnPositionNone} + } + case 47: + { + parser.yyVAL.item = &ast.ColumnPosition{Tp: ast.ColumnPositionFirst} + } + case 48: + { + parser.yyVAL.item = &ast.ColumnPosition{ + Tp: ast.ColumnPositionAfter, + RelativeColumn: yyS[yypt-0].item.(*ast.ColumnName), + } + } + case 49: + { + parser.yyVAL.item = []*ast.AlterTableSpec{yyS[yypt-0].item.(*ast.AlterTableSpec)} + } + case 50: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.AlterTableSpec), yyS[yypt-0].item.(*ast.AlterTableSpec)) + } + case 51: + { + parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} + } + case 52: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) + } + case 53: + { + parser.yyVAL.item = nil + } + case 54: + { + parser.yyVAL.item = nil + } + case 55: + { + parser.yyVAL.item = yyS[yypt-0].item.(string) + } + case 56: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 57: + { + parser.yyVAL.statement = &ast.RenameTableStmt{ + OldTable: yyS[yypt-0].item.([]*ast.TableToTable)[0].OldTable, + NewTable: yyS[yypt-0].item.([]*ast.TableToTable)[0].NewTable, + TableToTables: yyS[yypt-0].item.([]*ast.TableToTable), + } + } + case 58: + { + parser.yyVAL.item = []*ast.TableToTable{yyS[yypt-0].item.(*ast.TableToTable)} + } + case 59: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.TableToTable), yyS[yypt-0].item.(*ast.TableToTable)) + } + case 60: + { + parser.yyVAL.item = &ast.TableToTable{ + OldTable: yyS[yypt-2].item.(*ast.TableName), + NewTable: yyS[yypt-0].item.(*ast.TableName), + } + } + case 61: + { + parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: yyS[yypt-1].item.([]*ast.TableName), MaxNumBuckets: yyS[yypt-0].item.(uint64)} + } + case 62: + { + parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{yyS[yypt-3].item.(*ast.TableName)}, IndexNames: yyS[yypt-1].item.([]model.CIStr), IndexFlag: true, MaxNumBuckets: yyS[yypt-0].item.(uint64)} + } + case 63: + { + parser.yyVAL.statement = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{yyS[yypt-3].item.(*ast.TableName)}, PartitionNames: yyS[yypt-1].item.([]model.CIStr), MaxNumBuckets: yyS[yypt-0].item.(uint64)} + } + case 64: + { + parser.yyVAL.statement = &ast.AnalyzeTableStmt{ + TableNames: []*ast.TableName{yyS[yypt-5].item.(*ast.TableName)}, + PartitionNames: yyS[yypt-3].item.([]model.CIStr), + IndexNames: yyS[yypt-1].item.([]model.CIStr), + IndexFlag: true, + MaxNumBuckets: yyS[yypt-0].item.(uint64), + } + } + case 65: + { + parser.yyVAL.item = uint64(0) + } + case 66: + { + parser.yyVAL.item = getUint64FromNUM(yyS[yypt-1].item) + } + case 67: + { + parser.yyVAL.item = &ast.Assignment{Column: yyS[yypt-2].item.(*ast.ColumnName), Expr: yyS[yypt-0].expr} + } + case 68: + { + parser.yyVAL.item = []*ast.Assignment{yyS[yypt-0].item.(*ast.Assignment)} + } + case 69: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.Assignment), yyS[yypt-0].item.(*ast.Assignment)) + } + case 70: + { + parser.yyVAL.item = []*ast.Assignment{} + } + case 72: + { + parser.yyVAL.statement = &ast.BeginStmt{} + } + case 73: + { + parser.yyVAL.statement = &ast.BeginStmt{} + } + case 74: + { + parser.yyVAL.statement = &ast.BeginStmt{} + } + case 75: + { + parser.yyVAL.statement = &ast.BinlogStmt{Str: yyS[yypt-0].ident} + } + case 76: + { + parser.yyVAL.item = []*ast.ColumnDef{yyS[yypt-0].item.(*ast.ColumnDef)} + } + case 77: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ColumnDef), yyS[yypt-0].item.(*ast.ColumnDef)) + } + case 78: + { + parser.yyVAL.item = &ast.ColumnDef{Name: yyS[yypt-2].item.(*ast.ColumnName), Tp: yyS[yypt-1].item.(*types.FieldType), Options: yyS[yypt-0].item.([]*ast.ColumnOption)} + } + case 79: + { + parser.yyVAL.item = &ast.ColumnName{Name: model.NewCIStr(yyS[yypt-0].ident)} + } + case 80: + { + parser.yyVAL.item = &ast.ColumnName{Table: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident)} + } + case 81: + { + parser.yyVAL.item = &ast.ColumnName{Schema: model.NewCIStr(yyS[yypt-4].ident), Table: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident)} + } + case 82: + { + parser.yyVAL.item = []*ast.ColumnName{yyS[yypt-0].item.(*ast.ColumnName)} + } + case 83: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ColumnName), yyS[yypt-0].item.(*ast.ColumnName)) + } + case 84: + { + parser.yyVAL.item = []*ast.ColumnName{} + } + case 85: + { + parser.yyVAL.item = yyS[yypt-0].item.([]*ast.ColumnName) + } + case 86: + { + parser.yyVAL.item = []*ast.ColumnName{} + } + case 87: + { + parser.yyVAL.item = yyS[yypt-1].item.([]*ast.ColumnName) + } + case 88: + { + parser.yyVAL.statement = &ast.CommitStmt{} + } + case 91: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionNotNull} + } + case 92: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionNull} + } + case 93: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionAutoIncrement} + } + case 94: + { + // KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY + // can also be specified as just KEY when given in a column definition. + // See http://dev.mysql.com/doc/refman/5.7/en/create-table.html + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionPrimaryKey} + } + case 95: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey} + } + case 96: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey} + } + case 97: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionDefaultValue, Expr: yyS[yypt-0].expr} + } + case 98: + { + nowFunc := &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: nowFunc} + } + case 99: + { + parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr(yyS[yypt-0].ident)} + } + case 100: + { + // See https://dev.mysql.com/doc/refman/5.7/en/create-table.html + // The CHECK clause is parsed but ignored by all storage engines. + parser.yyVAL.item = &ast.ColumnOption{} + } + case 101: + { + startOffset := parser.startOffset(&yyS[yypt-2]) + endOffset := parser.endOffset(&yyS[yypt-1]) + expr := yyS[yypt-2].expr + expr.SetText(parser.src[startOffset:endOffset]) + + parser.yyVAL.item = &ast.ColumnOption{ + Tp: ast.ColumnOptionGenerated, + Expr: expr, + Stored: yyS[yypt-0].item.(bool), + } + } + case 102: + { + parser.yyVAL.item = &ast.ColumnOption{ + Tp: ast.ColumnOptionReference, + Refer: yyS[yypt-0].item.(*ast.ReferenceDef), + } + } + case 105: + { + parser.yyVAL.item = false + } + case 106: + { + parser.yyVAL.item = false + } + case 107: + { + parser.yyVAL.item = true + } + case 108: + { + parser.yyVAL.item = []*ast.ColumnOption{yyS[yypt-0].item.(*ast.ColumnOption)} + } + case 109: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.ColumnOption), yyS[yypt-0].item.(*ast.ColumnOption)) + } + case 110: + { + parser.yyVAL.item = []*ast.ColumnOption{} + } + case 111: + { + parser.yyVAL.item = yyS[yypt-0].item.([]*ast.ColumnOption) + } + case 112: + { + c := &ast.Constraint{ + Tp: ast.ConstraintPrimaryKey, + Keys: yyS[yypt-2].item.([]*ast.IndexColName), + } + if yyS[yypt-0].item != nil { + c.Option = yyS[yypt-0].item.(*ast.IndexOption) + } + if yyS[yypt-4].item != nil { + if c.Option == nil { + c.Option = &ast.IndexOption{} + } + c.Option.Tp = yyS[yypt-4].item.(model.IndexType) + } + parser.yyVAL.item = c + } + case 113: + { + c := &ast.Constraint{ + Tp: ast.ConstraintFulltext, + Keys: yyS[yypt-2].item.([]*ast.IndexColName), + Name: yyS[yypt-4].item.(string), + } + if yyS[yypt-0].item != nil { + c.Option = yyS[yypt-0].item.(*ast.IndexOption) + } + parser.yyVAL.item = c + } + case 114: + { + c := &ast.Constraint{ + Tp: ast.ConstraintIndex, + Keys: yyS[yypt-2].item.([]*ast.IndexColName), + Name: yyS[yypt-5].item.(string), + } + if yyS[yypt-0].item != nil { + c.Option = yyS[yypt-0].item.(*ast.IndexOption) + } + if yyS[yypt-4].item != nil { + if c.Option == nil { + c.Option = &ast.IndexOption{} + } + c.Option.Tp = yyS[yypt-4].item.(model.IndexType) + } + parser.yyVAL.item = c + } + case 115: + { + c := &ast.Constraint{ + Tp: ast.ConstraintUniq, + Keys: yyS[yypt-2].item.([]*ast.IndexColName), + Name: yyS[yypt-5].item.(string), + } + if yyS[yypt-0].item != nil { + c.Option = yyS[yypt-0].item.(*ast.IndexOption) + } + if yyS[yypt-4].item != nil { + if c.Option == nil { + c.Option = &ast.IndexOption{} + } + c.Option.Tp = yyS[yypt-4].item.(model.IndexType) + } + parser.yyVAL.item = c + } + case 116: + { + parser.yyVAL.item = &ast.Constraint{ + Tp: ast.ConstraintForeignKey, + Keys: yyS[yypt-2].item.([]*ast.IndexColName), + Name: yyS[yypt-4].item.(string), + Refer: yyS[yypt-0].item.(*ast.ReferenceDef), + } + } + case 117: + { + var onDeleteOpt *ast.OnDeleteOpt + if yyS[yypt-1].item != nil { + onDeleteOpt = yyS[yypt-1].item.(*ast.OnDeleteOpt) + } + var onUpdateOpt *ast.OnUpdateOpt + if yyS[yypt-0].item != nil { + onUpdateOpt = yyS[yypt-0].item.(*ast.OnUpdateOpt) + } + parser.yyVAL.item = &ast.ReferenceDef{ + Table: yyS[yypt-5].item.(*ast.TableName), + IndexColNames: yyS[yypt-3].item.([]*ast.IndexColName), + OnDelete: onDeleteOpt, + OnUpdate: onUpdateOpt, + } + } + case 118: + { + parser.yyVAL.item = &ast.OnDeleteOpt{} + } + case 119: + { + parser.yyVAL.item = &ast.OnDeleteOpt{ReferOpt: yyS[yypt-0].item.(ast.ReferOptionType)} + } + case 120: + { + parser.yyVAL.item = &ast.OnUpdateOpt{} + } + case 121: + { + parser.yyVAL.item = &ast.OnUpdateOpt{ReferOpt: yyS[yypt-0].item.(ast.ReferOptionType)} + } + case 122: + { + parser.yyVAL.item = ast.ReferOptionRestrict + } + case 123: + { + parser.yyVAL.item = ast.ReferOptionCascade + } + case 124: + { + parser.yyVAL.item = ast.ReferOptionSetNull + } + case 125: + { + parser.yyVAL.item = ast.ReferOptionNoAction + } + case 128: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } + case 129: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } + case 130: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } + case 138: + { + parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].expr) + } + case 139: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr(yyS[yypt-0].item)} + } + case 140: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(yyS[yypt-0].item)} + } + case 144: + { + var indexOption *ast.IndexOption + if yyS[yypt-1].item != nil { + indexOption = yyS[yypt-1].item.(*ast.IndexOption) + if indexOption.Tp == model.IndexTypeInvalid { + if yyS[yypt-7].item != nil { + indexOption.Tp = yyS[yypt-7].item.(model.IndexType) + } + } + } else { + indexOption = &ast.IndexOption{} + if yyS[yypt-7].item != nil { + indexOption.Tp = yyS[yypt-7].item.(model.IndexType) + } + } + parser.yyVAL.statement = &ast.CreateIndexStmt{ + Unique: yyS[yypt-10].item.(bool), + IndexName: yyS[yypt-8].ident, + Table: yyS[yypt-5].item.(*ast.TableName), + IndexColNames: yyS[yypt-3].item.([]*ast.IndexColName), + IndexOption: indexOption, + } + } + case 145: + { + parser.yyVAL.item = false + } + case 146: + { + parser.yyVAL.item = true + } + case 147: + { + //Order is parsed but just ignored as MySQL did + parser.yyVAL.item = &ast.IndexColName{Column: yyS[yypt-2].item.(*ast.ColumnName), Length: yyS[yypt-1].item.(int)} + } + case 148: + { + parser.yyVAL.item = []*ast.IndexColName{yyS[yypt-0].item.(*ast.IndexColName)} + } + case 149: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.IndexColName), yyS[yypt-0].item.(*ast.IndexColName)) + } + case 150: + { + parser.yyVAL.statement = &ast.CreateDatabaseStmt{ + IfNotExists: yyS[yypt-2].item.(bool), + Name: yyS[yypt-1].item.(string), + Options: yyS[yypt-0].item.([]*ast.DatabaseOption), + } + } + case 151: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 152: + { + parser.yyVAL.item = &ast.DatabaseOption{Tp: ast.DatabaseOptionCharset, Value: yyS[yypt-0].item.(string)} + } + case 153: + { + parser.yyVAL.item = &ast.DatabaseOption{Tp: ast.DatabaseOptionCollate, Value: yyS[yypt-0].item.(string)} + } + case 154: + { + parser.yyVAL.item = []*ast.DatabaseOption{} + } + case 156: + { + parser.yyVAL.item = []*ast.DatabaseOption{yyS[yypt-0].item.(*ast.DatabaseOption)} + } + case 157: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.DatabaseOption), yyS[yypt-0].item.(*ast.DatabaseOption)) + } + case 158: + { + stmt := yyS[yypt-5].item.(*ast.CreateTableStmt) + stmt.Table = yyS[yypt-6].item.(*ast.TableName) + stmt.IfNotExists = yyS[yypt-7].item.(bool) + stmt.Options = yyS[yypt-4].item.([]*ast.TableOption) + if yyS[yypt-3].item != nil { + stmt.Partition = yyS[yypt-3].item.(*ast.PartitionOptions) + } + stmt.OnDuplicate = yyS[yypt-2].item.(ast.OnDuplicateCreateTableSelectType) + stmt.Select = yyS[yypt-0].item.(*ast.CreateTableStmt).Select + parser.yyVAL.statement = stmt + } + case 159: + { + parser.yyVAL.statement = &ast.CreateTableStmt{ + Table: yyS[yypt-1].item.(*ast.TableName), + ReferTable: yyS[yypt-0].item.(*ast.TableName), + IfNotExists: yyS[yypt-2].item.(bool), + } + } + case 162: + { + parser.yyVAL.item = nil + } + case 163: + { + parser.yyVAL.item = nil + } + case 164: + { + tmp := &ast.PartitionOptions{ + Tp: model.PartitionTypeHash, + Expr: yyS[yypt-2].expr.(ast.ExprNode), + // If you do not include a PARTITIONS clause, the number of partitions defaults to 1 + Num: 1, + } + if yyS[yypt-0].item != nil { + tmp.Num = getUint64FromNUM(yyS[yypt-0].item) + } + parser.yyVAL.item = tmp + } + case 165: + { + var defs []*ast.PartitionDefinition + if yyS[yypt-0].item != nil { + defs = yyS[yypt-0].item.([]*ast.PartitionDefinition) + } + parser.yyVAL.item = &ast.PartitionOptions{ + Tp: model.PartitionTypeRange, + Expr: yyS[yypt-4].expr.(ast.ExprNode), + Definitions: defs, + } + } + case 166: + { + var defs []*ast.PartitionDefinition + if yyS[yypt-0].item != nil { + defs = yyS[yypt-0].item.([]*ast.PartitionDefinition) + } + parser.yyVAL.item = &ast.PartitionOptions{ + Tp: model.PartitionTypeRange, + ColumnNames: yyS[yypt-3].item.([]*ast.ColumnName), + Definitions: defs, + } + } + case 172: + { + parser.yyVAL.item = nil + } + case 173: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 174: + { + parser.yyVAL.item = nil + } + case 175: + { + parser.yyVAL.item = yyS[yypt-1].item.([]*ast.PartitionDefinition) + } + case 176: + { + parser.yyVAL.item = []*ast.PartitionDefinition{yyS[yypt-0].item.(*ast.PartitionDefinition)} + } + case 177: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.PartitionDefinition), yyS[yypt-0].item.(*ast.PartitionDefinition)) + } + case 178: + { + partDef := &ast.PartitionDefinition{ + Name: model.NewCIStr(yyS[yypt-2].ident), + } + switch yyS[yypt-1].item.(type) { + case []ast.ExprNode: + partDef.LessThan = yyS[yypt-1].item.([]ast.ExprNode) + case ast.ExprNode: + partDef.LessThan = make([]ast.ExprNode, 1) + partDef.LessThan[0] = yyS[yypt-1].item.(ast.ExprNode) + } + + if comment, ok := yyS[yypt-0].item.(string); ok { + partDef.Comment = comment + } + parser.yyVAL.item = partDef + } + case 179: + { + parser.yyVAL.item = nil + } + case 180: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 181: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 182: + { + if yyS[yypt-1].item != nil { + parser.yyVAL.item = yyS[yypt-1].item + } else { + parser.yyVAL.item = yyS[yypt-0].item + } + } + case 183: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 184: + { + parser.yyVAL.item = nil + } + case 185: + { + parser.yyVAL.item = nil + } + case 186: + { + parser.yyVAL.item = nil + } + case 187: + { + parser.yyVAL.item = &ast.MaxValueExpr{} + } + case 188: + { + parser.yyVAL.item = yyS[yypt-1].item + } + case 189: + { + parser.yyVAL.item = ast.OnDuplicateCreateTableSelectError + } + case 190: + { + parser.yyVAL.item = ast.OnDuplicateCreateTableSelectIgnore + } + case 191: + { + parser.yyVAL.item = ast.OnDuplicateCreateTableSelectReplace + } + case 194: + { + parser.yyVAL.item = &ast.CreateTableStmt{} + } + case 195: + { + parser.yyVAL.item = &ast.CreateTableStmt{Select: yyS[yypt-0].statement} + } + case 196: + { + parser.yyVAL.item = &ast.CreateTableStmt{Select: yyS[yypt-0].statement} + } + case 197: + { + parser.yyVAL.item = &ast.CreateTableStmt{Select: yyS[yypt-0].expr} + } + case 198: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 199: + { + parser.yyVAL.item = yyS[yypt-1].item + } + case 200: + { + startOffset := parser.startOffset(&yyS[yypt-1]) + selStmt := yyS[yypt-1].statement.(*ast.SelectStmt) + selStmt.SetText(string(parser.src[startOffset:])) + x := &ast.CreateViewStmt{ + OrReplace: yyS[yypt-9].item.(bool), + ViewName: yyS[yypt-4].item.(*ast.TableName), + Select: selStmt, + } + if yyS[yypt-3].item != nil { + x.Cols = yyS[yypt-3].item.([]model.CIStr) + } + parser.yyVAL.statement = x + } + case 201: + { + parser.yyVAL.item = false + } + case 202: + { + parser.yyVAL.item = true + } + case 203: + { + parser.yyVAL.item = "UNDEFINED" + } + case 204: + { + parser.yyVAL.item = strings.ToUpper(yyS[yypt-0].ident) + } + case 205: + { + parser.yyVAL.item = strings.ToUpper(yyS[yypt-0].ident) + } + case 206: + { + parser.yyVAL.item = strings.ToUpper(yyS[yypt-0].ident) + } + case 207: + { + parser.yyVAL.item = nil + } + case 208: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 209: + { + parser.yyVAL.item = "DEFINER" + } + case 210: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 211: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 212: + { + parser.yyVAL.item = yyS[yypt-0].item.(*ast.TableName) + } + case 213: + { + parser.yyVAL.item = nil + } + case 214: + { + parser.yyVAL.item = yyS[yypt-1].item.([]model.CIStr) + } + case 215: + { + parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} + } + case 216: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) + } + case 217: + { + parser.yyVAL.item = nil + } + case 218: + { + parser.yyVAL.item = yyS[yypt-2].ident + } + case 219: + { + parser.yyVAL.item = yyS[yypt-2].ident + } + case 220: + { + parser.yyVAL.statement = &ast.DoStmt{ + Exprs: yyS[yypt-0].item.([]ast.ExprNode), + } + } + case 221: + { + // Single Table + tn := yyS[yypt-4].item.(*ast.TableName) + tn.IndexHints = yyS[yypt-3].item.([]*ast.IndexHint) + join := &ast.Join{Left: &ast.TableSource{Source: tn}, Right: nil} + x := &ast.DeleteStmt{ + TableRefs: &ast.TableRefsClause{TableRefs: join}, + Priority: yyS[yypt-8].item.(mysql.PriorityEnum), + Quick: yyS[yypt-7].item.(bool), + IgnoreErr: yyS[yypt-6].item.(bool), + } + if yyS[yypt-2].item != nil { + x.Where = yyS[yypt-2].item.(ast.ExprNode) + } + if yyS[yypt-1].item != nil { + x.Order = yyS[yypt-1].item.(*ast.OrderByClause) + } + if yyS[yypt-0].item != nil { + x.Limit = yyS[yypt-0].item.(*ast.Limit) + } + + parser.yyVAL.statement = x + } + case 222: + { + // Multiple Table + x := &ast.DeleteStmt{ + Priority: yyS[yypt-6].item.(mysql.PriorityEnum), + Quick: yyS[yypt-5].item.(bool), + IgnoreErr: yyS[yypt-4].item.(bool), + IsMultiTable: true, + BeforeFrom: true, + Tables: &ast.DeleteTableList{Tables: yyS[yypt-3].item.([]*ast.TableName)}, + TableRefs: &ast.TableRefsClause{TableRefs: yyS[yypt-1].item.(*ast.Join)}, + } + if yyS[yypt-7].item != nil { + x.TableHints = yyS[yypt-7].item.([]*ast.TableOptimizerHint) + } + if yyS[yypt-0].item != nil { + x.Where = yyS[yypt-0].item.(ast.ExprNode) + } + parser.yyVAL.statement = x + } + case 223: + { + // Multiple Table + x := &ast.DeleteStmt{ + Priority: yyS[yypt-7].item.(mysql.PriorityEnum), + Quick: yyS[yypt-6].item.(bool), + IgnoreErr: yyS[yypt-5].item.(bool), + IsMultiTable: true, + Tables: &ast.DeleteTableList{Tables: yyS[yypt-3].item.([]*ast.TableName)}, + TableRefs: &ast.TableRefsClause{TableRefs: yyS[yypt-1].item.(*ast.Join)}, + } + if yyS[yypt-8].item != nil { + x.TableHints = yyS[yypt-8].item.([]*ast.TableOptimizerHint) + } + if yyS[yypt-0].item != nil { + x.Where = yyS[yypt-0].item.(ast.ExprNode) + } + parser.yyVAL.statement = x + } + case 225: + { + parser.yyVAL.statement = &ast.DropDatabaseStmt{IfExists: yyS[yypt-1].item.(bool), Name: yyS[yypt-0].item.(string)} + } + case 226: + { + parser.yyVAL.statement = &ast.DropIndexStmt{IfExists: yyS[yypt-3].item.(bool), IndexName: yyS[yypt-2].ident, Table: yyS[yypt-0].item.(*ast.TableName)} + } + case 227: + { + parser.yyVAL.statement = &ast.DropTableStmt{Tables: yyS[yypt-1].item.([]*ast.TableName)} + } + case 228: + { + parser.yyVAL.statement = &ast.DropTableStmt{IfExists: true, Tables: yyS[yypt-1].item.([]*ast.TableName)} + } + case 229: + { + parser.yyVAL.statement = &ast.DoStmt{} + } + case 230: + { + parser.yyVAL.statement = &ast.DropUserStmt{IfExists: false, UserList: yyS[yypt-0].item.([]*auth.UserIdentity)} + } + case 231: + { + parser.yyVAL.statement = &ast.DropUserStmt{IfExists: true, UserList: yyS[yypt-0].item.([]*auth.UserIdentity)} + } + case 232: + { + parser.yyVAL.statement = &ast.DropStatsStmt{Table: yyS[yypt-0].item.(*ast.TableName)} + } + case 240: + { + parser.yyVAL.statement = nil + } + case 241: + { + parser.yyVAL.statement = &ast.TraceStmt{ + Stmt: yyS[yypt-0].statement, + Format: "json", + } + startOffset := parser.startOffset(&yyS[yypt]) + yyS[yypt-0].statement.SetText(string(parser.src[startOffset:])) + } + case 242: + { + parser.yyVAL.statement = &ast.TraceStmt{ + Stmt: yyS[yypt-0].statement, + Format: yyS[yypt-1].ident, + } + startOffset := parser.startOffset(&yyS[yypt]) + yyS[yypt-0].statement.SetText(string(parser.src[startOffset:])) + } + case 246: + { + parser.yyVAL.statement = &ast.ExplainStmt{ + Stmt: &ast.ShowStmt{ + Tp: ast.ShowColumns, + Table: yyS[yypt-0].item.(*ast.TableName), + }, + } + } + case 247: + { + parser.yyVAL.statement = &ast.ExplainStmt{ + Stmt: &ast.ShowStmt{ + Tp: ast.ShowColumns, + Table: yyS[yypt-1].item.(*ast.TableName), + Column: yyS[yypt-0].item.(*ast.ColumnName), + }, + } + } + case 248: + { + parser.yyVAL.statement = &ast.ExplainStmt{ + Stmt: yyS[yypt-0].statement, + Format: "row", + } + } + case 249: + { + parser.yyVAL.statement = &ast.ExplainStmt{ + Stmt: yyS[yypt-0].statement, + Format: yyS[yypt-1].ident, + } + } + case 250: + { + parser.yyVAL.statement = &ast.ExplainStmt{ + Stmt: yyS[yypt-0].statement, + Format: "row", + Analyze: true, + } + } + case 251: + { + parser.yyVAL.item = getUint64FromNUM(yyS[yypt-0].item) + } + case 253: + { + v := yyS[yypt-2].ident + v = strings.TrimPrefix(v, "@") + parser.yyVAL.expr = &ast.VariableExpr{ + Name: v, + IsGlobal: false, + IsSystem: false, + Value: yyS[yypt-0].expr, + } + } + case 254: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LogicOr, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 255: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LogicXor, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 256: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LogicAnd, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 257: + { + expr, ok := yyS[yypt-0].expr.(*ast.ExistsSubqueryExpr) + if ok { + expr.Not = true + parser.yyVAL.expr = yyS[yypt-0].expr + } else { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Not, V: yyS[yypt-0].expr} + } + } + case 258: + { + parser.yyVAL.expr = &ast.IsTruthExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool), True: int64(1)} + } + case 259: + { + parser.yyVAL.expr = &ast.IsTruthExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool), True: int64(0)} + } + case 260: + { + /* https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_is */ + parser.yyVAL.expr = &ast.IsNullExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool)} + } + case 262: + { + parser.yyVAL.expr = &ast.MaxValueExpr{} + } + case 263: + { + parser.yyVAL.expr = yyS[yypt-0].expr + } + case 268: + { + parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} + } + case 269: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) + } + case 270: + { + parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} + } + case 271: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) + } + case 272: + { + parser.yyVAL.item = []ast.ExprNode{} + } + case 274: + { + parser.yyVAL.item = []ast.ExprNode{} + } + case 275: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 276: + { + expr := ast.NewValueExpr(yyS[yypt-0].item) + parser.yyVAL.item = []ast.ExprNode{expr} + } + case 277: + { + parser.yyVAL.expr = &ast.IsNullExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool)} + } + case 278: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: yyS[yypt-1].item.(opcode.Op), L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 279: + { + sq := yyS[yypt-0].expr.(*ast.SubqueryExpr) + sq.MultiRows = true + parser.yyVAL.expr = &ast.CompareSubqueryExpr{Op: yyS[yypt-2].item.(opcode.Op), L: yyS[yypt-3].expr, R: sq, All: yyS[yypt-1].item.(bool)} + } + case 280: + { + v := yyS[yypt-2].ident + v = strings.TrimPrefix(v, "@") + variable := &ast.VariableExpr{ + Name: v, + IsGlobal: false, + IsSystem: false, + Value: yyS[yypt-0].expr, + } + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: yyS[yypt-3].item.(opcode.Op), L: yyS[yypt-4].expr, R: variable} + } + case 282: + { + parser.yyVAL.item = opcode.GE + } + case 283: + { + parser.yyVAL.item = opcode.GT + } + case 284: + { + parser.yyVAL.item = opcode.LE + } + case 285: + { + parser.yyVAL.item = opcode.LT + } + case 286: + { + parser.yyVAL.item = opcode.NE + } + case 287: + { + parser.yyVAL.item = opcode.NE + } + case 288: + { + parser.yyVAL.item = opcode.EQ + } + case 289: + { + parser.yyVAL.item = opcode.NullEQ + } + case 290: + { + parser.yyVAL.item = true + } + case 291: + { + parser.yyVAL.item = false + } + case 292: + { + parser.yyVAL.item = true + } + case 293: + { + parser.yyVAL.item = false + } + case 294: + { + parser.yyVAL.item = true + } + case 295: + { + parser.yyVAL.item = false + } + case 296: + { + parser.yyVAL.item = true + } + case 297: + { + parser.yyVAL.item = false + } + case 298: + { + parser.yyVAL.item = true + } + case 299: + { + parser.yyVAL.item = false + } + case 300: + { + parser.yyVAL.item = false + } + case 301: + { + parser.yyVAL.item = false + } + case 302: + { + parser.yyVAL.item = true + } + case 303: + { + parser.yyVAL.expr = &ast.PatternInExpr{Expr: yyS[yypt-4].expr, Not: !yyS[yypt-3].item.(bool), List: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 304: + { + sq := yyS[yypt-0].expr.(*ast.SubqueryExpr) + sq.MultiRows = true + parser.yyVAL.expr = &ast.PatternInExpr{Expr: yyS[yypt-2].expr, Not: !yyS[yypt-1].item.(bool), Sel: sq} + } + case 305: + { + parser.yyVAL.expr = &ast.BetweenExpr{ + Expr: yyS[yypt-4].expr, + Left: yyS[yypt-2].expr, + Right: yyS[yypt-0].expr, + Not: !yyS[yypt-3].item.(bool), + } + } + case 306: + { + escape := yyS[yypt-0].item.(string) + if len(escape) > 1 { + yylex.Errorf("Incorrect arguments %s to ESCAPE", escape) + return 1 + } else if len(escape) == 0 { + escape = "\\" + } + parser.yyVAL.expr = &ast.PatternLikeExpr{ + Expr: yyS[yypt-3].expr, + Pattern: yyS[yypt-1].expr, + Not: !yyS[yypt-2].item.(bool), + Escape: escape[0], + } + } + case 307: + { + parser.yyVAL.expr = &ast.PatternRegexpExpr{Expr: yyS[yypt-2].expr, Pattern: yyS[yypt-0].expr, Not: !yyS[yypt-1].item.(bool)} + } + case 311: + { + parser.yyVAL.item = "\\" + } + case 312: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 313: + { + parser.yyVAL.item = &ast.SelectField{WildCard: &ast.WildCardField{}} + } + case 314: + { + wildCard := &ast.WildCardField{Table: model.NewCIStr(yyS[yypt-2].ident)} + parser.yyVAL.item = &ast.SelectField{WildCard: wildCard} + } + case 315: + { + wildCard := &ast.WildCardField{Schema: model.NewCIStr(yyS[yypt-4].ident), Table: model.NewCIStr(yyS[yypt-2].ident)} + parser.yyVAL.item = &ast.SelectField{WildCard: wildCard} + } + case 316: + { + expr := yyS[yypt-1].expr + asName := yyS[yypt-0].item.(string) + parser.yyVAL.item = &ast.SelectField{Expr: expr, AsName: model.NewCIStr(asName)} + } + case 317: + { + /* + * ODBC escape syntax. + * See https://dev.mysql.com/doc/refman/5.7/en/expressions.html + */ + expr := yyS[yypt-2].expr + asName := yyS[yypt-0].item.(string) + parser.yyVAL.item = &ast.SelectField{Expr: expr, AsName: model.NewCIStr(asName)} + } + case 318: + { + parser.yyVAL.item = "" + } + case 319: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 320: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 321: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 322: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 323: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 324: + { + field := yyS[yypt-0].item.(*ast.SelectField) + field.Offset = parser.startOffset(&yyS[yypt]) + parser.yyVAL.item = []*ast.SelectField{field} + } + case 325: + { + + fl := yyS[yypt-2].item.([]*ast.SelectField) + last := fl[len(fl)-1] + if last.Expr != nil && last.AsName.O == "" { + lastEnd := parser.endOffset(&yyS[yypt-1]) + last.SetText(parser.src[last.Offset:lastEnd]) + } + newField := yyS[yypt-0].item.(*ast.SelectField) + newField.Offset = parser.startOffset(&yyS[yypt]) + parser.yyVAL.item = append(fl, newField) + } + case 326: + { + parser.yyVAL.item = &ast.GroupByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} + } + case 327: + { + parser.yyVAL.item = nil + } + case 328: + { + parser.yyVAL.item = &ast.HavingClause{Expr: yyS[yypt-0].expr} + } + case 329: + { + parser.yyVAL.item = false + } + case 330: + { + parser.yyVAL.item = true + } + case 331: + { + parser.yyVAL.item = false + } + case 332: + { + parser.yyVAL.item = true + } + case 333: + { + parser.yyVAL.item = false + } + case 334: + { + parser.yyVAL.item = true + } + case 335: + { + parser.yyVAL.item = "" + } + case 336: + { + //"index name" + parser.yyVAL.item = yyS[yypt-0].ident + } + case 337: + { + parser.yyVAL.item = nil + } + case 338: + { + // Merge the options + if yyS[yypt-1].item == nil { + parser.yyVAL.item = yyS[yypt-0].item + } else { + opt1 := yyS[yypt-1].item.(*ast.IndexOption) + opt2 := yyS[yypt-0].item.(*ast.IndexOption) + if len(opt2.Comment) > 0 { + opt1.Comment = opt2.Comment + } else if opt2.Tp != 0 { + opt1.Tp = opt2.Tp + } + parser.yyVAL.item = opt1 + } + } + case 339: + { + parser.yyVAL.item = &ast.IndexOption{ + // TODO bug should be fix here! + // KeyBlockSize: $1.(uint64), + } + } + case 340: + { + parser.yyVAL.item = &ast.IndexOption{ + Tp: yyS[yypt-0].item.(model.IndexType), + } + } + case 341: + { + parser.yyVAL.item = &ast.IndexOption{ + Comment: yyS[yypt-0].ident, + } + } + case 342: + { + parser.yyVAL.item = model.IndexTypeBtree + } + case 343: + { + parser.yyVAL.item = model.IndexTypeHash + } + case 344: + { + parser.yyVAL.item = nil + } + case 345: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 562: + { + x := yyS[yypt-1].item.(*ast.InsertStmt) + x.Priority = yyS[yypt-5].item.(mysql.PriorityEnum) + x.IgnoreErr = yyS[yypt-4].item.(bool) + // Wraps many layers here so that it can be processed the same way as select statement. + ts := &ast.TableSource{Source: yyS[yypt-2].item.(*ast.TableName)} + x.Table = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}} + if yyS[yypt-0].item != nil { + x.OnDuplicate = yyS[yypt-0].item.([]*ast.Assignment) + } + parser.yyVAL.statement = x + } + case 565: + { + parser.yyVAL.item = &ast.InsertStmt{ + Columns: yyS[yypt-3].item.([]*ast.ColumnName), + Lists: yyS[yypt-0].item.([][]ast.ExprNode), + } + } + case 566: + { + parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-2].item.([]*ast.ColumnName), Select: yyS[yypt-0].statement.(*ast.SelectStmt)} + } + case 567: + { + parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-4].item.([]*ast.ColumnName), Select: yyS[yypt-1].statement.(*ast.SelectStmt)} + } + case 568: + { + parser.yyVAL.item = &ast.InsertStmt{Columns: yyS[yypt-2].item.([]*ast.ColumnName), Select: yyS[yypt-0].statement.(*ast.UnionStmt)} + } + case 569: + { + parser.yyVAL.item = &ast.InsertStmt{Lists: yyS[yypt-0].item.([][]ast.ExprNode)} + } + case 570: + { + parser.yyVAL.item = &ast.InsertStmt{Select: yyS[yypt-1].statement.(*ast.SelectStmt)} + } + case 571: + { + parser.yyVAL.item = &ast.InsertStmt{Select: yyS[yypt-0].statement.(*ast.SelectStmt)} + } + case 572: + { + parser.yyVAL.item = &ast.InsertStmt{Select: yyS[yypt-0].statement.(*ast.UnionStmt)} + } + case 573: + { + parser.yyVAL.item = &ast.InsertStmt{Setlist: yyS[yypt-0].item.([]*ast.Assignment)} + } + case 576: + { + parser.yyVAL.item = [][]ast.ExprNode{yyS[yypt-0].item.([]ast.ExprNode)} + } + case 577: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([][]ast.ExprNode), yyS[yypt-0].item.([]ast.ExprNode)) + } + case 578: + { + parser.yyVAL.item = yyS[yypt-1].item + } + case 579: + { + parser.yyVAL.item = []ast.ExprNode{} + } + case 581: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) + } + case 582: + { + parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} + } + case 584: + { + parser.yyVAL.expr = &ast.DefaultExpr{} + } + case 585: + { + parser.yyVAL.item = &ast.Assignment{ + Column: yyS[yypt-2].item.(*ast.ColumnName), + Expr: yyS[yypt-0].expr, + } + } + case 586: + { + parser.yyVAL.item = []*ast.Assignment{} + } + case 587: + { + parser.yyVAL.item = []*ast.Assignment{yyS[yypt-0].item.(*ast.Assignment)} + } + case 588: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.Assignment), yyS[yypt-0].item.(*ast.Assignment)) + } + case 589: + { + parser.yyVAL.item = nil + } + case 590: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 591: + { + x := yyS[yypt-0].item.(*ast.InsertStmt) + x.IsReplace = true + x.Priority = yyS[yypt-3].item.(mysql.PriorityEnum) + ts := &ast.TableSource{Source: yyS[yypt-1].item.(*ast.TableName)} + x.Table = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}} + parser.yyVAL.statement = x + } + case 592: + { + parser.yyVAL.ident = ast.DateLiteral + } + case 593: + { + parser.yyVAL.ident = ast.TimeLiteral + } + case 594: + { + parser.yyVAL.ident = ast.TimestampLiteral + } + case 595: + { + parser.yyVAL.expr = ast.NewValueExpr(false) + } + case 596: + { + parser.yyVAL.expr = ast.NewValueExpr(nil) + } + case 597: + { + parser.yyVAL.expr = ast.NewValueExpr(true) + } + case 598: + { + parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item) + } + case 599: + { + parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item) + } + case 600: + { + parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item) + } + case 601: + { + parser.yyVAL.expr = yyS[yypt-0].expr + } + case 602: + { + // See https://dev.mysql.com/doc/refman/5.7/en/charset-literal.html + co, err := charset.GetDefaultCollation(yyS[yypt-1].ident) + if err != nil { + yylex.Errorf("Get collation error for charset: %s", yyS[yypt-1].ident) + return 1 + } + expr := ast.NewValueExpr(yyS[yypt-0].ident) + tp := expr.GetType() + tp.Charset = yyS[yypt-1].ident + tp.Collate = co + if tp.Collate == charset.CollationBin { + tp.Flag |= mysql.BinaryFlag + } + parser.yyVAL.expr = expr + } + case 603: + { + parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item) + } + case 604: + { + parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item) + } + case 605: + { + expr := ast.NewValueExpr(yyS[yypt-0].ident) + parser.yyVAL.expr = expr + } + case 606: + { + valExpr := yyS[yypt-1].expr.(ast.ValueExpr) + strLit := valExpr.GetString() + expr := ast.NewValueExpr(strLit + yyS[yypt-0].ident) + // Fix #4239, use first string literal as projection name. + if valExpr.GetProjectionOffset() >= 0 { + expr.SetProjectionOffset(valExpr.GetProjectionOffset()) + } else { + expr.SetProjectionOffset(len(strLit)) + } + parser.yyVAL.expr = expr + } + case 607: + { + parser.yyVAL.item = &ast.OrderByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} + } + case 608: + { + parser.yyVAL.item = []*ast.ByItem{yyS[yypt-0].item.(*ast.ByItem)} + } + case 609: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.ByItem), yyS[yypt-0].item.(*ast.ByItem)) + } + case 610: + { + expr := yyS[yypt-1].expr + valueExpr, ok := expr.(ast.ValueExpr) + if ok { + position, isPosition := valueExpr.GetValue().(int64) + if isPosition { + expr = &ast.PositionExpr{N: int(position)} + } + } + parser.yyVAL.item = &ast.ByItem{Expr: expr, Desc: yyS[yypt-0].item.(bool)} + } + case 611: + { + parser.yyVAL.item = false // ASC by default + } + case 612: + { + parser.yyVAL.item = false + } + case 613: + { + parser.yyVAL.item = true + } + case 614: + { + parser.yyVAL.item = nil + } + case 615: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 616: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Or, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 617: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.And, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 618: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.LeftShift, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 619: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.RightShift, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 620: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Plus, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 621: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Minus, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 622: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr("DATE_ADD"), + Args: []ast.ExprNode{ + yyS[yypt-4].expr, + yyS[yypt-1].expr, + ast.NewValueExpr(yyS[yypt-0].ident), + }, + } + } + case 623: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr("DATE_SUB"), + Args: []ast.ExprNode{ + yyS[yypt-4].expr, + yyS[yypt-1].expr, + ast.NewValueExpr(yyS[yypt-0].ident), + }, + } + } + case 624: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mul, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 625: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Div, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 626: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mod, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 627: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.IntDiv, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 628: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mod, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 629: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Xor, L: yyS[yypt-2].expr, R: yyS[yypt-0].expr} + } + case 631: + { + parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Name: model.NewCIStr(yyS[yypt-0].ident), + }} + } + case 632: + { + parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Table: model.NewCIStr(yyS[yypt-2].ident), + Name: model.NewCIStr(yyS[yypt-0].ident), + }} + } + case 633: + { + parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Table: model.NewCIStr(yyS[yypt-2].ident), + Name: model.NewCIStr(yyS[yypt-0].ident), + }} + } + case 634: + { + parser.yyVAL.expr = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Schema: model.NewCIStr(yyS[yypt-4].ident), + Table: model.NewCIStr(yyS[yypt-2].ident), + Name: model.NewCIStr(yyS[yypt-0].ident), + }} + } + case 639: + { + // TODO: Create a builtin function hold expr and collation. When do evaluation, convert expr result using the collation. + parser.yyVAL.expr = yyS[yypt-2].expr + } + case 640: + { + parser.yyVAL.expr = yyS[yypt-0].item.(*ast.WindowFuncExpr) + } + case 642: + { + parser.yyVAL.expr = ast.NewParamMarkerExpr(yyS[yypt].offset) + } + case 645: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Not, V: yyS[yypt-0].expr} + } + case 646: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.BitNeg, V: yyS[yypt-0].expr} + } + case 647: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Minus, V: yyS[yypt-0].expr} + } + case 648: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Plus, V: yyS[yypt-0].expr} + } + case 649: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.Concat), Args: []ast.ExprNode{yyS[yypt-2].expr, yyS[yypt-0].expr}} + } + case 650: + { + parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Not, V: yyS[yypt-0].expr} + } + case 652: + { + startOffset := parser.startOffset(&yyS[yypt-1]) + endOffset := parser.endOffset(&yyS[yypt]) + expr := yyS[yypt-1].expr + expr.SetText(parser.src[startOffset:endOffset]) + parser.yyVAL.expr = &ast.ParenthesesExpr{Expr: expr} + } + case 653: + { + values := append(yyS[yypt-3].item.([]ast.ExprNode), yyS[yypt-1].expr) + parser.yyVAL.expr = &ast.RowExpr{Values: values} + } + case 654: + { + values := append(yyS[yypt-3].item.([]ast.ExprNode), yyS[yypt-1].expr) + parser.yyVAL.expr = &ast.RowExpr{Values: values} + } + case 655: + { + sq := yyS[yypt-0].expr.(*ast.SubqueryExpr) + sq.Exists = true + parser.yyVAL.expr = &ast.ExistsSubqueryExpr{Sel: sq} + } + case 656: + { + // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#operator_binary + x := types.NewFieldType(mysql.TypeString) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + parser.yyVAL.expr = &ast.FuncCastExpr{ + Expr: yyS[yypt-0].expr, + Tp: x, + FunctionType: ast.CastBinaryOperator, + } + } + case 657: + { + /* See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast */ + tp := yyS[yypt-1].item.(*types.FieldType) + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.Tp) + if tp.Flen == types.UnspecifiedLength { + tp.Flen = defaultFlen + } + if tp.Decimal == types.UnspecifiedLength { + tp.Decimal = defaultDecimal + } + parser.yyVAL.expr = &ast.FuncCastExpr{ + Expr: yyS[yypt-3].expr, + Tp: tp, + FunctionType: ast.CastFunction, + } + } + case 658: + { + x := &ast.CaseExpr{WhenClauses: yyS[yypt-2].item.([]*ast.WhenClause)} + if yyS[yypt-3].expr != nil { + x.Value = yyS[yypt-3].expr + } + if yyS[yypt-1].item != nil { + x.ElseClause = yyS[yypt-1].item.(ast.ExprNode) + } + parser.yyVAL.expr = x + } + case 659: + { + // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert + tp := yyS[yypt-1].item.(*types.FieldType) + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.Tp) + if tp.Flen == types.UnspecifiedLength { + tp.Flen = defaultFlen + } + if tp.Decimal == types.UnspecifiedLength { + tp.Decimal = defaultDecimal + } + parser.yyVAL.expr = &ast.FuncCastExpr{ + Expr: yyS[yypt-3].expr, + Tp: tp, + FunctionType: ast.CastConvertFunction, + } + } + case 660: + { + // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert + charset1 := ast.NewValueExpr(yyS[yypt-1].item) + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{yyS[yypt-3].expr, charset1}, + } + } + case 661: + { + parser.yyVAL.expr = &ast.DefaultExpr{Name: yyS[yypt-1].expr.(*ast.ColumnNameExpr).Name} + } + case 662: + { + parser.yyVAL.expr = &ast.ValuesExpr{Column: yyS[yypt-1].expr.(*ast.ColumnNameExpr)} + } + case 663: + { + expr := ast.NewValueExpr(yyS[yypt-0].ident) + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{yyS[yypt-2].expr, expr}} + } + case 664: + { + expr := ast.NewValueExpr(yyS[yypt-0].ident) + extract := &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{yyS[yypt-2].expr, expr}} + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONUnquote), Args: []ast.ExprNode{extract}} + } + case 667: + { + parser.yyVAL.item = false + } + case 668: + { + parser.yyVAL.item = true + } + case 669: + { + parser.yyVAL.item = false + } + case 671: + { + parser.yyVAL.item = true + } + case 674: + { + parser.yyVAL.item = true + } + case 715: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 716: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 717: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-1].ident)} + } + case 718: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-2].ident)} + } + case 719: + { + args := []ast.ExprNode{} + if yyS[yypt-0].item != nil { + args = append(args, yyS[yypt-0].item.(ast.ExprNode)) + } + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-1].ident), Args: args} + } + case 720: + { + nilVal := ast.NewValueExpr(nil) + args := yyS[yypt-1].item.([]ast.ExprNode) + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(ast.CharFunc), + Args: append(args, nilVal), + } + } + case 721: + { + charset1 := ast.NewValueExpr(yyS[yypt-1].item) + args := yyS[yypt-3].item.([]ast.ExprNode) + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(ast.CharFunc), + Args: append(args, charset1), + } + } + case 722: + { + expr := ast.NewValueExpr(yyS[yypt-0].ident) + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{expr}} + } + case 723: + { + expr := ast.NewValueExpr(yyS[yypt-0].ident) + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{expr}} + } + case 724: + { + expr := ast.NewValueExpr(yyS[yypt-0].ident) + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{expr}} + } + case 725: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.InsertFunc), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 726: + { + parser.yyVAL.expr = &ast.BinaryOperationExpr{Op: opcode.Mod, L: yyS[yypt-3].expr, R: yyS[yypt-1].expr} + } + case 727: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.PasswordFunc), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 728: + { + // This is ODBC syntax for date and time literals. + // See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html + expr := ast.NewValueExpr(yyS[yypt-1].ident) + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-2].ident), Args: []ast.ExprNode{expr}} + } + case 729: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 730: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 731: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{ + yyS[yypt-3].expr, + yyS[yypt-1].expr, + ast.NewValueExpr("DAY"), + }, + } + } + case 732: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-7].ident), + Args: []ast.ExprNode{ + yyS[yypt-5].expr, + yyS[yypt-2].expr, + ast.NewValueExpr(yyS[yypt-1].ident), + }, + } + } + case 733: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-7].ident), + Args: []ast.ExprNode{ + yyS[yypt-5].expr, + yyS[yypt-2].expr, + ast.NewValueExpr(yyS[yypt-1].ident), + }, + } + } + case 734: + { + timeUnit := ast.NewValueExpr(yyS[yypt-3].ident) + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{timeUnit, yyS[yypt-1].expr}, + } + } + case 735: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{ast.NewValueExpr(yyS[yypt-3].ident), yyS[yypt-1].expr}, + } + } + case 736: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-5].ident), Args: []ast.ExprNode{yyS[yypt-3].expr, yyS[yypt-1].expr}} + } + case 737: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{yyS[yypt-3].expr, yyS[yypt-1].expr}, + } + } + case 738: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{yyS[yypt-3].expr, yyS[yypt-1].expr}, + } + } + case 739: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-7].ident), + Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-3].expr, yyS[yypt-1].expr}, + } + } + case 740: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-7].ident), + Args: []ast.ExprNode{yyS[yypt-5].expr, yyS[yypt-3].expr, yyS[yypt-1].expr}, + } + } + case 741: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-7].ident), + Args: []ast.ExprNode{ast.NewValueExpr(yyS[yypt-5].ident), yyS[yypt-3].expr, yyS[yypt-1].expr}, + } + } + case 742: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-7].ident), + Args: []ast.ExprNode{ast.NewValueExpr(yyS[yypt-5].ident), yyS[yypt-3].expr, yyS[yypt-1].expr}, + } + } + case 743: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-3].ident), + Args: []ast.ExprNode{yyS[yypt-1].expr}, + } + } + case 744: + { + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{yyS[yypt-1].expr, yyS[yypt-3].expr}, + } + } + case 745: + { + nilVal := ast.NewValueExpr(nil) + direction := ast.NewValueExpr(int(yyS[yypt-3].item.(ast.TrimDirectionType))) + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].ident), + Args: []ast.ExprNode{yyS[yypt-1].expr, nilVal, direction}, + } + } + case 746: + { + direction := ast.NewValueExpr(int(yyS[yypt-4].item.(ast.TrimDirectionType))) + parser.yyVAL.expr = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-6].ident), + Args: []ast.ExprNode{yyS[yypt-1].expr, yyS[yypt-3].expr, direction}, + } + } + case 747: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 748: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 749: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 750: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 755: + { + parser.yyVAL.item = ast.TrimBoth + } + case 756: + { + parser.yyVAL.item = ast.TrimLeading + } + case 757: + { + parser.yyVAL.item = ast.TrimTrailing + } + case 758: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} + } + } + case 759: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 760: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 761: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 762: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 763: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 764: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 765: + { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: yyS[yypt-1].item.([]ast.ExprNode), Distinct: true} + } + case 766: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 767: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}} + } + } + case 768: + { + args := []ast.ExprNode{ast.NewValueExpr(1)} + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: args, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-4].ident, Args: args} + } + } + case 769: + { + args := yyS[yypt-3].item.([]ast.ExprNode) + args = append(args, yyS[yypt-1].item.(ast.ExprNode)) + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-6].ident, Args: args, Distinct: yyS[yypt-4].item.(bool)} + } + case 770: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} + } + } + case 771: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} + } + } + case 772: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} + } + } + case 773: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} + } + } + case 774: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool), Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))} + } else { + parser.yyVAL.expr = &ast.AggregateFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Distinct: yyS[yypt-3].item.(bool)} + } + } + case 775: + { + parser.yyVAL.item = ast.NewValueExpr(",") + } + case 776: + { + parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].ident) + } + case 777: + { + parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-3].ident), Args: yyS[yypt-1].item.([]ast.ExprNode)} + } + case 778: + { + parser.yyVAL.item = nil + } + case 779: + { + parser.yyVAL.item = nil + } + case 780: + { + expr := ast.NewValueExpr(yyS[yypt-1].item) + parser.yyVAL.item = expr + } + case 781: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 782: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 783: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 784: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 785: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 786: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 787: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 788: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 789: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 790: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 791: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 792: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 793: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 794: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 795: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 796: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 797: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 798: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 799: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 800: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 801: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 802: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 803: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 804: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 805: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 806: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 807: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 808: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 809: + { + parser.yyVAL.ident = strings.ToUpper(yyS[yypt-0].ident) + } + case 810: + { + parser.yyVAL.expr = nil + } + case 811: + { + parser.yyVAL.expr = yyS[yypt-0].expr + } + case 812: + { + parser.yyVAL.item = []*ast.WhenClause{yyS[yypt-0].item.(*ast.WhenClause)} + } + case 813: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.WhenClause), yyS[yypt-0].item.(*ast.WhenClause)) + } + case 814: + { + parser.yyVAL.item = &ast.WhenClause{ + Expr: yyS[yypt-2].expr, + Result: yyS[yypt-0].expr, + } + } + case 815: + { + parser.yyVAL.item = nil + } + case 816: + { + parser.yyVAL.item = yyS[yypt-0].expr + } + case 817: + { + x := types.NewFieldType(mysql.TypeVarString) + x.Flen = yyS[yypt-0].item.(int) // TODO: Flen should be the flen of expression + if x.Flen != types.UnspecifiedLength { + x.Tp = mysql.TypeString + } + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 818: + { + x := types.NewFieldType(mysql.TypeVarString) + x.Flen = yyS[yypt-1].item.(int) // TODO: Flen should be the flen of expression + x.Charset = yyS[yypt-0].item.(*ast.OptBinary).Charset + if yyS[yypt-0].item.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + if x.Charset == "" { + x.Charset = mysql.DefaultCharset + x.Collate = mysql.DefaultCollationName + } + parser.yyVAL.item = x + } + case 819: + { + x := types.NewFieldType(mysql.TypeDate) + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 820: + { + x := types.NewFieldType(mysql.TypeDatetime) + x.Flen, _ = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDatetime) + x.Decimal = yyS[yypt-0].item.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 821: + { + fopt := yyS[yypt-0].item.(*ast.FloatOpt) + x := types.NewFieldType(mysql.TypeNewDecimal) + x.Flen = fopt.Flen + x.Decimal = fopt.Decimal + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 822: + { + x := types.NewFieldType(mysql.TypeDuration) + x.Flen, _ = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDuration) + x.Decimal = yyS[yypt-0].item.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 823: + { + x := types.NewFieldType(mysql.TypeLonglong) + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 824: + { + x := types.NewFieldType(mysql.TypeLonglong) + x.Flag |= mysql.UnsignedFlag | mysql.BinaryFlag + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + parser.yyVAL.item = x + } + case 825: + { + x := types.NewFieldType(mysql.TypeJSON) + x.Flag |= mysql.BinaryFlag | (mysql.ParseToJSONFlag) + x.Charset = mysql.DefaultCharset + x.Collate = mysql.DefaultCollationName + parser.yyVAL.item = x + } + case 826: + { + parser.yyVAL.item = mysql.NoPriority + } + case 827: + { + parser.yyVAL.item = mysql.LowPriority + } + case 828: + { + parser.yyVAL.item = mysql.HighPriority + } + case 829: + { + parser.yyVAL.item = mysql.DelayedPriority + } + case 830: + { + parser.yyVAL.item = &ast.TableName{Name: model.NewCIStr(yyS[yypt-0].ident)} + } + case 831: + { + parser.yyVAL.item = &ast.TableName{Schema: model.NewCIStr(yyS[yypt-2].ident), Name: model.NewCIStr(yyS[yypt-0].ident)} + } + case 832: + { + tbl := []*ast.TableName{yyS[yypt-0].item.(*ast.TableName)} + parser.yyVAL.item = tbl + } + case 833: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.TableName), yyS[yypt-0].item.(*ast.TableName)) + } + case 834: + { + parser.yyVAL.item = false + } + case 835: + { + parser.yyVAL.item = true + } + case 836: + { + var sqlText string + var sqlVar *ast.VariableExpr + switch yyS[yypt-0].item.(type) { + case string: + sqlText = yyS[yypt-0].item.(string) + case *ast.VariableExpr: + sqlVar = yyS[yypt-0].item.(*ast.VariableExpr) + } + parser.yyVAL.statement = &ast.PrepareStmt{ + Name: yyS[yypt-2].ident, + SQLText: sqlText, + SQLVar: sqlVar, + } + } + case 837: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 838: + { + parser.yyVAL.item = yyS[yypt-0].expr.(interface{}) + } + case 839: + { + parser.yyVAL.statement = &ast.ExecuteStmt{Name: yyS[yypt-0].ident} + } + case 840: + { + parser.yyVAL.statement = &ast.ExecuteStmt{ + Name: yyS[yypt-2].ident, + UsingVars: yyS[yypt-0].item.([]ast.ExprNode), + } + } + case 841: + { + parser.yyVAL.item = []ast.ExprNode{yyS[yypt-0].expr} + } + case 842: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.ExprNode), yyS[yypt-0].expr) + } + case 843: + { + parser.yyVAL.statement = &ast.DeallocateStmt{Name: yyS[yypt-0].ident} + } + case 846: + { + parser.yyVAL.statement = &ast.RollbackStmt{} + } + case 847: + { + st := &ast.SelectStmt{ + SelectStmtOpts: yyS[yypt-1].item.(*ast.SelectStmtOpts), + Distinct: yyS[yypt-1].item.(*ast.SelectStmtOpts).Distinct, + Fields: yyS[yypt-0].item.(*ast.FieldList), + } + parser.yyVAL.item = st + } + case 848: + { + st := yyS[yypt-2].item.(*ast.SelectStmt) + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Expr != nil && lastField.AsName.O == "" { + lastEnd := yyS[yypt-1].offset - 1 + lastField.SetText(parser.src[lastField.Offset:lastEnd]) + } + if yyS[yypt-0].item != nil { + st.Where = yyS[yypt-0].item.(ast.ExprNode) + } + } + case 849: + { + st := yyS[yypt-6].item.(*ast.SelectStmt) + st.From = yyS[yypt-4].item.(*ast.TableRefsClause) + if st.SelectStmtOpts.TableHints != nil { + st.TableHints = st.SelectStmtOpts.TableHints + } + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Expr != nil && lastField.AsName.O == "" { + lastEnd := parser.endOffset(&yyS[yypt-5]) + lastField.SetText(parser.src[lastField.Offset:lastEnd]) + } + if yyS[yypt-3].item != nil { + st.Where = yyS[yypt-3].item.(ast.ExprNode) + } + if yyS[yypt-2].item != nil { + st.GroupBy = yyS[yypt-2].item.(*ast.GroupByClause) + } + if yyS[yypt-1].item != nil { + st.Having = yyS[yypt-1].item.(*ast.HavingClause) + } + if yyS[yypt-0].item != nil { + st.WindowSpecs = (yyS[yypt-0].item.([]ast.WindowSpec)) + } + parser.yyVAL.item = st + } + case 850: + { + st := yyS[yypt-3].item.(*ast.SelectStmt) + st.LockTp = yyS[yypt-0].item.(ast.SelectLockType) + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Expr != nil && lastField.AsName.O == "" { + src := parser.src + var lastEnd int + if yyS[yypt-2].item != nil { + lastEnd = yyS[yypt-2].offset - 1 + } else if yyS[yypt-1].item != nil { + lastEnd = yyS[yypt-1].offset - 1 + } else if yyS[yypt-0].item != ast.SelectLockNone { + lastEnd = yyS[yypt].offset - 1 + } else { + lastEnd = len(src) + if src[lastEnd-1] == ';' { + lastEnd-- + } + } + lastField.SetText(src[lastField.Offset:lastEnd]) + } + if yyS[yypt-2].item != nil { + st.OrderBy = yyS[yypt-2].item.(*ast.OrderByClause) + } + if yyS[yypt-1].item != nil { + st.Limit = yyS[yypt-1].item.(*ast.Limit) + } + parser.yyVAL.statement = st + } + case 851: + { + st := yyS[yypt-3].item.(*ast.SelectStmt) + if yyS[yypt-2].item != nil { + st.OrderBy = yyS[yypt-2].item.(*ast.OrderByClause) + } + if yyS[yypt-1].item != nil { + st.Limit = yyS[yypt-1].item.(*ast.Limit) + } + st.LockTp = yyS[yypt-0].item.(ast.SelectLockType) + parser.yyVAL.statement = st + } + case 852: + { + st := yyS[yypt-3].item.(*ast.SelectStmt) + st.LockTp = yyS[yypt-0].item.(ast.SelectLockType) + if yyS[yypt-2].item != nil { + st.OrderBy = yyS[yypt-2].item.(*ast.OrderByClause) + } + if yyS[yypt-1].item != nil { + st.Limit = yyS[yypt-1].item.(*ast.Limit) + } + parser.yyVAL.statement = st + } + case 854: + { + parser.yyVAL.item = nil + } + case 855: + { + parser.yyVAL.item = yyS[yypt-0].item.([]ast.WindowSpec) + } + case 856: + { + parser.yyVAL.item = []ast.WindowSpec{yyS[yypt-0].item.(ast.WindowSpec)} + } + case 857: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.WindowSpec), yyS[yypt-0].item.(ast.WindowSpec)) + } + case 858: + { + var spec = yyS[yypt-0].item.(ast.WindowSpec) + spec.Name = yyS[yypt-2].item.(model.CIStr) + parser.yyVAL.item = spec + } + case 859: + { + parser.yyVAL.item = model.NewCIStr(yyS[yypt-0].ident) + } + case 860: + { + parser.yyVAL.item = yyS[yypt-1].item.(ast.WindowSpec) + } + case 861: + { + spec := ast.WindowSpec{Ref: yyS[yypt-3].item.(model.CIStr)} + if yyS[yypt-2].item != nil { + spec.PartitionBy = yyS[yypt-2].item.(*ast.PartitionByClause) + } + if yyS[yypt-1].item != nil { + spec.OrderBy = yyS[yypt-1].item.(*ast.OrderByClause) + } + if yyS[yypt-0].item != nil { + spec.Frame = yyS[yypt-0].item.(*ast.FrameClause) + } + parser.yyVAL.item = spec + } + case 862: + { + parser.yyVAL.item = model.CIStr{} + } + case 863: + { + parser.yyVAL.item = yyS[yypt-0].item.(model.CIStr) + } + case 864: + { + parser.yyVAL.item = nil + } + case 865: + { + parser.yyVAL.item = &ast.PartitionByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} + } + case 866: + { + parser.yyVAL.item = nil + } + case 867: + { + parser.yyVAL.item = &ast.OrderByClause{Items: yyS[yypt-0].item.([]*ast.ByItem)} + } + case 868: + { + parser.yyVAL.item = nil + } + case 869: + { + parser.yyVAL.item = &ast.FrameClause{ + Type: yyS[yypt-1].item.(ast.FrameType), + Extent: yyS[yypt-0].item.(ast.FrameExtent), + } + } + case 870: + { + parser.yyVAL.item = ast.FrameType(ast.Rows) + } + case 871: + { + parser.yyVAL.item = ast.FrameType(ast.Ranges) + } + case 872: + { + parser.yyVAL.item = ast.FrameType(ast.Groups) + } + case 873: + { + parser.yyVAL.item = ast.FrameExtent{ + Start: yyS[yypt-0].item.(ast.FrameBound), + End: ast.FrameBound{Type: ast.CurrentRow}, + } + } + case 874: + { + parser.yyVAL.item = yyS[yypt-0].item.(ast.FrameExtent) + } + case 875: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, UnBounded: true} + } + case 876: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr(yyS[yypt-1].item)} + } + case 877: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr(yyS[yypt-1].item)} + } + case 878: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr(yyS[yypt-2].expr), Unit: ast.NewValueExpr(yyS[yypt-1].ident)} + } + case 879: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.CurrentRow} + } + case 880: + { + parser.yyVAL.item = ast.FrameExtent{Start: yyS[yypt-2].item.(ast.FrameBound), End: yyS[yypt-0].item.(ast.FrameBound)} + } + case 881: + { + parser.yyVAL.item = yyS[yypt-0].item.(ast.FrameBound) + } + case 882: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Following, UnBounded: true} + } + case 883: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr(yyS[yypt-1].item)} + } + case 884: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr(yyS[yypt-1].item)} + } + case 885: + { + parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr(yyS[yypt-2].expr), Unit: ast.NewValueExpr(yyS[yypt-1].ident)} + } + case 886: + { + parser.yyVAL.item = nil + } + case 887: + { + spec := yyS[yypt-0].item.(ast.WindowSpec) + parser.yyVAL.item = &spec + } + case 888: + { + parser.yyVAL.item = yyS[yypt-0].item.(ast.WindowSpec) + } + case 889: + { + parser.yyVAL.item = ast.WindowSpec{Ref: yyS[yypt-0].item.(model.CIStr)} + } + case 890: + { + parser.yyVAL.item = yyS[yypt-0].item.(ast.WindowSpec) + } + case 891: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 892: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 893: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 894: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 895: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-3].ident, Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 896: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: []ast.ExprNode{yyS[yypt-2].expr}, Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 897: + { + args := []ast.ExprNode{yyS[yypt-4].expr} + if yyS[yypt-3].item != nil { + args = append(args, yyS[yypt-3].item.([]ast.ExprNode)...) + } + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-6].ident, Args: args, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 898: + { + args := []ast.ExprNode{yyS[yypt-4].expr} + if yyS[yypt-3].item != nil { + args = append(args, yyS[yypt-3].item.([]ast.ExprNode)...) + } + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-6].ident, Args: args, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 899: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-3].expr}, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 900: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-5].ident, Args: []ast.ExprNode{yyS[yypt-3].expr}, IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 901: + { + parser.yyVAL.item = &ast.WindowFuncExpr{F: yyS[yypt-8].ident, Args: []ast.ExprNode{yyS[yypt-6].expr, yyS[yypt-4].expr}, FromLast: yyS[yypt-2].item.(bool), IgnoreNull: yyS[yypt-1].item.(bool), Spec: yyS[yypt-0].item.(ast.WindowSpec)} + } + case 902: + { + parser.yyVAL.item = nil + } + case 903: + { + args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item)} + if yyS[yypt-0].item != nil { + args = append(args, yyS[yypt-0].item.(ast.ExprNode)) + } + parser.yyVAL.item = args + } + case 904: + { + args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item)} + if yyS[yypt-0].item != nil { + args = append(args, yyS[yypt-0].item.(ast.ExprNode)) + } + parser.yyVAL.item = args + } + case 905: + { + parser.yyVAL.item = nil + } + case 906: + { + parser.yyVAL.item = yyS[yypt-0].expr + } + case 907: + { + parser.yyVAL.item = false + } + case 908: + { + parser.yyVAL.item = false + } + case 909: + { + parser.yyVAL.item = true + } + case 910: + { + parser.yyVAL.item = false + } + case 911: + { + parser.yyVAL.item = false + } + case 912: + { + parser.yyVAL.item = true + } + case 913: + { + parser.yyVAL.item = &ast.TableRefsClause{TableRefs: yyS[yypt-0].item.(*ast.Join)} + } + case 914: + { + if j, ok := yyS[yypt-0].item.(*ast.Join); ok { + // if $1 is Join, use it directly + parser.yyVAL.item = j + } else { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-0].item.(ast.ResultSetNode), Right: nil} + } + } + case 915: + { + /* from a, b is default cross join */ + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-2].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), Tp: ast.CrossJoin} + } + case 916: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 917: + { + /* + * ODBC escape syntax for outer join is { OJ join_table } + * Use an Identifier for OJ + */ + parser.yyVAL.item = yyS[yypt-1].item + } + case 918: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 919: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 920: + { + tn := yyS[yypt-2].item.(*ast.TableName) + tn.IndexHints = yyS[yypt-0].item.([]*ast.IndexHint) + parser.yyVAL.item = &ast.TableSource{Source: tn, AsName: yyS[yypt-1].item.(model.CIStr)} + } + case 921: + { + st := yyS[yypt-2].statement.(*ast.SelectStmt) + endOffset := parser.endOffset(&yyS[yypt-1]) + parser.setLastSelectFieldText(st, endOffset) + parser.yyVAL.item = &ast.TableSource{Source: yyS[yypt-2].statement.(*ast.SelectStmt), AsName: yyS[yypt-0].item.(model.CIStr)} + } + case 922: + { + parser.yyVAL.item = &ast.TableSource{Source: yyS[yypt-2].statement.(*ast.UnionStmt), AsName: yyS[yypt-0].item.(model.CIStr)} + } + case 923: + { + parser.yyVAL.item = yyS[yypt-1].item + } + case 924: + { + parser.yyVAL.item = model.CIStr{} + } + case 925: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 926: + { + parser.yyVAL.item = model.NewCIStr(yyS[yypt-0].ident) + } + case 927: + { + parser.yyVAL.item = model.NewCIStr(yyS[yypt-0].ident) + } + case 928: + { + parser.yyVAL.item = ast.HintUse + } + case 929: + { + parser.yyVAL.item = ast.HintIgnore + } + case 930: + { + parser.yyVAL.item = ast.HintForce + } + case 931: + { + parser.yyVAL.item = ast.HintForScan + } + case 932: + { + parser.yyVAL.item = ast.HintForJoin + } + case 933: + { + parser.yyVAL.item = ast.HintForOrderBy + } + case 934: + { + parser.yyVAL.item = ast.HintForGroupBy + } + case 935: + { + parser.yyVAL.item = &ast.IndexHint{ + IndexNames: yyS[yypt-1].item.([]model.CIStr), + HintType: yyS[yypt-4].item.(ast.IndexHintType), + HintScope: yyS[yypt-3].item.(ast.IndexHintScope), + } + } + case 936: + { + var nameList []model.CIStr + parser.yyVAL.item = nameList + } + case 937: + { + parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} + } + case 938: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) + } + case 939: + { + parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} + } + case 940: + { + parser.yyVAL.item = []*ast.IndexHint{yyS[yypt-0].item.(*ast.IndexHint)} + } + case 941: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.IndexHint), yyS[yypt-0].item.(*ast.IndexHint)) + } + case 942: + { + var hintList []*ast.IndexHint + parser.yyVAL.item = hintList + } + case 943: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 944: + { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-2].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), Tp: ast.CrossJoin} + } + case 945: + { + on := &ast.OnCondition{Expr: yyS[yypt-0].expr} + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-4].item.(ast.ResultSetNode), Right: yyS[yypt-2].item.(ast.ResultSetNode), Tp: ast.CrossJoin, On: on} + } + case 946: + { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-6].item.(ast.ResultSetNode), Right: yyS[yypt-4].item.(ast.ResultSetNode), Tp: ast.CrossJoin, Using: yyS[yypt-1].item.([]*ast.ColumnName)} + } + case 947: + { + on := &ast.OnCondition{Expr: yyS[yypt-0].expr} + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-6].item.(ast.ResultSetNode), Right: yyS[yypt-2].item.(ast.ResultSetNode), Tp: yyS[yypt-5].item.(ast.JoinType), On: on} + } + case 948: + { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-8].item.(ast.ResultSetNode), Right: yyS[yypt-4].item.(ast.ResultSetNode), Tp: yyS[yypt-7].item.(ast.JoinType), Using: yyS[yypt-1].item.([]*ast.ColumnName)} + } + case 949: + { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-3].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), NaturalJoin: true} + } + case 950: + { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-5].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), Tp: yyS[yypt-3].item.(ast.JoinType), NaturalJoin: true} + } + case 951: + { + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-2].item.(ast.ResultSetNode), Right: yyS[yypt-0].item.(ast.ResultSetNode), StraightJoin: true} + } + case 952: + { + on := &ast.OnCondition{Expr: yyS[yypt-0].expr} + parser.yyVAL.item = &ast.Join{Left: yyS[yypt-4].item.(ast.ResultSetNode), Right: yyS[yypt-2].item.(ast.ResultSetNode), StraightJoin: true, On: on} + } + case 953: + { + parser.yyVAL.item = ast.LeftJoin + } + case 954: + { + parser.yyVAL.item = ast.RightJoin + } + case 960: + { + parser.yyVAL.item = nil + } + case 961: + { + parser.yyVAL.item = &ast.Limit{Count: yyS[yypt-0].item.(ast.ValueExpr)} + } + case 962: + { + parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].item) + } + case 963: + { + parser.yyVAL.item = ast.NewParamMarkerExpr(yyS[yypt].offset) + } + case 964: + { + parser.yyVAL.item = nil + } + case 965: + { + parser.yyVAL.item = &ast.Limit{Count: yyS[yypt-0].item.(ast.ExprNode)} + } + case 966: + { + parser.yyVAL.item = &ast.Limit{Offset: yyS[yypt-2].item.(ast.ExprNode), Count: yyS[yypt-0].item.(ast.ExprNode)} + } + case 967: + { + parser.yyVAL.item = &ast.Limit{Offset: yyS[yypt-0].item.(ast.ExprNode), Count: yyS[yypt-2].item.(ast.ExprNode)} + } + case 968: + { + opt := &ast.SelectStmtOpts{} + if yyS[yypt-5].item != nil { + opt.TableHints = yyS[yypt-5].item.([]*ast.TableOptimizerHint) + } + if yyS[yypt-4].item != nil { + opt.Distinct = yyS[yypt-4].item.(bool) + } + if yyS[yypt-3].item != nil { + opt.Priority = yyS[yypt-3].item.(mysql.PriorityEnum) + } + if yyS[yypt-2].item != nil { + opt.SQLCache = yyS[yypt-2].item.(bool) + } + if yyS[yypt-1].item != nil { + opt.CalcFoundRows = yyS[yypt-1].item.(bool) + } + if yyS[yypt-0].item != nil { + opt.StraightJoin = yyS[yypt-0].item.(bool) + } + + parser.yyVAL.item = opt + } + case 969: + { + parser.yyVAL.item = nil + } + case 970: + { + parser.yyVAL.item = yyS[yypt-1].item + } + case 971: + { + parser.yyVAL.item = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} + } + case 972: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]model.CIStr), model.NewCIStr(yyS[yypt-0].ident)) + } + case 973: + { + parser.yyVAL.item = []*ast.TableOptimizerHint{yyS[yypt-0].item.(*ast.TableOptimizerHint)} + } + case 974: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.TableOptimizerHint), yyS[yypt-0].item.(*ast.TableOptimizerHint)) + } + case 975: + { + parser.yyVAL.item = &ast.TableOptimizerHint{HintName: model.NewCIStr(yyS[yypt-3].ident), Tables: yyS[yypt-1].item.([]model.CIStr)} + } + case 976: + { + parser.yyVAL.item = &ast.TableOptimizerHint{HintName: model.NewCIStr(yyS[yypt-3].ident), Tables: yyS[yypt-1].item.([]model.CIStr)} + } + case 977: + { + parser.yyVAL.item = &ast.TableOptimizerHint{HintName: model.NewCIStr(yyS[yypt-3].ident), Tables: yyS[yypt-1].item.([]model.CIStr)} + } + case 978: + { + parser.yyVAL.item = &ast.TableOptimizerHint{HintName: model.NewCIStr(yyS[yypt-3].ident), MaxExecutionTime: getUint64FromNUM(yyS[yypt-1].item)} + } + case 979: + { + parser.yyVAL.item = false + } + case 980: + { + parser.yyVAL.item = true + } + case 981: + { + parser.yyVAL.item = true + } + case 982: + { + parser.yyVAL.item = true + } + case 983: + { + parser.yyVAL.item = false + } + case 984: + { + parser.yyVAL.item = false + } + case 985: + { + parser.yyVAL.item = true + } + case 986: + { + parser.yyVAL.item = &ast.FieldList{Fields: yyS[yypt-0].item.([]*ast.SelectField)} + } + case 987: + { + parser.yyVAL.item = nil + } + case 989: + { + s := yyS[yypt-1].statement.(*ast.SelectStmt) + endOffset := parser.endOffset(&yyS[yypt]) + parser.setLastSelectFieldText(s, endOffset) + src := parser.src + // See the implementation of yyParse function + s.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + parser.yyVAL.expr = &ast.SubqueryExpr{Query: s} + } + case 990: + { + s := yyS[yypt-1].statement.(*ast.UnionStmt) + src := parser.src + // See the implementation of yyParse function + s.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + parser.yyVAL.expr = &ast.SubqueryExpr{Query: s} + } + case 991: + { + parser.yyVAL.item = ast.SelectLockNone + } + case 992: + { + parser.yyVAL.item = ast.SelectLockForUpdate + } + case 993: + { + parser.yyVAL.item = ast.SelectLockInShareMode + } + case 994: + { + st := yyS[yypt-3].item.(*ast.SelectStmt) + union := yyS[yypt-6].item.(*ast.UnionStmt) + st.IsAfterUnionDistinct = yyS[yypt-4].item.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-5]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if yyS[yypt-2].item != nil { + union.OrderBy = yyS[yypt-2].item.(*ast.OrderByClause) + } + if yyS[yypt-1].item != nil { + union.Limit = yyS[yypt-1].item.(*ast.Limit) + } + if yyS[yypt-2].item == nil && yyS[yypt-1].item == nil { + st.LockTp = yyS[yypt-0].item.(ast.SelectLockType) + } + parser.yyVAL.statement = union + } + case 995: + { + st := yyS[yypt-3].item.(*ast.SelectStmt) + union := yyS[yypt-6].item.(*ast.UnionStmt) + st.IsAfterUnionDistinct = yyS[yypt-4].item.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-5]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if yyS[yypt-2].item != nil { + union.OrderBy = yyS[yypt-2].item.(*ast.OrderByClause) + } + if yyS[yypt-1].item != nil { + union.Limit = yyS[yypt-1].item.(*ast.Limit) + } + if yyS[yypt-2].item == nil && yyS[yypt-1].item == nil { + st.LockTp = yyS[yypt-0].item.(ast.SelectLockType) + } + parser.yyVAL.statement = union + } + case 996: + { + st := yyS[yypt-3].item.(*ast.SelectStmt) + union := yyS[yypt-6].item.(*ast.UnionStmt) + st.IsAfterUnionDistinct = yyS[yypt-4].item.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-5]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if yyS[yypt-2].item != nil { + union.OrderBy = yyS[yypt-2].item.(*ast.OrderByClause) + } + if yyS[yypt-1].item != nil { + union.Limit = yyS[yypt-1].item.(*ast.Limit) + } + if yyS[yypt-2].item == nil && yyS[yypt-1].item == nil { + st.LockTp = yyS[yypt-0].item.(ast.SelectLockType) + } + parser.yyVAL.statement = union + } + case 997: + { + union := yyS[yypt-7].item.(*ast.UnionStmt) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-6]) + parser.setLastSelectFieldText(lastSelect, endOffset) + st := yyS[yypt-3].statement.(*ast.SelectStmt) + st.IsInBraces = true + st.IsAfterUnionDistinct = yyS[yypt-5].item.(bool) + endOffset = parser.endOffset(&yyS[yypt-2]) + parser.setLastSelectFieldText(st, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if yyS[yypt-1].item != nil { + union.OrderBy = yyS[yypt-1].item.(*ast.OrderByClause) + } + if yyS[yypt-0].item != nil { + union.Limit = yyS[yypt-0].item.(*ast.Limit) + } + parser.yyVAL.statement = union + } + case 998: + { + selectList := &ast.UnionSelectList{Selects: []*ast.SelectStmt{yyS[yypt-0].item.(*ast.SelectStmt)}} + parser.yyVAL.item = &ast.UnionStmt{ + SelectList: selectList, + } + } + case 999: + { + union := yyS[yypt-3].item.(*ast.UnionStmt) + st := yyS[yypt-0].item.(*ast.SelectStmt) + st.IsAfterUnionDistinct = yyS[yypt-1].item.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-2]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + parser.yyVAL.item = union + } + case 1000: + { + parser.yyVAL.item = yyS[yypt-0].statement.(interface{}) + } + case 1001: + { + st := yyS[yypt-1].statement.(*ast.SelectStmt) + st.IsInBraces = true + endOffset := parser.endOffset(&yyS[yypt]) + parser.setLastSelectFieldText(st, endOffset) + parser.yyVAL.item = yyS[yypt-1].statement + } + case 1003: + { + parser.yyVAL.statement = &ast.SetStmt{Variables: yyS[yypt-0].item.([]*ast.VariableAssignment)} + } + case 1004: + { + parser.yyVAL.statement = &ast.SetPwdStmt{Password: yyS[yypt-0].item.(string)} + } + case 1005: + { + parser.yyVAL.statement = &ast.SetPwdStmt{User: yyS[yypt-2].item.(*auth.UserIdentity), Password: yyS[yypt-0].item.(string)} + } + case 1006: + { + vars := yyS[yypt-0].item.([]*ast.VariableAssignment) + for _, v := range vars { + v.IsGlobal = true + } + parser.yyVAL.statement = &ast.SetStmt{Variables: vars} + } + case 1007: + { + parser.yyVAL.statement = &ast.SetStmt{Variables: yyS[yypt-0].item.([]*ast.VariableAssignment)} + } + case 1008: + { + assigns := yyS[yypt-0].item.([]*ast.VariableAssignment) + for i := 0; i < len(assigns); i++ { + if assigns[i].Name == "tx_isolation" { + // A special session variable that make setting tx_isolation take effect one time. + assigns[i].Name = "tx_isolation_one_shot" + } + } + parser.yyVAL.statement = &ast.SetStmt{Variables: assigns} + } + case 1009: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.item = yyS[yypt-0].item + } else { + parser.yyVAL.item = []*ast.VariableAssignment{} + } + } + case 1010: + { + if yyS[yypt-0].item != nil { + varAssigns := yyS[yypt-0].item.([]*ast.VariableAssignment) + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.VariableAssignment), varAssigns...) + } else { + parser.yyVAL.item = yyS[yypt-2].item + } + } + case 1011: + { + varAssigns := []*ast.VariableAssignment{} + expr := ast.NewValueExpr(yyS[yypt-0].ident) + varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_isolation", Value: expr, IsSystem: true}) + parser.yyVAL.item = varAssigns + } + case 1012: + { + varAssigns := []*ast.VariableAssignment{} + expr := ast.NewValueExpr("0") + varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true}) + parser.yyVAL.item = varAssigns + } + case 1013: + { + varAssigns := []*ast.VariableAssignment{} + expr := ast.NewValueExpr("1") + varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true}) + parser.yyVAL.item = varAssigns + } + case 1014: + { + parser.yyVAL.ident = ast.RepeatableRead + } + case 1015: + { + parser.yyVAL.ident = ast.ReadCommitted + } + case 1016: + { + parser.yyVAL.ident = ast.ReadUncommitted + } + case 1017: + { + parser.yyVAL.ident = ast.Serializable + } + case 1018: + { + parser.yyVAL.expr = ast.NewValueExpr("ON") + } + case 1020: + { + parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsSystem: true} + } + case 1021: + { + parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsGlobal: true, IsSystem: true} + } + case 1022: + { + parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsSystem: true} + } + case 1023: + { + parser.yyVAL.item = &ast.VariableAssignment{Name: yyS[yypt-2].ident, Value: yyS[yypt-0].expr, IsSystem: true} + } + case 1024: + { + v := strings.ToLower(yyS[yypt-2].ident) + var isGlobal bool + if strings.HasPrefix(v, "@@global.") { + isGlobal = true + v = strings.TrimPrefix(v, "@@global.") + } else if strings.HasPrefix(v, "@@session.") { + v = strings.TrimPrefix(v, "@@session.") + } else if strings.HasPrefix(v, "@@local.") { + v = strings.TrimPrefix(v, "@@local.") + } else if strings.HasPrefix(v, "@@") { + v = strings.TrimPrefix(v, "@@") + } + parser.yyVAL.item = &ast.VariableAssignment{Name: v, Value: yyS[yypt-0].expr, IsGlobal: isGlobal, IsSystem: true} + } + case 1025: + { + v := yyS[yypt-2].ident + v = strings.TrimPrefix(v, "@") + parser.yyVAL.item = &ast.VariableAssignment{Name: v, Value: yyS[yypt-0].expr} + } + case 1026: + { + v := yyS[yypt-2].ident + v = strings.TrimPrefix(v, "@") + parser.yyVAL.item = &ast.VariableAssignment{Name: v, Value: yyS[yypt-0].expr} + } + case 1027: + { + parser.yyVAL.item = &ast.VariableAssignment{ + Name: ast.SetNames, + Value: ast.NewValueExpr(yyS[yypt-0].item.(string)), + } + } + case 1028: + { + parser.yyVAL.item = &ast.VariableAssignment{ + Name: ast.SetNames, + Value: ast.NewValueExpr(yyS[yypt-2].item.(string)), + } + } + case 1029: + { + parser.yyVAL.item = &ast.VariableAssignment{ + Name: ast.SetNames, + Value: ast.NewValueExpr(yyS[yypt-2].item.(string)), + ExtendValue: ast.NewValueExpr(yyS[yypt-0].item.(string)), + } + } + case 1030: + { + parser.yyVAL.item = &ast.VariableAssignment{ + Name: ast.SetNames, + Value: ast.NewValueExpr(yyS[yypt-0].item.(string)), + } + } + case 1031: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 1032: + { + parser.yyVAL.item = charset.CharsetBin + } + case 1033: + { + parser.yyVAL.item = []*ast.VariableAssignment{} + } + case 1034: + { + parser.yyVAL.item = []*ast.VariableAssignment{yyS[yypt-0].item.(*ast.VariableAssignment)} + } + case 1035: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.VariableAssignment), yyS[yypt-0].item.(*ast.VariableAssignment)) + } + case 1038: + { + v := strings.ToLower(yyS[yypt-0].ident) + var isGlobal bool + explicitScope := true + if strings.HasPrefix(v, "@@global.") { + isGlobal = true + v = strings.TrimPrefix(v, "@@global.") + } else if strings.HasPrefix(v, "@@session.") { + v = strings.TrimPrefix(v, "@@session.") + } else if strings.HasPrefix(v, "@@local.") { + v = strings.TrimPrefix(v, "@@local.") + } else if strings.HasPrefix(v, "@@") { + v, explicitScope = strings.TrimPrefix(v, "@@"), false + } + parser.yyVAL.expr = &ast.VariableExpr{Name: v, IsGlobal: isGlobal, IsSystem: true, ExplicitScope: explicitScope} + } + case 1039: + { + v := yyS[yypt-0].ident + v = strings.TrimPrefix(v, "@") + parser.yyVAL.expr = &ast.VariableExpr{Name: v, IsGlobal: false, IsSystem: false} + } + case 1040: + { + parser.yyVAL.item = &auth.UserIdentity{Username: yyS[yypt-0].item.(string), Hostname: "%"} + } + case 1041: + { + parser.yyVAL.item = &auth.UserIdentity{Username: yyS[yypt-2].item.(string), Hostname: yyS[yypt-0].item.(string)} + } + case 1042: + { + parser.yyVAL.item = &auth.UserIdentity{Username: yyS[yypt-1].item.(string), Hostname: strings.TrimPrefix(yyS[yypt-0].ident, "@")} + } + case 1043: + { + parser.yyVAL.item = &auth.UserIdentity{CurrentUser: true} + } + case 1044: + { + parser.yyVAL.item = []*auth.UserIdentity{yyS[yypt-0].item.(*auth.UserIdentity)} + } + case 1045: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*auth.UserIdentity), yyS[yypt-0].item.(*auth.UserIdentity)) + } + case 1046: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1047: + { + parser.yyVAL.item = yyS[yypt-1].item.(string) + } + case 1048: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1049: + { + parser.yyVAL.statement = &ast.AdminStmt{Tp: ast.AdminShowDDL} + } + case 1050: + { + parser.yyVAL.statement = &ast.AdminStmt{Tp: ast.AdminShowDDLJobs} + } + case 1051: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminShowDDLJobs, + JobNumber: yyS[yypt-0].item.(int64), + } + } + case 1052: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminShowNextRowID, + Tables: []*ast.TableName{yyS[yypt-1].item.(*ast.TableName)}, + } + } + case 1053: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminCheckTable, + Tables: yyS[yypt-0].item.([]*ast.TableName), + } + } + case 1054: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminCheckIndex, + Tables: []*ast.TableName{yyS[yypt-1].item.(*ast.TableName)}, + Index: string(yyS[yypt-0].ident), + } + } + case 1055: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminRecoverIndex, + Tables: []*ast.TableName{yyS[yypt-1].item.(*ast.TableName)}, + Index: string(yyS[yypt-0].ident), + } + } + case 1056: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminCleanupIndex, + Tables: []*ast.TableName{yyS[yypt-1].item.(*ast.TableName)}, + Index: string(yyS[yypt-0].ident), + } + } + case 1057: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminCheckIndexRange, + Tables: []*ast.TableName{yyS[yypt-2].item.(*ast.TableName)}, + Index: string(yyS[yypt-1].ident), + HandleRanges: yyS[yypt-0].item.([]ast.HandleRange), + } + } + case 1058: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminChecksumTable, + Tables: yyS[yypt-0].item.([]*ast.TableName), + } + } + case 1059: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminCancelDDLJobs, + JobIDs: yyS[yypt-0].item.([]int64), + } + } + case 1060: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminShowDDLJobQueries, + JobIDs: yyS[yypt-0].item.([]int64), + } + } + case 1061: + { + parser.yyVAL.statement = &ast.AdminStmt{ + Tp: ast.AdminShowSlow, + ShowSlow: yyS[yypt-0].item.(*ast.ShowSlow), + } + } + case 1062: + { + parser.yyVAL.item = &ast.ShowSlow{ + Tp: ast.ShowSlowRecent, + Count: getUint64FromNUM(yyS[yypt-0].item), + } + } + case 1063: + { + parser.yyVAL.item = &ast.ShowSlow{ + Tp: ast.ShowSlowTop, + Kind: ast.ShowSlowKindDefault, + Count: getUint64FromNUM(yyS[yypt-0].item), + } + } + case 1064: + { + parser.yyVAL.item = &ast.ShowSlow{ + Tp: ast.ShowSlowTop, + Kind: ast.ShowSlowKindInternal, + Count: getUint64FromNUM(yyS[yypt-0].item), + } + } + case 1065: + { + parser.yyVAL.item = &ast.ShowSlow{ + Tp: ast.ShowSlowTop, + Kind: ast.ShowSlowKindAll, + Count: getUint64FromNUM(yyS[yypt-0].item), + } + } + case 1066: + { + parser.yyVAL.item = []ast.HandleRange{yyS[yypt-0].item.(ast.HandleRange)} + } + case 1067: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]ast.HandleRange), yyS[yypt-0].item.(ast.HandleRange)) + } + case 1068: + { + parser.yyVAL.item = ast.HandleRange{Begin: yyS[yypt-3].item.(int64), End: yyS[yypt-1].item.(int64)} + } + case 1069: + { + parser.yyVAL.item = []int64{yyS[yypt-0].item.(int64)} + } + case 1070: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]int64), yyS[yypt-0].item.(int64)) + } + case 1071: + { + stmt := yyS[yypt-1].item.(*ast.ShowStmt) + if yyS[yypt-0].item != nil { + if x, ok := yyS[yypt-0].item.(*ast.PatternLikeExpr); ok { + stmt.Pattern = x + } else { + stmt.Where = yyS[yypt-0].item.(ast.ExprNode) + } + } + parser.yyVAL.statement = stmt + } + case 1072: + { + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowCreateTable, + Table: yyS[yypt-0].item.(*ast.TableName), + } + } + case 1073: + { + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowCreateDatabase, + DBName: yyS[yypt-0].item.(string), + } + } + case 1074: + { + // See https://dev.mysql.com/doc/refman/5.7/en/show-grants.html + parser.yyVAL.statement = &ast.ShowStmt{Tp: ast.ShowGrants} + } + case 1075: + { + // See https://dev.mysql.com/doc/refman/5.7/en/show-grants.html + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowGrants, + User: yyS[yypt-0].item.(*auth.UserIdentity), + } + } + case 1076: + { + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowMasterStatus, + } + } + case 1077: + { + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowProcessList, + Full: yyS[yypt-1].item.(bool), + } + } + case 1078: + { + stmt := &ast.ShowStmt{ + Tp: ast.ShowStatsMeta, + } + if yyS[yypt-0].item != nil { + if x, ok := yyS[yypt-0].item.(*ast.PatternLikeExpr); ok { + stmt.Pattern = x + } else { + stmt.Where = yyS[yypt-0].item.(ast.ExprNode) + } + } + parser.yyVAL.statement = stmt + } + case 1079: + { + stmt := &ast.ShowStmt{ + Tp: ast.ShowStatsHistograms, + } + if yyS[yypt-0].item != nil { + if x, ok := yyS[yypt-0].item.(*ast.PatternLikeExpr); ok { + stmt.Pattern = x + } else { + stmt.Where = yyS[yypt-0].item.(ast.ExprNode) + } + } + parser.yyVAL.statement = stmt + } + case 1080: + { + stmt := &ast.ShowStmt{ + Tp: ast.ShowStatsBuckets, + } + if yyS[yypt-0].item != nil { + if x, ok := yyS[yypt-0].item.(*ast.PatternLikeExpr); ok { + stmt.Pattern = x + } else { + stmt.Where = yyS[yypt-0].item.(ast.ExprNode) + } + } + parser.yyVAL.statement = stmt + } + case 1081: + { + stmt := &ast.ShowStmt{ + Tp: ast.ShowStatsHealthy, + } + if yyS[yypt-0].item != nil { + if x, ok := yyS[yypt-0].item.(*ast.PatternLikeExpr); ok { + stmt.Pattern = x + } else { + stmt.Where = yyS[yypt-0].item.(ast.ExprNode) + } + } + parser.yyVAL.statement = stmt + } + case 1082: + { + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowProfiles, + } + } + case 1083: + { + parser.yyVAL.statement = &ast.ShowStmt{ + Tp: ast.ShowPrivileges, + } + } + case 1089: + { + parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowEngines} + } + case 1090: + { + parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowDatabases} + } + case 1091: + { + parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowCharset} + } + case 1092: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowTables, + DBName: yyS[yypt-0].item.(string), + Full: yyS[yypt-2].item.(bool), + } + } + case 1093: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowTableStatus, + DBName: yyS[yypt-0].item.(string), + } + } + case 1094: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowIndex, + Table: yyS[yypt-0].item.(*ast.TableName), + } + } + case 1095: + { + show := &ast.ShowStmt{ + Tp: ast.ShowIndex, + Table: &ast.TableName{Name: model.NewCIStr(yyS[yypt-2].ident), Schema: model.NewCIStr(yyS[yypt-0].ident)}, + } + parser.yyVAL.item = show + } + case 1096: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowColumns, + Table: yyS[yypt-1].item.(*ast.TableName), + DBName: yyS[yypt-0].item.(string), + Full: yyS[yypt-3].item.(bool), + } + } + case 1097: + { + // SHOW FIELDS is a synonym for SHOW COLUMNS. + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowColumns, + Table: yyS[yypt-1].item.(*ast.TableName), + DBName: yyS[yypt-0].item.(string), + Full: yyS[yypt-3].item.(bool), + } + } + case 1098: + { + parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowWarnings} + } + case 1099: + { + parser.yyVAL.item = &ast.ShowStmt{Tp: ast.ShowErrors} + } + case 1100: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowVariables, + GlobalScope: yyS[yypt-1].item.(bool), + } + } + case 1101: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowStatus, + GlobalScope: yyS[yypt-1].item.(bool), + } + } + case 1102: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowCollation, + } + } + case 1103: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowTriggers, + DBName: yyS[yypt-0].item.(string), + } + } + case 1104: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowProcedureStatus, + } + } + case 1105: + { + // This statement is similar to SHOW PROCEDURE STATUS but for stored functions. + // See http://dev.mysql.com/doc/refman/5.7/en/show-function-status.html + // We do not support neither stored functions nor stored procedures. + // So we reuse show procedure status process logic. + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowProcedureStatus, + } + } + case 1106: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowEvents, + DBName: yyS[yypt-0].item.(string), + } + } + case 1107: + { + parser.yyVAL.item = &ast.ShowStmt{ + Tp: ast.ShowPlugins, + } + } + case 1108: + { + parser.yyVAL.item = nil + } + case 1109: + { + parser.yyVAL.item = &ast.PatternLikeExpr{ + Pattern: yyS[yypt-0].expr, + Escape: '\\', + } + } + case 1110: + { + parser.yyVAL.item = yyS[yypt-0].expr + } + case 1111: + { + parser.yyVAL.item = false + } + case 1112: + { + parser.yyVAL.item = true + } + case 1113: + { + parser.yyVAL.item = false + } + case 1114: + { + parser.yyVAL.item = false + } + case 1115: + { + parser.yyVAL.item = true + } + case 1116: + { + parser.yyVAL.item = "" + } + case 1117: + { + parser.yyVAL.item = yyS[yypt-0].item.(string) + } + case 1118: + { + parser.yyVAL.item = yyS[yypt-0].item.(*ast.TableName) + } + case 1119: + { + tmp := yyS[yypt-0].item.(*ast.FlushStmt) + tmp.NoWriteToBinLog = yyS[yypt-1].item.(bool) + parser.yyVAL.statement = tmp + } + case 1120: + { + parser.yyVAL.item = &ast.FlushStmt{ + Tp: ast.FlushPrivileges, + } + } + case 1121: + { + parser.yyVAL.item = &ast.FlushStmt{ + Tp: ast.FlushStatus, + } + } + case 1122: + { + parser.yyVAL.item = &ast.FlushStmt{ + Tp: ast.FlushTables, + Tables: yyS[yypt-1].item.([]*ast.TableName), + ReadLock: yyS[yypt-0].item.(bool), + } + } + case 1123: + { + parser.yyVAL.item = false + } + case 1124: + { + parser.yyVAL.item = true + } + case 1125: + { + parser.yyVAL.item = true + } + case 1126: + { + parser.yyVAL.item = []*ast.TableName{} + } + case 1127: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 1128: + { + parser.yyVAL.item = false + } + case 1129: + { + parser.yyVAL.item = true + } + case 1169: + { + // `(select 1)`; is a valid select statement + // TODO: This is used to fix issue #320. There may be a better solution. + parser.yyVAL.statement = yyS[yypt-0].expr.(*ast.SubqueryExpr).Query.(ast.StmtNode) + } + case 1188: + { + if yyS[yypt-0].statement != nil { + s := yyS[yypt-0].statement + if lexer, ok := yylex.(stmtTexter); ok { + s.SetText(lexer.stmtText()) + } + parser.result = append(parser.result, s) + } + } + case 1189: + { + if yyS[yypt-0].statement != nil { + s := yyS[yypt-0].statement + if lexer, ok := yylex.(stmtTexter); ok { + s.SetText(lexer.stmtText()) + } + parser.result = append(parser.result, s) + } + } + case 1190: + { + cst := yyS[yypt-0].item.(*ast.Constraint) + if yyS[yypt-1].item != nil { + cst.Name = yyS[yypt-1].item.(string) + } + parser.yyVAL.item = cst + } + case 1191: + { + parser.yyVAL.item = yyS[yypt-0].item.(*ast.ColumnDef) + } + case 1192: + { + parser.yyVAL.item = yyS[yypt-0].item.(*ast.Constraint) + } + case 1193: + { + /* Nothing to do now */ + parser.yyVAL.item = nil + } + case 1194: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.item = []interface{}{yyS[yypt-0].item.(interface{})} + } else { + parser.yyVAL.item = []interface{}{} + } + } + case 1195: + { + if yyS[yypt-0].item != nil { + parser.yyVAL.item = append(yyS[yypt-2].item.([]interface{}), yyS[yypt-0].item) + } else { + parser.yyVAL.item = yyS[yypt-2].item + } + } + case 1196: + { + var columnDefs []*ast.ColumnDef + var constraints []*ast.Constraint + parser.yyVAL.item = &ast.CreateTableStmt{ + Cols: columnDefs, + Constraints: constraints, + } + } + case 1197: + { + tes := yyS[yypt-1].item.([]interface{}) + var columnDefs []*ast.ColumnDef + var constraints []*ast.Constraint + for _, te := range tes { + switch te := te.(type) { + case *ast.ColumnDef: + columnDefs = append(columnDefs, te) + case *ast.Constraint: + constraints = append(constraints, te) + } + } + parser.yyVAL.item = &ast.CreateTableStmt{ + Cols: columnDefs, + Constraints: constraints, + } + } + case 1198: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionEngine, StrValue: yyS[yypt-0].item.(string)} + } + case 1199: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionEngine, StrValue: yyS[yypt-0].item.(string)} + } + case 1200: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCharset, StrValue: yyS[yypt-0].item.(string)} + } + case 1201: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: yyS[yypt-0].item.(string)} + } + case 1202: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionAutoIncrement, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1203: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionComment, StrValue: yyS[yypt-0].ident} + } + case 1204: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionAvgRowLength, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1205: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionConnection, StrValue: yyS[yypt-0].ident} + } + case 1206: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCheckSum, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1207: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionPassword, StrValue: yyS[yypt-0].ident} + } + case 1208: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionCompression, StrValue: yyS[yypt-0].ident} + } + case 1209: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionKeyBlockSize, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1210: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionMaxRows, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1211: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionMinRows, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1212: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionDelayKeyWrite, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1213: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionRowFormat, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1214: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionStatsPersistent} + } + case 1215: + { + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionShardRowID, UintValue: yyS[yypt-0].item.(uint64)} + } + case 1216: + { + // Parse it but will ignore it. + parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionPackKeys} + } + case 1219: + { + parser.yyVAL.item = []*ast.TableOption{} + } + case 1221: + { + parser.yyVAL.item = []*ast.TableOption{} + } + case 1223: + { + parser.yyVAL.item = []*ast.TableOption{yyS[yypt-0].item.(*ast.TableOption)} + } + case 1224: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.TableOption), yyS[yypt-0].item.(*ast.TableOption)) + } + case 1225: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.TableOption), yyS[yypt-0].item.(*ast.TableOption)) + } + case 1228: + { + parser.yyVAL.statement = &ast.TruncateTableStmt{Table: yyS[yypt-0].item.(*ast.TableName)} + } + case 1229: + { + parser.yyVAL.item = ast.RowFormatDefault + } + case 1230: + { + parser.yyVAL.item = ast.RowFormatDynamic + } + case 1231: + { + parser.yyVAL.item = ast.RowFormatFixed + } + case 1232: + { + parser.yyVAL.item = ast.RowFormatCompressed + } + case 1233: + { + parser.yyVAL.item = ast.RowFormatRedundant + } + case 1234: + { + parser.yyVAL.item = ast.RowFormatCompact + } + case 1235: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 1236: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 1237: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 1238: + { + // TODO: check flen 0 + x := types.NewFieldType(yyS[yypt-2].item.(byte)) + x.Flen = yyS[yypt-1].item.(int) + for _, o := range yyS[yypt-0].item.([]*ast.TypeOpt) { + if o.IsUnsigned { + x.Flag |= mysql.UnsignedFlag + } + if o.IsZerofill { + x.Flag |= mysql.ZerofillFlag + } + } + parser.yyVAL.item = x + } + case 1239: + { + // TODO: check flen 0 + x := types.NewFieldType(yyS[yypt-1].item.(byte)) + x.Flen = 1 + for _, o := range yyS[yypt-0].item.([]*ast.TypeOpt) { + if o.IsUnsigned { + x.Flag |= mysql.UnsignedFlag + } + if o.IsZerofill { + x.Flag |= mysql.ZerofillFlag + } + } + parser.yyVAL.item = x + } + case 1240: + { + fopt := yyS[yypt-1].item.(*ast.FloatOpt) + x := types.NewFieldType(yyS[yypt-2].item.(byte)) + x.Flen = fopt.Flen + x.Decimal = fopt.Decimal + for _, o := range yyS[yypt-0].item.([]*ast.TypeOpt) { + if o.IsUnsigned { + x.Flag |= mysql.UnsignedFlag + } + if o.IsZerofill { + x.Flag |= mysql.ZerofillFlag + } + } + parser.yyVAL.item = x + } + case 1241: + { + fopt := yyS[yypt-1].item.(*ast.FloatOpt) + x := types.NewFieldType(yyS[yypt-2].item.(byte)) + x.Flen = fopt.Flen + if x.Tp == mysql.TypeFloat { + if x.Flen > 24 { + x.Tp = mysql.TypeDouble + } + } + x.Decimal = fopt.Decimal + for _, o := range yyS[yypt-0].item.([]*ast.TypeOpt) { + if o.IsUnsigned { + x.Flag |= mysql.UnsignedFlag + } + if o.IsZerofill { + x.Flag |= mysql.ZerofillFlag + } + } + parser.yyVAL.item = x + } + case 1242: + { + x := types.NewFieldType(yyS[yypt-1].item.(byte)) + x.Flen = yyS[yypt-0].item.(int) + if x.Flen == types.UnspecifiedLength || x.Flen == 0 { + x.Flen = 1 + } else if x.Flen > 64 { + yylex.Errorf("invalid field length %d for bit type, must in [1, 64]", x.Flen) + } + parser.yyVAL.item = x + } + case 1243: + { + parser.yyVAL.item = mysql.TypeTiny + } + case 1244: + { + parser.yyVAL.item = mysql.TypeShort + } + case 1245: + { + parser.yyVAL.item = mysql.TypeInt24 + } + case 1246: + { + parser.yyVAL.item = mysql.TypeLong + } + case 1247: + { + parser.yyVAL.item = mysql.TypeTiny + } + case 1248: + { + parser.yyVAL.item = mysql.TypeShort + } + case 1249: + { + parser.yyVAL.item = mysql.TypeInt24 + } + case 1250: + { + parser.yyVAL.item = mysql.TypeLong + } + case 1251: + { + parser.yyVAL.item = mysql.TypeLonglong + } + case 1252: + { + parser.yyVAL.item = mysql.TypeLong + } + case 1253: + { + parser.yyVAL.item = mysql.TypeLonglong + } + case 1254: + { + parser.yyVAL.item = mysql.TypeTiny + } + case 1255: + { + parser.yyVAL.item = mysql.TypeTiny + } + case 1259: + { + parser.yyVAL.item = mysql.TypeNewDecimal + } + case 1260: + { + parser.yyVAL.item = mysql.TypeNewDecimal + } + case 1261: + { + parser.yyVAL.item = mysql.TypeFloat + } + case 1262: + { + if parser.lexer.GetSQLMode().HasRealAsFloatMode() { + parser.yyVAL.item = mysql.TypeFloat + } else { + parser.yyVAL.item = mysql.TypeDouble + } + } + case 1263: + { + parser.yyVAL.item = mysql.TypeDouble + } + case 1264: + { + parser.yyVAL.item = mysql.TypeDouble + } + case 1265: + { + parser.yyVAL.item = mysql.TypeBit + } + case 1266: + { + x := types.NewFieldType(mysql.TypeString) + x.Flen = yyS[yypt-2].item.(int) + x.Charset = yyS[yypt-1].item.(*ast.OptBinary).Charset + x.Collate = yyS[yypt-0].item.(string) + if yyS[yypt-1].item.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + parser.yyVAL.item = x + } + case 1267: + { + x := types.NewFieldType(mysql.TypeString) + x.Charset = yyS[yypt-1].item.(*ast.OptBinary).Charset + x.Collate = yyS[yypt-0].item.(string) + if yyS[yypt-1].item.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + parser.yyVAL.item = x + } + case 1268: + { + x := types.NewFieldType(mysql.TypeString) + x.Flen = yyS[yypt-2].item.(int) + x.Charset = yyS[yypt-1].item.(*ast.OptBinary).Charset + x.Collate = yyS[yypt-0].item.(string) + if yyS[yypt-1].item.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + parser.yyVAL.item = x + } + case 1269: + { + x := types.NewFieldType(mysql.TypeVarchar) + x.Flen = yyS[yypt-2].item.(int) + x.Charset = yyS[yypt-1].item.(*ast.OptBinary).Charset + x.Collate = yyS[yypt-0].item.(string) + if yyS[yypt-1].item.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + parser.yyVAL.item = x + } + case 1270: + { + x := types.NewFieldType(mysql.TypeString) + x.Flen = yyS[yypt-0].item.(int) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 1271: + { + x := types.NewFieldType(mysql.TypeVarchar) + x.Flen = yyS[yypt-0].item.(int) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = x + } + case 1272: + { + x := yyS[yypt-0].item.(*types.FieldType) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + x.Flag |= mysql.BinaryFlag + parser.yyVAL.item = yyS[yypt-0].item.(*types.FieldType) + } + case 1273: + { + x := yyS[yypt-2].item.(*types.FieldType) + x.Charset = yyS[yypt-1].item.(*ast.OptBinary).Charset + x.Collate = yyS[yypt-0].item.(string) + if yyS[yypt-1].item.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + parser.yyVAL.item = x + } + case 1274: + { + x := types.NewFieldType(mysql.TypeEnum) + x.Elems = yyS[yypt-3].item.([]string) + x.Charset = yyS[yypt-1].item.(string) + x.Collate = yyS[yypt-0].item.(string) + parser.yyVAL.item = x + } + case 1275: + { + x := types.NewFieldType(mysql.TypeSet) + x.Elems = yyS[yypt-3].item.([]string) + x.Charset = yyS[yypt-1].item.(string) + x.Collate = yyS[yypt-0].item.(string) + parser.yyVAL.item = x + } + case 1276: + { + x := types.NewFieldType(mysql.TypeJSON) + x.Decimal = 0 + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + parser.yyVAL.item = x + } + case 1282: + { + x := types.NewFieldType(mysql.TypeTinyBlob) + parser.yyVAL.item = x + } + case 1283: + { + x := types.NewFieldType(mysql.TypeBlob) + x.Flen = yyS[yypt-0].item.(int) + parser.yyVAL.item = x + } + case 1284: + { + x := types.NewFieldType(mysql.TypeMediumBlob) + parser.yyVAL.item = x + } + case 1285: + { + x := types.NewFieldType(mysql.TypeLongBlob) + parser.yyVAL.item = x + } + case 1286: + { + x := types.NewFieldType(mysql.TypeTinyBlob) + parser.yyVAL.item = x + + } + case 1287: + { + x := types.NewFieldType(mysql.TypeBlob) + x.Flen = yyS[yypt-0].item.(int) + parser.yyVAL.item = x + } + case 1288: + { + x := types.NewFieldType(mysql.TypeMediumBlob) + parser.yyVAL.item = x + } + case 1289: + { + x := types.NewFieldType(mysql.TypeLongBlob) + parser.yyVAL.item = x + } + case 1290: + { + x := types.NewFieldType(mysql.TypeMediumBlob) + parser.yyVAL.item = x + } + case 1291: + { + x := types.NewFieldType(mysql.TypeDate) + parser.yyVAL.item = x + } + case 1292: + { + x := types.NewFieldType(mysql.TypeDatetime) + x.Flen = mysql.MaxDatetimeWidthNoFsp + x.Decimal = yyS[yypt-0].item.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + parser.yyVAL.item = x + } + case 1293: + { + x := types.NewFieldType(mysql.TypeTimestamp) + x.Flen = mysql.MaxDatetimeWidthNoFsp + x.Decimal = yyS[yypt-0].item.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + parser.yyVAL.item = x + } + case 1294: + { + x := types.NewFieldType(mysql.TypeDuration) + x.Flen = mysql.MaxDurationWidthNoFsp + x.Decimal = yyS[yypt-0].item.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + parser.yyVAL.item = x + } + case 1295: + { + x := types.NewFieldType(mysql.TypeYear) + x.Flen = yyS[yypt-1].item.(int) + if x.Flen != types.UnspecifiedLength && x.Flen != 4 { + yylex.Errorf("Supports only YEAR or YEAR(4) column.") + return -1 + } + parser.yyVAL.item = x + } + case 1296: + { + parser.yyVAL.item = int(yyS[yypt-1].item.(uint64)) + } + case 1297: + { + parser.yyVAL.item = types.UnspecifiedLength + } + case 1298: + { + parser.yyVAL.item = yyS[yypt-0].item.(int) + } + case 1299: + { + parser.yyVAL.item = &ast.TypeOpt{IsUnsigned: true} + } + case 1300: + { + parser.yyVAL.item = &ast.TypeOpt{IsUnsigned: false} + } + case 1301: + { + parser.yyVAL.item = &ast.TypeOpt{IsZerofill: true, IsUnsigned: true} + } + case 1302: + { + parser.yyVAL.item = []*ast.TypeOpt{} + } + case 1303: + { + parser.yyVAL.item = append(yyS[yypt-1].item.([]*ast.TypeOpt), yyS[yypt-0].item.(*ast.TypeOpt)) + } + case 1304: + { + parser.yyVAL.item = &ast.FloatOpt{Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength} + } + case 1305: + { + parser.yyVAL.item = &ast.FloatOpt{Flen: yyS[yypt-0].item.(int), Decimal: types.UnspecifiedLength} + } + case 1306: + { + parser.yyVAL.item = yyS[yypt-0].item.(*ast.FloatOpt) + } + case 1307: + { + parser.yyVAL.item = &ast.FloatOpt{Flen: int(yyS[yypt-3].item.(uint64)), Decimal: int(yyS[yypt-1].item.(uint64))} + } + case 1308: + { + parser.yyVAL.item = false + } + case 1309: + { + parser.yyVAL.item = true + } + case 1310: + { + parser.yyVAL.item = &ast.OptBinary{ + IsBinary: false, + Charset: "", + } + } + case 1311: + { + parser.yyVAL.item = &ast.OptBinary{ + IsBinary: true, + Charset: yyS[yypt-0].item.(string), + } + } + case 1312: + { + parser.yyVAL.item = &ast.OptBinary{ + IsBinary: yyS[yypt-0].item.(bool), + Charset: yyS[yypt-1].item.(string), + } + } + case 1313: + { + parser.yyVAL.item = "" + } + case 1314: + { + parser.yyVAL.item = yyS[yypt-0].item.(string) + } + case 1317: + { + parser.yyVAL.item = "" + } + case 1318: + { + parser.yyVAL.item = yyS[yypt-0].item.(string) + } + case 1319: + { + parser.yyVAL.item = []string{yyS[yypt-0].ident} + } + case 1320: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]string), yyS[yypt-0].ident) + } + case 1321: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1322: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1323: + { + var refs *ast.Join + if x, ok := yyS[yypt-5].item.(*ast.Join); ok { + refs = x + } else { + refs = &ast.Join{Left: yyS[yypt-5].item.(ast.ResultSetNode)} + } + st := &ast.UpdateStmt{ + Priority: yyS[yypt-7].item.(mysql.PriorityEnum), + TableRefs: &ast.TableRefsClause{TableRefs: refs}, + List: yyS[yypt-3].item.([]*ast.Assignment), + IgnoreErr: yyS[yypt-6].item.(bool), + } + if yyS[yypt-8].item != nil { + st.TableHints = yyS[yypt-8].item.([]*ast.TableOptimizerHint) + } + if yyS[yypt-2].item != nil { + st.Where = yyS[yypt-2].item.(ast.ExprNode) + } + if yyS[yypt-1].item != nil { + st.Order = yyS[yypt-1].item.(*ast.OrderByClause) + } + if yyS[yypt-0].item != nil { + st.Limit = yyS[yypt-0].item.(*ast.Limit) + } + parser.yyVAL.statement = st + } + case 1324: + { + st := &ast.UpdateStmt{ + Priority: yyS[yypt-5].item.(mysql.PriorityEnum), + TableRefs: &ast.TableRefsClause{TableRefs: yyS[yypt-3].item.(*ast.Join)}, + List: yyS[yypt-1].item.([]*ast.Assignment), + IgnoreErr: yyS[yypt-4].item.(bool), + } + if yyS[yypt-6].item != nil { + st.TableHints = yyS[yypt-6].item.([]*ast.TableOptimizerHint) + } + if yyS[yypt-0].item != nil { + st.Where = yyS[yypt-0].item.(ast.ExprNode) + } + parser.yyVAL.statement = st + } + case 1325: + { + parser.yyVAL.statement = &ast.UseStmt{DBName: yyS[yypt-0].item.(string)} + } + case 1326: + { + parser.yyVAL.item = yyS[yypt-0].expr + } + case 1327: + { + parser.yyVAL.item = nil + } + case 1328: + { + parser.yyVAL.item = yyS[yypt-0].item + } + case 1331: + { + // See https://dev.mysql.com/doc/refman/5.7/en/create-user.html + parser.yyVAL.statement = &ast.CreateUserStmt{ + IfNotExists: yyS[yypt-1].item.(bool), + Specs: yyS[yypt-0].item.([]*ast.UserSpec), + } + } + case 1332: + { + parser.yyVAL.statement = &ast.AlterUserStmt{ + IfExists: yyS[yypt-1].item.(bool), + Specs: yyS[yypt-0].item.([]*ast.UserSpec), + } + } + case 1333: + { + auth := &ast.AuthOption{ + AuthString: yyS[yypt-0].item.(string), + ByAuthString: true, + } + parser.yyVAL.statement = &ast.AlterUserStmt{ + IfExists: yyS[yypt-6].item.(bool), + CurrentAuth: auth, + } + } + case 1334: + { + userSpec := &ast.UserSpec{ + User: yyS[yypt-1].item.(*auth.UserIdentity), + } + if yyS[yypt-0].item != nil { + userSpec.AuthOpt = yyS[yypt-0].item.(*ast.AuthOption) + } + parser.yyVAL.item = userSpec + } + case 1335: + { + parser.yyVAL.item = []*ast.UserSpec{yyS[yypt-0].item.(*ast.UserSpec)} + } + case 1336: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.UserSpec), yyS[yypt-0].item.(*ast.UserSpec)) + } + case 1337: + { + parser.yyVAL.item = nil + } + case 1338: + { + parser.yyVAL.item = &ast.AuthOption{ + AuthString: yyS[yypt-0].item.(string), + ByAuthString: true, + } + } + case 1339: + { + parser.yyVAL.item = nil + } + case 1340: + { + parser.yyVAL.item = &ast.AuthOption{ + AuthString: yyS[yypt-0].item.(string), + ByAuthString: true, + } + } + case 1341: + { + parser.yyVAL.item = &ast.AuthOption{ + HashString: yyS[yypt-0].item.(string), + } + } + case 1342: + { + parser.yyVAL.item = &ast.AuthOption{ + HashString: yyS[yypt-0].item.(string), + } + } + case 1343: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1344: + { + parser.yyVAL.statement = &ast.GrantStmt{ + Privs: yyS[yypt-6].item.([]*ast.PrivElem), + ObjectType: yyS[yypt-4].item.(ast.ObjectTypeType), + Level: yyS[yypt-3].item.(*ast.GrantLevel), + Users: yyS[yypt-1].item.([]*ast.UserSpec), + WithGrant: yyS[yypt-0].item.(bool), + } + } + case 1345: + { + parser.yyVAL.item = false + } + case 1346: + { + parser.yyVAL.item = true + } + case 1347: + { + parser.yyVAL.item = false + } + case 1348: + { + parser.yyVAL.item = false + } + case 1349: + { + parser.yyVAL.item = false + } + case 1350: + { + parser.yyVAL.item = false + } + case 1351: + { + parser.yyVAL.item = &ast.PrivElem{ + Priv: yyS[yypt-0].item.(mysql.PrivilegeType), + } + } + case 1352: + { + parser.yyVAL.item = &ast.PrivElem{ + Priv: yyS[yypt-3].item.(mysql.PrivilegeType), + Cols: yyS[yypt-1].item.([]*ast.ColumnName), + } + } + case 1353: + { + parser.yyVAL.item = []*ast.PrivElem{yyS[yypt-0].item.(*ast.PrivElem)} + } + case 1354: + { + parser.yyVAL.item = append(yyS[yypt-2].item.([]*ast.PrivElem), yyS[yypt-0].item.(*ast.PrivElem)) + } + case 1355: + { + parser.yyVAL.item = mysql.AllPriv + } + case 1356: + { + parser.yyVAL.item = mysql.AllPriv + } + case 1357: + { + parser.yyVAL.item = mysql.AlterPriv + } + case 1358: + { + parser.yyVAL.item = mysql.CreatePriv + } + case 1359: + { + parser.yyVAL.item = mysql.CreateUserPriv + } + case 1360: + { + parser.yyVAL.item = mysql.TriggerPriv + } + case 1361: + { + parser.yyVAL.item = mysql.DeletePriv + } + case 1362: + { + parser.yyVAL.item = mysql.DropPriv + } + case 1363: + { + parser.yyVAL.item = mysql.ProcessPriv + } + case 1364: + { + parser.yyVAL.item = mysql.ExecutePriv + } + case 1365: + { + parser.yyVAL.item = mysql.IndexPriv + } + case 1366: + { + parser.yyVAL.item = mysql.InsertPriv + } + case 1367: + { + parser.yyVAL.item = mysql.SelectPriv + } + case 1368: + { + parser.yyVAL.item = mysql.SuperPriv + } + case 1369: + { + parser.yyVAL.item = mysql.ShowDBPriv + } + case 1370: + { + parser.yyVAL.item = mysql.UpdatePriv + } + case 1371: + { + parser.yyVAL.item = mysql.GrantPriv + } + case 1372: + { + parser.yyVAL.item = mysql.ReferencesPriv + } + case 1373: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1374: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1375: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1376: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1377: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1378: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1379: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1380: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1381: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1382: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1383: + { + parser.yyVAL.item = mysql.PrivilegeType(0) + } + case 1384: + { + parser.yyVAL.item = ast.ObjectTypeNone + } + case 1385: + { + parser.yyVAL.item = ast.ObjectTypeTable + } + case 1386: + { + parser.yyVAL.item = &ast.GrantLevel{ + Level: ast.GrantLevelDB, + } + } + case 1387: + { + parser.yyVAL.item = &ast.GrantLevel{ + Level: ast.GrantLevelGlobal, + } + } + case 1388: + { + parser.yyVAL.item = &ast.GrantLevel{ + Level: ast.GrantLevelDB, + DBName: yyS[yypt-2].ident, + } + } + case 1389: + { + parser.yyVAL.item = &ast.GrantLevel{ + Level: ast.GrantLevelTable, + DBName: yyS[yypt-2].ident, + TableName: yyS[yypt-0].ident, + } + } + case 1390: + { + parser.yyVAL.item = &ast.GrantLevel{ + Level: ast.GrantLevelTable, + TableName: yyS[yypt-0].ident, + } + } + case 1391: + { + parser.yyVAL.statement = &ast.RevokeStmt{ + Privs: yyS[yypt-5].item.([]*ast.PrivElem), + ObjectType: yyS[yypt-3].item.(ast.ObjectTypeType), + Level: yyS[yypt-2].item.(*ast.GrantLevel), + Users: yyS[yypt-0].item.([]*ast.UserSpec), + } + } + case 1392: + { + x := &ast.LoadDataStmt{ + Path: yyS[yypt-8].ident, + Table: yyS[yypt-5].item.(*ast.TableName), + Columns: yyS[yypt-0].item.([]*ast.ColumnName), + IgnoreLines: yyS[yypt-1].item.(uint64), + } + if yyS[yypt-10].item != nil { + x.IsLocal = true + } + if yyS[yypt-3].item != nil { + x.FieldsInfo = yyS[yypt-3].item.(*ast.FieldsClause) + } + if yyS[yypt-2].item != nil { + x.LinesInfo = yyS[yypt-2].item.(*ast.LinesClause) + } + parser.yyVAL.statement = x + } + case 1393: + { + parser.yyVAL.item = uint64(0) + } + case 1394: + { + parser.yyVAL.item = getUint64FromNUM(yyS[yypt-1].item) + } + case 1397: + { + parser.yyVAL.item = nil + } + case 1398: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1399: + { + escape := "\\" + parser.yyVAL.item = &ast.FieldsClause{ + Terminated: "\t", + Escaped: escape[0], + } + } + case 1400: + { + escape := yyS[yypt-0].item.(string) + if escape != "\\" && len(escape) > 1 { + yylex.Errorf("Incorrect arguments %s to ESCAPE", escape) + return 1 + } + var enclosed byte + str := yyS[yypt-1].item.(string) + if len(str) > 1 { + yylex.Errorf("Incorrect arguments %s to ENCLOSED", escape) + return 1 + } else if len(str) != 0 { + enclosed = str[0] + } + var escaped byte + if len(escape) > 0 { + escaped = escape[0] + } + parser.yyVAL.item = &ast.FieldsClause{ + Terminated: yyS[yypt-2].item.(string), + Enclosed: enclosed, + Escaped: escaped, + } + } + case 1403: + { + parser.yyVAL.item = "\t" + } + case 1404: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1405: + { + parser.yyVAL.item = "" + } + case 1406: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1407: + { + parser.yyVAL.item = "\\" + } + case 1408: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1409: + { + parser.yyVAL.item = &ast.LinesClause{Terminated: "\n"} + } + case 1410: + { + parser.yyVAL.item = &ast.LinesClause{Starting: yyS[yypt-1].item.(string), Terminated: yyS[yypt-0].item.(string)} + } + case 1411: + { + parser.yyVAL.item = "" + } + case 1412: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1413: + { + parser.yyVAL.item = "\n" + } + case 1414: + { + parser.yyVAL.item = yyS[yypt-0].ident + } + case 1425: + { + parser.yyVAL.statement = &ast.KillStmt{ + ConnectionID: getUint64FromNUM(yyS[yypt-0].item), + TiDBExtension: yyS[yypt-1].item.(bool), + } + } + case 1426: + { + parser.yyVAL.statement = &ast.KillStmt{ + ConnectionID: getUint64FromNUM(yyS[yypt-0].item), + TiDBExtension: yyS[yypt-2].item.(bool), + } + } + case 1427: + { + parser.yyVAL.statement = &ast.KillStmt{ + ConnectionID: getUint64FromNUM(yyS[yypt-0].item), + Query: true, + TiDBExtension: yyS[yypt-2].item.(bool), + } + } + case 1428: + { + parser.yyVAL.item = false + } + case 1429: + { + parser.yyVAL.item = true + } + case 1430: + { + parser.yyVAL.statement = &ast.LoadStatsStmt{ + Path: yyS[yypt-0].ident, + } + } + + } + + if yyEx != nil && yyEx.Reduced(r, exState, &parser.yyVAL) { + return -1 + } + goto yystack /* stack new state and value */ +} diff --git a/vendor/github.com/pingcap/parser/parser.y b/vendor/github.com/pingcap/parser/parser.y new file mode 100644 index 0000000000000000000000000000000000000000..02edf33cb152116b70e29280e470461ada9547b0 --- /dev/null +++ b/vendor/github.com/pingcap/parser/parser.y @@ -0,0 +1,7692 @@ +%{ +// Copyright 2013 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Initial yacc source generated by ebnf2y[1] +// at 2013-10-04 23:10:47.861401015 +0200 CEST +// +// $ ebnf2y -o ql.y -oe ql.ebnf -start StatementList -pkg ql -p _ +// +// [1]: http://github.com/cznic/ebnf2y + +package parser + +import ( + "strings" + + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/model" + "github.com/pingcap/parser/opcode" + "github.com/pingcap/parser/auth" + "github.com/pingcap/parser/charset" + "github.com/pingcap/parser/types" +) + +%} + +%union { + offset int // offset + item interface{} + ident string + expr ast.ExprNode + statement ast.StmtNode +} + +%token + /*yy:token "%c" */ identifier "identifier" + /*yy:token "_%c" */ underscoreCS "UNDERSCORE_CHARSET" + /*yy:token "\"%c\"" */ stringLit "string literal" + singleAtIdentifier "identifier with single leading at" + doubleAtIdentifier "identifier with double leading at" + invalid "a special token never used by parser, used by lexer to indicate error" + hintBegin "hintBegin is a virtual token for optimizer hint grammar" + hintEnd "hintEnd is a virtual token for optimizer hint grammar" + andand "&&" + pipes "||" + + /* The following tokens belong to ODBCDateTimeType. */ + odbcDateType "d" + odbcTimeType "t" + odbcTimestampType "ts" + + /* The following tokens belong to ReservedKeyword. */ + add "ADD" + all "ALL" + alter "ALTER" + analyze "ANALYZE" + and "AND" + as "AS" + asc "ASC" + between "BETWEEN" + bigIntType "BIGINT" + binaryType "BINARY" + blobType "BLOB" + both "BOTH" + by "BY" + cascade "CASCADE" + caseKwd "CASE" + change "CHANGE" + character "CHARACTER" + charType "CHAR" + check "CHECK" + collate "COLLATE" + column "COLUMN" + constraint "CONSTRAINT" + convert "CONVERT" + create "CREATE" + cross "CROSS" + cumeDist "CUME_DIST" + currentDate "CURRENT_DATE" + currentTime "CURRENT_TIME" + currentTs "CURRENT_TIMESTAMP" + currentUser "CURRENT_USER" + database "DATABASE" + databases "DATABASES" + dayHour "DAY_HOUR" + dayMicrosecond "DAY_MICROSECOND" + dayMinute "DAY_MINUTE" + daySecond "DAY_SECOND" + decimalType "DECIMAL" + defaultKwd "DEFAULT" + delayed "DELAYED" + deleteKwd "DELETE" + denseRank "DENSE_RANK" + desc "DESC" + describe "DESCRIBE" + distinct "DISTINCT" + distinctRow "DISTINCTROW" + div "DIV" + doubleType "DOUBLE" + drop "DROP" + dual "DUAL" + elseKwd "ELSE" + enclosed "ENCLOSED" + escaped "ESCAPED" + exists "EXISTS" + explain "EXPLAIN" + falseKwd "FALSE" + firstValue "FIRST_VALUE" + floatType "FLOAT" + forKwd "FOR" + force "FORCE" + foreign "FOREIGN" + from "FROM" + fulltext "FULLTEXT" + generated "GENERATED" + grant "GRANT" + group "GROUP" + groups "GROUPS" + having "HAVING" + highPriority "HIGH_PRIORITY" + hourMicrosecond "HOUR_MICROSECOND" + hourMinute "HOUR_MINUTE" + hourSecond "HOUR_SECOND" + ifKwd "IF" + ignore "IGNORE" + in "IN" + index "INDEX" + infile "INFILE" + inner "INNER" + integerType "INTEGER" + interval "INTERVAL" + into "INTO" + is "IS" + insert "INSERT" + intType "INT" + int1Type "INT1" + int2Type "INT2" + int3Type "INT3" + int4Type "INT4" + int8Type "INT8" + join "JOIN" + key "KEY" + keys "KEYS" + kill "KILL" + lag "LAG" + lastValue "LAST_VALUE" + lead "LEAD" + leading "LEADING" + left "LEFT" + like "LIKE" + limit "LIMIT" + lines "LINES" + load "LOAD" + localTime "LOCALTIME" + localTs "LOCALTIMESTAMP" + lock "LOCK" + longblobType "LONGBLOB" + longtextType "LONGTEXT" + lowPriority "LOW_PRIORITY" + maxValue "MAXVALUE" + mediumblobType "MEDIUMBLOB" + mediumIntType "MEDIUMINT" + mediumtextType "MEDIUMTEXT" + minuteMicrosecond "MINUTE_MICROSECOND" + minuteSecond "MINUTE_SECOND" + mod "MOD" + not "NOT" + noWriteToBinLog "NO_WRITE_TO_BINLOG" + nthValue "NTH_VALUE" + ntile "NTILE" + null "NULL" + numericType "NUMERIC" + nvarcharType "NVARCHAR" + on "ON" + option "OPTION" + or "OR" + order "ORDER" + outer "OUTER" + over "OVER" + packKeys "PACK_KEYS" + partition "PARTITION" + percentRank "PERCENT_RANK" + precisionType "PRECISION" + primary "PRIMARY" + procedure "PROCEDURE" + shardRowIDBits "SHARD_ROW_ID_BITS" + rangeKwd "RANGE" + rank "RANK" + read "READ" + realType "REAL" + references "REFERENCES" + regexpKwd "REGEXP" + rename "RENAME" + repeat "REPEAT" + replace "REPLACE" + restrict "RESTRICT" + revoke "REVOKE" + right "RIGHT" + rlike "RLIKE" + row "ROW" + rows "ROWS" + rowNumber "ROW_NUMBER" + secondMicrosecond "SECOND_MICROSECOND" + selectKwd "SELECT" + set "SET" + show "SHOW" + smallIntType "SMALLINT" + sql "SQL" + sqlCalcFoundRows "SQL_CALC_FOUND_ROWS" + starting "STARTING" + straightJoin "STRAIGHT_JOIN" + tableKwd "TABLE" + stored "STORED" + terminated "TERMINATED" + then "THEN" + tinyblobType "TINYBLOB" + tinyIntType "TINYINT" + tinytextType "TINYTEXT" + to "TO" + trailing "TRAILING" + trigger "TRIGGER" + trueKwd "TRUE" + unique "UNIQUE" + union "UNION" + unlock "UNLOCK" + unsigned "UNSIGNED" + update "UPDATE" + usage "USAGE" + use "USE" + using "USING" + utcDate "UTC_DATE" + utcTimestamp "UTC_TIMESTAMP" + utcTime "UTC_TIME" + values "VALUES" + long "LONG" + varcharType "VARCHAR" + varbinaryType "VARBINARY" + virtual "VIRTUAL" + when "WHEN" + where "WHERE" + write "WRITE" + window "WINDOW" + with "WITH" + xor "XOR" + yearMonth "YEAR_MONTH" + zerofill "ZEROFILL" + natural "NATURAL" + + /* The following tokens belong to UnReservedKeyword. */ + action "ACTION" + after "AFTER" + always "ALWAYS" + algorithm "ALGORITHM" + any "ANY" + ascii "ASCII" + autoIncrement "AUTO_INCREMENT" + avgRowLength "AVG_ROW_LENGTH" + avg "AVG" + begin "BEGIN" + binlog "BINLOG" + bitType "BIT" + booleanType "BOOLEAN" + boolType "BOOL" + btree "BTREE" + byteType "BYTE" + cascaded "CASCADED" + charsetKwd "CHARSET" + checksum "CHECKSUM" + cleanup "CLEANUP" + client "CLIENT" + coalesce "COALESCE" + collation "COLLATION" + columns "COLUMNS" + comment "COMMENT" + commit "COMMIT" + committed "COMMITTED" + compact "COMPACT" + compressed "COMPRESSED" + compression "COMPRESSION" + connection "CONNECTION" + consistent "CONSISTENT" + current "CURRENT" + day "DAY" + data "DATA" + dateType "DATE" + datetimeType "DATETIME" + deallocate "DEALLOCATE" + definer "DEFINER" + delayKeyWrite "DELAY_KEY_WRITE" + disable "DISABLE" + do "DO" + duplicate "DUPLICATE" + dynamic "DYNAMIC" + enable "ENABLE" + end "END" + engine "ENGINE" + engines "ENGINES" + enum "ENUM" + event "EVENT" + events "EVENTS" + escape "ESCAPE" + exclusive "EXCLUSIVE" + execute "EXECUTE" + fields "FIELDS" + first "FIRST" + fixed "FIXED" + flush "FLUSH" + following "FOLLOWING" + format "FORMAT" + full "FULL" + function "FUNCTION" + grants "GRANTS" + hash "HASH" + hour "HOUR" + identified "IDENTIFIED" + isolation "ISOLATION" + indexes "INDEXES" + invoker "INVOKER" + jsonType "JSON" + keyBlockSize "KEY_BLOCK_SIZE" + local "LOCAL" + last "LAST" + less "LESS" + level "LEVEL" + master "MASTER" + microsecond "MICROSECOND" + minute "MINUTE" + mode "MODE" + modify "MODIFY" + month "MONTH" + maxRows "MAX_ROWS" + maxConnectionsPerHour "MAX_CONNECTIONS_PER_HOUR" + maxQueriesPerHour "MAX_QUERIES_PER_HOUR" + maxUpdatesPerHour "MAX_UPDATES_PER_HOUR" + maxUserConnections "MAX_USER_CONNECTIONS" + merge "MERGE" + minRows "MIN_ROWS" + names "NAMES" + national "NATIONAL" + no "NO" + none "NONE" + nulls "NULLS" + offset "OFFSET" + only "ONLY" + password "PASSWORD" + partitions "PARTITIONS" + pipesAsOr + plugins "PLUGINS" + preceding "PRECEDING" + prepare "PREPARE" + privileges "PRIVILEGES" + process "PROCESS" + processlist "PROCESSLIST" + profiles "PROFILES" + quarter "QUARTER" + query "QUERY" + queries "QUERIES" + quick "QUICK" + recover "RECOVER" + redundant "REDUNDANT" + reload "RELOAD" + repeatable "REPEATABLE" + respect "RESPECT" + replication "REPLICATION" + reverse "REVERSE" + rollback "ROLLBACK" + routine "ROUTINE" + rowCount "ROW_COUNT" + rowFormat "ROW_FORMAT" + second "SECOND" + security "SECURITY" + separator "SEPARATOR" + serializable "SERIALIZABLE" + session "SESSION" + share "SHARE" + shared "SHARED" + signed "SIGNED" + slave "SLAVE" + slow "SLOW" + snapshot "SNAPSHOT" + sqlCache "SQL_CACHE" + sqlNoCache "SQL_NO_CACHE" + start "START" + statsPersistent "STATS_PERSISTENT" + status "STATUS" + subpartition "SUBPARTITION" + subpartitions "SUBPARTITIONS" + super "SUPER" + some "SOME" + global "GLOBAL" + tables "TABLES" + tablespace "TABLESPACE" + temporary "TEMPORARY" + temptable "TEMPTABLE" + textType "TEXT" + than "THAN" + timeType "TIME" + timestampType "TIMESTAMP" + trace "TRACE" + transaction "TRANSACTION" + triggers "TRIGGERS" + truncate "TRUNCATE" + unbounded "UNBOUNDED" + uncommitted "UNCOMMITTED" + unknown "UNKNOWN" + user "USER" + undefined "UNDEFINED" + value "VALUE" + variables "VARIABLES" + view "VIEW" + warnings "WARNINGS" + identSQLErrors "ERRORS" + week "WEEK" + yearType "YEAR" + + /* The following tokens belong to NotKeywordToken. */ + addDate "ADDDATE" + bitAnd "BIT_AND" + bitOr "BIT_OR" + bitXor "BIT_XOR" + cast "CAST" + copyKwd "COPY" + count "COUNT" + curTime "CURTIME" + dateAdd "DATE_ADD" + dateSub "DATE_SUB" + extract "EXTRACT" + getFormat "GET_FORMAT" + groupConcat "GROUP_CONCAT" + next_row_id "NEXT_ROW_ID" + inplace "INPLACE" + internal "INTERNAL" + min "MIN" + max "MAX" + maxExecutionTime "MAX_EXECUTION_TIME" + now "NOW" + position "POSITION" + recent "RECENT" + std "STD" + stddev "STDDEV" + stddevPop "STDDEV_POP" + stddevSamp "STDDEV_SAMP" + subDate "SUBDATE" + sum "SUM" + substring "SUBSTRING" + timestampAdd "TIMESTAMPADD" + timestampDiff "TIMESTAMPDIFF" + top "TOP" + trim "TRIM" + + /* The following tokens belong to TiDBKeyword. */ + admin "ADMIN" + buckets "BUCKETS" + cancel "CANCEL" + ddl "DDL" + jobs "JOBS" + job "JOB" + stats "STATS" + statsMeta "STATS_META" + statsHistograms "STATS_HISTOGRAMS" + statsBuckets "STATS_BUCKETS" + statsHealthy "STATS_HEALTHY" + tidb "TIDB" + tidbHJ "TIDB_HJ" + tidbSMJ "TIDB_SMJ" + tidbINLJ "TIDB_INLJ" + + builtinAddDate + builtinBitAnd + builtinBitOr + builtinBitXor + builtinCast + builtinCount + builtinCurDate + builtinCurTime + builtinDateAdd + builtinDateSub + builtinExtract + builtinGroupConcat + builtinMax + builtinMin + builtinNow + builtinPosition + builtinSubDate + builtinSubstring + builtinSum + builtinSysDate + builtinStddevPop + builtinStddevSamp + builtinTrim + builtinUser + builtinVarPop + builtinVarSamp + +%token + + /*yy:token "1.%d" */ floatLit "floating-point literal" + /*yy:token "1.%d" */ decLit "decimal literal" + /*yy:token "%d" */ intLit "integer literal" + /*yy:token "%x" */ hexLit "hexadecimal literal" + /*yy:token "%b" */ bitLit "bit literal" + + andnot "&^" + assignmentEq ":=" + eq "=" + ge ">=" + le "<=" + jss "->" + juss "->>" + lsh "<<" + neq "!=" + neqSynonym "<>" + nulleq "<=>" + paramMarker "?" + rsh ">>" + +%token not2 + +%type + Expression "expression" + MaxValueOrExpression "maxvalue or expression" + BoolPri "boolean primary expression" + ExprOrDefault "expression or default" + PredicateExpr "Predicate expression factor" + SetExpr "Set variable statement value's expression" + BitExpr "bit expression" + SimpleExpr "simple expression" + SimpleIdent "Simple Identifier expression" + SumExpr "aggregate functions" + FunctionCallGeneric "Function call with Identifier" + FunctionCallKeyword "Function call with keyword as function name" + FunctionCallNonKeyword "Function call with nonkeyword as function name" + Literal "literal value" + Variable "User or system variable" + SystemVariable "System defined variable name" + UserVariable "User defined variable name" + SubSelect "Sub Select" + StringLiteral "text literal" + ExpressionOpt "Optional expression" + SignedLiteral "Literal or NumLiteral with sign" + DefaultValueExpr "DefaultValueExpr(Now or Signed Literal)" + NowSymOptionFraction "NowSym with optional fraction part" + +%type + AdminStmt "Check table statement or show ddl statement" + AlterTableStmt "Alter table statement" + AlterUserStmt "Alter user statement" + AnalyzeTableStmt "Analyze table statement" + BeginTransactionStmt "BEGIN TRANSACTION statement" + BinlogStmt "Binlog base64 statement" + CommitStmt "COMMIT statement" + CreateTableStmt "CREATE TABLE statement" + CreateViewStmt "CREATE VIEW stetement" + CreateUserStmt "CREATE User statement" + CreateDatabaseStmt "Create Database Statement" + CreateIndexStmt "CREATE INDEX statement" + DoStmt "Do statement" + DropDatabaseStmt "DROP DATABASE statement" + DropIndexStmt "DROP INDEX statement" + DropStatsStmt "DROP STATS statement" + DropTableStmt "DROP TABLE statement" + DropUserStmt "DROP USER" + DropViewStmt "DROP VIEW statement" + DeallocateStmt "Deallocate prepared statement" + DeleteFromStmt "DELETE FROM statement" + EmptyStmt "empty statement" + ExecuteStmt "Execute statement" + ExplainStmt "EXPLAIN statement" + ExplainableStmt "explainable statement" + FlushStmt "Flush statement" + GrantStmt "Grant statement" + InsertIntoStmt "INSERT INTO statement" + KillStmt "Kill statement" + LoadDataStmt "Load data statement" + LoadStatsStmt "Load statistic statement" + LockTablesStmt "Lock tables statement" + PreparedStmt "PreparedStmt" + SelectStmt "SELECT statement" + RenameTableStmt "rename table statement" + ReplaceIntoStmt "REPLACE INTO statement" + RevokeStmt "Revoke statement" + RollbackStmt "ROLLBACK statement" + SetStmt "Set variable statement" + ShowStmt "Show engines/databases/tables/columns/warnings/status statement" + Statement "statement" + TraceStmt "TRACE statement" + TraceableStmt "traceable statment" + TruncateTableStmt "TRUNCATE TABLE statement" + UnlockTablesStmt "Unlock tables statement" + UpdateStmt "UPDATE statement" + UnionStmt "Union select state ment" + UseStmt "USE statement" + +%type + AdminShowSlow "Admin Show Slow statement" + AlterTableOptionListOpt "alter table option list opt" + AlterTableSpec "Alter table specification" + AlterTableSpecList "Alter table specification list" + AnyOrAll "Any or All for subquery" + Assignment "assignment" + AssignmentList "assignment list" + AssignmentListOpt "assignment list opt" + AuthOption "User auth option" + AuthString "Password string value" + OptionalBraces "optional braces" + CastType "Cast function target type" + CharsetName "Character set name" + ColumnDef "table column definition" + ColumnDefList "table column definition list" + ColumnName "column name" + ColumnNameList "column name list" + ColumnList "column list" + ColumnNameListOpt "column name list opt" + ColumnNameListOptWithBrackets "column name list opt with brackets" + ColumnSetValue "insert statement set value by column name" + ColumnSetValueList "insert statement set value by column name list" + CompareOp "Compare opcode" + ColumnOption "column definition option" + ColumnOptionList "column definition option list" + VirtualOrStored "indicate generated column is stored or not" + ColumnOptionListOpt "optional column definition option list" + Constraint "table constraint" + ConstraintElem "table constraint element" + ConstraintKeywordOpt "Constraint Keyword or empty" + CreateIndexStmtUnique "CREATE INDEX optional UNIQUE clause" + CreateTableOptionListOpt "create table option list opt" + CreateTableSelectOpt "Select/Union statement in CREATE TABLE ... SELECT" + DatabaseOption "CREATE Database specification" + DatabaseOptionList "CREATE Database specification list" + DatabaseOptionListOpt "CREATE Database specification list opt" + DBName "Database Name" + DistinctOpt "Explicit distinct option" + DefaultFalseDistinctOpt "Distinct option which defaults to false" + DefaultTrueDistinctOpt "Distinct option which defaults to true" + BuggyDefaultFalseDistinctOpt "Distinct option which accepts DISTINCT ALL and defaults to false" + Enclosed "Enclosed by" + EqOpt "= or empty" + EscapedTableRef "escaped table reference" + Escaped "Escaped by" + ExpressionList "expression list" + MaxValueOrExpressionList "maxvalue or expression list" + ExpressionListOpt "expression list opt" + FuncDatetimePrecListOpt "Function datetime precision list opt" + FuncDatetimePrecList "Function datetime precision list" + Field "field expression" + Fields "Fields clause" + FieldsTerminated "Fields terminated by" + FieldAsName "Field alias name" + FieldAsNameOpt "Field alias name opt" + FieldList "field expression list" + FlushOption "Flush option" + TableRefsClause "Table references clause" + FuncDatetimePrec "Function datetime precision" + GlobalScope "The scope of variable" + GroupByClause "GROUP BY clause" + HashString "Hashed string" + HavingClause "HAVING clause" + HandleRange "handle range" + HandleRangeList "handle range list" + IfExists "If Exists" + IfNotExists "If Not Exists" + IgnoreOptional "IGNORE or empty" + IndexColName "Index column name" + IndexColNameList "List of index column name" + IndexHint "index hint" + IndexHintList "index hint list" + IndexHintListOpt "index hint list opt" + IndexHintScope "index hint scope" + IndexHintType "index hint type" + IndexName "index name" + IndexNameList "index name list" + IndexOption "Index Option" + IndexOptionList "Index Option List or empty" + IndexType "index type" + IndexTypeOpt "Optional index type" + InsertValues "Rest part of INSERT/REPLACE INTO statement" + JoinTable "join table" + JoinType "join type" + KillOrKillTiDB "Kill or Kill TiDB" + LikeEscapeOpt "like escape option" + LikeTableWithOrWithoutParen "LIKE table_name or ( LIKE table_name )" + LimitClause "LIMIT clause" + LimitOption "Limit option could be integer or parameter marker." + Lines "Lines clause" + LinesTerminated "Lines terminated by" + LocalOpt "Local opt" + LockClause "Alter table lock clause" + MaxNumBuckets "Max number of buckets" + NumLiteral "Num/Int/Float/Decimal Literal" + NoWriteToBinLogAliasOpt "NO_WRITE_TO_BINLOG alias LOCAL or empty" + ObjectType "Grant statement object type" + OnDuplicateKeyUpdate "ON DUPLICATE KEY UPDATE value list" + DuplicateOpt "[IGNORE|REPLACE] in CREATE TABLE ... SELECT statement" + OptFull "Full or empty" + Order "ORDER BY clause optional collation specification" + OrderBy "ORDER BY clause" + OrReplace "or replace" + ByItem "BY item" + OrderByOptional "Optional ORDER BY clause optional" + ByList "BY list" + QuickOptional "QUICK or empty" + PartitionDefinition "Partition definition" + PartitionDefinitionList "Partition definition list" + PartitionDefinitionListOpt "Partition definition list option" + PartitionOpt "Partition option" + PartitionNameList "Partition name list" + PartitionNumOpt "PARTITION NUM option" + PartDefValuesOpt "VALUES {LESS THAN {(expr | value_list) | MAXVALUE} | IN {value_list}" + PartDefOptionsOpt "PartDefOptionList option" + PartDefOptionList "PartDefOption list" + PartDefOption "COMMENT [=] xxx | TABLESPACE [=] tablespace_name | ENGINE [=] xxx" + PasswordOpt "Password option" + ColumnPosition "Column position [First|After ColumnName]" + PrepareSQL "Prepare statement sql string" + PriorityOpt "Statement priority option" + PrivElem "Privilege element" + PrivElemList "Privilege element list" + PrivLevel "Privilege scope" + PrivType "Privilege type" + ReferDef "Reference definition" + OnDeleteOpt "optional ON DELETE clause" + OnUpdateOpt "optional ON UPDATE clause" + OptGConcatSeparator "optional GROUP_CONCAT SEPARATOR" + ReferOpt "reference option" + RowFormat "Row format option" + RowValue "Row value" + SelectLockOpt "FOR UPDATE or LOCK IN SHARE MODE," + SelectStmtCalcFoundRows "SELECT statement optional SQL_CALC_FOUND_ROWS" + SelectStmtSQLCache "SELECT statement optional SQL_CAHCE/SQL_NO_CACHE" + SelectStmtStraightJoin "SELECT statement optional STRAIGHT_JOIN" + SelectStmtFieldList "SELECT statement field list" + SelectStmtLimit "SELECT statement optional LIMIT clause" + SelectStmtOpts "Select statement options" + SelectStmtBasic "SELECT statement from constant value" + SelectStmtFromDualTable "SELECT statement from dual table" + SelectStmtFromTable "SELECT statement from table" + SelectStmtGroup "SELECT statement optional GROUP BY clause" + ShowTargetFilterable "Show target that can be filtered by WHERE or LIKE" + ShowDatabaseNameOpt "Show tables/columns statement database name option" + ShowTableAliasOpt "Show table alias option" + ShowLikeOrWhereOpt "Show like or where clause option" + Starting "Starting by" + StatementList "statement list" + StatsPersistentVal "stats_persistent value" + StringName "string literal or identifier" + StringList "string list" + SubPartitionOpt "SubPartition option" + SubPartitionNumOpt "SubPartition NUM option" + Symbol "Constraint Symbol" + TableAsName "table alias name" + TableAsNameOpt "table alias name optional" + TableElement "table definition element" + TableElementList "table definition element list" + TableElementListOpt "table definition element list optional" + TableFactor "table factor" + TableLock "Table name and lock type" + TableLockList "Table lock list" + TableName "Table name" + TableNameList "Table name list" + TableNameListOpt "Table name list opt" + TableOption "create table option" + TableOptionList "create table option list" + TableRef "table reference" + TableRefs "table references" + TableToTable "rename table to table" + TableToTableList "rename table to table by list" + + TransactionChar "Transaction characteristic" + TransactionChars "Transaction characteristic list" + TrimDirection "Trim string direction" + UnionOpt "Union Option(empty/ALL/DISTINCT)" + UnionClauseList "Union select clause list" + UnionSelect "Union (select) item" + Username "Username" + UsernameList "UsernameList" + UserSpec "Username and auth option" + UserSpecList "Username and auth option list" + UserVariableList "User defined variable name list" + Values "values" + ValuesList "values list" + ValuesOpt "values optional" + VariableAssignment "set variable value" + VariableAssignmentList "set variable value list" + ViewAlgorithm "view algorithm" + ViewCheckOption "view check option" + ViewDefiner "view definer" + ViewName "view name" + ViewFieldList "create view statement field list" + ViewSQLSecurity "view sql security" + WhereClause "WHERE clause" + WhereClauseOptional "Optional WHERE clause" + WhenClause "When clause" + WhenClauseList "When clause list" + WithReadLockOpt "With Read Lock opt" + WithGrantOptionOpt "With Grant Option opt" + ElseOpt "Optional else clause" + Type "Types" + + OptExistingWindowName "Optional existing WINDOW name" + OptFromFirstLast "Optional FROM FIRST/LAST" + OptLLDefault "Optional LEAD/LAG default" + OptLeadLagInfo "Optional LEAD/LAG info" + OptNullTreatment "Optional NULL treatment" + OptPartitionClause "Optional PARTITION clause" + OptWindowOrderByClause "Optional ORDER BY clause in WINDOW" + OptWindowFrameClause "Optional FRAME clause in WINDOW" + OptWindowingClause "Optional OVER clause" + WindowingClause "OVER clause" + WindowClauseOptional "Optional WINDOW clause" + WindowDefinitionList "WINDOW definition list" + WindowDefinition "WINDOW definition" + WindowFrameUnits "WINDOW frame units" + WindowFrameBetween "WINDOW frame between" + WindowFrameBound "WINDOW frame bound" + WindowFrameExtent "WINDOW frame extent" + WindowFrameStart "WINDOW frame start" + WindowFuncCall "WINDOW function call" + WindowName "WINDOW name" + WindowNameOrSpec "WINDOW name or spec" + WindowSpec "WINDOW spec" + WindowSpecDetails "WINDOW spec details" + + BetweenOrNotOp "Between predicate" + IsOrNotOp "Is predicate" + InOrNotOp "In predicate" + LikeOrNotOp "Like predicate" + RegexpOrNotOp "Regexp predicate" + + NumericType "Numeric types" + IntegerType "Integer Types types" + BooleanType "Boolean Types types" + FixedPointType "Exact value types" + FloatingPointType "Approximate value types" + BitValueType "bit value types" + StringType "String types" + BlobType "Blob types" + TextType "Text types" + DateAndTimeType "Date and Time types" + + OptFieldLen "Field length or empty" + FieldLen "Field length" + FieldOpts "Field type definition option list" + FieldOpt "Field type definition option" + FloatOpt "Floating-point type option" + Precision "Floating-point precision option" + OptBinary "Optional BINARY" + OptBinMod "Optional BINARY mode" + OptCharset "Optional Character setting" + OptCollate "Optional Collate setting" + IgnoreLines "Ignore num(int) lines" + NUM "A number" + NumList "Some numbers" + LengthNum "Field length num(uint64)" + HintTableList "Table list in optimizer hint" + TableOptimizerHintOpt "Table level optimizer hint" + TableOptimizerHints "Table level optimizer hints" + TableOptimizerHintList "Table level optimizer hint list" + +%type + AsOpt "AS or EmptyString" + KeyOrIndex "{KEY|INDEX}" + ColumnKeywordOpt "Column keyword or empty" + PrimaryOpt "Optional primary keyword" + NowSym "CURRENT_TIMESTAMP/LOCALTIME/LOCALTIMESTAMP" + NowSymFunc "CURRENT_TIMESTAMP/LOCALTIME/LOCALTIMESTAMP/NOW" + DefaultKwdOpt "optional DEFAULT keyword" + DatabaseSym "DATABASE or SCHEMA" + ExplainSym "EXPLAIN or DESCRIBE or DESC" + RegexpSym "REGEXP or RLIKE" + IntoOpt "INTO or EmptyString" + ValueSym "Value or Values" + Varchar "{NATIONAL VARCHAR|VARCHAR|NVARCHAR}" + TimeUnit "Time unit for 'DATE_ADD', 'DATE_SUB', 'ADDDATE', 'SUBDATE', 'EXTRACT'" + TimestampUnit "Time unit for 'TIMESTAMPADD' and 'TIMESTAMPDIFF'" + DeallocateSym "Deallocate or drop" + OuterOpt "optional OUTER clause" + CrossOpt "Cross join option" + TablesTerminalSym "{TABLE|TABLES}" + IsolationLevel "Isolation level" + ShowIndexKwd "Show index/indexs/key keyword" + DistinctKwd "DISTINCT/DISTINCTROW keyword" + FromOrIn "From or In" + OptTable "Optional table keyword" + OptInteger "Optional Integer keyword" + NationalOpt "National option" + CharsetKw "charset or charater set" + CommaOpt "optional comma" + LockType "Table locks type" + logAnd "logical and operator" + logOr "logical or operator" + FieldsOrColumns "Fields or columns" + GetFormatSelector "{DATE|DATETIME|TIME|TIMESTAMP}" + +%type + ODBCDateTimeType "ODBC type keywords for date and time literals" + Identifier "identifier or unreserved keyword" + NotKeywordToken "Tokens not mysql keyword but treated specially" + UnReservedKeyword "MySQL unreserved keywords" + TiDBKeyword "TiDB added keywords" + FunctionNameConflict "Built-in function call names which are conflict with keywords" + FunctionNameOptionalBraces "Function with optional braces, all of them are reserved keywords." + FunctionNameDatetimePrecision "Function with optional datetime precision, all of them are reserved keywords." + FunctionNameDateArith "Date arith function call names (date_add or date_sub)" + FunctionNameDateArithMultiForms "Date arith function call names (adddate or subdate)" + +%precedence empty + +%precedence sqlCache sqlNoCache +%precedence lowerThanIntervalKeyword +%precedence interval +%precedence lowerThanStringLitToken +%precedence stringLit +%precedence lowerThanSetKeyword +%precedence set +%precedence lowerThanInsertValues +%precedence insertValues +%precedence lowerThanCreateTableSelect +%precedence createTableSelect +%precedence lowerThanKey +%precedence key + +%left join straightJoin inner cross left right full natural +/* A dummy token to force the priority of TableRef production in a join. */ +%left tableRefPriority +%precedence lowerThanOn +%precedence on using +%right assignmentEq +%left pipes or pipesAsOr +%left xor +%left andand and +%left between +%precedence lowerThanEq +%left eq ge le neq neqSynonym '>' '<' is like in +%left '|' +%left '&' +%left rsh lsh +%left '-' '+' +%left '*' '/' '%' div mod +%left '^' +%left '~' neg +%right not not2 +%right collate + +%precedence '(' +%precedence quick +%precedence escape +%precedence lowerThanComma +%precedence ',' +%precedence higherThanComma + +%start Start + +%% + +Start: + StatementList + +/**************************************AlterTableStmt*************************************** + * See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html + *******************************************************************************************/ +AlterTableStmt: + "ALTER" IgnoreOptional "TABLE" TableName AlterTableSpecList + { + $$ = &ast.AlterTableStmt{ + Table: $4.(*ast.TableName), + Specs: $5.([]*ast.AlterTableSpec), + } + } +| "ALTER" IgnoreOptional "TABLE" TableName "ANALYZE" "PARTITION" PartitionNameList MaxNumBuckets + { + $$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$4.(*ast.TableName)}, PartitionNames: $7.([]model.CIStr), MaxNumBuckets: $8.(uint64),} + } +| "ALTER" IgnoreOptional "TABLE" TableName "ANALYZE" "PARTITION" PartitionNameList "INDEX" IndexNameList MaxNumBuckets + { + $$ = &ast.AnalyzeTableStmt{ + TableNames: []*ast.TableName{$4.(*ast.TableName)}, + PartitionNames: $7.([]model.CIStr), + IndexNames: $9.([]model.CIStr), + IndexFlag: true, + MaxNumBuckets: $10.(uint64), + } + } + +AlterTableSpec: + AlterTableOptionListOpt + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableOption, + Options:$1.([]*ast.TableOption), + } + } +| "CONVERT" "TO" CharsetKw CharsetName OptCollate + { + op := &ast.AlterTableSpec{ + Tp: ast.AlterTableOption, + Options:[]*ast.TableOption{{Tp: ast.TableOptionCharset, StrValue: $4.(string)}}, + } + if $5 != "" { + op.Options = append(op.Options, &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: $5.(string)}) + } + $$ = op + } +| "ADD" ColumnKeywordOpt ColumnDef ColumnPosition + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddColumns, + NewColumns: []*ast.ColumnDef{$3.(*ast.ColumnDef)}, + Position: $4.(*ast.ColumnPosition), + } + } +| "ADD" ColumnKeywordOpt '(' ColumnDefList ')' + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddColumns, + NewColumns: $4.([]*ast.ColumnDef), + } + } +| "ADD" Constraint + { + constraint := $2.(*ast.Constraint) + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddConstraint, + Constraint: constraint, + } + } +| "ADD" "PARTITION" PartitionDefinitionListOpt + { + var defs []*ast.PartitionDefinition + if $3 != nil { + defs = $3.([]*ast.PartitionDefinition) + } + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddPartitions, + PartDefinitions: defs, + } + } +| "ADD" "PARTITION" "PARTITIONS" NUM + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAddPartitions, + Num: getUint64FromNUM($4), + } + } +| "COALESCE" "PARTITION" NUM + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableCoalescePartitions, + Num: getUint64FromNUM($3), + } + } +| "DROP" ColumnKeywordOpt ColumnName RestrictOrCascadeOpt + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropColumn, + OldColumnName: $3.(*ast.ColumnName), + } + } +| "DROP" "PRIMARY" "KEY" + { + $$ = &ast.AlterTableSpec{Tp: ast.AlterTableDropPrimaryKey} + } +| "DROP" "PARTITION" Identifier + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropPartition, + Name: $3, + } + } +| "DROP" KeyOrIndex Identifier + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropIndex, + Name: $3, + } + } +| "DROP" "FOREIGN" "KEY" Symbol + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableDropForeignKey, + Name: $4.(string), + } + } +| "DISABLE" "KEYS" + { + $$ = &ast.AlterTableSpec{} + } +| "ENABLE" "KEYS" + { + $$ = &ast.AlterTableSpec{} + } +| "MODIFY" ColumnKeywordOpt ColumnDef ColumnPosition + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableModifyColumn, + NewColumns: []*ast.ColumnDef{$3.(*ast.ColumnDef)}, + Position: $4.(*ast.ColumnPosition), + } + } +| "CHANGE" ColumnKeywordOpt ColumnName ColumnDef ColumnPosition + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableChangeColumn, + OldColumnName: $3.(*ast.ColumnName), + NewColumns: []*ast.ColumnDef{$4.(*ast.ColumnDef)}, + Position: $5.(*ast.ColumnPosition), + } + } +| "ALTER" ColumnKeywordOpt ColumnName "SET" "DEFAULT" SignedLiteral + { + option := &ast.ColumnOption{Expr: $6} + colDef := &ast.ColumnDef{ + Name: $3.(*ast.ColumnName), + Options: []*ast.ColumnOption{option}, + } + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAlterColumn, + NewColumns: []*ast.ColumnDef{colDef}, + } + } +| "ALTER" ColumnKeywordOpt ColumnName "DROP" "DEFAULT" + { + colDef := &ast.ColumnDef{ + Name: $3.(*ast.ColumnName), + } + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAlterColumn, + NewColumns: []*ast.ColumnDef{colDef}, + } + } +| "RENAME" "TO" TableName + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameTable, + NewTable: $3.(*ast.TableName), + } + } +| "RENAME" TableName + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameTable, + NewTable: $2.(*ast.TableName), + } + } +| "RENAME" "AS" TableName + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameTable, + NewTable: $3.(*ast.TableName), + } + } +| "RENAME" KeyOrIndex Identifier "TO" Identifier + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableRenameIndex, + FromKey: model.NewCIStr($3), + ToKey: model.NewCIStr($5), + } + } +| LockClause + { + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableLock, + LockType: $1.(ast.LockType), + } + } +| "ALGORITHM" EqOpt AlterAlgorithm + { + // Parse it and ignore it. Just for compatibility. + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableAlgorithm, + } + } +| "FORCE" + { + // Parse it and ignore it. Just for compatibility. + $$ = &ast.AlterTableSpec{ + Tp: ast.AlterTableForce, + } + } + + +AlterAlgorithm: + "DEFAULT" | "INPLACE" | "COPY" + +LockClauseOpt: + {} +| LockClause {} + +LockClause: + "LOCK" eq "NONE" + { + $$ = ast.LockTypeNone + } +| "LOCK" eq "DEFAULT" + { + $$ = ast.LockTypeDefault + } +| "LOCK" eq "SHARED" + { + $$ = ast.LockTypeShared + } +| "LOCK" eq "EXCLUSIVE" + { + $$ = ast.LockTypeExclusive + } + +KeyOrIndex: "KEY" | "INDEX" + + +KeyOrIndexOpt: + {} +| KeyOrIndex + +ColumnKeywordOpt: + {} +| "COLUMN" + +ColumnPosition: + { + $$ = &ast.ColumnPosition{Tp: ast.ColumnPositionNone} + } +| "FIRST" + { + $$ = &ast.ColumnPosition{Tp: ast.ColumnPositionFirst} + } +| "AFTER" ColumnName + { + $$ = &ast.ColumnPosition{ + Tp: ast.ColumnPositionAfter, + RelativeColumn: $2.(*ast.ColumnName), + } + } + +AlterTableSpecList: + AlterTableSpec + { + $$ = []*ast.AlterTableSpec{$1.(*ast.AlterTableSpec)} + } +| AlterTableSpecList ',' AlterTableSpec + { + $$ = append($1.([]*ast.AlterTableSpec), $3.(*ast.AlterTableSpec)) + } + +PartitionNameList: + Identifier + { + $$ = []model.CIStr{model.NewCIStr($1)} + } +| PartitionNameList ',' Identifier + { + $$ = append($1.([]model.CIStr), model.NewCIStr($3)) + } + +ConstraintKeywordOpt: + { + $$ = nil + } +| "CONSTRAINT" + { + $$ = nil + } +| "CONSTRAINT" Symbol + { + $$ = $2.(string) + } + +Symbol: + Identifier + { + $$ = $1 + } + +/**************************************RenameTableStmt*************************************** + * See http://dev.mysql.com/doc/refman/5.7/en/rename-table.html + * + * TODO: refactor this when you are going to add full support for multiple schema changes. + * Currently it is only useful for syncer which depends heavily on tidb parser to do some dirty work. + *******************************************************************************************/ +RenameTableStmt: + "RENAME" "TABLE" TableToTableList + { + $$ = &ast.RenameTableStmt{ + OldTable: $3.([]*ast.TableToTable)[0].OldTable, + NewTable: $3.([]*ast.TableToTable)[0].NewTable, + TableToTables: $3.([]*ast.TableToTable), + } + } + +TableToTableList: + TableToTable + { + $$ = []*ast.TableToTable{$1.(*ast.TableToTable)} + } +| TableToTableList ',' TableToTable + { + $$ = append($1.([]*ast.TableToTable), $3.(*ast.TableToTable)) + } + +TableToTable: + TableName "TO" TableName + { + $$ = &ast.TableToTable{ + OldTable: $1.(*ast.TableName), + NewTable: $3.(*ast.TableName), + } + } + + +/*******************************************************************************************/ + +AnalyzeTableStmt: + "ANALYZE" "TABLE" TableNameList MaxNumBuckets + { + $$ = &ast.AnalyzeTableStmt{TableNames: $3.([]*ast.TableName), MaxNumBuckets: $4.(uint64)} + } +| "ANALYZE" "TABLE" TableName "INDEX" IndexNameList MaxNumBuckets + { + $$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$3.(*ast.TableName)}, IndexNames: $5.([]model.CIStr), IndexFlag: true, MaxNumBuckets: $6.(uint64)} + } +| "ANALYZE" "TABLE" TableName "PARTITION" PartitionNameList MaxNumBuckets + { + $$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$3.(*ast.TableName)}, PartitionNames: $5.([]model.CIStr), MaxNumBuckets: $6.(uint64),} + } +| "ANALYZE" "TABLE" TableName "PARTITION" PartitionNameList "INDEX" IndexNameList MaxNumBuckets + { + $$ = &ast.AnalyzeTableStmt{ + TableNames: []*ast.TableName{$3.(*ast.TableName)}, + PartitionNames: $5.([]model.CIStr), + IndexNames: $7.([]model.CIStr), + IndexFlag: true, + MaxNumBuckets: $8.(uint64), + } + } + +MaxNumBuckets: + { + $$ = uint64(0) + } +| "WITH" NUM "BUCKETS" + { + $$ = getUint64FromNUM($2) + } + +/*******************************************************************************************/ +Assignment: + ColumnName eq Expression + { + $$ = &ast.Assignment{Column: $1.(*ast.ColumnName), Expr:$3} + } + +AssignmentList: + Assignment + { + $$ = []*ast.Assignment{$1.(*ast.Assignment)} + } +| AssignmentList ',' Assignment + { + $$ = append($1.([]*ast.Assignment), $3.(*ast.Assignment)) + } + +AssignmentListOpt: + /* EMPTY */ + { + $$ = []*ast.Assignment{} + } +| AssignmentList + +BeginTransactionStmt: + "BEGIN" + { + $$ = &ast.BeginStmt{} + } +| "START" "TRANSACTION" + { + $$ = &ast.BeginStmt{} + } +| "START" "TRANSACTION" "WITH" "CONSISTENT" "SNAPSHOT" + { + $$ = &ast.BeginStmt{} + } + +BinlogStmt: + "BINLOG" stringLit + { + $$ = &ast.BinlogStmt{Str: $2} + } + +ColumnDefList: + ColumnDef + { + $$ = []*ast.ColumnDef{$1.(*ast.ColumnDef)} + } +| ColumnDefList ',' ColumnDef + { + $$ = append($1.([]*ast.ColumnDef), $3.(*ast.ColumnDef)) + } + +ColumnDef: + ColumnName Type ColumnOptionListOpt + { + $$ = &ast.ColumnDef{Name: $1.(*ast.ColumnName), Tp: $2.(*types.FieldType), Options: $3.([]*ast.ColumnOption)} + } + +ColumnName: + Identifier + { + $$ = &ast.ColumnName{Name: model.NewCIStr($1)} + } +| Identifier '.' Identifier + { + $$ = &ast.ColumnName{Table: model.NewCIStr($1), Name: model.NewCIStr($3)} + } +| Identifier '.' Identifier '.' Identifier + { + $$ = &ast.ColumnName{Schema: model.NewCIStr($1), Table: model.NewCIStr($3), Name: model.NewCIStr($5)} + } + +ColumnNameList: + ColumnName + { + $$ = []*ast.ColumnName{$1.(*ast.ColumnName)} + } +| ColumnNameList ',' ColumnName + { + $$ = append($1.([]*ast.ColumnName), $3.(*ast.ColumnName)) + } + +ColumnNameListOpt: + /* EMPTY */ + { + $$ = []*ast.ColumnName{} + } +| ColumnNameList + { + $$ = $1.([]*ast.ColumnName) + } + +ColumnNameListOptWithBrackets: + /* EMPTY */ + { + $$ = []*ast.ColumnName{} + } +| '(' ColumnNameListOpt ')' + { + $$ = $2.([]*ast.ColumnName) + } + +CommitStmt: + "COMMIT" + { + $$ = &ast.CommitStmt{} + } + +PrimaryOpt: + {} +| "PRIMARY" + +ColumnOption: + "NOT" "NULL" + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionNotNull} + } +| "NULL" + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionNull} + } +| "AUTO_INCREMENT" + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionAutoIncrement} + } +| PrimaryOpt "KEY" + { + // KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY + // can also be specified as just KEY when given in a column definition. + // See http://dev.mysql.com/doc/refman/5.7/en/create-table.html + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionPrimaryKey} + } +| "UNIQUE" %prec lowerThanKey + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey} + } +| "UNIQUE" "KEY" + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey} + } +| "DEFAULT" DefaultValueExpr + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionDefaultValue, Expr: $2} + } +| "ON" "UPDATE" NowSymOptionFraction + { + nowFunc := &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: nowFunc} + } +| "COMMENT" stringLit + { + $$ = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr($2)} + } +| "CHECK" '(' Expression ')' + { + // See https://dev.mysql.com/doc/refman/5.7/en/create-table.html + // The CHECK clause is parsed but ignored by all storage engines. + $$ = &ast.ColumnOption{} + } +| GeneratedAlways "AS" '(' Expression ')' VirtualOrStored + { + startOffset := parser.startOffset(&yyS[yypt-2]) + endOffset := parser.endOffset(&yyS[yypt-1]) + expr := $4 + expr.SetText(parser.src[startOffset:endOffset]) + + $$ = &ast.ColumnOption{ + Tp: ast.ColumnOptionGenerated, + Expr: expr, + Stored: $6.(bool), + } + } +| ReferDef + { + $$ = &ast.ColumnOption{ + Tp: ast.ColumnOptionReference, + Refer: $1.(*ast.ReferenceDef), + } + } + +GeneratedAlways: | "GENERATED" "ALWAYS" + +VirtualOrStored: + { + $$ = false + } +| "VIRTUAL" + { + $$ = false + } +| "STORED" + { + $$ = true + } + +ColumnOptionList: + ColumnOption + { + $$ = []*ast.ColumnOption{$1.(*ast.ColumnOption)} + } +| ColumnOptionList ColumnOption + { + $$ = append($1.([]*ast.ColumnOption), $2.(*ast.ColumnOption)) + } + +ColumnOptionListOpt: + { + $$ = []*ast.ColumnOption{} + } +| ColumnOptionList + { + $$ = $1.([]*ast.ColumnOption) + } + +ConstraintElem: + "PRIMARY" "KEY" IndexName IndexTypeOpt '(' IndexColNameList ')' IndexOptionList + { + c := &ast.Constraint{ + Tp: ast.ConstraintPrimaryKey, + Keys: $6.([]*ast.IndexColName), + } + if $8 != nil { + c.Option = $8.(*ast.IndexOption) + } + if $4 != nil { + if c.Option == nil { + c.Option = &ast.IndexOption{} + } + c.Option.Tp = $4.(model.IndexType) + } + $$ = c + } +| "FULLTEXT" KeyOrIndex IndexName '(' IndexColNameList ')' IndexOptionList + { + c := &ast.Constraint{ + Tp: ast.ConstraintFulltext, + Keys: $5.([]*ast.IndexColName), + Name: $3.(string), + } + if $7 != nil { + c.Option = $7.(*ast.IndexOption) + } + $$ = c + } +| KeyOrIndex IndexName IndexTypeOpt '(' IndexColNameList ')' IndexOptionList + { + c := &ast.Constraint{ + Tp: ast.ConstraintIndex, + Keys: $5.([]*ast.IndexColName), + Name: $2.(string), + } + if $7 != nil { + c.Option = $7.(*ast.IndexOption) + } + if $3 != nil { + if c.Option == nil { + c.Option = &ast.IndexOption{} + } + c.Option.Tp = $3.(model.IndexType) + } + $$ = c + } +| "UNIQUE" KeyOrIndexOpt IndexName IndexTypeOpt '(' IndexColNameList ')' IndexOptionList + { + c := &ast.Constraint{ + Tp: ast.ConstraintUniq, + Keys: $6.([]*ast.IndexColName), + Name: $3.(string), + } + if $8 != nil { + c.Option = $8.(*ast.IndexOption) + } + if $4 != nil { + if c.Option == nil { + c.Option = &ast.IndexOption{} + } + c.Option.Tp = $4.(model.IndexType) + } + $$ = c + } +| "FOREIGN" "KEY" IndexName '(' IndexColNameList ')' ReferDef + { + $$ = &ast.Constraint{ + Tp: ast.ConstraintForeignKey, + Keys: $5.([]*ast.IndexColName), + Name: $3.(string), + Refer: $7.(*ast.ReferenceDef), + } + } + +ReferDef: + "REFERENCES" TableName '(' IndexColNameList ')' OnDeleteOpt OnUpdateOpt + { + var onDeleteOpt *ast.OnDeleteOpt + if $6 != nil { + onDeleteOpt = $6.(*ast.OnDeleteOpt) + } + var onUpdateOpt *ast.OnUpdateOpt + if $7 != nil { + onUpdateOpt = $7.(*ast.OnUpdateOpt) + } + $$ = &ast.ReferenceDef{ + Table: $2.(*ast.TableName), + IndexColNames: $4.([]*ast.IndexColName), + OnDelete: onDeleteOpt, + OnUpdate: onUpdateOpt, + } + } + +OnDeleteOpt: + { + $$ = &ast.OnDeleteOpt{} + } %prec lowerThanOn +| "ON" "DELETE" ReferOpt + { + $$ = &ast.OnDeleteOpt{ReferOpt: $3.(ast.ReferOptionType)} + } + +OnUpdateOpt: + { + $$ = &ast.OnUpdateOpt{} + } %prec lowerThanOn +| "ON" "UPDATE" ReferOpt + { + $$ = &ast.OnUpdateOpt{ReferOpt: $3.(ast.ReferOptionType)} + } + +ReferOpt: + "RESTRICT" + { + $$ = ast.ReferOptionRestrict + } +| "CASCADE" + { + $$ = ast.ReferOptionCascade + } +| "SET" "NULL" + { + $$ = ast.ReferOptionSetNull + } +| "NO" "ACTION" + { + $$ = ast.ReferOptionNoAction + } + +/* + * The DEFAULT clause specifies a default value for a column. + * With one exception, the default value must be a constant; + * it cannot be a function or an expression. This means, for example, + * that you cannot set the default for a date column to be the value of + * a function such as NOW() or CURRENT_DATE. The exception is that you + * can specify CURRENT_TIMESTAMP as the default for a TIMESTAMP or DATETIME column. + * + * See http://dev.mysql.com/doc/refman/5.7/en/create-table.html + * https://github.com/mysql/mysql-server/blob/5.7/sql/sql_yacc.yy#L6832 + */ +DefaultValueExpr: + NowSymOptionFraction | SignedLiteral + +NowSymOptionFraction: + NowSym + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } +| NowSymFunc '(' ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } +| NowSymFunc '(' NUM ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")} + } + +/* +* See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_localtime +* TODO: Process other three keywords +*/ +NowSymFunc: + "CURRENT_TIMESTAMP" | "LOCALTIME" | "LOCALTIMESTAMP" | builtinNow +NowSym: + "CURRENT_TIMESTAMP" | "LOCALTIME" | "LOCALTIMESTAMP" + + +SignedLiteral: + Literal + { + $$ = ast.NewValueExpr($1) + } +| '+' NumLiteral + { + $$ = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr($2)} + } +| '-' NumLiteral + { + $$ = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr($2)} + } + +NumLiteral: + intLit +| floatLit +| decLit + + +CreateIndexStmt: + "CREATE" CreateIndexStmtUnique "INDEX" Identifier IndexTypeOpt "ON" TableName '(' IndexColNameList ')' IndexOptionList LockClauseOpt + { + var indexOption *ast.IndexOption + if $11 != nil { + indexOption = $11.(*ast.IndexOption) + if indexOption.Tp == model.IndexTypeInvalid { + if $5 != nil { + indexOption.Tp = $5.(model.IndexType) + } + } + } else { + indexOption = &ast.IndexOption{} + if $5 != nil { + indexOption.Tp = $5.(model.IndexType) + } + } + $$ = &ast.CreateIndexStmt{ + Unique: $2.(bool), + IndexName: $4, + Table: $7.(*ast.TableName), + IndexColNames: $9.([]*ast.IndexColName), + IndexOption: indexOption, + } + } + +CreateIndexStmtUnique: + { + $$ = false + } +| "UNIQUE" + { + $$ = true + } + +IndexColName: + ColumnName OptFieldLen Order + { + //Order is parsed but just ignored as MySQL did + $$ = &ast.IndexColName{Column: $1.(*ast.ColumnName), Length: $2.(int)} + } + +IndexColNameList: + IndexColName + { + $$ = []*ast.IndexColName{$1.(*ast.IndexColName)} + } +| IndexColNameList ',' IndexColName + { + $$ = append($1.([]*ast.IndexColName), $3.(*ast.IndexColName)) + } + + + +/******************************************************************* + * + * Create Database Statement + * CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name + * [create_specification] ... + * + * create_specification: + * [DEFAULT] CHARACTER SET [=] charset_name + * | [DEFAULT] COLLATE [=] collation_name + *******************************************************************/ +CreateDatabaseStmt: + "CREATE" DatabaseSym IfNotExists DBName DatabaseOptionListOpt + { + $$ = &ast.CreateDatabaseStmt{ + IfNotExists: $3.(bool), + Name: $4.(string), + Options: $5.([]*ast.DatabaseOption), + } + } + +DBName: + Identifier + { + $$ = $1 + } + +DatabaseOption: + DefaultKwdOpt CharsetKw EqOpt CharsetName + { + $$ = &ast.DatabaseOption{Tp: ast.DatabaseOptionCharset, Value: $4.(string)} + } +| DefaultKwdOpt "COLLATE" EqOpt StringName + { + $$ = &ast.DatabaseOption{Tp: ast.DatabaseOptionCollate, Value: $4.(string)} + } + +DatabaseOptionListOpt: + { + $$ = []*ast.DatabaseOption{} + } +| DatabaseOptionList + +DatabaseOptionList: + DatabaseOption + { + $$ = []*ast.DatabaseOption{$1.(*ast.DatabaseOption)} + } +| DatabaseOptionList DatabaseOption + { + $$ = append($1.([]*ast.DatabaseOption), $2.(*ast.DatabaseOption)) + } + +/******************************************************************* + * + * Create Table Statement + * + * Example: + * CREATE TABLE Persons + * ( + * P_Id int NOT NULL, + * LastName varchar(255) NOT NULL, + * FirstName varchar(255), + * Address varchar(255), + * City varchar(255), + * PRIMARY KEY (P_Id) + * ) + *******************************************************************/ + +CreateTableStmt: + "CREATE" "TABLE" IfNotExists TableName TableElementListOpt CreateTableOptionListOpt PartitionOpt DuplicateOpt AsOpt CreateTableSelectOpt + { + stmt := $5.(*ast.CreateTableStmt) + stmt.Table = $4.(*ast.TableName) + stmt.IfNotExists = $3.(bool) + stmt.Options = $6.([]*ast.TableOption) + if $7 != nil { + stmt.Partition = $7.(*ast.PartitionOptions) + } + stmt.OnDuplicate = $8.(ast.OnDuplicateCreateTableSelectType) + stmt.Select = $10.(*ast.CreateTableStmt).Select + $$ = stmt + } +| "CREATE" "TABLE" IfNotExists TableName LikeTableWithOrWithoutParen + { + $$ = &ast.CreateTableStmt{ + Table: $4.(*ast.TableName), + ReferTable: $5.(*ast.TableName), + IfNotExists: $3.(bool), + } + } + +DefaultKwdOpt: + {} +| "DEFAULT" + +PartitionOpt: + { + $$ = nil + } +| "PARTITION" "BY" "KEY" '(' ColumnNameList ')' PartitionNumOpt PartitionDefinitionListOpt + { + $$ = nil + } +| "PARTITION" "BY" "HASH" '(' Expression ')' PartitionNumOpt + { + tmp := &ast.PartitionOptions{ + Tp: model.PartitionTypeHash, + Expr: $5.(ast.ExprNode), + // If you do not include a PARTITIONS clause, the number of partitions defaults to 1 + Num: 1, + } + if $7 != nil { + tmp.Num = getUint64FromNUM($7) + } + $$ = tmp + } +| "PARTITION" "BY" "RANGE" '(' Expression ')' PartitionNumOpt SubPartitionOpt PartitionDefinitionListOpt + { + var defs []*ast.PartitionDefinition + if $9 != nil { + defs = $9.([]*ast.PartitionDefinition) + } + $$ = &ast.PartitionOptions{ + Tp: model.PartitionTypeRange, + Expr: $5.(ast.ExprNode), + Definitions: defs, + } + } +| "PARTITION" "BY" "RANGE" "COLUMNS" '(' ColumnNameList ')' PartitionNumOpt PartitionDefinitionListOpt + { + var defs []*ast.PartitionDefinition + if $9 != nil { + defs = $9.([]*ast.PartitionDefinition) + } + $$ = &ast.PartitionOptions{ + Tp: model.PartitionTypeRange, + ColumnNames: $6.([]*ast.ColumnName), + Definitions: defs, + } + } + +SubPartitionOpt: + {} +| "SUBPARTITION" "BY" "HASH" '(' Expression ')' SubPartitionNumOpt + {} +| "SUBPARTITION" "BY" "KEY" '(' ColumnNameList ')' SubPartitionNumOpt + {} + +SubPartitionNumOpt: + {} +| "SUBPARTITIONS" NUM + {} + +PartitionNumOpt: + { + $$ = nil + } +| "PARTITIONS" NUM + { + $$ = $2 + } + +PartitionDefinitionListOpt: + /* empty */ %prec lowerThanCreateTableSelect + { + $$ = nil + } +| '(' PartitionDefinitionList ')' + { + $$ = $2.([]*ast.PartitionDefinition) + } + +PartitionDefinitionList: + PartitionDefinition + { + $$ = []*ast.PartitionDefinition{$1.(*ast.PartitionDefinition)} + } +| PartitionDefinitionList ',' PartitionDefinition + { + $$ = append($1.([]*ast.PartitionDefinition), $3.(*ast.PartitionDefinition)) + } + +PartitionDefinition: + "PARTITION" Identifier PartDefValuesOpt PartDefOptionsOpt + { + partDef := &ast.PartitionDefinition{ + Name: model.NewCIStr($2), + } + switch $3.(type) { + case []ast.ExprNode: + partDef.LessThan = $3.([]ast.ExprNode) + case ast.ExprNode: + partDef.LessThan = make([]ast.ExprNode, 1) + partDef.LessThan[0] = $3.(ast.ExprNode) + } + + if comment, ok := $4.(string); ok { + partDef.Comment = comment + } + $$ = partDef + } + +PartDefOptionsOpt: + { + $$ = nil + } +| PartDefOptionList + { + $$ = $1 + } + +PartDefOptionList: + PartDefOption + { + $$ = $1 + } +| PartDefOptionList PartDefOption + { + if $1 != nil { + $$ = $1 + } else { + $$ = $2 + } + } + +PartDefOption: + "COMMENT" EqOpt stringLit + { + $$ = $3 + } +| "ENGINE" EqOpt Identifier + { + $$ = nil + } +| "TABLESPACE" EqOpt Identifier + { + $$ = nil + } + + +PartDefValuesOpt: + { + $$ = nil + } +| "VALUES" "LESS" "THAN" "MAXVALUE" + { + $$ = &ast.MaxValueExpr{} + } +| "VALUES" "LESS" "THAN" '(' MaxValueOrExpressionList ')' + { + $$ = $5 + } + +DuplicateOpt: + { + $$ = ast.OnDuplicateCreateTableSelectError + } +| "IGNORE" + { + $$ = ast.OnDuplicateCreateTableSelectIgnore + } +| "REPLACE" + { + $$ = ast.OnDuplicateCreateTableSelectReplace + } + +AsOpt: + {} +| "AS" + {} + +CreateTableSelectOpt: + /* empty */ + { + $$ = &ast.CreateTableStmt{} + } +| + SelectStmt + { + $$ = &ast.CreateTableStmt{Select: $1} + } +| + UnionStmt + { + $$ = &ast.CreateTableStmt{Select: $1} + } +| + SubSelect %prec createTableSelect + // TODO: We may need better solution as issue #320. + { + $$ = &ast.CreateTableStmt{Select: $1} + } + +LikeTableWithOrWithoutParen: + "LIKE" TableName + { + $$ = $2 + } +| + '(' "LIKE" TableName ')' + { + $$ = $3 + } + +/******************************************************************* + * + * Create View Statement + * + * Example: + * CREATE VIEW OR REPLACE ALGORITHM = MERGE DEFINER="root@localhost" SQL SECURITY = definer view_name (col1,col2) + * as select Col1,Col2 from table WITH LOCAL CHECK OPTION + *******************************************************************/ +CreateViewStmt: + "CREATE" OrReplace ViewAlgorithm ViewDefiner ViewSQLSecurity "VIEW" ViewName ViewFieldList "AS" SelectStmt ViewCheckOption + { + startOffset := parser.startOffset(&yyS[yypt-1]) + selStmt := $10.(*ast.SelectStmt) + selStmt.SetText(string(parser.src[startOffset:])) + x := &ast.CreateViewStmt { + OrReplace: $2.(bool), + ViewName: $7.(*ast.TableName), + Select: selStmt, + } + if $8 != nil{ + x.Cols = $8.([]model.CIStr) + } + $$ = x + } + +OrReplace: + { + $$ = false + } +| "OR" "REPLACE" + { + $$ = true + } + +ViewAlgorithm: + /* EMPTY */ + { + $$ = "UNDEFINED" + } +| "ALGORITHM" "=" "UNDEFINED" + { + $$ = strings.ToUpper($3) + } +| "ALGORITHM" "=" "MERGE" + { + $$ = strings.ToUpper($3) + } +| "ALGORITHM" "=" "TEMPTABLE" + { + $$ = strings.ToUpper($3) + } + +ViewDefiner: + /* EMPTY */ + { + $$ = nil + } +| "DEFINER" "=" Username + { + $$ = $3 + } + +ViewSQLSecurity: + /* EMPTY */ + { + $$ = "DEFINER" + } +| "SQL" "SECURITY" "DEFINER" + { + $$ = $3 + } +| "SQL" "SECURITY" "INVOKER" + { + $$ = $3 + } + +ViewName: + TableName + { + $$ = $1.(*ast.TableName) + } + +ViewFieldList: + /* Empty */ + { + $$ = nil + } +| '(' ColumnList ')' + { + $$ = $2.([]model.CIStr) + } + +ColumnList: + Identifier + { + $$ = []model.CIStr{model.NewCIStr($1)} + } +| ColumnList ',' Identifier + { + $$ = append($1.([]model.CIStr), model.NewCIStr($3)) + } + +ViewCheckOption: + /* EMPTY */ + { + $$ = nil + } +| "WITH" "CASCADED" "CHECK" "OPTION" + { + $$ = $2 + } +| "WITH" "LOCAL" "CHECK" "OPTION" + { + $$ = $2 + } + +/****************************************************************** + * Do statement + * See https://dev.mysql.com/doc/refman/5.7/en/do.html + ******************************************************************/ +DoStmt: + "DO" ExpressionList + { + $$ = &ast.DoStmt { + Exprs: $2.([]ast.ExprNode), + } + } + +/******************************************************************* + * + * Delete Statement + * + *******************************************************************/ +DeleteFromStmt: + "DELETE" TableOptimizerHints PriorityOpt QuickOptional IgnoreOptional "FROM" TableName IndexHintListOpt WhereClauseOptional OrderByOptional LimitClause + { + // Single Table + tn := $7.(*ast.TableName) + tn.IndexHints = $8.([]*ast.IndexHint) + join := &ast.Join{Left: &ast.TableSource{Source: tn}, Right: nil} + x := &ast.DeleteStmt{ + TableRefs: &ast.TableRefsClause{TableRefs: join}, + Priority: $3.(mysql.PriorityEnum), + Quick: $4.(bool), + IgnoreErr: $5.(bool), + } + if $9 != nil { + x.Where = $9.(ast.ExprNode) + } + if $10 != nil { + x.Order = $10.(*ast.OrderByClause) + } + if $11 != nil { + x.Limit = $11.(*ast.Limit) + } + + $$ = x + } +| "DELETE" TableOptimizerHints PriorityOpt QuickOptional IgnoreOptional TableNameList "FROM" TableRefs WhereClauseOptional + { + // Multiple Table + x := &ast.DeleteStmt{ + Priority: $3.(mysql.PriorityEnum), + Quick: $4.(bool), + IgnoreErr: $5.(bool), + IsMultiTable: true, + BeforeFrom: true, + Tables: &ast.DeleteTableList{Tables: $6.([]*ast.TableName)}, + TableRefs: &ast.TableRefsClause{TableRefs: $8.(*ast.Join)}, + } + if $2 != nil { + x.TableHints = $2.([]*ast.TableOptimizerHint) + } + if $9 != nil { + x.Where = $9.(ast.ExprNode) + } + $$ = x + } + +| "DELETE" TableOptimizerHints PriorityOpt QuickOptional IgnoreOptional "FROM" TableNameList "USING" TableRefs WhereClauseOptional + { + // Multiple Table + x := &ast.DeleteStmt{ + Priority: $3.(mysql.PriorityEnum), + Quick: $4.(bool), + IgnoreErr: $5.(bool), + IsMultiTable: true, + Tables: &ast.DeleteTableList{Tables: $7.([]*ast.TableName)}, + TableRefs: &ast.TableRefsClause{TableRefs: $9.(*ast.Join)}, + } + if $2 != nil { + x.TableHints = $2.([]*ast.TableOptimizerHint) + } + if $10 != nil { + x.Where = $10.(ast.ExprNode) + } + $$ = x + } + +DatabaseSym: +"DATABASE" + +DropDatabaseStmt: + "DROP" DatabaseSym IfExists DBName + { + $$ = &ast.DropDatabaseStmt{IfExists: $3.(bool), Name: $4.(string)} + } + +DropIndexStmt: + "DROP" "INDEX" IfExists Identifier "ON" TableName + { + $$ = &ast.DropIndexStmt{IfExists: $3.(bool), IndexName: $4, Table: $6.(*ast.TableName)} + } + +DropTableStmt: + "DROP" TableOrTables TableNameList RestrictOrCascadeOpt + { + $$ = &ast.DropTableStmt{Tables: $3.([]*ast.TableName)} + } +| "DROP" TableOrTables "IF" "EXISTS" TableNameList RestrictOrCascadeOpt + { + $$ = &ast.DropTableStmt{IfExists: true, Tables: $5.([]*ast.TableName)} + } + +DropViewStmt: + "DROP" "VIEW" "IF" "EXISTS" TableNameList + { + $$ = &ast.DoStmt{} + } + +DropUserStmt: + "DROP" "USER" UsernameList + { + $$ = &ast.DropUserStmt{IfExists: false, UserList: $3.([]*auth.UserIdentity)} + } +| "DROP" "USER" "IF" "EXISTS" UsernameList + { + $$ = &ast.DropUserStmt{IfExists: true, UserList: $5.([]*auth.UserIdentity)} + } + +DropStatsStmt: + "DROP" "STATS" TableName + { + $$ = &ast.DropStatsStmt{Table: $3.(*ast.TableName)} + } + +RestrictOrCascadeOpt: + {} +| "RESTRICT" +| "CASCADE" + +TableOrTables: + "TABLE" +| "TABLES" + +EqOpt: + {} +| eq + +EmptyStmt: + /* EMPTY */ + { + $$ = nil + } + +TraceStmt: + "TRACE" TraceableStmt + { + $$ = &ast.TraceStmt{ + Stmt: $2, + Format: "json", + } + startOffset := parser.startOffset(&yyS[yypt]) + $2.SetText(string(parser.src[startOffset:])) + } +| "TRACE" "FORMAT" "=" stringLit TraceableStmt + { + $$ = &ast.TraceStmt{ + Stmt: $5, + Format: $4, + } + startOffset := parser.startOffset(&yyS[yypt]) + $5.SetText(string(parser.src[startOffset:])) + } + +ExplainSym: +"EXPLAIN" | "DESCRIBE" | "DESC" + +ExplainStmt: + ExplainSym TableName + { + $$ = &ast.ExplainStmt{ + Stmt: &ast.ShowStmt{ + Tp: ast.ShowColumns, + Table: $2.(*ast.TableName), + }, + } + } +| ExplainSym TableName ColumnName + { + $$ = &ast.ExplainStmt{ + Stmt: &ast.ShowStmt{ + Tp: ast.ShowColumns, + Table: $2.(*ast.TableName), + Column: $3.(*ast.ColumnName), + }, + } + } +| ExplainSym ExplainableStmt + { + $$ = &ast.ExplainStmt{ + Stmt: $2, + Format: "row", + } + } +| ExplainSym "FORMAT" "=" stringLit ExplainableStmt + { + $$ = &ast.ExplainStmt{ + Stmt: $5, + Format: $4, + } + } +| ExplainSym "ANALYZE" ExplainableStmt + { + $$ = &ast.ExplainStmt { + Stmt: $3, + Format: "row", + Analyze: true, + } + } + +LengthNum: + NUM + { + $$ = getUint64FromNUM($1) + } + +NUM: + intLit + +Expression: + singleAtIdentifier assignmentEq Expression %prec assignmentEq + { + v := $1 + v = strings.TrimPrefix(v, "@") + $$ = &ast.VariableExpr{ + Name: v, + IsGlobal: false, + IsSystem: false, + Value: $3, + } + } +| Expression logOr Expression %prec pipes + { + $$ = &ast.BinaryOperationExpr{Op: opcode.LogicOr, L: $1, R: $3} + } +| Expression "XOR" Expression %prec xor + { + $$ = &ast.BinaryOperationExpr{Op: opcode.LogicXor, L: $1, R: $3} + } +| Expression logAnd Expression %prec andand + { + $$ = &ast.BinaryOperationExpr{Op: opcode.LogicAnd, L: $1, R: $3} + } +| "NOT" Expression %prec not + { + expr, ok := $2.(*ast.ExistsSubqueryExpr) + if ok { + expr.Not = true + $$ = $2 + } else { + $$ = &ast.UnaryOperationExpr{Op: opcode.Not, V: $2} + } + } +| BoolPri IsOrNotOp trueKwd %prec is + { + $$ = &ast.IsTruthExpr{Expr:$1, Not: !$2.(bool), True: int64(1)} + } +| BoolPri IsOrNotOp falseKwd %prec is + { + $$ = &ast.IsTruthExpr{Expr:$1, Not: !$2.(bool), True: int64(0)} + } +| BoolPri IsOrNotOp "UNKNOWN" %prec is + { + /* https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_is */ + $$ = &ast.IsNullExpr{Expr: $1, Not: !$2.(bool)} + } +| BoolPri + +MaxValueOrExpression: + "MAXVALUE" + { + $$ = &ast.MaxValueExpr{} + } +| Expression + { + $$ = $1 + } + + +logOr: + pipesAsOr +| "OR" + +logAnd: +"&&" | "AND" + +ExpressionList: + Expression + { + $$ = []ast.ExprNode{$1} + } +| ExpressionList ',' Expression + { + $$ = append($1.([]ast.ExprNode), $3) + } + +MaxValueOrExpressionList: + MaxValueOrExpression + { + $$ = []ast.ExprNode{$1} +} +| MaxValueOrExpressionList ',' MaxValueOrExpression +{ + $$ = append($1.([]ast.ExprNode), $3) + } + + +ExpressionListOpt: + { + $$ = []ast.ExprNode{} + } +| ExpressionList + +FuncDatetimePrecListOpt: + { + $$ = []ast.ExprNode{} + } +| FuncDatetimePrecList + { + $$ = $1 + } + +FuncDatetimePrecList: + intLit + { + expr := ast.NewValueExpr($1) + $$ = []ast.ExprNode{expr} + } + +BoolPri: + BoolPri IsOrNotOp "NULL" %prec is + { + $$ = &ast.IsNullExpr{Expr: $1, Not: !$2.(bool)} + } +| BoolPri CompareOp PredicateExpr %prec eq + { + $$ = &ast.BinaryOperationExpr{Op: $2.(opcode.Op), L: $1, R: $3} + } +| BoolPri CompareOp AnyOrAll SubSelect %prec eq + { + sq := $4.(*ast.SubqueryExpr) + sq.MultiRows = true + $$ = &ast.CompareSubqueryExpr{Op: $2.(opcode.Op), L: $1, R: sq, All: $3.(bool)} + } +| BoolPri CompareOp singleAtIdentifier assignmentEq PredicateExpr %prec assignmentEq + { + v := $3 + v = strings.TrimPrefix(v, "@") + variable := &ast.VariableExpr{ + Name: v, + IsGlobal: false, + IsSystem: false, + Value: $5, + } + $$ = &ast.BinaryOperationExpr{Op: $2.(opcode.Op), L: $1, R: variable} + } +| PredicateExpr + +CompareOp: + ">=" + { + $$ = opcode.GE + } +| '>' + { + $$ = opcode.GT + } +| "<=" + { + $$ = opcode.LE + } +| '<' + { + $$ = opcode.LT + } +| "!=" + { + $$ = opcode.NE + } +| "<>" + { + $$ = opcode.NE + } +| "=" + { + $$ = opcode.EQ + } +| "<=>" + { + $$ = opcode.NullEQ + } + +BetweenOrNotOp: + "BETWEEN" + { + $$ = true + } +| "NOT" "BETWEEN" + { + $$ = false + } + +IsOrNotOp: + "IS" + { + $$ = true + } +| "IS" "NOT" + { + $$ = false + } + +InOrNotOp: + "IN" + { + $$ = true + } +| "NOT" "IN" + { + $$ = false + } + +LikeOrNotOp: + "LIKE" + { + $$ = true + } +| "NOT" "LIKE" + { + $$ = false + } + +RegexpOrNotOp: + RegexpSym + { + $$ = true + } +| "NOT" RegexpSym + { + $$ = false + } + +AnyOrAll: + "ANY" + { + $$ = false + } +| "SOME" + { + $$ = false + } +| "ALL" + { + $$ = true + } + +PredicateExpr: + BitExpr InOrNotOp '(' ExpressionList ')' + { + $$ = &ast.PatternInExpr{Expr: $1, Not: !$2.(bool), List: $4.([]ast.ExprNode)} + } +| BitExpr InOrNotOp SubSelect + { + sq := $3.(*ast.SubqueryExpr) + sq.MultiRows = true + $$ = &ast.PatternInExpr{Expr: $1, Not: !$2.(bool), Sel: sq} + } +| BitExpr BetweenOrNotOp BitExpr "AND" PredicateExpr + { + $$ = &ast.BetweenExpr{ + Expr: $1, + Left: $3, + Right: $5, + Not: !$2.(bool), + } + } +| BitExpr LikeOrNotOp SimpleExpr LikeEscapeOpt + { + escape := $4.(string) + if len(escape) > 1 { + yylex.Errorf("Incorrect arguments %s to ESCAPE", escape) + return 1 + } else if len(escape) == 0 { + escape = "\\" + } + $$ = &ast.PatternLikeExpr{ + Expr: $1, + Pattern: $3, + Not: !$2.(bool), + Escape: escape[0], + } + } +| BitExpr RegexpOrNotOp SimpleExpr + { + $$ = &ast.PatternRegexpExpr{Expr: $1, Pattern: $3, Not: !$2.(bool)} + } +| BitExpr + +RegexpSym: +"REGEXP" | "RLIKE" + +LikeEscapeOpt: + %prec empty + { + $$ = "\\" + } +| "ESCAPE" stringLit + { + $$ = $2 + } + +Field: + '*' + { + $$ = &ast.SelectField{WildCard: &ast.WildCardField{}} + } +| Identifier '.' '*' + { + wildCard := &ast.WildCardField{Table: model.NewCIStr($1)} + $$ = &ast.SelectField{WildCard: wildCard} + } +| Identifier '.' Identifier '.' '*' + { + wildCard := &ast.WildCardField{Schema: model.NewCIStr($1), Table: model.NewCIStr($3)} + $$ = &ast.SelectField{WildCard: wildCard} + } +| Expression FieldAsNameOpt + { + expr := $1 + asName := $2.(string) + $$ = &ast.SelectField{Expr: expr, AsName: model.NewCIStr(asName)} + } +| '{' Identifier Expression '}' FieldAsNameOpt + { + /* + * ODBC escape syntax. + * See https://dev.mysql.com/doc/refman/5.7/en/expressions.html + */ + expr := $3 + asName := $5.(string) + $$ = &ast.SelectField{Expr: expr, AsName: model.NewCIStr(asName)} + } + +FieldAsNameOpt: + /* EMPTY */ + { + $$ = "" + } +| FieldAsName + { + $$ = $1 + } + +FieldAsName: + Identifier + { + $$ = $1 + } +| "AS" Identifier + { + $$ = $2 + } +| stringLit + { + $$ = $1 + } +| "AS" stringLit + { + $$ = $2 + } + +FieldList: + Field + { + field := $1.(*ast.SelectField) + field.Offset = parser.startOffset(&yyS[yypt]) + $$ = []*ast.SelectField{field} + } +| FieldList ',' Field + { + + fl := $1.([]*ast.SelectField) + last := fl[len(fl)-1] + if last.Expr != nil && last.AsName.O == "" { + lastEnd := parser.endOffset(&yyS[yypt-1]) + last.SetText(parser.src[last.Offset:lastEnd]) + } + newField := $3.(*ast.SelectField) + newField.Offset = parser.startOffset(&yyS[yypt]) + $$ = append(fl, newField) + } + +GroupByClause: + "GROUP" "BY" ByList + { + $$ = &ast.GroupByClause{Items: $3.([]*ast.ByItem)} + } + +HavingClause: + { + $$ = nil + } +| "HAVING" Expression + { + $$ = &ast.HavingClause{Expr: $2} + } + +IfExists: + { + $$ = false + } +| "IF" "EXISTS" + { + $$ = true + } + +IfNotExists: + { + $$ = false + } +| "IF" "NOT" "EXISTS" + { + $$ = true + } + + +IgnoreOptional: + { + $$ = false + } +| "IGNORE" + { + $$ = true + } + +IndexName: + { + $$ = "" + } +| Identifier + { + //"index name" + $$ = $1 + } + +IndexOptionList: + { + $$ = nil + } +| IndexOptionList IndexOption + { + // Merge the options + if $1 == nil { + $$ = $2 + } else { + opt1 := $1.(*ast.IndexOption) + opt2 := $2.(*ast.IndexOption) + if len(opt2.Comment) > 0 { + opt1.Comment = opt2.Comment + } else if opt2.Tp != 0 { + opt1.Tp = opt2.Tp + } + $$ = opt1 + } + } + + +IndexOption: + "KEY_BLOCK_SIZE" EqOpt LengthNum + { + $$ = &ast.IndexOption{ + // TODO bug should be fix here! + // KeyBlockSize: $1.(uint64), + } + } +| IndexType + { + $$ = &ast.IndexOption { + Tp: $1.(model.IndexType), + } + } +| "COMMENT" stringLit + { + $$ = &ast.IndexOption { + Comment: $2, + } + } + +IndexType: + "USING" "BTREE" + { + $$ = model.IndexTypeBtree + } +| "USING" "HASH" + { + $$ = model.IndexTypeHash + } + +IndexTypeOpt: + { + $$ = nil + } +| IndexType + { + $$ = $1 + } + +/**********************************Identifier********************************************/ +Identifier: +identifier | UnReservedKeyword | NotKeywordToken | TiDBKeyword + +UnReservedKeyword: + "ACTION" | "ASCII" | "AUTO_INCREMENT" | "AFTER" | "ALWAYS" | "AVG" | "BEGIN" | "BIT" | "BOOL" | "BOOLEAN" | "BTREE" | "BYTE" | "CLEANUP" | "CHARSET" +| "COLUMNS" | "COMMIT" | "COMPACT" | "COMPRESSED" | "CONSISTENT" | "CURRENT" | "DATA" | "DATE" %prec lowerThanStringLitToken| "DATETIME" | "DAY" | "DEALLOCATE" | "DO" | "DUPLICATE" +| "DYNAMIC"| "END" | "ENGINE" | "ENGINES" | "ENUM" | "ERRORS" | "ESCAPE" | "EXECUTE" | "FIELDS" | "FIRST" | "FIXED" | "FLUSH" | "FOLLOWING" | "FORMAT" | "FULL" |"GLOBAL" +| "HASH" | "HOUR" | "LESS" | "LOCAL" | "LAST" | "NAMES" | "OFFSET" | "PASSWORD" %prec lowerThanEq | "PREPARE" | "QUICK" | "REDUNDANT" +| "ROLLBACK" | "SESSION" | "SIGNED" | "SNAPSHOT" | "START" | "STATUS" | "SUBPARTITIONS" | "SUBPARTITION" | "TABLES" | "TABLESPACE" | "TEXT" | "THAN" | "TIME" %prec lowerThanStringLitToken +| "TIMESTAMP" %prec lowerThanStringLitToken | "TRACE" | "TRANSACTION" | "TRUNCATE" | "UNBOUNDED" | "UNKNOWN" | "VALUE" | "WARNINGS" | "YEAR" | "MODE" | "WEEK" | "ANY" | "SOME" | "USER" | "IDENTIFIED" +| "COLLATION" | "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MASTER" | "MAX_ROWS" +| "MIN_ROWS" | "NATIONAL" | "ROW_FORMAT" | "QUARTER" | "GRANTS" | "TRIGGERS" | "DELAY_KEY_WRITE" | "ISOLATION" | "JSON" +| "REPEATABLE" | "RESPECT" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES" | "SQL_CACHE" | "INDEXES" | "PROCESSLIST" +| "SQL_NO_CACHE" | "DISABLE" | "ENABLE" | "REVERSE" | "PRIVILEGES" | "NO" | "BINLOG" | "FUNCTION" | "VIEW" | "MODIFY" | "EVENTS" | "PARTITIONS" +| "NONE" | "NULLS" | "SUPER" | "EXCLUSIVE" | "STATS_PERSISTENT" | "ROW_COUNT" | "COALESCE" | "MONTH" | "PROCESS" | "PROFILES" +| "MICROSECOND" | "MINUTE" | "PLUGINS" | "PRECEDING" | "QUERY" | "QUERIES" | "SECOND" | "SEPARATOR" | "SHARE" | "SHARED" | "SLOW" | "MAX_CONNECTIONS_PER_HOUR" | "MAX_QUERIES_PER_HOUR" | "MAX_UPDATES_PER_HOUR" +| "MAX_USER_CONNECTIONS" | "REPLICATION" | "CLIENT" | "SLAVE" | "RELOAD" | "TEMPORARY" | "ROUTINE" | "EVENT" | "ALGORITHM" | "DEFINER" | "INVOKER" | "MERGE" | "TEMPTABLE" | "UNDEFINED" | "SECURITY" | "CASCADED" | "RECOVER" + + + +TiDBKeyword: +"ADMIN" | "BUCKETS" | "CANCEL" | "DDL" | "JOBS" | "JOB" | "STATS" | "STATS_META" | "STATS_HISTOGRAMS" | "STATS_BUCKETS" | "STATS_HEALTHY" | "TIDB" | "TIDB_HJ" | "TIDB_SMJ" | "TIDB_INLJ" + +NotKeywordToken: + "ADDDATE" | "BIT_AND" | "BIT_OR" | "BIT_XOR" | "CAST" | "COPY" | "COUNT" | "CURTIME" | "DATE_ADD" | "DATE_SUB" | "EXTRACT" | "GET_FORMAT" | "GROUP_CONCAT" +| "INPLACE" | "INTERNAL" |"MIN" | "MAX" | "MAX_EXECUTION_TIME" | "NOW" | "RECENT" | "POSITION" | "SUBDATE" | "SUBSTRING" | "SUM" | "STD" | "STDDEV" | "STDDEV_POP" | "STDDEV_SAMP" +| "TIMESTAMPADD" | "TIMESTAMPDIFF" | "TOP" | "TRIM" | "NEXT_ROW_ID" + +/************************************************************************************ + * + * Insert Statements + * + * TODO: support PARTITION + **********************************************************************************/ +InsertIntoStmt: + "INSERT" PriorityOpt IgnoreOptional IntoOpt TableName InsertValues OnDuplicateKeyUpdate + { + x := $6.(*ast.InsertStmt) + x.Priority = $2.(mysql.PriorityEnum) + x.IgnoreErr = $3.(bool) + // Wraps many layers here so that it can be processed the same way as select statement. + ts := &ast.TableSource{Source: $5.(*ast.TableName)} + x.Table = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}} + if $7 != nil { + x.OnDuplicate = $7.([]*ast.Assignment) + } + $$ = x + } + +IntoOpt: + {} +| "INTO" + +InsertValues: + '(' ColumnNameListOpt ')' ValueSym ValuesList + { + $$ = &ast.InsertStmt{ + Columns: $2.([]*ast.ColumnName), + Lists: $5.([][]ast.ExprNode), + } + } +| '(' ColumnNameListOpt ')' SelectStmt + { + $$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: $4.(*ast.SelectStmt)} + } +| '(' ColumnNameListOpt ')' '(' SelectStmt ')' + { + $$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: $5.(*ast.SelectStmt)} + } +| '(' ColumnNameListOpt ')' UnionStmt + { + $$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: $4.(*ast.UnionStmt)} + } +| ValueSym ValuesList %prec insertValues + { + $$ = &ast.InsertStmt{Lists: $2.([][]ast.ExprNode)} + } +| '(' SelectStmt ')' + { + $$ = &ast.InsertStmt{Select: $2.(*ast.SelectStmt)} + } +| SelectStmt + { + $$ = &ast.InsertStmt{Select: $1.(*ast.SelectStmt)} + } +| UnionStmt + { + $$ = &ast.InsertStmt{Select: $1.(*ast.UnionStmt)} + } +| "SET" ColumnSetValueList + { + $$ = &ast.InsertStmt{Setlist: $2.([]*ast.Assignment)} + } + +ValueSym: +"VALUE" | "VALUES" + +ValuesList: + RowValue + { + $$ = [][]ast.ExprNode{$1.([]ast.ExprNode)} + } +| ValuesList ',' RowValue + { + $$ = append($1.([][]ast.ExprNode), $3.([]ast.ExprNode)) + } + +RowValue: + '(' ValuesOpt ')' + { + $$ = $2 + } + +ValuesOpt: + { + $$ = []ast.ExprNode{} + } +| Values + +Values: + Values ',' ExprOrDefault + { + $$ = append($1.([]ast.ExprNode), $3) + } +| ExprOrDefault + { + $$ = []ast.ExprNode{$1} + } + +ExprOrDefault: + Expression +| "DEFAULT" + { + $$ = &ast.DefaultExpr{} + } + +ColumnSetValue: + ColumnName eq Expression + { + $$ = &ast.Assignment{ + Column: $1.(*ast.ColumnName), + Expr: $3, + } + } + +ColumnSetValueList: + { + $$ = []*ast.Assignment{} + } +| ColumnSetValue + { + $$ = []*ast.Assignment{$1.(*ast.Assignment)} + } +| ColumnSetValueList ',' ColumnSetValue + { + $$ = append($1.([]*ast.Assignment), $3.(*ast.Assignment)) + } + +/* + * ON DUPLICATE KEY UPDATE col_name=expr [, col_name=expr] ... + * See https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html + */ +OnDuplicateKeyUpdate: + { + $$ = nil + } +| "ON" "DUPLICATE" "KEY" "UPDATE" AssignmentList + { + $$ = $5 + } + +/***********************************Insert Statements END************************************/ + +/************************************************************************************ + * Replace Statements + * See https://dev.mysql.com/doc/refman/5.7/en/replace.html + * + * TODO: support PARTITION + **********************************************************************************/ +ReplaceIntoStmt: + "REPLACE" PriorityOpt IntoOpt TableName InsertValues + { + x := $5.(*ast.InsertStmt) + x.IsReplace = true + x.Priority = $2.(mysql.PriorityEnum) + ts := &ast.TableSource{Source: $4.(*ast.TableName)} + x.Table = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}} + $$ = x + } + +/***********************************Replace Statements END************************************/ + +ODBCDateTimeType: + "d" + { + $$ = ast.DateLiteral + } +| "t" + { + $$ = ast.TimeLiteral + } +| "ts" + { + $$ = ast.TimestampLiteral + } + +Literal: + "FALSE" + { + $$ = ast.NewValueExpr(false) + } +| "NULL" + { + $$ = ast.NewValueExpr(nil) + } +| "TRUE" + { + $$ = ast.NewValueExpr(true) + } +| floatLit + { + $$ = ast.NewValueExpr($1) + } +| decLit + { + $$ = ast.NewValueExpr($1) + } +| intLit + { + $$ = ast.NewValueExpr($1) + } +| StringLiteral %prec lowerThanStringLitToken + { + $$ = $1 + } +| "UNDERSCORE_CHARSET" stringLit + { + // See https://dev.mysql.com/doc/refman/5.7/en/charset-literal.html + co, err := charset.GetDefaultCollation($1) + if err != nil { + yylex.Errorf("Get collation error for charset: %s", $1) + return 1 + } + expr := ast.NewValueExpr($2) + tp := expr.GetType() + tp.Charset = $1 + tp.Collate = co + if tp.Collate == charset.CollationBin { + tp.Flag |= mysql.BinaryFlag + } + $$ = expr + } +| hexLit + { + $$ = ast.NewValueExpr($1) + } +| bitLit + { + $$ = ast.NewValueExpr($1) + } + +StringLiteral: + stringLit + { + expr := ast.NewValueExpr($1) + $$ = expr + } +| StringLiteral stringLit + { + valExpr := $1.(ast.ValueExpr) + strLit := valExpr.GetString() + expr := ast.NewValueExpr(strLit+$2) + // Fix #4239, use first string literal as projection name. + if valExpr.GetProjectionOffset() >= 0 { + expr.SetProjectionOffset(valExpr.GetProjectionOffset()) + } else { + expr.SetProjectionOffset(len(strLit)) + } + $$ = expr + } + + +OrderBy: + "ORDER" "BY" ByList + { + $$ = &ast.OrderByClause{Items: $3.([]*ast.ByItem)} + } + +ByList: + ByItem + { + $$ = []*ast.ByItem{$1.(*ast.ByItem)} + } +| ByList ',' ByItem + { + $$ = append($1.([]*ast.ByItem), $3.(*ast.ByItem)) + } + +ByItem: + Expression Order + { + expr := $1 + valueExpr, ok := expr.(ast.ValueExpr) + if ok { + position, isPosition := valueExpr.GetValue().(int64) + if isPosition { + expr = &ast.PositionExpr{N: int(position)} + } + } + $$ = &ast.ByItem{Expr: expr, Desc: $2.(bool)} + } + +Order: + /* EMPTY */ + { + $$ = false // ASC by default + } +| "ASC" + { + $$ = false + } +| "DESC" + { + $$ = true + } + +OrderByOptional: + { + $$ = nil + } +| OrderBy + { + $$ = $1 + } + +BitExpr: + BitExpr '|' BitExpr %prec '|' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Or, L: $1, R: $3} + } +| BitExpr '&' BitExpr %prec '&' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.And, L: $1, R: $3} + } +| BitExpr "<<" BitExpr %prec lsh + { + $$ = &ast.BinaryOperationExpr{Op: opcode.LeftShift, L: $1, R: $3} + } +| BitExpr ">>" BitExpr %prec rsh + { + $$ = &ast.BinaryOperationExpr{Op: opcode.RightShift, L: $1, R: $3} + } +| BitExpr '+' BitExpr %prec '+' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Plus, L: $1, R: $3} + } +| BitExpr '-' BitExpr %prec '-' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Minus, L: $1, R: $3} + } +| BitExpr '+' "INTERVAL" Expression TimeUnit %prec '+' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr("DATE_ADD"), + Args: []ast.ExprNode{ + $1, + $4, + ast.NewValueExpr($5), + }, + } + } +| BitExpr '-' "INTERVAL" Expression TimeUnit %prec '+' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr("DATE_SUB"), + Args: []ast.ExprNode{ + $1, + $4, + ast.NewValueExpr($5), + }, + } + } +| BitExpr '*' BitExpr %prec '*' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Mul, L: $1, R: $3} + } +| BitExpr '/' BitExpr %prec '/' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Div, L: $1, R: $3} + } +| BitExpr '%' BitExpr %prec '%' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Mod, L: $1, R: $3} + } +| BitExpr "DIV" BitExpr %prec div + { + $$ = &ast.BinaryOperationExpr{Op: opcode.IntDiv, L: $1, R: $3} + } +| BitExpr "MOD" BitExpr %prec mod + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Mod, L: $1, R: $3} + } +| BitExpr '^' BitExpr + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Xor, L: $1, R: $3} + } +| SimpleExpr + +SimpleIdent: + Identifier + { + $$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Name: model.NewCIStr($1), + }} + } +| Identifier '.' Identifier + { + $$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Table: model.NewCIStr($1), + Name: model.NewCIStr($3), + }} + } +| '.' Identifier '.' Identifier + { + $$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Table: model.NewCIStr($2), + Name: model.NewCIStr($4), + }} + } +| Identifier '.' Identifier '.' Identifier + { + $$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{ + Schema: model.NewCIStr($1), + Table: model.NewCIStr($3), + Name: model.NewCIStr($5), + }} + } + +SimpleExpr: + SimpleIdent +| FunctionCallKeyword +| FunctionCallNonKeyword +| FunctionCallGeneric +| SimpleExpr "COLLATE" StringName %prec neg + { + // TODO: Create a builtin function hold expr and collation. When do evaluation, convert expr result using the collation. + $$ = $1 + } +| WindowFuncCall + { + $$ = $1.(*ast.WindowFuncExpr) + } +| Literal +| paramMarker + { + $$ = ast.NewParamMarkerExpr(yyS[yypt].offset) + } +| Variable +| SumExpr +| '!' SimpleExpr %prec neg + { + $$ = &ast.UnaryOperationExpr{Op: opcode.Not, V: $2} + } +| '~' SimpleExpr %prec neg + { + $$ = &ast.UnaryOperationExpr{Op: opcode.BitNeg, V: $2} + } +| '-' SimpleExpr %prec neg + { + $$ = &ast.UnaryOperationExpr{Op: opcode.Minus, V: $2} + } +| '+' SimpleExpr %prec neg + { + $$ = &ast.UnaryOperationExpr{Op: opcode.Plus, V: $2} + } +| SimpleExpr pipes SimpleExpr + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.Concat), Args: []ast.ExprNode{$1, $3}} + } +| not2 SimpleExpr %prec neg + { + $$ = &ast.UnaryOperationExpr{Op: opcode.Not, V: $2} + } +| SubSelect +| '(' Expression ')' { + startOffset := parser.startOffset(&yyS[yypt-1]) + endOffset := parser.endOffset(&yyS[yypt]) + expr := $2 + expr.SetText(parser.src[startOffset:endOffset]) + $$ = &ast.ParenthesesExpr{Expr: expr} + } +| '(' ExpressionList ',' Expression ')' + { + values := append($2.([]ast.ExprNode), $4) + $$ = &ast.RowExpr{Values: values} + } +| "ROW" '(' ExpressionList ',' Expression ')' + { + values := append($3.([]ast.ExprNode), $5) + $$ = &ast.RowExpr{Values: values} + } +| "EXISTS" SubSelect + { + sq := $2.(*ast.SubqueryExpr) + sq.Exists = true + $$ = &ast.ExistsSubqueryExpr{Sel: sq} + } +| "BINARY" SimpleExpr %prec neg + { + // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#operator_binary + x := types.NewFieldType(mysql.TypeString) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + $$ = &ast.FuncCastExpr{ + Expr: $2, + Tp: x, + FunctionType: ast.CastBinaryOperator, + } + } +| builtinCast '(' Expression "AS" CastType ')' + { + /* See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast */ + tp := $5.(*types.FieldType) + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.Tp) + if tp.Flen == types.UnspecifiedLength { + tp.Flen = defaultFlen + } + if tp.Decimal == types.UnspecifiedLength { + tp.Decimal = defaultDecimal + } + $$ = &ast.FuncCastExpr{ + Expr: $3, + Tp: tp, + FunctionType: ast.CastFunction, + } + } +| "CASE" ExpressionOpt WhenClauseList ElseOpt "END" + { + x := &ast.CaseExpr{WhenClauses: $3.([]*ast.WhenClause)} + if $2 != nil { + x.Value = $2 + } + if $4 != nil { + x.ElseClause = $4.(ast.ExprNode) + } + $$ = x + } +| "CONVERT" '(' Expression ',' CastType ')' + { + // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert + tp := $5.(*types.FieldType) + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.Tp) + if tp.Flen == types.UnspecifiedLength { + tp.Flen = defaultFlen + } + if tp.Decimal == types.UnspecifiedLength { + tp.Decimal = defaultDecimal + } + $$ = &ast.FuncCastExpr{ + Expr: $3, + Tp: tp, + FunctionType: ast.CastConvertFunction, + } + } +| "CONVERT" '(' Expression "USING" StringName ')' + { + // See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert + charset1 := ast.NewValueExpr($5) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$3, charset1}, + } + } +| "DEFAULT" '(' SimpleIdent ')' + { + $$ = &ast.DefaultExpr{Name: $3.(*ast.ColumnNameExpr).Name} + } +| "VALUES" '(' SimpleIdent ')' %prec lowerThanInsertValues + { + $$ = &ast.ValuesExpr{Column: $3.(*ast.ColumnNameExpr)} + } +| SimpleIdent jss stringLit + { + expr := ast.NewValueExpr($3) + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{$1, expr}} + } +| SimpleIdent juss stringLit + { + expr := ast.NewValueExpr($3) + extract := &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{$1, expr}} + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONUnquote), Args: []ast.ExprNode{extract}} + } + +DistinctKwd: + "DISTINCT" +| "DISTINCTROW" + +DistinctOpt: + "ALL" + { + $$ = false + } +| DistinctKwd + { + $$ = true + } + +DefaultFalseDistinctOpt: + { + $$ = false + } +| DistinctOpt + +DefaultTrueDistinctOpt: + { + $$ = true + } +| DistinctOpt + +BuggyDefaultFalseDistinctOpt: + DefaultFalseDistinctOpt +| DistinctKwd "ALL" + { + $$ = true + } + + +FunctionNameConflict: + "ASCII" +| "CHARSET" +| "COALESCE" +| "COLLATION" +| "DATE" +| "DATABASE" +| "DAY" +| "HOUR" +| "IF" +| "INTERVAL" %prec lowerThanIntervalKeyword +| "FORMAT" +| "LEFT" +| "MICROSECOND" +| "MINUTE" +| "MONTH" +| builtinNow +| "QUARTER" +| "REPEAT" +| "REPLACE" +| "REVERSE" +| "RIGHT" +| "ROW_COUNT" +| "SECOND" +| "TIME" +| "TIMESTAMP" +| "TRUNCATE" +| "USER" +| "WEEK" +| "YEAR" + +OptionalBraces: + {} | '(' ')' {} + +FunctionNameOptionalBraces: + "CURRENT_USER" +| "CURRENT_DATE" +| "UTC_DATE" + +FunctionNameDatetimePrecision: + "CURRENT_TIME" +| "CURRENT_TIMESTAMP" +| "LOCALTIME" +| "LOCALTIMESTAMP" +| "UTC_TIME" +| "UTC_TIMESTAMP" + +FunctionCallKeyword: + FunctionNameConflict '(' ExpressionListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)} + } +| builtinUser '(' ExpressionListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)} + } +| FunctionNameOptionalBraces OptionalBraces + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1)} + } +| builtinCurDate '(' ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1)} + } +| FunctionNameDatetimePrecision FuncDatetimePrec + { + args := []ast.ExprNode{} + if $2 != nil { + args = append(args, $2.(ast.ExprNode)) + } + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: args} + } +| "CHAR" '(' ExpressionList ')' + { + nilVal := ast.NewValueExpr(nil) + args := $3.([]ast.ExprNode) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr(ast.CharFunc), + Args: append(args, nilVal), + } + } +| "CHAR" '(' ExpressionList "USING" StringName ')' + { + charset1 := ast.NewValueExpr($5) + args := $3.([]ast.ExprNode) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr(ast.CharFunc), + Args: append(args, charset1), + } + } +| "DATE" stringLit + { + expr := ast.NewValueExpr($2) + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{expr}} + } +| "TIME" stringLit + { + expr := ast.NewValueExpr($2) + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{expr}} + } +| "TIMESTAMP" stringLit + { + expr := ast.NewValueExpr($2) + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{expr}} + } +| "INSERT" '(' ExpressionListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName:model.NewCIStr(ast.InsertFunc), Args: $3.([]ast.ExprNode)} + } +| "MOD" '(' BitExpr ',' BitExpr ')' + { + $$ = &ast.BinaryOperationExpr{Op: opcode.Mod, L: $3, R: $5} + } +| "PASSWORD" '(' ExpressionListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName:model.NewCIStr(ast.PasswordFunc), Args: $3.([]ast.ExprNode)} + } +| '{' ODBCDateTimeType stringLit '}' + { + // This is ODBC syntax for date and time literals. + // See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html + expr := ast.NewValueExpr($3) + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($2), Args: []ast.ExprNode{expr}} + } + +FunctionCallNonKeyword: + builtinCurTime '(' FuncDatetimePrecListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)} + } +| builtinSysDate '(' FuncDatetimePrecListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)} + } +| FunctionNameDateArithMultiForms '(' Expression ',' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{ + $3, + $5, + ast.NewValueExpr("DAY"), + }, + } + } +| FunctionNameDateArithMultiForms '(' Expression ',' "INTERVAL" Expression TimeUnit ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{ + $3, + $6, + ast.NewValueExpr($7), + }, + } + } +| FunctionNameDateArith '(' Expression ',' "INTERVAL" Expression TimeUnit ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{ + $3, + $6, + ast.NewValueExpr($7), + }, + } + } +| builtinExtract '(' TimeUnit "FROM" Expression ')' + { + timeUnit := ast.NewValueExpr($3) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{timeUnit, $5}, + } + } +| "GET_FORMAT" '(' GetFormatSelector ',' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{ast.NewValueExpr($3), $5}, + } + } +| builtinPosition '(' BitExpr "IN" Expression ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: []ast.ExprNode{$3, $5}} + } +| builtinSubstring '(' Expression ',' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$3, $5}, + } + } +| builtinSubstring '(' Expression "FROM" Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$3, $5}, + } + } +| builtinSubstring '(' Expression ',' Expression ',' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$3, $5, $7}, + } + } +| builtinSubstring '(' Expression "FROM" Expression "FOR" Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$3, $5, $7}, + } + } +| "TIMESTAMPADD" '(' TimestampUnit ',' Expression ',' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{ast.NewValueExpr($3), $5, $7}, + } + } +| "TIMESTAMPDIFF" '(' TimestampUnit ',' Expression ',' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{ast.NewValueExpr($3), $5, $7}, + } + } +| builtinTrim '(' Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$3}, + } + } +| builtinTrim '(' Expression "FROM" Expression ')' + { + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$5, $3}, + } + } +| builtinTrim '(' TrimDirection "FROM" Expression ')' + { + nilVal := ast.NewValueExpr(nil) + direction := ast.NewValueExpr(int($3.(ast.TrimDirectionType))) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$5, nilVal, direction}, + } + } +| builtinTrim '(' TrimDirection Expression "FROM" Expression ')' + { + direction := ast.NewValueExpr(int($3.(ast.TrimDirectionType))) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1), + Args: []ast.ExprNode{$6, $4, direction}, + } + } + +GetFormatSelector: + "DATE" + { + $$ = strings.ToUpper($1) + } +| "DATETIME" + { + $$ = strings.ToUpper($1) + } +| "TIME" + { + $$ = strings.ToUpper($1) + } +| "TIMESTAMP" + { + $$ = strings.ToUpper($1) + } + + +FunctionNameDateArith: + builtinDateAdd +| builtinDateSub + + +FunctionNameDateArithMultiForms: + builtinAddDate +| builtinSubDate + + +TrimDirection: + "BOTH" + { + $$ = ast.TrimBoth + } +| "LEADING" + { + $$ = ast.TrimLeading + } +| "TRAILING" + { + $$ = ast.TrimTrailing + } + +SumExpr: + "AVG" '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)} + } + } +| builtinBitAnd '(' Expression ')' OptWindowingClause + { + if $5 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3},} + } + } +| builtinBitAnd '(' "ALL" Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4},} + } + } +| builtinBitOr '(' Expression ')' OptWindowingClause + { + if $5 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3},} + } + } +| builtinBitOr '(' "ALL" Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4},} + } + } +| builtinBitXor '(' Expression ')' OptWindowingClause + { + if $5 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3},} + } + } +| builtinBitXor '(' "ALL" Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4},} + } + } +| builtinCount '(' DistinctKwd ExpressionList ')' + { + $$ = &ast.AggregateFuncExpr{F: $1, Args: $4.([]ast.ExprNode), Distinct: true} + } +| builtinCount '(' "ALL" Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4},} + } + } +| builtinCount '(' Expression ')' OptWindowingClause + { + if $5 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3},} + } + } +| builtinCount '(' '*' ')' OptWindowingClause + { + args := []ast.ExprNode{ast.NewValueExpr(1)} + if $5 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: args, Spec: *($5.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: args,} + } + } +| builtinGroupConcat '(' BuggyDefaultFalseDistinctOpt ExpressionList OrderByOptional OptGConcatSeparator ')' + { + args := $4.([]ast.ExprNode) + args = append(args, $6.(ast.ExprNode)) + $$ = &ast.AggregateFuncExpr{F: $1, Args: args, Distinct: $3.(bool)} + } +| builtinMax '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)} + } + } +| builtinMin '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)} + } + } +| builtinSum '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)} + } + } +| builtinStddevPop '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)} + } + } +| builtinStddevSamp '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause + { + if $6 != nil { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec)),} + } else { + $$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)} + } + } + +OptGConcatSeparator: + { + $$ = ast.NewValueExpr(",") + } +| "SEPARATOR" stringLit + { + $$ = ast.NewValueExpr($2) + } + + +FunctionCallGeneric: + identifier '(' ExpressionListOpt ')' + { + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)} + } + +FuncDatetimePrec: + { + $$ = nil + } +| '(' ')' + { + $$ = nil + } +| '(' intLit ')' + { + expr := ast.NewValueExpr($2) + $$ = expr + } + +TimeUnit: + "MICROSECOND" + { + $$ = strings.ToUpper($1) + } +| "SECOND" + { + $$ = strings.ToUpper($1) + } +| "MINUTE" + { + $$ = strings.ToUpper($1) + } +| "HOUR" + { + $$ = strings.ToUpper($1) + } +| "DAY" + { + $$ = strings.ToUpper($1) + } +| "WEEK" + { + $$ = strings.ToUpper($1) + } +| "MONTH" + { + $$ = strings.ToUpper($1) + } +| "QUARTER" + { + $$ = strings.ToUpper($1) + } +| "YEAR" + { + $$ = strings.ToUpper($1) + } +| "SECOND_MICROSECOND" + { + $$ = strings.ToUpper($1) + } +| "MINUTE_MICROSECOND" + { + $$ = strings.ToUpper($1) + } +| "MINUTE_SECOND" + { + $$ = strings.ToUpper($1) + } +| "HOUR_MICROSECOND" + { + $$ = strings.ToUpper($1) + } +| "HOUR_SECOND" + { + $$ = strings.ToUpper($1) + } +| "HOUR_MINUTE" + { + $$ = strings.ToUpper($1) + } +| "DAY_MICROSECOND" + { + $$ = strings.ToUpper($1) + } +| "DAY_SECOND" + { + $$ = strings.ToUpper($1) + } +| "DAY_MINUTE" + { + $$ = strings.ToUpper($1) + } +| "DAY_HOUR" + { + $$ = strings.ToUpper($1) + } +| "YEAR_MONTH" + { + $$ = strings.ToUpper($1) + } + +TimestampUnit: + "MICROSECOND" + { + $$ = strings.ToUpper($1) + } +| "SECOND" + { + $$ = strings.ToUpper($1) + } +| "MINUTE" + { + $$ = strings.ToUpper($1) + } +| "HOUR" + { + $$ = strings.ToUpper($1) + } +| "DAY" + { + $$ = strings.ToUpper($1) + } +| "WEEK" + { + $$ = strings.ToUpper($1) + } +| "MONTH" + { + $$ = strings.ToUpper($1) + } +| "QUARTER" + { + $$ = strings.ToUpper($1) + } +| "YEAR" + { + $$ = strings.ToUpper($1) + } + +ExpressionOpt: + { + $$ = nil + } +| Expression + { + $$ = $1 + } + +WhenClauseList: + WhenClause + { + $$ = []*ast.WhenClause{$1.(*ast.WhenClause)} + } +| WhenClauseList WhenClause + { + $$ = append($1.([]*ast.WhenClause), $2.(*ast.WhenClause)) + } + +WhenClause: + "WHEN" Expression "THEN" Expression + { + $$ = &ast.WhenClause{ + Expr: $2, + Result: $4, + } + } + +ElseOpt: + /* empty */ + { + $$ = nil + } +| "ELSE" Expression + { + $$ = $2 + } + +CastType: + "BINARY" OptFieldLen + { + x := types.NewFieldType(mysql.TypeVarString) + x.Flen = $2.(int) // TODO: Flen should be the flen of expression + if x.Flen != types.UnspecifiedLength { + x.Tp = mysql.TypeString + } + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "CHAR" OptFieldLen OptBinary + { + x := types.NewFieldType(mysql.TypeVarString) + x.Flen = $2.(int) // TODO: Flen should be the flen of expression + x.Charset = $3.(*ast.OptBinary).Charset + if $3.(*ast.OptBinary).IsBinary{ + x.Flag |= mysql.BinaryFlag + } + if x.Charset == "" { + x.Charset = mysql.DefaultCharset + x.Collate = mysql.DefaultCollationName + } + $$ = x + } +| "DATE" + { + x := types.NewFieldType(mysql.TypeDate) + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "DATETIME" OptFieldLen + { + x := types.NewFieldType(mysql.TypeDatetime) + x.Flen, _ = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDatetime) + x.Decimal = $2.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "DECIMAL" FloatOpt + { + fopt := $2.(*ast.FloatOpt) + x := types.NewFieldType(mysql.TypeNewDecimal) + x.Flen = fopt.Flen + x.Decimal = fopt.Decimal + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "TIME" OptFieldLen + { + x := types.NewFieldType(mysql.TypeDuration) + x.Flen, _ = mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDuration) + x.Decimal = $2.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "SIGNED" OptInteger + { + x := types.NewFieldType(mysql.TypeLonglong) + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "UNSIGNED" OptInteger + { + x := types.NewFieldType(mysql.TypeLonglong) + x.Flag |= mysql.UnsignedFlag | mysql.BinaryFlag + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + $$ = x + } +| "JSON" + { + x := types.NewFieldType(mysql.TypeJSON) + x.Flag |= mysql.BinaryFlag | (mysql.ParseToJSONFlag) + x.Charset = mysql.DefaultCharset + x.Collate = mysql.DefaultCollationName + $$ = x + } + +PriorityOpt: + { + $$ = mysql.NoPriority + } +| "LOW_PRIORITY" + { + $$ = mysql.LowPriority + } +| "HIGH_PRIORITY" + { + $$ = mysql.HighPriority + } +| "DELAYED" + { + $$ = mysql.DelayedPriority + } + +TableName: + Identifier + { + $$ = &ast.TableName{Name:model.NewCIStr($1)} + } +| Identifier '.' Identifier + { + $$ = &ast.TableName{Schema:model.NewCIStr($1), Name:model.NewCIStr($3)} + } + +TableNameList: + TableName + { + tbl := []*ast.TableName{$1.(*ast.TableName)} + $$ = tbl + } +| TableNameList ',' TableName + { + $$ = append($1.([]*ast.TableName), $3.(*ast.TableName)) + } + +QuickOptional: + %prec empty + { + $$ = false + } +| "QUICK" + { + $$ = true + } + +/***************************Prepared Statement Start****************************** + * See https://dev.mysql.com/doc/refman/5.7/en/prepare.html + * Example: + * PREPARE stmt_name FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; + * OR + * SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; + * PREPARE stmt_name FROM @s; + */ + +PreparedStmt: + "PREPARE" Identifier "FROM" PrepareSQL + { + var sqlText string + var sqlVar *ast.VariableExpr + switch $4.(type) { + case string: + sqlText = $4.(string) + case *ast.VariableExpr: + sqlVar = $4.(*ast.VariableExpr) + } + $$ = &ast.PrepareStmt{ + Name: $2, + SQLText: sqlText, + SQLVar: sqlVar, + } + } + +PrepareSQL: + stringLit + { + $$ = $1 + } +| UserVariable + { + $$ = $1.(interface{}) + } + + +/* + * See https://dev.mysql.com/doc/refman/5.7/en/execute.html + * Example: + * EXECUTE stmt1 USING @a, @b; + * OR + * EXECUTE stmt1; + */ +ExecuteStmt: + "EXECUTE" Identifier + { + $$ = &ast.ExecuteStmt{Name: $2} + } +| "EXECUTE" Identifier "USING" UserVariableList + { + $$ = &ast.ExecuteStmt{ + Name: $2, + UsingVars: $4.([]ast.ExprNode), + } + } + +UserVariableList: + UserVariable + { + $$ = []ast.ExprNode{$1} + } +| UserVariableList ',' UserVariable + { + $$ = append($1.([]ast.ExprNode), $3) + } + +/* + * See https://dev.mysql.com/doc/refman/5.0/en/deallocate-prepare.html + */ + +DeallocateStmt: + DeallocateSym "PREPARE" Identifier + { + $$ = &ast.DeallocateStmt{Name: $3} + } + +DeallocateSym: +"DEALLOCATE" | "DROP" + +/****************************Prepared Statement End*******************************/ + + +RollbackStmt: + "ROLLBACK" + { + $$ = &ast.RollbackStmt{} + } + +SelectStmtBasic: + "SELECT" SelectStmtOpts SelectStmtFieldList + { + st := &ast.SelectStmt { + SelectStmtOpts: $2.(*ast.SelectStmtOpts), + Distinct: $2.(*ast.SelectStmtOpts).Distinct, + Fields: $3.(*ast.FieldList), + } + $$ = st + } + +SelectStmtFromDualTable: + SelectStmtBasic FromDual WhereClauseOptional + { + st := $1.(*ast.SelectStmt) + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Expr != nil && lastField.AsName.O == "" { + lastEnd := yyS[yypt-1].offset-1 + lastField.SetText(parser.src[lastField.Offset:lastEnd]) + } + if $3 != nil { + st.Where = $3.(ast.ExprNode) + } + } + +SelectStmtFromTable: + SelectStmtBasic "FROM" + TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause WindowClauseOptional + { + st := $1.(*ast.SelectStmt) + st.From = $3.(*ast.TableRefsClause) + if st.SelectStmtOpts.TableHints != nil { + st.TableHints = st.SelectStmtOpts.TableHints + } + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Expr != nil && lastField.AsName.O == "" { + lastEnd := parser.endOffset(&yyS[yypt-5]) + lastField.SetText(parser.src[lastField.Offset:lastEnd]) + } + if $4 != nil { + st.Where = $4.(ast.ExprNode) + } + if $5 != nil { + st.GroupBy = $5.(*ast.GroupByClause) + } + if $6 != nil { + st.Having = $6.(*ast.HavingClause) + } + if $7 != nil { + st.WindowSpecs = ($7.([]ast.WindowSpec)) + } + $$ = st + } + +SelectStmt: + SelectStmtBasic OrderByOptional SelectStmtLimit SelectLockOpt + { + st := $1.(*ast.SelectStmt) + st.LockTp = $4.(ast.SelectLockType) + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Expr != nil && lastField.AsName.O == "" { + src := parser.src + var lastEnd int + if $2 != nil { + lastEnd = yyS[yypt-2].offset-1 + } else if $3 != nil { + lastEnd = yyS[yypt-1].offset-1 + } else if $4 != ast.SelectLockNone { + lastEnd = yyS[yypt].offset-1 + } else { + lastEnd = len(src) + if src[lastEnd-1] == ';' { + lastEnd-- + } + } + lastField.SetText(src[lastField.Offset:lastEnd]) + } + if $2 != nil { + st.OrderBy = $2.(*ast.OrderByClause) + } + if $3 != nil { + st.Limit = $3.(*ast.Limit) + } + $$ = st + } +| SelectStmtFromDualTable OrderByOptional SelectStmtLimit SelectLockOpt + { + st := $1.(*ast.SelectStmt) + if $2 != nil { + st.OrderBy = $2.(*ast.OrderByClause) + } + if $3 != nil { + st.Limit = $3.(*ast.Limit) + } + st.LockTp = $4.(ast.SelectLockType) + $$ = st + } +| SelectStmtFromTable OrderByOptional SelectStmtLimit SelectLockOpt + { + st := $1.(*ast.SelectStmt) + st.LockTp = $4.(ast.SelectLockType) + if $2 != nil { + st.OrderBy = $2.(*ast.OrderByClause) + } + if $3 != nil { + st.Limit = $3.(*ast.Limit) + } + $$ = st + } + +FromDual: + "FROM" "DUAL" + +WindowClauseOptional: + { + $$ = nil + } +| "WINDOW" WindowDefinitionList + { + $$ = $2.([]ast.WindowSpec) + } + +WindowDefinitionList: + WindowDefinition + { + $$ = []ast.WindowSpec{$1.(ast.WindowSpec)} + } +| WindowDefinitionList ',' WindowDefinition + { + $$ = append($1.([]ast.WindowSpec), $3.(ast.WindowSpec)) + } + +WindowDefinition: + WindowName "AS" WindowSpec + { + var spec = $3.(ast.WindowSpec) + spec.Name = $1.(model.CIStr) + $$ = spec + } + +WindowName: + Identifier + { + $$ = model.NewCIStr($1) + } + +WindowSpec: + '(' WindowSpecDetails ')' + { + $$ = $2.(ast.WindowSpec) + } + +WindowSpecDetails: + OptExistingWindowName OptPartitionClause OptWindowOrderByClause OptWindowFrameClause + { + spec := ast.WindowSpec{Ref: $1.(model.CIStr),} + if $2 != nil { + spec.PartitionBy = $2.(*ast.PartitionByClause) + } + if $3 != nil { + spec.OrderBy = $3.(*ast.OrderByClause) + } + if $4 != nil { + spec.Frame = $4.(*ast.FrameClause) + } + $$ = spec + } + +OptExistingWindowName: + { + $$ = model.CIStr{} + } +| WindowName + { + $$ = $1.(model.CIStr) + } + +OptPartitionClause: + { + $$ = nil + } +| "PARTITION" "BY" ByList + { + $$ = &ast.PartitionByClause{Items: $3.([]*ast.ByItem)} + } + +OptWindowOrderByClause: + { + $$ = nil + } +| "ORDER" "BY" ByList + { + $$ = &ast.OrderByClause{Items: $3.([]*ast.ByItem)} + } + +OptWindowFrameClause: + { + $$ = nil + } +| WindowFrameUnits WindowFrameExtent + { + $$ = &ast.FrameClause{ + Type: $1.(ast.FrameType), + Extent: $2.(ast.FrameExtent), + } + } + +WindowFrameUnits: + "ROWS" + { + $$ = ast.FrameType(ast.Rows) + } +| "RANGE" + { + $$ = ast.FrameType(ast.Ranges) + } +| "GROUPS" + { + $$ = ast.FrameType(ast.Groups) + } + +WindowFrameExtent: + WindowFrameStart + { + $$ = ast.FrameExtent { + Start: $1.(ast.FrameBound), + End: ast.FrameBound{Type: ast.CurrentRow,}, + } + } +| WindowFrameBetween + { + $$ = $1.(ast.FrameExtent) + } + +WindowFrameStart: + "UNBOUNDED" "PRECEDING" + { + $$ = ast.FrameBound{Type: ast.Preceding, UnBounded: true,} + } +| NumLiteral "PRECEDING" + { + $$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($1),} + } +| paramMarker "PRECEDING" + { + $$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($1),} + } +| "INTERVAL" Expression TimeUnit "PRECEDING" + { + $$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($2), Unit: ast.NewValueExpr($3),} + } +| "CURRENT" "ROW" + { + $$ = ast.FrameBound{Type: ast.CurrentRow,} + } + +WindowFrameBetween: + "BETWEEN" WindowFrameBound "AND" WindowFrameBound + { + $$ = ast.FrameExtent{Start: $2.(ast.FrameBound), End: $4.(ast.FrameBound),} + } + +WindowFrameBound: + WindowFrameStart + { + $$ = $1.(ast.FrameBound) + } +| "UNBOUNDED" "FOLLOWING" + { + $$ = ast.FrameBound{Type: ast.Following, UnBounded: true,} + } +| NumLiteral "FOLLOWING" + { + $$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($1),} + } +| paramMarker "FOLLOWING" + { + $$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($1),} + } +| "INTERVAL" Expression TimeUnit "FOLLOWING" + { + $$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($2), Unit: ast.NewValueExpr($3),} + } + +OptWindowingClause: + { + $$ = nil + } +| WindowingClause + { + spec := $1.(ast.WindowSpec) + $$ = &spec + } + +WindowingClause: + "OVER" WindowNameOrSpec + { + $$ = $2.(ast.WindowSpec) + } + +WindowNameOrSpec: + WindowName + { + $$ = ast.WindowSpec{Ref: $1.(model.CIStr)} + } +| WindowSpec + { + $$ = $1.(ast.WindowSpec) + } + +WindowFuncCall: + "ROW_NUMBER" '(' ')' WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Spec: $4.(ast.WindowSpec),} + } +| "RANK" '(' ')' WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Spec: $4.(ast.WindowSpec),} + } +| "DENSE_RANK" '(' ')' WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Spec: $4.(ast.WindowSpec),} + } +| "CUME_DIST" '(' ')' WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Spec: $4.(ast.WindowSpec),} + } +| "PERCENT_RANK" '(' ')' WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Spec: $4.(ast.WindowSpec),} + } +| "NTILE" '(' SimpleExpr ')' WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, Spec: $5.(ast.WindowSpec),} + } +| "LEAD" '(' Expression OptLeadLagInfo ')' OptNullTreatment WindowingClause + { + args := []ast.ExprNode{$3} + if $4 != nil { + args = append(args, $4.([]ast.ExprNode)...) + } + $$ = &ast.WindowFuncExpr{F: $1, Args: args, IgnoreNull: $6.(bool), Spec: $7.(ast.WindowSpec),} + } +| "LAG" '(' Expression OptLeadLagInfo ')' OptNullTreatment WindowingClause + { + args := []ast.ExprNode{$3} + if $4 != nil { + args = append(args, $4.([]ast.ExprNode)...) + } + $$ = &ast.WindowFuncExpr{F: $1, Args: args, IgnoreNull: $6.(bool), Spec: $7.(ast.WindowSpec),} + } +| "FIRST_VALUE" '(' Expression ')' OptNullTreatment WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, IgnoreNull: $5.(bool), Spec: $6.(ast.WindowSpec),} + } +| "LAST_VALUE" '(' Expression ')' OptNullTreatment WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3}, IgnoreNull: $5.(bool), Spec: $6.(ast.WindowSpec),} + } +| "NTH_VALUE" '(' Expression ',' SimpleExpr ')' OptFromFirstLast OptNullTreatment WindowingClause + { + $$ = &ast.WindowFuncExpr{F: $1, Args: []ast.ExprNode{$3, $5}, FromLast: $7.(bool), IgnoreNull: $8.(bool), Spec: $9.(ast.WindowSpec),} + } + +OptLeadLagInfo: + { + $$ = nil + } +| ',' NumLiteral OptLLDefault + { + args := []ast.ExprNode{ast.NewValueExpr($2)} + if $3 != nil { + args = append(args, $3.(ast.ExprNode)) + } + $$ = args + } +| ',' paramMarker OptLLDefault + { + args := []ast.ExprNode{ast.NewValueExpr($2)} + if $3 != nil { + args = append(args, $3.(ast.ExprNode)) + } + $$ = args + } + +OptLLDefault: + { + $$ = nil + } +| ',' Expression + { + $$ = $2 + } + +OptNullTreatment: + { + $$ = false + } +| "RESPECT" "NULLS" + { + $$ = false + } +| "IGNORE" "NULLS" + { + $$ = true + } + +OptFromFirstLast: + { + $$ = false + } +| "FROM" "FIRST" + { + $$ = false + } +| "FROM" "LAST" + { + $$ = true + } + +TableRefsClause: + TableRefs + { + $$ = &ast.TableRefsClause{TableRefs: $1.(*ast.Join)} + } + +TableRefs: + EscapedTableRef + { + if j, ok := $1.(*ast.Join); ok { + // if $1 is Join, use it directly + $$ = j + } else { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: nil} + } + } +| TableRefs ',' EscapedTableRef + { + /* from a, b is default cross join */ + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin} + } + +EscapedTableRef: + TableRef %prec lowerThanSetKeyword + { + $$ = $1 + } +| '{' Identifier TableRef '}' + { + /* + * ODBC escape syntax for outer join is { OJ join_table } + * Use an Identifier for OJ + */ + $$ = $3 + } + +TableRef: + TableFactor + { + $$ = $1 + } +| JoinTable + { + $$ = $1 + } + +TableFactor: + TableName TableAsNameOpt IndexHintListOpt + { + tn := $1.(*ast.TableName) + tn.IndexHints = $3.([]*ast.IndexHint) + $$ = &ast.TableSource{Source: tn, AsName: $2.(model.CIStr)} + } +| '(' SelectStmt ')' TableAsName + { + st := $2.(*ast.SelectStmt) + endOffset := parser.endOffset(&yyS[yypt-1]) + parser.setLastSelectFieldText(st, endOffset) + $$ = &ast.TableSource{Source: $2.(*ast.SelectStmt), AsName: $4.(model.CIStr)} + } +| '(' UnionStmt ')' TableAsName + { + $$ = &ast.TableSource{Source: $2.(*ast.UnionStmt), AsName: $4.(model.CIStr)} + } +| '(' TableRefs ')' + { + $$ = $2 + } + +TableAsNameOpt: + { + $$ = model.CIStr{} + } +| TableAsName + { + $$ = $1 + } + +TableAsName: + Identifier + { + $$ = model.NewCIStr($1) + } +| "AS" Identifier + { + $$ = model.NewCIStr($2) + } + +IndexHintType: + "USE" KeyOrIndex + { + $$ = ast.HintUse + } +| "IGNORE" KeyOrIndex + { + $$ = ast.HintIgnore + } +| "FORCE" KeyOrIndex + { + $$ = ast.HintForce + } + +IndexHintScope: + { + $$ = ast.HintForScan + } +| "FOR" "JOIN" + { + $$ = ast.HintForJoin + } +| "FOR" "ORDER" "BY" + { + $$ = ast.HintForOrderBy + } +| "FOR" "GROUP" "BY" + { + $$ = ast.HintForGroupBy + } + + +IndexHint: + IndexHintType IndexHintScope '(' IndexNameList ')' + { + $$ = &ast.IndexHint{ + IndexNames: $4.([]model.CIStr), + HintType: $1.(ast.IndexHintType), + HintScope: $2.(ast.IndexHintScope), + } + } + +IndexNameList: + { + var nameList []model.CIStr + $$ = nameList + } +| Identifier + { + $$ = []model.CIStr{model.NewCIStr($1)} + } +| IndexNameList ',' Identifier + { + $$ = append($1.([]model.CIStr), model.NewCIStr($3)) + } +| "PRIMARY" + { + $$ = []model.CIStr{model.NewCIStr($1)} + } + +IndexHintList: + IndexHint + { + $$ = []*ast.IndexHint{$1.(*ast.IndexHint)} + } +| IndexHintList IndexHint + { + $$ = append($1.([]*ast.IndexHint), $2.(*ast.IndexHint)) + } + +IndexHintListOpt: + { + var hintList []*ast.IndexHint + $$ = hintList + } +| IndexHintList + { + $$ = $1 + } + +JoinTable: + /* Use %prec to evaluate production TableRef before cross join */ + TableRef CrossOpt TableRef %prec tableRefPriority + { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin} + } +| TableRef CrossOpt TableRef "ON" Expression + { + on := &ast.OnCondition{Expr: $5} + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin, On: on} + } +| TableRef CrossOpt TableRef "USING" '(' ColumnNameList ')' + { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin, Using: $6.([]*ast.ColumnName)} + } +| TableRef JoinType OuterOpt "JOIN" TableRef "ON" Expression + { + on := &ast.OnCondition{Expr: $7} + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $5.(ast.ResultSetNode), Tp: $2.(ast.JoinType), On: on} + } +| TableRef JoinType OuterOpt "JOIN" TableRef "USING" '(' ColumnNameList ')' + { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $5.(ast.ResultSetNode), Tp: $2.(ast.JoinType), Using: $8.([]*ast.ColumnName)} + } +| TableRef "NATURAL" "JOIN" TableRef + { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $4.(ast.ResultSetNode), NaturalJoin: true} + } +| TableRef "NATURAL" JoinType OuterOpt "JOIN" TableRef + { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $6.(ast.ResultSetNode), Tp: $3.(ast.JoinType), NaturalJoin: true} + } +| TableRef "STRAIGHT_JOIN" TableRef + { + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), StraightJoin: true} + } +| TableRef "STRAIGHT_JOIN" TableRef "ON" Expression + { + on := &ast.OnCondition{Expr: $5} + $$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), StraightJoin: true, On: on} + } + +JoinType: + "LEFT" + { + $$ = ast.LeftJoin + } +| "RIGHT" + { + $$ = ast.RightJoin + } + +OuterOpt: + {} +| "OUTER" + +CrossOpt: + "JOIN" +| "CROSS" "JOIN" +| "INNER" "JOIN" + + +LimitClause: + { + $$ = nil + } +| "LIMIT" LimitOption + { + $$ = &ast.Limit{Count: $2.(ast.ValueExpr)} + } + +LimitOption: + LengthNum + { + $$ = ast.NewValueExpr($1) + } +| paramMarker + { + $$ = ast.NewParamMarkerExpr(yyS[yypt].offset) + } + +SelectStmtLimit: + { + $$ = nil + } +| "LIMIT" LimitOption + { + $$ = &ast.Limit{Count: $2.(ast.ExprNode)} + } +| "LIMIT" LimitOption ',' LimitOption + { + $$ = &ast.Limit{Offset: $2.(ast.ExprNode), Count: $4.(ast.ExprNode)} + } +| "LIMIT" LimitOption "OFFSET" LimitOption + { + $$ = &ast.Limit{Offset: $4.(ast.ExprNode), Count: $2.(ast.ExprNode)} + } + + +SelectStmtOpts: + TableOptimizerHints DefaultFalseDistinctOpt PriorityOpt SelectStmtSQLCache SelectStmtCalcFoundRows SelectStmtStraightJoin + { + opt := &ast.SelectStmtOpts{} + if $1 != nil { + opt.TableHints = $1.([]*ast.TableOptimizerHint) + } + if $2 != nil { + opt.Distinct = $2.(bool) + } + if $3 != nil { + opt.Priority = $3.(mysql.PriorityEnum) + } + if $4 != nil { + opt.SQLCache = $4.(bool) + } + if $5 != nil { + opt.CalcFoundRows = $5.(bool) + } + if $6 != nil { + opt.StraightJoin = $6.(bool) + } + + $$ = opt + } + +TableOptimizerHints: + /* empty */ + { + $$ = nil + } +| hintBegin TableOptimizerHintList hintEnd + { + $$ = $2 + } + +HintTableList: + Identifier + { + $$ = []model.CIStr{model.NewCIStr($1)} + } +| HintTableList ',' Identifier + { + $$ = append($1.([]model.CIStr), model.NewCIStr($3)) + } + +TableOptimizerHintList: + TableOptimizerHintOpt + { + $$ = []*ast.TableOptimizerHint{$1.(*ast.TableOptimizerHint)} + } +| TableOptimizerHintList TableOptimizerHintOpt + { + $$ = append($1.([]*ast.TableOptimizerHint), $2.(*ast.TableOptimizerHint)) + } + +TableOptimizerHintOpt: + tidbSMJ '(' HintTableList ')' + { + $$ = &ast.TableOptimizerHint{HintName: model.NewCIStr($1), Tables: $3.([]model.CIStr)} + } +| tidbINLJ '(' HintTableList ')' + { + $$ = &ast.TableOptimizerHint{HintName: model.NewCIStr($1), Tables: $3.([]model.CIStr)} + } +| tidbHJ '(' HintTableList ')' + { + $$ = &ast.TableOptimizerHint{HintName: model.NewCIStr($1), Tables: $3.([]model.CIStr)} + } +| maxExecutionTime '(' NUM ')' + { + $$ = &ast.TableOptimizerHint{HintName: model.NewCIStr($1), MaxExecutionTime: getUint64FromNUM($3)} + } + +SelectStmtCalcFoundRows: + { + $$ = false + } +| "SQL_CALC_FOUND_ROWS" + { + $$ = true + } +SelectStmtSQLCache: + %prec empty + { + $$ = true + } +| "SQL_CACHE" + { + $$ = true + } +| "SQL_NO_CACHE" + { + $$ = false + } +SelectStmtStraightJoin: + %prec empty + { + $$ = false + } +| "STRAIGHT_JOIN" + { + $$ = true + } + +SelectStmtFieldList: + FieldList + { + $$ = &ast.FieldList{Fields: $1.([]*ast.SelectField)} + } + +SelectStmtGroup: + /* EMPTY */ + { + $$ = nil + } +| GroupByClause + +// See https://dev.mysql.com/doc/refman/5.7/en/subqueries.html +SubSelect: + '(' SelectStmt ')' + { + s := $2.(*ast.SelectStmt) + endOffset := parser.endOffset(&yyS[yypt]) + parser.setLastSelectFieldText(s, endOffset) + src := parser.src + // See the implementation of yyParse function + s.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + $$ = &ast.SubqueryExpr{Query: s} + } +| '(' UnionStmt ')' + { + s := $2.(*ast.UnionStmt) + src := parser.src + // See the implementation of yyParse function + s.SetText(src[yyS[yypt-1].offset:yyS[yypt].offset]) + $$ = &ast.SubqueryExpr{Query: s} + } + +// See https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html +SelectLockOpt: + /* empty */ + { + $$ = ast.SelectLockNone + } +| "FOR" "UPDATE" + { + $$ = ast.SelectLockForUpdate + } +| "LOCK" "IN" "SHARE" "MODE" + { + $$ = ast.SelectLockInShareMode + } + +// See https://dev.mysql.com/doc/refman/5.7/en/union.html +UnionStmt: + UnionClauseList "UNION" UnionOpt SelectStmtBasic OrderByOptional SelectStmtLimit SelectLockOpt + { + st := $4.(*ast.SelectStmt) + union := $1.(*ast.UnionStmt) + st.IsAfterUnionDistinct = $3.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-5]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if $5 != nil { + union.OrderBy = $5.(*ast.OrderByClause) + } + if $6 != nil { + union.Limit = $6.(*ast.Limit) + } + if $5 == nil && $6 == nil { + st.LockTp = $7.(ast.SelectLockType) + } + $$ = union + } +| UnionClauseList "UNION" UnionOpt SelectStmtFromDualTable OrderByOptional + SelectStmtLimit SelectLockOpt + { + st := $4.(*ast.SelectStmt) + union := $1.(*ast.UnionStmt) + st.IsAfterUnionDistinct = $3.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-5]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if $5 != nil { + union.OrderBy = $5.(*ast.OrderByClause) + } + if $6 != nil { + union.Limit = $6.(*ast.Limit) + } + if $5 == nil && $6 == nil { + st.LockTp = $7.(ast.SelectLockType) + } + $$ = union + } +| UnionClauseList "UNION" UnionOpt SelectStmtFromTable OrderByOptional + SelectStmtLimit SelectLockOpt + { + st := $4.(*ast.SelectStmt) + union := $1.(*ast.UnionStmt) + st.IsAfterUnionDistinct = $3.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-5]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if $5 != nil { + union.OrderBy = $5.(*ast.OrderByClause) + } + if $6 != nil { + union.Limit = $6.(*ast.Limit) + } + if $5 == nil && $6 == nil { + st.LockTp = $7.(ast.SelectLockType) + } + $$ = union + } +| UnionClauseList "UNION" UnionOpt '(' SelectStmt ')' OrderByOptional SelectStmtLimit + { + union := $1.(*ast.UnionStmt) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-6]) + parser.setLastSelectFieldText(lastSelect, endOffset) + st := $5.(*ast.SelectStmt) + st.IsInBraces = true + st.IsAfterUnionDistinct = $3.(bool) + endOffset = parser.endOffset(&yyS[yypt-2]) + parser.setLastSelectFieldText(st, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + if $7 != nil { + union.OrderBy = $7.(*ast.OrderByClause) + } + if $8 != nil { + union.Limit = $8.(*ast.Limit) + } + $$ = union + } + +UnionClauseList: + UnionSelect + { + selectList := &ast.UnionSelectList{Selects: []*ast.SelectStmt{$1.(*ast.SelectStmt)}} + $$ = &ast.UnionStmt{ + SelectList: selectList, + } + } +| UnionClauseList "UNION" UnionOpt UnionSelect + { + union := $1.(*ast.UnionStmt) + st := $4.(*ast.SelectStmt) + st.IsAfterUnionDistinct = $3.(bool) + lastSelect := union.SelectList.Selects[len(union.SelectList.Selects)-1] + endOffset := parser.endOffset(&yyS[yypt-2]) + parser.setLastSelectFieldText(lastSelect, endOffset) + union.SelectList.Selects = append(union.SelectList.Selects, st) + $$ = union + } + +UnionSelect: + SelectStmt + { + $$ = $1.(interface{}) + } +| '(' SelectStmt ')' + { + st := $2.(*ast.SelectStmt) + st.IsInBraces = true + endOffset := parser.endOffset(&yyS[yypt]) + parser.setLastSelectFieldText(st, endOffset) + $$ = $2 + } + +UnionOpt: +DefaultTrueDistinctOpt + + +/********************Set Statement*******************************/ +SetStmt: + "SET" VariableAssignmentList + { + $$ = &ast.SetStmt{Variables: $2.([]*ast.VariableAssignment)} + } +| "SET" "PASSWORD" eq PasswordOpt + { + $$ = &ast.SetPwdStmt{Password: $4.(string)} + } +| "SET" "PASSWORD" "FOR" Username eq PasswordOpt + { + $$ = &ast.SetPwdStmt{User: $4.(*auth.UserIdentity), Password: $6.(string)} + } +| "SET" "GLOBAL" "TRANSACTION" TransactionChars + { + vars := $4.([]*ast.VariableAssignment) + for _, v := range vars { + v.IsGlobal = true + } + $$ = &ast.SetStmt{Variables: vars} + } +| "SET" "SESSION" "TRANSACTION" TransactionChars + { + $$ = &ast.SetStmt{Variables: $4.([]*ast.VariableAssignment)} + } +| "SET" "TRANSACTION" TransactionChars + { + assigns := $3.([]*ast.VariableAssignment) + for i:=0; i 24 { + x.Tp = mysql.TypeDouble + } + } + x.Decimal = fopt.Decimal + for _, o := range $3.([]*ast.TypeOpt) { + if o.IsUnsigned { + x.Flag |= mysql.UnsignedFlag + } + if o.IsZerofill { + x.Flag |= mysql.ZerofillFlag + } + } + $$ = x + } +| BitValueType OptFieldLen + { + x := types.NewFieldType($1.(byte)) + x.Flen = $2.(int) + if x.Flen == types.UnspecifiedLength || x.Flen == 0 { + x.Flen = 1 + } else if x.Flen > 64 { + yylex.Errorf("invalid field length %d for bit type, must in [1, 64]", x.Flen) + } + $$ = x + } + +IntegerType: + "TINYINT" + { + $$ = mysql.TypeTiny + } +| "SMALLINT" + { + $$ = mysql.TypeShort + } +| "MEDIUMINT" + { + $$ = mysql.TypeInt24 + } +| "INT" + { + $$ = mysql.TypeLong + } +| "INT1" + { + $$ = mysql.TypeTiny + } +| "INT2" + { + $$ = mysql.TypeShort + } +| "INT3" + { + $$ = mysql.TypeInt24 + } +| "INT4" + { + $$ = mysql.TypeLong + } +| "INT8" + { + $$ = mysql.TypeLonglong + } +| "INTEGER" + { + $$ = mysql.TypeLong + } +| "BIGINT" + { + $$ = mysql.TypeLonglong + } + + +BooleanType: + "BOOL" + { + $$ = mysql.TypeTiny + } +| "BOOLEAN" + { + $$ = mysql.TypeTiny + } + +OptInteger: + {} +| "INTEGER" +| "INT" + +FixedPointType: + "DECIMAL" + { + $$ = mysql.TypeNewDecimal + } +| "NUMERIC" + { + $$ = mysql.TypeNewDecimal + } + +FloatingPointType: + "FLOAT" + { + $$ = mysql.TypeFloat + } +| "REAL" + { + if parser.lexer.GetSQLMode().HasRealAsFloatMode() { + $$ = mysql.TypeFloat + } else { + $$ = mysql.TypeDouble + } + } +| "DOUBLE" + { + $$ = mysql.TypeDouble + } +| "DOUBLE" "PRECISION" + { + $$ = mysql.TypeDouble + } + +BitValueType: + "BIT" + { + $$ = mysql.TypeBit + } + +StringType: + NationalOpt "CHAR" FieldLen OptBinary OptCollate + { + x := types.NewFieldType(mysql.TypeString) + x.Flen = $3.(int) + x.Charset = $4.(*ast.OptBinary).Charset + x.Collate = $5.(string) + if $4.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + $$ = x + } +| NationalOpt "CHAR" OptBinary OptCollate + { + x := types.NewFieldType(mysql.TypeString) + x.Charset = $3.(*ast.OptBinary).Charset + x.Collate = $4.(string) + if $3.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + $$ = x + } +| "NATIONAL" "CHARACTER" FieldLen OptBinary OptCollate + { + x := types.NewFieldType(mysql.TypeString) + x.Flen = $3.(int) + x.Charset = $4.(*ast.OptBinary).Charset + x.Collate = $5.(string) + if $4.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + $$ = x + } +| Varchar FieldLen OptBinary OptCollate + { + x := types.NewFieldType(mysql.TypeVarchar) + x.Flen = $2.(int) + x.Charset = $3.(*ast.OptBinary).Charset + x.Collate = $4.(string) + if $3.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + $$ = x + } +| "BINARY" OptFieldLen + { + x := types.NewFieldType(mysql.TypeString) + x.Flen = $2.(int) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| "VARBINARY" FieldLen + { + x := types.NewFieldType(mysql.TypeVarchar) + x.Flen = $2.(int) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + x.Flag |= mysql.BinaryFlag + $$ = x + } +| BlobType + { + x := $1.(*types.FieldType) + x.Charset = charset.CharsetBin + x.Collate = charset.CharsetBin + x.Flag |= mysql.BinaryFlag + $$ = $1.(*types.FieldType) + } +| TextType OptBinary OptCollate + { + x := $1.(*types.FieldType) + x.Charset = $2.(*ast.OptBinary).Charset + x.Collate = $3.(string) + if $2.(*ast.OptBinary).IsBinary { + x.Flag |= mysql.BinaryFlag + } + $$ = x + } +| "ENUM" '(' StringList ')' OptCharset OptCollate + { + x := types.NewFieldType(mysql.TypeEnum) + x.Elems = $3.([]string) + x.Charset = $5.(string) + x.Collate = $6.(string) + $$ = x + } +| "SET" '(' StringList ')' OptCharset OptCollate + { + x := types.NewFieldType(mysql.TypeSet) + x.Elems = $3.([]string) + x.Charset = $5.(string) + x.Collate = $6.(string) + $$ = x + } +| "JSON" + { + x := types.NewFieldType(mysql.TypeJSON) + x.Decimal = 0 + x.Charset = charset.CharsetBin + x.Collate = charset.CollationBin + $$ = x + } + +NationalOpt: + {} +| "NATIONAL" + +Varchar: +"NATIONAL" "VARCHAR" +| "VARCHAR" +| "NVARCHAR" + + +BlobType: + "TINYBLOB" + { + x := types.NewFieldType(mysql.TypeTinyBlob) + $$ = x + } +| "BLOB" OptFieldLen + { + x := types.NewFieldType(mysql.TypeBlob) + x.Flen = $2.(int) + $$ = x + } +| "MEDIUMBLOB" + { + x := types.NewFieldType(mysql.TypeMediumBlob) + $$ = x + } +| "LONGBLOB" + { + x := types.NewFieldType(mysql.TypeLongBlob) + $$ = x + } + +TextType: + "TINYTEXT" + { + x := types.NewFieldType(mysql.TypeTinyBlob) + $$ = x + + } +| "TEXT" OptFieldLen + { + x := types.NewFieldType(mysql.TypeBlob) + x.Flen = $2.(int) + $$ = x + } +| "MEDIUMTEXT" + { + x := types.NewFieldType(mysql.TypeMediumBlob) + $$ = x + } +| "LONGTEXT" + { + x := types.NewFieldType(mysql.TypeLongBlob) + $$ = x + } +| "LONG" "VARCHAR" + { + x := types.NewFieldType(mysql.TypeMediumBlob) + $$ = x + } + + +DateAndTimeType: + "DATE" + { + x := types.NewFieldType(mysql.TypeDate) + $$ = x + } +| "DATETIME" OptFieldLen + { + x := types.NewFieldType(mysql.TypeDatetime) + x.Flen = mysql.MaxDatetimeWidthNoFsp + x.Decimal = $2.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + $$ = x + } +| "TIMESTAMP" OptFieldLen + { + x := types.NewFieldType(mysql.TypeTimestamp) + x.Flen = mysql.MaxDatetimeWidthNoFsp + x.Decimal = $2.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + $$ = x + } +| "TIME" OptFieldLen + { + x := types.NewFieldType(mysql.TypeDuration) + x.Flen = mysql.MaxDurationWidthNoFsp + x.Decimal = $2.(int) + if x.Decimal > 0 { + x.Flen = x.Flen + 1 + x.Decimal + } + $$ = x + } +| "YEAR" OptFieldLen FieldOpts + { + x := types.NewFieldType(mysql.TypeYear) + x.Flen = $2.(int) + if x.Flen != types.UnspecifiedLength && x.Flen != 4 { + yylex.Errorf("Supports only YEAR or YEAR(4) column.") + return -1 + } + $$ = x + } + +FieldLen: + '(' LengthNum ')' + { + $$ = int($2.(uint64)) + } + +OptFieldLen: + { + $$ = types.UnspecifiedLength + } +| FieldLen + { + $$ = $1.(int) + } + +FieldOpt: + "UNSIGNED" + { + $$ = &ast.TypeOpt{IsUnsigned: true} + } +| "SIGNED" + { + $$ = &ast.TypeOpt{IsUnsigned: false} + } +| "ZEROFILL" + { + $$ = &ast.TypeOpt{IsZerofill: true, IsUnsigned: true} + } + +FieldOpts: + { + $$ = []*ast.TypeOpt{} + } +| FieldOpts FieldOpt + { + $$ = append($1.([]*ast.TypeOpt), $2.(*ast.TypeOpt)) + } + +FloatOpt: + { + $$ = &ast.FloatOpt{Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength} + } +| FieldLen + { + $$ = &ast.FloatOpt{Flen: $1.(int), Decimal: types.UnspecifiedLength} + } +| Precision + { + $$ = $1.(*ast.FloatOpt) + } + +Precision: + '(' LengthNum ',' LengthNum ')' + { + $$ = &ast.FloatOpt{Flen: int($2.(uint64)), Decimal: int($4.(uint64))} + } + +OptBinMod: + { + $$ = false + } +| "BINARY" + { + $$ = true + } + +OptBinary: + { + $$ = &ast.OptBinary{ + IsBinary: false, + Charset: "", + } + } +| "BINARY" OptCharset + { + $$ = &ast.OptBinary{ + IsBinary: true, + Charset: $2.(string), + } + } +| CharsetKw CharsetName OptBinMod + { + $$ = &ast.OptBinary{ + IsBinary: $3.(bool), + Charset: $2.(string), + } + } + +OptCharset: + { + $$ = "" + } +| CharsetKw CharsetName + { + $$ = $2.(string) + } + +CharsetKw: + "CHARACTER" "SET" +| "CHARSET" + +OptCollate: + { + $$ = "" + } +| "COLLATE" StringName + { + $$ = $2.(string) + } + +StringList: + stringLit + { + $$ = []string{$1} + } +| StringList ',' stringLit + { + $$ = append($1.([]string), $3) + } + +StringName: + stringLit + { + $$ = $1 + } +| Identifier + { + $$ = $1 + } + +/*********************************************************************************** + * Update Statement + * See https://dev.mysql.com/doc/refman/5.7/en/update.html + ***********************************************************************************/ +UpdateStmt: + "UPDATE" TableOptimizerHints PriorityOpt IgnoreOptional TableRef "SET" AssignmentList WhereClauseOptional OrderByOptional LimitClause + { + var refs *ast.Join + if x, ok := $5.(*ast.Join); ok { + refs = x + } else { + refs = &ast.Join{Left: $5.(ast.ResultSetNode)} + } + st := &ast.UpdateStmt{ + Priority: $3.(mysql.PriorityEnum), + TableRefs: &ast.TableRefsClause{TableRefs: refs}, + List: $7.([]*ast.Assignment), + IgnoreErr: $4.(bool), + } + if $2 != nil { + st.TableHints = $2.([]*ast.TableOptimizerHint) + } + if $8 != nil { + st.Where = $8.(ast.ExprNode) + } + if $9 != nil { + st.Order = $9.(*ast.OrderByClause) + } + if $10 != nil { + st.Limit = $10.(*ast.Limit) + } + $$ = st + } +| "UPDATE" TableOptimizerHints PriorityOpt IgnoreOptional TableRefs "SET" AssignmentList WhereClauseOptional + { + st := &ast.UpdateStmt{ + Priority: $3.(mysql.PriorityEnum), + TableRefs: &ast.TableRefsClause{TableRefs: $5.(*ast.Join)}, + List: $7.([]*ast.Assignment), + IgnoreErr: $4.(bool), + } + if $2 != nil { + st.TableHints = $2.([]*ast.TableOptimizerHint) + } + if $8 != nil { + st.Where = $8.(ast.ExprNode) + } + $$ = st + } + +UseStmt: + "USE" DBName + { + $$ = &ast.UseStmt{DBName: $2.(string)} + } + +WhereClause: + "WHERE" Expression + { + $$ = $2 + } + +WhereClauseOptional: + { + $$ = nil + } +| WhereClause + { + $$ = $1 + } + +CommaOpt: + {} +| ',' + {} + +/************************************************************************************ + * Account Management Statements + * https://dev.mysql.com/doc/refman/5.7/en/account-management-sql.html + ************************************************************************************/ +CreateUserStmt: + "CREATE" "USER" IfNotExists UserSpecList + { + // See https://dev.mysql.com/doc/refman/5.7/en/create-user.html + $$ = &ast.CreateUserStmt{ + IfNotExists: $3.(bool), + Specs: $4.([]*ast.UserSpec), + } + } + +/* See http://dev.mysql.com/doc/refman/5.7/en/alter-user.html */ +AlterUserStmt: + "ALTER" "USER" IfExists UserSpecList + { + $$ = &ast.AlterUserStmt{ + IfExists: $3.(bool), + Specs: $4.([]*ast.UserSpec), + } + } +| "ALTER" "USER" IfExists "USER" '(' ')' "IDENTIFIED" "BY" AuthString + { + auth := &ast.AuthOption { + AuthString: $9.(string), + ByAuthString: true, + } + $$ = &ast.AlterUserStmt{ + IfExists: $3.(bool), + CurrentAuth: auth, + } + } + +UserSpec: + Username AuthOption + { + userSpec := &ast.UserSpec{ + User: $1.(*auth.UserIdentity), + } + if $2 != nil { + userSpec.AuthOpt = $2.(*ast.AuthOption) + } + $$ = userSpec + } + +UserSpecList: + UserSpec + { + $$ = []*ast.UserSpec{$1.(*ast.UserSpec)} + } +| UserSpecList ',' UserSpec + { + $$ = append($1.([]*ast.UserSpec), $3.(*ast.UserSpec)) + } + +AuthOption: + { + $$ = nil + } +| "IDENTIFIED" "BY" AuthString + { + $$ = &ast.AuthOption { + AuthString: $3.(string), + ByAuthString: true, + } + } +| "IDENTIFIED" "WITH" StringName + { + $$ = nil + } +| "IDENTIFIED" "WITH" StringName "BY" AuthString + { + $$ = &ast.AuthOption { + AuthString: $5.(string), + ByAuthString: true, + } + } +| "IDENTIFIED" "WITH" StringName "AS" HashString + { + $$ = &ast.AuthOption{ + HashString: $5.(string), + } + } +| "IDENTIFIED" "BY" "PASSWORD" HashString + { + $$ = &ast.AuthOption{ + HashString: $4.(string), + } + } + +HashString: + stringLit + { + $$ = $1 + } + +/************************************************************************************* + * Grant statement + * See https://dev.mysql.com/doc/refman/5.7/en/grant.html + *************************************************************************************/ +GrantStmt: + "GRANT" PrivElemList "ON" ObjectType PrivLevel "TO" UserSpecList WithGrantOptionOpt + { + $$ = &ast.GrantStmt{ + Privs: $2.([]*ast.PrivElem), + ObjectType: $4.(ast.ObjectTypeType), + Level: $5.(*ast.GrantLevel), + Users: $7.([]*ast.UserSpec), + WithGrant: $8.(bool), + } + } + +WithGrantOptionOpt: + { + $$ = false + } +| "WITH" "GRANT" "OPTION" + { + $$ = true + } +| "WITH" "MAX_QUERIES_PER_HOUR" NUM + { + $$ = false + } +| "WITH" "MAX_UPDATES_PER_HOUR" NUM + { + $$ = false + } +| "WITH" "MAX_CONNECTIONS_PER_HOUR" NUM + { + $$ = false + } +| "WITH" "MAX_USER_CONNECTIONS" NUM + { + $$ = false + } + +PrivElem: + PrivType + { + $$ = &ast.PrivElem{ + Priv: $1.(mysql.PrivilegeType), + } + } +| PrivType '(' ColumnNameList ')' + { + $$ = &ast.PrivElem{ + Priv: $1.(mysql.PrivilegeType), + Cols: $3.([]*ast.ColumnName), + } + } + +PrivElemList: + PrivElem + { + $$ = []*ast.PrivElem{$1.(*ast.PrivElem)} + } +| PrivElemList ',' PrivElem + { + $$ = append($1.([]*ast.PrivElem), $3.(*ast.PrivElem)) + } + +PrivType: + "ALL" + { + $$ = mysql.AllPriv + } +| "ALL" "PRIVILEGES" + { + $$ = mysql.AllPriv + } +| "ALTER" + { + $$ = mysql.AlterPriv + } +| "CREATE" + { + $$ = mysql.CreatePriv + } +| "CREATE" "USER" + { + $$ = mysql.CreateUserPriv + } +| "TRIGGER" + { + $$ = mysql.TriggerPriv + } +| "DELETE" + { + $$ = mysql.DeletePriv + } +| "DROP" + { + $$ = mysql.DropPriv + } +| "PROCESS" + { + $$ = mysql.ProcessPriv + } +| "EXECUTE" + { + $$ = mysql.ExecutePriv + } +| "INDEX" + { + $$ = mysql.IndexPriv + } +| "INSERT" + { + $$ = mysql.InsertPriv + } +| "SELECT" + { + $$ = mysql.SelectPriv + } +| "SUPER" + { + $$ = mysql.SuperPriv + } +| "SHOW" "DATABASES" + { + $$ = mysql.ShowDBPriv + } +| "UPDATE" + { + $$ = mysql.UpdatePriv + } +| "GRANT" "OPTION" + { + $$ = mysql.GrantPriv + } +| "REFERENCES" + { + $$ = mysql.ReferencesPriv + } +| "REPLICATION" "SLAVE" + { + $$ = mysql.PrivilegeType(0) + } +| "REPLICATION" "CLIENT" + { + $$ = mysql.PrivilegeType(0) + } +| "USAGE" + { + $$ = mysql.PrivilegeType(0) + } +| "RELOAD" + { + $$ = mysql.PrivilegeType(0) + } +| "CREATE" "TEMPORARY" "TABLES" + { + $$ = mysql.PrivilegeType(0) + } +| "LOCK" "TABLES" + { + $$ = mysql.PrivilegeType(0) + } +| "CREATE" "VIEW" + { + $$ = mysql.PrivilegeType(0) + } +| "SHOW" "VIEW" + { + $$ = mysql.PrivilegeType(0) + } +| "CREATE" "ROUTINE" + { + $$ = mysql.PrivilegeType(0) + } +| "ALTER" "ROUTINE" + { + $$ = mysql.PrivilegeType(0) + } +| "EVENT" + { + $$ = mysql.PrivilegeType(0) + } + +ObjectType: + { + $$ = ast.ObjectTypeNone + } +| "TABLE" + { + $$ = ast.ObjectTypeTable + } + +PrivLevel: + '*' + { + $$ = &ast.GrantLevel { + Level: ast.GrantLevelDB, + } + } +| '*' '.' '*' + { + $$ = &ast.GrantLevel { + Level: ast.GrantLevelGlobal, + } + } +| Identifier '.' '*' + { + $$ = &ast.GrantLevel { + Level: ast.GrantLevelDB, + DBName: $1, + } + } +| Identifier '.' Identifier + { + $$ = &ast.GrantLevel { + Level: ast.GrantLevelTable, + DBName: $1, + TableName: $3, + } + } +| Identifier + { + $$ = &ast.GrantLevel { + Level: ast.GrantLevelTable, + TableName: $1, + } + } + +/**************************************RevokeStmt******************************************* + * See https://dev.mysql.com/doc/refman/5.7/en/revoke.html + *******************************************************************************************/ +RevokeStmt: + "REVOKE" PrivElemList "ON" ObjectType PrivLevel "FROM" UserSpecList + { + $$ = &ast.RevokeStmt{ + Privs: $2.([]*ast.PrivElem), + ObjectType: $4.(ast.ObjectTypeType), + Level: $5.(*ast.GrantLevel), + Users: $7.([]*ast.UserSpec), + } + } + +/**************************************LoadDataStmt***************************************** + * See https://dev.mysql.com/doc/refman/5.7/en/load-data.html + *******************************************************************************************/ +LoadDataStmt: + "LOAD" "DATA" LocalOpt "INFILE" stringLit "INTO" "TABLE" TableName CharsetOpt Fields Lines IgnoreLines ColumnNameListOptWithBrackets + { + x := &ast.LoadDataStmt{ + Path: $5, + Table: $8.(*ast.TableName), + Columns: $13.([]*ast.ColumnName), + IgnoreLines:$12.(uint64), + } + if $3 != nil { + x.IsLocal = true + } + if $10 != nil { + x.FieldsInfo = $10.(*ast.FieldsClause) + } + if $11 != nil { + x.LinesInfo = $11.(*ast.LinesClause) + } + $$ = x + } + +IgnoreLines: + { + $$ = uint64(0) + } +| "IGNORE" NUM "LINES" + { + $$ = getUint64FromNUM($2) + } + +CharsetOpt: + {} +| "CHARACTER" "SET" CharsetName + +LocalOpt: + { + $$ = nil + } +| "LOCAL" + { + $$ = $1 + } + +Fields: + { + escape := "\\" + $$ = &ast.FieldsClause{ + Terminated: "\t", + Escaped: escape[0], + } + } +| FieldsOrColumns FieldsTerminated Enclosed Escaped + { + escape := $4.(string) + if escape != "\\" && len(escape) > 1 { + yylex.Errorf("Incorrect arguments %s to ESCAPE", escape) + return 1 + } + var enclosed byte + str := $3.(string) + if len(str) > 1 { + yylex.Errorf("Incorrect arguments %s to ENCLOSED", escape) + return 1 + }else if len(str) != 0 { + enclosed = str[0] + } + var escaped byte + if len(escape) > 0 { + escaped = escape[0] + } + $$ = &ast.FieldsClause{ + Terminated: $2.(string), + Enclosed: enclosed, + Escaped: escaped, + } + } + +FieldsOrColumns: +"FIELDS" | "COLUMNS" + +FieldsTerminated: + { + $$ = "\t" + } +| "TERMINATED" "BY" stringLit + { + $$ = $3 + } + +Enclosed: + { + $$ = "" + } +| "ENCLOSED" "BY" stringLit + { + $$ = $3 + } + +Escaped: + { + $$ = "\\" + } +| "ESCAPED" "BY" stringLit + { + $$ = $3 + } + +Lines: + { + $$ = &ast.LinesClause{Terminated: "\n"} + } +| "LINES" Starting LinesTerminated + { + $$ = &ast.LinesClause{Starting: $2.(string), Terminated: $3.(string)} + } + +Starting: + { + $$ = "" + } +| "STARTING" "BY" stringLit + { + $$ = $3 + } + +LinesTerminated: + { + $$ = "\n" + } +| "TERMINATED" "BY" stringLit + { + $$ = $3 + } + + +/********************************************************************* + * Lock/Unlock Tables + * See http://dev.mysql.com/doc/refman/5.7/en/lock-tables.html + * All the statement leaves empty. This is used to prevent mysqldump error. + *********************************************************************/ + +UnlockTablesStmt: + "UNLOCK" TablesTerminalSym {} + +LockTablesStmt: + "LOCK" TablesTerminalSym TableLockList + {} + +TablesTerminalSym: + "TABLES" +| "TABLE" + +TableLock: + TableName LockType + +LockType: + "READ" +| "READ" "LOCAL" +| "WRITE" + +TableLockList: + TableLock +| TableLockList ',' TableLock + + +/******************************************************************** + * Kill Statement + * See https://dev.mysql.com/doc/refman/5.7/en/kill.html + *******************************************************************/ + +KillStmt: + KillOrKillTiDB NUM + { + $$ = &ast.KillStmt{ + ConnectionID: getUint64FromNUM($2), + TiDBExtension: $1.(bool), + } + } +| KillOrKillTiDB "CONNECTION" NUM + { + $$ = &ast.KillStmt{ + ConnectionID: getUint64FromNUM($3), + TiDBExtension: $1.(bool), + } + } +| KillOrKillTiDB "QUERY" NUM + { + $$ = &ast.KillStmt{ + ConnectionID: getUint64FromNUM($3), + Query: true, + TiDBExtension: $1.(bool), + } + } + +KillOrKillTiDB: + "KILL" + { + $$ = false + } +/* KILL TIDB is a special grammar extension in TiDB, it can be used only when + the client connect to TiDB directly, not proxied under LVS. */ +| "KILL" "TIDB" + { + $$ = true + } + +/*******************************************************************************************/ + +LoadStatsStmt: + "LOAD" "STATS" stringLit + { + $$ = &ast.LoadStatsStmt{ + Path: $3, + } + } + +%% diff --git a/vendor/github.com/pingcap/parser/terror/terror.go b/vendor/github.com/pingcap/parser/terror/terror.go new file mode 100644 index 0000000000000000000000000000000000000000..a5443653d71cda5d8debce5f3e197cf26dff92ff --- /dev/null +++ b/vendor/github.com/pingcap/parser/terror/terror.go @@ -0,0 +1,344 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package terror + +import ( + "encoding/json" + "fmt" + "strconv" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/mysql" + log "github.com/sirupsen/logrus" +) + +// Global error instances. +var ( + ErrCritical = ClassGlobal.New(CodeExecResultIsEmpty, "critical error %v") + ErrResultUndetermined = ClassGlobal.New(CodeResultUndetermined, "execution result undetermined") +) + +// ErrCode represents a specific error type in a error class. +// Same error code can be used in different error classes. +type ErrCode int + +const ( + // Executor error codes. + + // CodeUnknown is for errors of unknown reason. + CodeUnknown ErrCode = -1 + // CodeExecResultIsEmpty indicates execution result is empty. + CodeExecResultIsEmpty ErrCode = 3 + + // Expression error codes. + + // CodeMissConnectionID indicates connection id is missing. + CodeMissConnectionID ErrCode = 1 + + // Special error codes. + + // CodeResultUndetermined indicates the sql execution result is undetermined. + CodeResultUndetermined ErrCode = 2 +) + +// ErrClass represents a class of errors. +type ErrClass int + +// Error classes. +const ( + ClassAutoid ErrClass = iota + 1 + ClassDDL + ClassDomain + ClassEvaluator + ClassExecutor + ClassExpression + ClassAdmin + ClassKV + ClassMeta + ClassOptimizer + ClassParser + ClassPerfSchema + ClassPrivilege + ClassSchema + ClassServer + ClassStructure + ClassVariable + ClassXEval + ClassTable + ClassTypes + ClassGlobal + ClassMockTikv + ClassJSON + ClassTiKV + ClassSession + // Add more as needed. +) + +var errClz2Str = map[ErrClass]string{ + ClassAutoid: "autoid", + ClassDDL: "ddl", + ClassDomain: "domain", + ClassExecutor: "executor", + ClassExpression: "expression", + ClassAdmin: "admin", + ClassMeta: "meta", + ClassKV: "kv", + ClassOptimizer: "planner", + ClassParser: "parser", + ClassPerfSchema: "perfschema", + ClassPrivilege: "privilege", + ClassSchema: "schema", + ClassServer: "server", + ClassStructure: "structure", + ClassVariable: "variable", + ClassTable: "table", + ClassTypes: "types", + ClassGlobal: "global", + ClassMockTikv: "mocktikv", + ClassJSON: "json", + ClassTiKV: "tikv", + ClassSession: "session", +} + +// String implements fmt.Stringer interface. +func (ec ErrClass) String() string { + if s, exists := errClz2Str[ec]; exists { + return s + } + return strconv.Itoa(int(ec)) +} + +// EqualClass returns true if err is *Error with the same class. +func (ec ErrClass) EqualClass(err error) bool { + e := errors.Cause(err) + if e == nil { + return false + } + if te, ok := e.(*Error); ok { + return te.class == ec + } + return false +} + +// NotEqualClass returns true if err is not *Error with the same class. +func (ec ErrClass) NotEqualClass(err error) bool { + return !ec.EqualClass(err) +} + +// New creates an *Error with an error code and an error message. +// Usually used to create base *Error. +func (ec ErrClass) New(code ErrCode, message string) *Error { + return &Error{ + class: ec, + code: code, + message: message, + } +} + +// Error implements error interface and adds integer Class and Code, so +// errors with different message can be compared. +type Error struct { + class ErrClass + code ErrCode + message string + args []interface{} + file string + line int +} + +// Class returns ErrClass +func (e *Error) Class() ErrClass { + return e.class +} + +// Code returns ErrCode +func (e *Error) Code() ErrCode { + return e.code +} + +// MarshalJSON implements json.Marshaler interface. +func (e *Error) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + Class ErrClass `json:"class"` + Code ErrCode `json:"code"` + Msg string `json:"message"` + }{ + Class: e.class, + Code: e.code, + Msg: e.getMsg(), + }) +} + +// UnmarshalJSON implements json.Unmarshaler interface. +func (e *Error) UnmarshalJSON(data []byte) error { + err := &struct { + Class ErrClass `json:"class"` + Code ErrCode `json:"code"` + Msg string `json:"message"` + }{} + + if err := json.Unmarshal(data, &err); err != nil { + return errors.Trace(err) + } + + e.class = err.Class + e.code = err.Code + e.message = err.Msg + return nil +} + +// Location returns the location where the error is created, +// implements juju/errors locationer interface. +func (e *Error) Location() (file string, line int) { + return e.file, e.line +} + +// Error implements error interface. +func (e *Error) Error() string { + return fmt.Sprintf("[%s:%d]%s", e.class, e.code, e.getMsg()) +} + +func (e *Error) getMsg() string { + if len(e.args) > 0 { + return fmt.Sprintf(e.message, e.args...) + } + return e.message +} + +// GenWithStack generates a new *Error with the same class and code, and a new formatted message. +func (e *Error) GenWithStack(format string, args ...interface{}) error { + err := *e + err.message = format + err.args = args + return errors.AddStack(&err) +} + +// GenWithStackByArgs generates a new *Error with the same class and code, and new arguments. +func (e *Error) GenWithStackByArgs(args ...interface{}) error { + err := *e + err.args = args + return errors.AddStack(&err) +} + +// FastGen generates a new *Error with the same class and code, and a new formatted message. +// This will not call runtime.Caller to get file and line. +func (e *Error) FastGen(format string, args ...interface{}) error { + err := *e + err.message = format + err.args = args + return &err +} + +// Equal checks if err is equal to e. +func (e *Error) Equal(err error) bool { + originErr := errors.Cause(err) + if originErr == nil { + return false + } + + if error(e) == originErr { + return true + } + inErr, ok := originErr.(*Error) + return ok && e.class == inErr.class && e.code == inErr.code +} + +// NotEqual checks if err is not equal to e. +func (e *Error) NotEqual(err error) bool { + return !e.Equal(err) +} + +// ToSQLError convert Error to mysql.SQLError. +func (e *Error) ToSQLError() *mysql.SQLError { + code := e.getMySQLErrorCode() + return mysql.NewErrf(code, "%s", e.getMsg()) +} + +var defaultMySQLErrorCode uint16 + +func (e *Error) getMySQLErrorCode() uint16 { + codeMap, ok := ErrClassToMySQLCodes[e.class] + if !ok { + log.Warnf("Unknown error class: %v", e.class) + return defaultMySQLErrorCode + } + code, ok := codeMap[e.code] + if !ok { + log.Debugf("Unknown error class: %v code: %v", e.class, e.code) + return defaultMySQLErrorCode + } + return code +} + +var ( + // ErrClassToMySQLCodes is the map of ErrClass to code-map. + ErrClassToMySQLCodes map[ErrClass]map[ErrCode]uint16 +) + +func init() { + ErrClassToMySQLCodes = make(map[ErrClass]map[ErrCode]uint16) + defaultMySQLErrorCode = mysql.ErrUnknown +} + +// ErrorEqual returns a boolean indicating whether err1 is equal to err2. +func ErrorEqual(err1, err2 error) bool { + e1 := errors.Cause(err1) + e2 := errors.Cause(err2) + + if e1 == e2 { + return true + } + + if e1 == nil || e2 == nil { + return e1 == e2 + } + + te1, ok1 := e1.(*Error) + te2, ok2 := e2.(*Error) + if ok1 && ok2 { + return te1.class == te2.class && te1.code == te2.code + } + + return e1.Error() == e2.Error() +} + +// ErrorNotEqual returns a boolean indicating whether err1 isn't equal to err2. +func ErrorNotEqual(err1, err2 error) bool { + return !ErrorEqual(err1, err2) +} + +// MustNil cleans up and fatals if err is not nil. +func MustNil(err error, closeFuns ...func()) { + if err != nil { + for _, f := range closeFuns { + f() + } + log.Fatalf(errors.ErrorStack(err)) + } +} + +// Call executes a function and checks the returned err. +func Call(fn func() error) { + err := fn() + if err != nil { + log.Error(errors.ErrorStack(err)) + } +} + +// Log logs the error if it is not nil. +func Log(err error) { + if err != nil { + log.Error(errors.ErrorStack(err)) + } +} diff --git a/vendor/github.com/pingcap/parser/test.sh b/vendor/github.com/pingcap/parser/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..37733f4c4d667e4974c75e24047374059caa8d46 --- /dev/null +++ b/vendor/github.com/pingcap/parser/test.sh @@ -0,0 +1,11 @@ +{ + mv go.mod1 go.mod + mv go.sum1 go.sum + GO111MODULE=on go test ./... +} || { + mv go.mod go.mod1 + mv go.sum go.sum1 +} + +mv go.mod go.mod1 +mv go.sum go.sum1 diff --git a/vendor/github.com/pingcap/parser/types/etc.go b/vendor/github.com/pingcap/parser/types/etc.go new file mode 100644 index 0000000000000000000000000000000000000000..84b2966c55e67303da27641ac10d84c1fc306d72 --- /dev/null +++ b/vendor/github.com/pingcap/parser/types/etc.go @@ -0,0 +1,112 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "strings" + + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" +) + +// IsTypeBlob returns a boolean indicating whether the tp is a blob type. +func IsTypeBlob(tp byte) bool { + switch tp { + case mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob: + return true + default: + return false + } +} + +// IsTypeChar returns a boolean indicating +// whether the tp is the char type like a string type or a varchar type. +func IsTypeChar(tp byte) bool { + return tp == mysql.TypeString || tp == mysql.TypeVarchar +} + +var type2Str = map[byte]string{ + mysql.TypeBit: "bit", + mysql.TypeBlob: "text", + mysql.TypeDate: "date", + mysql.TypeDatetime: "datetime", + mysql.TypeDecimal: "unspecified", + mysql.TypeNewDecimal: "decimal", + mysql.TypeDouble: "double", + mysql.TypeEnum: "enum", + mysql.TypeFloat: "float", + mysql.TypeGeometry: "geometry", + mysql.TypeInt24: "mediumint", + mysql.TypeJSON: "json", + mysql.TypeLong: "int", + mysql.TypeLonglong: "bigint", + mysql.TypeLongBlob: "longtext", + mysql.TypeMediumBlob: "mediumtext", + mysql.TypeNull: "null", + mysql.TypeSet: "set", + mysql.TypeShort: "smallint", + mysql.TypeString: "char", + mysql.TypeDuration: "time", + mysql.TypeTimestamp: "timestamp", + mysql.TypeTiny: "tinyint", + mysql.TypeTinyBlob: "tinytext", + mysql.TypeVarchar: "varchar", + mysql.TypeVarString: "var_string", + mysql.TypeYear: "year", +} + +// TypeStr converts tp to a string. +func TypeStr(tp byte) (r string) { + return type2Str[tp] +} + +// TypeToStr converts a field to a string. +// It is used for converting Text to Blob, +// or converting Char to Binary. +// Args: +// tp: type enum +// cs: charset +func TypeToStr(tp byte, cs string) (r string) { + ts := type2Str[tp] + if cs != "binary" { + return ts + } + if IsTypeBlob(tp) { + ts = strings.Replace(ts, "text", "blob", 1) + } else if IsTypeChar(tp) { + ts = strings.Replace(ts, "char", "binary", 1) + } + return ts +} + +var ( + dig2bytes = [10]int{0, 1, 1, 2, 2, 3, 3, 4, 4, 4} +) + +// constant values. +const ( + digitsPerWord = 9 // A word holds 9 digits. + wordSize = 4 // A word is 4 bytes int32. +) + +const ( + codeInvalidDefault = terror.ErrCode(mysql.ErrInvalidDefault) +) + +// ErrInvalidDefault is returned when meet a invalid default value. +var ErrInvalidDefault = terror.ClassTypes.New(codeInvalidDefault, "Invalid default value for '%s'") diff --git a/vendor/github.com/pingcap/parser/types/eval_type.go b/vendor/github.com/pingcap/parser/types/eval_type.go new file mode 100644 index 0000000000000000000000000000000000000000..47775953d97c5be58659fd307b8136fa94f35090 --- /dev/null +++ b/vendor/github.com/pingcap/parser/types/eval_type.go @@ -0,0 +1,42 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +// EvalType indicates the specified types that arguments and result of a built-in function should be. +type EvalType byte + +const ( + // ETInt represents type INT in evaluation. + ETInt EvalType = iota + // ETReal represents type REAL in evaluation. + ETReal + // ETDecimal represents type DECIMAL in evaluation. + ETDecimal + // ETString represents type STRING in evaluation. + ETString + // ETDatetime represents type DATETIME in evaluation. + ETDatetime + // ETTimestamp represents type TIMESTAMP in evaluation. + ETTimestamp + // ETDuration represents type DURATION in evaluation. + ETDuration + // ETJson represents type JSON in evaluation. + ETJson +) + +// IsStringKind returns true for ETString, ETDatetime, ETTimestamp, ETDuration, ETJson EvalTypes. +func (et EvalType) IsStringKind() bool { + return et == ETString || et == ETDatetime || + et == ETTimestamp || et == ETDuration || et == ETJson +} diff --git a/vendor/github.com/pingcap/parser/types/field_type.go b/vendor/github.com/pingcap/parser/types/field_type.go new file mode 100644 index 0000000000000000000000000000000000000000..af2a2b29184be3e194778499833862df3467c46f --- /dev/null +++ b/vendor/github.com/pingcap/parser/types/field_type.go @@ -0,0 +1,258 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "io" + "strings" + + "github.com/pingcap/parser/charset" + "github.com/pingcap/parser/format" + "github.com/pingcap/parser/mysql" +) + +// UnspecifiedLength is unspecified length. +const ( + UnspecifiedLength = -1 +) + +// FieldType records field type information. +type FieldType struct { + Tp byte + Flag uint + Flen int + Decimal int + Charset string + Collate string + // Elems is the element list for enum and set type. + Elems []string +} + +// NewFieldType returns a FieldType, +// with a type and other information about field type. +func NewFieldType(tp byte) *FieldType { + return &FieldType{ + Tp: tp, + Flen: UnspecifiedLength, + Decimal: UnspecifiedLength, + } +} + +// Equal checks whether two FieldType objects are equal. +func (ft *FieldType) Equal(other *FieldType) bool { + // We do not need to compare whole `ft.Flag == other.Flag` when wrapping cast upon an Expression. + // but need compare unsigned_flag of ft.Flag. + partialEqual := ft.Tp == other.Tp && + ft.Flen == other.Flen && + ft.Decimal == other.Decimal && + ft.Charset == other.Charset && + ft.Collate == other.Collate && + mysql.HasUnsignedFlag(ft.Flag) == mysql.HasUnsignedFlag(other.Flag) + if !partialEqual || len(ft.Elems) != len(other.Elems) { + return false + } + for i := range ft.Elems { + if ft.Elems[i] != other.Elems[i] { + return false + } + } + return true +} + +// EvalType gets the type in evaluation. +func (ft *FieldType) EvalType() EvalType { + switch ft.Tp { + case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, + mysql.TypeBit, mysql.TypeYear: + return ETInt + case mysql.TypeFloat, mysql.TypeDouble: + return ETReal + case mysql.TypeNewDecimal: + return ETDecimal + case mysql.TypeDate, mysql.TypeDatetime: + return ETDatetime + case mysql.TypeTimestamp: + return ETTimestamp + case mysql.TypeDuration: + return ETDuration + case mysql.TypeJSON: + return ETJson + } + return ETString +} + +// Hybrid checks whether a type is a hybrid type, which can represent different types of value in specific context. +func (ft *FieldType) Hybrid() bool { + return ft.Tp == mysql.TypeEnum || ft.Tp == mysql.TypeBit || ft.Tp == mysql.TypeSet +} + +// Init initializes the FieldType data. +func (ft *FieldType) Init(tp byte) { + ft.Tp = tp + ft.Flen = UnspecifiedLength + ft.Decimal = UnspecifiedLength +} + +// CompactStr only considers Tp/CharsetBin/Flen/Deimal. +// This is used for showing column type in infoschema. +func (ft *FieldType) CompactStr() string { + ts := TypeToStr(ft.Tp, ft.Charset) + suffix := "" + + defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(ft.Tp) + isDecimalNotDefault := ft.Decimal != defaultDecimal && ft.Decimal != 0 && ft.Decimal != UnspecifiedLength + + // displayFlen and displayDecimal are flen and decimal values with `-1` substituted with default value. + displayFlen, displayDecimal := ft.Flen, ft.Decimal + if displayFlen == 0 || displayFlen == UnspecifiedLength { + displayFlen = defaultFlen + } + if displayDecimal == 0 || displayDecimal == UnspecifiedLength { + displayDecimal = defaultDecimal + } + + switch ft.Tp { + case mysql.TypeEnum, mysql.TypeSet: + // Format is ENUM ('e1', 'e2') or SET ('e1', 'e2') + es := make([]string, 0, len(ft.Elems)) + for _, e := range ft.Elems { + e = format.OutputFormat(e) + es = append(es, e) + } + suffix = fmt.Sprintf("('%s')", strings.Join(es, "','")) + case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDuration: + if isDecimalNotDefault { + suffix = fmt.Sprintf("(%d)", displayDecimal) + } + case mysql.TypeDouble, mysql.TypeFloat: + // 1. Flen Not Default, Decimal Not Default -> Valid + // 2. Flen Not Default, Decimal Default (-1) -> Invalid + // 3. Flen Default, Decimal Not Default -> Valid + // 4. Flen Default, Decimal Default -> Valid (hide) + if isDecimalNotDefault { + suffix = fmt.Sprintf("(%d,%d)", displayFlen, displayDecimal) + } + case mysql.TypeNewDecimal: + suffix = fmt.Sprintf("(%d,%d)", displayFlen, displayDecimal) + case mysql.TypeBit, mysql.TypeShort, mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeString, mysql.TypeVarString: + // Flen is always shown. + suffix = fmt.Sprintf("(%d)", displayFlen) + } + return ts + suffix +} + +// InfoSchemaStr joins the CompactStr with unsigned flag and +// returns a string. +func (ft *FieldType) InfoSchemaStr() string { + suffix := "" + if mysql.HasUnsignedFlag(ft.Flag) { + suffix = " unsigned" + } + return ft.CompactStr() + suffix +} + +// String joins the information of FieldType and returns a string. +// Note: when flen or decimal is unspecified, this function will use the default value instead of -1. +func (ft *FieldType) String() string { + strs := []string{ft.CompactStr()} + if mysql.HasUnsignedFlag(ft.Flag) { + strs = append(strs, "UNSIGNED") + } + if mysql.HasZerofillFlag(ft.Flag) { + strs = append(strs, "ZEROFILL") + } + if mysql.HasBinaryFlag(ft.Flag) && ft.Tp != mysql.TypeString { + strs = append(strs, "BINARY") + } + + if IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp) { + if ft.Charset != "" && ft.Charset != charset.CharsetBin { + strs = append(strs, fmt.Sprintf("CHARACTER SET %s", ft.Charset)) + } + if ft.Collate != "" && ft.Collate != charset.CharsetBin { + strs = append(strs, fmt.Sprintf("COLLATE %s", ft.Collate)) + } + } + + return strings.Join(strs, " ") +} + +// FormatAsCastType is used for write AST back to string. +func (ft *FieldType) FormatAsCastType(w io.Writer) { + switch ft.Tp { + case mysql.TypeVarString: + if ft.Charset == charset.CharsetBin && ft.Collate == charset.CollationBin { + fmt.Fprint(w, "BINARY") + } else { + fmt.Fprint(w, "CHAR") + } + if ft.Flen != UnspecifiedLength { + fmt.Fprintf(w, "(%d)", ft.Flen) + } + if ft.Flag&mysql.BinaryFlag != 0 { + fmt.Fprint(w, " BINARY") + } + if ft.Charset != charset.CharsetBin && ft.Charset != mysql.DefaultCharset { + fmt.Fprintf(w, " %s", ft.Charset) + } + case mysql.TypeDate: + fmt.Fprint(w, "DATE") + case mysql.TypeDatetime: + fmt.Fprint(w, "DATETIME") + if ft.Decimal > 0 { + fmt.Fprintf(w, "(%d)", ft.Decimal) + } + case mysql.TypeNewDecimal: + fmt.Fprint(w, "DECIMAL") + if ft.Flen > 0 && ft.Decimal > 0 { + fmt.Fprintf(w, "(%d, %d)", ft.Flen, ft.Decimal) + } else if ft.Flen > 0 { + fmt.Fprintf(w, "(%d)", ft.Flen) + } + case mysql.TypeDuration: + fmt.Fprint(w, "TIME") + if ft.Decimal > 0 { + fmt.Fprintf(w, "(%d)", ft.Decimal) + } + case mysql.TypeLonglong: + if ft.Flag&mysql.UnsignedFlag != 0 { + fmt.Fprint(w, "UNSIGNED") + } else { + fmt.Fprint(w, "SIGNED") + } + case mysql.TypeJSON: + fmt.Fprint(w, "JSON") + } +} + +// VarStorageLen indicates this column is a variable length column. +const VarStorageLen = -1 + +// StorageLength is the length of stored value for the type. +func (ft *FieldType) StorageLength() int { + switch ft.Tp { + case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, + mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeFloat, mysql.TypeYear, mysql.TypeDuration, + mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp, mysql.TypeEnum, mysql.TypeSet, + mysql.TypeBit: + // This may not be the accurate length, because we may encode them as varint. + return 8 + case mysql.TypeNewDecimal: + precision, frac := ft.Flen-ft.Decimal, ft.Decimal + return precision/digitsPerWord*wordSize + dig2bytes[precision%digitsPerWord] + frac/digitsPerWord*wordSize + dig2bytes[frac%digitsPerWord] + default: + return VarStorageLen + } +} diff --git a/vendor/github.com/pingcap/parser/yy_parser.go b/vendor/github.com/pingcap/parser/yy_parser.go new file mode 100644 index 0000000000000000000000000000000000000000..10a3208534043e42a5265b8b1188c2890eaf0f82 --- /dev/null +++ b/vendor/github.com/pingcap/parser/yy_parser.go @@ -0,0 +1,251 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "math" + "regexp" + "strconv" + "unicode" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" +) + +const ( + codeErrParse = terror.ErrCode(mysql.ErrParse) + codeErrSyntax = terror.ErrCode(mysql.ErrSyntax) +) + +var ( + // ErrSyntax returns for sql syntax error. + ErrSyntax = terror.ClassParser.New(codeErrSyntax, mysql.MySQLErrName[mysql.ErrSyntax]) + // ErrParse returns for sql parse error. + ErrParse = terror.ClassParser.New(codeErrParse, mysql.MySQLErrName[mysql.ErrParse]) + // SpecFieldPattern special result field pattern + SpecFieldPattern = regexp.MustCompile(`(\/\*!(M?[0-9]{5,6})?|\*\/)`) + specCodePattern = regexp.MustCompile(`\/\*!(M?[0-9]{5,6})?([^*]|\*+[^*/])*\*+\/`) + specCodeStart = regexp.MustCompile(`^\/\*!(M?[0-9]{5,6})?[ \t]*`) + specCodeEnd = regexp.MustCompile(`[ \t]*\*\/$`) +) + +func init() { + parserMySQLErrCodes := map[terror.ErrCode]uint16{ + codeErrSyntax: mysql.ErrSyntax, + codeErrParse: mysql.ErrParse, + } + terror.ErrClassToMySQLCodes[terror.ClassParser] = parserMySQLErrCodes +} + +// TrimComment trim comment for special comment code of MySQL. +func TrimComment(txt string) string { + txt = specCodeStart.ReplaceAllString(txt, "") + return specCodeEnd.ReplaceAllString(txt, "") +} + +// Parser represents a parser instance. Some temporary objects are stored in it to reduce object allocation during Parse function. +type Parser struct { + charset string + collation string + result []ast.StmtNode + src string + lexer Scanner + + // the following fields are used by yyParse to reduce allocation. + cache []yySymType + yylval yySymType + yyVAL yySymType +} + +type stmtTexter interface { + stmtText() string +} + +// New returns a Parser object. +func New() *Parser { + if ast.NewValueExpr == nil || + ast.NewParamMarkerExpr == nil || + ast.NewHexLiteral == nil || + ast.NewBitLiteral == nil { + panic("no parser driver (forgotten import?) https://github.com/pingcap/parser/issues/43") + } + + return &Parser{ + cache: make([]yySymType, 200), + } +} + +// Parse parses a query string to raw ast.StmtNode. +// If charset or collation is "", default charset and collation will be used. +func (parser *Parser) Parse(sql, charset, collation string) ([]ast.StmtNode, error) { + if charset == "" { + charset = mysql.DefaultCharset + } + if collation == "" { + collation = mysql.DefaultCollationName + } + parser.charset = charset + parser.collation = collation + parser.src = sql + parser.result = parser.result[:0] + + var l yyLexer + parser.lexer.reset(sql) + l = &parser.lexer + yyParse(l, parser) + + if len(l.Errors()) != 0 { + return nil, errors.Trace(l.Errors()[0]) + } + for _, stmt := range parser.result { + ast.SetFlag(stmt) + } + return parser.result, nil +} + +// ParseOneStmt parses a query and returns an ast.StmtNode. +// The query must have one statement, otherwise ErrSyntax is returned. +func (parser *Parser) ParseOneStmt(sql, charset, collation string) (ast.StmtNode, error) { + stmts, err := parser.Parse(sql, charset, collation) + if err != nil { + return nil, errors.Trace(err) + } + if len(stmts) != 1 { + return nil, ErrSyntax + } + ast.SetFlag(stmts[0]) + return stmts[0], nil +} + +// SetSQLMode sets the SQL mode for parser. +func (parser *Parser) SetSQLMode(mode mysql.SQLMode) { + parser.lexer.SetSQLMode(mode) +} + +// EnableWindowFunc enables the parser to parse syntax related with window function. +func (parser *Parser) EnableWindowFunc() { + parser.lexer.EnableWindowFunc() +} + +// ParseErrorWith returns "You have a syntax error near..." error message compatible with mysql. +func ParseErrorWith(errstr string, lineno int) error { + if len(errstr) > mysql.ErrTextLength { + errstr = errstr[:mysql.ErrTextLength] + } + return ErrParse.GenWithStackByArgs(mysql.MySQLErrName[mysql.ErrSyntax], errstr, lineno) +} + +// The select statement is not at the end of the whole statement, if the last +// field text was set from its offset to the end of the src string, update +// the last field text. +func (parser *Parser) setLastSelectFieldText(st *ast.SelectStmt, lastEnd int) { + lastField := st.Fields.Fields[len(st.Fields.Fields)-1] + if lastField.Offset+len(lastField.Text()) >= len(parser.src)-1 { + lastField.SetText(parser.src[lastField.Offset:lastEnd]) + } +} + +func (parser *Parser) startOffset(v *yySymType) int { + return v.offset +} + +func (parser *Parser) endOffset(v *yySymType) int { + offset := v.offset + for offset > 0 && unicode.IsSpace(rune(parser.src[offset-1])) { + offset-- + } + return offset +} + +func toInt(l yyLexer, lval *yySymType, str string) int { + n, err := strconv.ParseUint(str, 10, 64) + if err != nil { + e := err.(*strconv.NumError) + if e.Err == strconv.ErrRange { + // TODO: toDecimal maybe out of range still. + // This kind of error should be throw to higher level, because truncated data maybe legal. + // For example, this SQL returns error: + // create table test (id decimal(30, 0)); + // insert into test values(123456789012345678901234567890123094839045793405723406801943850); + // While this SQL: + // select 1234567890123456789012345678901230948390457934057234068019438509023041874359081325875128590860234789847359871045943057; + // get value 99999999999999999999999999999999999999999999999999999999999999999 + return toDecimal(l, lval, str) + } + l.Errorf("integer literal: %v", err) + return int(unicode.ReplacementChar) + } + + switch { + case n < math.MaxInt64: + lval.item = int64(n) + default: + lval.item = n + } + return intLit +} + +func toDecimal(l yyLexer, lval *yySymType, str string) int { + dec, err := ast.NewDecimal(str) + if err != nil { + l.Errorf("decimal literal: %v", err) + } + lval.item = dec + return decLit +} + +func toFloat(l yyLexer, lval *yySymType, str string) int { + n, err := strconv.ParseFloat(str, 64) + if err != nil { + l.Errorf("float literal: %v", err) + return int(unicode.ReplacementChar) + } + + lval.item = n + return floatLit +} + +// See https://dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html +func toHex(l yyLexer, lval *yySymType, str string) int { + h, err := ast.NewHexLiteral(str) + if err != nil { + l.Errorf("hex literal: %v", err) + return int(unicode.ReplacementChar) + } + lval.item = h + return hexLit +} + +// See https://dev.mysql.com/doc/refman/5.7/en/bit-type.html +func toBit(l yyLexer, lval *yySymType, str string) int { + b, err := ast.NewBitLiteral(str) + if err != nil { + l.Errorf("bit literal: %v", err) + return int(unicode.ReplacementChar) + } + lval.item = b + return bitLit +} + +func getUint64FromNUM(num interface{}) uint64 { + switch v := num.(type) { + case int64: + return uint64(v) + case uint64: + return v + } + return 0 +} diff --git a/vendor/github.com/pingcap/tidb/LICENSE b/vendor/github.com/pingcap/tidb/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..b67d9091009d10eac119854d30478c83218a70b4 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {} + + 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. diff --git a/vendor/github.com/pingcap/tidb/sessionctx/stmtctx/stmtctx.go b/vendor/github.com/pingcap/tidb/sessionctx/stmtctx/stmtctx.go new file mode 100644 index 0000000000000000000000000000000000000000..ef416642c2c6244285cd20de0e23f7628489649b --- /dev/null +++ b/vendor/github.com/pingcap/tidb/sessionctx/stmtctx/stmtctx.go @@ -0,0 +1,266 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package stmtctx + +import ( + "math" + "sync" + "time" + + "github.com/pingcap/parser/mysql" + "github.com/pingcap/tidb/util/execdetails" + "github.com/pingcap/tidb/util/memory" +) + +const ( + // WarnLevelError represents level "Error" for 'SHOW WARNINGS' syntax. + WarnLevelError = "Error" + // WarnLevelWarning represents level "Warning" for 'SHOW WARNINGS' syntax. + WarnLevelWarning = "Warning" + // WarnLevelNote represents level "Note" for 'SHOW WARNINGS' syntax. + WarnLevelNote = "Note" +) + +// SQLWarn relates a sql warning and it's level. +type SQLWarn struct { + Level string + Err error +} + +// StatementContext contains variables for a statement. +// It should be reset before executing a statement. +type StatementContext struct { + // Set the following variables before execution + + // IsDDLJobInQueue is used to mark whether the DDL job is put into the queue. + // If IsDDLJobInQueue is true, it means the DDL job is in the queue of storage, and it can be handled by the DDL worker. + IsDDLJobInQueue bool + InInsertStmt bool + InUpdateOrDeleteStmt bool + InSelectStmt bool + IgnoreTruncate bool + IgnoreZeroInDate bool + DupKeyAsWarning bool + BadNullAsWarning bool + DividedByZeroAsWarning bool + TruncateAsWarning bool + OverflowAsWarning bool + InShowWarning bool + UseCache bool + PadCharToFullLength bool + BatchCheck bool + InNullRejectCheck bool + + // mu struct holds variables that change during execution. + mu struct { + sync.Mutex + affectedRows uint64 + foundRows uint64 + warnings []SQLWarn + histogramsNotLoad bool + execDetails execdetails.ExecDetails + } + + // Copied from SessionVars.TimeZone. + TimeZone *time.Location + Priority mysql.PriorityEnum + NotFillCache bool + MemTracker *memory.Tracker + RuntimeStatsColl *execdetails.RuntimeStatsColl + TableIDs []int64 + IndexIDs []int64 + NowTs time.Time + SysTs time.Time +} + +// AddAffectedRows adds affected rows. +func (sc *StatementContext) AddAffectedRows(rows uint64) { + sc.mu.Lock() + sc.mu.affectedRows += rows + sc.mu.Unlock() +} + +// AffectedRows gets affected rows. +func (sc *StatementContext) AffectedRows() uint64 { + sc.mu.Lock() + rows := sc.mu.affectedRows + sc.mu.Unlock() + return rows +} + +// FoundRows gets found rows. +func (sc *StatementContext) FoundRows() uint64 { + sc.mu.Lock() + rows := sc.mu.foundRows + sc.mu.Unlock() + return rows +} + +// AddFoundRows adds found rows. +func (sc *StatementContext) AddFoundRows(rows uint64) { + sc.mu.Lock() + sc.mu.foundRows += rows + sc.mu.Unlock() +} + +// GetWarnings gets warnings. +func (sc *StatementContext) GetWarnings() []SQLWarn { + sc.mu.Lock() + warns := make([]SQLWarn, len(sc.mu.warnings)) + copy(warns, sc.mu.warnings) + sc.mu.Unlock() + return warns +} + +// WarningCount gets warning count. +func (sc *StatementContext) WarningCount() uint16 { + if sc.InShowWarning { + return 0 + } + sc.mu.Lock() + wc := uint16(len(sc.mu.warnings)) + sc.mu.Unlock() + return wc +} + +// NumWarnings gets warning count. It's different from `WarningCount` in that +// `WarningCount` return the warning count of the last executed command, so if +// the last command is a SHOW statement, `WarningCount` return 0. On the other +// hand, `NumWarnings` always return number of warnings(or errors if `errOnly` +// is set). +func (sc *StatementContext) NumWarnings(errOnly bool) uint16 { + var wc uint16 + sc.mu.Lock() + defer sc.mu.Unlock() + if errOnly { + for _, warn := range sc.mu.warnings { + if warn.Level == WarnLevelError { + wc++ + } + } + } else { + wc = uint16(len(sc.mu.warnings)) + } + return wc +} + +// SetWarnings sets warnings. +func (sc *StatementContext) SetWarnings(warns []SQLWarn) { + sc.mu.Lock() + sc.mu.warnings = warns + sc.mu.Unlock() +} + +// AppendWarning appends a warning with level 'Warning'. +func (sc *StatementContext) AppendWarning(warn error) { + sc.mu.Lock() + if len(sc.mu.warnings) < math.MaxUint16 { + sc.mu.warnings = append(sc.mu.warnings, SQLWarn{WarnLevelWarning, warn}) + } + sc.mu.Unlock() +} + +// AppendNote appends a warning with level 'Note'. +func (sc *StatementContext) AppendNote(warn error) { + sc.mu.Lock() + if len(sc.mu.warnings) < math.MaxUint16 { + sc.mu.warnings = append(sc.mu.warnings, SQLWarn{WarnLevelNote, warn}) + } + sc.mu.Unlock() +} + +// AppendError appends a warning with level 'Error'. +func (sc *StatementContext) AppendError(warn error) { + sc.mu.Lock() + if len(sc.mu.warnings) < math.MaxUint16 { + sc.mu.warnings = append(sc.mu.warnings, SQLWarn{WarnLevelError, warn}) + } + sc.mu.Unlock() +} + +// SetHistogramsNotLoad sets histogramsNotLoad. +func (sc *StatementContext) SetHistogramsNotLoad() { + sc.mu.Lock() + sc.mu.histogramsNotLoad = true + sc.mu.Unlock() +} + +// HistogramsNotLoad gets histogramsNotLoad. +func (sc *StatementContext) HistogramsNotLoad() bool { + sc.mu.Lock() + notLoad := sc.mu.histogramsNotLoad + sc.mu.Unlock() + return notLoad +} + +// HandleTruncate ignores or returns the error based on the StatementContext state. +func (sc *StatementContext) HandleTruncate(err error) error { + // TODO: At present we have not checked whether the error can be ignored or treated as warning. + // We will do that later, and then append WarnDataTruncated instead of the error itself. + if err == nil { + return nil + } + if sc.IgnoreTruncate { + return nil + } + if sc.TruncateAsWarning { + sc.AppendWarning(err) + return nil + } + return err +} + +// HandleOverflow treats ErrOverflow as warnings or returns the error based on the StmtCtx.OverflowAsWarning state. +func (sc *StatementContext) HandleOverflow(err error, warnErr error) error { + if err == nil { + return nil + } + + if sc.OverflowAsWarning { + sc.AppendWarning(warnErr) + return nil + } + return err +} + +// ResetForRetry resets the changed states during execution. +func (sc *StatementContext) ResetForRetry() { + sc.mu.Lock() + sc.mu.affectedRows = 0 + sc.mu.foundRows = 0 + sc.mu.warnings = nil + sc.mu.Unlock() +} + +// MergeExecDetails merges a single region execution details into self, used to print +// the information in slow query log. +func (sc *StatementContext) MergeExecDetails(details *execdetails.ExecDetails) { + sc.mu.Lock() + sc.mu.execDetails.ProcessTime += details.ProcessTime + sc.mu.execDetails.WaitTime += details.WaitTime + sc.mu.execDetails.BackoffTime += details.BackoffTime + sc.mu.execDetails.RequestCount++ + sc.mu.execDetails.TotalKeys += details.TotalKeys + sc.mu.execDetails.ProcessedKeys += details.ProcessedKeys + sc.mu.Unlock() +} + +// GetExecDetails gets the execution details for the statement. +func (sc *StatementContext) GetExecDetails() execdetails.ExecDetails { + var details execdetails.ExecDetails + sc.mu.Lock() + details = sc.mu.execDetails + sc.mu.Unlock() + return details +} diff --git a/vendor/github.com/pingcap/tidb/types/binary_literal.go b/vendor/github.com/pingcap/tidb/types/binary_literal.go new file mode 100644 index 0000000000000000000000000000000000000000..91d85b98e6559d75e7c0e1a583ffc91bc64c21df --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/binary_literal.go @@ -0,0 +1,227 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "math" + "strconv" + "strings" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/sessionctx/stmtctx" +) + +// BinaryLiteral is the internal type for storing bit / hex literal type. +type BinaryLiteral []byte + +// BitLiteral is the bit literal type. +type BitLiteral BinaryLiteral + +// HexLiteral is the hex literal type. +type HexLiteral BinaryLiteral + +// ZeroBinaryLiteral is a BinaryLiteral literal with zero value. +var ZeroBinaryLiteral = BinaryLiteral{} + +func trimLeadingZeroBytes(bytes []byte) []byte { + if len(bytes) == 0 { + return bytes + } + pos, posMax := 0, len(bytes)-1 + for ; pos < posMax; pos++ { + if bytes[pos] != 0 { + break + } + } + return bytes[pos:] +} + +// NewBinaryLiteralFromUint creates a new BinaryLiteral instance by the given uint value in BitEndian. +// byteSize will be used as the length of the new BinaryLiteral, with leading bytes filled to zero. +// If byteSize is -1, the leading zeros in new BinaryLiteral will be trimmed. +func NewBinaryLiteralFromUint(value uint64, byteSize int) BinaryLiteral { + if byteSize != -1 && (byteSize < 1 || byteSize > 8) { + panic("Invalid byteSize") + } + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, value) + if byteSize == -1 { + buf = trimLeadingZeroBytes(buf) + } else { + buf = buf[8-byteSize:] + } + return buf +} + +// String implements fmt.Stringer interface. +func (b BinaryLiteral) String() string { + if len(b) == 0 { + return "" + } + return "0x" + hex.EncodeToString(b) +} + +// ToString returns the string representation for the literal. +func (b BinaryLiteral) ToString() string { + return string(b) +} + +// ToBitLiteralString returns the bit literal representation for the literal. +func (b BinaryLiteral) ToBitLiteralString(trimLeadingZero bool) string { + if len(b) == 0 { + return "b''" + } + var buf bytes.Buffer + for _, data := range b { + fmt.Fprintf(&buf, "%08b", data) + } + ret := buf.Bytes() + if trimLeadingZero { + ret = bytes.TrimLeft(ret, "0") + if len(ret) == 0 { + ret = []byte{'0'} + } + } + return fmt.Sprintf("b'%s'", string(ret)) +} + +// ToInt returns the int value for the literal. +func (b BinaryLiteral) ToInt(sc *stmtctx.StatementContext) (uint64, error) { + buf := trimLeadingZeroBytes(b) + length := len(buf) + if length == 0 { + return 0, nil + } + if length > 8 { + var err error = ErrTruncatedWrongVal.GenWithStackByArgs("BINARY", b) + if sc != nil { + err = sc.HandleTruncate(err) + } + return math.MaxUint64, err + } + // Note: the byte-order is BigEndian. + val := uint64(buf[0]) + for i := 1; i < length; i++ { + val = (val << 8) | uint64(buf[i]) + } + return val, nil +} + +// Compare compares BinaryLiteral to another one +func (b BinaryLiteral) Compare(b2 BinaryLiteral) int { + bufB := trimLeadingZeroBytes(b) + bufB2 := trimLeadingZeroBytes(b2) + if len(bufB) > len(bufB2) { + return 1 + } + if len(bufB) < len(bufB2) { + return -1 + } + return bytes.Compare(bufB, bufB2) +} + +// ParseBitStr parses bit string. +// The string format can be b'val', B'val' or 0bval, val must be 0 or 1. +// See https://dev.mysql.com/doc/refman/5.7/en/bit-value-literals.html +func ParseBitStr(s string) (BinaryLiteral, error) { + if len(s) == 0 { + return nil, errors.Errorf("invalid empty string for parsing bit type") + } + + if s[0] == 'b' || s[0] == 'B' { + // format is b'val' or B'val' + s = strings.Trim(s[1:], "'") + } else if strings.HasPrefix(s, "0b") { + s = s[2:] + } else { + // here means format is not b'val', B'val' or 0bval. + return nil, errors.Errorf("invalid bit type format %s", s) + } + + if len(s) == 0 { + return ZeroBinaryLiteral, nil + } + + alignedLength := (len(s) + 7) &^ 7 + s = ("00000000" + s)[len(s)+8-alignedLength:] // Pad with zero (slice from `-alignedLength`) + byteLength := len(s) >> 3 + buf := make([]byte, byteLength) + + for i := 0; i < byteLength; i++ { + strPosition := i << 3 + val, err := strconv.ParseUint(s[strPosition:strPosition+8], 2, 8) + if err != nil { + return nil, errors.Trace(err) + } + buf[i] = byte(val) + } + + return buf, nil +} + +// NewBitLiteral parses bit string as BitLiteral type. +func NewBitLiteral(s string) (BitLiteral, error) { + b, err := ParseBitStr(s) + if err != nil { + return BitLiteral{}, err + } + return BitLiteral(b), nil +} + +// ParseHexStr parses hexadecimal string literal. +// See https://dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html +func ParseHexStr(s string) (BinaryLiteral, error) { + if len(s) == 0 { + return nil, errors.Errorf("invalid empty string for parsing hexadecimal literal") + } + + if s[0] == 'x' || s[0] == 'X' { + // format is x'val' or X'val' + s = strings.Trim(s[1:], "'") + if len(s)%2 != 0 { + return nil, errors.Errorf("invalid hexadecimal format, must even numbers, but %d", len(s)) + } + } else if strings.HasPrefix(s, "0x") { + s = s[2:] + } else { + // here means format is not x'val', X'val' or 0xval. + return nil, errors.Errorf("invalid hexadecimal format %s", s) + } + + if len(s) == 0 { + return ZeroBinaryLiteral, nil + } + + if len(s)%2 != 0 { + s = "0" + s + } + buf, err := hex.DecodeString(s) + if err != nil { + return nil, errors.Trace(err) + } + return buf, nil +} + +// NewHexLiteral parses hexadecimal string as HexLiteral type. +func NewHexLiteral(s string) (HexLiteral, error) { + h, err := ParseHexStr(s) + if err != nil { + return HexLiteral{}, err + } + return HexLiteral(h), nil +} diff --git a/vendor/github.com/pingcap/tidb/types/compare.go b/vendor/github.com/pingcap/tidb/types/compare.go new file mode 100644 index 0000000000000000000000000000000000000000..6774d6f351d6790161d59bbc6a62e9cb6d79b4ef --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/compare.go @@ -0,0 +1,58 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +// CompareInt64 returns an integer comparing the int64 x to y. +func CompareInt64(x, y int64) int { + if x < y { + return -1 + } else if x == y { + return 0 + } + + return 1 +} + +// CompareUint64 returns an integer comparing the uint64 x to y. +func CompareUint64(x, y uint64) int { + if x < y { + return -1 + } else if x == y { + return 0 + } + + return 1 +} + +// CompareFloat64 returns an integer comparing the float64 x to y. +func CompareFloat64(x, y float64) int { + if x < y { + return -1 + } else if x == y { + return 0 + } + + return 1 +} + +// CompareString returns an integer comparing the string x to y. +func CompareString(x, y string) int { + if x < y { + return -1 + } else if x == y { + return 0 + } + + return 1 +} diff --git a/vendor/github.com/pingcap/tidb/types/convert.go b/vendor/github.com/pingcap/tidb/types/convert.go new file mode 100644 index 0000000000000000000000000000000000000000..27df51b7719977fc1dd9379e764747966b76b5dd --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/convert.go @@ -0,0 +1,535 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "math" + "strconv" + "strings" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/types/json" + "github.com/pingcap/tidb/util/hack" +) + +func truncateStr(str string, flen int) string { + if flen != UnspecifiedLength && len(str) > flen { + str = str[:flen] + } + return str +} + +// UnsignedUpperBound indicates the max uint64 values of different mysql types. +var UnsignedUpperBound = map[byte]uint64{ + mysql.TypeTiny: math.MaxUint8, + mysql.TypeShort: math.MaxUint16, + mysql.TypeInt24: mysql.MaxUint24, + mysql.TypeLong: math.MaxUint32, + mysql.TypeLonglong: math.MaxUint64, + mysql.TypeBit: math.MaxUint64, + mysql.TypeEnum: math.MaxUint64, + mysql.TypeSet: math.MaxUint64, +} + +// SignedUpperBound indicates the max int64 values of different mysql types. +var SignedUpperBound = map[byte]int64{ + mysql.TypeTiny: math.MaxInt8, + mysql.TypeShort: math.MaxInt16, + mysql.TypeInt24: mysql.MaxInt24, + mysql.TypeLong: math.MaxInt32, + mysql.TypeLonglong: math.MaxInt64, +} + +// SignedLowerBound indicates the min int64 values of different mysql types. +var SignedLowerBound = map[byte]int64{ + mysql.TypeTiny: math.MinInt8, + mysql.TypeShort: math.MinInt16, + mysql.TypeInt24: mysql.MinInt24, + mysql.TypeLong: math.MinInt32, + mysql.TypeLonglong: math.MinInt64, +} + +// ConvertFloatToInt converts a float64 value to a int value. +func ConvertFloatToInt(fval float64, lowerBound, upperBound int64, tp byte) (int64, error) { + val := RoundFloat(fval) + if val < float64(lowerBound) { + return lowerBound, overflow(val, tp) + } + + if val >= float64(upperBound) { + if val == float64(upperBound) { + return upperBound, nil + } + return upperBound, overflow(val, tp) + } + return int64(val), nil +} + +// ConvertIntToInt converts an int value to another int value of different precision. +func ConvertIntToInt(val int64, lowerBound int64, upperBound int64, tp byte) (int64, error) { + if val < lowerBound { + return lowerBound, overflow(val, tp) + } + + if val > upperBound { + return upperBound, overflow(val, tp) + } + + return val, nil +} + +// ConvertUintToInt converts an uint value to an int value. +func ConvertUintToInt(val uint64, upperBound int64, tp byte) (int64, error) { + if val > uint64(upperBound) { + return upperBound, overflow(val, tp) + } + + return int64(val), nil +} + +// ConvertIntToUint converts an int value to an uint value. +func ConvertIntToUint(val int64, upperBound uint64, tp byte) (uint64, error) { + if uint64(val) > upperBound { + return upperBound, overflow(val, tp) + } + + return uint64(val), nil +} + +// ConvertUintToUint converts an uint value to another uint value of different precision. +func ConvertUintToUint(val uint64, upperBound uint64, tp byte) (uint64, error) { + if val > upperBound { + return upperBound, overflow(val, tp) + } + + return val, nil +} + +// ConvertFloatToUint converts a float value to an uint value. +func ConvertFloatToUint(fval float64, upperBound uint64, tp byte) (uint64, error) { + val := RoundFloat(fval) + if val < 0 { + return uint64(int64(val)), overflow(val, tp) + } + + if val > float64(upperBound) { + return upperBound, overflow(val, tp) + } + return uint64(val), nil +} + +// StrToInt converts a string to an integer at the best-effort. +func StrToInt(sc *stmtctx.StatementContext, str string) (int64, error) { + str = strings.TrimSpace(str) + validPrefix, err := getValidIntPrefix(sc, str) + iVal, err1 := strconv.ParseInt(validPrefix, 10, 64) + if err1 != nil { + return iVal, ErrOverflow.GenWithStackByArgs("BIGINT", validPrefix) + } + return iVal, errors.Trace(err) +} + +// StrToUint converts a string to an unsigned integer at the best-effortt. +func StrToUint(sc *stmtctx.StatementContext, str string) (uint64, error) { + str = strings.TrimSpace(str) + validPrefix, err := getValidIntPrefix(sc, str) + if validPrefix[0] == '+' { + validPrefix = validPrefix[1:] + } + uVal, err1 := strconv.ParseUint(validPrefix, 10, 64) + if err1 != nil { + return uVal, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", validPrefix) + } + return uVal, errors.Trace(err) +} + +// StrToDateTime converts str to MySQL DateTime. +func StrToDateTime(sc *stmtctx.StatementContext, str string, fsp int) (Time, error) { + return ParseTime(sc, str, mysql.TypeDatetime, fsp) +} + +// StrToDuration converts str to Duration. It returns Duration in normal case, +// and returns Time when str is in datetime format. +// when isDuration is true, the d is returned, when it is false, the t is returned. +// See https://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html. +func StrToDuration(sc *stmtctx.StatementContext, str string, fsp int) (d Duration, t Time, isDuration bool, err error) { + str = strings.TrimSpace(str) + length := len(str) + if length > 0 && str[0] == '-' { + length-- + } + // Timestamp format is 'YYYYMMDDHHMMSS' or 'YYMMDDHHMMSS', which length is 12. + // See #3923, it explains what we do here. + if length >= 12 { + t, err = StrToDateTime(sc, str, fsp) + if err == nil { + return d, t, false, nil + } + } + + d, err = ParseDuration(sc, str, fsp) + if ErrTruncatedWrongVal.Equal(err) { + err = sc.HandleTruncate(err) + } + return d, t, true, errors.Trace(err) +} + +// NumberToDuration converts number to Duration. +func NumberToDuration(number int64, fsp int) (Duration, error) { + if number > TimeMaxValue { + // Try to parse DATETIME. + if number >= 10000000000 { // '2001-00-00 00-00-00' + if t, err := ParseDatetimeFromNum(nil, number); err == nil { + dur, err1 := t.ConvertToDuration() + return dur, errors.Trace(err1) + } + } + dur, err1 := MaxMySQLTime(fsp).ConvertToDuration() + terror.Log(err1) + return dur, ErrOverflow.GenWithStackByArgs("Duration", strconv.Itoa(int(number))) + } else if number < -TimeMaxValue { + dur, err1 := MaxMySQLTime(fsp).ConvertToDuration() + terror.Log(err1) + dur.Duration = -dur.Duration + return dur, ErrOverflow.GenWithStackByArgs("Duration", strconv.Itoa(int(number))) + } + var neg bool + if neg = number < 0; neg { + number = -number + } + + if number/10000 > TimeMaxHour || number%100 >= 60 || (number/100)%100 >= 60 { + return ZeroDuration, errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(number)) + } + t := Time{Time: FromDate(0, 0, 0, int(number/10000), int((number/100)%100), int(number%100), 0), Type: mysql.TypeDuration, Fsp: fsp} + dur, err := t.ConvertToDuration() + if err != nil { + return ZeroDuration, errors.Trace(err) + } + if neg { + dur.Duration = -dur.Duration + } + return dur, nil +} + +// getValidIntPrefix gets prefix of the string which can be successfully parsed as int. +func getValidIntPrefix(sc *stmtctx.StatementContext, str string) (string, error) { + floatPrefix, err := getValidFloatPrefix(sc, str) + if err != nil { + return floatPrefix, errors.Trace(err) + } + return floatStrToIntStr(sc, floatPrefix, str) +} + +// roundIntStr is to round int string base on the number following dot. +func roundIntStr(numNextDot byte, intStr string) string { + if numNextDot < '5' { + return intStr + } + retStr := []byte(intStr) + for i := len(intStr) - 1; i >= 0; i-- { + if retStr[i] != '9' { + retStr[i]++ + break + } + if i == 0 { + retStr[i] = '1' + retStr = append(retStr, '0') + break + } + retStr[i] = '0' + } + return string(retStr) +} + +// floatStrToIntStr converts a valid float string into valid integer string which can be parsed by +// strconv.ParseInt, we can't parse float first then convert it to string because precision will +// be lost. For example, the string value "18446744073709551615" which is the max number of unsigned +// int will cause some precision to lose. intStr[0] may be a positive and negative sign like '+' or '-'. +func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr string) (intStr string, _ error) { + var dotIdx = -1 + var eIdx = -1 + for i := 0; i < len(validFloat); i++ { + switch validFloat[i] { + case '.': + dotIdx = i + case 'e', 'E': + eIdx = i + } + } + if eIdx == -1 { + if dotIdx == -1 { + return validFloat, nil + } + var digits []byte + if validFloat[0] == '-' || validFloat[0] == '+' { + dotIdx-- + digits = []byte(validFloat[1:]) + } else { + digits = []byte(validFloat) + } + if dotIdx == 0 { + intStr = "0" + } else { + intStr = string(digits)[:dotIdx] + } + if len(digits) > dotIdx+1 { + intStr = roundIntStr(digits[dotIdx+1], intStr) + } + if (len(intStr) > 1 || intStr[0] != '0') && validFloat[0] == '-' { + intStr = "-" + intStr + } + return intStr, nil + } + var intCnt int + digits := make([]byte, 0, len(validFloat)) + if dotIdx == -1 { + digits = append(digits, validFloat[:eIdx]...) + intCnt = len(digits) + } else { + digits = append(digits, validFloat[:dotIdx]...) + intCnt = len(digits) + digits = append(digits, validFloat[dotIdx+1:eIdx]...) + } + exp, err := strconv.Atoi(validFloat[eIdx+1:]) + if err != nil { + return validFloat, errors.Trace(err) + } + if exp > 0 && int64(intCnt) > (math.MaxInt64-int64(exp)) { + // (exp + incCnt) overflows MaxInt64. + sc.AppendWarning(ErrOverflow.GenWithStackByArgs("BIGINT", oriStr)) + return validFloat[:eIdx], nil + } + intCnt += exp + if intCnt <= 0 { + intStr = "0" + if intCnt == 0 && len(digits) > 0 { + dotIdx = -1 + intStr = roundIntStr(digits[0], intStr) + } + return intStr, nil + } + if intCnt == 1 && (digits[0] == '-' || digits[0] == '+') { + intStr = "0" + dotIdx = 0 + if len(digits) > 1 { + intStr = roundIntStr(digits[1], intStr) + } + if intStr[0] == '1' { + intStr = string(digits[:1]) + intStr + } + return intStr, nil + } + if intCnt <= len(digits) { + intStr = string(digits[:intCnt]) + if intCnt < len(digits) { + intStr = roundIntStr(digits[intCnt], intStr) + } + } else { + // convert scientific notation decimal number + extraZeroCount := intCnt - len(digits) + if extraZeroCount > 20 { + // Append overflow warning and return to avoid allocating too much memory. + sc.AppendWarning(ErrOverflow.GenWithStackByArgs("BIGINT", oriStr)) + return validFloat[:eIdx], nil + } + intStr = string(digits) + strings.Repeat("0", extraZeroCount) + } + return intStr, nil +} + +// StrToFloat converts a string to a float64 at the best-effort. +func StrToFloat(sc *stmtctx.StatementContext, str string) (float64, error) { + str = strings.TrimSpace(str) + validStr, err := getValidFloatPrefix(sc, str) + f, err1 := strconv.ParseFloat(validStr, 64) + if err1 != nil { + if err2, ok := err1.(*strconv.NumError); ok { + // value will truncate to MAX/MIN if out of range. + if err2.Err == strconv.ErrRange { + err1 = sc.HandleTruncate(ErrTruncatedWrongVal.GenWithStackByArgs("DOUBLE", str)) + if math.IsInf(f, 1) { + f = math.MaxFloat64 + } else if math.IsInf(f, -1) { + f = -math.MaxFloat64 + } + } + } + return f, errors.Trace(err1) + } + return f, errors.Trace(err) +} + +// ConvertJSONToInt casts JSON into int64. +func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned bool) (int64, error) { + switch j.TypeCode { + case json.TypeCodeObject, json.TypeCodeArray: + return 0, nil + case json.TypeCodeLiteral: + switch j.Value[0] { + case json.LiteralNil, json.LiteralFalse: + return 0, nil + default: + return 1, nil + } + case json.TypeCodeInt64, json.TypeCodeUint64: + return j.GetInt64(), nil + case json.TypeCodeFloat64: + f := j.GetFloat64() + if !unsigned { + lBound := SignedLowerBound[mysql.TypeLonglong] + uBound := SignedUpperBound[mysql.TypeLonglong] + return ConvertFloatToInt(f, lBound, uBound, mysql.TypeDouble) + } + bound := UnsignedUpperBound[mysql.TypeLonglong] + u, err := ConvertFloatToUint(f, bound, mysql.TypeDouble) + return int64(u), errors.Trace(err) + case json.TypeCodeString: + return StrToInt(sc, hack.String(j.GetString())) + } + return 0, errors.New("Unknown type code in JSON") +} + +// ConvertJSONToFloat casts JSON into float64. +func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float64, error) { + switch j.TypeCode { + case json.TypeCodeObject, json.TypeCodeArray: + return 0, nil + case json.TypeCodeLiteral: + switch j.Value[0] { + case json.LiteralNil, json.LiteralFalse: + return 0, nil + default: + return 1, nil + } + case json.TypeCodeInt64: + return float64(j.GetInt64()), nil + case json.TypeCodeUint64: + u, err := ConvertIntToUint(j.GetInt64(), UnsignedUpperBound[mysql.TypeLonglong], mysql.TypeLonglong) + return float64(u), errors.Trace(err) + case json.TypeCodeFloat64: + return j.GetFloat64(), nil + case json.TypeCodeString: + return StrToFloat(sc, hack.String(j.GetString())) + } + return 0, errors.New("Unknown type code in JSON") +} + +// ConvertJSONToDecimal casts JSON into decimal. +func ConvertJSONToDecimal(sc *stmtctx.StatementContext, j json.BinaryJSON) (*MyDecimal, error) { + res := new(MyDecimal) + if j.TypeCode != json.TypeCodeString { + f64, err := ConvertJSONToFloat(sc, j) + if err != nil { + return res, errors.Trace(err) + } + err = res.FromFloat64(f64) + return res, errors.Trace(err) + } + err := sc.HandleTruncate(res.FromString([]byte(j.GetString()))) + return res, errors.Trace(err) +} + +// getValidFloatPrefix gets prefix of string which can be successfully parsed as float. +func getValidFloatPrefix(sc *stmtctx.StatementContext, s string) (valid string, err error) { + var ( + sawDot bool + sawDigit bool + validLen int + eIdx int + ) + for i := 0; i < len(s); i++ { + c := s[i] + if c == '+' || c == '-' { + if i != 0 && i != eIdx+1 { // "1e+1" is valid. + break + } + } else if c == '.' { + if sawDot || eIdx > 0 { // "1.1." or "1e1.1" + break + } + sawDot = true + if sawDigit { // "123." is valid. + validLen = i + 1 + } + } else if c == 'e' || c == 'E' { + if !sawDigit { // "+.e" + break + } + if eIdx != 0 { // "1e5e" + break + } + eIdx = i + } else if c < '0' || c > '9' { + break + } else { + sawDigit = true + validLen = i + 1 + } + } + valid = s[:validLen] + if valid == "" { + valid = "0" + } + if validLen == 0 || validLen != len(s) { + err = errors.Trace(handleTruncateError(sc)) + } + return valid, err +} + +// ToString converts an interface to a string. +func ToString(value interface{}) (string, error) { + switch v := value.(type) { + case bool: + if v { + return "1", nil + } + return "0", nil + case int: + return strconv.FormatInt(int64(v), 10), nil + case int64: + return strconv.FormatInt(v, 10), nil + case uint64: + return strconv.FormatUint(v, 10), nil + case float32: + return strconv.FormatFloat(float64(v), 'f', -1, 32), nil + case float64: + return strconv.FormatFloat(v, 'f', -1, 64), nil + case string: + return v, nil + case []byte: + return string(v), nil + case Time: + return v.String(), nil + case Duration: + return v.String(), nil + case *MyDecimal: + return v.String(), nil + case BinaryLiteral: + return v.ToString(), nil + case Enum: + return v.String(), nil + case Set: + return v.String(), nil + default: + return "", errors.Errorf("cannot convert %v(type %T) to string", value, value) + } +} diff --git a/vendor/github.com/pingcap/tidb/types/datum.go b/vendor/github.com/pingcap/tidb/types/datum.go new file mode 100644 index 0000000000000000000000000000000000000000..20f70a50ad19ad8450e2967a5251de092f6b0fd2 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/datum.go @@ -0,0 +1,1895 @@ +// Copyright 2016 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "math" + "sort" + "strconv" + "strings" + "time" + "unicode/utf8" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/charset" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/types/json" + "github.com/pingcap/tidb/util/hack" + log "github.com/sirupsen/logrus" +) + +// Kind constants. +const ( + KindNull byte = 0 + KindInt64 byte = 1 + KindUint64 byte = 2 + KindFloat32 byte = 3 + KindFloat64 byte = 4 + KindString byte = 5 + KindBytes byte = 6 + KindBinaryLiteral byte = 7 // Used for BIT / HEX literals. + KindMysqlDecimal byte = 8 + KindMysqlDuration byte = 9 + KindMysqlEnum byte = 10 + KindMysqlBit byte = 11 // Used for BIT table column values. + KindMysqlSet byte = 12 + KindMysqlTime byte = 13 + KindInterface byte = 14 + KindMinNotNull byte = 15 + KindMaxValue byte = 16 + KindRaw byte = 17 + KindMysqlJSON byte = 18 +) + +// Datum is a data box holds different kind of data. +// It has better performance and is easier to use than `interface{}`. +type Datum struct { + k byte // datum kind. + collation uint8 // collation can hold uint8 values. + decimal uint16 // decimal can hold uint16 values. + length uint32 // length can hold uint32 values. + i int64 // i can hold int64 uint64 float64 values. + b []byte // b can hold string or []byte values. + x interface{} // x hold all other types. +} + +// Copy deep copies a Datum. +func (d *Datum) Copy() *Datum { + ret := *d + if d.b != nil { + ret.b = make([]byte, len(d.b)) + copy(ret.b, d.b) + } + switch ret.Kind() { + case KindMysqlDecimal: + d := *d.GetMysqlDecimal() + ret.SetMysqlDecimal(&d) + case KindMysqlTime: + ret.SetMysqlTime(d.GetMysqlTime()) + } + return &ret +} + +// Kind gets the kind of the datum. +func (d *Datum) Kind() byte { + return d.k +} + +// Collation gets the collation of the datum. +func (d *Datum) Collation() byte { + return d.collation +} + +// SetCollation sets the collation of the datum. +func (d *Datum) SetCollation(collation byte) { + d.collation = collation +} + +// Frac gets the frac of the datum. +func (d *Datum) Frac() int { + return int(d.decimal) +} + +// SetFrac sets the frac of the datum. +func (d *Datum) SetFrac(frac int) { + d.decimal = uint16(frac) +} + +// Length gets the length of the datum. +func (d *Datum) Length() int { + return int(d.length) +} + +// SetLength sets the length of the datum. +func (d *Datum) SetLength(l int) { + d.length = uint32(l) +} + +// IsNull checks if datum is null. +func (d *Datum) IsNull() bool { + return d.k == KindNull +} + +// GetInt64 gets int64 value. +func (d *Datum) GetInt64() int64 { + return d.i +} + +// SetInt64 sets int64 value. +func (d *Datum) SetInt64(i int64) { + d.k = KindInt64 + d.i = i +} + +// GetUint64 gets uint64 value. +func (d *Datum) GetUint64() uint64 { + return uint64(d.i) +} + +// SetUint64 sets uint64 value. +func (d *Datum) SetUint64(i uint64) { + d.k = KindUint64 + d.i = int64(i) +} + +// GetFloat64 gets float64 value. +func (d *Datum) GetFloat64() float64 { + return math.Float64frombits(uint64(d.i)) +} + +// SetFloat64 sets float64 value. +func (d *Datum) SetFloat64(f float64) { + d.k = KindFloat64 + d.i = int64(math.Float64bits(f)) +} + +// GetFloat32 gets float32 value. +func (d *Datum) GetFloat32() float32 { + return float32(math.Float64frombits(uint64(d.i))) +} + +// SetFloat32 sets float32 value. +func (d *Datum) SetFloat32(f float32) { + d.k = KindFloat32 + d.i = int64(math.Float64bits(float64(f))) +} + +// GetString gets string value. +func (d *Datum) GetString() string { + return hack.String(d.b) +} + +// SetString sets string value. +func (d *Datum) SetString(s string) { + d.k = KindString + sink(s) + d.b = hack.Slice(s) +} + +// sink prevents s from being allocated on the stack. +var sink = func(s string) { +} + +// GetBytes gets bytes value. +func (d *Datum) GetBytes() []byte { + return d.b +} + +// SetBytes sets bytes value to datum. +func (d *Datum) SetBytes(b []byte) { + d.k = KindBytes + d.b = b +} + +// SetBytesAsString sets bytes value to datum as string type. +func (d *Datum) SetBytesAsString(b []byte) { + d.k = KindString + d.b = b +} + +// GetInterface gets interface value. +func (d *Datum) GetInterface() interface{} { + return d.x +} + +// SetInterface sets interface to datum. +func (d *Datum) SetInterface(x interface{}) { + d.k = KindInterface + d.x = x +} + +// SetNull sets datum to nil. +func (d *Datum) SetNull() { + d.k = KindNull + d.x = nil +} + +// GetBinaryLiteral gets Bit value +func (d *Datum) GetBinaryLiteral() BinaryLiteral { + return d.b +} + +// GetMysqlBit gets MysqlBit value +func (d *Datum) GetMysqlBit() BinaryLiteral { + return d.GetBinaryLiteral() +} + +// SetBinaryLiteral sets Bit value +func (d *Datum) SetBinaryLiteral(b BinaryLiteral) { + d.k = KindBinaryLiteral + d.b = b +} + +// SetMysqlBit sets MysqlBit value +func (d *Datum) SetMysqlBit(b BinaryLiteral) { + d.k = KindMysqlBit + d.b = b +} + +// GetMysqlDecimal gets Decimal value +func (d *Datum) GetMysqlDecimal() *MyDecimal { + return d.x.(*MyDecimal) +} + +// SetMysqlDecimal sets Decimal value +func (d *Datum) SetMysqlDecimal(b *MyDecimal) { + d.k = KindMysqlDecimal + d.x = b +} + +// GetMysqlDuration gets Duration value +func (d *Datum) GetMysqlDuration() Duration { + return Duration{Duration: time.Duration(d.i), Fsp: int(d.decimal)} +} + +// SetMysqlDuration sets Duration value +func (d *Datum) SetMysqlDuration(b Duration) { + d.k = KindMysqlDuration + d.i = int64(b.Duration) + d.decimal = uint16(b.Fsp) +} + +// GetMysqlEnum gets Enum value +func (d *Datum) GetMysqlEnum() Enum { + return Enum{Value: uint64(d.i), Name: hack.String(d.b)} +} + +// SetMysqlEnum sets Enum value +func (d *Datum) SetMysqlEnum(b Enum) { + d.k = KindMysqlEnum + d.i = int64(b.Value) + sink(b.Name) + d.b = hack.Slice(b.Name) +} + +// GetMysqlSet gets Set value +func (d *Datum) GetMysqlSet() Set { + return Set{Value: uint64(d.i), Name: hack.String(d.b)} +} + +// SetMysqlSet sets Set value +func (d *Datum) SetMysqlSet(b Set) { + d.k = KindMysqlSet + d.i = int64(b.Value) + sink(b.Name) + d.b = hack.Slice(b.Name) +} + +// GetMysqlJSON gets json.BinaryJSON value +func (d *Datum) GetMysqlJSON() json.BinaryJSON { + return json.BinaryJSON{TypeCode: byte(d.i), Value: d.b} +} + +// SetMysqlJSON sets json.BinaryJSON value +func (d *Datum) SetMysqlJSON(b json.BinaryJSON) { + d.k = KindMysqlJSON + d.i = int64(b.TypeCode) + d.b = b.Value +} + +// GetMysqlTime gets types.Time value +func (d *Datum) GetMysqlTime() Time { + return d.x.(Time) +} + +// SetMysqlTime sets types.Time value +func (d *Datum) SetMysqlTime(b Time) { + d.k = KindMysqlTime + d.x = b +} + +// SetRaw sets raw value. +func (d *Datum) SetRaw(b []byte) { + d.k = KindRaw + d.b = b +} + +// GetRaw gets raw value. +func (d *Datum) GetRaw() []byte { + return d.b +} + +// SetAutoID set the auto increment ID according to its int flag. +func (d *Datum) SetAutoID(id int64, flag uint) { + if mysql.HasUnsignedFlag(flag) { + d.SetUint64(uint64(id)) + } else { + d.SetInt64(id) + } +} + +// GetValue gets the value of the datum of any kind. +func (d *Datum) GetValue() interface{} { + switch d.k { + case KindInt64: + return d.GetInt64() + case KindUint64: + return d.GetUint64() + case KindFloat32: + return d.GetFloat32() + case KindFloat64: + return d.GetFloat64() + case KindString: + return d.GetString() + case KindBytes: + return d.GetBytes() + case KindMysqlDecimal: + return d.GetMysqlDecimal() + case KindMysqlDuration: + return d.GetMysqlDuration() + case KindMysqlEnum: + return d.GetMysqlEnum() + case KindBinaryLiteral, KindMysqlBit: + return d.GetBinaryLiteral() + case KindMysqlSet: + return d.GetMysqlSet() + case KindMysqlJSON: + return d.GetMysqlJSON() + case KindMysqlTime: + return d.GetMysqlTime() + default: + return d.GetInterface() + } +} + +// SetValue sets any kind of value. +func (d *Datum) SetValue(val interface{}) { + switch x := val.(type) { + case nil: + d.SetNull() + case bool: + if x { + d.SetInt64(1) + } else { + d.SetInt64(0) + } + case int: + d.SetInt64(int64(x)) + case int64: + d.SetInt64(x) + case uint64: + d.SetUint64(x) + case float32: + d.SetFloat32(x) + case float64: + d.SetFloat64(x) + case string: + d.SetString(x) + case []byte: + d.SetBytes(x) + case *MyDecimal: + d.SetMysqlDecimal(x) + case Duration: + d.SetMysqlDuration(x) + case Enum: + d.SetMysqlEnum(x) + case BinaryLiteral: + d.SetBinaryLiteral(x) + case BitLiteral: // Store as BinaryLiteral for Bit and Hex literals + d.SetBinaryLiteral(BinaryLiteral(x)) + case HexLiteral: + d.SetBinaryLiteral(BinaryLiteral(x)) + case Set: + d.SetMysqlSet(x) + case json.BinaryJSON: + d.SetMysqlJSON(x) + case Time: + d.SetMysqlTime(x) + default: + d.SetInterface(x) + } +} + +// CompareDatum compares datum to another datum. +// TODO: return error properly. +func (d *Datum) CompareDatum(sc *stmtctx.StatementContext, ad *Datum) (int, error) { + if d.k == KindMysqlJSON && ad.k != KindMysqlJSON { + cmp, err := ad.CompareDatum(sc, d) + return cmp * -1, errors.Trace(err) + } + switch ad.k { + case KindNull: + if d.k == KindNull { + return 0, nil + } + return 1, nil + case KindMinNotNull: + if d.k == KindNull { + return -1, nil + } else if d.k == KindMinNotNull { + return 0, nil + } + return 1, nil + case KindMaxValue: + if d.k == KindMaxValue { + return 0, nil + } + return -1, nil + case KindInt64: + return d.compareInt64(sc, ad.GetInt64()) + case KindUint64: + return d.compareUint64(sc, ad.GetUint64()) + case KindFloat32, KindFloat64: + return d.compareFloat64(sc, ad.GetFloat64()) + case KindString: + return d.compareString(sc, ad.GetString()) + case KindBytes: + return d.compareBytes(sc, ad.GetBytes()) + case KindMysqlDecimal: + return d.compareMysqlDecimal(sc, ad.GetMysqlDecimal()) + case KindMysqlDuration: + return d.compareMysqlDuration(sc, ad.GetMysqlDuration()) + case KindMysqlEnum: + return d.compareMysqlEnum(sc, ad.GetMysqlEnum()) + case KindBinaryLiteral, KindMysqlBit: + return d.compareBinaryLiteral(sc, ad.GetBinaryLiteral()) + case KindMysqlSet: + return d.compareMysqlSet(sc, ad.GetMysqlSet()) + case KindMysqlJSON: + return d.compareMysqlJSON(sc, ad.GetMysqlJSON()) + case KindMysqlTime: + return d.compareMysqlTime(sc, ad.GetMysqlTime()) + default: + return 0, nil + } +} + +func (d *Datum) compareInt64(sc *stmtctx.StatementContext, i int64) (int, error) { + switch d.k { + case KindMaxValue: + return 1, nil + case KindInt64: + return CompareInt64(d.i, i), nil + case KindUint64: + if i < 0 || d.GetUint64() > math.MaxInt64 { + return 1, nil + } + return CompareInt64(d.i, i), nil + default: + return d.compareFloat64(sc, float64(i)) + } +} + +func (d *Datum) compareUint64(sc *stmtctx.StatementContext, u uint64) (int, error) { + switch d.k { + case KindMaxValue: + return 1, nil + case KindInt64: + if d.i < 0 || u > math.MaxInt64 { + return -1, nil + } + return CompareInt64(d.i, int64(u)), nil + case KindUint64: + return CompareUint64(d.GetUint64(), u), nil + default: + return d.compareFloat64(sc, float64(u)) + } +} + +func (d *Datum) compareFloat64(sc *stmtctx.StatementContext, f float64) (int, error) { + switch d.k { + case KindNull, KindMinNotNull: + return -1, nil + case KindMaxValue: + return 1, nil + case KindInt64: + return CompareFloat64(float64(d.i), f), nil + case KindUint64: + return CompareFloat64(float64(d.GetUint64()), f), nil + case KindFloat32, KindFloat64: + return CompareFloat64(d.GetFloat64(), f), nil + case KindString, KindBytes: + fVal, err := StrToFloat(sc, d.GetString()) + return CompareFloat64(fVal, f), errors.Trace(err) + case KindMysqlDecimal: + fVal, err := d.GetMysqlDecimal().ToFloat64() + return CompareFloat64(fVal, f), errors.Trace(err) + case KindMysqlDuration: + fVal := d.GetMysqlDuration().Seconds() + return CompareFloat64(fVal, f), nil + case KindMysqlEnum: + fVal := d.GetMysqlEnum().ToNumber() + return CompareFloat64(fVal, f), nil + case KindBinaryLiteral, KindMysqlBit: + val, err := d.GetBinaryLiteral().ToInt(sc) + fVal := float64(val) + return CompareFloat64(fVal, f), errors.Trace(err) + case KindMysqlSet: + fVal := d.GetMysqlSet().ToNumber() + return CompareFloat64(fVal, f), nil + case KindMysqlTime: + fVal, err := d.GetMysqlTime().ToNumber().ToFloat64() + return CompareFloat64(fVal, f), errors.Trace(err) + default: + return -1, nil + } +} + +func (d *Datum) compareString(sc *stmtctx.StatementContext, s string) (int, error) { + switch d.k { + case KindNull, KindMinNotNull: + return -1, nil + case KindMaxValue: + return 1, nil + case KindString, KindBytes: + return CompareString(d.GetString(), s), nil + case KindMysqlDecimal: + dec := new(MyDecimal) + err := sc.HandleTruncate(dec.FromString(hack.Slice(s))) + return d.GetMysqlDecimal().Compare(dec), errors.Trace(err) + case KindMysqlTime: + dt, err := ParseDatetime(sc, s) + return d.GetMysqlTime().Compare(dt), errors.Trace(err) + case KindMysqlDuration: + dur, err := ParseDuration(sc, s, MaxFsp) + return d.GetMysqlDuration().Compare(dur), errors.Trace(err) + case KindMysqlSet: + return CompareString(d.GetMysqlSet().String(), s), nil + case KindMysqlEnum: + return CompareString(d.GetMysqlEnum().String(), s), nil + case KindBinaryLiteral, KindMysqlBit: + return CompareString(d.GetBinaryLiteral().ToString(), s), nil + default: + fVal, err := StrToFloat(sc, s) + if err != nil { + return 0, errors.Trace(err) + } + return d.compareFloat64(sc, fVal) + } +} + +func (d *Datum) compareBytes(sc *stmtctx.StatementContext, b []byte) (int, error) { + return d.compareString(sc, hack.String(b)) +} + +func (d *Datum) compareMysqlDecimal(sc *stmtctx.StatementContext, dec *MyDecimal) (int, error) { + switch d.k { + case KindNull, KindMinNotNull: + return -1, nil + case KindMaxValue: + return 1, nil + case KindMysqlDecimal: + return d.GetMysqlDecimal().Compare(dec), nil + case KindString, KindBytes: + dDec := new(MyDecimal) + err := sc.HandleTruncate(dDec.FromString(d.GetBytes())) + return dDec.Compare(dec), errors.Trace(err) + default: + dVal, err := d.ConvertTo(sc, NewFieldType(mysql.TypeNewDecimal)) + if err != nil { + return 0, errors.Trace(err) + } + return dVal.GetMysqlDecimal().Compare(dec), nil + } +} + +func (d *Datum) compareMysqlDuration(sc *stmtctx.StatementContext, dur Duration) (int, error) { + switch d.k { + case KindMysqlDuration: + return d.GetMysqlDuration().Compare(dur), nil + case KindString, KindBytes: + dDur, err := ParseDuration(sc, d.GetString(), MaxFsp) + return dDur.Compare(dur), errors.Trace(err) + default: + return d.compareFloat64(sc, dur.Seconds()) + } +} + +func (d *Datum) compareMysqlEnum(sc *stmtctx.StatementContext, enum Enum) (int, error) { + switch d.k { + case KindString, KindBytes: + return CompareString(d.GetString(), enum.String()), nil + default: + return d.compareFloat64(sc, enum.ToNumber()) + } +} + +func (d *Datum) compareBinaryLiteral(sc *stmtctx.StatementContext, b BinaryLiteral) (int, error) { + switch d.k { + case KindString, KindBytes: + return CompareString(d.GetString(), b.ToString()), nil + case KindBinaryLiteral, KindMysqlBit: + return CompareString(d.GetBinaryLiteral().ToString(), b.ToString()), nil + default: + val, err := b.ToInt(sc) + if err != nil { + return 0, errors.Trace(err) + } + result, err := d.compareFloat64(sc, float64(val)) + return result, errors.Trace(err) + } +} + +func (d *Datum) compareMysqlSet(sc *stmtctx.StatementContext, set Set) (int, error) { + switch d.k { + case KindString, KindBytes: + return CompareString(d.GetString(), set.String()), nil + default: + return d.compareFloat64(sc, set.ToNumber()) + } +} + +func (d *Datum) compareMysqlJSON(sc *stmtctx.StatementContext, target json.BinaryJSON) (int, error) { + origin, err := d.ToMysqlJSON() + if err != nil { + return 0, errors.Trace(err) + } + return json.CompareBinary(origin, target), nil +} + +func (d *Datum) compareMysqlTime(sc *stmtctx.StatementContext, time Time) (int, error) { + switch d.k { + case KindString, KindBytes: + dt, err := ParseDatetime(sc, d.GetString()) + return dt.Compare(time), errors.Trace(err) + case KindMysqlTime: + return d.GetMysqlTime().Compare(time), nil + default: + fVal, err := time.ToNumber().ToFloat64() + if err != nil { + return 0, errors.Trace(err) + } + return d.compareFloat64(sc, fVal) + } +} + +// ConvertTo converts a datum to the target field type. +func (d *Datum) ConvertTo(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + if d.k == KindNull { + return Datum{}, nil + } + switch target.Tp { // TODO: implement mysql types convert when "CAST() AS" syntax are supported. + case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: + unsigned := mysql.HasUnsignedFlag(target.Flag) + if unsigned { + return d.convertToUint(sc, target) + } + return d.convertToInt(sc, target) + case mysql.TypeFloat, mysql.TypeDouble: + return d.convertToFloat(sc, target) + case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, + mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString: + return d.convertToString(sc, target) + case mysql.TypeTimestamp: + return d.convertToMysqlTimestamp(sc, target) + case mysql.TypeDatetime, mysql.TypeDate: + return d.convertToMysqlTime(sc, target) + case mysql.TypeDuration: + return d.convertToMysqlDuration(sc, target) + case mysql.TypeNewDecimal: + return d.convertToMysqlDecimal(sc, target) + case mysql.TypeYear: + return d.convertToMysqlYear(sc, target) + case mysql.TypeEnum: + return d.convertToMysqlEnum(sc, target) + case mysql.TypeBit: + return d.convertToMysqlBit(sc, target) + case mysql.TypeSet: + return d.convertToMysqlSet(sc, target) + case mysql.TypeJSON: + return d.convertToMysqlJSON(sc, target) + case mysql.TypeNull: + return Datum{}, nil + default: + panic("should never happen") + } +} + +func (d *Datum) convertToFloat(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ( + f float64 + ret Datum + err error + ) + switch d.k { + case KindNull: + return ret, nil + case KindInt64: + f = float64(d.GetInt64()) + case KindUint64: + f = float64(d.GetUint64()) + case KindFloat32, KindFloat64: + f = d.GetFloat64() + case KindString, KindBytes: + f, err = StrToFloat(sc, d.GetString()) + case KindMysqlTime: + f, err = d.GetMysqlTime().ToNumber().ToFloat64() + case KindMysqlDuration: + f, err = d.GetMysqlDuration().ToNumber().ToFloat64() + case KindMysqlDecimal: + f, err = d.GetMysqlDecimal().ToFloat64() + case KindMysqlSet: + f = d.GetMysqlSet().ToNumber() + case KindMysqlEnum: + f = d.GetMysqlEnum().ToNumber() + case KindBinaryLiteral, KindMysqlBit: + val, err1 := d.GetBinaryLiteral().ToInt(sc) + f, err = float64(val), err1 + case KindMysqlJSON: + f, err = ConvertJSONToFloat(sc, d.GetMysqlJSON()) + default: + return invalidConv(d, target.Tp) + } + var err1 error + f, err1 = ProduceFloatWithSpecifiedTp(f, target, sc) + if err == nil && err1 != nil { + err = err1 + } + if target.Tp == mysql.TypeFloat { + ret.SetFloat32(float32(f)) + } else { + ret.SetFloat64(f) + } + return ret, errors.Trace(err) +} + +// ProduceFloatWithSpecifiedTp produces a new float64 according to `flen` and `decimal`. +func ProduceFloatWithSpecifiedTp(f float64, target *FieldType, sc *stmtctx.StatementContext) (_ float64, err error) { + // For float and following double type, we will only truncate it for float(M, D) format. + // If no D is set, we will handle it like origin float whether M is set or not. + if target.Flen != UnspecifiedLength && target.Decimal != UnspecifiedLength { + f, err = TruncateFloat(f, target.Flen, target.Decimal) + if err = sc.HandleOverflow(err, err); err != nil { + return f, errors.Trace(err) + } + } + if mysql.HasUnsignedFlag(target.Flag) && f < 0 { + return 0, overflow(f, target.Tp) + } + return f, nil +} + +func (d *Datum) convertToString(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ret Datum + var s string + switch d.k { + case KindInt64: + s = strconv.FormatInt(d.GetInt64(), 10) + case KindUint64: + s = strconv.FormatUint(d.GetUint64(), 10) + case KindFloat32: + s = strconv.FormatFloat(d.GetFloat64(), 'f', -1, 32) + case KindFloat64: + s = strconv.FormatFloat(d.GetFloat64(), 'f', -1, 64) + case KindString, KindBytes: + s = d.GetString() + case KindMysqlTime: + s = d.GetMysqlTime().String() + case KindMysqlDuration: + s = d.GetMysqlDuration().String() + case KindMysqlDecimal: + s = d.GetMysqlDecimal().String() + case KindMysqlEnum: + s = d.GetMysqlEnum().String() + case KindMysqlSet: + s = d.GetMysqlSet().String() + case KindBinaryLiteral, KindMysqlBit: + s = d.GetBinaryLiteral().ToString() + case KindMysqlJSON: + s = d.GetMysqlJSON().String() + default: + return invalidConv(d, target.Tp) + } + s, err := ProduceStrWithSpecifiedTp(s, target, sc) + ret.SetString(s) + if target.Charset == charset.CharsetBin { + ret.k = KindBytes + } + return ret, errors.Trace(err) +} + +// ProduceStrWithSpecifiedTp produces a new string according to `flen` and `chs`. +func ProduceStrWithSpecifiedTp(s string, tp *FieldType, sc *stmtctx.StatementContext) (_ string, err error) { + flen, chs := tp.Flen, tp.Charset + if flen >= 0 { + // Flen is the rune length, not binary length, for UTF8 charset, we need to calculate the + // rune count and truncate to Flen runes if it is too long. + if chs == charset.CharsetUTF8 || chs == charset.CharsetUTF8MB4 { + characterLen := utf8.RuneCountInString(s) + if characterLen > flen { + // 1. If len(s) is 0 and flen is 0, truncateLen will be 0, don't truncate s. + // CREATE TABLE t (a char(0)); + // INSERT INTO t VALUES (``); + // 2. If len(s) is 10 and flen is 0, truncateLen will be 0 too, but we still need to truncate s. + // SELECT 1, CAST(1234 AS CHAR(0)); + // So truncateLen is not a suitable variable to determine to do truncate or not. + var runeCount int + var truncateLen int + for i := range s { + if runeCount == flen { + truncateLen = i + break + } + runeCount++ + } + err = ErrDataTooLong.GenWithStack("Data Too Long, field len %d, data len %d", flen, characterLen) + s = truncateStr(s, truncateLen) + } + } else if len(s) > flen { + err = ErrDataTooLong.GenWithStack("Data Too Long, field len %d, data len %d", flen, len(s)) + s = truncateStr(s, flen) + } else if tp.Tp == mysql.TypeString && IsBinaryStr(tp) && len(s) < flen { + padding := make([]byte, flen-len(s)) + s = string(append([]byte(s), padding...)) + } + } + return s, errors.Trace(sc.HandleTruncate(err)) +} + +func (d *Datum) convertToInt(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + i64, err := d.toSignedInteger(sc, target.Tp) + return NewIntDatum(i64), errors.Trace(err) +} + +func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + tp := target.Tp + upperBound := UnsignedUpperBound[tp] + var ( + val uint64 + err error + ret Datum + ) + switch d.k { + case KindInt64: + val, err = ConvertIntToUint(d.GetInt64(), upperBound, tp) + case KindUint64: + val, err = ConvertUintToUint(d.GetUint64(), upperBound, tp) + case KindFloat32, KindFloat64: + val, err = ConvertFloatToUint(d.GetFloat64(), upperBound, tp) + case KindString, KindBytes: + val, err = StrToUint(sc, d.GetString()) + if err != nil { + return ret, errors.Trace(err) + } + val, err = ConvertUintToUint(val, upperBound, tp) + if err != nil { + return ret, errors.Trace(err) + } + ret.SetUint64(val) + case KindMysqlTime: + dec := d.GetMysqlTime().ToNumber() + err = dec.Round(dec, 0, ModeHalfEven) + ival, err1 := dec.ToInt() + if err == nil { + err = err1 + } + val, err1 = ConvertIntToUint(ival, upperBound, tp) + if err == nil { + err = err1 + } + case KindMysqlDuration: + dec := d.GetMysqlDuration().ToNumber() + err = dec.Round(dec, 0, ModeHalfEven) + ival, err1 := dec.ToInt() + if err1 == nil { + val, err = ConvertIntToUint(ival, upperBound, tp) + } + case KindMysqlDecimal: + fval, err1 := d.GetMysqlDecimal().ToFloat64() + val, err = ConvertFloatToUint(fval, upperBound, tp) + if err == nil { + err = err1 + } + case KindMysqlEnum: + val, err = ConvertFloatToUint(d.GetMysqlEnum().ToNumber(), upperBound, tp) + case KindMysqlSet: + val, err = ConvertFloatToUint(d.GetMysqlSet().ToNumber(), upperBound, tp) + case KindBinaryLiteral, KindMysqlBit: + val, err = d.GetBinaryLiteral().ToInt(sc) + case KindMysqlJSON: + var i64 int64 + i64, err = ConvertJSONToInt(sc, d.GetMysqlJSON(), true) + val = uint64(i64) + default: + return invalidConv(d, target.Tp) + } + ret.SetUint64(val) + if err != nil { + return ret, errors.Trace(err) + } + return ret, nil +} + +func (d *Datum) convertToMysqlTimestamp(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ( + ret Datum + t Time + err error + ) + fsp := DefaultFsp + if target.Decimal != UnspecifiedLength { + fsp = target.Decimal + } + switch d.k { + case KindMysqlTime: + t = d.GetMysqlTime() + t, err = t.RoundFrac(sc, fsp) + case KindMysqlDuration: + t, err = d.GetMysqlDuration().ConvertToTime(sc, mysql.TypeTimestamp) + if err != nil { + ret.SetValue(t) + return ret, errors.Trace(err) + } + t, err = t.RoundFrac(sc, fsp) + case KindString, KindBytes: + t, err = ParseTime(sc, d.GetString(), mysql.TypeTimestamp, fsp) + case KindInt64: + t, err = ParseTimeFromNum(sc, d.GetInt64(), mysql.TypeTimestamp, fsp) + default: + return invalidConv(d, mysql.TypeTimestamp) + } + t.Type = mysql.TypeTimestamp + ret.SetMysqlTime(t) + if err != nil { + return ret, errors.Trace(err) + } + return ret, nil +} + +func (d *Datum) convertToMysqlTime(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + tp := target.Tp + fsp := DefaultFsp + if target.Decimal != UnspecifiedLength { + fsp = target.Decimal + } + var ( + ret Datum + t Time + err error + ) + switch d.k { + case KindMysqlTime: + t, err = d.GetMysqlTime().Convert(sc, tp) + if err != nil { + ret.SetValue(t) + return ret, errors.Trace(err) + } + t, err = t.RoundFrac(sc, fsp) + case KindMysqlDuration: + t, err = d.GetMysqlDuration().ConvertToTime(sc, tp) + if err != nil { + ret.SetValue(t) + return ret, errors.Trace(err) + } + t, err = t.RoundFrac(sc, fsp) + case KindString, KindBytes: + t, err = ParseTime(sc, d.GetString(), tp, fsp) + case KindInt64: + t, err = ParseTimeFromNum(sc, d.GetInt64(), tp, fsp) + default: + return invalidConv(d, tp) + } + if tp == mysql.TypeDate { + // Truncate hh:mm:ss part if the type is Date. + t.Time = FromDate(t.Time.Year(), t.Time.Month(), t.Time.Day(), 0, 0, 0, 0) + } + ret.SetValue(t) + if err != nil { + return ret, errors.Trace(err) + } + return ret, nil +} + +func (d *Datum) convertToMysqlDuration(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + tp := target.Tp + fsp := DefaultFsp + if target.Decimal != UnspecifiedLength { + fsp = target.Decimal + } + var ret Datum + switch d.k { + case KindMysqlTime: + dur, err := d.GetMysqlTime().ConvertToDuration() + if err != nil { + ret.SetValue(dur) + return ret, errors.Trace(err) + } + dur, err = dur.RoundFrac(fsp) + ret.SetValue(dur) + if err != nil { + return ret, errors.Trace(err) + } + case KindMysqlDuration: + dur, err := d.GetMysqlDuration().RoundFrac(fsp) + ret.SetValue(dur) + if err != nil { + return ret, errors.Trace(err) + } + case KindInt64, KindFloat32, KindFloat64, KindMysqlDecimal: + // TODO: We need a ParseDurationFromNum to avoid the cost of converting a num to string. + timeStr, err := d.ToString() + if err != nil { + return ret, errors.Trace(err) + } + timeNum, err := d.ToInt64(sc) + if err != nil { + return ret, errors.Trace(err) + } + // For huge numbers(>'0001-00-00 00-00-00') try full DATETIME in ParseDuration. + if timeNum > MaxDuration && timeNum < 10000000000 { + // mysql return max in no strict sql mode. + ret.SetValue(Duration{Duration: MaxTime, Fsp: 0}) + return ret, ErrInvalidTimeFormat.GenWithStack("Incorrect time value: '%s'", timeStr) + } + if timeNum < -MaxDuration { + return ret, ErrInvalidTimeFormat.GenWithStack("Incorrect time value: '%s'", timeStr) + } + t, err := ParseDuration(sc, timeStr, fsp) + ret.SetValue(t) + if err != nil { + return ret, errors.Trace(err) + } + case KindString, KindBytes: + t, err := ParseDuration(sc, d.GetString(), fsp) + ret.SetValue(t) + if err != nil { + return ret, errors.Trace(err) + } + default: + return invalidConv(d, tp) + } + return ret, nil +} + +func (d *Datum) convertToMysqlDecimal(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ret Datum + ret.SetLength(target.Flen) + ret.SetFrac(target.Decimal) + var dec = &MyDecimal{} + var err error + switch d.k { + case KindInt64: + dec.FromInt(d.GetInt64()) + case KindUint64: + dec.FromUint(d.GetUint64()) + case KindFloat32, KindFloat64: + err = dec.FromFloat64(d.GetFloat64()) + case KindString, KindBytes: + err = dec.FromString(d.GetBytes()) + case KindMysqlDecimal: + *dec = *d.GetMysqlDecimal() + case KindMysqlTime: + dec = d.GetMysqlTime().ToNumber() + case KindMysqlDuration: + dec = d.GetMysqlDuration().ToNumber() + case KindMysqlEnum: + err = dec.FromFloat64(d.GetMysqlEnum().ToNumber()) + case KindMysqlSet: + err = dec.FromFloat64(d.GetMysqlSet().ToNumber()) + case KindBinaryLiteral, KindMysqlBit: + val, err1 := d.GetBinaryLiteral().ToInt(sc) + err = err1 + dec.FromUint(val) + case KindMysqlJSON: + f, err1 := ConvertJSONToFloat(sc, d.GetMysqlJSON()) + if err1 != nil { + return ret, errors.Trace(err1) + } + err = dec.FromFloat64(f) + default: + return invalidConv(d, target.Tp) + } + var err1 error + dec, err1 = ProduceDecWithSpecifiedTp(dec, target, sc) + if err == nil && err1 != nil { + err = err1 + } + if dec.negative && mysql.HasUnsignedFlag(target.Flag) { + *dec = zeroMyDecimal + if err == nil { + err = ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%d, %d)", target.Flen, target.Decimal)) + } + } + ret.SetValue(dec) + return ret, errors.Trace(err) +} + +// ProduceDecWithSpecifiedTp produces a new decimal according to `flen` and `decimal`. +func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.StatementContext) (_ *MyDecimal, err error) { + flen, decimal := tp.Flen, tp.Decimal + if flen != UnspecifiedLength && decimal != UnspecifiedLength { + if flen < decimal { + return nil, ErrMBiggerThanD.GenWithStackByArgs("") + } + prec, frac := dec.PrecisionAndFrac() + if !dec.IsZero() && prec-frac > flen-decimal { + dec = NewMaxOrMinDec(dec.IsNegative(), flen, decimal) + // select (cast 111 as decimal(1)) causes a warning in MySQL. + err = ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%d, %d)", flen, decimal)) + } else if frac != decimal { + old := *dec + err = dec.Round(dec, decimal, ModeHalfEven) + if err != nil { + return nil, errors.Trace(err) + } + if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 { + if sc.InInsertStmt || sc.InUpdateOrDeleteStmt { + // fix https://github.com/pingcap/tidb/issues/3895 + // fix https://github.com/pingcap/tidb/issues/5532 + sc.AppendWarning(ErrTruncated) + err = nil + } else { + err = sc.HandleTruncate(ErrTruncated) + } + } + } + } + + if ErrOverflow.Equal(err) { + // TODO: warnErr need to be ErrWarnDataOutOfRange + err = sc.HandleOverflow(err, err) + } + unsigned := mysql.HasUnsignedFlag(tp.Flag) + if unsigned && dec.IsNegative() { + dec = dec.FromUint(0) + } + return dec, errors.Trace(err) +} + +func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ( + ret Datum + y int64 + err error + fromStr bool + ) + switch d.k { + case KindString, KindBytes: + y, err = StrToInt(sc, d.GetString()) + if err != nil { + return ret, errors.Trace(err) + } + fromStr = true + case KindMysqlTime: + y = int64(d.GetMysqlTime().Time.Year()) + case KindMysqlDuration: + y = int64(time.Now().Year()) + default: + ret, err = d.convertToInt(sc, NewFieldType(mysql.TypeLonglong)) + if err != nil { + return invalidConv(d, target.Tp) + } + y = ret.GetInt64() + } + y, err = AdjustYear(y, fromStr) + if err != nil { + return invalidConv(d, target.Tp) + } + ret.SetInt64(y) + return ret, nil +} + +func (d *Datum) convertToMysqlBit(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ret Datum + var uintValue uint64 + var err error + switch d.k { + case KindString, KindBytes: + uintValue, err = BinaryLiteral(d.b).ToInt(sc) + default: + uintDatum, err1 := d.convertToUint(sc, target) + uintValue, err = uintDatum.GetUint64(), err1 + } + if target.Flen < 64 && uintValue >= 1<<(uint64(target.Flen)) { + return Datum{}, errors.Trace(ErrOverflow.GenWithStackByArgs("BIT", fmt.Sprintf("(%d)", target.Flen))) + } + byteSize := (target.Flen + 7) >> 3 + ret.SetMysqlBit(NewBinaryLiteralFromUint(uintValue, byteSize)) + return ret, errors.Trace(err) +} + +func (d *Datum) convertToMysqlEnum(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ( + ret Datum + e Enum + err error + ) + switch d.k { + case KindString, KindBytes: + e, err = ParseEnumName(target.Elems, d.GetString()) + default: + var uintDatum Datum + uintDatum, err = d.convertToUint(sc, target) + if err != nil { + return ret, errors.Trace(err) + } + e, err = ParseEnumValue(target.Elems, uintDatum.GetUint64()) + } + if err != nil { + log.Error(err) + err = errors.Trace(ErrTruncated) + } + ret.SetValue(e) + return ret, err +} + +func (d *Datum) convertToMysqlSet(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { + var ( + ret Datum + s Set + err error + ) + switch d.k { + case KindString, KindBytes: + s, err = ParseSetName(target.Elems, d.GetString()) + default: + var uintDatum Datum + uintDatum, err = d.convertToUint(sc, target) + if err != nil { + return ret, errors.Trace(err) + } + s, err = ParseSetValue(target.Elems, uintDatum.GetUint64()) + } + + if err != nil { + return invalidConv(d, target.Tp) + } + ret.SetValue(s) + return ret, nil +} + +func (d *Datum) convertToMysqlJSON(sc *stmtctx.StatementContext, target *FieldType) (ret Datum, err error) { + switch d.k { + case KindString, KindBytes: + var j json.BinaryJSON + if j, err = json.ParseBinaryFromString(d.GetString()); err == nil { + ret.SetMysqlJSON(j) + } + case KindInt64: + i64 := d.GetInt64() + ret.SetMysqlJSON(json.CreateBinary(i64)) + case KindUint64: + u64 := d.GetUint64() + ret.SetMysqlJSON(json.CreateBinary(u64)) + case KindFloat32, KindFloat64: + f64 := d.GetFloat64() + ret.SetMysqlJSON(json.CreateBinary(f64)) + case KindMysqlDecimal: + var f64 float64 + if f64, err = d.GetMysqlDecimal().ToFloat64(); err == nil { + ret.SetMysqlJSON(json.CreateBinary(f64)) + } + case KindMysqlJSON: + ret = *d + default: + var s string + if s, err = d.ToString(); err == nil { + // TODO: fix precision of MysqlTime. For example, + // On MySQL 5.7 CAST(NOW() AS JSON) -> "2011-11-11 11:11:11.111111", + // But now we can only return "2011-11-11 11:11:11". + ret.SetMysqlJSON(json.CreateBinary(s)) + } + } + return ret, errors.Trace(err) +} + +// ToBool converts to a bool. +// We will use 1 for true, and 0 for false. +func (d *Datum) ToBool(sc *stmtctx.StatementContext) (int64, error) { + var err error + isZero := false + switch d.Kind() { + case KindInt64: + isZero = d.GetInt64() == 0 + case KindUint64: + isZero = d.GetUint64() == 0 + case KindFloat32: + isZero = RoundFloat(d.GetFloat64()) == 0 + case KindFloat64: + isZero = RoundFloat(d.GetFloat64()) == 0 + case KindString, KindBytes: + iVal, err1 := StrToInt(sc, d.GetString()) + isZero, err = iVal == 0, err1 + case KindMysqlTime: + isZero = d.GetMysqlTime().IsZero() + case KindMysqlDuration: + isZero = d.GetMysqlDuration().Duration == 0 + case KindMysqlDecimal: + v, err1 := d.GetMysqlDecimal().ToFloat64() + isZero, err = RoundFloat(v) == 0, err1 + case KindMysqlEnum: + isZero = d.GetMysqlEnum().ToNumber() == 0 + case KindMysqlSet: + isZero = d.GetMysqlSet().ToNumber() == 0 + case KindBinaryLiteral, KindMysqlBit: + val, err1 := d.GetBinaryLiteral().ToInt(sc) + isZero, err = val == 0, err1 + default: + return 0, errors.Errorf("cannot convert %v(type %T) to bool", d.GetValue(), d.GetValue()) + } + var ret int64 + if isZero { + ret = 0 + } else { + ret = 1 + } + if err != nil { + return ret, errors.Trace(err) + } + return ret, nil +} + +// ConvertDatumToDecimal converts datum to decimal. +func ConvertDatumToDecimal(sc *stmtctx.StatementContext, d Datum) (*MyDecimal, error) { + dec := new(MyDecimal) + var err error + switch d.Kind() { + case KindInt64: + dec.FromInt(d.GetInt64()) + case KindUint64: + dec.FromUint(d.GetUint64()) + case KindFloat32: + err = dec.FromFloat64(float64(d.GetFloat32())) + case KindFloat64: + err = dec.FromFloat64(d.GetFloat64()) + case KindString: + err = sc.HandleTruncate(dec.FromString(d.GetBytes())) + case KindMysqlDecimal: + *dec = *d.GetMysqlDecimal() + case KindMysqlEnum: + dec.FromUint(d.GetMysqlEnum().Value) + case KindMysqlSet: + dec.FromUint(d.GetMysqlSet().Value) + case KindBinaryLiteral, KindMysqlBit: + val, err1 := d.GetBinaryLiteral().ToInt(sc) + dec.FromUint(val) + err = err1 + case KindMysqlJSON: + f, err1 := ConvertJSONToFloat(sc, d.GetMysqlJSON()) + if err1 != nil { + return nil, errors.Trace(err1) + } + err = dec.FromFloat64(f) + default: + err = fmt.Errorf("can't convert %v to decimal", d.GetValue()) + } + return dec, errors.Trace(err) +} + +// ToDecimal converts to a decimal. +func (d *Datum) ToDecimal(sc *stmtctx.StatementContext) (*MyDecimal, error) { + switch d.Kind() { + case KindMysqlTime: + return d.GetMysqlTime().ToNumber(), nil + case KindMysqlDuration: + return d.GetMysqlDuration().ToNumber(), nil + default: + return ConvertDatumToDecimal(sc, *d) + } +} + +// ToInt64 converts to a int64. +func (d *Datum) ToInt64(sc *stmtctx.StatementContext) (int64, error) { + return d.toSignedInteger(sc, mysql.TypeLonglong) +} + +func (d *Datum) toSignedInteger(sc *stmtctx.StatementContext, tp byte) (int64, error) { + lowerBound := SignedLowerBound[tp] + upperBound := SignedUpperBound[tp] + switch d.Kind() { + case KindInt64: + return ConvertIntToInt(d.GetInt64(), lowerBound, upperBound, tp) + case KindUint64: + return ConvertUintToInt(d.GetUint64(), upperBound, tp) + case KindFloat32: + return ConvertFloatToInt(float64(d.GetFloat32()), lowerBound, upperBound, tp) + case KindFloat64: + return ConvertFloatToInt(d.GetFloat64(), lowerBound, upperBound, tp) + case KindString, KindBytes: + iVal, err := StrToInt(sc, d.GetString()) + iVal, err2 := ConvertIntToInt(iVal, lowerBound, upperBound, tp) + if err == nil { + err = err2 + } + return iVal, errors.Trace(err) + case KindMysqlTime: + // 2011-11-10 11:11:11.999999 -> 20111110111112 + // 2011-11-10 11:59:59.999999 -> 20111110120000 + t, err := d.GetMysqlTime().RoundFrac(sc, DefaultFsp) + if err != nil { + return 0, errors.Trace(err) + } + ival, err := t.ToNumber().ToInt() + ival, err2 := ConvertIntToInt(ival, lowerBound, upperBound, tp) + if err == nil { + err = err2 + } + return ival, errors.Trace(err) + case KindMysqlDuration: + // 11:11:11.999999 -> 111112 + // 11:59:59.999999 -> 120000 + dur, err := d.GetMysqlDuration().RoundFrac(DefaultFsp) + if err != nil { + return 0, errors.Trace(err) + } + ival, err := dur.ToNumber().ToInt() + ival, err2 := ConvertIntToInt(ival, lowerBound, upperBound, tp) + if err == nil { + err = err2 + } + return ival, errors.Trace(err) + case KindMysqlDecimal: + var to MyDecimal + err := d.GetMysqlDecimal().Round(&to, 0, ModeHalfEven) + ival, err1 := to.ToInt() + if err == nil { + err = err1 + } + ival, err2 := ConvertIntToInt(ival, lowerBound, upperBound, tp) + if err == nil { + err = err2 + } + return ival, errors.Trace(err) + case KindMysqlEnum: + fval := d.GetMysqlEnum().ToNumber() + return ConvertFloatToInt(fval, lowerBound, upperBound, tp) + case KindMysqlSet: + fval := d.GetMysqlSet().ToNumber() + return ConvertFloatToInt(fval, lowerBound, upperBound, tp) + case KindMysqlJSON: + return ConvertJSONToInt(sc, d.GetMysqlJSON(), false) + case KindBinaryLiteral, KindMysqlBit: + val, err := d.GetBinaryLiteral().ToInt(sc) + return int64(val), errors.Trace(err) + default: + return 0, errors.Errorf("cannot convert %v(type %T) to int64", d.GetValue(), d.GetValue()) + } +} + +// ToFloat64 converts to a float64 +func (d *Datum) ToFloat64(sc *stmtctx.StatementContext) (float64, error) { + switch d.Kind() { + case KindInt64: + return float64(d.GetInt64()), nil + case KindUint64: + return float64(d.GetUint64()), nil + case KindFloat32: + return float64(d.GetFloat32()), nil + case KindFloat64: + return d.GetFloat64(), nil + case KindString: + return StrToFloat(sc, d.GetString()) + case KindBytes: + return StrToFloat(sc, string(d.GetBytes())) + case KindMysqlTime: + f, err := d.GetMysqlTime().ToNumber().ToFloat64() + return f, errors.Trace(err) + case KindMysqlDuration: + f, err := d.GetMysqlDuration().ToNumber().ToFloat64() + return f, errors.Trace(err) + case KindMysqlDecimal: + f, err := d.GetMysqlDecimal().ToFloat64() + return f, errors.Trace(err) + case KindMysqlEnum: + return d.GetMysqlEnum().ToNumber(), nil + case KindMysqlSet: + return d.GetMysqlSet().ToNumber(), nil + case KindBinaryLiteral, KindMysqlBit: + val, err := d.GetBinaryLiteral().ToInt(sc) + return float64(val), errors.Trace(err) + case KindMysqlJSON: + f, err := ConvertJSONToFloat(sc, d.GetMysqlJSON()) + return f, errors.Trace(err) + default: + return 0, errors.Errorf("cannot convert %v(type %T) to float64", d.GetValue(), d.GetValue()) + } +} + +// ToString gets the string representation of the datum. +func (d *Datum) ToString() (string, error) { + switch d.Kind() { + case KindInt64: + return strconv.FormatInt(d.GetInt64(), 10), nil + case KindUint64: + return strconv.FormatUint(d.GetUint64(), 10), nil + case KindFloat32: + return strconv.FormatFloat(float64(d.GetFloat32()), 'f', -1, 32), nil + case KindFloat64: + return strconv.FormatFloat(d.GetFloat64(), 'f', -1, 64), nil + case KindString: + return d.GetString(), nil + case KindBytes: + return d.GetString(), nil + case KindMysqlTime: + return d.GetMysqlTime().String(), nil + case KindMysqlDuration: + return d.GetMysqlDuration().String(), nil + case KindMysqlDecimal: + return d.GetMysqlDecimal().String(), nil + case KindMysqlEnum: + return d.GetMysqlEnum().String(), nil + case KindMysqlSet: + return d.GetMysqlSet().String(), nil + case KindMysqlJSON: + return d.GetMysqlJSON().String(), nil + case KindBinaryLiteral, KindMysqlBit: + return d.GetBinaryLiteral().ToString(), nil + default: + return "", errors.Errorf("cannot convert %v(type %T) to string", d.GetValue(), d.GetValue()) + } +} + +// ToBytes gets the bytes representation of the datum. +func (d *Datum) ToBytes() ([]byte, error) { + switch d.k { + case KindString, KindBytes: + return d.GetBytes(), nil + default: + str, err := d.ToString() + if err != nil { + return nil, errors.Trace(err) + } + return []byte(str), nil + } +} + +// ToMysqlJSON is similar to convertToMysqlJSON, except the +// latter parses from string, but the former uses it as primitive. +func (d *Datum) ToMysqlJSON() (j json.BinaryJSON, err error) { + var in interface{} + switch d.Kind() { + case KindMysqlJSON: + j = d.GetMysqlJSON() + return + case KindInt64: + in = d.GetInt64() + case KindUint64: + in = d.GetUint64() + case KindFloat32, KindFloat64: + in = d.GetFloat64() + case KindMysqlDecimal: + in, err = d.GetMysqlDecimal().ToFloat64() + case KindString, KindBytes: + in = d.GetString() + case KindBinaryLiteral, KindMysqlBit: + in = d.GetBinaryLiteral().ToString() + case KindNull: + in = nil + default: + in, err = d.ToString() + } + if err != nil { + err = errors.Trace(err) + return + } + j = json.CreateBinary(in) + return +} + +func invalidConv(d *Datum, tp byte) (Datum, error) { + return Datum{}, errors.Errorf("cannot convert datum from %s to type %s.", KindStr(d.Kind()), TypeStr(tp)) +} + +func (d *Datum) convergeType(hasUint, hasDecimal, hasFloat *bool) (x Datum) { + x = *d + switch d.Kind() { + case KindUint64: + *hasUint = true + case KindFloat32: + f := d.GetFloat32() + x.SetFloat64(float64(f)) + *hasFloat = true + case KindFloat64: + *hasFloat = true + case KindMysqlDecimal: + *hasDecimal = true + } + return x +} + +// CoerceDatum changes type. +// If a or b is Float, changes the both to Float. +// Else if a or b is Decimal, changes the both to Decimal. +// Else if a or b is Uint and op is not div, mod, or intDiv changes the both to Uint. +func CoerceDatum(sc *stmtctx.StatementContext, a, b Datum) (x, y Datum, err error) { + if a.IsNull() || b.IsNull() { + return x, y, nil + } + var hasUint, hasDecimal, hasFloat bool + x = a.convergeType(&hasUint, &hasDecimal, &hasFloat) + y = b.convergeType(&hasUint, &hasDecimal, &hasFloat) + if hasFloat { + switch x.Kind() { + case KindInt64: + x.SetFloat64(float64(x.GetInt64())) + case KindUint64: + x.SetFloat64(float64(x.GetUint64())) + case KindMysqlEnum: + x.SetFloat64(x.GetMysqlEnum().ToNumber()) + case KindMysqlSet: + x.SetFloat64(x.GetMysqlSet().ToNumber()) + case KindMysqlDecimal: + var fval float64 + fval, err = x.ToFloat64(sc) + if err != nil { + return x, y, errors.Trace(err) + } + x.SetFloat64(fval) + } + switch y.Kind() { + case KindInt64: + y.SetFloat64(float64(y.GetInt64())) + case KindUint64: + y.SetFloat64(float64(y.GetUint64())) + case KindBinaryLiteral, KindMysqlBit: + var fval uint64 + fval, err = y.GetBinaryLiteral().ToInt(sc) + if err != nil { + return x, y, errors.Trace(err) + } + y.SetFloat64(float64(fval)) + case KindMysqlEnum: + y.SetFloat64(y.GetMysqlEnum().ToNumber()) + case KindMysqlSet: + y.SetFloat64(y.GetMysqlSet().ToNumber()) + case KindMysqlDecimal: + var fval float64 + fval, err = y.ToFloat64(sc) + if err != nil { + return x, y, errors.Trace(err) + } + y.SetFloat64(fval) + } + } else if hasDecimal { + var dec *MyDecimal + dec, err = ConvertDatumToDecimal(sc, x) + if err != nil { + return x, y, errors.Trace(err) + } + x.SetMysqlDecimal(dec) + dec, err = ConvertDatumToDecimal(sc, y) + if err != nil { + return x, y, errors.Trace(err) + } + y.SetMysqlDecimal(dec) + } + return +} + +// NewDatum creates a new Datum from an interface{}. +func NewDatum(in interface{}) (d Datum) { + switch x := in.(type) { + case []interface{}: + d.SetValue(MakeDatums(x...)) + default: + d.SetValue(in) + } + return d +} + +// NewIntDatum creates a new Datum from an int64 value. +func NewIntDatum(i int64) (d Datum) { + d.SetInt64(i) + return d +} + +// NewUintDatum creates a new Datum from an uint64 value. +func NewUintDatum(i uint64) (d Datum) { + d.SetUint64(i) + return d +} + +// NewBytesDatum creates a new Datum from a byte slice. +func NewBytesDatum(b []byte) (d Datum) { + d.SetBytes(b) + return d +} + +// NewStringDatum creates a new Datum from a string. +func NewStringDatum(s string) (d Datum) { + d.SetString(s) + return d +} + +// NewFloat64Datum creates a new Datum from a float64 value. +func NewFloat64Datum(f float64) (d Datum) { + d.SetFloat64(f) + return d +} + +// NewFloat32Datum creates a new Datum from a float32 value. +func NewFloat32Datum(f float32) (d Datum) { + d.SetFloat32(f) + return d +} + +// NewDurationDatum creates a new Datum from a Duration value. +func NewDurationDatum(dur Duration) (d Datum) { + d.SetMysqlDuration(dur) + return d +} + +// NewTimeDatum creates a new Time from a Time value. +func NewTimeDatum(t Time) (d Datum) { + d.SetMysqlTime(t) + return d +} + +// NewDecimalDatum creates a new Datum form a MyDecimal value. +func NewDecimalDatum(dec *MyDecimal) (d Datum) { + d.SetMysqlDecimal(dec) + return d +} + +// NewBinaryLiteralDatum creates a new BinaryLiteral Datum for a BinaryLiteral value. +func NewBinaryLiteralDatum(b BinaryLiteral) (d Datum) { + d.SetBinaryLiteral(b) + return d +} + +// NewMysqlBitDatum creates a new MysqlBit Datum for a BinaryLiteral value. +func NewMysqlBitDatum(b BinaryLiteral) (d Datum) { + d.SetMysqlBit(b) + return d +} + +// MakeDatums creates datum slice from interfaces. +func MakeDatums(args ...interface{}) []Datum { + datums := make([]Datum, len(args)) + for i, v := range args { + datums[i] = NewDatum(v) + } + return datums +} + +// MinNotNullDatum returns a datum represents minimum not null value. +func MinNotNullDatum() Datum { + return Datum{k: KindMinNotNull} +} + +// MaxValueDatum returns a datum represents max value. +func MaxValueDatum() Datum { + return Datum{k: KindMaxValue} +} + +// EqualDatums compare if a and b contains the same datum values. +func EqualDatums(sc *stmtctx.StatementContext, a []Datum, b []Datum) (bool, error) { + if len(a) != len(b) { + return false, nil + } + if a == nil && b == nil { + return true, nil + } + if a == nil || b == nil { + return false, nil + } + for i, ai := range a { + v, err := ai.CompareDatum(sc, &b[i]) + if err != nil { + return false, errors.Trace(err) + } + if v != 0 { + return false, nil + } + } + return true, nil +} + +// SortDatums sorts a slice of datum. +func SortDatums(sc *stmtctx.StatementContext, datums []Datum) error { + sorter := datumsSorter{datums: datums, sc: sc} + sort.Sort(&sorter) + return sorter.err +} + +type datumsSorter struct { + datums []Datum + sc *stmtctx.StatementContext + err error +} + +func (ds *datumsSorter) Len() int { + return len(ds.datums) +} + +func (ds *datumsSorter) Less(i, j int) bool { + cmp, err := ds.datums[i].CompareDatum(ds.sc, &ds.datums[j]) + if err != nil { + ds.err = errors.Trace(err) + return true + } + return cmp < 0 +} + +func (ds *datumsSorter) Swap(i, j int) { + ds.datums[i], ds.datums[j] = ds.datums[j], ds.datums[i] +} + +func handleTruncateError(sc *stmtctx.StatementContext) error { + if sc.IgnoreTruncate { + return nil + } + if !sc.TruncateAsWarning { + return ErrTruncated + } + sc.AppendWarning(ErrTruncated) + return nil +} + +// DatumsToString converts several datums to formatted string. +func DatumsToString(datums []Datum, handleSpecialValue bool) (string, error) { + var strs []string + for _, datum := range datums { + if handleSpecialValue { + switch datum.Kind() { + case KindNull: + strs = append(strs, "NULL") + continue + case KindMinNotNull: + strs = append(strs, "-inf") + continue + case KindMaxValue: + strs = append(strs, "+inf") + continue + } + } + str, err := datum.ToString() + if err != nil { + return "", errors.Trace(err) + } + strs = append(strs, str) + } + size := len(datums) + if size > 1 { + strs[0] = "(" + strs[0] + strs[size-1] = strs[size-1] + ")" + } + return strings.Join(strs, ", "), nil +} + +// DatumsToStrNoErr converts some datums to a formatted string. +// If an error occurs, it will print a log instead of returning an error. +func DatumsToStrNoErr(datums []Datum) string { + str, err := DatumsToString(datums, true) + terror.Log(errors.Trace(err)) + return str +} + +// CopyDatum returns a new copy of the datum. +// TODO: Abandon this function. +func CopyDatum(datum Datum) Datum { + return *datum.Copy() +} + +// CopyRow deep copies a Datum slice. +func CopyRow(dr []Datum) []Datum { + c := make([]Datum, len(dr)) + for i, d := range dr { + c[i] = *d.Copy() + } + return c +} diff --git a/vendor/github.com/pingcap/tidb/types/datum_eval.go b/vendor/github.com/pingcap/tidb/types/datum_eval.go new file mode 100644 index 0000000000000000000000000000000000000000..a2d4d744b4d6077b636347a89182e489d5c2092e --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/datum_eval.go @@ -0,0 +1,66 @@ +// Copyright 2016 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "github.com/cznic/mathutil" + "github.com/pingcap/errors" + "github.com/pingcap/parser/opcode" +) + +// ComputePlus computes the result of a+b. +func ComputePlus(a, b Datum) (d Datum, err error) { + switch a.Kind() { + case KindInt64: + switch b.Kind() { + case KindInt64: + r, err1 := AddInt64(a.GetInt64(), b.GetInt64()) + d.SetInt64(r) + return d, errors.Trace(err1) + case KindUint64: + r, err1 := AddInteger(b.GetUint64(), a.GetInt64()) + d.SetUint64(r) + return d, errors.Trace(err1) + } + case KindUint64: + switch b.Kind() { + case KindInt64: + r, err1 := AddInteger(a.GetUint64(), b.GetInt64()) + d.SetUint64(r) + return d, errors.Trace(err1) + case KindUint64: + r, err1 := AddUint64(a.GetUint64(), b.GetUint64()) + d.SetUint64(r) + return d, errors.Trace(err1) + } + case KindFloat64: + switch b.Kind() { + case KindFloat64: + r := a.GetFloat64() + b.GetFloat64() + d.SetFloat64(r) + return d, nil + } + case KindMysqlDecimal: + switch b.Kind() { + case KindMysqlDecimal: + r := new(MyDecimal) + err = DecimalAdd(a.GetMysqlDecimal(), b.GetMysqlDecimal(), r) + d.SetMysqlDecimal(r) + d.SetFrac(mathutil.Max(a.Frac(), b.Frac())) + return d, err + } + } + _, err = InvOp2(a.GetValue(), b.GetValue(), opcode.Plus) + return d, err +} diff --git a/vendor/github.com/pingcap/tidb/types/enum.go b/vendor/github.com/pingcap/tidb/types/enum.go new file mode 100644 index 0000000000000000000000000000000000000000..45c15a3d2208f662a6ad9708c0b9950ea0d53ccf --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/enum.go @@ -0,0 +1,62 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "strconv" + "strings" + + "github.com/pingcap/errors" +) + +// Enum is for MySQL enum type. +type Enum struct { + Name string + Value uint64 +} + +// String implements fmt.Stringer interface. +func (e Enum) String() string { + return e.Name +} + +// ToNumber changes enum index to float64 for numeric operation. +func (e Enum) ToNumber() float64 { + return float64(e.Value) +} + +// ParseEnumName creates a Enum with item name. +func ParseEnumName(elems []string, name string) (Enum, error) { + for i, n := range elems { + if strings.EqualFold(n, name) { + return Enum{Name: n, Value: uint64(i) + 1}, nil + } + } + + // name doesn't exist, maybe an integer? + if num, err := strconv.ParseUint(name, 0, 64); err == nil { + return ParseEnumValue(elems, num) + } + + return Enum{}, errors.Errorf("item %s is not in enum %v", name, elems) +} + +// ParseEnumValue creates a Enum with special number. +func ParseEnumValue(elems []string, number uint64) (Enum, error) { + if number == 0 || number > uint64(len(elems)) { + return Enum{}, errors.Errorf("number %d overflow enum boundary [1, %d]", number, len(elems)) + } + + return Enum{Name: elems[number-1], Value: number}, nil +} diff --git a/vendor/github.com/pingcap/tidb/types/errors.go b/vendor/github.com/pingcap/tidb/types/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..f1f012cbea6e07ffbd5668ef56b3120b36e100e7 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/errors.go @@ -0,0 +1,114 @@ +// Copyright 2016 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" + parser_types "github.com/pingcap/parser/types" +) + +var ( + // ErrDataTooLong is returned when converts a string value that is longer than field type length. + ErrDataTooLong = terror.ClassTypes.New(codeDataTooLong, "Data Too Long") + // ErrIllegalValueForType is returned when value of type is illegal. + ErrIllegalValueForType = terror.ClassTypes.New(codeIllegalValueForType, mysql.MySQLErrName[mysql.ErrIllegalValueForType]) + // ErrTruncated is returned when data has been truncated during conversion. + ErrTruncated = terror.ClassTypes.New(codeTruncated, "Data Truncated") + // ErrTruncatedWrongVal is returned when data has been truncated during conversion. + ErrTruncatedWrongVal = terror.ClassTypes.New(codeTruncatedWrongValue, msgTruncatedWrongVal) + // ErrOverflow is returned when data is out of range for a field type. + ErrOverflow = terror.ClassTypes.New(codeOverflow, msgOverflow) + // ErrDivByZero is return when do division by 0. + ErrDivByZero = terror.ClassTypes.New(codeDivByZero, "Division by 0") + // ErrTooBigDisplayWidth is return when display width out of range for column. + ErrTooBigDisplayWidth = terror.ClassTypes.New(codeTooBigDisplayWidth, "Too Big Display width") + // ErrTooBigFieldLength is return when column length too big for column. + ErrTooBigFieldLength = terror.ClassTypes.New(codeTooBigFieldLength, "Too Big Field length") + // ErrTooBigSet is returned when too many strings for column. + ErrTooBigSet = terror.ClassTypes.New(codeTooBigSet, "Too Big Set") + // ErrTooBigScale is returned when type DECIMAL/NUMERIC scale is bigger than mysql.MaxDecimalScale. + ErrTooBigScale = terror.ClassTypes.New(codeTooBigScale, mysql.MySQLErrName[mysql.ErrTooBigScale]) + // ErrTooBigPrecision is returned when type DECIMAL/NUMERIC precision is bigger than mysql.MaxDecimalWidth + ErrTooBigPrecision = terror.ClassTypes.New(codeTooBigPrecision, mysql.MySQLErrName[mysql.ErrTooBigPrecision]) + // ErrWrongFieldSpec is return when incorrect column specifier for column. + ErrWrongFieldSpec = terror.ClassTypes.New(codeWrongFieldSpec, "Wrong Field Spec") + // ErrBadNumber is return when parsing an invalid binary decimal number. + ErrBadNumber = terror.ClassTypes.New(codeBadNumber, "Bad Number") + // ErrInvalidDefault is returned when meet a invalid default value. + ErrInvalidDefault = parser_types.ErrInvalidDefault + // ErrCastAsSignedOverflow is returned when positive out-of-range integer, and convert to it's negative complement. + ErrCastAsSignedOverflow = terror.ClassTypes.New(codeUnknown, msgCastAsSignedOverflow) + // ErrCastNegIntAsUnsigned is returned when a negative integer be casted to an unsigned int. + ErrCastNegIntAsUnsigned = terror.ClassTypes.New(codeUnknown, msgCastNegIntAsUnsigned) + // ErrMBiggerThanD is returned when precision less than the scale. + ErrMBiggerThanD = terror.ClassTypes.New(codeMBiggerThanD, mysql.MySQLErrName[mysql.ErrMBiggerThanD]) + // ErrWarnDataOutOfRange is returned when the value in a numeric column that is outside the permissible range of the column data type. + // See https://dev.mysql.com/doc/refman/5.5/en/out-of-range-and-overflow.html for details + ErrWarnDataOutOfRange = terror.ClassTypes.New(codeDataOutOfRange, mysql.MySQLErrName[mysql.ErrWarnDataOutOfRange]) + // ErrDuplicatedValueInType is returned when enum column has duplicated value. + ErrDuplicatedValueInType = terror.ClassTypes.New(codeDuplicatedValueInType, mysql.MySQLErrName[mysql.ErrDuplicatedValueInType]) +) + +const ( + codeBadNumber terror.ErrCode = 1 + + codeDataTooLong = terror.ErrCode(mysql.ErrDataTooLong) + codeIllegalValueForType = terror.ErrCode(mysql.ErrIllegalValueForType) + codeTruncated = terror.ErrCode(mysql.WarnDataTruncated) + codeOverflow = terror.ErrCode(mysql.ErrDataOutOfRange) + codeDivByZero = terror.ErrCode(mysql.ErrDivisionByZero) + codeTooBigDisplayWidth = terror.ErrCode(mysql.ErrTooBigDisplaywidth) + codeTooBigFieldLength = terror.ErrCode(mysql.ErrTooBigFieldlength) + codeTooBigSet = terror.ErrCode(mysql.ErrTooBigSet) + codeTooBigScale = terror.ErrCode(mysql.ErrTooBigScale) + codeTooBigPrecision = terror.ErrCode(mysql.ErrTooBigPrecision) + codeWrongFieldSpec = terror.ErrCode(mysql.ErrWrongFieldSpec) + codeTruncatedWrongValue = terror.ErrCode(mysql.ErrTruncatedWrongValue) + codeUnknown = terror.ErrCode(mysql.ErrUnknown) + codeInvalidDefault = terror.ErrCode(mysql.ErrInvalidDefault) + codeMBiggerThanD = terror.ErrCode(mysql.ErrMBiggerThanD) + codeDataOutOfRange = terror.ErrCode(mysql.ErrWarnDataOutOfRange) + codeDuplicatedValueInType = terror.ErrCode(mysql.ErrDuplicatedValueInType) +) + +var ( + msgOverflow = mysql.MySQLErrName[mysql.ErrDataOutOfRange] + msgTruncatedWrongVal = mysql.MySQLErrName[mysql.ErrTruncatedWrongValue] + msgCastAsSignedOverflow = "Cast to signed converted positive out-of-range integer to it's negative complement" + msgCastNegIntAsUnsigned = "Cast to unsigned converted negative integer to it's positive complement" +) + +func init() { + typesMySQLErrCodes := map[terror.ErrCode]uint16{ + codeDataTooLong: mysql.ErrDataTooLong, + codeIllegalValueForType: mysql.ErrIllegalValueForType, + codeTruncated: mysql.WarnDataTruncated, + codeOverflow: mysql.ErrDataOutOfRange, + codeDivByZero: mysql.ErrDivisionByZero, + codeTooBigDisplayWidth: mysql.ErrTooBigDisplaywidth, + codeTooBigFieldLength: mysql.ErrTooBigFieldlength, + codeTooBigSet: mysql.ErrTooBigSet, + codeTooBigScale: mysql.ErrTooBigScale, + codeTooBigPrecision: mysql.ErrTooBigPrecision, + codeWrongFieldSpec: mysql.ErrWrongFieldSpec, + codeTruncatedWrongValue: mysql.ErrTruncatedWrongValue, + codeUnknown: mysql.ErrUnknown, + codeInvalidDefault: mysql.ErrInvalidDefault, + codeMBiggerThanD: mysql.ErrMBiggerThanD, + codeDataOutOfRange: mysql.ErrWarnDataOutOfRange, + codeDuplicatedValueInType: mysql.ErrDuplicatedValueInType, + } + terror.ErrClassToMySQLCodes[terror.ClassTypes] = typesMySQLErrCodes +} diff --git a/vendor/github.com/pingcap/tidb/types/etc.go b/vendor/github.com/pingcap/tidb/types/etc.go new file mode 100644 index 0000000000000000000000000000000000000000..b8b5af64f38d5f857405f4f8f21065d866423492 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/etc.go @@ -0,0 +1,172 @@ +// Copyright 2014 The ql Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSES/QL-LICENSE file. + +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "io" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/charset" + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/opcode" + "github.com/pingcap/parser/terror" + ast "github.com/pingcap/parser/types" +) + +// IsTypeBlob returns a boolean indicating whether the tp is a blob type. +var IsTypeBlob = ast.IsTypeBlob + +// IsTypeChar returns a boolean indicating +// whether the tp is the char type like a string type or a varchar type. +var IsTypeChar = ast.IsTypeChar + +// IsTypeVarchar returns a boolean indicating +// whether the tp is the varchar type like a varstring type or a varchar type. +func IsTypeVarchar(tp byte) bool { + return tp == mysql.TypeVarString || tp == mysql.TypeVarchar +} + +// IsTypeUnspecified returns a boolean indicating whether the tp is the Unspecified type. +func IsTypeUnspecified(tp byte) bool { + return tp == mysql.TypeUnspecified +} + +// IsTypePrefixable returns a boolean indicating +// whether an index on a column with the tp can be defined with a prefix. +func IsTypePrefixable(tp byte) bool { + return IsTypeBlob(tp) || IsTypeChar(tp) +} + +// IsTypeFractionable returns a boolean indicating +// whether the tp can has time fraction. +func IsTypeFractionable(tp byte) bool { + return tp == mysql.TypeDatetime || tp == mysql.TypeDuration || tp == mysql.TypeTimestamp +} + +// IsTypeTime returns a boolean indicating +// whether the tp is time type like datetime, date or timestamp. +func IsTypeTime(tp byte) bool { + return tp == mysql.TypeDatetime || tp == mysql.TypeDate || tp == mysql.TypeTimestamp +} + +// IsTypeNumeric returns a boolean indicating whether the tp is numeric type. +func IsTypeNumeric(tp byte) bool { + switch tp { + case mysql.TypeBit, mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeNewDecimal, + mysql.TypeDecimal, mysql.TypeFloat, mysql.TypeDouble, mysql.TypeShort: + return true + } + return false +} + +// IsTemporalWithDate returns a boolean indicating +// whether the tp is time type with date. +func IsTemporalWithDate(tp byte) bool { + return IsTypeTime(tp) +} + +// IsBinaryStr returns a boolean indicating +// whether the field type is a binary string type. +func IsBinaryStr(ft *FieldType) bool { + if ft.Collate == charset.CollationBin && IsString(ft.Tp) { + return true + } + return false +} + +// IsNonBinaryStr returns a boolean indicating +// whether the field type is a non-binary string type. +func IsNonBinaryStr(ft *FieldType) bool { + if ft.Collate != charset.CollationBin && IsString(ft.Tp) { + return true + } + return false +} + +// IsString returns a boolean indicating +// whether the field type is a string type. +func IsString(tp byte) bool { + return IsTypeChar(tp) || IsTypeBlob(tp) || IsTypeVarchar(tp) || IsTypeUnspecified(tp) +} + +var kind2Str = map[byte]string{ + KindNull: "null", + KindInt64: "bigint", + KindUint64: "unsigned bigint", + KindFloat32: "float", + KindFloat64: "double", + KindString: "char", + KindBytes: "bytes", + KindBinaryLiteral: "bit/hex literal", + KindMysqlDecimal: "decimal", + KindMysqlDuration: "time", + KindMysqlEnum: "enum", + KindMysqlBit: "bit", + KindMysqlSet: "set", + KindMysqlTime: "datetime", + KindInterface: "interface", + KindMinNotNull: "min_not_null", + KindMaxValue: "max_value", + KindRaw: "raw", + KindMysqlJSON: "json", +} + +// TypeStr converts tp to a string. +var TypeStr = ast.TypeStr + +// KindStr converts kind to a string. +func KindStr(kind byte) (r string) { + return kind2Str[kind] +} + +// TypeToStr converts a field to a string. +// It is used for converting Text to Blob, +// or converting Char to Binary. +// Args: +// tp: type enum +// cs: charset +var TypeToStr = ast.TypeToStr + +// EOFAsNil filtrates errors, +// If err is equal to io.EOF returns nil. +func EOFAsNil(err error) error { + if terror.ErrorEqual(err, io.EOF) { + return nil + } + return errors.Trace(err) +} + +// InvOp2 returns an invalid operation error. +func InvOp2(x, y interface{}, o opcode.Op) (interface{}, error) { + return nil, errors.Errorf("Invalid operation: %v %v %v (mismatched types %T and %T)", x, o, y, x, y) +} + +// overflow returns an overflowed error. +func overflow(v interface{}, tp byte) error { + return ErrOverflow.GenWithStack("constant %v overflows %s", v, TypeStr(tp)) +} + +// IsTypeTemporal checks if a type is a temporal type. +func IsTypeTemporal(tp byte) bool { + switch tp { + case mysql.TypeDuration, mysql.TypeDatetime, mysql.TypeTimestamp, + mysql.TypeDate, mysql.TypeNewDate: + return true + } + return false +} diff --git a/vendor/github.com/pingcap/tidb/types/eval_type.go b/vendor/github.com/pingcap/tidb/types/eval_type.go new file mode 100644 index 0000000000000000000000000000000000000000..3eb17cae856f9738890b11084690b3a0fbbbb925 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/eval_type.go @@ -0,0 +1,38 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ast "github.com/pingcap/parser/types" + +// EvalType indicates the specified types that arguments and result of a built-in function should be. +type EvalType = ast.EvalType + +const ( + // ETInt represents type INT in evaluation. + ETInt = ast.ETInt + // ETReal represents type REAL in evaluation. + ETReal = ast.ETReal + // ETDecimal represents type DECIMAL in evaluation. + ETDecimal = ast.ETDecimal + // ETString represents type STRING in evaluation. + ETString = ast.ETString + // ETDatetime represents type DATETIME in evaluation. + ETDatetime = ast.ETDatetime + // ETTimestamp represents type TIMESTAMP in evaluation. + ETTimestamp = ast.ETTimestamp + // ETDuration represents type DURATION in evaluation. + ETDuration = ast.ETDuration + // ETJson represents type JSON in evaluation. + ETJson = ast.ETJson +) diff --git a/vendor/github.com/pingcap/tidb/types/field_type.go b/vendor/github.com/pingcap/tidb/types/field_type.go new file mode 100644 index 0000000000000000000000000000000000000000..7fd81b97b947337c8164c7d8715b38690eab758d --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/field_type.go @@ -0,0 +1,1219 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "strconv" + + "github.com/pingcap/parser/charset" + "github.com/pingcap/parser/mysql" + ast "github.com/pingcap/parser/types" + "github.com/pingcap/tidb/types/json" +) + +// UnspecifiedLength is unspecified length. +const ( + UnspecifiedLength = -1 +) + +// FieldType records field type information. +type FieldType = ast.FieldType + +// NewFieldType returns a FieldType, +// with a type and other information about field type. +func NewFieldType(tp byte) *FieldType { + return &FieldType{ + Tp: tp, + Flen: UnspecifiedLength, + Decimal: UnspecifiedLength, + } +} + +// AggFieldType aggregates field types for a multi-argument function like `IF`, `IFNULL`, `COALESCE` +// whose return type is determined by the arguments' FieldTypes. +// Aggregation is performed by MergeFieldType function. +func AggFieldType(tps []*FieldType) *FieldType { + var currType FieldType + for i, t := range tps { + if i == 0 && currType.Tp == mysql.TypeUnspecified { + currType = *t + continue + } + mtp := MergeFieldType(currType.Tp, t.Tp) + currType.Tp = mtp + } + + return &currType +} + +// AggregateEvalType aggregates arguments' EvalType of a multi-argument function. +func AggregateEvalType(fts []*FieldType, flag *uint) EvalType { + var ( + aggregatedEvalType = ETString + unsigned bool + gotFirst bool + gotBinString bool + ) + lft := fts[0] + for _, ft := range fts { + if ft.Tp == mysql.TypeNull { + continue + } + et := ft.EvalType() + rft := ft + if (IsTypeBlob(ft.Tp) || IsTypeVarchar(ft.Tp) || IsTypeChar(ft.Tp)) && mysql.HasBinaryFlag(ft.Flag) { + gotBinString = true + } + if !gotFirst { + gotFirst = true + aggregatedEvalType = et + unsigned = mysql.HasUnsignedFlag(ft.Flag) + } else { + aggregatedEvalType = mergeEvalType(aggregatedEvalType, et, lft, rft, unsigned, mysql.HasUnsignedFlag(ft.Flag)) + unsigned = unsigned && mysql.HasUnsignedFlag(ft.Flag) + } + lft = rft + } + setTypeFlag(flag, mysql.UnsignedFlag, unsigned) + setTypeFlag(flag, mysql.BinaryFlag, !aggregatedEvalType.IsStringKind() || gotBinString) + return aggregatedEvalType +} + +func mergeEvalType(lhs, rhs EvalType, lft, rft *FieldType, isLHSUnsigned, isRHSUnsigned bool) EvalType { + if lft.Tp == mysql.TypeUnspecified || rft.Tp == mysql.TypeUnspecified { + if lft.Tp == rft.Tp { + return ETString + } + if lft.Tp == mysql.TypeUnspecified { + lhs = rhs + } else { + rhs = lhs + } + } + if lhs.IsStringKind() || rhs.IsStringKind() { + return ETString + } else if lhs == ETReal || rhs == ETReal { + return ETReal + } else if lhs == ETDecimal || rhs == ETDecimal || isLHSUnsigned != isRHSUnsigned { + return ETDecimal + } + return ETInt +} + +func setTypeFlag(flag *uint, flagItem uint, on bool) { + if on { + *flag |= flagItem + } else { + *flag &= ^flagItem + } +} + +// DefaultParamTypeForValue returns the default FieldType for the parameterized value. +func DefaultParamTypeForValue(value interface{}, tp *FieldType) { + switch value.(type) { + case nil: + tp.Tp = mysql.TypeUnspecified + tp.Flen = UnspecifiedLength + tp.Decimal = UnspecifiedLength + default: + DefaultTypeForValue(value, tp) + } +} + +// DefaultTypeForValue returns the default FieldType for the value. +func DefaultTypeForValue(value interface{}, tp *FieldType) { + switch x := value.(type) { + case nil: + tp.Tp = mysql.TypeNull + tp.Flen = 0 + tp.Decimal = 0 + SetBinChsClnFlag(tp) + case bool: + tp.Tp = mysql.TypeLonglong + tp.Flen = 1 + tp.Decimal = 0 + tp.Flag |= mysql.IsBooleanFlag + SetBinChsClnFlag(tp) + case int: + tp.Tp = mysql.TypeLonglong + tp.Flen = len(strconv.FormatInt(int64(x), 10)) + tp.Decimal = 0 + SetBinChsClnFlag(tp) + case int64: + tp.Tp = mysql.TypeLonglong + tp.Flen = len(strconv.FormatInt(x, 10)) + tp.Decimal = 0 + SetBinChsClnFlag(tp) + case uint64: + tp.Tp = mysql.TypeLonglong + tp.Flag |= mysql.UnsignedFlag + tp.Flen = len(strconv.FormatUint(x, 10)) + tp.Decimal = 0 + SetBinChsClnFlag(tp) + case string: + tp.Tp = mysql.TypeVarString + // TODO: tp.Flen should be len(x) * 3 (max bytes length of CharsetUTF8) + tp.Flen = len(x) + tp.Decimal = UnspecifiedLength + tp.Charset, tp.Collate = charset.GetDefaultCharsetAndCollate() + case float64: + tp.Tp = mysql.TypeDouble + s := strconv.FormatFloat(x, 'f', -1, 64) + tp.Flen = len(s) + tp.Decimal = UnspecifiedLength + SetBinChsClnFlag(tp) + case []byte: + tp.Tp = mysql.TypeBlob + tp.Flen = len(x) + tp.Decimal = UnspecifiedLength + SetBinChsClnFlag(tp) + case BitLiteral: + tp.Tp = mysql.TypeVarString + tp.Flen = len(x) + tp.Decimal = 0 + SetBinChsClnFlag(tp) + case HexLiteral: + tp.Tp = mysql.TypeVarString + tp.Flen = len(x) + tp.Decimal = 0 + tp.Flag |= mysql.UnsignedFlag + SetBinChsClnFlag(tp) + case BinaryLiteral: + tp.Tp = mysql.TypeBit + tp.Flen = len(x) * 8 + tp.Decimal = 0 + SetBinChsClnFlag(tp) + tp.Flag &= ^mysql.BinaryFlag + tp.Flag |= mysql.UnsignedFlag + case Time: + tp.Tp = x.Type + switch x.Type { + case mysql.TypeDate: + tp.Flen = mysql.MaxDateWidth + tp.Decimal = UnspecifiedLength + case mysql.TypeDatetime, mysql.TypeTimestamp: + tp.Flen = mysql.MaxDatetimeWidthNoFsp + if x.Fsp > DefaultFsp { // consider point('.') and the fractional part. + tp.Flen += x.Fsp + 1 + } + tp.Decimal = x.Fsp + } + SetBinChsClnFlag(tp) + case Duration: + tp.Tp = mysql.TypeDuration + tp.Flen = len(x.String()) + if x.Fsp > DefaultFsp { // consider point('.') and the fractional part. + tp.Flen = x.Fsp + 1 + } + tp.Decimal = x.Fsp + SetBinChsClnFlag(tp) + case *MyDecimal: + tp.Tp = mysql.TypeNewDecimal + tp.Flen = len(x.ToString()) + tp.Decimal = int(x.digitsFrac) + SetBinChsClnFlag(tp) + case Enum: + tp.Tp = mysql.TypeEnum + tp.Flen = len(x.Name) + tp.Decimal = UnspecifiedLength + SetBinChsClnFlag(tp) + case Set: + tp.Tp = mysql.TypeSet + tp.Flen = len(x.Name) + tp.Decimal = UnspecifiedLength + SetBinChsClnFlag(tp) + case json.BinaryJSON: + tp.Tp = mysql.TypeJSON + tp.Flen = UnspecifiedLength + tp.Decimal = 0 + tp.Charset = charset.CharsetBin + tp.Collate = charset.CollationBin + default: + tp.Tp = mysql.TypeUnspecified + tp.Flen = UnspecifiedLength + tp.Decimal = UnspecifiedLength + } +} + +// DefaultCharsetForType returns the default charset/collation for mysql type. +func DefaultCharsetForType(tp byte) (string, string) { + switch tp { + case mysql.TypeVarString, mysql.TypeString, mysql.TypeVarchar: + // Default charset for string types is utf8. + return mysql.DefaultCharset, mysql.DefaultCollationName + } + return charset.CharsetBin, charset.CollationBin +} + +// MergeFieldType merges two MySQL type to a new type. +// This is used in hybrid field type expression. +// For example "select case c when 1 then 2 when 2 then 'tidb' from t;" +// The result field type of the case expression is the merged type of the two when clause. +// See https://github.com/mysql/mysql-server/blob/5.7/sql/field.cc#L1042 +func MergeFieldType(a byte, b byte) byte { + ia := getFieldTypeIndex(a) + ib := getFieldTypeIndex(b) + return fieldTypeMergeRules[ia][ib] +} + +func getFieldTypeIndex(tp byte) int { + itp := int(tp) + if itp < fieldTypeTearFrom { + return itp + } + return fieldTypeTearFrom + itp - fieldTypeTearTo - 1 +} + +const ( + fieldTypeTearFrom = int(mysql.TypeBit) + 1 + fieldTypeTearTo = int(mysql.TypeJSON) - 1 + fieldTypeNum = fieldTypeTearFrom + (255 - fieldTypeTearTo) +) + +var fieldTypeMergeRules = [fieldTypeNum][fieldTypeNum]byte{ + /* mysql.TypeDecimal -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeNewDecimal, + //mysql.TypeShort mysql.TypeLong + mysql.TypeNewDecimal, mysql.TypeNewDecimal, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeDecimal, mysql.TypeDecimal, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeTiny -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeTiny, + //mysql.TypeShort mysql.TypeLong + mysql.TypeShort, mysql.TypeLong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeTiny, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeInt24, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeTiny, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeShort -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeShort, + //mysql.TypeShort mysql.TypeLong + mysql.TypeShort, mysql.TypeLong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeShort, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeInt24, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeShort, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeLong -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeLong, + //mysql.TypeShort mysql.TypeLong + mysql.TypeLong, mysql.TypeLong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeLong, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeLong, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeLong, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeFloat -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeDouble, mysql.TypeFloat, + //mysql.TypeShort mysql.TypeLong + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeFloat, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeFloat, mysql.TypeFloat, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeFloat, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeDouble, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeDouble -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeShort mysql.TypeLong + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeDouble, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeDouble, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeDouble, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeNull -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeTiny, + //mysql.TypeShort mysql.TypeLong + mysql.TypeShort, mysql.TypeLong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeNull, mysql.TypeTimestamp, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeLonglong, + //mysql.TypeDate mysql.TypeTime + mysql.TypeDate, mysql.TypeDuration, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeDatetime, mysql.TypeYear, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeBit, + //mysql.TypeJSON + mysql.TypeJSON, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeEnum, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeSet, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeGeometry, + }, + /* mysql.TypeTimestamp -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeTimestamp, mysql.TypeTimestamp, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeDatetime, mysql.TypeDatetime, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeDatetime, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeLonglong -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeLonglong, + //mysql.TypeShort mysql.TypeLong + mysql.TypeLonglong, mysql.TypeLonglong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeLonglong, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeLong, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeLonglong, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeInt24 -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeInt24, + //mysql.TypeShort mysql.TypeLong + mysql.TypeInt24, mysql.TypeLong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeInt24, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeInt24, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeInt24, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeDate -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeDate, mysql.TypeDatetime, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeDate, mysql.TypeDatetime, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeDatetime, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeTime -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeDuration, mysql.TypeDatetime, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeDatetime, mysql.TypeDuration, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeDatetime, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeDatetime -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeDatetime, mysql.TypeDatetime, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeDatetime, mysql.TypeDatetime, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeDatetime, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeYear -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeDecimal, mysql.TypeTiny, + //mysql.TypeShort mysql.TypeLong + mysql.TypeShort, mysql.TypeLong, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeFloat, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeYear, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLonglong, mysql.TypeInt24, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeYear, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeNewDate -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeNewDate, mysql.TypeDatetime, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeNewDate, mysql.TypeDatetime, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeDatetime, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeNewDate, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeVarchar -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeVarchar, mysql.TypeVarchar, + }, + /* mysql.TypeBit -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeBit, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeBit, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeJSON -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeJSON, mysql.TypeVarchar, + //mysql.TypeLongLONG mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate MYSQL_TYPE_TIME + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime MYSQL_TYPE_YEAR + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeJSON, + //mysql.TypeNewDecimal MYSQL_TYPE_ENUM + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeLongBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeLongBlob, mysql.TypeVarchar, + //mysql.TypeString MYSQL_TYPE_GEOMETRY + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeNewDecimal -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeNewDecimal, mysql.TypeNewDecimal, + //mysql.TypeShort mysql.TypeLong + mysql.TypeNewDecimal, mysql.TypeNewDecimal, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeDouble, mysql.TypeDouble, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeNewDecimal, mysql.TypeNewDecimal, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeNewDecimal, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeNewDecimal, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeEnum -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeEnum, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeSet -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeSet, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeVarchar, + }, + /* mysql.TypeTinyBlob -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeShort mysql.TypeLong + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeDate mysql.TypeTime + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeBit <16>-<244> + mysql.TypeTinyBlob, + //mysql.TypeJSON + mysql.TypeLongBlob, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeTinyBlob, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeTinyBlob, mysql.TypeTinyBlob, + }, + /* mysql.TypeMediumBlob -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeShort mysql.TypeLong + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeDate mysql.TypeTime + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeBit <16>-<244> + mysql.TypeMediumBlob, + //mysql.TypeJSON + mysql.TypeLongBlob, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeMediumBlob, mysql.TypeMediumBlob, + }, + /* mysql.TypeLongBlob -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeShort mysql.TypeLong + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeDate mysql.TypeTime + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeBit <16>-<244> + mysql.TypeLongBlob, + //mysql.TypeJSON + mysql.TypeLongBlob, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeLongBlob, mysql.TypeLongBlob, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeLongBlob, mysql.TypeLongBlob, + }, + /* mysql.TypeBlob -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeShort mysql.TypeLong + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeDate mysql.TypeTime + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeBit <16>-<244> + mysql.TypeBlob, + //mysql.TypeJSON + mysql.TypeLongBlob, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeBlob, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeBlob, mysql.TypeBlob, + }, + /* mysql.TypeVarString -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeVarchar, mysql.TypeVarchar, + }, + /* mysql.TypeString -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeString, mysql.TypeString, + //mysql.TypeShort mysql.TypeLong + mysql.TypeString, mysql.TypeString, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeString, mysql.TypeString, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeString, mysql.TypeString, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeString, mysql.TypeString, + //mysql.TypeDate mysql.TypeTime + mysql.TypeString, mysql.TypeString, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeString, mysql.TypeString, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeString, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeString, + //mysql.TypeJSON + mysql.TypeString, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeString, mysql.TypeString, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeString, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeString, + }, + /* mysql.TypeGeometry -> */ + { + //mysql.TypeDecimal mysql.TypeTiny + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeShort mysql.TypeLong + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeFloat mysql.TypeDouble + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNull mysql.TypeTimestamp + mysql.TypeGeometry, mysql.TypeVarchar, + //mysql.TypeLonglong mysql.TypeInt24 + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDate mysql.TypeTime + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeDatetime mysql.TypeYear + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeNewDate mysql.TypeVarchar + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeBit <16>-<244> + mysql.TypeVarchar, + //mysql.TypeJSON + mysql.TypeVarchar, + //mysql.TypeNewDecimal mysql.TypeEnum + mysql.TypeVarchar, mysql.TypeVarchar, + //mysql.TypeSet mysql.TypeTinyBlob + mysql.TypeVarchar, mysql.TypeTinyBlob, + //mysql.TypeMediumBlob mysql.TypeLongBlob + mysql.TypeMediumBlob, mysql.TypeLongBlob, + //mysql.TypeBlob mysql.TypeVarString + mysql.TypeBlob, mysql.TypeVarchar, + //mysql.TypeString mysql.TypeGeometry + mysql.TypeString, mysql.TypeGeometry, + }, +} + +// SetBinChsClnFlag sets charset, collation as 'binary' and adds binaryFlag to FieldType. +func SetBinChsClnFlag(ft *FieldType) { + ft.Charset = charset.CharsetBin + ft.Collate = charset.CollationBin + ft.Flag |= mysql.BinaryFlag +} + +// VarStorageLen indicates this column is a variable length column. +const VarStorageLen = ast.VarStorageLen diff --git a/vendor/github.com/pingcap/tidb/types/fsp.go b/vendor/github.com/pingcap/tidb/types/fsp.go new file mode 100644 index 0000000000000000000000000000000000000000..fe5a656cd87bb6977f4fa21f758f2a7cef0c283e --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/fsp.go @@ -0,0 +1,97 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "math" + "strconv" + "strings" + + "github.com/pingcap/errors" +) + +const ( + // UnspecifiedFsp is the unspecified fractional seconds part. + UnspecifiedFsp = -1 + // MaxFsp is the maximum digit of fractional seconds part. + MaxFsp = 6 + // MinFsp is the minimum digit of fractional seconds part. + MinFsp = 0 + // DefaultFsp is the default digit of fractional seconds part. + // MySQL use 0 as the default Fsp. + DefaultFsp = 0 +) + +// CheckFsp checks whether fsp is in valid range. +func CheckFsp(fsp int) (int, error) { + if fsp == UnspecifiedFsp { + return DefaultFsp, nil + } + if fsp < MinFsp || fsp > MaxFsp { + return DefaultFsp, errors.Errorf("Invalid fsp %d", fsp) + } + return fsp, nil +} + +// ParseFrac parses the input string according to fsp, returns the microsecond, +// and also a bool value to indice overflow. eg: +// "999" fsp=2 will overflow. +func ParseFrac(s string, fsp int) (v int, overflow bool, err error) { + if len(s) == 0 { + return 0, false, nil + } + + fsp, err = CheckFsp(fsp) + if err != nil { + return 0, false, errors.Trace(err) + } + + if fsp >= len(s) { + tmp, e := strconv.ParseInt(s, 10, 64) + if e != nil { + return 0, false, errors.Trace(e) + } + v = int(float64(tmp) * math.Pow10(MaxFsp-len(s))) + return + } + + // Round when fsp < string length. + tmp, e := strconv.ParseInt(s[:fsp+1], 10, 64) + if e != nil { + return 0, false, errors.Trace(e) + } + tmp = (tmp + 5) / 10 + + if float64(tmp) >= math.Pow10(fsp) { + // overflow + return 0, true, nil + } + + // Get the final frac, with 6 digit number + // 1236 round 3 -> 124 -> 124000 + // 0312 round 2 -> 3 -> 30000 + // 999 round 2 -> 100 -> overflow + v = int(float64(tmp) * math.Pow10(MaxFsp-fsp)) + return +} + +// alignFrac is used to generate alignment frac, like `100` -> `100000` +func alignFrac(s string, fsp int) string { + sl := len(s) + if sl < fsp { + return s + strings.Repeat("0", fsp-sl) + } + + return s +} diff --git a/vendor/github.com/pingcap/tidb/types/helper.go b/vendor/github.com/pingcap/tidb/types/helper.go new file mode 100644 index 0000000000000000000000000000000000000000..f03dc1390c6dec0885ca6976dcd51a9429cae474 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/helper.go @@ -0,0 +1,195 @@ +// Copyright 2015 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "math" + "strings" + "unicode" + + "github.com/pingcap/errors" +) + +// RoundFloat rounds float val to the nearest integer value with float64 format, like MySQL Round function. +// RoundFloat uses default rounding mode, see https://dev.mysql.com/doc/refman/5.7/en/precision-math-rounding.html +// so rounding use "round half away from zero". +// e.g, 1.5 -> 2, -1.5 -> -2. +func RoundFloat(f float64) float64 { + if math.Abs(f) < 0.5 { + return 0 + } + + return math.Trunc(f + math.Copysign(0.5, f)) +} + +// Round rounds the argument f to dec decimal places. +// dec defaults to 0 if not specified. dec can be negative +// to cause dec digits left of the decimal point of the +// value f to become zero. +func Round(f float64, dec int) float64 { + shift := math.Pow10(dec) + tmp := f * shift + if math.IsInf(tmp, 0) { + return f + } + return RoundFloat(tmp) / shift +} + +// Truncate truncates the argument f to dec decimal places. +// dec defaults to 0 if not specified. dec can be negative +// to cause dec digits left of the decimal point of the +// value f to become zero. +func Truncate(f float64, dec int) float64 { + shift := math.Pow10(dec) + tmp := f * shift + if math.IsInf(tmp, 0) { + return f + } + return math.Trunc(tmp) / shift +} + +// GetMaxFloat gets the max float for given flen and decimal. +func GetMaxFloat(flen int, decimal int) float64 { + intPartLen := flen - decimal + f := math.Pow10(intPartLen) + f -= math.Pow10(-decimal) + return f +} + +// TruncateFloat tries to truncate f. +// If the result exceeds the max/min float that flen/decimal allowed, returns the max/min float allowed. +func TruncateFloat(f float64, flen int, decimal int) (float64, error) { + if math.IsNaN(f) { + // nan returns 0 + return 0, ErrOverflow.GenWithStackByArgs("DOUBLE", "") + } + + maxF := GetMaxFloat(flen, decimal) + + if !math.IsInf(f, 0) { + f = Round(f, decimal) + } + + var err error + if f > maxF { + f = maxF + err = ErrOverflow.GenWithStackByArgs("DOUBLE", "") + } else if f < -maxF { + f = -maxF + err = ErrOverflow.GenWithStackByArgs("DOUBLE", "") + } + + return f, errors.Trace(err) +} + +func isSpace(c byte) bool { + return c == ' ' || c == '\t' +} + +func isDigit(c byte) bool { + return c >= '0' && c <= '9' +} + +func myMax(a, b int) int { + if a > b { + return a + } + return b +} + +func myMaxInt8(a, b int8) int8 { + if a > b { + return a + } + return b +} + +func myMin(a, b int) int { + if a < b { + return a + } + return b +} + +func myMinInt8(a, b int8) int8 { + if a < b { + return a + } + return b +} + +const ( + maxUint = uint64(math.MaxUint64) + uintCutOff = maxUint/uint64(10) + 1 + intCutOff = uint64(math.MaxInt64) + 1 +) + +// strToInt converts a string to an integer in best effort. +func strToInt(str string) (int64, error) { + str = strings.TrimSpace(str) + if len(str) == 0 { + return 0, ErrTruncated + } + negative := false + i := 0 + if str[i] == '-' { + negative = true + i++ + } else if str[i] == '+' { + i++ + } + + var ( + err error + hasNum = false + ) + r := uint64(0) + for ; i < len(str); i++ { + if !unicode.IsDigit(rune(str[i])) { + err = ErrTruncated + break + } + hasNum = true + if r >= uintCutOff { + r = 0 + err = errors.Trace(ErrBadNumber) + break + } + r = r * uint64(10) + + r1 := r + uint64(str[i]-'0') + if r1 < r || r1 > maxUint { + r = 0 + err = errors.Trace(ErrBadNumber) + break + } + r = r1 + } + if !hasNum { + err = ErrTruncated + } + + if !negative && r >= intCutOff { + return math.MaxInt64, errors.Trace(ErrBadNumber) + } + + if negative && r > intCutOff { + return math.MinInt64, errors.Trace(ErrBadNumber) + } + + if negative { + r = -r + } + return int64(r), err +} diff --git a/vendor/github.com/pingcap/tidb/types/json/binary.go b/vendor/github.com/pingcap/tidb/types/json/binary.go new file mode 100644 index 0000000000000000000000000000000000000000..c5c277d451cba2efe94dd4f86be3ccdee54a1e8d --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/json/binary.go @@ -0,0 +1,630 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package json + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "unicode/utf8" + + "github.com/pingcap/errors" + "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/util/hack" +) + +/* + The binary JSON format from MySQL 5.7 is as follows: + + JSON doc ::= type value + type ::= + 0x01 | // large JSON object + 0x03 | // large JSON array + 0x04 | // literal (true/false/null) + 0x05 | // int16 + 0x06 | // uint16 + 0x07 | // int32 + 0x08 | // uint32 + 0x09 | // int64 + 0x0a | // uint64 + 0x0b | // double + 0x0c | // utf8mb4 string + + value ::= + object | + array | + literal | + number | + string | + + object ::= element-count size key-entry* value-entry* key* value* + + array ::= element-count size value-entry* value* + + // number of members in object or number of elements in array + element-count ::= uint32 + + // number of bytes in the binary representation of the object or array + size ::= uint32 + + key-entry ::= key-offset key-length + + key-offset ::= uint32 + + key-length ::= uint16 // key length must be less than 64KB + + value-entry ::= type offset-or-inlined-value + + // This field holds either the offset to where the value is stored, + // or the value itself if it is small enough to be inlined (that is, + // if it is a JSON literal or a small enough [u]int). + offset-or-inlined-value ::= uint32 + + key ::= utf8mb4-data + + literal ::= + 0x00 | // JSON null literal + 0x01 | // JSON true literal + 0x02 | // JSON false literal + + number ::= .... // little-endian format for [u]int(16|32|64), whereas + // double is stored in a platform-independent, eight-byte + // format using float8store() + + string ::= data-length utf8mb4-data + + data-length ::= uint8* // If the high bit of a byte is 1, the length + // field is continued in the next byte, + // otherwise it is the last byte of the length + // field. So we need 1 byte to represent + // lengths up to 127, 2 bytes to represent + // lengths up to 16383, and so on... +*/ + +// BinaryJSON represents a binary encoded JSON object. +// It can be randomly accessed without deserialization. +type BinaryJSON struct { + TypeCode TypeCode + Value []byte +} + +// String implements fmt.Stringer interface. +func (bj BinaryJSON) String() string { + out, err := bj.MarshalJSON() + terror.Log(err) + return string(out) +} + +// Copy makes a copy of the BinaryJSON +func (bj BinaryJSON) Copy() BinaryJSON { + buf := make([]byte, len(bj.Value)) + copy(buf, bj.Value) + return BinaryJSON{TypeCode: bj.TypeCode, Value: buf} +} + +// MarshalJSON implements the json.Marshaler interface. +func (bj BinaryJSON) MarshalJSON() ([]byte, error) { + buf := make([]byte, 0, len(bj.Value)*3/2) + return bj.marshalTo(buf) +} + +func (bj BinaryJSON) marshalTo(buf []byte) ([]byte, error) { + switch bj.TypeCode { + case TypeCodeString: + return marshalStringTo(buf, bj.GetString()), nil + case TypeCodeLiteral: + return marshalLiteralTo(buf, bj.Value[0]), nil + case TypeCodeInt64: + return strconv.AppendInt(buf, bj.GetInt64(), 10), nil + case TypeCodeUint64: + return strconv.AppendUint(buf, bj.GetUint64(), 10), nil + case TypeCodeFloat64: + return bj.marshalFloat64To(buf) + case TypeCodeArray: + return bj.marshalArrayTo(buf) + case TypeCodeObject: + return bj.marshalObjTo(buf) + } + return buf, nil +} + +// GetInt64 gets the int64 value. +func (bj BinaryJSON) GetInt64() int64 { + return int64(endian.Uint64(bj.Value)) +} + +// GetUint64 gets the uint64 value. +func (bj BinaryJSON) GetUint64() uint64 { + return endian.Uint64(bj.Value) +} + +// GetFloat64 gets the float64 value. +func (bj BinaryJSON) GetFloat64() float64 { + return math.Float64frombits(bj.GetUint64()) +} + +// GetString gets the string value. +func (bj BinaryJSON) GetString() []byte { + strLen, lenLen := uint64(bj.Value[0]), 1 + if strLen >= utf8.RuneSelf { + strLen, lenLen = binary.Uvarint(bj.Value) + } + return bj.Value[lenLen : lenLen+int(strLen)] +} + +// GetKeys gets the keys of the object +func (bj BinaryJSON) GetKeys() BinaryJSON { + count := bj.GetElemCount() + ret := make([]BinaryJSON, 0, count) + for i := 0; i < count; i++ { + ret = append(ret, CreateBinary(string(bj.objectGetKey(i)))) + } + return buildBinaryArray(ret) +} + +// GetElemCount gets the count of Object or Array. +func (bj BinaryJSON) GetElemCount() int { + return int(endian.Uint32(bj.Value)) +} + +func (bj BinaryJSON) arrayGetElem(idx int) BinaryJSON { + return bj.valEntryGet(headerSize + idx*valEntrySize) +} + +func (bj BinaryJSON) objectGetKey(i int) []byte { + keyOff := int(endian.Uint32(bj.Value[headerSize+i*keyEntrySize:])) + keyLen := int(endian.Uint16(bj.Value[headerSize+i*keyEntrySize+keyLenOff:])) + return bj.Value[keyOff : keyOff+keyLen] +} + +func (bj BinaryJSON) objectGetVal(i int) BinaryJSON { + elemCount := bj.GetElemCount() + return bj.valEntryGet(headerSize + elemCount*keyEntrySize + i*valEntrySize) +} + +func (bj BinaryJSON) valEntryGet(valEntryOff int) BinaryJSON { + tpCode := bj.Value[valEntryOff] + valOff := endian.Uint32(bj.Value[valEntryOff+valTypeSize:]) + switch tpCode { + case TypeCodeLiteral: + return BinaryJSON{TypeCode: TypeCodeLiteral, Value: bj.Value[valEntryOff+valTypeSize : valEntryOff+valTypeSize+1]} + case TypeCodeUint64, TypeCodeInt64, TypeCodeFloat64: + return BinaryJSON{TypeCode: tpCode, Value: bj.Value[valOff : valOff+8]} + case TypeCodeString: + strLen, lenLen := uint64(bj.Value[valOff]), 1 + if strLen >= utf8.RuneSelf { + strLen, lenLen = binary.Uvarint(bj.Value[valOff:]) + } + totalLen := uint32(lenLen) + uint32(strLen) + return BinaryJSON{TypeCode: tpCode, Value: bj.Value[valOff : valOff+totalLen]} + } + dataSize := endian.Uint32(bj.Value[valOff+dataSizeOff:]) + return BinaryJSON{TypeCode: tpCode, Value: bj.Value[valOff : valOff+dataSize]} +} + +func (bj BinaryJSON) marshalFloat64To(buf []byte) ([]byte, error) { + // NOTE: copied from Go standard library. + f := bj.GetFloat64() + if math.IsInf(f, 0) || math.IsNaN(f) { + return buf, &json.UnsupportedValueError{Str: strconv.FormatFloat(f, 'g', -1, 64)} + } + + // Convert as if by ES6 number to string conversion. + // This matches most other JSON generators. + // See golang.org/issue/6384 and golang.org/issue/14135. + // Like fmt %g, but the exponent cutoffs are different + // and exponents themselves are not padded to two digits. + abs := math.Abs(f) + ffmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if abs < 1e-6 || abs >= 1e21 { + ffmt = 'e' + } + } + buf = strconv.AppendFloat(buf, f, ffmt, -1, 64) + if ffmt == 'e' { + // clean up e-09 to e-9 + n := len(buf) + if n >= 4 && buf[n-4] == 'e' && buf[n-3] == '-' && buf[n-2] == '0' { + buf[n-2] = buf[n-1] + buf = buf[:n-1] + } + } + return buf, nil +} + +func (bj BinaryJSON) marshalArrayTo(buf []byte) ([]byte, error) { + elemCount := int(endian.Uint32(bj.Value)) + buf = append(buf, '[') + for i := 0; i < elemCount; i++ { + if i != 0 { + buf = append(buf, ", "...) + } + var err error + buf, err = bj.arrayGetElem(i).marshalTo(buf) + if err != nil { + return nil, errors.Trace(err) + } + } + return append(buf, ']'), nil +} + +func (bj BinaryJSON) marshalObjTo(buf []byte) ([]byte, error) { + elemCount := int(endian.Uint32(bj.Value)) + buf = append(buf, '{') + for i := 0; i < elemCount; i++ { + if i != 0 { + buf = append(buf, ", "...) + } + buf = marshalStringTo(buf, bj.objectGetKey(i)) + buf = append(buf, ": "...) + var err error + buf, err = bj.objectGetVal(i).marshalTo(buf) + if err != nil { + return nil, errors.Trace(err) + } + } + return append(buf, '}'), nil +} + +func marshalStringTo(buf, s []byte) []byte { + // NOTE: copied from Go standard library. + // NOTE: keep in sync with string above. + buf = append(buf, '"') + start := 0 + for i := 0; i < len(s); { + if b := s[i]; b < utf8.RuneSelf { + if htmlSafeSet[b] { + i++ + continue + } + if start < i { + buf = append(buf, s[start:i]...) + } + switch b { + case '\\', '"': + buf = append(buf, '\\', b) + case '\n': + buf = append(buf, '\\', 'n') + case '\r': + buf = append(buf, '\\', 'r') + case '\t': + buf = append(buf, '\\', 't') + default: + // This encodes bytes < 0x20 except for \t, \n and \r. + // If escapeHTML is set, it also escapes <, >, and & + // because they can lead to security holes when + // user-controlled strings are rendered into JSON + // and served to some browsers. + buf = append(buf, `\u00`...) + buf = append(buf, hexChars[b>>4], hexChars[b&0xF]) + } + i++ + start = i + continue + } + c, size := utf8.DecodeRune(s[i:]) + if c == utf8.RuneError && size == 1 { + if start < i { + buf = append(buf, s[start:i]...) + } + buf = append(buf, `\ufffd`...) + i += size + start = i + continue + } + // U+2028 is LINE SEPARATOR. + // U+2029 is PARAGRAPH SEPARATOR. + // They are both technically valid characters in JSON strings, + // but don't work in JSONP, which has to be evaluated as JavaScript, + // and can lead to security holes there. It is valid JSON to + // escape them, so we do so unconditionally. + // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. + if c == '\u2028' || c == '\u2029' { + if start < i { + buf = append(buf, s[start:i]...) + } + buf = append(buf, `\u202`...) + buf = append(buf, hexChars[c&0xF]) + i += size + start = i + continue + } + i += size + } + if start < len(s) { + buf = append(buf, s[start:]...) + } + buf = append(buf, '"') + return buf +} + +func (bj BinaryJSON) marshalValueEntryTo(buf []byte, entryOff int) ([]byte, error) { + tpCode := bj.Value[entryOff] + switch tpCode { + case TypeCodeLiteral: + buf = marshalLiteralTo(buf, bj.Value[entryOff+1]) + default: + offset := endian.Uint32(bj.Value[entryOff+1:]) + tmp := BinaryJSON{TypeCode: tpCode, Value: bj.Value[offset:]} + var err error + buf, err = tmp.marshalTo(buf) + if err != nil { + return nil, errors.Trace(err) + } + } + return buf, nil +} + +func marshalLiteralTo(b []byte, litType byte) []byte { + switch litType { + case LiteralFalse: + return append(b, "false"...) + case LiteralTrue: + return append(b, "true"...) + case LiteralNil: + return append(b, "null"...) + } + return b +} + +// ParseBinaryFromString parses a json from string. +func ParseBinaryFromString(s string) (bj BinaryJSON, err error) { + if len(s) == 0 { + err = ErrInvalidJSONText.GenWithStackByArgs("The document is empty") + return + } + if err = bj.UnmarshalJSON(hack.Slice(s)); err != nil { + err = ErrInvalidJSONText.GenWithStackByArgs(err) + } + return +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (bj *BinaryJSON) UnmarshalJSON(data []byte) error { + var decoder = json.NewDecoder(bytes.NewReader(data)) + decoder.UseNumber() + var in interface{} + err := decoder.Decode(&in) + if err != nil { + return errors.Trace(err) + } + buf := make([]byte, 0, len(data)) + var typeCode TypeCode + typeCode, buf, err = appendBinary(buf, in) + if err != nil { + return errors.Trace(err) + } + bj.TypeCode = typeCode + bj.Value = buf + return nil +} + +// CreateBinary creates a BinaryJSON from interface. +func CreateBinary(in interface{}) BinaryJSON { + typeCode, buf, err := appendBinary(nil, in) + if err != nil { + panic(err) + } + return BinaryJSON{TypeCode: typeCode, Value: buf} +} + +func appendBinary(buf []byte, in interface{}) (TypeCode, []byte, error) { + var typeCode byte + var err error + switch x := in.(type) { + case nil: + typeCode = TypeCodeLiteral + buf = append(buf, LiteralNil) + case bool: + typeCode = TypeCodeLiteral + if x { + buf = append(buf, LiteralTrue) + } else { + buf = append(buf, LiteralFalse) + } + case int64: + typeCode = TypeCodeInt64 + buf = appendBinaryUint64(buf, uint64(x)) + case uint64: + typeCode = TypeCodeUint64 + buf = appendBinaryUint64(buf, x) + case float64: + typeCode = TypeCodeFloat64 + buf = appendBinaryFloat64(buf, x) + case json.Number: + typeCode, buf, err = appendBinaryNumber(buf, x) + if err != nil { + return typeCode, nil, errors.Trace(err) + } + case string: + typeCode = TypeCodeString + buf = appendBinaryString(buf, x) + case BinaryJSON: + typeCode = x.TypeCode + buf = append(buf, x.Value...) + case []interface{}: + typeCode = TypeCodeArray + buf, err = appendBinaryArray(buf, x) + if err != nil { + return typeCode, nil, errors.Trace(err) + } + case map[string]interface{}: + typeCode = TypeCodeObject + buf, err = appendBinaryObject(buf, x) + if err != nil { + return typeCode, nil, errors.Trace(err) + } + default: + msg := fmt.Sprintf(unknownTypeErrorMsg, reflect.TypeOf(in)) + err = errors.New(msg) + } + return typeCode, buf, err +} + +func appendZero(buf []byte, length int) []byte { + var tmp [8]byte + rem := length % 8 + loop := length / 8 + for i := 0; i < loop; i++ { + buf = append(buf, tmp[:]...) + } + for i := 0; i < rem; i++ { + buf = append(buf, 0) + } + return buf +} + +func appendUint32(buf []byte, v uint32) []byte { + var tmp [4]byte + endian.PutUint32(tmp[:], v) + return append(buf, tmp[:]...) +} + +func appendBinaryNumber(buf []byte, x json.Number) (TypeCode, []byte, error) { + var typeCode TypeCode + if strings.ContainsAny(string(x), "Ee.") { + typeCode = TypeCodeFloat64 + f64, err := x.Float64() + if err != nil { + return typeCode, nil, errors.Trace(err) + } + buf = appendBinaryFloat64(buf, f64) + } else { + typeCode = TypeCodeInt64 + i64, err := x.Int64() + if err != nil { + typeCode = TypeCodeFloat64 + f64, err := x.Float64() + if err != nil { + return typeCode, nil, errors.Trace(err) + } + buf = appendBinaryFloat64(buf, f64) + } else { + buf = appendBinaryUint64(buf, uint64(i64)) + } + } + return typeCode, buf, nil +} + +func appendBinaryString(buf []byte, v string) []byte { + begin := len(buf) + buf = appendZero(buf, binary.MaxVarintLen64) + lenLen := binary.PutUvarint(buf[begin:], uint64(len(v))) + buf = buf[:len(buf)-binary.MaxVarintLen64+lenLen] + buf = append(buf, v...) + return buf +} + +func appendBinaryFloat64(buf []byte, v float64) []byte { + off := len(buf) + buf = appendZero(buf, 8) + endian.PutUint64(buf[off:], math.Float64bits(v)) + return buf +} + +func appendBinaryUint64(buf []byte, v uint64) []byte { + off := len(buf) + buf = appendZero(buf, 8) + endian.PutUint64(buf[off:], v) + return buf +} + +func appendBinaryArray(buf []byte, array []interface{}) ([]byte, error) { + docOff := len(buf) + buf = appendUint32(buf, uint32(len(array))) + buf = appendZero(buf, dataSizeOff) + valEntryBegin := len(buf) + buf = appendZero(buf, len(array)*valEntrySize) + for i, val := range array { + var err error + buf, err = appendBinaryValElem(buf, docOff, valEntryBegin+i*valEntrySize, val) + if err != nil { + return nil, errors.Trace(err) + } + } + docSize := len(buf) - docOff + endian.PutUint32(buf[docOff+dataSizeOff:], uint32(docSize)) + return buf, nil +} + +func appendBinaryValElem(buf []byte, docOff, valEntryOff int, val interface{}) ([]byte, error) { + var typeCode TypeCode + var err error + elemDocOff := len(buf) + typeCode, buf, err = appendBinary(buf, val) + if err != nil { + return nil, errors.Trace(err) + } + switch typeCode { + case TypeCodeLiteral: + litCode := buf[elemDocOff] + buf = buf[:elemDocOff] + buf[valEntryOff] = TypeCodeLiteral + buf[valEntryOff+1] = litCode + return buf, nil + } + buf[valEntryOff] = typeCode + valOff := elemDocOff - docOff + endian.PutUint32(buf[valEntryOff+1:], uint32(valOff)) + return buf, nil +} + +type field struct { + key string + val interface{} +} + +func appendBinaryObject(buf []byte, x map[string]interface{}) ([]byte, error) { + docOff := len(buf) + buf = appendUint32(buf, uint32(len(x))) + buf = appendZero(buf, dataSizeOff) + keyEntryBegin := len(buf) + buf = appendZero(buf, len(x)*keyEntrySize) + valEntryBegin := len(buf) + buf = appendZero(buf, len(x)*valEntrySize) + + fields := make([]field, 0, len(x)) + for key, val := range x { + fields = append(fields, field{key: key, val: val}) + } + sort.Slice(fields, func(i, j int) bool { + return fields[i].key < fields[j].key + }) + for i, field := range fields { + keyEntryOff := keyEntryBegin + i*keyEntrySize + keyOff := len(buf) - docOff + keyLen := uint32(len(field.key)) + endian.PutUint32(buf[keyEntryOff:], uint32(keyOff)) + endian.PutUint16(buf[keyEntryOff+keyLenOff:], uint16(keyLen)) + buf = append(buf, field.key...) + } + for i, field := range fields { + var err error + buf, err = appendBinaryValElem(buf, docOff, valEntryBegin+i*valEntrySize, field.val) + if err != nil { + return nil, errors.Trace(err) + } + } + docSize := len(buf) - docOff + endian.PutUint32(buf[docOff+dataSizeOff:], uint32(docSize)) + return buf, nil +} diff --git a/vendor/github.com/pingcap/tidb/types/json/binary_functions.go b/vendor/github.com/pingcap/tidb/types/json/binary_functions.go new file mode 100644 index 0000000000000000000000000000000000000000..93b4b6221f71bafafc167fcdcb8aa63500332e67 --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/json/binary_functions.go @@ -0,0 +1,772 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package json + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "sort" + "unicode/utf8" + "unsafe" + + "github.com/pingcap/errors" + "github.com/pingcap/tidb/util/hack" +) + +// Type returns type of BinaryJSON as string. +func (bj BinaryJSON) Type() string { + switch bj.TypeCode { + case TypeCodeObject: + return "OBJECT" + case TypeCodeArray: + return "ARRAY" + case TypeCodeLiteral: + switch bj.Value[0] { + case LiteralNil: + return "NULL" + default: + return "BOOLEAN" + } + case TypeCodeInt64: + return "INTEGER" + case TypeCodeUint64: + return "UNSIGNED INTEGER" + case TypeCodeFloat64: + return "DOUBLE" + case TypeCodeString: + return "STRING" + default: + msg := fmt.Sprintf(unknownTypeCodeErrorMsg, bj.TypeCode) + panic(msg) + } +} + +// Unquote is for JSON_UNQUOTE. +func (bj BinaryJSON) Unquote() (string, error) { + switch bj.TypeCode { + case TypeCodeString: + s, err := unquoteString(hack.String(bj.GetString())) + if err != nil { + return "", errors.Trace(err) + } + // Remove prefix and suffix '"'. + slen := len(s) + if slen > 1 { + head, tail := s[0], s[slen-1] + if head == '"' && tail == '"' { + return s[1 : slen-1], nil + } + } + return s, nil + default: + return bj.String(), nil + } +} + +// unquoteString recognizes the escape sequences shown in: +// https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#json-unquote-character-escape-sequences +func unquoteString(s string) (string, error) { + ret := new(bytes.Buffer) + for i := 0; i < len(s); i++ { + if s[i] == '\\' { + i++ + if i == len(s) { + return "", errors.New("Missing a closing quotation mark in string") + } + switch s[i] { + case '"': + ret.WriteByte('"') + case 'b': + ret.WriteByte('\b') + case 'f': + ret.WriteByte('\f') + case 'n': + ret.WriteByte('\n') + case 'r': + ret.WriteByte('\r') + case 't': + ret.WriteByte('\t') + case '\\': + ret.WriteByte('\\') + case 'u': + if i+4 > len(s) { + return "", errors.Errorf("Invalid unicode: %s", s[i+1:]) + } + char, size, err := decodeEscapedUnicode(hack.Slice(s[i+1 : i+5])) + if err != nil { + return "", errors.Trace(err) + } + ret.Write(char[0:size]) + i += 4 + default: + // For all other escape sequences, backslash is ignored. + ret.WriteByte(s[i]) + } + } else { + ret.WriteByte(s[i]) + } + } + return ret.String(), nil +} + +// decodeEscapedUnicode decodes unicode into utf8 bytes specified in RFC 3629. +// According RFC 3629, the max length of utf8 characters is 4 bytes. +// And MySQL use 4 bytes to represent the unicode which must be in [0, 65536). +func decodeEscapedUnicode(s []byte) (char [4]byte, size int, err error) { + size, err = hex.Decode(char[0:2], s) + if err != nil || size != 2 { + // The unicode must can be represented in 2 bytes. + return char, 0, errors.Trace(err) + } + var unicode uint16 + err = binary.Read(bytes.NewReader(char[0:2]), binary.BigEndian, &unicode) + if err != nil { + return char, 0, errors.Trace(err) + } + size = utf8.RuneLen(rune(unicode)) + utf8.EncodeRune(char[0:size], rune(unicode)) + return +} + +// Extract receives several path expressions as arguments, matches them in bj, and returns: +// ret: target JSON matched any path expressions. maybe autowrapped as an array. +// found: true if any path expressions matched. +func (bj BinaryJSON) Extract(pathExprList []PathExpression) (ret BinaryJSON, found bool) { + buf := make([]BinaryJSON, 0, 1) + for _, pathExpr := range pathExprList { + buf = bj.extractTo(buf, pathExpr) + } + if len(buf) == 0 { + found = false + } else if len(pathExprList) == 1 && len(buf) == 1 { + // If pathExpr contains asterisks, len(elemList) won't be 1 + // even if len(pathExprList) equals to 1. + found = true + ret = buf[0] + } else { + found = true + ret = buildBinaryArray(buf) + } + return +} + +func (bj BinaryJSON) extractTo(buf []BinaryJSON, pathExpr PathExpression) []BinaryJSON { + if len(pathExpr.legs) == 0 { + return append(buf, bj) + } + currentLeg, subPathExpr := pathExpr.popOneLeg() + if currentLeg.typ == pathLegIndex { + if bj.TypeCode != TypeCodeArray { + if currentLeg.arrayIndex <= 0 && currentLeg.arrayIndex != arrayIndexAsterisk { + buf = bj.extractTo(buf, subPathExpr) + } + return buf + } + elemCount := bj.GetElemCount() + if currentLeg.arrayIndex == arrayIndexAsterisk { + for i := 0; i < elemCount; i++ { + buf = bj.arrayGetElem(i).extractTo(buf, subPathExpr) + } + } else if currentLeg.arrayIndex < elemCount { + buf = bj.arrayGetElem(currentLeg.arrayIndex).extractTo(buf, subPathExpr) + } + } else if currentLeg.typ == pathLegKey && bj.TypeCode == TypeCodeObject { + elemCount := bj.GetElemCount() + if currentLeg.dotKey == "*" { + for i := 0; i < elemCount; i++ { + buf = bj.objectGetVal(i).extractTo(buf, subPathExpr) + } + } else { + child, ok := bj.objectSearchKey(hack.Slice(currentLeg.dotKey)) + if ok { + buf = child.extractTo(buf, subPathExpr) + } + } + } else if currentLeg.typ == pathLegDoubleAsterisk { + buf = bj.extractTo(buf, subPathExpr) + if bj.TypeCode == TypeCodeArray { + elemCount := bj.GetElemCount() + for i := 0; i < elemCount; i++ { + buf = bj.arrayGetElem(i).extractTo(buf, pathExpr) + } + } else if bj.TypeCode == TypeCodeObject { + elemCount := bj.GetElemCount() + for i := 0; i < elemCount; i++ { + buf = bj.objectGetVal(i).extractTo(buf, pathExpr) + } + } + } + return buf +} + +func (bj BinaryJSON) objectSearchKey(key []byte) (BinaryJSON, bool) { + elemCount := bj.GetElemCount() + idx := sort.Search(elemCount, func(i int) bool { + return bytes.Compare(bj.objectGetKey(i), key) >= 0 + }) + if idx < elemCount && bytes.Compare(bj.objectGetKey(idx), key) == 0 { + return bj.objectGetVal(idx), true + } + return BinaryJSON{}, false +} + +func buildBinaryArray(elems []BinaryJSON) BinaryJSON { + totalSize := headerSize + len(elems)*valEntrySize + for _, elem := range elems { + if elem.TypeCode != TypeCodeLiteral { + totalSize += len(elem.Value) + } + } + buf := make([]byte, headerSize+len(elems)*valEntrySize, totalSize) + endian.PutUint32(buf, uint32(len(elems))) + endian.PutUint32(buf[dataSizeOff:], uint32(totalSize)) + buf = buildBinaryElements(buf, headerSize, elems) + return BinaryJSON{TypeCode: TypeCodeArray, Value: buf} +} + +func buildBinaryElements(buf []byte, entryStart int, elems []BinaryJSON) []byte { + for i, elem := range elems { + buf[entryStart+i*valEntrySize] = elem.TypeCode + if elem.TypeCode == TypeCodeLiteral { + buf[entryStart+i*valEntrySize+valTypeSize] = elem.Value[0] + } else { + endian.PutUint32(buf[entryStart+i*valEntrySize+valTypeSize:], uint32(len(buf))) + buf = append(buf, elem.Value...) + } + } + return buf +} + +func buildBinaryObject(keys [][]byte, elems []BinaryJSON) BinaryJSON { + totalSize := headerSize + len(elems)*(keyEntrySize+valEntrySize) + for i, elem := range elems { + if elem.TypeCode != TypeCodeLiteral { + totalSize += len(elem.Value) + } + totalSize += len(keys[i]) + } + buf := make([]byte, headerSize+len(elems)*(keyEntrySize+valEntrySize), totalSize) + endian.PutUint32(buf, uint32(len(elems))) + endian.PutUint32(buf[dataSizeOff:], uint32(totalSize)) + for i, key := range keys { + endian.PutUint32(buf[headerSize+i*keyEntrySize:], uint32(len(buf))) + endian.PutUint16(buf[headerSize+i*keyEntrySize+keyLenOff:], uint16(len(key))) + buf = append(buf, key...) + } + entryStart := headerSize + len(elems)*keyEntrySize + buf = buildBinaryElements(buf, entryStart, elems) + return BinaryJSON{TypeCode: TypeCodeObject, Value: buf} +} + +// Modify modifies a JSON object by insert, replace or set. +// All path expressions cannot contain * or ** wildcard. +// If any error occurs, the input won't be changed. +func (bj BinaryJSON) Modify(pathExprList []PathExpression, values []BinaryJSON, mt ModifyType) (retj BinaryJSON, err error) { + if len(pathExprList) != len(values) { + // TODO: should return 1582(42000) + return retj, errors.New("Incorrect parameter count") + } + for _, pathExpr := range pathExprList { + if pathExpr.flags.containsAnyAsterisk() { + // TODO: should return 3149(42000) + return retj, errors.New("Invalid path expression") + } + } + for i := 0; i < len(pathExprList); i++ { + pathExpr, value := pathExprList[i], values[i] + modifier := &binaryModifier{bj: bj} + switch mt { + case ModifyInsert: + bj = modifier.insert(pathExpr, value) + case ModifyReplace: + bj = modifier.replace(pathExpr, value) + case ModifySet: + bj = modifier.set(pathExpr, value) + } + } + return bj, nil +} + +// Remove removes the elements indicated by pathExprList from JSON. +func (bj BinaryJSON) Remove(pathExprList []PathExpression) (BinaryJSON, error) { + for _, pathExpr := range pathExprList { + if len(pathExpr.legs) == 0 { + // TODO: should return 3153(42000) + return bj, errors.New("Invalid path expression") + } + if pathExpr.flags.containsAnyAsterisk() { + // TODO: should return 3149(42000) + return bj, errors.New("Invalid path expression") + } + modifer := &binaryModifier{bj: bj} + bj = modifer.remove(pathExpr) + } + return bj, nil +} + +type binaryModifier struct { + bj BinaryJSON + modifyPtr *byte + modifyValue BinaryJSON +} + +func (bm *binaryModifier) set(path PathExpression, newBj BinaryJSON) BinaryJSON { + result := make([]BinaryJSON, 0, 1) + result = bm.bj.extractTo(result, path) + if len(result) > 0 { + bm.modifyPtr = &result[0].Value[0] + bm.modifyValue = newBj + return bm.rebuild() + } + bm.doInsert(path, newBj) + return bm.rebuild() +} + +func (bm *binaryModifier) replace(path PathExpression, newBj BinaryJSON) BinaryJSON { + result := make([]BinaryJSON, 0, 1) + result = bm.bj.extractTo(result, path) + if len(result) == 0 { + return bm.bj + } + bm.modifyPtr = &result[0].Value[0] + bm.modifyValue = newBj + return bm.rebuild() +} + +func (bm *binaryModifier) insert(path PathExpression, newBj BinaryJSON) BinaryJSON { + result := make([]BinaryJSON, 0, 1) + result = bm.bj.extractTo(result, path) + if len(result) > 0 { + return bm.bj + } + bm.doInsert(path, newBj) + return bm.rebuild() +} + +// doInsert inserts the newBj to its parent, and builds the new parent. +func (bm *binaryModifier) doInsert(path PathExpression, newBj BinaryJSON) { + parentPath, lastLeg := path.popOneLastLeg() + result := make([]BinaryJSON, 0, 1) + result = bm.bj.extractTo(result, parentPath) + if len(result) == 0 { + return + } + parentBj := result[0] + if lastLeg.typ == pathLegIndex { + bm.modifyPtr = &parentBj.Value[0] + if parentBj.TypeCode != TypeCodeArray { + bm.modifyValue = buildBinaryArray([]BinaryJSON{parentBj, newBj}) + return + } + elemCount := parentBj.GetElemCount() + elems := make([]BinaryJSON, 0, elemCount+1) + for i := 0; i < elemCount; i++ { + elems = append(elems, parentBj.arrayGetElem(i)) + } + elems = append(elems, newBj) + bm.modifyValue = buildBinaryArray(elems) + return + } + if parentBj.TypeCode != TypeCodeObject { + return + } + bm.modifyPtr = &parentBj.Value[0] + elemCount := parentBj.GetElemCount() + insertKey := hack.Slice(lastLeg.dotKey) + insertIdx := sort.Search(elemCount, func(i int) bool { + return bytes.Compare(parentBj.objectGetKey(i), insertKey) >= 0 + }) + keys := make([][]byte, 0, elemCount+1) + elems := make([]BinaryJSON, 0, elemCount+1) + for i := 0; i < elemCount; i++ { + if i == insertIdx { + keys = append(keys, insertKey) + elems = append(elems, newBj) + } + keys = append(keys, parentBj.objectGetKey(i)) + elems = append(elems, parentBj.objectGetVal(i)) + } + if insertIdx == elemCount { + keys = append(keys, insertKey) + elems = append(elems, newBj) + } + bm.modifyValue = buildBinaryObject(keys, elems) +} + +func (bm *binaryModifier) remove(path PathExpression) BinaryJSON { + result := make([]BinaryJSON, 0, 1) + result = bm.bj.extractTo(result, path) + if len(result) == 0 { + return bm.bj + } + bm.doRemove(path) + return bm.rebuild() +} + +func (bm *binaryModifier) doRemove(path PathExpression) { + parentPath, lastLeg := path.popOneLastLeg() + result := make([]BinaryJSON, 0, 1) + result = bm.bj.extractTo(result, parentPath) + if len(result) == 0 { + return + } + parentBj := result[0] + if lastLeg.typ == pathLegIndex { + if parentBj.TypeCode != TypeCodeArray { + return + } + bm.modifyPtr = &parentBj.Value[0] + elemCount := parentBj.GetElemCount() + elems := make([]BinaryJSON, 0, elemCount-1) + for i := 0; i < elemCount; i++ { + if i != lastLeg.arrayIndex { + elems = append(elems, parentBj.arrayGetElem(i)) + } + } + bm.modifyValue = buildBinaryArray(elems) + return + } + if parentBj.TypeCode != TypeCodeObject { + return + } + bm.modifyPtr = &parentBj.Value[0] + elemCount := parentBj.GetElemCount() + removeKey := hack.Slice(lastLeg.dotKey) + keys := make([][]byte, 0, elemCount+1) + elems := make([]BinaryJSON, 0, elemCount+1) + for i := 0; i < elemCount; i++ { + key := parentBj.objectGetKey(i) + if !bytes.Equal(key, removeKey) { + keys = append(keys, parentBj.objectGetKey(i)) + elems = append(elems, parentBj.objectGetVal(i)) + } + } + bm.modifyValue = buildBinaryObject(keys, elems) +} + +// rebuild merges the old and the modified JSON into a new BinaryJSON +func (bm *binaryModifier) rebuild() BinaryJSON { + buf := make([]byte, 0, len(bm.bj.Value)+len(bm.modifyValue.Value)) + value, tpCode := bm.rebuildTo(buf) + return BinaryJSON{TypeCode: tpCode, Value: value} +} + +func (bm *binaryModifier) rebuildTo(buf []byte) ([]byte, TypeCode) { + if bm.modifyPtr == &bm.bj.Value[0] { + bm.modifyPtr = nil + return append(buf, bm.modifyValue.Value...), bm.modifyValue.TypeCode + } else if bm.modifyPtr == nil { + return append(buf, bm.bj.Value...), bm.bj.TypeCode + } + bj := bm.bj + switch bj.TypeCode { + case TypeCodeLiteral, TypeCodeInt64, TypeCodeUint64, TypeCodeFloat64, TypeCodeString: + return append(buf, bj.Value...), bj.TypeCode + } + docOff := len(buf) + elemCount := bj.GetElemCount() + var valEntryStart int + if bj.TypeCode == TypeCodeArray { + copySize := headerSize + elemCount*valEntrySize + valEntryStart = headerSize + buf = append(buf, bj.Value[:copySize]...) + } else { + copySize := headerSize + elemCount*(keyEntrySize+valEntrySize) + valEntryStart = headerSize + elemCount*keyEntrySize + buf = append(buf, bj.Value[:copySize]...) + if elemCount > 0 { + firstKeyOff := int(endian.Uint32(bj.Value[headerSize:])) + lastKeyOff := int(endian.Uint32(bj.Value[headerSize+(elemCount-1)*keyEntrySize:])) + lastKeyLen := int(endian.Uint16(bj.Value[headerSize+(elemCount-1)*keyEntrySize+keyLenOff:])) + buf = append(buf, bj.Value[firstKeyOff:lastKeyOff+lastKeyLen]...) + } + } + for i := 0; i < elemCount; i++ { + valEntryOff := valEntryStart + i*valEntrySize + elem := bj.valEntryGet(valEntryOff) + bm.bj = elem + var tpCode TypeCode + valOff := len(buf) - docOff + buf, tpCode = bm.rebuildTo(buf) + buf[docOff+valEntryOff] = tpCode + if tpCode == TypeCodeLiteral { + lastIdx := len(buf) - 1 + endian.PutUint32(buf[docOff+valEntryOff+valTypeSize:], uint32(buf[lastIdx])) + buf = buf[:lastIdx] + } else { + endian.PutUint32(buf[docOff+valEntryOff+valTypeSize:], uint32(valOff)) + } + } + endian.PutUint32(buf[docOff+dataSizeOff:], uint32(len(buf)-docOff)) + return buf, bj.TypeCode +} + +// floatEpsilon is the acceptable error quantity when comparing two float numbers. +const floatEpsilon = 1.e-8 + +// compareFloat64 returns an integer comparing the float64 x to y, +// allowing precision loss. +func compareFloat64PrecisionLoss(x, y float64) int { + if x-y < floatEpsilon && y-x < floatEpsilon { + return 0 + } else if x-y < 0 { + return -1 + } + return 1 +} + +// CompareBinary compares two binary json objects. Returns -1 if left < right, +// 0 if left == right, else returns 1. +func CompareBinary(left, right BinaryJSON) int { + precedence1 := jsonTypePrecedences[left.Type()] + precedence2 := jsonTypePrecedences[right.Type()] + var cmp int + if precedence1 == precedence2 { + if precedence1 == jsonTypePrecedences["NULL"] { + // for JSON null. + cmp = 0 + } + switch left.TypeCode { + case TypeCodeLiteral: + // false is less than true. + cmp = int(right.Value[0]) - int(left.Value[0]) + case TypeCodeInt64, TypeCodeUint64, TypeCodeFloat64: + leftFloat := i64AsFloat64(left.GetInt64(), left.TypeCode) + rightFloat := i64AsFloat64(right.GetInt64(), right.TypeCode) + cmp = compareFloat64PrecisionLoss(leftFloat, rightFloat) + case TypeCodeString: + cmp = bytes.Compare(left.GetString(), right.GetString()) + case TypeCodeArray: + leftCount := left.GetElemCount() + rightCount := right.GetElemCount() + for i := 0; i < leftCount && i < rightCount; i++ { + elem1 := left.arrayGetElem(i) + elem2 := right.arrayGetElem(i) + cmp = CompareBinary(elem1, elem2) + if cmp != 0 { + return cmp + } + } + cmp = leftCount - rightCount + case TypeCodeObject: + // only equal is defined on two json objects. + // larger and smaller are not defined. + cmp = bytes.Compare(left.Value, right.Value) + } + } else { + cmp = precedence1 - precedence2 + } + return cmp +} + +func i64AsFloat64(i64 int64, typeCode TypeCode) float64 { + switch typeCode { + case TypeCodeLiteral, TypeCodeInt64: + return float64(i64) + case TypeCodeUint64: + u64 := *(*uint64)(unsafe.Pointer(&i64)) + return float64(u64) + case TypeCodeFloat64: + return *(*float64)(unsafe.Pointer(&i64)) + default: + msg := fmt.Sprintf(unknownTypeCodeErrorMsg, typeCode) + panic(msg) + } +} + +// MergeBinary merges multiple BinaryJSON into one according the following rules: +// 1) adjacent arrays are merged to a single array; +// 2) adjacent object are merged to a single object; +// 3) a scalar value is autowrapped as an array before merge; +// 4) an adjacent array and object are merged by autowrapping the object as an array. +func MergeBinary(bjs []BinaryJSON) BinaryJSON { + var remain = bjs + var objects []BinaryJSON + var results []BinaryJSON + for len(remain) > 0 { + if remain[0].TypeCode != TypeCodeObject { + results = append(results, remain[0]) + remain = remain[1:] + } else { + objects, remain = getAdjacentObjects(remain) + results = append(results, mergeBinaryObject(objects)) + } + } + if len(results) == 1 { + return results[0] + } + return mergeBinaryArray(results) +} + +func getAdjacentObjects(bjs []BinaryJSON) (objects, remain []BinaryJSON) { + for i := 0; i < len(bjs); i++ { + if bjs[i].TypeCode != TypeCodeObject { + return bjs[:i], bjs[i:] + } + } + return bjs, nil +} + +func mergeBinaryArray(elems []BinaryJSON) BinaryJSON { + buf := make([]BinaryJSON, 0, len(elems)) + for i := 0; i < len(elems); i++ { + elem := elems[i] + if elem.TypeCode != TypeCodeArray { + buf = append(buf, elem) + } else { + childCount := elem.GetElemCount() + for j := 0; j < childCount; j++ { + buf = append(buf, elem.arrayGetElem(j)) + } + } + } + return buildBinaryArray(buf) +} + +func mergeBinaryObject(objects []BinaryJSON) BinaryJSON { + keyValMap := make(map[string]BinaryJSON) + keys := make([][]byte, 0, len(keyValMap)) + for _, obj := range objects { + elemCount := obj.GetElemCount() + for i := 0; i < elemCount; i++ { + key := obj.objectGetKey(i) + val := obj.objectGetVal(i) + if old, ok := keyValMap[string(key)]; ok { + keyValMap[string(key)] = MergeBinary([]BinaryJSON{old, val}) + } else { + keyValMap[string(key)] = val + keys = append(keys, key) + } + } + } + sort.Slice(keys, func(i, j int) bool { + return bytes.Compare(keys[i], keys[j]) < 0 + }) + values := make([]BinaryJSON, len(keys)) + for i, key := range keys { + values[i] = keyValMap[string(key)] + } + return buildBinaryObject(keys, values) +} + +// PeekBytesAsJSON trys to peek some bytes from b, until +// we can deserialize a JSON from those bytes. +func PeekBytesAsJSON(b []byte) (n int, err error) { + if len(b) <= 0 { + err = errors.New("Cant peek from empty bytes") + return + } + switch c := TypeCode(b[0]); c { + case TypeCodeObject, TypeCodeArray: + if len(b) >= valTypeSize+headerSize { + size := endian.Uint32(b[valTypeSize+dataSizeOff:]) + n = valTypeSize + int(size) + return + } + case TypeCodeString: + strLen, lenLen := binary.Uvarint(b[valTypeSize:]) + return valTypeSize + int(strLen) + lenLen, nil + case TypeCodeInt64, TypeCodeUint64, TypeCodeFloat64: + n = valTypeSize + 8 + return + case TypeCodeLiteral: + n = valTypeSize + 1 + return + } + err = errors.New("Invalid JSON bytes") + return +} + +// ContainsBinary check whether JSON document contains specific target according the following rules: +// 1) object contains a target object if and only if every key is contained in source object and the value associated with the target key is contained in the value associated with the source key; +// 2) array contains a target nonarray if and only if the target is contained in some element of the array; +// 3) array contains a target array if and only if every element is contained in some element of the array; +// 4) scalar contains a target scalar if and only if they are comparable and are equal; +func ContainsBinary(obj, target BinaryJSON) bool { + switch obj.TypeCode { + case TypeCodeObject: + if target.TypeCode == TypeCodeObject { + len := target.GetElemCount() + for i := 0; i < len; i++ { + key := target.objectGetKey(i) + val := target.objectGetVal(i) + if exp, exists := obj.objectSearchKey(key); !exists || !ContainsBinary(exp, val) { + return false + } + } + return true + } + return false + case TypeCodeArray: + if target.TypeCode == TypeCodeArray { + len := target.GetElemCount() + for i := 0; i < len; i++ { + if !ContainsBinary(obj, target.arrayGetElem(i)) { + return false + } + } + return true + } + len := obj.GetElemCount() + for i := 0; i < len; i++ { + if ContainsBinary(obj.arrayGetElem(i), target) { + return true + } + } + return false + default: + return CompareBinary(obj, target) == 0 + } +} + +// GetElemDepth for JSON_DEPTH +// Returns the maximum depth of a JSON document +// rules referenced by MySQL JSON_DEPTH function +// [https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-depth] +// 1) An empty array, empty object, or scalar value has depth 1. +// 2) A nonempty array containing only elements of depth 1 or nonempty object containing only member values of depth 1 has depth 2. +// 3) Otherwise, a JSON document has depth greater than 2. +// e.g. depth of '{}', '[]', 'true': 1 +// e.g. depth of '[10, 20]', '[[], {}]': 2 +// e.g. depth of '[10, {"a": 20}]': 3 +func (bj BinaryJSON) GetElemDepth() int { + switch bj.TypeCode { + case TypeCodeObject: + len := bj.GetElemCount() + maxDepth := 0 + for i := 0; i < len; i++ { + obj := bj.objectGetVal(i) + depth := obj.GetElemDepth() + if depth > maxDepth { + maxDepth = depth + } + } + return maxDepth + 1 + case TypeCodeArray: + len := bj.GetElemCount() + maxDepth := 0 + for i := 0; i < len; i++ { + obj := bj.arrayGetElem(i) + depth := obj.GetElemDepth() + if depth > maxDepth { + maxDepth = depth + } + } + return maxDepth + 1 + default: + return 1 + } +} diff --git a/vendor/github.com/pingcap/tidb/types/json/constants.go b/vendor/github.com/pingcap/tidb/types/json/constants.go new file mode 100644 index 0000000000000000000000000000000000000000..03c9a5aa7a5a22e13d12e4c6e65b12cb943af94a --- /dev/null +++ b/vendor/github.com/pingcap/tidb/types/json/constants.go @@ -0,0 +1,238 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. + +package json + +import ( + "encoding/binary" + "unicode/utf8" + + "github.com/pingcap/parser/mysql" + "github.com/pingcap/parser/terror" +) + +// TypeCode indicates JSON type. +type TypeCode = byte + +const ( + // TypeCodeObject indicates the JSON is an object. + TypeCodeObject TypeCode = 0x01 + // TypeCodeArray indicates the JSON is an array. + TypeCodeArray TypeCode = 0x03 + // TypeCodeLiteral indicates the JSON is a literal. + TypeCodeLiteral TypeCode = 0x04 + // TypeCodeInt64 indicates the JSON is a signed integer. + TypeCodeInt64 TypeCode = 0x09 + // TypeCodeUint64 indicates the JSON is a unsigned integer. + TypeCodeUint64 TypeCode = 0x0a + // TypeCodeFloat64 indicates the JSON is a double float number. + TypeCodeFloat64 TypeCode = 0x0b + // TypeCodeString indicates the JSON is a string. + TypeCodeString TypeCode = 0x0c +) + +const ( + // LiteralNil represents JSON null. + LiteralNil byte = 0x00 + // LiteralTrue represents JSON true. + LiteralTrue byte = 0x01 + // LiteralFalse represents JSON false. + LiteralFalse byte = 0x02 +) + +const unknownTypeCodeErrorMsg = "unknown type code: %d" +const unknownTypeErrorMsg = "unknown type: %s" + +// htmlSafeSet holds the value true if the ASCII character with the given +// array position can be safely represented inside a JSON string, embedded +// inside of HTML