From 43c60b4885b54a395dbce2bb472c21675a87359c Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Wed, 21 Jan 2026 14:28:34 +0800 Subject: [PATCH 01/23] filter multiple tombstone/data, only keep last one --- pkg/frontend/data_branch.go | 171 +++++++++++- .../databranchutils/branch_hashmap.go | 246 ++++++++++++++++-- .../databranchutils/branch_hashmap_test.go | 159 +++++++++++ .../cases/git4data/branch/diff/diff_7.result | 55 ++++ .../cases/git4data/branch/diff/diff_7.sql | 59 +++++ 5 files changed, 651 insertions(+), 39 deletions(-) create mode 100644 test/distributed/cases/git4data/branch/diff/diff_7.result create mode 100644 test/distributed/cases/git4data/branch/diff/diff_7.sql diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 9f0537943de81..9b4d4554530ba 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -55,6 +55,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/util/executor" "github.com/matrixorigin/matrixone/pkg/vectorindex/sqlexec" "github.com/matrixorigin/matrixone/pkg/vm/engine" + "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" "github.com/panjf2000/ants/v2" ) @@ -845,7 +846,7 @@ func diffMergeAgency( } if dagInfo, err = decideLCABranchTSFromBranchDAG( - ctx, ses, bh, tblStuff.tarRel, tblStuff.baseRel, + ctx, ses, bh, tblStuff, ); err != nil { return } @@ -3226,7 +3227,8 @@ func findDeleteAndUpdateBat( } func appendTupleToBat(ses *Session, bat *batch.Batch, tuple types.Tuple, tblStuff tableStuff) error { - for j, val := range tuple { + // exclude the commit ts column + for j, val := range tuple[:len(tuple)-1] { vec := bat.Vecs[j] if err := vector.AppendAny( @@ -3957,9 +3959,13 @@ func buildHashmapForTable( ll := bat.VectorCount() var taskErr error if isTombstone { - taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll-1], []int{0}) + // keep the commit ts + taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll], []int{0}) + fmt.Println("A", common.MoBatchToString(bat, bat.RowCount())) } else { - taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll-1], []int{tblStuff.def.pkColIdx}) + // keep the commit ts + taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll], []int{tblStuff.def.pkColIdx}) + fmt.Println("B", common.MoBatchToString(bat, bat.RowCount())) } bat.Clean(mp) @@ -4005,6 +4011,135 @@ func buildHashmapForTable( err = atomicErr.Load().(error) } + if err != nil { + return + } + + if tblStuff.def.pkKind == fakeKind { + return + } + + /* + case 1: + insert update update update + pk1 pk1 pk1 pk1 .... + |------|-------------------------------------| + | collect range | + 1.1. the last one is an update: only keep the last update op + 1.2. the last one is a deletion: only keep the last deletion op + + case 2: + insert update update + pk1 pk1 pk1 .... + |------|-------------------------------------| + | collect range | + 2.1. the last one is an update: only keep the last update op + 2.2. the last one is a deletion: only keep the last deletion op + + case 3: + insert delete update update + pk1 pk1 pk1 pk1 .... + |------|-------------------------------------| + | collect range | + 3.1. the last one is an update: only keep the last update op + 3.2. the last one is a deletion: only keep the last deletion op + */ + + if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + var ( + err2 error + err3 error + maxTs types.TS + maxIdx int + tuple types.Tuple + dataRet databranchutils.GetResult + ) + if err2 = cursor.ForEach(func(key []byte, rows [][]byte) error { + if len(rows) > 1 { + //tsMap := make(map[types.TS]struct{}) + maxIdx = 0 + maxTs = types.MinTs() + for i := 0; i < len(rows); i++ { + if tuple, _, err3 = tombstoneHashmap.DecodeRow(rows[i]); err3 != nil { + return err3 + } + cur := types.TS(tuple[len(tuple)-1].([]uint8)) + if cur.GT(&maxTs) { + maxTs = cur + maxIdx = i + } + //tsMap[cur] = struct{}{} + } + //delete(tsMap, maxTs) + + for i := range rows { + if i != maxIdx { + if _, err3 = cursor.PopByEncodedKeyValue( + key, rows[i], false, + ); err3 != nil { + return err3 + } + } + } + + if dataRet, err3 = dataHashmap.GetByEncodedKey(key); err3 != nil { + return err3 + } + + if dataRet.Exists { + for i := range dataRet.Rows { + if tuple, _, err3 = dataHashmap.DecodeRow(dataRet.Rows[i]); err3 != nil { + return err3 + } + cur := types.TS(tuple[len(tuple)-1].([]uint8)) + // cannot use tsMap to filter, why? + // cannot use cur != maxTS to filter, why? + if cur.LT(&maxTs) { + if _, err3 = dataHashmap.PopByEncodedKeyValue( + key, dataRet.Rows[i], false, + ); err3 != nil { + return err3 + } + } + } + } + } + return nil + }); err2 != nil { + return err2 + } + return nil + }, -1); err != nil { + return nil, nil, err + } + + //tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + // cursor.ForEach(func(key []byte, rows [][]byte) error { + // for i := range rows { + // if tuple, _, err3 := tombstoneHashmap.DecodeRow(rows[i]); err3 != nil { + // return err3 + // } else { + // fmt.Println("tombstone", tuple[0].(int32)) + // } + // } + // return nil + // }) + // return nil + //}, 1) + // + //dataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + // cursor.ForEach(func(key []byte, rows [][]byte) error { + // for i := range rows { + // if tuple, _, err3 := dataHashmap.DecodeRow(rows[i]); err3 != nil { + // return err3 + // } else { + // fmt.Println("data", tuple[0].(int32), tuple[1].(int32)) + // } + // } + // return nil + // }) + // return nil + //}, 1) return } @@ -4319,10 +4454,12 @@ func decideCollectRange( tarCollectRange.rel = append(tarCollectRange.rel, lcaRel) tarCollectRange.from = append(tarCollectRange.from, dagInfo.baseBranchTS.Next()) tarCollectRange.end = append(tarCollectRange.end, dagInfo.tarBranchTS) + dagInfo.tarBranchTS = dagInfo.baseBranchTS } else { baseCollectRange.rel = append(baseCollectRange.rel, lcaRel) baseCollectRange.from = append(baseCollectRange.from, dagInfo.tarBranchTS.Next()) baseCollectRange.end = append(baseCollectRange.end, dagInfo.baseBranchTS) + dagInfo.baseBranchTS = dagInfo.tarBranchTS } } return @@ -4523,8 +4660,7 @@ func decideLCABranchTSFromBranchDAG( ctx context.Context, ses *Session, bh BackgroundExec, - tarRel engine.Relation, - baseRel engine.Relation, + tblStuff tableStuff, ) ( branchInfo branchMetaInfo, err error, @@ -4569,14 +4705,14 @@ func decideLCABranchTSFromBranchDAG( // if a table is cloned table, the commit ts of the cloned data // should be the creation time of the table. if lcaTableID, tarTS, baseTS, hasLca = dag.FindLCA( - tarRel.GetTableID(ctx), baseRel.GetTableID(ctx), + tblStuff.tarRel.GetTableID(ctx), tblStuff.baseRel.GetTableID(ctx), ); hasLca { - if lcaTableID == baseRel.GetTableID(ctx) { + if lcaTableID == tblStuff.baseRel.GetTableID(ctx) { ts := timestamp.Timestamp{PhysicalTime: tarTS} tarBranchTS = ts baseBranchTS = ts lcaType = lcaRight - } else if lcaTableID == tarRel.GetTableID(ctx) { + } else if lcaTableID == tblStuff.tarRel.GetTableID(ctx) { ts := timestamp.Timestamp{PhysicalTime: baseTS} tarBranchTS = ts baseBranchTS = ts @@ -4586,8 +4722,21 @@ func decideLCABranchTSFromBranchDAG( tarBranchTS = timestamp.Timestamp{PhysicalTime: tarTS} baseBranchTS = timestamp.Timestamp{PhysicalTime: baseTS} } - } else { - lcaType = lcaEmpty + } else if tblStuff.tarRel.GetTableID(ctx) == tblStuff.baseRel.GetTableID(ctx) { + lcaTableID = tblStuff.tarRel.GetTableID(ctx) + if tblStuff.tarSnap == nil && tblStuff.baseSnap == nil { + lcaType = lcaRight + } else if tblStuff.tarSnap == nil { + // diff tar{now} against base{sp} + lcaType = lcaRight + } else if tblStuff.baseSnap == nil { + // diff tar{sp} against base{now} + lcaType = lcaLeft + } else if tblStuff.tarSnap.TS.LessEq(*tblStuff.baseSnap.TS) { + lcaType = lcaLeft + } else { + lcaType = lcaRight + } } return diff --git a/pkg/frontend/databranchutils/branch_hashmap.go b/pkg/frontend/databranchutils/branch_hashmap.go index d9390cb499548..48ac372970b1a 100644 --- a/pkg/frontend/databranchutils/branch_hashmap.go +++ b/pkg/frontend/databranchutils/branch_hashmap.go @@ -43,6 +43,10 @@ type BranchHashmap interface { // GetResult per probed row, preserving the order of the original vectors. The // returned rows reference the internal storage and must be treated as read-only. GetByVectors(keyVecs []*vector.Vector) ([]GetResult, error) + // GetByEncodedKey retrieves rows using a pre-encoded key such as one obtained + // from ForEachShardParallel. Returned rows reference internal storage and must + // be treated as read-only. + GetByEncodedKey(encodedKey []byte) (GetResult, error) // PopByVectors behaves like GetByVectors but removes matching rows from the // hashmap. When removeAll is true, all rows associated with a key are removed. // When removeAll is false, only a single row is removed. Returned rows are @@ -51,10 +55,17 @@ type BranchHashmap interface { // PopByEncodedKey removes rows using a pre-encoded key such as one obtained // from ForEachShardParallel. It mirrors PopByVectors semantics. PopByEncodedKey(encodedKey []byte, removeAll bool) (GetResult, error) + // PopByEncodedKeyValue removes rows matching both the encoded key and encoded + // value. When removeAll is true it removes all matching rows, otherwise it + // removes a single row. It returns the number of rows removed. + PopByEncodedKeyValue(encodedKey []byte, encodedValue []byte, removeAll bool) (int, error) // PopByEncodedFullValue PopByEncodedFullValues removes rows by reconstructing the key from a full // encoded row payload. The full row must match the value encoding used by // PutByVectors. It mirrors PopByEncodedKey semantics. PopByEncodedFullValue(encodedValue []byte, removeAll bool) (GetResult, error) + // PopByEncodedFullValueExact removes rows by matching the full encoded row + // payload, including the value bytes. It mirrors PopByEncodedKeyValue semantics. + PopByEncodedFullValueExact(encodedValue []byte, removeAll bool) (int, error) // ForEachShardParallel provides exclusive access to each shard. The callback // receives a cursor offering read-only iteration plus mutation helpers that // avoid blocking other shards. parallelism <= 0 selects the default value: @@ -89,6 +100,9 @@ type ShardCursor interface { // PopByEncodedKey removes entries from the shard while the caller still owns // the iteration lock, ensuring In-shard mutations stay non-blocking. PopByEncodedKey(encodedKey []byte, removeAll bool) (GetResult, error) + // PopByEncodedKeyValue removes entries matching both key and value while the + // caller still owns the iteration lock. + PopByEncodedKeyValue(encodedKey []byte, encodedValue []byte, removeAll bool) (int, error) } // GetResult bundles the original rows associated with a probed key. @@ -356,6 +370,36 @@ func (bh *branchHashmap) GetByVectors(keyVecs []*vector.Vector) ([]GetResult, er return bh.lookupByVectors(keyVecs, nil) } +func (bh *branchHashmap) GetByEncodedKey(encodedKey []byte) (GetResult, error) { + var result GetResult + + bh.metaMu.RLock() + if bh.closed { + bh.metaMu.RUnlock() + return result, moerr.NewInternalErrorNoCtx("branchHashmap is closed") + } + if len(bh.keyTypes) == 0 { + bh.metaMu.RUnlock() + return result, nil + } + shardCount := bh.shardCount + bh.metaMu.RUnlock() + + if shardCount == 0 { + return result, nil + } + + hash := hashKey(encodedKey) + shard := bh.shards[int(hash%uint64(shardCount))] + rows, err := shard.getRows(hash, encodedKey) + if err != nil { + return result, err + } + result.Rows = rows + result.Exists = len(rows) > 0 + return result, nil +} + func (bh *branchHashmap) PopByVectors(keyVecs []*vector.Vector, removeAll bool) ([]GetResult, error) { return bh.lookupByVectors(keyVecs, &removeAll) } @@ -459,6 +503,28 @@ func (bh *branchHashmap) PopByEncodedKey(encodedKey []byte, removeAll bool) (Get return result, nil } +func (bh *branchHashmap) PopByEncodedKeyValue(encodedKey []byte, encodedValue []byte, removeAll bool) (int, error) { + bh.metaMu.RLock() + if bh.closed { + bh.metaMu.RUnlock() + return 0, moerr.NewInternalErrorNoCtx("branchHashmap is closed") + } + if len(bh.keyTypes) == 0 { + bh.metaMu.RUnlock() + return 0, nil + } + shardCount := bh.shardCount + bh.metaMu.RUnlock() + + if shardCount == 0 { + return 0, nil + } + + hash := hashKey(encodedKey) + shard := bh.shards[int(hash%uint64(shardCount))] + return shard.popRowsByValue(hash, encodedKey, encodedValue, removeAll) +} + func (bh *branchHashmap) PopByEncodedFullValue(encodedValue []byte, removeAll bool) (GetResult, error) { var result GetResult @@ -505,6 +571,51 @@ func (bh *branchHashmap) PopByEncodedFullValue(encodedValue []byte, removeAll bo encodedKey := packer.Bytes() return bh.PopByEncodedKey(encodedKey, removeAll) } + +func (bh *branchHashmap) PopByEncodedFullValueExact(encodedValue []byte, removeAll bool) (int, error) { + if bh.ItemCount() == 0 { + return 0, nil + } + + bh.metaMu.RLock() + if bh.closed { + bh.metaMu.RUnlock() + return 0, moerr.NewInternalErrorNoCtx("branchHashmap is closed") + } + valueTypes := cloneTypesFromSlice(bh.valueTypes) + keyTypes := cloneTypesFromSlice(bh.keyTypes) + keyCols := cloneInts(bh.keyCols) + bh.metaMu.RUnlock() + + if len(valueTypes) == 0 || len(keyTypes) == 0 || len(keyCols) == 0 { + return 0, moerr.NewInvalidInputNoCtx("branchHashmap PopByEncodedFullValueExact requires initialized key and value types") + } + if len(keyCols) != len(keyTypes) { + return 0, moerr.NewInvalidInputNoCtx("branchHashmap key columns/types mismatch") + } + + tuple, err := types.Unpack(encodedValue) + if err != nil { + return 0, err + } + if len(tuple) != len(valueTypes) { + return 0, moerr.NewInvalidInputNoCtxf("unexpected row width %d, want %d", len(tuple), len(valueTypes)) + } + + packer := bh.getPacker() + defer bh.putPacker(packer) + + for i, colIdx := range keyCols { + if valueTypes[colIdx] != keyTypes[i] { + return 0, moerr.NewInvalidInputNoCtx("key column type mismatch") + } + if err := encodeDecodedValue(packer, valueTypes[colIdx], tuple[colIdx]); err != nil { + return 0, err + } + } + encodedKey := packer.Bytes() + return bh.PopByEncodedKeyValue(encodedKey, encodedValue, removeAll) +} func (bh *branchHashmap) ForEachShardParallel(fn func(cursor ShardCursor) error, parallelism int) error { if fn == nil { return nil @@ -772,6 +883,13 @@ func (sc *shardCursor) PopByEncodedKey(encodedKey []byte, removeAll bool) (GetRe result.Exists = len(rows) > 0 return result, nil } + +func (sc *shardCursor) PopByEncodedKeyValue(encodedKey []byte, encodedValue []byte, removeAll bool) (int, error) { + if sc == nil || sc.shard == nil { + return 0, nil + } + return sc.shard.popRowsByValueDuringIteration(hashKey(encodedKey), encodedKey, encodedValue, removeAll) +} func (bh *branchHashmap) DecodeRow(data []byte) (types.Tuple, []types.Type, error) { t, err := types.Unpack(data) //bh.metaMu.RLock() @@ -875,13 +993,13 @@ func (hs *hashShard) insertEntryLocked(entry *hashEntry) { func (hs *hashShard) getRows(hash uint64, key []byte) ([][]byte, error) { hs.lock() defer hs.unlock() - rows := hs.collectFromMemory(hash, key, nil, nil, false) + rows := hs.collectFromMemory(hash, key, nil, nil, false, true) if len(hs.spills) == 0 { return rows, nil } var scratch []byte for _, part := range hs.spills { - if err := part.collect(hash, key, &rows, &scratch, nil); err != nil { + if err := part.collect(hash, key, &rows, &scratch, nil, true); err != nil { return nil, err } } @@ -893,6 +1011,12 @@ func (hs *hashShard) popRows(hash uint64, key []byte, removeAll bool) ([][]byte, return hs.popRowsUnsafe(hash, key, removeAll) } +func (hs *hashShard) popRowsByValue(hash uint64, key []byte, value []byte, removeAll bool) (int, error) { + hs.lock() + defer hs.unlock() + return hs.popRowsByValueUnsafe(hash, key, value, removeAll) +} + func (hs *hashShard) popRowsDuringIteration(hash uint64, key []byte, removeAll bool) ([][]byte, error) { if !hs.iterating { return nil, moerr.NewInternalErrorNoCtx("shard iteration context required") @@ -900,9 +1024,16 @@ func (hs *hashShard) popRowsDuringIteration(hash uint64, key []byte, removeAll b return hs.popRowsUnsafe(hash, key, removeAll) } +func (hs *hashShard) popRowsByValueDuringIteration(hash uint64, key []byte, value []byte, removeAll bool) (int, error) { + if !hs.iterating { + return 0, moerr.NewInternalErrorNoCtx("shard iteration context required") + } + return hs.popRowsByValueUnsafe(hash, key, value, removeAll) +} + func (hs *hashShard) popRowsUnsafe(hash uint64, key []byte, removeAll bool) ([][]byte, error) { plan := newRemovalPlan(removeAll) - rows := hs.collectFromMemory(hash, key, nil, plan, true) + rows := hs.collectFromMemory(hash, key, nil, plan, true, true) if len(hs.spills) == 0 { if removed := len(rows); removed > 0 { atomic.AddInt64(&hs.items, -int64(removed)) @@ -914,7 +1045,7 @@ func (hs *hashShard) popRowsUnsafe(hash uint64, key []byte, removeAll bool) ([][ if plan != nil && !plan.hasRemaining() { break } - if err := part.collect(hash, key, &rows, &scratch, plan); err != nil { + if err := part.collect(hash, key, &rows, &scratch, plan, true); err != nil { return nil, err } } @@ -923,7 +1054,41 @@ func (hs *hashShard) popRowsUnsafe(hash uint64, key []byte, removeAll bool) ([][ } return rows, nil } -func (hs *hashShard) collectFromMemory(hash uint64, key []byte, dst [][]byte, plan *removalPlan, copyValues bool) [][]byte { + +func (hs *hashShard) popRowsByValueUnsafe(hash uint64, key []byte, value []byte, removeAll bool) (int, error) { + matchValue := value + if removeAll && len(value) > 0 { + matchValue = make([]byte, len(value)) + copy(matchValue, value) + } + plan := newValueRemovalPlan(removeAll, matchValue) + hs.collectFromMemory(hash, key, nil, plan, false, false) + if len(hs.spills) == 0 { + removed := plan.removed + if removed > 0 { + atomic.AddInt64(&hs.items, -int64(removed)) + } + return removed, nil + } + var ( + scratch []byte + unused [][]byte + ) + for _, part := range hs.spills { + if plan != nil && !plan.hasRemaining() { + break + } + if err := part.collect(hash, key, &unused, &scratch, plan, false); err != nil { + return 0, err + } + } + removed := plan.removed + if removed > 0 { + atomic.AddInt64(&hs.items, -int64(removed)) + } + return removed, nil +} +func (hs *hashShard) collectFromMemory(hash uint64, key []byte, dst [][]byte, plan *removalPlan, copyValues bool, collectValues bool) [][]byte { bucket, ok := hs.inMemory[hash] if !ok { return dst @@ -936,16 +1101,18 @@ func (hs *hashShard) collectFromMemory(hash uint64, key []byte, dst [][]byte, pl newEntries = append(newEntries, entry) continue } - if int(entry.keyLen) == matchLen && bytes.Equal(entry.keyBytes(), key) && plan.take() { - value := entry.valueBytes() - var payload []byte - if copyValues { - payload = make([]byte, len(value)) - copy(payload, value) - } else { - payload = value + if int(entry.keyLen) == matchLen && bytes.Equal(entry.keyBytes(), key) && plan.matchesValue(entry.valueBytes()) && plan.take() { + if collectValues { + value := entry.valueBytes() + var payload []byte + if copyValues { + payload = make([]byte, len(value)) + copy(payload, value) + } else { + payload = value + } + dst = append(dst, payload) } - dst = append(dst, payload) hs.memInUse -= uint64(len(entry.buf)) entry.release() } else { @@ -973,13 +1140,15 @@ func (hs *hashShard) collectFromMemory(hash uint64, key []byte, dst [][]byte, pl continue } if bytes.Equal(entry.keyBytes(), key) { - value := entry.valueBytes() - if copyValues { - copied := make([]byte, len(value)) - copy(copied, value) - dst = append(dst, copied) - } else { - dst = append(dst, value) + if collectValues { + value := entry.valueBytes() + if copyValues { + copied := make([]byte, len(value)) + copy(copied, value) + dst = append(dst, copied) + } else { + dst = append(dst, value) + } } } } @@ -1615,7 +1784,7 @@ func (sp *spillPartition) append(entry *hashEntry) error { return nil } -func (sp *spillPartition) collect(hash uint64, key []byte, dst *[][]byte, scratch *[]byte, plan *removalPlan) error { +func (sp *spillPartition) collect(hash uint64, key []byte, dst *[][]byte, scratch *[]byte, plan *removalPlan, collectValues bool) error { pointers := sp.index[hash] if len(pointers) == 0 { return nil @@ -1641,16 +1810,18 @@ func (sp *spillPartition) collect(hash uint64, key []byte, dst *[][]byte, scratc matched := bytes.Equal(buf[:ptr.keyLen], key) switch { case plan == nil: - if matched { + if matched && collectValues { payload := make([]byte, ptr.valueLen) copy(payload, buf[ptr.keyLen:]) *dst = append(*dst, payload) } kept = append(kept, ptr) - case matched && plan.take(): - payload := make([]byte, ptr.valueLen) - copy(payload, buf[ptr.keyLen:]) - *dst = append(*dst, payload) + case matched && plan.matchesValue(buf[ptr.keyLen:ptr.keyLen+ptr.valueLen]) && plan.take(): + if collectValues { + payload := make([]byte, ptr.valueLen) + copy(payload, buf[ptr.keyLen:]) + *dst = append(*dst, payload) + } default: kept = append(kept, ptr) } @@ -1683,8 +1854,18 @@ func newRemovalPlan(removeAll bool) *removalPlan { return &removalPlan{remaining: 1} } +func newValueRemovalPlan(removeAll bool, value []byte) *removalPlan { + plan := newRemovalPlan(removeAll) + plan.matchValue = value + plan.matchValueSet = true + return plan +} + type removalPlan struct { - remaining int + remaining int + removed int + matchValue []byte + matchValueSet bool } func (rp *removalPlan) take() bool { @@ -1692,12 +1873,14 @@ func (rp *removalPlan) take() bool { return false } if rp.remaining < 0 { + rp.removed++ return true } if rp.remaining == 0 { return false } rp.remaining-- + rp.removed++ return true } @@ -1711,6 +1894,13 @@ func (rp *removalPlan) hasRemaining() bool { return rp.remaining > 0 } +func (rp *removalPlan) matchesValue(value []byte) bool { + if rp == nil || !rp.matchValueSet { + return true + } + return bytes.Equal(value, rp.matchValue) +} + type iterationGroup struct { key []byte rows [][]byte diff --git a/pkg/frontend/databranchutils/branch_hashmap_test.go b/pkg/frontend/databranchutils/branch_hashmap_test.go index 5d2a60ea1b024..911a2ba4b3dec 100644 --- a/pkg/frontend/databranchutils/branch_hashmap_test.go +++ b/pkg/frontend/databranchutils/branch_hashmap_test.go @@ -946,6 +946,165 @@ func TestBranchHashmapPopByEncodedKeyInMemory(t *testing.T) { require.Empty(t, final[0].Rows) } +func TestBranchHashmapGetByEncodedKey(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + keyVec := buildInt64Vector(t, mp, []int64{1, 1, 2}) + valVec := buildStringVector(t, mp, []string{"one", "uno", "two"}) + defer keyVec.Free(mp) + defer valVec.Free(mp) + + bh, err := NewBranchHashmap() + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + + require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) + + encodedKeys := collectInt64EncodedKeys(t, bh) + encodedKey, ok := encodedKeys[1] + require.True(t, ok) + + got, err := bh.GetByEncodedKey(encodedKey) + require.NoError(t, err) + require.True(t, got.Exists) + require.Len(t, got.Rows, 2) + + values := make(map[string]struct{}, len(got.Rows)) + for _, row := range got.Rows { + tuple, _, err := bh.DecodeRow(row) + require.NoError(t, err) + require.Equal(t, int64(1), tuple[0]) + valueBytes, ok := tuple[1].([]byte) + require.True(t, ok) + values[string(valueBytes)] = struct{}{} + } + require.Len(t, values, 2) + _, ok = values["one"] + require.True(t, ok) + _, ok = values["uno"] + require.True(t, ok) +} + +func TestBranchHashmapPopByEncodedKeyValue(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + keyVec := buildInt64Vector(t, mp, []int64{1, 1, 1}) + valVec := buildStringVector(t, mp, []string{"one", "uno", "eins"}) + defer keyVec.Free(mp) + defer valVec.Free(mp) + + bh, err := NewBranchHashmap() + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + + require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) + + var ( + keyCopy []byte + valueCopy []byte + removedValue string + ) + err = bh.ForEachShardParallel(func(cursor ShardCursor) error { + return cursor.ForEach(func(key []byte, rows [][]byte) error { + if len(rows) < 2 || len(keyCopy) > 0 { + return nil + } + keyCopy = append([]byte(nil), key...) + valueCopy = append([]byte(nil), rows[1]...) + tuple, _, err := bh.DecodeRow(valueCopy) + require.NoError(t, err) + valueBytes, ok := tuple[1].([]byte) + require.True(t, ok) + removedValue = string(valueBytes) + return nil + }) + }, 1) + require.NoError(t, err) + require.NotEmpty(t, keyCopy) + require.NotEmpty(t, valueCopy) + + removed, err := bh.PopByEncodedKeyValue(keyCopy, valueCopy, false) + require.NoError(t, err) + require.Equal(t, 1, removed) + + probe := buildInt64Vector(t, mp, []int64{1}) + defer probe.Free(mp) + + results, err := bh.GetByVectors([]*vector.Vector{probe}) + require.NoError(t, err) + require.True(t, results[0].Exists) + require.Len(t, results[0].Rows, 2) + for _, row := range results[0].Rows { + tuple, _, err := bh.DecodeRow(row) + require.NoError(t, err) + valueBytes, ok := tuple[1].([]byte) + require.True(t, ok) + require.NotEqual(t, removedValue, string(valueBytes)) + } +} + +func TestBranchHashmapPopByEncodedFullValueExact(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + keyVec := buildInt64Vector(t, mp, []int64{1, 1}) + valVec := buildStringVector(t, mp, []string{"one", "uno"}) + defer keyVec.Free(mp) + defer valVec.Free(mp) + + bh, err := NewBranchHashmap() + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + + require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) + + var ( + valueCopy []byte + removedValue string + ) + err = bh.ForEachShardParallel(func(cursor ShardCursor) error { + return cursor.ForEach(func(_ []byte, rows [][]byte) error { + if len(rows) == 0 || len(valueCopy) > 0 { + return nil + } + valueCopy = append([]byte(nil), rows[0]...) + tuple, _, err := bh.DecodeRow(valueCopy) + require.NoError(t, err) + valueBytes, ok := tuple[1].([]byte) + require.True(t, ok) + removedValue = string(valueBytes) + return nil + }) + }, 1) + require.NoError(t, err) + require.NotEmpty(t, valueCopy) + + removed, err := bh.PopByEncodedFullValueExact(valueCopy, false) + require.NoError(t, err) + require.Equal(t, 1, removed) + + probe := buildInt64Vector(t, mp, []int64{1}) + defer probe.Free(mp) + + results, err := bh.GetByVectors([]*vector.Vector{probe}) + require.NoError(t, err) + require.True(t, results[0].Exists) + require.Len(t, results[0].Rows, 1) + remaining, _, err := bh.DecodeRow(results[0].Rows[0]) + require.NoError(t, err) + valueBytes, ok := remaining[1].([]byte) + require.True(t, ok) + require.NotEqual(t, removedValue, string(valueBytes)) +} + func TestBranchHashmapPopByEncodedKeySpilled(t *testing.T) { mp := mpool.MustNewZero() defer mpool.DeleteMPool(mp) diff --git a/test/distributed/cases/git4data/branch/diff/diff_7.result b/test/distributed/cases/git4data/branch/diff/diff_7.result new file mode 100644 index 0000000000000..1971107cfaee7 --- /dev/null +++ b/test/distributed/cases/git4data/branch/diff/diff_7.result @@ -0,0 +1,55 @@ + +drop database if exists test; +create database test; +use test; +create table t1 (a int primary key, b int); +insert into t1 values(1,1); +insert into t1 values(2,2); +create snapshot sp for table test t1; +update t1 set b=2 where a = 1; +select mo_ctl("dn", "flush", "test.t1"); +mo_ctl(dn, flush, test.t1) +{\n "method": "Flush",\n "result": [\n {\n "returnStr": "OK"\n }\n ]\n}\n +update t1 set b=3 where a = 1; +select mo_ctl("dn", "flush", "test.t1"); +mo_ctl(dn, flush, test.t1) +{\n "method": "Flush",\n "result": [\n {\n "returnStr": "OK"\n }\n ]\n}\n +update t1 set b=4 where a = 1; +data branch diff t1 against t1{snapshot="sp"}; +diff t1 against t1 flag a b +t1 UPDATE 1 4 +select mo_ctl("dn", "flush", "test.t1"); +mo_ctl(dn, flush, test.t1) +{\n "method": "Flush",\n "result": [\n {\n "returnStr": "OK"\n }\n ]\n}\n +delete from t1 where a = 1; +data branch diff t1 against t1{snapshot="sp"}; +diff t1 against t1 flag a b +t1 DELETE 1 1 +drop snapshot sp; +drop table t1; +create table t1 (a int primary key, b int); +create snapshot sp for table test t1; +insert into t1 values(1,1); +insert into t1 values(2,2); +update t1 set b=2 where a = 1; +select mo_ctl("dn", "flush", "test.t1"); +mo_ctl(dn, flush, test.t1) +{\n "method": "Flush",\n "result": [\n {\n "returnStr": "OK"\n }\n ]\n}\n +update t1 set b=3 where a = 1; +select mo_ctl("dn", "flush", "test.t1"); +mo_ctl(dn, flush, test.t1) +{\n "method": "Flush",\n "result": [\n {\n "returnStr": "OK"\n }\n ]\n}\n +update t1 set b=4 where a = 1; +data branch diff t1 against t1{snapshot="sp"}; +diff t1 against t1 flag a b +t1 INSERT 1 4 +t1 INSERT 2 2 +select mo_ctl("dn", "flush", "test.t1"); +mo_ctl(dn, flush, test.t1) +{\n "method": "Flush",\n "result": [\n {\n "returnStr": "OK"\n }\n ]\n}\n +delete from t1 where a = 1; +data branch diff t1 against t1{snapshot="sp"}; +diff t1 against t1 flag a b +t1 INSERT 2 2 +drop snapshot sp; +drop table t1; diff --git a/test/distributed/cases/git4data/branch/diff/diff_7.sql b/test/distributed/cases/git4data/branch/diff/diff_7.sql new file mode 100644 index 0000000000000..f1c863176654b --- /dev/null +++ b/test/distributed/cases/git4data/branch/diff/diff_7.sql @@ -0,0 +1,59 @@ +drop database if exists test; +create database test; +use test; + +-- refer to data_branch.go#buildHashmapForTable +-- case 1.1 +create table t1 (a int primary key, b int); +insert into t1 values(1,1); +insert into t1 values(2,2); + +create snapshot sp for table test t1; + +update t1 set b=2 where a = 1; +-- @ignore:0 +select mo_ctl("dn", "flush", "test.t1"); + +update t1 set b=3 where a = 1; +-- @ignore:0 +select mo_ctl("dn", "flush", "test.t1"); + +update t1 set b=4 where a = 1; + +data branch diff t1 against t1{snapshot="sp"}; + +-- case 1.2 +select mo_ctl("dn", "flush", "test.t1"); +delete from t1 where a = 1; + +data branch diff t1 against t1{snapshot="sp"}; +drop snapshot sp; +drop table t1; + +create table t1 (a int primary key, b int); + +create snapshot sp for table test t1; + +insert into t1 values(1,1); +insert into t1 values(2,2); + +update t1 set b=2 where a = 1; +-- @ignore:0 +select mo_ctl("dn", "flush", "test.t1"); + +update t1 set b=3 where a = 1; +-- @ignore:0 +select mo_ctl("dn", "flush", "test.t1"); + +update t1 set b=4 where a = 1; + +-- case 2.1 +data branch diff t1 against t1{snapshot="sp"}; + +select mo_ctl("dn", "flush", "test.t1"); +delete from t1 where a = 1; + +-- case 2.2 +data branch diff t1 against t1{snapshot="sp"}; +drop snapshot sp; +drop table t1; From d357af59e9199d0855e0a6bd4f0a720402ae1b74 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 22 Jan 2026 17:27:36 +0800 Subject: [PATCH 02/23] fix: diff sql output and merge cases --- pkg/frontend/data_branch.go | 395 ++++++++++++------ pkg/tests/dml/dml_test.go | 243 +++++++++-- .../git4data/branch/merge/merge_4.result | 33 ++ .../cases/git4data/branch/merge/merge_4.sql | 37 ++ .../git4data/branch/merge/merge_5.result | 44 ++ .../cases/git4data/branch/merge/merge_5.sql | 55 +++ .../git4data/branch/merge/merge_6.result | 90 ++++ .../cases/git4data/branch/merge/merge_6.sql | 62 +++ .../git4data/branch/merge/merge_7.result | 38 ++ .../cases/git4data/branch/merge/merge_7.sql | 34 ++ 10 files changed, 872 insertions(+), 159 deletions(-) create mode 100644 test/distributed/cases/git4data/branch/merge/merge_4.result create mode 100644 test/distributed/cases/git4data/branch/merge/merge_4.sql create mode 100644 test/distributed/cases/git4data/branch/merge/merge_5.result create mode 100644 test/distributed/cases/git4data/branch/merge/merge_5.sql create mode 100644 test/distributed/cases/git4data/branch/merge/merge_6.result create mode 100644 test/distributed/cases/git4data/branch/merge/merge_6.sql create mode 100644 test/distributed/cases/git4data/branch/merge/merge_7.result create mode 100644 test/distributed/cases/git4data/branch/merge/merge_7.sql diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 9b4d4554530ba..f21a433e4b788 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -55,7 +55,6 @@ import ( "github.com/matrixorigin/matrixone/pkg/util/executor" "github.com/matrixorigin/matrixone/pkg/vectorindex/sqlexec" "github.com/matrixorigin/matrixone/pkg/vm/engine" - "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" "github.com/panjf2000/ants/v2" ) @@ -79,8 +78,8 @@ const ( ) const ( - maxSqlBatchCnt = objectio.BlockMaxRows * 10 - maxSqlBatchSize = mpool.MB * 48 + maxSqlBatchCnt = objectio.BlockMaxRows + maxSqlBatchSize = mpool.MB * 32 ) func acquireBuffer(pool *sync.Pool) *bytes.Buffer { @@ -355,7 +354,9 @@ func (retBatchPool *retBatchList) freeAllRetBatches(mp *mpool.MPool) { } type compositeOption struct { - conflictOpt *tree.ConflictOpt + conflictOpt *tree.ConflictOpt + outputSQL bool + expandUpdate bool } func runSql( @@ -830,6 +831,8 @@ func diffMergeAgency( copt.conflictOpt = &tree.ConflictOpt{ Opt: tree.CONFLICT_ACCEPT, } + copt.outputSQL = true + copt.expandUpdate = true } if tblStuff, err = getTableStuff( ctx, ses, bh, diffStmt.TargetTable, diffStmt.BaseTable, @@ -838,6 +841,7 @@ func diffMergeAgency( } } else { copt.conflictOpt = mergeStmt.ConflictOpt + copt.expandUpdate = true if tblStuff, err = getTableStuff( ctx, ses, bh, mergeStmt.SrcTable, mergeStmt.DstTable, ); err != nil { @@ -963,7 +967,7 @@ func handleBranchMerge( return diffMergeAgency(ses, execCtx, stmt) } -func tryFlushDeletesOrReplace( +func tryFlushDeletesOrInserts( ctx context.Context, ses *Session, bh BackgroundExec, @@ -971,16 +975,17 @@ func tryFlushDeletesOrReplace( newKind string, newValsLen int, newRowCnt int, + deleteByFullRow bool, deleteCnt *int, deletesBuf *bytes.Buffer, - replaceCnt *int, - replaceBuf *bytes.Buffer, + insertCnt *int, + insertBuf *bytes.Buffer, writeFile func([]byte) error, ) (err error) { flushDeletes := func() error { if err = flushSqlValues( - ctx, ses, bh, tblStuff, deletesBuf, true, writeFile, + ctx, ses, bh, tblStuff, deletesBuf, true, deleteByFullRow, writeFile, ); err != nil { return err } @@ -990,16 +995,15 @@ func tryFlushDeletesOrReplace( return nil } - flushReplace := func() error { - + flushInserts := func() error { if err = flushSqlValues( - ctx, ses, bh, tblStuff, replaceBuf, false, writeFile, + ctx, ses, bh, tblStuff, insertBuf, false, false, writeFile, ); err != nil { return err } - *replaceCnt = 0 - replaceBuf.Reset() + *insertCnt = 0 + insertBuf.Reset() return nil } @@ -1011,22 +1015,27 @@ func tryFlushDeletesOrReplace( return flushDeletes() } } else { - if replaceBuf.Len()+newValsLen >= maxSqlBatchSize || - *replaceCnt+newRowCnt >= maxSqlBatchCnt { - return flushReplace() + if insertBuf.Len()+newValsLen >= maxSqlBatchSize || + *insertCnt+newRowCnt >= maxSqlBatchCnt { + if *deleteCnt > 0 { + if err = flushDeletes(); err != nil { + return err + } + } + return flushInserts() } } return nil } - if *replaceCnt > 0 { - if err = flushReplace(); err != nil { + if *deleteCnt > 0 { + if err = flushDeletes(); err != nil { return err } } - if *deleteCnt > 0 { - if err = flushDeletes(); err != nil { + if *insertCnt > 0 { + if err = flushInserts(); err != nil { return err } } @@ -1035,15 +1044,16 @@ func tryFlushDeletesOrReplace( } type sqlValuesAppender struct { - ctx context.Context - ses *Session - bh BackgroundExec - tblStuff tableStuff - deleteCnt *int - deleteBuf *bytes.Buffer - replaceCnt *int - replaceBuf *bytes.Buffer - writeFile func([]byte) error + ctx context.Context + ses *Session + bh BackgroundExec + tblStuff tableStuff + deleteByFullRow bool + deleteCnt *int + deleteBuf *bytes.Buffer + insertCnt *int + insertBuf *bytes.Buffer + writeFile func([]byte) error } func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { @@ -1055,9 +1065,22 @@ func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { if kind == diffDelete { targetBuf = sva.deleteBuf rowCnt = sva.deleteCnt + if sva.deleteByFullRow { + newValsLen := len(rowValues) + if err := tryFlushDeletesOrInserts( + sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, + sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + ); err != nil { + return err + } + + targetBuf.Write(rowValues) + *rowCnt++ + return nil + } } else { - targetBuf = sva.replaceBuf - rowCnt = sva.replaceCnt + targetBuf = sva.insertBuf + rowCnt = sva.insertCnt } newValsLen := len(rowValues) @@ -1065,9 +1088,9 @@ func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { newValsLen++ } - if err := tryFlushDeletesOrReplace( - sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, - sva.deleteCnt, sva.deleteBuf, sva.replaceCnt, sva.replaceBuf, sva.writeFile, + if err := tryFlushDeletesOrInserts( + sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, + sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, ); err != nil { return err } @@ -1081,13 +1104,13 @@ func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { } func (sva sqlValuesAppender) flushAll() error { - return tryFlushDeletesOrReplace( + return tryFlushDeletesOrInserts( sva.ctx, sva.ses, sva.bh, sva.tblStuff, "", - 0, 0, sva.deleteCnt, sva.deleteBuf, sva.replaceCnt, sva.replaceBuf, sva.writeFile, + 0, 0, sva.deleteByFullRow, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, ) } -func writeReplaceRowValues( +func writeInsertRowValues( ses *Session, tblStuff tableStuff, row []any, @@ -1131,6 +1154,39 @@ func writeDeleteRowValues( return nil } +func writeDeleteRowSQLFull( + ctx context.Context, + ses *Session, + tblStuff tableStuff, + row []any, + buf *bytes.Buffer, +) error { + // Use NULL-aware equality and LIMIT 1 to preserve duplicate-row semantics. + buf.WriteString(fmt.Sprintf( + "delete from %s.%s where ", + tblStuff.baseRel.GetTableDef(ctx).DbName, + tblStuff.baseRel.GetTableDef(ctx).Name, + )) + for i, idx := range tblStuff.def.visibleIdxes { + if i > 0 { + buf.WriteString(" and ") + } + colName := tblStuff.def.colNames[idx] + if row[idx] == nil { + buf.WriteString(colName) + buf.WriteString(" is null") + } else { + buf.WriteString(colName) + buf.WriteString(" = ") + if err := formatValIntoString(ses, row[idx], tblStuff.def.colTypes[idx], buf); err != nil { + return err + } + } + } + buf.WriteString(" limit 1;\n") + return nil +} + func appendBatchRowsAsSQLValues( ctx context.Context, ses *Session, @@ -1196,11 +1252,17 @@ func appendBatchRowsAsSQLValues( tmpValsBuffer.Reset() if wrapped.kind == diffDelete { - if err = writeDeleteRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { - return + if appender.deleteByFullRow { + if err = writeDeleteRowSQLFull(ctx, ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } + } else { + if err = writeDeleteRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } } } else { - if err = writeReplaceRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { + if err = writeInsertRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { return } } @@ -1229,17 +1291,17 @@ func mergeDiffs( ) (err error) { var ( - replaceCnt int - deleteCnt int + insertCnt int + deleteCnt int - replaceIntoVals = acquireBuffer(tblStuff.bufPool) - deleteFromVals = acquireBuffer(tblStuff.bufPool) - firstErr error - tmpValsBuffer = acquireBuffer(tblStuff.bufPool) + insertIntoVals = acquireBuffer(tblStuff.bufPool) + deleteFromVals = acquireBuffer(tblStuff.bufPool) + firstErr error + tmpValsBuffer = acquireBuffer(tblStuff.bufPool) ) defer func() { - releaseBuffer(tblStuff.bufPool, replaceIntoVals) + releaseBuffer(tblStuff.bufPool, insertIntoVals) releaseBuffer(tblStuff.bufPool, deleteFromVals) releaseBuffer(tblStuff.bufPool, tmpValsBuffer) }() @@ -1249,14 +1311,15 @@ func mergeDiffs( }() appender := sqlValuesAppender{ - ctx: ctx, - ses: ses, - bh: bh, - tblStuff: tblStuff, - deleteCnt: &deleteCnt, - deleteBuf: deleteFromVals, - replaceCnt: &replaceCnt, - replaceBuf: replaceIntoVals, + ctx: ctx, + ses: ses, + bh: bh, + tblStuff: tblStuff, + deleteByFullRow: tblStuff.def.pkKind == fakeKind, + deleteCnt: &deleteCnt, + deleteBuf: deleteFromVals, + insertCnt: &insertCnt, + insertBuf: insertIntoVals, } // conflict option should be pushed down to the hash phase, @@ -1403,12 +1466,12 @@ func satisfyDiffOutputOpt( } else if len(stmt.OutputOpt.DirPath) != 0 { var ( - replaceCnt int - deleteCnt int + insertCnt int + deleteCnt int - deleteFromValsBuffer = acquireBuffer(tblStuff.bufPool) - replaceIntoValsBuffer = acquireBuffer(tblStuff.bufPool) - tmpValsBuffer = acquireBuffer(tblStuff.bufPool) + deleteFromValsBuffer = acquireBuffer(tblStuff.bufPool) + insertIntoValsBuffer = acquireBuffer(tblStuff.bufPool) + tmpValsBuffer = acquireBuffer(tblStuff.bufPool) fileHint string fullFilePath string @@ -1426,7 +1489,7 @@ func satisfyDiffOutputOpt( release() } releaseBuffer(tblStuff.bufPool, deleteFromValsBuffer) - releaseBuffer(tblStuff.bufPool, replaceIntoValsBuffer) + releaseBuffer(tblStuff.bufPool, insertIntoValsBuffer) releaseBuffer(tblStuff.bufPool, tmpValsBuffer) }() @@ -1437,15 +1500,16 @@ func satisfyDiffOutputOpt( } appender := sqlValuesAppender{ - ctx: ctx, - ses: ses, - bh: bh, - tblStuff: tblStuff, - deleteCnt: &deleteCnt, - deleteBuf: deleteFromValsBuffer, - replaceCnt: &replaceCnt, - replaceBuf: replaceIntoValsBuffer, - writeFile: writeFile, + ctx: ctx, + ses: ses, + bh: bh, + tblStuff: tblStuff, + deleteByFullRow: tblStuff.def.pkKind == fakeKind, + deleteCnt: &deleteCnt, + deleteBuf: deleteFromValsBuffer, + insertCnt: &insertCnt, + insertBuf: insertIntoValsBuffer, + writeFile: writeFile, } if writeFile != nil { // Make generated SQL runnable in one transaction. @@ -1475,6 +1539,20 @@ func satisfyDiffOutputOpt( tblStuff.retPool.releaseRetBatch(wrapped.batch, false) continue } + } else if wrapped.name == tblStuff.baseRel.GetTableName() { + if wrapped.kind == diffInsert { + wrapped.kind = diffDelete + } + if wrapped.kind == diffDelete { + if err = appendBatchRowsAsSQLValues( + ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, + ); err != nil { + first = err + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + } } tblStuff.retPool.releaseRetBatch(wrapped.batch, false) @@ -1708,7 +1786,7 @@ func prepareFSForDiffAsFile( } sqlRetHint = fmt.Sprintf( - "DELETE FROM %s.%s, REPLACE INTO %s.%s", + "DELETE FROM %s.%s, INSERT INTO %s.%s", tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableName(), tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableName(), ) @@ -1893,15 +1971,41 @@ func flushSqlValues( tblStuff tableStuff, buf *bytes.Buffer, isDeleteFrom bool, + deleteByFullRow bool, writeFile func([]byte) error, ) (err error) { + if buf.Len() == 0 { + return nil + } + + if isDeleteFrom && deleteByFullRow { + if writeFile != nil { + return writeFile(buf.Bytes()) + } + + statements := bytes.Split(buf.Bytes(), []byte(";\n")) + for _, stmt := range statements { + stmt = bytes.TrimSpace(stmt) + if len(stmt) == 0 { + continue + } + var ret executor.Result + ret, err = runSql(ctx, ses, bh, string(stmt)+";", nil, nil) + ret.Close() + if err != nil { + return err + } + } + return nil + } + sqlBuffer := acquireBuffer(tblStuff.bufPool) defer releaseBuffer(tblStuff.bufPool, sqlBuffer) - initReplaceIntoBuf := func() { + initInsertIntoBuf := func() { sqlBuffer.WriteString(fmt.Sprintf( - "replace into %s.%s values ", + "insert into %s.%s values ", tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableDef(ctx).Name, )) @@ -1934,7 +2038,7 @@ func flushSqlValues( sqlBuffer.Write(buf.Bytes()) sqlBuffer.WriteString(")") } else { - initReplaceIntoBuf() + initInsertIntoBuf() sqlBuffer.Write(buf.Bytes()) } @@ -2903,7 +3007,7 @@ func hashDiffIfHasLCA( if err3 := findDeleteAndUpdateBat( newCtx, ses, bh, tblStuff, name, - tmpCh, branchTS, hashmap1, hashmap2, + tmpCh, branchTS, copt.expandUpdate, hashmap1, hashmap2, ); err3 != nil { atomicErr.Store(err3) } @@ -3093,18 +3197,20 @@ func compareRowInWrappedBatches( func findDeleteAndUpdateBat( ctx context.Context, ses *Session, bh BackgroundExec, tblStuff tableStuff, tblName string, tmpCh chan batchWithKind, branchTS types.TS, + expandUpdate bool, dataHashmap, tombstoneHashmap databranchutils.BranchHashmap, ) (err error) { if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { var ( - err2 error - tuple types.Tuple - dBat *batch.Batch - tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) - tBat2 *batch.Batch - updateBat *batch.Batch - checkRet []databranchutils.GetResult + err2 error + tuple types.Tuple + dBat *batch.Batch + tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) + tBat2 *batch.Batch + updateBat *batch.Batch + updateDeleteBat *batch.Batch + checkRet []databranchutils.GetResult ) send := func(bwk batchWithKind) error { @@ -3177,11 +3283,20 @@ func findDeleteAndUpdateBat( if updateBat == nil { updateBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) } + if expandUpdate && updateDeleteBat == nil { + updateDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } if tuple, _, err2 = dataHashmap.DecodeRow(check.Rows[0]); err2 != nil { return err2 } + if expandUpdate { + if err2 = updateDeleteBat.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { + return err2 + } + } + if err2 = appendTupleToBat(ses, updateBat, tuple, tblStuff); err2 != nil { return err2 } @@ -3199,12 +3314,32 @@ func findDeleteAndUpdateBat( if updateBat != nil { updateBat.SetRowCount(updateBat.Vecs[0].Length()) - if err2 = send(batchWithKind{ - name: tblName, - batch: updateBat, - kind: diffUpdate, - }); err2 != nil { - return err2 + if expandUpdate { + if updateDeleteBat != nil { + updateDeleteBat.SetRowCount(updateDeleteBat.Vecs[0].Length()) + if err2 = send(batchWithKind{ + name: tblName, + batch: updateDeleteBat, + kind: diffDelete, + }); err2 != nil { + return err2 + } + } + if err2 = send(batchWithKind{ + name: tblName, + batch: updateBat, + kind: diffInsert, + }); err2 != nil { + return err2 + } + } else { + if err2 = send(batchWithKind{ + name: tblName, + batch: updateBat, + kind: diffUpdate, + }); err2 != nil { + return err2 + } } } @@ -3316,12 +3451,13 @@ func diffDataHelper( if err = tarDataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { var ( - err2 error - tarBat *batch.Batch - baseBat *batch.Batch - tarTuple types.Tuple - baseTuple types.Tuple - checkRet databranchutils.GetResult + err2 error + tarBat *batch.Batch + baseBat *batch.Batch + baseDeleteBat *batch.Batch + tarTuple types.Tuple + baseTuple types.Tuple + checkRet databranchutils.GetResult ) tarBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) @@ -3385,11 +3521,25 @@ func diffDataHelper( } if notSame { - // conflict happened - if err2 = checkConflictAndAppendToBat( - ses, copt, tblStuff, tarBat, baseBat, tarTuple, baseTuple, - ); err2 != nil { - return err2 + if copt.conflictOpt != nil && + copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT && + copt.expandUpdate { + if baseDeleteBat == nil { + baseDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } + if err2 = appendTupleToBat(ses, baseDeleteBat, baseTuple, tblStuff); err2 != nil { + return err2 + } + if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + return err2 + } + } else { + // conflict happened + if err2 = checkConflictAndAppendToBat( + ses, copt, tblStuff, tarBat, baseBat, tarTuple, baseTuple, + ); err2 != nil { + return err2 + } } } } @@ -3406,6 +3556,18 @@ func diffDataHelper( default: } + if baseDeleteBat != nil { + if stop, err3 := emitBatch(emit, batchWithKind{ + batch: baseDeleteBat, + kind: diffDelete, + name: tblStuff.baseRel.GetTableName(), + }, false, tblStuff.retPool); err3 != nil { + return err3 + } else if stop { + return nil + } + } + if stop, err3 := emitBatch(emit, batchWithKind{ batch: tarBat, kind: diffInsert, @@ -3432,8 +3594,10 @@ func diffDataHelper( } if copt.conflictOpt != nil { - // merge doesnt need the base data - return nil + if !copt.outputSQL { + // merge doesnt need the base data + return nil + } } if err = baseDataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { @@ -3961,11 +4125,9 @@ func buildHashmapForTable( if isTombstone { // keep the commit ts taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll], []int{0}) - fmt.Println("A", common.MoBatchToString(bat, bat.RowCount())) } else { // keep the commit ts taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll], []int{tblStuff.def.pkColIdx}) - fmt.Println("B", common.MoBatchToString(bat, bat.RowCount())) } bat.Clean(mp) @@ -4113,33 +4275,6 @@ func buildHashmapForTable( return nil, nil, err } - //tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - // cursor.ForEach(func(key []byte, rows [][]byte) error { - // for i := range rows { - // if tuple, _, err3 := tombstoneHashmap.DecodeRow(rows[i]); err3 != nil { - // return err3 - // } else { - // fmt.Println("tombstone", tuple[0].(int32)) - // } - // } - // return nil - // }) - // return nil - //}, 1) - // - //dataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - // cursor.ForEach(func(key []byte, rows [][]byte) error { - // for i := range rows { - // if tuple, _, err3 := dataHashmap.DecodeRow(rows[i]); err3 != nil { - // return err3 - // } else { - // fmt.Println("data", tuple[0].(int32), tuple[1].(int32)) - // } - // } - // return nil - // }) - // return nil - //}, 1) return } diff --git a/pkg/tests/dml/dml_test.go b/pkg/tests/dml/dml_test.go index 49376bad692cf..e708350d889cc 100644 --- a/pkg/tests/dml/dml_test.go +++ b/pkg/tests/dml/dml_test.go @@ -140,6 +140,18 @@ func TestDataBranchDiffAsFile(t *testing.T) { t.Log("large composite diff with multi column workload") runLargeCompositeDiff(t, ctx, sqlDB) + t.Log("diff output splits updates into delete + insert (single pk)") + runUpdateSplitDiffAsFile(t, ctx, sqlDB) + + t.Log("diff output splits updates into delete + insert (composite pk)") + runCompositeUpdateSplitDiffAsFile(t, ctx, sqlDB) + + t.Log("diff output handles no-pk duplicates and null deletes") + runNoPKDuplicateDiffAsFile(t, ctx, sqlDB) + + t.Log("diff output handles mixed types and string edge cases") + runComplexTypeDiffAsFile(t, ctx, sqlDB) + t.Log("sql diff handles rows containing NULL values") runSQLDiffHandlesNulls(t, ctx, sqlDB) @@ -200,7 +212,7 @@ func runSinglePKWithBase(t *testing.T, parentCtx context.Context, db *sql.DB) { sqlContent := readSQLFile(t, diffPath) lowerContent := strings.ToLower(sqlContent) - require.Contains(t, lowerContent, fmt.Sprintf("replace into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) applyDiffStatements(t, ctx, db, sqlContent) assertTablesEqual(t, ctx, db, dbName, branch, base) @@ -240,7 +252,7 @@ func runMultiPKWithBase(t *testing.T, parentCtx context.Context, db *sql.DB) { sqlContent := readSQLFile(t, diffPath) lowerContent := strings.ToLower(sqlContent) - require.Contains(t, lowerContent, fmt.Sprintf("replace into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) require.Contains(t, lowerContent, fmt.Sprintf("delete from %s.%s where (org_id,event_id)", strings.ToLower(dbName), base)) applyDiffStatements(t, ctx, db, sqlContent) @@ -283,7 +295,7 @@ func runSinglePKNoBase(t *testing.T, parentCtx context.Context, db *sql.DB) { } require.ElementsMatch(t, expected, records) - applyCSVDiffRecords(t, ctx, db, dbName, base, records) + loadDiffCSVIntoTable(t, ctx, db, base, diffPath) assertTablesEqual(t, ctx, db, dbName, target, base) } @@ -323,7 +335,7 @@ func runMultiPKNoBase(t *testing.T, parentCtx context.Context, db *sql.DB) { } require.ElementsMatch(t, expected, records) - applyCSVDiffRecords(t, ctx, db, dbName, base, records) + loadDiffCSVIntoTable(t, ctx, db, base, diffPath) assertTablesEqual(t, ctx, db, dbName, target, base) } @@ -400,7 +412,7 @@ from generate_series(10001, 10800) as g`, branch) sqlContent := readSQLFile(t, diffPath) lowerContent := strings.ToLower(sqlContent) - require.Contains(t, lowerContent, fmt.Sprintf("replace into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) require.Contains(t, lowerContent, fmt.Sprintf("delete from %s.%s", strings.ToLower(dbName), base)) applyDiffStatements(t, ctx, db, sqlContent) @@ -753,13 +765,209 @@ func runDiffOutputToStage(t *testing.T, parentCtx context.Context, db *sql.DB) { require.NotEmpty(t, payload, "stage diff payload is empty") sqlContent := strings.ToLower(string(payload)) - require.Contains(t, sqlContent, fmt.Sprintf("replace into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, sqlContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) require.Contains(t, sqlContent, fmt.Sprintf("delete from %s.%s", strings.ToLower(dbName), base)) applyDiffStatements(t, ctx, db, string(payload)) assertTablesEqual(t, ctx, db, dbName, branch, base) } +func runUpdateSplitDiffAsFile(t *testing.T, parentCtx context.Context, db *sql.DB) { + t.Helper() + + ctx, cancel := context.WithTimeout(parentCtx, time.Second*90) + defer cancel() + + dbName := testutils.GetDatabaseName(t) + base := "split_pk_base" + branch := "split_pk_branch" + diffDir := t.TempDir() + diffLiteral := strings.ReplaceAll(diffDir, "'", "''") + + execSQLDB(t, ctx, db, fmt.Sprintf("create database `%s`", dbName)) + defer func() { + execSQLDB(t, ctx, db, "use mo_catalog") + execSQLDB(t, ctx, db, fmt.Sprintf("drop database if exists `%s`", dbName)) + }() + execSQLDB(t, ctx, db, fmt.Sprintf("use `%s`", dbName)) + + execSQLDB(t, ctx, db, fmt.Sprintf("create table `%s` (id int primary key, score int, note varchar(32))", base)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into `%s` values (1, 10, 'seed'), (2, 20, 'seed'), (3, 30, 'seed')", base)) + + execSQLDB(t, ctx, db, fmt.Sprintf("data branch create table `%s` from `%s`", branch, base)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set score = score + 9, note = 'changed' where id in (1,3)", branch)) + + diffStmt := fmt.Sprintf("data branch diff %s against %s output file '%s'", branch, base, diffLiteral) + diffPath := execDiffAndFetchFile(t, ctx, db, diffStmt) + require.Equal(t, ".sql", filepath.Ext(diffPath)) + require.True(t, strings.HasPrefix(diffPath, diffDir), "diff file %s not in dir %s", diffPath, diffDir) + + sqlContent := readSQLFile(t, diffPath) + lowerContent := strings.ToLower(sqlContent) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("delete from %s.%s where id in", strings.ToLower(dbName), base)) + require.NotContains(t, lowerContent, "update ") + + applyDiffStatements(t, ctx, db, sqlContent) + assertTablesEqual(t, ctx, db, dbName, branch, base) +} + +func runCompositeUpdateSplitDiffAsFile(t *testing.T, parentCtx context.Context, db *sql.DB) { + t.Helper() + + ctx, cancel := context.WithTimeout(parentCtx, time.Second*90) + defer cancel() + + dbName := testutils.GetDatabaseName(t) + base := "split_comp_base" + branch := "split_comp_branch" + diffDir := t.TempDir() + diffLiteral := strings.ReplaceAll(diffDir, "'", "''") + + execSQLDB(t, ctx, db, fmt.Sprintf("create database `%s`", dbName)) + defer func() { + execSQLDB(t, ctx, db, "use mo_catalog") + execSQLDB(t, ctx, db, fmt.Sprintf("drop database if exists `%s`", dbName)) + }() + execSQLDB(t, ctx, db, fmt.Sprintf("use `%s`", dbName)) + + execSQLDB(t, ctx, db, fmt.Sprintf("create table `%s` (org_id int, event_id int, qty int, note varchar(32), primary key (org_id, event_id))", base)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into `%s` values (1, 1, 10, 'seed'), (1, 2, 20, 'seed'), (2, 1, 30, 'seed')", base)) + + execSQLDB(t, ctx, db, fmt.Sprintf("data branch create table `%s` from `%s`", branch, base)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set qty = qty + 5, note = 'shifted' where org_id = 1 and event_id = 2", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set note = null where org_id = 2 and event_id = 1", branch)) + + diffStmt := fmt.Sprintf("data branch diff %s against %s output file '%s'", branch, base, diffLiteral) + diffPath := execDiffAndFetchFile(t, ctx, db, diffStmt) + require.Equal(t, ".sql", filepath.Ext(diffPath)) + require.True(t, strings.HasPrefix(diffPath, diffDir), "diff file %s not in dir %s", diffPath, diffDir) + + sqlContent := readSQLFile(t, diffPath) + lowerContent := strings.ToLower(sqlContent) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("delete from %s.%s where (org_id,event_id) in", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, "null") + require.NotContains(t, lowerContent, "update ") + + applyDiffStatements(t, ctx, db, sqlContent) + assertTablesEqual(t, ctx, db, dbName, branch, base) +} + +func runNoPKDuplicateDiffAsFile(t *testing.T, parentCtx context.Context, db *sql.DB) { + t.Helper() + + ctx, cancel := context.WithTimeout(parentCtx, time.Second*120) + defer cancel() + + dbName := testutils.GetDatabaseName(t) + base := "no_pk_base" + branch := "no_pk_branch" + diffDir := t.TempDir() + diffLiteral := strings.ReplaceAll(diffDir, "'", "''") + + execSQLDB(t, ctx, db, fmt.Sprintf("create database `%s`", dbName)) + defer func() { + execSQLDB(t, ctx, db, "use mo_catalog") + execSQLDB(t, ctx, db, fmt.Sprintf("drop database if exists `%s`", dbName)) + }() + execSQLDB(t, ctx, db, fmt.Sprintf("use `%s`", dbName)) + + execSQLDB(t, ctx, db, fmt.Sprintf("create table `%s` (id int, grp int, note varchar(32))", base)) + execSQLDB(t, ctx, db, fmt.Sprintf(`insert into %s values + (1, 10, 'dup'), + (1, 10, 'dup'), + (1, 10, 'dup'), + (1, 10, 'dup'), + (2, 20, null), + (3, 30, 'keep'), + (4, null, 'nil'), + (5, 50, 'change')`, base)) + + execSQLDB(t, ctx, db, fmt.Sprintf("data branch create table `%s` from `%s`", branch, base)) + execSQLDB(t, ctx, db, fmt.Sprintf("delete from `%s` where id = 1 and grp = 10 and note = 'dup' limit 1", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("delete from `%s` where id = 1 and grp = 10 and note = 'dup' limit 1", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("delete from `%s` where id = 2 and grp = 20 and note is null", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set grp = 41 where id = 4 and grp is null", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set grp = 55, note = 'changed' where id = 5 and grp = 50 and note = 'change'", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into `%s` values (6, 60, 'added')", branch)) + + diffStmt := fmt.Sprintf("data branch diff %s against %s output file '%s'", branch, base, diffLiteral) + diffPath := execDiffAndFetchFile(t, ctx, db, diffStmt) + require.Equal(t, ".sql", filepath.Ext(diffPath)) + require.True(t, strings.HasPrefix(diffPath, diffDir), "diff file %s not in dir %s", diffPath, diffDir) + + sqlContent := readSQLFile(t, diffPath) + lowerContent := strings.ToLower(sqlContent) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("delete from %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, "limit 1") + require.Contains(t, lowerContent, "is null") + require.NotContains(t, lowerContent, "update ") + + applyDiffStatements(t, ctx, db, sqlContent) + assertTablesEqual(t, ctx, db, dbName, branch, base) +} + +func runComplexTypeDiffAsFile(t *testing.T, parentCtx context.Context, db *sql.DB) { + t.Helper() + + ctx, cancel := context.WithTimeout(parentCtx, time.Second*120) + defer cancel() + + dbName := testutils.GetDatabaseName(t) + base := "complex_base" + branch := "complex_branch" + diffDir := t.TempDir() + diffLiteral := strings.ReplaceAll(diffDir, "'", "''") + + execSQLDB(t, ctx, db, fmt.Sprintf("create database `%s`", dbName)) + defer func() { + execSQLDB(t, ctx, db, "use mo_catalog") + execSQLDB(t, ctx, db, fmt.Sprintf("drop database if exists `%s`", dbName)) + }() + execSQLDB(t, ctx, db, fmt.Sprintf("use `%s`", dbName)) + + execSQLDB(t, ctx, db, fmt.Sprintf(` +create table %s ( + id int primary key, + name varchar(32), + note text, + amount decimal(10,2), + created_at datetime, + active bool +)`, base)) + + execSQLDB(t, ctx, db, fmt.Sprintf(`insert into %s values + (1, 'Alpha', 'Seed', 10.50, '2024-01-01 10:00:00', true), + (2, 'alpha', '', 0.00, null, false), + (3, 'MIX', 'case', 33.33, '2024-02-02 02:02:02', true), + (4, 'keep', 'NULLABLE', null, '2024-03-03 03:03:03', true)`, base)) + + execSQLDB(t, ctx, db, fmt.Sprintf("data branch create table `%s` from `%s`", branch, base)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set name = 'ALPHA', note = 'seed' where id = 1", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set note = 'O\\'Reilly', created_at = '2024-01-02 00:00:00', active = true where id = 2", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("update `%s` set note = '', amount = 40.00 where id = 3", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("delete from `%s` where id = 4", branch)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into `%s` values (5, 'path\\\\dir', null, 99.99, null, false)", branch)) + + diffStmt := fmt.Sprintf("data branch diff %s against %s output file '%s'", branch, base, diffLiteral) + diffPath := execDiffAndFetchFile(t, ctx, db, diffStmt) + require.Equal(t, ".sql", filepath.Ext(diffPath)) + require.True(t, strings.HasPrefix(diffPath, diffDir), "diff file %s not in dir %s", diffPath, diffDir) + + sqlContent := readSQLFile(t, diffPath) + lowerContent := strings.ToLower(sqlContent) + require.Contains(t, lowerContent, fmt.Sprintf("insert into %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, fmt.Sprintf("delete from %s.%s", strings.ToLower(dbName), base)) + require.Contains(t, lowerContent, "null") + require.Contains(t, lowerContent, "''") + require.NotContains(t, lowerContent, "update ") + + applyDiffStatements(t, ctx, db, sqlContent) + assertTablesEqual(t, ctx, db, dbName, branch, base) +} + func runBranchDatabaseMetadata(t *testing.T, parentCtx context.Context, db *sql.DB) { t.Helper() @@ -915,29 +1123,6 @@ func readDiffCSVFile(t *testing.T, path string) [][]string { return records } -func applyCSVDiffRecords(t *testing.T, ctx context.Context, db *sql.DB, schema, table string, records [][]string) { - t.Helper() - - require.NotEmpty(t, records, "no csv records to apply") - valueClauses := make([]string, len(records)) - for i, rec := range records { - values := make([]string, len(rec)) - for j, field := range rec { - values[j] = csvFieldToSQLLiteral(field) - } - valueClauses[i] = fmt.Sprintf("(%s)", strings.Join(values, ",")) - } - stmt := fmt.Sprintf("replace into %s.%s values %s", schema, table, strings.Join(valueClauses, ",")) - execSQLDB(t, ctx, db, stmt) -} - -func csvFieldToSQLLiteral(val string) string { - if val == `\N` { - return "NULL" - } - return fmt.Sprintf("'%s'", strings.ReplaceAll(val, "'", "''")) -} - func loadDiffCSVIntoTable(t *testing.T, ctx context.Context, db *sql.DB, table, csvPath string) { t.Helper() diff --git a/test/distributed/cases/git4data/branch/merge/merge_4.result b/test/distributed/cases/git4data/branch/merge/merge_4.result new file mode 100644 index 0000000000000..80ebf19499db3 --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_4.result @@ -0,0 +1,33 @@ +drop database if exists test_merge_nopk; +create database test_merge_nopk; +use test_merge_nopk; +create table t0(a int, b varchar(10), c int); +insert into t0 values +(1,'dup',null), +(1,'dup',null), +(2,null,2), +(3,'x',3); +drop snapshot if exists sp0; +create snapshot sp0 for table test_merge_nopk t0; +data branch create table t1 from t0{snapshot="sp0"}; +data branch create table t2 from t0{snapshot="sp0"}; +insert into t1 values(99,'base',99); +delete from t2 where a=1 and b='dup' and c is null limit 1; +delete from t2 where a=2 and b is null and c=2; +update t2 set b = null, c = 30 where a=3 and b='x' and c=3; +insert into t2 values(4,'new',null); +data branch merge t2 into t1; +select a, b, c, count(*) as cnt from t1 group by a, b, c order by a, b, c; +a b c cnt +1 dup null 1 +3 null 30 1 +4 new null 1 +99 base 99 1 +select * from t1 where a=99; +a b c +99 base 99 +drop snapshot sp0; +drop table t0; +drop table t1; +drop table t2; +drop database test_merge_nopk; diff --git a/test/distributed/cases/git4data/branch/merge/merge_4.sql b/test/distributed/cases/git4data/branch/merge/merge_4.sql new file mode 100644 index 0000000000000..b2796fc1df8e0 --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_4.sql @@ -0,0 +1,37 @@ +drop database if exists test_merge_nopk; +create database test_merge_nopk; +use test_merge_nopk; + +-- case 1: no PK with duplicates and NULLs, merge should delete only one duplicate +create table t0(a int, b varchar(10), c int); +insert into t0 values +(1,'dup',null), +(1,'dup',null), +(2,null,2), +(3,'x',3); + +drop snapshot if exists sp0; +create snapshot sp0 for table test_merge_nopk t0; + +data branch create table t1 from t0{snapshot="sp0"}; +data branch create table t2 from t0{snapshot="sp0"}; + +-- keep a base-only row in destination +insert into t1 values(99,'base',99); + +-- source changes: delete one duplicate, delete a NULL row, update to NULL, insert new row +delete from t2 where a=1 and b='dup' and c is null limit 1; +delete from t2 where a=2 and b is null and c=2; +update t2 set b = null, c = 30 where a=3 and b='x' and c=3; +insert into t2 values(4,'new',null); + +data branch merge t2 into t1; + +select a, b, c, count(*) as cnt from t1 group by a, b, c order by a, b, c; +select * from t1 where a=99; + +drop snapshot sp0; +drop table t0; +drop table t1; +drop table t2; +drop database test_merge_nopk; diff --git a/test/distributed/cases/git4data/branch/merge/merge_5.result b/test/distributed/cases/git4data/branch/merge/merge_5.result new file mode 100644 index 0000000000000..f43f6e0c1e736 --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_5.result @@ -0,0 +1,44 @@ +drop database if exists test_merge_pk; +create database test_merge_pk; +use test_merge_pk; +create table t0(a int primary key, b int, note varchar(10)); +insert into t0 values (1,10,'a'),(2,20,'b'),(3,30,'c'); +drop snapshot if exists sp0; +create snapshot sp0 for table test_merge_pk t0; +data branch create table t1 from t0{snapshot="sp0"}; +data branch create table t2 from t0{snapshot="sp0"}; +insert into t1 values(9,90,'base'); +update t2 set b = 22, note = 'b2' where a=2; +delete from t2 where a=3; +insert into t2 values(4,40,'d'); +data branch merge t2 into t1; +select * from t1 order by a; +a b note +1 10 a +2 22 b2 +4 40 d +9 90 base +drop snapshot sp0; +drop table t0; +drop table t1; +drop table t2; +create table t0(a int, b int, c varchar(10), primary key(a, b)); +insert into t0 values(1,1,'x'),(1,2,null),(2,1,'y'); +drop snapshot if exists sp1; +create snapshot sp1 for table test_merge_pk t0; +data branch create table t1 from t0{snapshot="sp1"}; +data branch create table t2 from t0{snapshot="sp1"}; +update t2 set c = 'x2' where a=1 and b=1; +delete from t2 where a=1 and b=2; +insert into t2 values(2,2,null); +data branch merge t2 into t1; +select * from t1 order by a, b; +a b c +1 1 x2 +2 1 y +2 2 null +drop snapshot sp1; +drop table t0; +drop table t1; +drop table t2; +drop database test_merge_pk; diff --git a/test/distributed/cases/git4data/branch/merge/merge_5.sql b/test/distributed/cases/git4data/branch/merge/merge_5.sql new file mode 100644 index 0000000000000..f11362bec474d --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_5.sql @@ -0,0 +1,55 @@ +drop database if exists test_merge_pk; +create database test_merge_pk; +use test_merge_pk; + +-- case 1: PK update/delete/insert with LCA, keep base-only row +create table t0(a int primary key, b int, note varchar(10)); +insert into t0 values (1,10,'a'),(2,20,'b'),(3,30,'c'); + +drop snapshot if exists sp0; +create snapshot sp0 for table test_merge_pk t0; + +data branch create table t1 from t0{snapshot="sp0"}; +data branch create table t2 from t0{snapshot="sp0"}; + +-- destination base-only row +insert into t1 values(9,90,'base'); + +-- source changes +update t2 set b = 22, note = 'b2' where a=2; +delete from t2 where a=3; +insert into t2 values(4,40,'d'); + +data branch merge t2 into t1; + +select * from t1 order by a; + +drop snapshot sp0; +drop table t0; +drop table t1; +drop table t2; + +-- case 2: composite PK with NULL payload changes +create table t0(a int, b int, c varchar(10), primary key(a, b)); +insert into t0 values(1,1,'x'),(1,2,null),(2,1,'y'); + +drop snapshot if exists sp1; +create snapshot sp1 for table test_merge_pk t0; + +data branch create table t1 from t0{snapshot="sp1"}; +data branch create table t2 from t0{snapshot="sp1"}; + +update t2 set c = 'x2' where a=1 and b=1; +delete from t2 where a=1 and b=2; +insert into t2 values(2,2,null); + +data branch merge t2 into t1; + +select * from t1 order by a, b; + +drop snapshot sp1; +drop table t0; +drop table t1; +drop table t2; + +drop database test_merge_pk; diff --git a/test/distributed/cases/git4data/branch/merge/merge_6.result b/test/distributed/cases/git4data/branch/merge/merge_6.result new file mode 100644 index 0000000000000..416f6cd19785e --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_6.result @@ -0,0 +1,90 @@ +drop database if exists test; +create database test; +use test; +create table t1 (a int, b int, note varchar(20)); +insert into t1 values +(1, 10, 'dup'), +(1, 10, 'dup'), +(1, 10, 'dup'), +(1, 10, 'dup'), +(2, 20, null), +(3, 30, 'keep'), +(4, 40, ''), +(5, 50, 'Case'); +data branch create table t2 from t1; +delete from t2 where a = 1 and b = 10 and note = 'dup' limit 1; +delete from t2 where a = 1 and b = 10 and note = 'dup' limit 1; +delete from t2 where a = 2 and b = 20 and note is null; +update t2 set note = '' where a = 3 and b = 30 and note = 'keep'; +update t2 set note = 'case' where a = 5 and b = 50 and note = 'Case'; +insert into t2 values (6, 60, 'new'), (7, 70, null); +data branch diff t2 against t1; +diff t2 against t1 flag a b note +t2 DELETE 1 10 dup +t2 DELETE 1 10 dup +t2 DELETE 2 20 null +t2 UPDATE 3 30 +t2 UPDATE 5 50 case +t2 INSERT 6 60 new +t2 INSERT 7 70 null +data branch merge t2 into t1; +select * from t1 order by a, b, note; +a b note +1 10 dup +1 10 dup +3 30 +4 40 +5 50 case +6 60 new +7 70 null +data branch diff t2 against t1; +diff t2 against t1 flag a b note +t2 UPDATE 3 30 +t1 INSERT 3 30 +t1 DELETE 3 30 keep +t1 DELETE 5 50 Case +t2 UPDATE 5 50 case +t1 INSERT 5 50 case +drop table t1; +drop table t2; +create table t1 (a int, b int, note varchar(20), primary key (a, b)); +insert into t1 values +(1, 10, 'dup'), +(1, 11, 'dup'), +(1, 12, 'dup'), +(1, 13, 'dup'), +(2, 20, null), +(3, 30, 'keep'), +(4, 40, ''), +(5, 50, 'Case'); +data branch create table t2 from t1; +delete from t2 where a = 1 and b = 10 and note = 'dup'; +delete from t2 where a = 1 and b = 11 and note = 'dup'; +delete from t2 where a = 2 and b = 20 and note is null; +update t2 set note = '' where a = 3 and b = 30 and note = 'keep'; +update t2 set note = 'case' where a = 5 and b = 50 and note = 'Case'; +insert into t2 values (6, 60, 'new'), (7, 70, null); +data branch diff t2 against t1; +diff t2 against t1 flag a b note +t2 DELETE 1 10 dup +t2 DELETE 1 11 dup +t2 DELETE 2 20 null +t2 UPDATE 3 30 +t2 UPDATE 5 50 case +t2 INSERT 6 60 new +t2 INSERT 7 70 null +data branch merge t2 into t1; +select * from t1 order by a, b, note; +a b note +1 12 dup +1 13 dup +3 30 +4 40 +5 50 case +6 60 new +7 70 null +data branch diff t2 against t1; +diff t2 against t1 flag a b note +drop table t1; +drop table t2; +drop database test; diff --git a/test/distributed/cases/git4data/branch/merge/merge_6.sql b/test/distributed/cases/git4data/branch/merge/merge_6.sql new file mode 100644 index 0000000000000..28649aadc0659 --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_6.sql @@ -0,0 +1,62 @@ +drop database if exists test; +create database test; +use test; + +-- case 6: no primary key with duplicates, nulls, and empty strings +create table t1 (a int, b int, note varchar(20)); +insert into t1 values + (1, 10, 'dup'), + (1, 10, 'dup'), + (1, 10, 'dup'), + (1, 10, 'dup'), + (2, 20, null), + (3, 30, 'keep'), + (4, 40, ''), + (5, 50, 'Case'); + +data branch create table t2 from t1; +delete from t2 where a = 1 and b = 10 and note = 'dup' limit 1; +delete from t2 where a = 1 and b = 10 and note = 'dup' limit 1; +delete from t2 where a = 2 and b = 20 and note is null; +update t2 set note = '' where a = 3 and b = 30 and note = 'keep'; +update t2 set note = 'case' where a = 5 and b = 50 and note = 'Case'; +insert into t2 values (6, 60, 'new'), (7, 70, null); + +data branch diff t2 against t1; +data branch merge t2 into t1; + +select * from t1 order by a, b, note; +data branch diff t2 against t1; + +drop table t1; +drop table t2; + +-- case 6b: composite primary key variant +create table t1 (a int, b int, note varchar(20), primary key (a, b)); +insert into t1 values + (1, 10, 'dup'), + (1, 11, 'dup'), + (1, 12, 'dup'), + (1, 13, 'dup'), + (2, 20, null), + (3, 30, 'keep'), + (4, 40, ''), + (5, 50, 'Case'); + +data branch create table t2 from t1; +delete from t2 where a = 1 and b = 10 and note = 'dup'; +delete from t2 where a = 1 and b = 11 and note = 'dup'; +delete from t2 where a = 2 and b = 20 and note is null; +update t2 set note = '' where a = 3 and b = 30 and note = 'keep'; +update t2 set note = 'case' where a = 5 and b = 50 and note = 'Case'; +insert into t2 values (6, 60, 'new'), (7, 70, null); + +data branch diff t2 against t1; +data branch merge t2 into t1; + +select * from t1 order by a, b, note; +data branch diff t2 against t1; + +drop table t1; +drop table t2; +drop database test; diff --git a/test/distributed/cases/git4data/branch/merge/merge_7.result b/test/distributed/cases/git4data/branch/merge/merge_7.result new file mode 100644 index 0000000000000..424a3acbda3c9 --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_7.result @@ -0,0 +1,38 @@ +drop database if exists test; +create database test; +use test; +create table t1 ( +org_id int, +event_id int, +name varchar(32), +amount decimal(10,2), +note text, +active bool, +primary key (org_id, event_id) +); +insert into t1 values +(1, 1, 'Alpha', 10.00, 'Seed', true), +(1, 2, 'beta', 20.00, '', false), +(2, 1, 'Gamma', 30.30, null, true); +data branch create table t2 from t1; +update t2 set name = 'ALPHA', amount = 11.00, note = 'seed' where org_id = 1 and event_id = 1; +update t2 set note = null, active = false where org_id = 1 and event_id = 2; +delete from t2 where org_id = 2 and event_id = 1; +insert into t2 values (3, 3, 'path\\dir', 99.99, '', true); +data branch diff t2 against t1; +diff t2 against t1 flag org_id event_id name amount note active +t2 UPDATE 1 1 ALPHA 11.00 seed 1 +t2 UPDATE 1 2 beta 20.00 null 0 +t2 DELETE 2 1 Gamma 30.30 null 1 +t2 INSERT 3 3 path\dir 99.99 1 +data branch merge t2 into t1; +select * from t1 order by org_id, event_id; +org_id event_id name amount note active +1 1 ALPHA 11.00 seed 1 +1 2 beta 20.00 null 0 +3 3 path\dir 99.99 1 +data branch diff t2 against t1; +diff t2 against t1 flag org_id event_id name amount note active +drop table t1; +drop table t2; +drop database test; diff --git a/test/distributed/cases/git4data/branch/merge/merge_7.sql b/test/distributed/cases/git4data/branch/merge/merge_7.sql new file mode 100644 index 0000000000000..11ea2f584d5f8 --- /dev/null +++ b/test/distributed/cases/git4data/branch/merge/merge_7.sql @@ -0,0 +1,34 @@ +drop database if exists test; +create database test; +use test; + +-- case 7: composite primary key with mixed types and nulls +create table t1 ( + org_id int, + event_id int, + name varchar(32), + amount decimal(10,2), + note text, + active bool, + primary key (org_id, event_id) +); +insert into t1 values + (1, 1, 'Alpha', 10.00, 'Seed', true), + (1, 2, 'beta', 20.00, '', false), + (2, 1, 'Gamma', 30.30, null, true); + +data branch create table t2 from t1; +update t2 set name = 'ALPHA', amount = 11.00, note = 'seed' where org_id = 1 and event_id = 1; +update t2 set note = null, active = false where org_id = 1 and event_id = 2; +delete from t2 where org_id = 2 and event_id = 1; +insert into t2 values (3, 3, 'path\\dir', 99.99, '', true); + +data branch diff t2 against t1; +data branch merge t2 into t1; + +select * from t1 order by org_id, event_id; +data branch diff t2 against t1; + +drop table t1; +drop table t2; +drop database test; From c0333b0b07c2643056e534ead6cfc1d70118d9ec Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 22 Jan 2026 18:50:10 +0800 Subject: [PATCH 03/23] update bvt case --- .../cases/git4data/branch/diff/diff_1.result | 6 ++--- .../cases/git4data/branch/diff/diff_2.result | 20 +++++++-------- .../cases/git4data/branch/diff/diff_3.result | Bin 6975 -> 6976 bytes .../cases/git4data/branch/diff/diff_5.result | 24 +++++++++--------- .../cases/git4data/branch/diff/diff_7.result | 1 - .../git4data/branch/merge/merge_2.result | 6 ++--- .../git4data/branch/merge/merge_3.result | 6 ++--- 7 files changed, 31 insertions(+), 32 deletions(-) diff --git a/test/distributed/cases/git4data/branch/diff/diff_1.result b/test/distributed/cases/git4data/branch/diff/diff_1.result index b6d5eee3fadc5..87a2c71166e1c 100644 --- a/test/distributed/cases/git4data/branch/diff/diff_1.result +++ b/test/distributed/cases/git4data/branch/diff/diff_1.result @@ -30,8 +30,8 @@ insert into t2 values(5, 5); create snapshot sp2 for table test t2; data branch diff t2{snapshot="sp2"} against t1{snapshot="sp1"}; diff t2 against t1 flag a b -t2 INSERT 5 5 t1 INSERT 4 4 +t2 INSERT 5 5 data branch diff t1{snapshot="sp1"} against t2{snapshot="sp2"}; diff t1 against t2 flag a b t1 INSERT 4 4 @@ -56,12 +56,12 @@ create snapshot sp2 for table test t2; data branch diff t2{snapshot="sp2"} against t1{snapshot="sp1"}; diff t2 against t1 flag a b t2 INSERT 2 2 -t2 INSERT 5 5 t1 INSERT 4 4 +t2 INSERT 5 5 data branch diff t1{snapshot="sp1"} against t2{snapshot="sp2"}; diff t1 against t2 flag a b -t1 INSERT 4 4 t2 INSERT 2 2 +t1 INSERT 4 4 t2 INSERT 5 5 drop snapshot sp1; drop snapshot sp2; diff --git a/test/distributed/cases/git4data/branch/diff/diff_2.result b/test/distributed/cases/git4data/branch/diff/diff_2.result index 17fd3d8573ed6..17193061657e9 100644 --- a/test/distributed/cases/git4data/branch/diff/diff_2.result +++ b/test/distributed/cases/git4data/branch/diff/diff_2.result @@ -23,12 +23,12 @@ create table t2(a int, b int, primary key(a)); insert into t2 select *,* from generate_series(1, 8192)g; data branch diff t2 against t1; diff t2 against t1 flag a b -t1 INSERT 9 10 t2 INSERT 9 9 -t1 INSERT 99 100 +t1 INSERT 9 10 t2 INSERT 99 99 -t1 INSERT 999 1000 +t1 INSERT 99 100 t2 INSERT 999 999 +t1 INSERT 999 1000 update t2 set b = b+1 where a in (9, 99, 999); data branch diff t2 against t1; diff t2 against t1 flag a b @@ -43,14 +43,14 @@ data branch create table t2 from t0; insert into t2 values(5, 5); data branch diff t2 against t1; diff t2 against t1 flag a b -t2 INSERT 5 5 t1 DELETE 3 3 t1 INSERT 4 4 +t2 INSERT 5 5 delete from t2 where a = 3; data branch diff t2 against t1; diff t2 against t1 flag a b -t2 INSERT 5 5 t1 INSERT 4 4 +t2 INSERT 5 5 drop table t0; drop table t1; drop table t2; @@ -63,14 +63,14 @@ data branch create table t2 from t0; insert into t2 values(5,5); data branch diff t2 against t1; diff t2 against t1 flag a b -t2 INSERT 5 5 t1 UPDATE 3 4 t1 INSERT 4 4 +t2 INSERT 5 5 update t2 set b = b + 1 where a = 3; data branch diff t2 against t1; diff t2 against t1 flag a b -t2 INSERT 5 5 t1 INSERT 4 4 +t2 INSERT 5 5 drop table t0; drop table t1; drop table t2; @@ -94,10 +94,10 @@ update t2 set c = c + 1 where a in (2, 200, 1000); insert into t2 values(9001, 9001, 9001); data branch diff t2 against t1; diff t2 against t1 flag a b c -t2 UPDATE 2 2 3 t1 UPDATE 1 1 2 -t2 UPDATE 200 200 201 +t2 UPDATE 2 2 3 t1 UPDATE 100 100 101 -t2 INSERT 9001 9001 9001 +t2 UPDATE 200 200 201 t1 INSERT 9000 9000 9000 +t2 INSERT 9001 9001 9001 drop database test; diff --git a/test/distributed/cases/git4data/branch/diff/diff_3.result b/test/distributed/cases/git4data/branch/diff/diff_3.result index 917d00cc721187fdb4d27d65b03313b36dd874d7..9ce5b3d68f915ca831b90f6da436f7c7baecae16 100644 GIT binary patch delta 75 zcmV-R0JQ(VHo!Kp4hWNY2x*f{31XAe2osYN2xXJu2wk(T2?GZK4U_T^O_O^N6qB40 hB9pQZOp`wmKC`|N4+xY08U>Rk8b*`98B~*O8q@Tr8m#~T delta 65 zcmV-H0KWggHorEo4hWOy2x^lK2x*g130;$E2ynBm2?Ga{G!adcz7Ro^fe}8Fa1bAp X6A>b_zYz}zlP4NRlfW5SlWiK)^xzhK diff --git a/test/distributed/cases/git4data/branch/diff/diff_5.result b/test/distributed/cases/git4data/branch/diff/diff_5.result index d09446257d435..c7286fe1adabf 100644 --- a/test/distributed/cases/git4data/branch/diff/diff_5.result +++ b/test/distributed/cases/git4data/branch/diff/diff_5.result @@ -35,12 +35,12 @@ COUNT(*) 6 data branch diff t1{snapshot="sp2"} against t1{snapshot="sp0"}; diff t1 against t1 flag a b c d -t1 INSERT 6 [0.6, 0.6, 0.6] [0.66, 0.66, 0.66] {"key6": "val6 ', \n, \t "} t1 INSERT 1 [0.1, 0.1, 0.1] [0.11, 0.11, 0.11] {"key1": "val1 ', \n, \t "} t1 INSERT 2 [0.2, 0.2, 0.2] [0.22, 0.22, 0.22] {"key2": "val2 ', \n, \t "} t1 INSERT 3 [0.3, 0.3, 0.3] [0.33, 0.33, 0.33] {"key2": "val2 ', \n, \t "} t1 INSERT 4 [0.4, 0.4, 0.4] [0.44, 0.44, 0.44] {"key4": "val4 ', \n, \t "} t1 INSERT 5 [0.5, 0.5, 0.5] [0.55, 0.55, 0.55] {"key5": "val5 ', \n, \t "} +t1 INSERT 6 [0.6, 0.6, 0.6] [0.66, 0.66, 0.66] {"key6": "val6 ', \n, \t "} drop snapshot sp0; drop snapshot sp1; drop snapshot sp2; @@ -98,16 +98,16 @@ delete from t1_copy1 where a in (1, 3, 5); insert into t1_copy1 values(1, 10); data branch diff t1_copy1 against t1; diff t1_copy1 against t1 flag a b -t1_copy1 UPDATE 11111 11112 +t1_copy1 DELETE 1 1 +t1_copy1 INSERT 1 10 +t1_copy1 DELETE 3 3 +t1_copy1 DELETE 5 5 t1_copy1 UPDATE 99 100 +t1_copy1 UPDATE 111 112 t1_copy1 UPDATE 999 1000 t1_copy1 UPDATE 1111 1112 t1_copy1 UPDATE 9999 10000 -t1_copy1 UPDATE 111 112 -t1_copy1 DELETE 3 3 -t1_copy1 DELETE 1 1 -t1_copy1 DELETE 5 5 -t1_copy1 INSERT 1 10 +t1_copy1 UPDATE 11111 11112 create table t2(a int auto_increment, b int, primary key(a)); insert into t2 select *,* from generate_series(1, 20000)g; data branch create table t2_copy1 from t2; @@ -117,13 +117,13 @@ delete from t2_copy1 where a in (1, 3, 5); insert into t2_copy1 values(1, 10); data branch diff t2_copy1 against t2; diff t2_copy1 against t2 flag a b -t2_copy1 UPDATE 1111 1112 -t2_copy1 UPDATE 9999 10000 +t2_copy1 UPDATE 1 10 +t2_copy1 DELETE 3 3 +t2_copy1 DELETE 5 5 t2_copy1 UPDATE 99 100 t2_copy1 UPDATE 111 112 t2_copy1 UPDATE 999 1000 -t2_copy1 UPDATE 1 10 +t2_copy1 UPDATE 1111 1112 +t2_copy1 UPDATE 9999 10000 t2_copy1 UPDATE 11111 11112 -t2_copy1 DELETE 5 5 -t2_copy1 DELETE 3 3 drop database test; diff --git a/test/distributed/cases/git4data/branch/diff/diff_7.result b/test/distributed/cases/git4data/branch/diff/diff_7.result index 1971107cfaee7..8119998fbf6cb 100644 --- a/test/distributed/cases/git4data/branch/diff/diff_7.result +++ b/test/distributed/cases/git4data/branch/diff/diff_7.result @@ -1,4 +1,3 @@ - drop database if exists test; create database test; use test; diff --git a/test/distributed/cases/git4data/branch/merge/merge_2.result b/test/distributed/cases/git4data/branch/merge/merge_2.result index 495469a3b9cce..f1e46b4515ff2 100644 --- a/test/distributed/cases/git4data/branch/merge/merge_2.result +++ b/test/distributed/cases/git4data/branch/merge/merge_2.result @@ -34,8 +34,8 @@ create table t2 (a int, b int, primary key(a)); insert into t2 values(1,2),(3,3); data branch diff t2 against t1; diff t2 against t1 flag a b -t1 INSERT 1 1 t2 INSERT 1 2 +t1 INSERT 1 1 t1 INSERT 2 2 t2 INSERT 3 3 data branch merge t2 into t1; @@ -64,7 +64,7 @@ diff t2 against t1 flag a b t2 UPDATE 1 3 t1 UPDATE 1 2 data branch merge t2 into t1; -internal error: conflict: t2 UPDATE and t1 UPDATE on pk(1) with different values +internal error: conflict: t2 DELETE and t1 DELETE on pk(1) with different values data branch merge t2 into t1 when conflict skip; select * from t1 order by a asc; a b @@ -87,7 +87,7 @@ diff t2 against t1 flag a b t2 UPDATE 1 3 t1 UPDATE 1 2 data branch merge t2 into t1; -internal error: conflict: t2 UPDATE and t1 UPDATE on pk(1) with different values +internal error: conflict: t2 DELETE and t1 DELETE on pk(1) with different values data branch merge t2 into t1 when conflict skip; select * from t1 order by a asc; a b diff --git a/test/distributed/cases/git4data/branch/merge/merge_3.result b/test/distributed/cases/git4data/branch/merge/merge_3.result index bfed1dbd51769..46bb9adf10961 100644 --- a/test/distributed/cases/git4data/branch/merge/merge_3.result +++ b/test/distributed/cases/git4data/branch/merge/merge_3.result @@ -52,7 +52,7 @@ payout_ops UPDATE 30 null null null 2024-02-28 10:00:00 leo payout_stage INSERT 40 north null 2500.00 null null ad-hoc bonus null null payout_ops INSERT 50 south 2 null null kai null ��3 new workflow data branch merge payout_stage into payout_ops; -internal error: conflict: payout_stage UPDATE and payout_ops UPDATE on pk(10) with different values +internal error: conflict: payout_stage DELETE and payout_ops DELETE on pk(10) with different values data branch merge payout_stage into payout_ops when conflict skip; select batch_id, region, total_count, payout_amount, reviewer, escalation_reason from payout_ops @@ -108,11 +108,11 @@ insert into audit_right values (104, 'd04', 1, x'CC33', 'open', null, null, null); data branch diff audit_right against audit_left; diff audit_right against audit_left flag job_id shard seq checksum status payload metric event_time -audit_left INSERT 101 a01 1 � open inventory gap null 2024-03-02 09:00:00 audit_right INSERT 101 a01 2 null null inventory gap 0.750 2024-03-03 11:00:00 +audit_left INSERT 101 a01 1 � open inventory gap null 2024-03-02 09:00:00 audit_left INSERT 102 b02 null null pending null 1.250 2024-03-02 10:30:00 -audit_left INSERT 103 c03 5 �" closed retry null null audit_right INSERT 103 c03 5 �" closed retry 1.500 2024-03-02 08:30:00 +audit_left INSERT 103 c03 5 �" closed retry null null audit_right INSERT 104 d04 1 �3 open null null null data branch merge audit_right into audit_left when conflict skip; select job_id, shard, seq, status, payload, metric From 920df166711cd31e7086a0f73001a8dec589bfae Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Fri, 23 Jan 2026 18:32:26 +0800 Subject: [PATCH 04/23] improve apply performance, not done # Conflicts: # pkg/frontend/stmt_kind.go --- bench_delete_perf_20260122_190508.md | 15 ++ bench_insert_perf_20260122_191042.md | 14 ++ bench_insert_perf_20260123_103322.md | 14 ++ pkg/frontend/data_branch.go | 216 +++++++++++++++++- pkg/frontend/stmt_kind.go | 3 + .../cases/git4data/branch/diff/diff_7.sql | 2 + 6 files changed, 256 insertions(+), 8 deletions(-) create mode 100644 bench_delete_perf_20260122_190508.md create mode 100644 bench_insert_perf_20260122_191042.md create mode 100644 bench_insert_perf_20260123_103322.md diff --git a/bench_delete_perf_20260122_190508.md b/bench_delete_perf_20260122_190508.md new file mode 100644 index 0000000000000..aa7972623355f --- /dev/null +++ b/bench_delete_perf_20260122_190508.md @@ -0,0 +1,15 @@ +# Delete Benchmark Report + +- db: bench_delete_perf +- total_rows: 10000000 +- delete_rows: 81920 +- batch_size: 8192 +- batches: 10 +- started_at: 20260122_190508 + +|strategy|total_sec|avg_ms_per_batch|rows_per_sec| +|---|---|---|---| +in_list|25.240|2524.032|3246 +subquery_in|0.332|33.198|246763 +join_keys|0.350|34.965|234295 +range|0.394|39.372|208067 diff --git a/bench_insert_perf_20260122_191042.md b/bench_insert_perf_20260122_191042.md new file mode 100644 index 0000000000000..995f6f01a7e2b --- /dev/null +++ b/bench_insert_perf_20260122_191042.md @@ -0,0 +1,14 @@ +# Insert Benchmark Report + +- db: bench_insert_perf +- total_rows: 10000000 +- insert_rows: 81920 +- batch_size: 8192 +- batches: 10 +- started_at: 20260122_191042 + +|strategy|total_sec|avg_ms_per_batch|rows_per_sec| +|---|---|---|---| +values_list|16.861|1686.127|4858 +values_select|19.714|1971.412|4155 +subquery_select|0.434|43.361|188923 diff --git a/bench_insert_perf_20260123_103322.md b/bench_insert_perf_20260123_103322.md new file mode 100644 index 0000000000000..25d6e240056eb --- /dev/null +++ b/bench_insert_perf_20260123_103322.md @@ -0,0 +1,14 @@ +# Insert Benchmark Report + +- db: bench_insert_perf +- total_rows: 10000000 +- insert_rows: 81920 +- batch_size: 8192 +- batches: 10 +- started_at: 20260123_103322 + +|strategy|total_sec|avg_ms_per_batch|rows_per_sec| +|---|---|---|---| +values_list|15.160|1516.049|5404 +values_select|16.953|1695.303|4832 +subquery_select|0.562|56.167|145851 diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index f21a433e4b788..4fdd8543a386c 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -70,6 +70,8 @@ const ( diffUpdate = "UPDATE" ) +var diffTempTableSeq uint64 + const ( lcaEmpty = iota lcaOther @@ -78,7 +80,7 @@ const ( ) const ( - maxSqlBatchCnt = objectio.BlockMaxRows + maxSqlBatchCnt = objectio.BlockMaxRows * 10 maxSqlBatchSize = mpool.MB * 32 ) @@ -976,6 +978,7 @@ func tryFlushDeletesOrInserts( newValsLen int, newRowCnt int, deleteByFullRow bool, + pkInfo *pkBatchInfo, deleteCnt *int, deletesBuf *bytes.Buffer, insertCnt *int, @@ -985,7 +988,7 @@ func tryFlushDeletesOrInserts( flushDeletes := func() error { if err = flushSqlValues( - ctx, ses, bh, tblStuff, deletesBuf, true, deleteByFullRow, writeFile, + ctx, ses, bh, tblStuff, deletesBuf, true, deleteByFullRow, pkInfo, writeFile, ); err != nil { return err } @@ -997,7 +1000,7 @@ func tryFlushDeletesOrInserts( flushInserts := func() error { if err = flushSqlValues( - ctx, ses, bh, tblStuff, insertBuf, false, false, writeFile, + ctx, ses, bh, tblStuff, insertBuf, false, false, pkInfo, writeFile, ); err != nil { return err } @@ -1043,12 +1046,130 @@ func tryFlushDeletesOrInserts( return nil } +type pkBatchInfo struct { + dbName string + baseTable string + deleteTable string + insertTable string + pkNames []string + visibleNames []string +} + +func newPKBatchInfo(ctx context.Context, ses *Session, tblStuff tableStuff) *pkBatchInfo { + if tblStuff.def.pkKind == fakeKind { + return nil + } + + pkNames := make([]string, len(tblStuff.def.pkColIdxes)) + for i, idx := range tblStuff.def.pkColIdxes { + pkNames[i] = tblStuff.def.colNames[idx] + } + + visibleNames := make([]string, len(tblStuff.def.visibleIdxes)) + for i, idx := range tblStuff.def.visibleIdxes { + visibleNames[i] = tblStuff.def.colNames[idx] + } + + seq := atomic.AddUint64(&diffTempTableSeq, 1) + sessionTag := strings.ReplaceAll(ses.GetUUIDString(), "-", "") + return &pkBatchInfo{ + dbName: tblStuff.baseRel.GetTableDef(ctx).DbName, + baseTable: tblStuff.baseRel.GetTableName(), + deleteTable: fmt.Sprintf("__mo_diff_del_%s_%d", sessionTag, seq), + insertTable: fmt.Sprintf("__mo_diff_ins_%s_%d", sessionTag, seq), + pkNames: pkNames, + visibleNames: visibleNames, + } +} + +func qualifiedTableName(dbName, tableName string) string { + return fmt.Sprintf("%s.%s", dbName, tableName) +} + +func execSQLStatements( + ctx context.Context, + ses *Session, + bh BackgroundExec, + writeFile func([]byte) error, + stmts []string, +) error { + for _, stmt := range stmts { + if stmt == "" { + continue + } + if writeFile != nil { + if err := writeFile([]byte(stmt + ";\n")); err != nil { + return err + } + continue + } + ret, err := runSql(ctx, ses, bh, stmt, nil, nil) + if len(ret.Batches) > 0 && ret.Mp != nil { + ret.Close() + } + if err != nil { + return err + } + } + return nil +} + +func initPKTables( + ctx context.Context, + ses *Session, + bh BackgroundExec, + pkInfo *pkBatchInfo, + writeFile func([]byte) error, +) error { + if pkInfo == nil { + return nil + } + + baseTable := qualifiedTableName(pkInfo.dbName, pkInfo.baseTable) + deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) + insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) + + deleteCols := strings.Join(pkInfo.pkNames, ",") + insertCols := strings.Join(pkInfo.visibleNames, ",") + + stmts := []string{ + fmt.Sprintf("drop table if exists %s", deleteTable), + fmt.Sprintf("drop table if exists %s", insertTable), + fmt.Sprintf("create table %s as select %s from %s where 1=0", deleteTable, deleteCols, baseTable), + fmt.Sprintf("create table %s as select %s from %s where 1=0", insertTable, insertCols, baseTable), + } + + return execSQLStatements(ctx, ses, bh, writeFile, stmts) +} + +func dropPKTables( + ctx context.Context, + ses *Session, + bh BackgroundExec, + pkInfo *pkBatchInfo, + writeFile func([]byte) error, +) error { + if pkInfo == nil { + return nil + } + + deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) + insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) + + stmts := []string{ + fmt.Sprintf("drop table if exists %s", deleteTable), + fmt.Sprintf("drop table if exists %s", insertTable), + } + return execSQLStatements(ctx, ses, bh, writeFile, stmts) +} + type sqlValuesAppender struct { ctx context.Context ses *Session bh BackgroundExec tblStuff tableStuff deleteByFullRow bool + pkInfo *pkBatchInfo deleteCnt *int deleteBuf *bytes.Buffer insertCnt *int @@ -1069,7 +1190,7 @@ func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { newValsLen := len(rowValues) if err := tryFlushDeletesOrInserts( sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, - sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, ); err != nil { return err } @@ -1090,7 +1211,7 @@ func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { if err := tryFlushDeletesOrInserts( sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, - sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, ); err != nil { return err } @@ -1106,7 +1227,7 @@ func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { func (sva sqlValuesAppender) flushAll() error { return tryFlushDeletesOrInserts( sva.ctx, sva.ses, sva.bh, sva.tblStuff, "", - 0, 0, sva.deleteByFullRow, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + 0, 0, sva.deleteByFullRow, sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, ) } @@ -1154,6 +1275,25 @@ func writeDeleteRowValues( return nil } +func writeDeleteRowValuesAsTuple( + ses *Session, + tblStuff tableStuff, + row []any, + buf *bytes.Buffer, +) error { + buf.WriteString("(") + for i, colIdx := range tblStuff.def.pkColIdxes { + if err := formatValIntoString(ses, row[colIdx], tblStuff.def.colTypes[colIdx], buf); err != nil { + return err + } + if i != len(tblStuff.def.pkColIdxes)-1 { + buf.WriteString(",") + } + } + buf.WriteString(")") + return nil +} + func writeDeleteRowSQLFull( ctx context.Context, ses *Session, @@ -1256,6 +1396,10 @@ func appendBatchRowsAsSQLValues( if err = writeDeleteRowSQLFull(ctx, ses, tblStuff, row, tmpValsBuffer); err != nil { return } + } else if appender.pkInfo != nil { + if err = writeDeleteRowValuesAsTuple(ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } } else { if err = writeDeleteRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { return @@ -1316,11 +1460,20 @@ func mergeDiffs( bh: bh, tblStuff: tblStuff, deleteByFullRow: tblStuff.def.pkKind == fakeKind, + pkInfo: newPKBatchInfo(ctx, ses, tblStuff), deleteCnt: &deleteCnt, deleteBuf: deleteFromVals, insertCnt: &insertCnt, insertBuf: insertIntoVals, } + if err = initPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { + return err + } + defer func() { + if err2 := dropPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err2 != nil && err == nil { + err = err2 + } + }() // conflict option should be pushed down to the hash phase, // so the batch we received is conflict-free. @@ -1505,6 +1658,7 @@ func satisfyDiffOutputOpt( bh: bh, tblStuff: tblStuff, deleteByFullRow: tblStuff.def.pkKind == fakeKind, + pkInfo: newPKBatchInfo(ctx, ses, tblStuff), deleteCnt: &deleteCnt, deleteBuf: deleteFromValsBuffer, insertCnt: &insertCnt, @@ -1517,6 +1671,9 @@ func satisfyDiffOutputOpt( return } } + if err = initPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { + return + } for wrapped := range retCh { if first != nil { @@ -1566,6 +1723,11 @@ func satisfyDiffOutputOpt( first = err cancel() } + if first == nil { + if err = dropPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { + return err + } + } if first == nil && writeFile != nil { if err = writeFile([]byte("COMMIT;\n")); err != nil { return err @@ -1972,6 +2134,7 @@ func flushSqlValues( buf *bytes.Buffer, isDeleteFrom bool, deleteByFullRow bool, + pkInfo *pkBatchInfo, writeFile func([]byte) error, ) (err error) { @@ -2000,6 +2163,35 @@ func flushSqlValues( return nil } + if pkInfo != nil { + baseTable := qualifiedTableName(pkInfo.dbName, pkInfo.baseTable) + deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) + insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) + + if isDeleteFrom { + insertStmt := fmt.Sprintf("insert into %s values %s", deleteTable, buf.String()) + pkExpr := pkInfo.pkNames[0] + if len(pkInfo.pkNames) > 1 { + pkExpr = fmt.Sprintf("(%s)", strings.Join(pkInfo.pkNames, ",")) + } + deleteStmt := fmt.Sprintf( + "delete from %s where %s in (select %s from %s)", + baseTable, pkExpr, strings.Join(pkInfo.pkNames, ","), deleteTable, + ) + clearStmt := fmt.Sprintf("delete from %s", deleteTable) + return execSQLStatements(ctx, ses, bh, writeFile, []string{insertStmt, deleteStmt, clearStmt}) + } + + insertStmt := fmt.Sprintf("insert into %s values %s", insertTable, buf.String()) + cols := strings.Join(pkInfo.visibleNames, ",") + applyStmt := fmt.Sprintf( + "insert into %s (%s) select %s from %s", + baseTable, cols, cols, insertTable, + ) + clearStmt := fmt.Sprintf("delete from %s", insertTable) + return execSQLStatements(ctx, ses, bh, writeFile, []string{insertStmt, applyStmt, clearStmt}) + } + sqlBuffer := acquireBuffer(tblStuff.bufPool) defer releaseBuffer(tblStuff.bufPool, sqlBuffer) @@ -2146,8 +2338,8 @@ func tryDiffAsCSV( tblStuff.baseRel.GetTableDef(ctx).Name, ) - if tblStuff.baseSnap != nil { - sql += fmt.Sprintf("{snapshot='%s'}", tblStuff.baseSnap.ExtraInfo.Name) + if tblStuff.baseSnap != nil && tblStuff.baseSnap.TS != nil { + sql += fmt.Sprintf("{mo_ts=%d}", tblStuff.baseSnap.TS.PhysicalTime) } var ( @@ -4948,6 +5140,14 @@ func compareSingleValInVector( rowIdx2 = 0 } + // Treat NULL as equal only when both sides are NULL. + if vec1.IsNull(uint64(rowIdx1)) || vec2.IsNull(uint64(rowIdx2)) { + if vec1.IsNull(uint64(rowIdx1)) && vec2.IsNull(uint64(rowIdx2)) { + return 0, nil + } + return 1, nil + } + // Use raw values to avoid format conversions in extractRowFromVector. switch vec1.GetType().Oid { case types.T_json: diff --git a/pkg/frontend/stmt_kind.go b/pkg/frontend/stmt_kind.go index 0a40c79eb7167..1d485330575c7 100644 --- a/pkg/frontend/stmt_kind.go +++ b/pkg/frontend/stmt_kind.go @@ -140,6 +140,9 @@ func statementCanBeExecutedInUncommittedTransaction( case *tree.CreateTable, *tree.CreateIndex, *tree.CreateView, *tree.AlterView, *tree.AlterTable: // CTAS is allowed in explicit transactions now because its internal // INSERT ... SELECT is executed in the same txn as CREATE TABLE. + //if createTblStmt, ok := stmt.(*tree.CreateTable); ok && createTblStmt.IsAsSelect { + // return false, nil + //} return true, nil case *tree.CreateDatabase, *tree.DropDatabase: return true, nil diff --git a/test/distributed/cases/git4data/branch/diff/diff_7.sql b/test/distributed/cases/git4data/branch/diff/diff_7.sql index f1c863176654b..eac93168628c0 100644 --- a/test/distributed/cases/git4data/branch/diff/diff_7.sql +++ b/test/distributed/cases/git4data/branch/diff/diff_7.sql @@ -23,6 +23,7 @@ update t1 set b=4 where a = 1; data branch diff t1 against t1{snapshot="sp"}; -- case 1.2 +-- @ignore:0 select mo_ctl("dn", "flush", "test.t1"); delete from t1 where a = 1; @@ -50,6 +51,7 @@ update t1 set b=4 where a = 1; -- case 2.1 data branch diff t1 against t1{snapshot="sp"}; +-- @ignore:0 select mo_ctl("dn", "flush", "test.t1"); delete from t1 where a = 1; From 161b59378a07a10b11338165011a7962a8ed71e6 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 29 Jan 2026 18:55:03 +0800 Subject: [PATCH 05/23] refactor branch hashmap --- pkg/frontend/data_branch.go | 361 ++-- .../BRANCH_HASHMAP_REDESIGN.md | 316 +++ .../databranchutils/branch_hashmap.go | 1702 +++++++++++++---- .../databranchutils/branch_hashmap_test.go | 43 +- 4 files changed, 1873 insertions(+), 549 deletions(-) create mode 100644 pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 4fdd8543a386c..4e5258a191462 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -35,6 +35,7 @@ import ( "time" "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/malloc" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" @@ -70,6 +71,71 @@ const ( diffUpdate = "UPDATE" ) +const branchHashmapMemoryLimit = 500 * 200 * mpool.MB + +type branchHashmapAllocator struct { + upstream malloc.Allocator + max uint64 + inUse atomic.Uint64 +} + +type branchHashmapDeallocator struct { + upstream malloc.Deallocator + inUse *atomic.Uint64 + size uint64 +} + +func newBranchHashmapAllocator(max uint64) *branchHashmapAllocator { + return &branchHashmapAllocator{ + upstream: malloc.GetDefault(nil), + max: max, + } +} + +func (a *branchHashmapAllocator) Allocate(size uint64, hints malloc.Hints) ([]byte, malloc.Deallocator, error) { + for { + cur := a.inUse.Load() + next := cur + size + if next > a.max { + // Treat limit as a spill signal, not an error. + return nil, nil, nil + } + if !a.inUse.CompareAndSwap(cur, next) { + continue + } + buf, dec, err := a.upstream.Allocate(size, hints) + if err != nil { + a.inUse.Add(^uint64(size - 1)) + return nil, nil, err + } + if buf == nil { + a.inUse.Add(^uint64(size - 1)) + return nil, nil, nil + } + return buf, &branchHashmapDeallocator{ + upstream: dec, + inUse: &a.inUse, + size: size, + }, nil + } +} + +func (d *branchHashmapDeallocator) Deallocate() { + if d.upstream != nil { + d.upstream.Deallocate() + } + if d.size > 0 && d.inUse != nil { + d.inUse.Add(^uint64(d.size - 1)) + } +} + +func (d *branchHashmapDeallocator) As(target malloc.Trait) bool { + if d.upstream != nil { + return d.upstream.As(target) + } + return false +} + var diffTempTableSeq uint64 const ( @@ -3325,7 +3391,7 @@ func hashDiffIfNoLCA( ) (err error) { if err = tarTombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(key []byte, _ []byte) error { _, err2 := tarDataHashmap.PopByEncodedKey(key, true) return err2 }) @@ -3335,7 +3401,7 @@ func hashDiffIfNoLCA( } if err = baseTombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(key []byte, _ []byte) error { _, err2 := baseDataHashmap.PopByEncodedKey(key, true) return err2 }) @@ -3415,24 +3481,21 @@ func findDeleteAndUpdateBat( } } - if err2 = cursor.ForEach(func(key []byte, rows [][]byte) error { - for range rows { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - if tuple, _, err2 = tombstoneHashmap.DecodeRow(key); err2 != nil { - return err2 - } else { - if err2 = vector.AppendAny(tBat1.Vecs[0], tuple[0], false, ses.proc.Mp()); err2 != nil { - return err2 - } + if err2 = cursor.ForEach(func(key []byte, _ []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } - tBat1.SetRowCount(tBat1.Vecs[0].Length()) - } + if tuple, _, err2 = tombstoneHashmap.DecodeRow(key); err2 != nil { + return err2 } + if err2 = vector.AppendAny(tBat1.Vecs[0], tuple[0], false, ses.proc.Mp()); err2 != nil { + return err2 + } + + tBat1.SetRowCount(tBat1.Vecs[0].Length()) return nil }); err2 != nil { return err2 @@ -3655,83 +3718,81 @@ func diffDataHelper( tarBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) baseBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - if err2 = cursor.ForEach(func(key []byte, rows [][]byte) error { + if err2 = cursor.ForEach(func(key []byte, row []byte) error { select { case <-ctx.Done(): return ctx.Err() default: } - for _, row := range rows { - if tblStuff.def.pkKind == fakeKind { - if checkRet, err2 = baseDataHashmap.PopByEncodedFullValue(row, false); err2 != nil { - return err2 - } - } else { - if checkRet, err2 = baseDataHashmap.PopByEncodedKey(key, false); err2 != nil { - return err2 - } + if tblStuff.def.pkKind == fakeKind { + if checkRet, err2 = baseDataHashmap.PopByEncodedFullValue(row, false); err2 != nil { + return err2 + } + } else { + if checkRet, err2 = baseDataHashmap.PopByEncodedKey(key, false); err2 != nil { + return err2 } + } - if !checkRet.Exists { + if !checkRet.Exists { + if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { + return err2 + } + + if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + return err2 + } + + } else { + // both has the key, we continue compare the left columns, + // if all columns are equal, exactly the same row, ignore. + if tblStuff.def.pkKind == fakeKind { + // all columns already compared. + // ignore + } else { if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { return err2 } - if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + if baseTuple, _, err2 = baseDataHashmap.DecodeRow(checkRet.Rows[0]); err2 != nil { return err2 } - } else { - // both has the key, we continue compare the left columns, - // if all columns are equal, exactly the same row, ignore. - if tblStuff.def.pkKind == fakeKind { - // all columns already compared. - // ignore - } else { - if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { - return err2 + notSame := false + for _, idx := range tblStuff.def.visibleIdxes { + if slices.Index(tblStuff.def.pkColIdxes, idx) != -1 { + // pk columns already compared + continue } - if baseTuple, _, err2 = baseDataHashmap.DecodeRow(checkRet.Rows[0]); err2 != nil { - return err2 + if types.CompareValue( + tarTuple[idx], baseTuple[idx], + ) != 0 { + notSame = true + break } + } - notSame := false - for _, idx := range tblStuff.def.visibleIdxes { - if slices.Index(tblStuff.def.pkColIdxes, idx) != -1 { - // pk columns already compared - continue + if notSame { + if copt.conflictOpt != nil && + copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT && + copt.expandUpdate { + if baseDeleteBat == nil { + baseDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) } - - if types.CompareValue( - tarTuple[idx], baseTuple[idx], - ) != 0 { - notSame = true - break + if err2 = appendTupleToBat(ses, baseDeleteBat, baseTuple, tblStuff); err2 != nil { + return err2 } - } - - if notSame { - if copt.conflictOpt != nil && - copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT && - copt.expandUpdate { - if baseDeleteBat == nil { - baseDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - } - if err2 = appendTupleToBat(ses, baseDeleteBat, baseTuple, tblStuff); err2 != nil { - return err2 - } - if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { - return err2 - } - } else { - // conflict happened - if err2 = checkConflictAndAppendToBat( - ses, copt, tblStuff, tarBat, baseBat, tarTuple, baseTuple, - ); err2 != nil { - return err2 - } + if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + return err2 + } + } else { + // conflict happened + if err2 = checkConflictAndAppendToBat( + ses, copt, tblStuff, tarBat, baseBat, tarTuple, baseTuple, + ); err2 != nil { + return err2 } } } @@ -3801,21 +3862,19 @@ func diffDataHelper( bat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - if err2 = cursor.ForEach(func(key []byte, rows [][]byte) error { + if err2 = cursor.ForEach(func(_ []byte, row []byte) error { select { case <-ctx.Done(): return ctx.Err() default: } - for _, row := range rows { - if tuple, _, err2 = baseDataHashmap.DecodeRow(row); err2 != nil { - return err2 - } + if tuple, _, err2 = baseDataHashmap.DecodeRow(row); err2 != nil { + return err2 + } - if err2 = appendTupleToBat(ses, bat, tuple, tblStuff); err2 != nil { - return err2 - } + if err2 = appendTupleToBat(ses, bat, tuple, tblStuff); err2 != nil { + return err2 } return nil }); err2 != nil { @@ -4294,11 +4353,17 @@ func buildHashmapForTable( } }() - if dataHashmap, err = databranchutils.NewBranchHashmap(); err != nil { + // Share one bounded allocator so both hashmaps spill instead of erroring. + sharedAllocator := newBranchHashmapAllocator(branchHashmapMemoryLimit) + if dataHashmap, err = databranchutils.NewBranchHashmap( + databranchutils.WithBranchHashmapAllocator(sharedAllocator), + ); err != nil { return } - if tombstoneHashmap, err = databranchutils.NewBranchHashmap(); err != nil { + if tombstoneHashmap, err = databranchutils.NewBranchHashmap( + databranchutils.WithBranchHashmapAllocator(sharedAllocator), + ); err != nil { return } @@ -4306,28 +4371,39 @@ func buildHashmapForTable( if bat == nil { return nil } + select { + case <-ctx.Done(): + bat.Clean(mp) + return ctx.Err() + default: + } wg.Add(1) if err = tblStuff.worker.Submit(func() { defer wg.Done() + defer bat.Clean(mp) ll := bat.VectorCount() var taskErr error - if isTombstone { - // keep the commit ts - taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll], []int{0}) - } else { - // keep the commit ts - taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll], []int{tblStuff.def.pkColIdx}) + select { + case <-ctx.Done(): + taskErr = ctx.Err() + default: + if isTombstone { + // keep the commit ts + taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll], []int{0}) + } else { + // keep the commit ts + taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll], []int{tblStuff.def.pkColIdx}) + } } - - bat.Clean(mp) if taskErr != nil { atomicErr.Store(taskErr) } }); err != nil { wg.Done() + bat.Clean(mp) } return err @@ -4335,6 +4411,12 @@ func buildHashmapForTable( for _, handle := range handles { for { + select { + case <-ctx.Done(): + err = ctx.Err() + return + default: + } if dataBat, tombstoneBat, _, err = handle.Next( ctx, mp, ); err != nil { @@ -4363,6 +4445,12 @@ func buildHashmapForTable( if atomicErr.Load() != nil { err = atomicErr.Load().(error) + } else { + select { + case <-ctx.Done(): + err = ctx.Err() + default: + } } if err != nil { @@ -4408,53 +4496,64 @@ func buildHashmapForTable( tuple types.Tuple dataRet databranchutils.GetResult ) - if err2 = cursor.ForEach(func(key []byte, rows [][]byte) error { - if len(rows) > 1 { - //tsMap := make(map[types.TS]struct{}) - maxIdx = 0 - maxTs = types.MinTs() - for i := 0; i < len(rows); i++ { - if tuple, _, err3 = tombstoneHashmap.DecodeRow(rows[i]); err3 != nil { - return err3 - } - cur := types.TS(tuple[len(tuple)-1].([]uint8)) - if cur.GT(&maxTs) { - maxTs = cur - maxIdx = i - } - //tsMap[cur] = struct{}{} + if err2 = cursor.ForEach(func(key []byte, _ []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + var tombstoneRet databranchutils.GetResult + if tombstoneRet, err3 = cursor.GetByEncodedKey(key); err3 != nil { + return err3 + } + if len(tombstoneRet.Rows) <= 1 { + return nil + } + + //tsMap := make(map[types.TS]struct{}) + maxIdx = 0 + maxTs = types.MinTs() + for i := 0; i < len(tombstoneRet.Rows); i++ { + if tuple, _, err3 = tombstoneHashmap.DecodeRow(tombstoneRet.Rows[i]); err3 != nil { + return err3 + } + cur := types.TS(tuple[len(tuple)-1].([]uint8)) + if cur.GT(&maxTs) { + maxTs = cur + maxIdx = i } - //delete(tsMap, maxTs) + //tsMap[cur] = struct{}{} + } + //delete(tsMap, maxTs) - for i := range rows { - if i != maxIdx { - if _, err3 = cursor.PopByEncodedKeyValue( - key, rows[i], false, - ); err3 != nil { - return err3 - } + for i := range tombstoneRet.Rows { + if i != maxIdx { + if _, err3 = cursor.PopByEncodedKeyValue( + key, tombstoneRet.Rows[i], false, + ); err3 != nil { + return err3 } } + } - if dataRet, err3 = dataHashmap.GetByEncodedKey(key); err3 != nil { - return err3 - } + if dataRet, err3 = dataHashmap.GetByEncodedKey(key); err3 != nil { + return err3 + } - if dataRet.Exists { - for i := range dataRet.Rows { - if tuple, _, err3 = dataHashmap.DecodeRow(dataRet.Rows[i]); err3 != nil { + if dataRet.Exists { + for i := range dataRet.Rows { + if tuple, _, err3 = dataHashmap.DecodeRow(dataRet.Rows[i]); err3 != nil { + return err3 + } + cur := types.TS(tuple[len(tuple)-1].([]uint8)) + // cannot use tsMap to filter, why? + // cannot use cur != maxTS to filter, why? + if cur.LT(&maxTs) { + if _, err3 = dataHashmap.PopByEncodedKeyValue( + key, dataRet.Rows[i], false, + ); err3 != nil { return err3 } - cur := types.TS(tuple[len(tuple)-1].([]uint8)) - // cannot use tsMap to filter, why? - // cannot use cur != maxTS to filter, why? - if cur.LT(&maxTs) { - if _, err3 = dataHashmap.PopByEncodedKeyValue( - key, dataRet.Rows[i], false, - ); err3 != nil { - return err3 - } - } } } } diff --git a/pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md b/pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md new file mode 100644 index 0000000000000..1dbe662f9c780 --- /dev/null +++ b/pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md @@ -0,0 +1,316 @@ +# Branch Hashmap Redesign (Bucketized Spill, Streamed Iteration) + +## Layered Structure (At a Glance) + +``` +BranchHashmap + ├─ Shards[] (N shards) + │ ├─ InMemoryStore + │ │ ├─ HashIndex (open addressing) + │ │ ├─ EntryMeta[] (flat array) + │ │ └─ EntryArena (allocator-managed byte blocks) + │ ├─ SpillStore (bucketized on disk) + │ │ ├─ BucketFiles[B] + │ │ ├─ BucketRowCount[B] + │ │ └─ TombstoneBitmap[B] (lazy) + │ └─ BucketCache (optional, per-shard LRU) + ├─ Global config (spill, cache, shard count) + └─ Pools (packers, temp buffers) +``` + +--- + +## 1. Goals and Constraints + +### 1.1 Goals +- **I/O friendly spill**: sequential disk I/O instead of random `ReadAt` during traversal or batch operations. +- **Memory/GC friendly**: reduce per-entry pointer structures and demonstrating predictable heap usage. +- **Batch/diff optimized**: primary use is bulk comparison/diff; design should favor streaming and bucket locality. +- **Stable mapping**: once spilled, data is never re-hashed or rewritten, ensuring deterministic bucket mapping. +- **Interface compatibility**: keep `BranchHashmap` public interface unchanged; `ForEach` semantics may be revised. + +### 1.2 Constraints / Assumptions +- BranchHashmap is **write-once-ish**: after build, no full rebuild or rehash is required. +- Primary keys are often unique, but duplicates must still be supported. +- ForEach is mainly used by `data_branch` diff logic and can tolerate changes in grouping semantics. +- Spill is **append-only**; no in-place updates. +- Spill reads can be sequential; occasional random point lookups are acceptable but not the dominant path. + +### 1.3 Non-goals +- Full general-purpose OLTP index performance. +- Perfect efficiency for single-key random access when spill is large. +- Immediate compaction or tombstone reclamation (can be added later). + +--- + +## 2. Core Concepts and Terminology + +- **Shard**: independent unit with its own lock, memory store, spill store, cache, and counters. +- **Bucket**: fixed partition of spill files within a shard (`bucket = hash & (B-1)`), **not** the same as in-memory hash buckets. +- **Entry**: a single row (key + full value payload). +- **Rid**: record id in a bucket file (0-based, append order). +- **Tombstone**: deletion marker for spilled rows, stored as bitmap indexed by rid. + +--- + +## 3. Data Structures + +### 3.1 InMemoryStore + +**Goal**: compact and GC-friendly storage while preserving O(1) lookup. + +``` +EntryMeta { + hash uint64 + keyOff uint32/uint64 + keyLen uint32 + valOff uint32/uint64 + valLen uint32 +} + +HashIndex: open addressing array of int32 indexes +EntryArena: large allocator blocks holding concatenated key/value bytes +``` + +**Design choices** +- Open addressing avoids `map` overhead. +- EntryMeta is a flat array to minimize pointer chasing. +- Allocator blocks reduce GC pressure. + +### 3.2 SpillStore + +**Goal**: sequential I/O, predictable file count, minimal in-memory index. + +``` +BucketFiles[B] +BucketRowCount[B] +TombstoneBitmap[B] (optional, created on first delete) +``` + +**File format** (append-only): +``` +[hash(uint64)][keyLen(uint32)][valLen(uint32)][key bytes][value bytes] +``` + +### 3.3 BucketCache (optional) + +**Goal**: reduce repeated sequential scans for hot buckets. + +- Per-shard LRU cache. +- Stores `key -> rid` and optionally `rid -> value`. +- Bounded by configurable memory budget. + +--- + +## 4. State Model and Transitions + +### 4.1 High-level States +- **EMPTY**: shard has no entries. +- **IN_MEMORY**: entries stored in InMemoryStore only. +- **SPILLING**: InMemoryStore evicts entries into SpillStore. +- **SPILLED**: bucket files exist; tombstones may exist. + +### 4.2 State Transitions +1) `EMPTY -> IN_MEMORY`: PutByVectors inserts first entry. +2) `IN_MEMORY -> SPILLING`: allocator pressure triggers spill. +3) `SPILLING -> SPILLED`: spill completes; entries removed from memory. +4) `SPILLED -> SPILLING`: additional spill from memory to disk. +5) `* -> CLOSED`: Close releases memory, closes files, deletes spill dirs. + +--- + +## 5. Algorithms (Detailed) + +### 5.1 PutByVectors +**Input**: vectors + keyCols + +**Steps**: +1) Encode key/value for each row into batch. +2) Allocate one block for batch payloads. +3) Create EntryMeta and insert into shard InMemoryStore. +4) If allocator fails, invoke `spill(required)`. + +**Notes**: +- No spill rehashing; entries are moved to bucket files by hash. + +### 5.2 spill(required) +**Goal**: free `required` bytes from InMemoryStore. + +**Steps**: +1) For each shard, evict entries in LRU order. +2) For each entry: + - compute bucket: `hash & (B-1)` + - append to bucket file (sequential) + - increment BucketRowCount[bucket] +3) Remove entry from InMemoryStore. + +**Logging**: +- log required, freed, pointers/entries, avg entry size. + +### 5.3 ForEach (new semantics) +**Goal**: streaming iteration, low memory, bucket-local I/O. + +**Semantic change**: +- Previously: `fn(key, rows)` grouped by key. +- Now: `fn(key, rows)` is called **per entry** with `len(rows)==1`. + +**Order**: +1) **In-memory first**: iterate EntryMeta array; call fn with in-memory slices. +2) **Spill next**: for each bucket file in order: + - sequentially scan file + - maintain rid counter + - skip if tombstone bit is set + - call fn per entry + +**Copy policy**: +- In-memory: zero-copy slices into arena. +- Spill: one copy into scratch buffer; valid only during callback. + +### 5.4 GetByVectors / PopByVectors +**Goal**: batch-friendly, bucket-local access. + +**Steps**: +1) Encode keys. +2) Group keys by bucket (hash & (B-1)). +3) For each bucket: + - if bucket cached, use cache for lookups + - else sequentially scan bucket file, building temporary map + - for Pop: set tombstone bit for matching rid +4) Return results in input order. + +### 5.5 PopByEncodedKey / PopByEncodedKeyValue +**Goal**: correctness with acceptable cost. + +**Steps**: +1) Compute bucket by hash. +2) If bucket cached, lookup rid, set tombstone. +3) Otherwise, sequentially scan bucket file to find key/value. + +**Note**: This is slower than current index-based random access but fits diff/batch use. + +--- + +## 6. Tombstone Strategy + +**Why tombstone**: no file rewrite; stable rid. + +- **Structure**: per-bucket bitmap (`rid -> deleted?`). +- **Lazy allocation**: only allocate when first delete happens. +- **Memory**: 1 bit per record; 1e8 deletions ≈ 12.5MB total (plus metadata). + +**Optional**: Trigger compaction when tombstone ratio exceeds threshold. + +--- + +## 7. Concurrency Model + +- Shard lock serializes shard operations. +- ForEach requires shard lock; Pop during iteration must be called via ShardCursor. +- Parallelism comes from `ForEachShardParallel`. +- Cache is per-shard to avoid cross-shard contention and pollution. + +--- + +## 8. Failure and Recovery Behavior + +- Spill files are created under shard-specific spillDir. +- On error during spill, shard stays consistent; entries remain in memory if spill fails. +- On Close: close files, delete spillDir. +- No crash recovery required (spill files are temp). + +--- + +## 9. Configuration + +| Parameter | Description | Default | +|---|---|---| +| `shardCount` | number of shards | `clamp(runtime.NumCPU()*4,4,128)` | +| `bucketCount` | spill buckets per shard (power of 2) | 128 or 256 | +| `spillPartitionMaxBytes` | max bucket file size (optional) | 128MB | +| `cacheBytesPerShard` | bucket cache budget | 64MB | +| `spillMinReleaseBytes` | minimum spill size | 1MB | + +--- + +## 10. Large-Scale Considerations (10TB+) + +To support tens of TB scale, the baseline design must add **segmented bucket files** and use **64-bit offsets** end-to-end. Without these, bucket files become too large, offsets overflow, and tombstone bitmaps balloon uncontrollably. + +### 10.1 Bucket Segmentation +- Each bucket is split into **fixed-size segments** (e.g. 1–4GB). +- Spill appends to the current segment; when full, rotates to the next. +- Maintain `BucketSegments[bucket] -> []SegmentMeta` including: + - `path` + - `rowCount` + - `byteSize` + - `minRid` / `maxRid` + +### 10.2 64-bit Offsets and RIDs +- Use `uint64` for all offsets and record counters. +- Record id becomes `rid = segmentBaseRid + localRid`. +- Hash index remains 32-bit if entry count < 2^31; otherwise, upgrade to 64-bit indexes. + +### 10.3 Tombstone Scaling +- Tombstones are **per-segment bitmaps**, not per-bucket monolithic bitmaps. +- This enables: + - small, cache-friendly bitmaps + - partial cleanup or compaction per segment +- With 10B rows fully deleted, bitmap memory remains in the low GB range and can be partitioned per segment. + +### 10.4 Cache Boundaries +- Strict per-shard cache limits (e.g. 64–128MB/shard). +- Eviction should drop segment caches cleanly to avoid page cache thrash. + +### 10.5 File Descriptor Strategy +- Never keep all bucket/segment files open. +- Maintain a per-shard FD LRU (1–4 active segment files). + +### 10.6 Suggested Defaults for 10TB +- `shardCount`: 64–128 +- `bucketCount`: 512–1024 +- `segmentSize`: 1GB +- `cacheBytesPerShard`: 64–128MB +- `spillMinReleaseBytes`: 8–64MB + +--- + +## 11. Behavioral Differences vs Current Implementation + +- ForEach is **streaming per entry** (no grouped rows). +- Spill uses **bucket files** rather than per-entry index. +- Random Get/Pop on spilled data is slower; batch operations are faster. +- Tombstones replace delete-in-file. + +--- + +## 12. Testing Strategy + +- **Correctness**: Put/Get/Pop with unique and duplicate keys. +- **Streaming**: ForEach returns all rows; order not guaranteed but count is. +- **Spill**: data survives spill; tombstone hides deleted rows. +- **Batch**: GetByVectors with mixed buckets. +- **Cache**: repeated gets hit cache; cache evictions do not corrupt data. +- **Concurrency**: ForEachShardParallel with mixed Pop calls. + +--- + +## 13. Implementation Checklist + +1) Add bucket spill store structures. +2) Update spill path to write bucket files sequentially. +3) Implement tombstone bitmap per bucket. +4) Update ForEach to stream entries (in-memory then spill buckets). +5) Update Get/Pop to bucket-grouped access. +6) Update tests for new ForEach semantics. +7) Update design docs and comments. + +--- + +## 14. Rationale Summary + +- **Bucketized spill** enables sequential I/O and avoids giant per-entry indexes. +- **Streaming ForEach** avoids full-map grouping and reduces memory spikes. +- **Tombstone bitmap** provides low-memory deletion marking for spilled rows. +- **Per-shard cache** prevents cross-shard cache pollution under concurrency. + +This design optimizes for the dominant workload (bulk diff) while maintaining correctness and concurrency safety. Even with changed ForEach semantics, the interface surface remains compatible and existing callers can be updated with minimal logic changes. diff --git a/pkg/frontend/databranchutils/branch_hashmap.go b/pkg/frontend/databranchutils/branch_hashmap.go index 48ac372970b1a..34edcddfc1757 100644 --- a/pkg/frontend/databranchutils/branch_hashmap.go +++ b/pkg/frontend/databranchutils/branch_hashmap.go @@ -15,13 +15,15 @@ package databranchutils import ( + "bufio" "bytes" - "container/list" "encoding/binary" "fmt" "io" "os" + "path/filepath" "runtime" + "strings" "sync" "sync/atomic" @@ -31,6 +33,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/container/hashtable" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/logutil" "github.com/panjf2000/ants/v2" ) @@ -94,9 +97,13 @@ type ShardCursor interface { // ShardID returns the zero-based shard identifier. ShardID() int // ForEach visits every encoded key stored inside the shard, including rows - // that have spilled to disk. The provided rows slices reference internal - // buffers and are therefore read-only and only valid inside the callback. - ForEach(fn func(key []byte, rows [][]byte) error) error + // that have spilled to disk. The callback is invoked per entry with a single + // payload row. The provided slices reference internal buffers (or scratch + // copies for spilled data) and are only valid inside the callback. + ForEach(fn func(key []byte, row []byte) error) error + // GetByEncodedKey retrieves rows using a pre-encoded key while the caller + // still owns the iteration lock. + GetByEncodedKey(encodedKey []byte) (GetResult, error) // PopByEncodedKey removes entries from the shard while the caller still owns // the iteration lock, ensuring In-shard mutations stay non-blocking. PopByEncodedKey(encodedKey []byte, removeAll bool) (GetResult, error) @@ -115,11 +122,30 @@ type GetResult struct { Rows [][]byte } +type keyProbe struct { + idx int + key []byte + keyStr string + hash uint64 + plan *removalPlan +} + +type probeGroup struct { + indices []int + plans []*removalPlan + next int + values [][]byte +} + const ( - branchHashSeed = 0x9e3779b97f4a7c15 - minShardCount = 4 - maxShardCount = 128 - putBatchSize = 8192 + branchHashSeed = 0x9e3779b97f4a7c15 + minShardCount = 4 + maxShardCount = 128 + putBatchSize = 8192 + defaultMemIndexSize = 1024 + defaultSpillBucketCount = 1024 + defaultSpillSegmentMaxSize = 128 * mpool.MB + spillEntryHeaderSize = 16 ) // branchHashmap is an adaptive hash map that accepts vector columns and @@ -134,6 +160,10 @@ type branchHashmap struct { keyCols []int spillRoot string + // spillBucketCount must be a power of two. + spillBucketCount uint32 + // spillSegmentMaxBytes controls the maximum size of a spill file segment. + spillSegmentMaxBytes uint64 packerPool sync.Pool entryBatchPool sync.Pool @@ -161,6 +191,25 @@ func WithBranchHashmapSpillRoot(root string) BranchHashmapOption { } } +// WithBranchHashmapSpillBucketCount sets the number of spill buckets per shard. +// The value is rounded up to the next power of two. +func WithBranchHashmapSpillBucketCount(bucketCount int) BranchHashmapOption { + return func(bh *branchHashmap) { + if bucketCount > 0 { + bh.spillBucketCount = uint32(bucketCount) + } + } +} + +// WithBranchHashmapSpillSegmentMaxBytes caps the size of each spill file segment. +func WithBranchHashmapSpillSegmentMaxBytes(maxBytes uint64) BranchHashmapOption { + return func(bh *branchHashmap) { + if maxBytes > 0 { + bh.spillSegmentMaxBytes = maxBytes + } + } +} + // WithBranchHashmapShardCount sets the shard count. Values outside [4, 64] are clamped. func WithBranchHashmapShardCount(shards int) BranchHashmapOption { return func(bh *branchHashmap) { @@ -171,11 +220,20 @@ func WithBranchHashmapShardCount(shards int) BranchHashmapOption { // NewBranchHashmap constructs a new branchHashmap. func NewBranchHashmap(opts ...BranchHashmapOption) (BranchHashmap, error) { bh := &branchHashmap{ - allocator: malloc.GetDefault(nil), + allocator: malloc.GetDefault(nil), + spillBucketCount: defaultSpillBucketCount, + spillSegmentMaxBytes: defaultSpillSegmentMaxSize, } for _, opt := range opts { opt(bh) } + if bh.spillBucketCount == 0 { + bh.spillBucketCount = defaultSpillBucketCount + } + bh.spillBucketCount = normalizeBucketCount(bh.spillBucketCount) + if bh.spillSegmentMaxBytes == 0 { + bh.spillSegmentMaxBytes = defaultSpillSegmentMaxSize + } if bh.allocator == nil { return nil, moerr.NewInternalErrorNoCtx("branchHashmap requires a non-nil allocator") } @@ -191,7 +249,7 @@ func NewBranchHashmap(opts ...BranchHashmapOption) (BranchHashmap, error) { } bh.shards = make([]*hashShard, bh.shardCount) for i := range bh.shards { - bh.shards[i] = newHashShard(i, bh.spillRoot) + bh.shards[i] = newHashShard(i, bh.spillRoot, bh.spillBucketCount, bh.spillSegmentMaxBytes) } return bh, nil } @@ -255,7 +313,7 @@ func (bh *branchHashmap) PutByVectors(vecs []*vector.Vector, keyCols []int) erro if batchSize > rowCount { batchSize = rowCount } - shardBuckets := make([][]*hashEntry, bh.shardCount) + shardEntries := make([][]int, bh.shardCount) for batchStart := 0; batchStart < rowCount; batchStart += batchSize { batchEnd := batchStart + batchSize if batchEnd > rowCount { @@ -278,7 +336,7 @@ func (bh *branchHashmap) PutByVectors(vecs []*vector.Vector, keyCols []int) erro value: valuePacker.Bytes(), }) } - if err := bh.flushPreparedEntries(shardBuckets, chunk); err != nil { + if err := bh.flushPreparedEntries(shardEntries, chunk); err != nil { bh.putPreparedEntryBatch(chunk) return err } @@ -288,7 +346,7 @@ func (bh *branchHashmap) PutByVectors(vecs []*vector.Vector, keyCols []int) erro return nil } -func (bh *branchHashmap) flushPreparedEntries(shardBuckets [][]*hashEntry, chunk []preparedEntry) error { +func (bh *branchHashmap) flushPreparedEntries(shardEntries [][]int, chunk []preparedEntry) error { if len(chunk) == 0 { return nil } @@ -316,53 +374,56 @@ func (bh *branchHashmap) flushPreparedEntries(shardBuckets [][]*hashEntry, chunk if mid == 0 { mid = 1 } - if err := bh.flushPreparedEntries(shardBuckets, chunk[:mid]); err != nil { + if err := bh.flushPreparedEntries(shardEntries, chunk[:mid]); err != nil { return err } - return bh.flushPreparedEntries(shardBuckets, chunk[mid:]) + return bh.flushPreparedEntries(shardEntries, chunk[mid:]) } } } block := &entryBlock{ + buf: buf, deallocator: deallocator, } block.remaining.Store(int32(len(chunk))) offset := 0 + entries := make([]memEntry, len(chunk)) for i := range chunk { prepared := &chunk[i] entrySize := len(prepared.key) + len(prepared.value) - var entryBuf []byte if entrySize > 0 { - entryBuf = buf[offset : offset+entrySize] + entryBuf := buf[offset : offset+entrySize] copy(entryBuf[:len(prepared.key)], prepared.key) copy(entryBuf[len(prepared.key):], prepared.value) } + hash := hashKey(prepared.key) + entries[i] = memEntry{ + hash: hash, + keyOff: uint32(offset), + keyLen: uint32(len(prepared.key)), + valOff: uint32(offset + len(prepared.key)), + valLen: uint32(len(prepared.value)), + block: block, + slot: -1, + lruPrev: -1, + lruNext: -1, + } offset += entrySize - entry := &hashEntry{ - hash: hashKey(prepared.key), - buf: entryBuf, - keyLen: uint32(len(prepared.key)), - valueLen: uint32(len(prepared.value)), - block: block, - } - shardIdx := int(entry.hash % uint64(bh.shardCount)) - shardBuckets[shardIdx] = append(shardBuckets[shardIdx], entry) - } - for idx, entries := range shardBuckets { - if len(entries) == 0 { + shardIdx := int(hash % uint64(bh.shardCount)) + shardEntries[shardIdx] = append(shardEntries[shardIdx], i) + } + for idx, entryIdxs := range shardEntries { + if len(entryIdxs) == 0 { continue } shard := bh.shards[idx] shard.lock() - for _, entry := range entries { - shard.insertEntryLocked(entry) + for _, entryIdx := range entryIdxs { + shard.insertEntryLocked(entries[entryIdx]) } shard.unlock() - for i := range entries { - entries[i] = nil - } - shardBuckets[idx] = entries[:0] + shardEntries[idx] = entryIdxs[:0] } return nil } @@ -445,32 +506,74 @@ func (bh *branchHashmap) lookupByVectors(keyVecs []*vector.Vector, removeAll *bo packer := bh.getPacker() defer bh.putPacker(packer) - + probesByShard := make(map[*hashShard][]*keyProbe, shardCount) for idx := 0; idx < rowCount; idx++ { packer.Reset() if err := encodeRow(packer, keyVecs, keyIndexes, idx); err != nil { return nil, err } keyBytes := packer.Bytes() - hash := hashKey(keyBytes) + keyCopy := make([]byte, len(keyBytes)) + copy(keyCopy, keyBytes) + hash := hashKey(keyCopy) shard := bh.shards[int(hash%uint64(shardCount))] - var ( - rows [][]byte - err error - ) - if removeAll == nil { - rows, err = shard.getRows(hash, keyBytes) - } else { - rows, err = shard.popRows(hash, keyBytes, *removeAll) + probe := &keyProbe{ + idx: idx, + key: keyCopy, + keyStr: string(keyCopy), + hash: hash, } - if err != nil { - return nil, err + if removeAll != nil { + probe.plan = newRemovalPlan(*removeAll) + } + probesByShard[shard] = append(probesByShard[shard], probe) + } + + for shard, probes := range probesByShard { + if shard == nil { + continue } - res := &results[idx] - res.Rows = rows - res.Exists = len(rows) > 0 + shard.lock() + var removedTotal int64 + copyValues := removeAll != nil + for _, probe := range probes { + if removeAll == nil { + rows, _, _ := shard.mem.collect(probe.hash, probe.key, nil, false, true) + results[probe.idx].Rows = rows + continue + } + rows, removedBytes, removedCount := shard.mem.collect(probe.hash, probe.key, probe.plan, copyValues, true) + results[probe.idx].Rows = rows + if removedBytes > 0 { + shard.memInUse -= removedBytes + } + if removedCount > 0 { + removedTotal += int64(removedCount) + } + } + + if shard.spill != nil { + if removeAll == nil { + if err := collectSpillGet(shard, probes, results); err != nil { + shard.unlock() + return nil, err + } + } else { + if err := collectSpillPop(shard, probes, results, *removeAll, &removedTotal); err != nil { + shard.unlock() + return nil, err + } + } + } + if removeAll != nil && removedTotal > 0 { + atomic.AddInt64(&shard.items, -removedTotal) + } + shard.unlock() } + for i := range results { + results[i].Exists = len(results[i].Rows) > 0 + } return results, nil } func (bh *branchHashmap) PopByEncodedKey(encodedKey []byte, removeAll bool) (GetResult, error) { @@ -716,6 +819,8 @@ func (bh *branchHashmap) projectInternal(keyCols []int, parallelism int, consume shardCount := bh.shardCount allocator := bh.allocator spillRoot := bh.spillRoot + spillBucketCount := bh.spillBucketCount + spillSegmentMaxBytes := bh.spillSegmentMaxBytes bh.metaMu.RUnlock() if len(valueTypes) == 0 { @@ -737,6 +842,8 @@ func (bh *branchHashmap) projectInternal(keyCols []int, parallelism int, consume targetIface, err := NewBranchHashmap( WithBranchHashmapAllocator(allocator), WithBranchHashmapSpillRoot(spillRoot), + WithBranchHashmapSpillBucketCount(int(spillBucketCount)), + WithBranchHashmapSpillSegmentMaxBytes(spillSegmentMaxBytes), WithBranchHashmapShardCount(shardCount), ) if err != nil { @@ -753,14 +860,14 @@ func (bh *branchHashmap) projectInternal(keyCols []int, parallelism int, consume target.metaMu.Unlock() err = bh.ForEachShardParallel(func(cursor ShardCursor) error { - shardBuckets := make([][]*hashEntry, target.shardCount) + shardEntries := make([][]int, target.shardCount) keyPacker := target.getPacker() chunk := target.getPreparedEntryBatch(0) flushChunk := func() error { if len(chunk) == 0 { return nil } - if err := target.flushPreparedEntries(shardBuckets, chunk); err != nil { + if err := target.flushPreparedEntries(shardEntries, chunk); err != nil { return err } target.putPreparedEntryBatch(chunk) @@ -772,7 +879,7 @@ func (bh *branchHashmap) projectInternal(keyCols []int, parallelism int, consume target.putPreparedEntryBatch(chunk) }() - err := cursor.ForEach(func(key []byte, rows [][]byte) error { + err := cursor.ForEach(func(key []byte, row []byte) error { var sourceRows [][]byte if consume { res, err := cursor.PopByEncodedKey(key, true) @@ -781,7 +888,7 @@ func (bh *branchHashmap) projectInternal(keyCols []int, parallelism int, consume } sourceRows = res.Rows } else { - sourceRows = rows + sourceRows = [][]byte{row} } if len(sourceRows) == 0 { return nil @@ -863,13 +970,27 @@ func (sc *shardCursor) ShardID() int { return sc.shard.id } -func (sc *shardCursor) ForEach(fn func(key []byte, rows [][]byte) error) error { +func (sc *shardCursor) ForEach(fn func(key []byte, row []byte) error) error { if fn == nil || sc == nil || sc.shard == nil { return nil } return sc.shard.iterateUnsafe(fn) } +func (sc *shardCursor) GetByEncodedKey(encodedKey []byte) (GetResult, error) { + var result GetResult + if sc == nil || sc.shard == nil { + return result, nil + } + rows, err := sc.shard.getRowsDuringIteration(hashKey(encodedKey), encodedKey) + if err != nil { + return result, err + } + result.Rows = rows + result.Exists = len(rows) > 0 + return result, nil +} + func (sc *shardCursor) PopByEncodedKey(encodedKey []byte, removeAll bool) (GetResult, error) { var result GetResult if sc == nil || sc.shard == nil { @@ -907,14 +1028,23 @@ func (bh *branchHashmap) Close() error { bh.metaMu.Unlock() var firstErr error + var agg spillSnapshot + var hadStats bool for _, shard := range bh.shards { if shard == nil { continue } + if snapshot := shard.snapshotSpillStats(); snapshot.hasData() { + agg.merge(snapshot) + hadStats = true + } if err := shard.close(); err != nil && firstErr == nil { firstErr = err } } + if hadStats { + logutil.Infof("%s", agg.summary("branchHashmap")) + } return firstErr } @@ -924,12 +1054,13 @@ type hashShard struct { id int spillRoot string - inMemory map[uint64]*hashBucket - order list.List + mem *memStore memInUse uint64 - spills []*spillPartition - spillDir string + spill *spillStore + spillDir string + spillBucketCount uint32 + spillSegmentMaxBytes uint64 items int64 @@ -938,12 +1069,18 @@ type hashShard struct { iterating bool } -func newHashShard(id int, spillRoot string) *hashShard { +func newHashShard(id int, spillRoot string, spillBucketCount uint32, spillSegmentMaxBytes uint64) *hashShard { hs := &hashShard{ - id: id, - spillRoot: spillRoot, - inMemory: make(map[uint64]*hashBucket), + id: id, + spillRoot: spillRoot, + mem: newMemStore(), + spillBucketCount: spillBucketCount, + spillSegmentMaxBytes: spillSegmentMaxBytes, + } + if hs.spillBucketCount == 0 { + hs.spillBucketCount = 1 } + hs.spillBucketCount = normalizeBucketCount(hs.spillBucketCount) hs.cond = sync.NewCond(&hs.mu) return hs } @@ -975,33 +1112,37 @@ func (hs *hashShard) endIteration() { hs.cond.Broadcast() } -func (hs *hashShard) insertEntryLocked(entry *hashEntry) { - bucket := hs.inMemory[entry.hash] - if bucket == nil { - bucket = &hashBucket{hash: entry.hash} - bucket.orderNode = hs.order.PushBack(entry.hash) - hs.inMemory[entry.hash] = bucket +func (hs *hashShard) insertEntryLocked(entry memEntry) { + if hs.mem == nil { + hs.mem = newMemStore() } - bucket.add(entry) - if bucket.orderNode != nil { - hs.order.MoveToBack(bucket.orderNode) - } - hs.memInUse += uint64(len(entry.buf)) + hs.mem.insert(entry) + hs.memInUse += entry.size() atomic.AddInt64(&hs.items, 1) // TODO(monitoring): track shard-level insertion metrics. } func (hs *hashShard) getRows(hash uint64, key []byte) ([][]byte, error) { hs.lock() defer hs.unlock() - rows := hs.collectFromMemory(hash, key, nil, nil, false, true) - if len(hs.spills) == 0 { + rows, _, _ := hs.mem.collect(hash, key, nil, false, true) + if hs.spill == nil { return rows, nil } - var scratch []byte - for _, part := range hs.spills { - if err := part.collect(hash, key, &rows, &scratch, nil, true); err != nil { - return nil, err - } + if err := hs.spill.collect(hs.spill.bucketID(hash), hash, key, &rows, nil, true, scanReasonGet); err != nil { + return nil, err + } + return rows, nil +} +func (hs *hashShard) getRowsDuringIteration(hash uint64, key []byte) ([][]byte, error) { + if !hs.iterating { + return nil, moerr.NewInternalErrorNoCtx("shard iteration context required") + } + rows, _, _ := hs.mem.collect(hash, key, nil, false, true) + if hs.spill == nil { + return rows, nil + } + if err := hs.spill.collect(hs.spill.bucketID(hash), hash, key, &rows, nil, true, scanReasonGet); err != nil { + return nil, err } return rows, nil } @@ -1033,19 +1174,18 @@ func (hs *hashShard) popRowsByValueDuringIteration(hash uint64, key []byte, valu func (hs *hashShard) popRowsUnsafe(hash uint64, key []byte, removeAll bool) ([][]byte, error) { plan := newRemovalPlan(removeAll) - rows := hs.collectFromMemory(hash, key, nil, plan, true, true) - if len(hs.spills) == 0 { - if removed := len(rows); removed > 0 { - atomic.AddInt64(&hs.items, -int64(removed)) + rows, removedBytes, removedCount := hs.mem.collect(hash, key, plan, true, true) + if removedBytes > 0 { + hs.memInUse -= removedBytes + } + if hs.spill == nil { + if removedCount > 0 { + atomic.AddInt64(&hs.items, -int64(removedCount)) } return rows, nil } - var scratch []byte - for _, part := range hs.spills { - if plan != nil && !plan.hasRemaining() { - break - } - if err := part.collect(hash, key, &rows, &scratch, plan, true); err != nil { + if plan != nil && plan.hasRemaining() { + if err := hs.spill.collect(hs.spill.bucketID(hash), hash, key, &rows, plan, true, scanReasonPop); err != nil { return nil, err } } @@ -1062,23 +1202,19 @@ func (hs *hashShard) popRowsByValueUnsafe(hash uint64, key []byte, value []byte, copy(matchValue, value) } plan := newValueRemovalPlan(removeAll, matchValue) - hs.collectFromMemory(hash, key, nil, plan, false, false) - if len(hs.spills) == 0 { - removed := plan.removed - if removed > 0 { - atomic.AddInt64(&hs.items, -int64(removed)) - } - return removed, nil + _, removedBytes, removedCount := hs.mem.collect(hash, key, plan, false, false) + if removedBytes > 0 { + hs.memInUse -= removedBytes } - var ( - scratch []byte - unused [][]byte - ) - for _, part := range hs.spills { - if plan != nil && !plan.hasRemaining() { - break + if hs.spill == nil { + if removedCount > 0 { + atomic.AddInt64(&hs.items, -int64(removedCount)) } - if err := part.collect(hash, key, &unused, &scratch, plan, false); err != nil { + return removedCount, nil + } + var unused [][]byte + if plan != nil && plan.hasRemaining() { + if err := hs.spill.collect(hs.spill.bucketID(hash), hash, key, &unused, plan, false, scanReasonPopValue); err != nil { return 0, err } } @@ -1088,133 +1224,58 @@ func (hs *hashShard) popRowsByValueUnsafe(hash uint64, key []byte, value []byte, } return removed, nil } -func (hs *hashShard) collectFromMemory(hash uint64, key []byte, dst [][]byte, plan *removalPlan, copyValues bool, collectValues bool) [][]byte { - bucket, ok := hs.inMemory[hash] - if !ok { - return dst - } - matchLen := len(key) - if plan != nil { - newEntries := bucket.entries[:0] - for _, entry := range bucket.entries { - if !plan.hasRemaining() { - newEntries = append(newEntries, entry) - continue - } - if int(entry.keyLen) == matchLen && bytes.Equal(entry.keyBytes(), key) && plan.matchesValue(entry.valueBytes()) && plan.take() { - if collectValues { - value := entry.valueBytes() - var payload []byte - if copyValues { - payload = make([]byte, len(value)) - copy(payload, value) - } else { - payload = value - } - dst = append(dst, payload) - } - hs.memInUse -= uint64(len(entry.buf)) - entry.release() - } else { - newEntries = append(newEntries, entry) - } - } - if len(newEntries) == 0 { - if bucket.orderNode != nil { - hs.order.Remove(bucket.orderNode) - } - delete(hs.inMemory, hash) - } else { - bucket.entries = newEntries - if bucket.orderNode != nil { - hs.order.MoveToBack(bucket.orderNode) - } - } - return dst - } - if bucket.orderNode != nil { - hs.order.MoveToBack(bucket.orderNode) - } - for _, entry := range bucket.entries { - if int(entry.keyLen) != matchLen { - continue - } - if bytes.Equal(entry.keyBytes(), key) { - if collectValues { - value := entry.valueBytes() - if copyValues { - copied := make([]byte, len(value)) - copy(copied, value) - dst = append(dst, copied) - } else { - dst = append(dst, value) - } - } - } - } - return dst -} func (hs *hashShard) spillLocked(required uint64) (uint64, error) { if required == 0 { return 0, nil } var ( - freed uint64 minRequired = max(mpool.MB, required) ) - for freed < minRequired { - element := hs.order.Front() - if element == nil { - break - } - hash := element.Value.(uint64) - bucket := hs.inMemory[hash] - hs.order.Remove(element) - if bucket == nil { - delete(hs.inMemory, hash) - continue - } - released, err := hs.spillBucketLocked(bucket) - if err != nil { - return freed, err - } - freed += released - delete(hs.inMemory, hash) + store, err := hs.ensureSpillStore() + if err != nil { + return 0, err } - return freed, nil -} - -func (hs *hashShard) spillBucketLocked(bucket *hashBucket) (uint64, error) { - if len(bucket.entries) == 0 { + entries, freed := hs.mem.pickEvictionEntries(minRequired) + if len(entries) == 0 { return 0, nil } - part, err := hs.ensureSpillPartition() - if err != nil { - return 0, err + grouped := make(map[uint32][]spillEntry, len(entries)) + for _, idx := range entries { + entry := &hs.mem.entries[idx] + bucketID := store.bucketID(entry.hash) + grouped[bucketID] = append(grouped[bucketID], spillEntry{ + hash: entry.hash, + key: entry.keyBytes(), + value: entry.valueBytes(), + }) } - var freed uint64 - for _, entry := range bucket.entries { - if err := part.append(entry); err != nil { - return freed, err + for bucketID, list := range grouped { + if err := store.appendEntries(bucketID, list); err != nil { + return 0, err + } + } + for _, idx := range entries { + freedBytes := hs.mem.removeEntry(idx) + if freedBytes > 0 { + hs.memInUse -= freedBytes } - freed += uint64(len(entry.buf)) - entry.release() } - bucket.entries = nil - hs.memInUse -= freed return freed, nil } -func (hs *hashShard) ensureSpillPartition() (*spillPartition, error) { +func (hs *hashShard) ensureSpillStore() (*spillStore, error) { + if hs.spill != nil { + return hs.spill, nil + } if err := hs.ensureSpillDir(); err != nil { return nil, err } - part, err := newSpillPartition(hs.spillDir) + store, err := newSpillStore(hs.spillDir, hs.spillBucketCount, hs.spillSegmentMaxBytes) if err != nil { return nil, err } - hs.spills = append(hs.spills, part) - return part, nil + hs.spill = store + return store, nil } func (hs *hashShard) ensureSpillDir() error { @@ -1242,28 +1303,27 @@ func (hs *hashShard) close() error { defer hs.unlock() var firstErr error - for hash, bucket := range hs.inMemory { - if bucket.orderNode != nil { - hs.order.Remove(bucket.orderNode) - } - for _, entry := range bucket.entries { - hs.memInUse -= uint64(len(entry.buf)) - entry.release() + if hs.mem != nil { + for idx := range hs.mem.entries { + entry := &hs.mem.entries[idx] + if !entry.inUse { + continue + } + hs.memInUse -= entry.size() + if entry.block != nil { + entry.block.release() + } } - delete(hs.inMemory, hash) + hs.mem = newMemStore() } + hs.memInUse = 0 - for _, part := range hs.spills { - if err := part.close(); err != nil && firstErr == nil { + if hs.spill != nil { + if err := hs.spill.close(); err != nil && firstErr == nil { firstErr = err } - if part.path != "" { - if err := os.Remove(part.path); err != nil && !os.IsNotExist(err) && firstErr == nil { - firstErr = err - } - } + hs.spill = nil } - hs.spills = nil if hs.spillDir != "" { if err := os.RemoveAll(hs.spillDir); err != nil && firstErr == nil { @@ -1274,6 +1334,62 @@ func (hs *hashShard) close() error { atomic.StoreInt64(&hs.items, 0) return firstErr } + +func (hs *hashShard) snapshotSpillStats() spillSnapshot { + if hs == nil || hs.spill == nil { + return spillSnapshot{} + } + ss := hs.spill.stats + snap := spillSnapshot{ + spilledEntries: ss.spilledEntries, + spilledPayloadBytes: ss.spilledPayloadBytes, + spilledBytes: ss.spilledBytes, + bucketScans: ss.bucketScans, + bucketScanBytes: ss.bucketScanBytes, + bucketScanEntries: ss.bucketScanEntries, + matchedEntries: ss.matchedEntries, + matchedBytes: ss.matchedBytes, + removedEntries: ss.removedEntries, + removedBytes: ss.removedBytes, + getProbeKeys: ss.getProbeKeys, + getBucketScans: ss.getBucketScans, + popProbeKeys: ss.popProbeKeys, + popBucketScans: ss.popBucketScans, + popValueProbeKeys: ss.popValueProbeKeys, + popValueBucketScans: ss.popValueBucketScans, + forEachBucketScans: ss.forEachBucketScans, + bucketCount: hs.spill.bucketCount, + } + var ( + maxSegments uint64 + segments uint64 + bucketsUsed uint64 + ) + for _, bucket := range hs.spill.buckets { + segCount := uint64(len(bucket.segments)) + segments += segCount + if segCount > maxSegments { + maxSegments = segCount + } + if bucket.rowCount > 0 { + bucketsUsed++ + } + } + snap.segmentsTotal = segments + snap.maxSegmentsPerBucket = maxSegments + snap.bucketsUsed = bucketsUsed + + for _, scanCount := range ss.scanPerBucket { + if scanCount == 0 { + continue + } + snap.bucketsScanned++ + if scanCount > 1 { + snap.repeatedBucketScans += scanCount - 1 + } + } + return snap +} func (bh *branchHashmap) allocateBuffer(size uint64) ([]byte, malloc.Deallocator, error) { buf, deallocator, err := bh.allocator.Allocate(size, malloc.NoClear) if err != nil { @@ -1400,6 +1516,20 @@ func hashKey(key []byte) uint64 { return states[0][0] } +func normalizeBucketCount(n uint32) uint32 { + if n <= 1 { + return 1 + } + n-- + n |= n >> 1 + n |= n >> 2 + n |= n >> 4 + n |= n >> 8 + n |= n >> 16 + n++ + return n +} + func cloneTypes(vecs []*vector.Vector) []types.Type { ret := make([]types.Type, len(vecs)) for i, vec := range vecs { @@ -1671,6 +1801,7 @@ type preparedEntry struct { } type entryBlock struct { + buf []byte deallocator malloc.Deallocator remaining atomic.Int32 } @@ -1688,163 +1819,994 @@ func (eb *entryBlock) release() { if cur-1 == 0 && eb.deallocator != nil { eb.deallocator.Deallocate() eb.deallocator = nil + eb.buf = nil } return } } } -type hashEntry struct { - hash uint64 - buf []byte - keyLen uint32 - valueLen uint32 - block *entryBlock -} +const ( + memSlotEmpty int32 = -1 + memSlotTombstone int32 = -2 +) -func (e *hashEntry) keyBytes() []byte { - if e.keyLen == 0 { +type memEntry struct { + hash uint64 + keyOff uint32 + keyLen uint32 + valOff uint32 + valLen uint32 + block *entryBlock + slot int32 + lruPrev int32 + lruNext int32 + inUse bool +} + +func (e *memEntry) keyBytes() []byte { + if e == nil || e.keyLen == 0 || e.block == nil { return nil } - return e.buf[:e.keyLen] + start := int(e.keyOff) + end := start + int(e.keyLen) + return e.block.buf[start:end] } -func (e *hashEntry) valueBytes() []byte { - if e.valueLen == 0 { +func (e *memEntry) valueBytes() []byte { + if e == nil || e.valLen == 0 || e.block == nil { return nil } - return e.buf[e.keyLen : e.keyLen+e.valueLen] + start := int(e.valOff) + end := start + int(e.valLen) + return e.block.buf[start:end] +} + +func (e *memEntry) size() uint64 { + return uint64(e.keyLen + e.valLen) +} + +type memStore struct { + index []int32 + entries []memEntry + freeList []int32 + count int + tombstones int + lruHead int32 + lruTail int32 +} + +func newMemStore() *memStore { + return &memStore{ + lruHead: -1, + lruTail: -1, + } +} + +func (ms *memStore) len() int { + if ms == nil { + return 0 + } + return ms.count +} + +func (ms *memStore) ensureCapacity(additional int) { + if ms.index == nil { + ms.init(defaultMemIndexSize) + } + needed := ms.count + additional + limit := int(float64(len(ms.index)) * 0.7) + if needed+ms.tombstones <= limit { + return + } + newCap := len(ms.index) * 2 + if newCap == 0 { + newCap = defaultMemIndexSize + } + for int(float64(newCap)*0.7) < needed { + newCap *= 2 + } + ms.rehash(newCap) } -func (e *hashEntry) release() { - e.buf = nil - if e.block != nil { - e.block.release() - e.block = nil +func (ms *memStore) init(capacity int) { + if capacity < defaultMemIndexSize { + capacity = defaultMemIndexSize + } + capacity = int(normalizeBucketCount(uint32(capacity))) + ms.index = make([]int32, capacity) + for i := range ms.index { + ms.index[i] = memSlotEmpty } } -type hashBucket struct { - hash uint64 - entries []*hashEntry - orderNode *list.Element +func (ms *memStore) rehash(capacity int) { + if capacity < defaultMemIndexSize { + capacity = defaultMemIndexSize + } + capacity = int(normalizeBucketCount(uint32(capacity))) + newIndex := make([]int32, capacity) + for i := range newIndex { + newIndex[i] = memSlotEmpty + } + mask := uint64(capacity - 1) + for idx := range ms.entries { + entry := &ms.entries[idx] + if !entry.inUse { + continue + } + slot := int(entry.hash & mask) + for { + if newIndex[slot] == memSlotEmpty { + newIndex[slot] = int32(idx) + entry.slot = int32(slot) + break + } + slot = (slot + 1) & (capacity - 1) + } + } + ms.index = newIndex + ms.tombstones = 0 } -func (b *hashBucket) add(entry *hashEntry) { - b.entries = append(b.entries, entry) +func (ms *memStore) allocateEntryIndex() int32 { + if n := len(ms.freeList); n > 0 { + idx := ms.freeList[n-1] + ms.freeList = ms.freeList[:n-1] + return idx + } + ms.entries = append(ms.entries, memEntry{}) + return int32(len(ms.entries) - 1) } -type spillPartition struct { - file *os.File - path string - offset int64 - index map[uint64][]spillPointer +func (ms *memStore) insert(entry memEntry) int32 { + ms.ensureCapacity(1) + slot, usedTombstone := ms.findSlot(entry.hash) + idx := ms.allocateEntryIndex() + entry.slot = int32(slot) + entry.inUse = true + entry.lruPrev = -1 + entry.lruNext = -1 + ms.entries[idx] = entry + ms.index[slot] = idx + if usedTombstone { + ms.tombstones-- + } + ms.count++ + ms.lruAppend(idx) + return idx } -type spillPointer struct { - offset int64 - keyLen uint32 - valueLen uint32 +func (ms *memStore) findSlot(hash uint64) (int, bool) { + mask := len(ms.index) - 1 + slot := int(hash & uint64(mask)) + firstTombstone := -1 + for { + cur := ms.index[slot] + switch cur { + case memSlotEmpty: + if firstTombstone >= 0 { + return firstTombstone, true + } + return slot, false + case memSlotTombstone: + if firstTombstone < 0 { + firstTombstone = slot + } + default: + } + slot = (slot + 1) & mask + } } -func newSpillPartition(dir string) (*spillPartition, error) { - file, err := os.CreateTemp(dir, "branch-spill-*.bin") - if err != nil { - return nil, moerr.NewInternalErrorNoCtxf("failed to create spill file: %v", err) +func (ms *memStore) lruAppend(idx int32) { + if idx < 0 { + return + } + if ms.lruTail < 0 { + ms.lruHead = idx + ms.lruTail = idx + return } - return &spillPartition{ - file: file, - path: file.Name(), - index: make(map[uint64][]spillPointer), - }, nil + tail := ms.lruTail + ms.entries[idx].lruPrev = tail + ms.entries[idx].lruNext = -1 + ms.entries[tail].lruNext = idx + ms.lruTail = idx } -func (sp *spillPartition) append(entry *hashEntry) error { - var header [16]byte - binary.LittleEndian.PutUint64(header[0:8], entry.hash) - binary.LittleEndian.PutUint32(header[8:12], entry.keyLen) - binary.LittleEndian.PutUint32(header[12:16], entry.valueLen) - if n, err := sp.file.Write(header[:]); err != nil { - return err - } else if n != len(header) { - return io.ErrShortWrite +func (ms *memStore) lruRemove(idx int32) { + if idx < 0 { + return } - if n, err := sp.file.Write(entry.buf); err != nil { - return err - } else if n != len(entry.buf) { - return io.ErrShortWrite - } - dataOffset := sp.offset + 16 - sp.index[entry.hash] = append(sp.index[entry.hash], spillPointer{ - offset: dataOffset, - keyLen: entry.keyLen, - valueLen: entry.valueLen, - }) - sp.offset += int64(16 + len(entry.buf)) - return nil + entry := &ms.entries[idx] + prev := entry.lruPrev + next := entry.lruNext + if prev >= 0 { + ms.entries[prev].lruNext = next + } else { + ms.lruHead = next + } + if next >= 0 { + ms.entries[next].lruPrev = prev + } else { + ms.lruTail = prev + } + entry.lruPrev = -1 + entry.lruNext = -1 } -func (sp *spillPartition) collect(hash uint64, key []byte, dst *[][]byte, scratch *[]byte, plan *removalPlan, collectValues bool) error { - pointers := sp.index[hash] - if len(pointers) == 0 { +func (ms *memStore) lruTouch(idx int32) { + if idx < 0 || ms.lruTail == idx { + return + } + ms.lruRemove(idx) + ms.lruAppend(idx) +} + +func (ms *memStore) removeEntry(idx int32) uint64 { + if idx < 0 { + return 0 + } + entry := &ms.entries[idx] + if !entry.inUse { + return 0 + } + if entry.slot >= 0 && entry.slot < int32(len(ms.index)) { + if ms.index[entry.slot] == idx { + ms.index[entry.slot] = memSlotTombstone + ms.tombstones++ + } + } + ms.count-- + ms.lruRemove(idx) + entry.inUse = false + size := entry.size() + if entry.block != nil { + entry.block.release() + } + *entry = memEntry{} + ms.freeList = append(ms.freeList, idx) + return size +} + +func (ms *memStore) collect(hash uint64, key []byte, plan *removalPlan, copyValues bool, collectValues bool) ([][]byte, uint64, int) { + if len(ms.index) == 0 || ms.count == 0 { + return nil, 0, 0 + } + var ( + rows [][]byte + removedCount int + removedBytes uint64 + ) + mask := len(ms.index) - 1 + slot := int(hash & uint64(mask)) + for { + cur := ms.index[slot] + if cur == memSlotEmpty { + break + } + if cur >= 0 { + entry := &ms.entries[cur] + if entry.inUse && entry.hash == hash && bytes.Equal(entry.keyBytes(), key) { + if plan == nil { + if collectValues { + value := entry.valueBytes() + if copyValues { + payload := make([]byte, len(value)) + copy(payload, value) + rows = append(rows, payload) + } else { + rows = append(rows, value) + } + } + ms.lruTouch(cur) + } else if plan.matchesValue(entry.valueBytes()) && plan.take() { + if collectValues { + value := entry.valueBytes() + payload := make([]byte, len(value)) + copy(payload, value) + rows = append(rows, payload) + } + removedCount++ + ms.lruTouch(cur) + removedBytes += ms.removeEntry(cur) + } + } + } + slot = (slot + 1) & mask + } + return rows, removedBytes, removedCount +} + +func (ms *memStore) forEach(fn func(entry *memEntry) error) error { + if fn == nil { return nil } - kept := pointers[:0] - for _, ptr := range pointers { - if plan != nil && !plan.hasRemaining() { - kept = append(kept, ptr) + for idx := range ms.entries { + entry := &ms.entries[idx] + if !entry.inUse { continue } - need := int(ptr.keyLen + ptr.valueLen) - if cap(*scratch) < need { - *scratch = make([]byte, need) + if err := fn(entry); err != nil { + return err + } + } + return nil +} + +func (ms *memStore) pickEvictionEntries(required uint64) ([]int32, uint64) { + var ( + selected []int32 + freed uint64 + ) + cur := ms.lruHead + for cur >= 0 && freed < required { + entry := &ms.entries[cur] + if entry.inUse { + selected = append(selected, cur) + freed += entry.size() + } + cur = entry.lruNext + } + return selected, freed +} + +type spillStore struct { + dir string + bucketCount uint32 + bucketMask uint64 + maxSegmentBytes uint64 + buckets []spillBucket + stats spillStats +} + +type spillEntry struct { + hash uint64 + key []byte + value []byte +} + +type spillBucket struct { + segments []*spillSegment + rowCount uint64 + tombstone *tombstoneBitmap +} + +type spillSegment struct { + path string + size int64 +} + +type tombstoneBitmap struct { + bits []uint64 +} + +type scanReason uint8 + +const ( + scanReasonUnknown scanReason = iota + scanReasonForEach + scanReasonGet + scanReasonPop + scanReasonPopValue +) + +type spillStats struct { + spilledEntries uint64 + spilledPayloadBytes uint64 + spilledBytes uint64 + segmentsCreated uint64 + + bucketScans uint64 + bucketScanBytes uint64 + bucketScanEntries uint64 + + matchedEntries uint64 + matchedBytes uint64 + removedEntries uint64 + removedBytes uint64 + + getProbeKeys uint64 + getBucketScans uint64 + popProbeKeys uint64 + popBucketScans uint64 + popValueProbeKeys uint64 + popValueBucketScans uint64 + forEachBucketScans uint64 + + scanPerBucket []uint64 +} + +type spillSnapshot struct { + spilledEntries uint64 + spilledPayloadBytes uint64 + spilledBytes uint64 + segmentsTotal uint64 + maxSegmentsPerBucket uint64 + bucketsUsed uint64 + bucketCount uint32 + + bucketScans uint64 + bucketScanBytes uint64 + bucketScanEntries uint64 + bucketsScanned uint64 + repeatedBucketScans uint64 + + matchedEntries uint64 + matchedBytes uint64 + removedEntries uint64 + removedBytes uint64 + + getProbeKeys uint64 + getBucketScans uint64 + popProbeKeys uint64 + popBucketScans uint64 + popValueProbeKeys uint64 + popValueBucketScans uint64 + forEachBucketScans uint64 +} + +func (ss *spillStats) recordProbe(reason scanReason, keys int, buckets int) { + if keys <= 0 || buckets <= 0 { + return + } + switch reason { + case scanReasonGet: + ss.getProbeKeys += uint64(keys) + case scanReasonPop: + ss.popProbeKeys += uint64(keys) + case scanReasonPopValue: + ss.popValueProbeKeys += uint64(keys) + } +} + +func (ss *spillStats) recordMatch(valueLen int, removed bool) { + if valueLen < 0 { + valueLen = 0 + } + ss.matchedEntries++ + ss.matchedBytes += uint64(valueLen) + if removed { + ss.removedEntries++ + ss.removedBytes += uint64(valueLen) + } +} + +func (ss *spillStats) recordScan(reason scanReason, bucketID uint32, entries uint64, bytes uint64) { + if entries == 0 && bytes == 0 { + return + } + ss.bucketScans++ + ss.bucketScanEntries += entries + ss.bucketScanBytes += bytes + if int(bucketID) < len(ss.scanPerBucket) { + ss.scanPerBucket[bucketID]++ + } + switch reason { + case scanReasonForEach: + ss.forEachBucketScans++ + case scanReasonGet: + ss.getBucketScans++ + case scanReasonPop: + ss.popBucketScans++ + case scanReasonPopValue: + ss.popValueBucketScans++ + } +} + +func (sn *spillSnapshot) merge(other spillSnapshot) { + sn.spilledEntries += other.spilledEntries + sn.spilledPayloadBytes += other.spilledPayloadBytes + sn.spilledBytes += other.spilledBytes + sn.segmentsTotal += other.segmentsTotal + if other.maxSegmentsPerBucket > sn.maxSegmentsPerBucket { + sn.maxSegmentsPerBucket = other.maxSegmentsPerBucket + } + sn.bucketsUsed += other.bucketsUsed + if sn.bucketCount == 0 { + sn.bucketCount = other.bucketCount + } + sn.bucketScans += other.bucketScans + sn.bucketScanBytes += other.bucketScanBytes + sn.bucketScanEntries += other.bucketScanEntries + sn.bucketsScanned += other.bucketsScanned + sn.repeatedBucketScans += other.repeatedBucketScans + sn.matchedEntries += other.matchedEntries + sn.matchedBytes += other.matchedBytes + sn.removedEntries += other.removedEntries + sn.removedBytes += other.removedBytes + sn.getProbeKeys += other.getProbeKeys + sn.getBucketScans += other.getBucketScans + sn.popProbeKeys += other.popProbeKeys + sn.popBucketScans += other.popBucketScans + sn.popValueProbeKeys += other.popValueProbeKeys + sn.popValueBucketScans += other.popValueBucketScans + sn.forEachBucketScans += other.forEachBucketScans +} + +func (sn spillSnapshot) hasData() bool { + return sn.spilledEntries > 0 || sn.bucketScans > 0 || sn.matchedEntries > 0 +} + +func (sn spillSnapshot) summary(prefix string) string { + avgEntry := uint64(0) + if sn.spilledEntries > 0 { + avgEntry = sn.spilledPayloadBytes / sn.spilledEntries + } + scanAmp := 0.0 + if sn.matchedEntries > 0 { + scanAmp = float64(sn.bucketScanEntries) / float64(sn.matchedEntries) + } + avgKeysPerGetScan := 0.0 + if sn.getBucketScans > 0 { + avgKeysPerGetScan = float64(sn.getProbeKeys) / float64(sn.getBucketScans) + } + avgKeysPerPopScan := 0.0 + if sn.popBucketScans > 0 { + avgKeysPerPopScan = float64(sn.popProbeKeys) / float64(sn.popBucketScans) + } + hints := make([]string, 0, 3) + if sn.matchedEntries > 0 && scanAmp > 50 { + hints = append(hints, "high scan amplification") + } + if sn.getBucketScans > 0 && avgKeysPerGetScan < 2 { + hints = append(hints, "low key batching on get") + } + if sn.popBucketScans > 0 && avgKeysPerPopScan < 2 { + hints = append(hints, "low key batching on pop") + } + if sn.repeatedBucketScans > sn.bucketScans/2 { + hints = append(hints, "many repeated bucket scans") + } + hintText := "ok" + if len(hints) > 0 { + hintText = strings.Join(hints, "; ") + } + return fmt.Sprintf( + "%s spill summary: spilled_entries=%d spilled_payload_bytes=%d spilled_bytes=%d avg_entry_bytes=%d segments=%d max_segments_per_bucket=%d buckets_used=%d bucket_scans=%d scan_entries=%d scan_bytes=%d matched_entries=%d removed_entries=%d scan_amp=%.2f get_keys=%d get_bucket_scans=%d pop_keys=%d pop_bucket_scans=%d foreach_bucket_scans=%d repeated_bucket_scans=%d hints=%s", + prefix, + sn.spilledEntries, + sn.spilledPayloadBytes, + sn.spilledBytes, + avgEntry, + sn.segmentsTotal, + sn.maxSegmentsPerBucket, + sn.bucketsUsed, + sn.bucketScans, + sn.bucketScanEntries, + sn.bucketScanBytes, + sn.matchedEntries, + sn.removedEntries, + scanAmp, + sn.getProbeKeys, + sn.getBucketScans, + sn.popProbeKeys, + sn.popBucketScans, + sn.forEachBucketScans, + sn.repeatedBucketScans, + hintText, + ) +} +func newSpillStore(dir string, bucketCount uint32, maxSegmentBytes uint64) (*spillStore, error) { + if bucketCount == 0 { + bucketCount = 1 + } + bucketCount = normalizeBucketCount(bucketCount) + if maxSegmentBytes == 0 { + maxSegmentBytes = defaultSpillSegmentMaxSize + } + store := &spillStore{ + dir: dir, + bucketCount: bucketCount, + bucketMask: uint64(bucketCount - 1), + maxSegmentBytes: maxSegmentBytes, + buckets: make([]spillBucket, bucketCount), + } + store.stats.scanPerBucket = make([]uint64, bucketCount) + return store, nil +} + +func (ss *spillStore) bucketID(hash uint64) uint32 { + return uint32(hash & ss.bucketMask) +} + +func (ss *spillStore) appendEntries(bucketID uint32, entries []spillEntry) error { + if len(entries) == 0 { + return nil + } + bucket := &ss.buckets[bucketID] + var ( + seg *spillSegment + file *os.File + writer *bufio.Writer + ) + if len(bucket.segments) > 0 { + seg = bucket.segments[len(bucket.segments)-1] + } + closeWriter := func() error { + if writer != nil { + if err := writer.Flush(); err != nil { + return err + } + } + if file != nil { + if err := file.Close(); err != nil { + return err + } + } + writer = nil + file = nil + return nil + } + for _, entry := range entries { + entryBytes := spillEntryHeaderSize + len(entry.key) + len(entry.value) + needsNewSegment := seg == nil + if !needsNewSegment && ss.maxSegmentBytes > 0 && seg.size > 0 && + seg.size+int64(entryBytes) > int64(ss.maxSegmentBytes) { + needsNewSegment = true } - buf := (*scratch)[:need] - n, err := sp.file.ReadAt(buf, ptr.offset) - if err != nil && err != io.EOF { + if needsNewSegment { + if err := closeWriter(); err != nil { + return err + } + var err error + seg, file, writer, err = ss.createSegment(bucket, bucketID) + if err != nil { + return err + } + } else if file == nil || writer == nil { + var err error + file, err = os.OpenFile(seg.path, os.O_WRONLY|os.O_APPEND, 0o600) + if err != nil { + return err + } + writer = bufio.NewWriter(file) + } + var header [spillEntryHeaderSize]byte + binary.LittleEndian.PutUint64(header[0:8], entry.hash) + binary.LittleEndian.PutUint32(header[8:12], uint32(len(entry.key))) + binary.LittleEndian.PutUint32(header[12:16], uint32(len(entry.value))) + if _, err := writer.Write(header[:]); err != nil { + _ = closeWriter() return err } - if n != len(buf) { - return io.ErrUnexpectedEOF + if len(entry.key) > 0 { + if _, err := writer.Write(entry.key); err != nil { + _ = closeWriter() + return err + } + } + if len(entry.value) > 0 { + if _, err := writer.Write(entry.value); err != nil { + _ = closeWriter() + return err + } } - matched := bytes.Equal(buf[:ptr.keyLen], key) - switch { - case plan == nil: - if matched && collectValues { - payload := make([]byte, ptr.valueLen) - copy(payload, buf[ptr.keyLen:]) + seg.size += int64(entryBytes) + bucket.rowCount++ + ss.stats.spilledEntries++ + ss.stats.spilledPayloadBytes += uint64(len(entry.key) + len(entry.value)) + ss.stats.spilledBytes += uint64(entryBytes) + } + return closeWriter() +} + +func (ss *spillStore) createSegment(bucket *spillBucket, bucketID uint32) (*spillSegment, *os.File, *bufio.Writer, error) { + segmentID := len(bucket.segments) + path := filepath.Join(ss.dir, fmt.Sprintf("spill-b%05d-%06d.bin", bucketID, segmentID)) + file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600) + if err != nil { + return nil, nil, nil, err + } + seg := &spillSegment{path: path} + bucket.segments = append(bucket.segments, seg) + ss.stats.segmentsCreated++ + return seg, file, bufio.NewWriter(file), nil +} + +func (ss *spillStore) forEachEntry(bucketID uint32, scratch *[]byte, fn func(key []byte, value []byte) error) error { + return ss.scanBucket(bucketID, scanReasonForEach, scratch, func(_ uint64, key []byte, value []byte, _ uint64) (bool, error) { + return false, fn(key, value) + }) +} + +func (ss *spillStore) collect(bucketID uint32, hash uint64, key []byte, dst *[][]byte, plan *removalPlan, collectValues bool, reason scanReason) error { + bucket := &ss.buckets[bucketID] + if bucket.rowCount == 0 { + return nil + } + ss.stats.recordProbe(reason, 1, 1) + var scratch []byte + return ss.scanBucket(bucketID, reason, &scratch, func(entryHash uint64, entryKey []byte, entryValue []byte, rid uint64) (bool, error) { + if entryHash != hash || !bytes.Equal(entryKey, key) { + return false, nil + } + if plan == nil { + if collectValues { + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) *dst = append(*dst, payload) } - kept = append(kept, ptr) - case matched && plan.matchesValue(buf[ptr.keyLen:ptr.keyLen+ptr.valueLen]) && plan.take(): + ss.stats.recordMatch(len(entryValue), false) + return false, nil + } + if plan.matchesValue(entryValue) && plan.take() { if collectValues { - payload := make([]byte, ptr.valueLen) - copy(payload, buf[ptr.keyLen:]) + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) *dst = append(*dst, payload) } - default: - kept = append(kept, ptr) + bucket.setTombstone(rid) + ss.stats.recordMatch(len(entryValue), true) + } + if !plan.hasRemaining() { + return true, nil + } + return false, nil + }) +} + +func (ss *spillStore) scanBucket(bucketID uint32, reason scanReason, scratch *[]byte, fn func(hash uint64, key []byte, value []byte, rid uint64) (bool, error)) error { + bucket := &ss.buckets[bucketID] + if bucket.rowCount == 0 { + return nil + } + var header [spillEntryHeaderSize]byte + var rid uint64 + var scannedEntries uint64 + var scannedBytes uint64 + for _, seg := range bucket.segments { + file, err := os.Open(seg.path) + if err != nil { + return err + } + reader := bufio.NewReader(file) + for { + if _, err := io.ReadFull(reader, header[:]); err != nil { + if err == io.EOF { + break + } + if err == io.ErrUnexpectedEOF { + _ = file.Close() + return io.ErrUnexpectedEOF + } + _ = file.Close() + return err + } + entryHash := binary.LittleEndian.Uint64(header[0:8]) + keyLen := binary.LittleEndian.Uint32(header[8:12]) + valLen := binary.LittleEndian.Uint32(header[12:16]) + total := int(keyLen + valLen) + scannedEntries++ + scannedBytes += uint64(spillEntryHeaderSize) + uint64(total) + if cap(*scratch) < total { + *scratch = make([]byte, total) + } + buf := (*scratch)[:total] + if _, err := io.ReadFull(reader, buf); err != nil { + _ = file.Close() + return err + } + if bucket.tombstone != nil && bucket.tombstone.isSet(rid) { + rid++ + continue + } + keyBytes := buf[:keyLen] + valBytes := buf[keyLen:] + stop, err := fn(entryHash, keyBytes, valBytes, rid) + if err != nil { + _ = file.Close() + return err + } + rid++ + if stop { + _ = file.Close() + return nil + } + } + if err := file.Close(); err != nil { + return err } } - if plan != nil { - if len(kept) == 0 { - delete(sp.index, hash) - } else { - sp.index[hash] = append(sp.index[hash][:0], kept...) + ss.stats.recordScan(reason, bucketID, scannedEntries, scannedBytes) + return nil +} + +func (ss *spillStore) close() error { + var firstErr error + for _, bucket := range ss.buckets { + for _, seg := range bucket.segments { + if seg.path == "" { + continue + } + if err := os.Remove(seg.path); err != nil && !os.IsNotExist(err) && firstErr == nil { + firstErr = err + } + } + } + return firstErr +} + +func (sb *spillBucket) setTombstone(rid uint64) { + if sb.tombstone == nil { + sb.tombstone = &tombstoneBitmap{} + } + sb.tombstone.set(rid) +} + +func (tb *tombstoneBitmap) isSet(rid uint64) bool { + idx := rid >> 6 + if int(idx) >= len(tb.bits) { + return false + } + return tb.bits[idx]&(1<<(rid&63)) != 0 +} + +func (tb *tombstoneBitmap) set(rid uint64) { + idx := rid >> 6 + if int(idx) >= len(tb.bits) { + expanded := make([]uint64, idx+1) + copy(expanded, tb.bits) + tb.bits = expanded + } + tb.bits[idx] |= 1 << (rid & 63) +} + +func collectSpillGet(shard *hashShard, probes []*keyProbe, results []GetResult) error { + buckets := make(map[uint32][]*keyProbe, len(probes)) + for _, probe := range probes { + bucketID := shard.spill.bucketID(probe.hash) + buckets[bucketID] = append(buckets[bucketID], probe) + } + var scratch []byte + for bucketID, bucketProbes := range buckets { + shard.spill.stats.recordProbe(scanReasonGet, len(bucketProbes), 1) + groupsByHash := make(map[uint64]map[string]*probeGroup, len(bucketProbes)) + for _, probe := range bucketProbes { + groups, ok := groupsByHash[probe.hash] + if !ok { + groups = make(map[string]*probeGroup, 1) + groupsByHash[probe.hash] = groups + } + group, ok := groups[probe.keyStr] + if !ok { + group = &probeGroup{} + groups[probe.keyStr] = group + } + group.indices = append(group.indices, probe.idx) + } + + if err := shard.spill.scanBucket(bucketID, scanReasonGet, &scratch, func(entryHash uint64, entryKey []byte, entryValue []byte, _ uint64) (bool, error) { + groups := groupsByHash[entryHash] + if len(groups) == 0 { + return false, nil + } + group := groups[string(entryKey)] + if group == nil { + return false, nil + } + shard.spill.stats.recordMatch(len(entryValue), false) + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) + group.values = append(group.values, payload) + return false, nil + }); err != nil { + return err + } + + for _, groups := range groupsByHash { + for _, group := range groups { + if len(group.values) == 0 { + continue + } + for _, idx := range group.indices { + results[idx].Rows = append(results[idx].Rows, group.values...) + } + } } - } else if len(kept) != len(pointers) { - sp.index[hash] = append(sp.index[hash][:0], kept...) } return nil } -func (sp *spillPartition) close() error { - if sp.file == nil { - return nil +func collectSpillPop(shard *hashShard, probes []*keyProbe, results []GetResult, removeAll bool, removedTotal *int64) error { + buckets := make(map[uint32][]*keyProbe, len(probes)) + seenKeys := map[string]struct{}{} + for _, probe := range probes { + if probe.plan == nil || !probe.plan.hasRemaining() { + continue + } + if removeAll { + if _, ok := seenKeys[probe.keyStr]; ok { + continue + } + seenKeys[probe.keyStr] = struct{}{} + } + bucketID := shard.spill.bucketID(probe.hash) + buckets[bucketID] = append(buckets[bucketID], probe) } - err := sp.file.Close() - sp.file = nil - return err + + var scratch []byte + for bucketID, bucketProbes := range buckets { + if len(bucketProbes) == 0 { + continue + } + shard.spill.stats.recordProbe(scanReasonPop, len(bucketProbes), 1) + groupsByHash := make(map[uint64]map[string]*probeGroup, len(bucketProbes)) + remaining := 0 + for _, probe := range bucketProbes { + groups, ok := groupsByHash[probe.hash] + if !ok { + groups = make(map[string]*probeGroup, 1) + groupsByHash[probe.hash] = groups + } + group, ok := groups[probe.keyStr] + if !ok { + group = &probeGroup{} + groups[probe.keyStr] = group + } + group.indices = append(group.indices, probe.idx) + group.plans = append(group.plans, probe.plan) + if !removeAll && probe.plan.hasRemaining() { + remaining++ + } + } + + err := shard.spill.scanBucket(bucketID, scanReasonPop, &scratch, func(entryHash uint64, entryKey []byte, entryValue []byte, rid uint64) (bool, error) { + groups := groupsByHash[entryHash] + if len(groups) == 0 { + return false, nil + } + group := groups[string(entryKey)] + if group == nil { + return false, nil + } + if removeAll { + plan := group.plans[0] + if plan.matchesValue(entryValue) && plan.take() { + shard.spill.buckets[bucketID].setTombstone(rid) + shard.spill.stats.recordMatch(len(entryValue), true) + if removedTotal != nil { + *removedTotal = *removedTotal + 1 + } + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) + results[group.indices[0]].Rows = append(results[group.indices[0]].Rows, payload) + } + return false, nil + } + + for group.next < len(group.plans) && !group.plans[group.next].hasRemaining() { + group.next++ + } + if group.next >= len(group.plans) { + return false, nil + } + plan := group.plans[group.next] + if plan.matchesValue(entryValue) && plan.take() { + shard.spill.buckets[bucketID].setTombstone(rid) + shard.spill.stats.recordMatch(len(entryValue), true) + if removedTotal != nil { + *removedTotal = *removedTotal + 1 + } + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) + results[group.indices[group.next]].Rows = append(results[group.indices[group.next]].Rows, payload) + if !plan.hasRemaining() { + group.next++ + remaining-- + if remaining <= 0 { + return true, nil + } + } + } + return false, nil + }) + if err != nil { + return err + } + } + return nil } func newRemovalPlan(removeAll bool) *removalPlan { @@ -1901,81 +2863,31 @@ func (rp *removalPlan) matchesValue(value []byte) bool { return bytes.Equal(value, rp.matchValue) } -type iterationGroup struct { - key []byte - rows [][]byte -} - -func bytesToStableString(b []byte) string { - if len(b) == 0 { - return "" - } - return string(b) -} -func (hs *hashShard) iterateUnsafe(fn func(key []byte, rows [][]byte) error) error { +func (hs *hashShard) iterateUnsafe(fn func(key []byte, row []byte) error) error { if fn == nil { return nil } if !hs.iterating { return moerr.NewInternalErrorNoCtx("shard iteration context required") } - groups := make(map[string]*iterationGroup, len(hs.inMemory)) - for _, bucket := range hs.inMemory { - for _, entry := range bucket.entries { - keyBytes := entry.keyBytes() - keyStr := bytesToStableString(keyBytes) - group, ok := groups[keyStr] - if !ok { - group = &iterationGroup{ - key: keyBytes, - rows: make([][]byte, 0, 1), - } - groups[keyStr] = group - } - group.rows = append(group.rows, entry.valueBytes()) + if hs.mem != nil { + if err := hs.mem.forEach(func(entry *memEntry) error { + return fn(entry.keyBytes(), entry.valueBytes()) + }); err != nil { + return err } } - - var scratch []byte - for _, part := range hs.spills { - for hash, pointers := range part.index { - _ = hash - for _, ptr := range pointers { - need := int(ptr.keyLen + ptr.valueLen) - if cap(scratch) < need { - scratch = make([]byte, need) - } - buf := scratch[:need] - n, err := part.file.ReadAt(buf, ptr.offset) - if err != nil && err != io.EOF { - return err - } - if n != len(buf) { - return io.ErrUnexpectedEOF - } - keyCopy := make([]byte, ptr.keyLen) - copy(keyCopy, buf[:ptr.keyLen]) - keyStr := string(keyCopy) - group, ok := groups[keyStr] - if !ok { - group = &iterationGroup{ - key: keyCopy, - rows: make([][]byte, 0, 1), - } - groups[keyStr] = group - } - valueCopy := make([]byte, ptr.valueLen) - copy(valueCopy, buf[ptr.keyLen:ptr.keyLen+ptr.valueLen]) - group.rows = append(group.rows, valueCopy) - } - } + if hs.spill == nil { + return nil } - - for keyStr, group := range groups { - if err := fn(group.key, group.rows); err != nil { + var scratch []byte + for bucketID := uint32(0); bucketID < hs.spill.bucketCount; bucketID++ { + err := hs.spill.forEachEntry(bucketID, &scratch, func(key []byte, value []byte) error { + return fn(key, value) + }) + if err != nil { return err } - delete(groups, keyStr) } return nil } diff --git a/pkg/frontend/databranchutils/branch_hashmap_test.go b/pkg/frontend/databranchutils/branch_hashmap_test.go index 911a2ba4b3dec..c6e132d54d1e0 100644 --- a/pkg/frontend/databranchutils/branch_hashmap_test.go +++ b/pkg/frontend/databranchutils/branch_hashmap_test.go @@ -741,21 +741,19 @@ func TestBranchHashmapForEach(t *testing.T) { collected := make(map[int64][]string) err = bhIface.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(key []byte, row []byte) error { tuple, _, err := bhIface.DecodeRow(key) require.NoError(t, err) require.Len(t, tuple, 1) keyVal, ok := tuple[0].(int64) require.True(t, ok) - for _, rowBytes := range rows { - rowTuple, _, err := bhIface.DecodeRow(rowBytes) - require.NoError(t, err) - require.Len(t, rowTuple, 2) - valueBytes, ok := rowTuple[1].([]byte) - require.True(t, ok) - collected[keyVal] = append(collected[keyVal], string(valueBytes)) - } + rowTuple, _, err := bhIface.DecodeRow(row) + require.NoError(t, err) + require.Len(t, rowTuple, 2) + valueBytes, ok := rowTuple[1].([]byte) + require.True(t, ok) + collected[keyVal] = append(collected[keyVal], string(valueBytes)) return nil }) }, 1) @@ -825,12 +823,12 @@ func TestBranchHashmapForEachShardPop(t *testing.T) { require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) err = bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(key []byte, _ []byte) error { keyCopy := append([]byte(nil), key...) res, err := cursor.PopByEncodedKey(keyCopy, true) require.NoError(t, err) require.True(t, res.Exists) - require.Len(t, res.Rows, len(rows)) + require.Len(t, res.Rows, 1) return nil }) }, 1) @@ -866,12 +864,12 @@ func testBranchHashmapForEachShardParallelPop(t *testing.T, parallelism int) { require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) err = bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(key []byte, _ []byte) error { keyCopy := append([]byte(nil), key...) res, err := cursor.PopByEncodedKey(keyCopy, true) require.NoError(t, err) require.True(t, res.Exists) - require.Len(t, res.Rows, len(rows)) + require.Len(t, res.Rows, 1) return nil }) }, parallelism) @@ -1011,12 +1009,12 @@ func TestBranchHashmapPopByEncodedKeyValue(t *testing.T) { removedValue string ) err = bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { - if len(rows) < 2 || len(keyCopy) > 0 { + return cursor.ForEach(func(key []byte, row []byte) error { + if len(row) == 0 || len(keyCopy) > 0 { return nil } keyCopy = append([]byte(nil), key...) - valueCopy = append([]byte(nil), rows[1]...) + valueCopy = append([]byte(nil), row...) tuple, _, err := bh.DecodeRow(valueCopy) require.NoError(t, err) valueBytes, ok := tuple[1].([]byte) @@ -1071,11 +1069,11 @@ func TestBranchHashmapPopByEncodedFullValueExact(t *testing.T) { removedValue string ) err = bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(_ []byte, rows [][]byte) error { - if len(rows) == 0 || len(valueCopy) > 0 { + return cursor.ForEach(func(_ []byte, row []byte) error { + if len(row) == 0 || len(valueCopy) > 0 { return nil } - valueCopy = append([]byte(nil), rows[0]...) + valueCopy = append([]byte(nil), row...) tuple, _, err := bh.DecodeRow(valueCopy) require.NoError(t, err) valueBytes, ok := tuple[1].([]byte) @@ -1509,8 +1507,7 @@ func collectInt64EncodedKeys(t *testing.T, bh BranchHashmap) map[int64][]byte { result := make(map[int64][]byte) err := bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { - _ = rows + return cursor.ForEach(func(key []byte, _ []byte) error { tuple, _, err := bh.DecodeRow(key) require.NoError(t, err) require.Len(t, tuple, 1) @@ -1710,7 +1707,7 @@ func BenchmarkForEachShardParallel(b *testing.B) { for i := 0; i < b.N; i++ { err := bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(_ []byte, _ []byte) error { return nil }) }, 1) @@ -1727,7 +1724,7 @@ func BenchmarkForEachShardParallel(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { err = bh.ForEachShardParallel(func(cursor ShardCursor) error { - return cursor.ForEach(func(key []byte, rows [][]byte) error { + return cursor.ForEach(func(_ []byte, _ []byte) error { return nil }) }, -1) From b50a2ec0061e2b2b486fb0a1de0266a112be3da1 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Fri, 30 Jan 2026 19:04:15 +0800 Subject: [PATCH 06/23] alloctor with throttler for data branch --- pkg/common/rscthrottler/resource_throttler.go | 16 ++ pkg/frontend/data_branch.go | 118 +++++----- .../databranchutils/branch_hashmap.go | 215 ++++++++++++++++++ 3 files changed, 296 insertions(+), 53 deletions(-) diff --git a/pkg/common/rscthrottler/resource_throttler.go b/pkg/common/rscthrottler/resource_throttler.go index 9b8741430fcec..a5f3e57f7189d 100644 --- a/pkg/common/rscthrottler/resource_throttler.go +++ b/pkg/common/rscthrottler/resource_throttler.go @@ -363,3 +363,19 @@ func AcquirePolicyForCNFlushS3( return defaultAcquirePolicy(throttler, ask) } + +func AcquirePolicyForDataBranch( + throttler *memThrottler, + ask int64, +) (int64, bool) { + + total := int64(throttler.actualTotalMemory.Load()) + if total > 0 && throttler.limitRate > 0 { + used := throttler.rss.Load() + ask + if float64(used) > float64(total)*throttler.limitRate { + return 0, false + } + } + + return defaultAcquirePolicy(throttler, ask) +} diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 4e5258a191462..4552ea52c2306 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -38,6 +38,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/common/malloc" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/common/rscthrottler" moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/bytejson" @@ -71,61 +72,70 @@ const ( diffUpdate = "UPDATE" ) -const branchHashmapMemoryLimit = 500 * 200 * mpool.MB +const dataBranchHashmapLimitRate = 0.8 type branchHashmapAllocator struct { - upstream malloc.Allocator - max uint64 - inUse atomic.Uint64 + upstream malloc.Allocator + throttler rscthrottler.RSCThrottler } type branchHashmapDeallocator struct { - upstream malloc.Deallocator - inUse *atomic.Uint64 - size uint64 + upstream malloc.Deallocator + throttler rscthrottler.RSCThrottler + size uint64 } -func newBranchHashmapAllocator(max uint64) *branchHashmapAllocator { +func newBranchHashmapAllocator(limitRate float64) *branchHashmapAllocator { + throttler := rscthrottler.NewMemThrottler( + "DataBranchHashmap", + limitRate, + rscthrottler.WithAcquirePolicy(rscthrottler.AcquirePolicyForDataBranch), + ) return &branchHashmapAllocator{ - upstream: malloc.GetDefault(nil), - max: max, + upstream: malloc.GetDefault(nil), + throttler: throttler, } } -func (a *branchHashmapAllocator) Allocate(size uint64, hints malloc.Hints) ([]byte, malloc.Deallocator, error) { - for { - cur := a.inUse.Load() - next := cur + size - if next > a.max { - // Treat limit as a spill signal, not an error. +func (a *branchHashmapAllocator) Allocate( + size uint64, + hints malloc.Hints, +) ([]byte, malloc.Deallocator, error) { + + if size == 0 { + return nil, nil, nil + } + if a.throttler != nil { + if _, ok := a.throttler.Acquire(int64(size)); !ok { return nil, nil, nil } - if !a.inUse.CompareAndSwap(cur, next) { - continue - } - buf, dec, err := a.upstream.Allocate(size, hints) - if err != nil { - a.inUse.Add(^uint64(size - 1)) - return nil, nil, err + } + buf, dec, err := a.upstream.Allocate(size, hints) + if err != nil { + if a.throttler != nil { + a.throttler.Release(int64(size)) } - if buf == nil { - a.inUse.Add(^uint64(size - 1)) - return nil, nil, nil + return nil, nil, err + } + if buf == nil { + if a.throttler != nil { + a.throttler.Release(int64(size)) } - return buf, &branchHashmapDeallocator{ - upstream: dec, - inUse: &a.inUse, - size: size, - }, nil + return nil, nil, nil } + return buf, &branchHashmapDeallocator{ + upstream: dec, + throttler: a.throttler, + size: size, + }, nil } func (d *branchHashmapDeallocator) Deallocate() { if d.upstream != nil { d.upstream.Deallocate() } - if d.size > 0 && d.inUse != nil { - d.inUse.Add(^uint64(d.size - 1)) + if d.throttler != nil && d.size > 0 { + d.throttler.Release(int64(d.size)) } } @@ -3468,7 +3478,6 @@ func findDeleteAndUpdateBat( tBat2 *batch.Batch updateBat *batch.Batch updateDeleteBat *batch.Batch - checkRet []databranchutils.GetResult ) send := func(bwk batchWithKind) error { @@ -3515,8 +3524,8 @@ func findDeleteAndUpdateBat( // merge inserts and deletes on the tar // this deletes is not on the lca if tBat1.RowCount() > 0 { - if _, err2 = dataHashmap.PopByVectors( - []*vector.Vector{tBat1.Vecs[0]}, false, + if _, err2 = dataHashmap.PopByVectorsStream( + []*vector.Vector{tBat1.Vecs[0]}, false, nil, ); err2 != nil { return err2 } @@ -3526,14 +3535,11 @@ func findDeleteAndUpdateBat( // find update if dBat.RowCount() > 0 { tBat2 = tblStuff.retPool.acquireRetBatch(tblStuff, false) - if checkRet, err2 = dataHashmap.PopByVectors( + seen := make([]bool, dBat.RowCount()) + if _, err2 = dataHashmap.PopByVectorsStream( []*vector.Vector{dBat.Vecs[tblStuff.def.pkColIdx]}, false, - ); err2 != nil { - return err2 - } - - for i, check := range checkRet { - if check.Exists { + func(idx int, _ []byte, row []byte) error { + seen[idx] = true // delete on lca and insert into tar ==> update if updateBat == nil { updateBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) @@ -3542,12 +3548,12 @@ func findDeleteAndUpdateBat( updateDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) } - if tuple, _, err2 = dataHashmap.DecodeRow(check.Rows[0]); err2 != nil { + if tuple, _, err2 = dataHashmap.DecodeRow(row); err2 != nil { return err2 } if expandUpdate { - if err2 = updateDeleteBat.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { + if err2 = updateDeleteBat.UnionOne(dBat, int64(idx), ses.proc.Mp()); err2 != nil { return err2 } } @@ -3555,12 +3561,19 @@ func findDeleteAndUpdateBat( if err2 = appendTupleToBat(ses, updateBat, tuple, tblStuff); err2 != nil { return err2 } + return nil + }, + ); err2 != nil { + return err2 + } - } else { - // delete on lca - if err2 = tBat2.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { - return err2 - } + for i := 0; i < dBat.RowCount(); i++ { + if seen[i] { + continue + } + // delete on lca + if err2 = tBat2.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { + return err2 } } @@ -3609,7 +3622,7 @@ func findDeleteAndUpdateBat( return nil - }, -1); err != nil { + }, 2); err != nil { return } @@ -4353,8 +4366,7 @@ func buildHashmapForTable( } }() - // Share one bounded allocator so both hashmaps spill instead of erroring. - sharedAllocator := newBranchHashmapAllocator(branchHashmapMemoryLimit) + sharedAllocator := newBranchHashmapAllocator(dataBranchHashmapLimitRate) if dataHashmap, err = databranchutils.NewBranchHashmap( databranchutils.WithBranchHashmapAllocator(sharedAllocator), ); err != nil { diff --git a/pkg/frontend/databranchutils/branch_hashmap.go b/pkg/frontend/databranchutils/branch_hashmap.go index 34edcddfc1757..c5daa3c8224c0 100644 --- a/pkg/frontend/databranchutils/branch_hashmap.go +++ b/pkg/frontend/databranchutils/branch_hashmap.go @@ -55,6 +55,11 @@ type BranchHashmap interface { // When removeAll is false, only a single row is removed. Returned rows are // detached copies because the underlying entries have been removed. PopByVectors(keyVecs []*vector.Vector, removeAll bool) ([]GetResult, error) + // PopByVectorsStream removes rows like PopByVectors but streams each matched + // row to the callback. The callback receives the original key row index plus + // the encoded key/value; the slices are detached copies and safe to keep. + // The returned integer counts removed rows. + PopByVectorsStream(keyVecs []*vector.Vector, removeAll bool, fn func(idx int, key []byte, row []byte) error) (int, error) // PopByEncodedKey removes rows using a pre-encoded key such as one obtained // from ForEachShardParallel. It mirrors PopByVectors semantics. PopByEncodedKey(encodedKey []byte, removeAll bool) (GetResult, error) @@ -465,6 +470,108 @@ func (bh *branchHashmap) PopByVectors(keyVecs []*vector.Vector, removeAll bool) return bh.lookupByVectors(keyVecs, &removeAll) } +func (bh *branchHashmap) PopByVectorsStream(keyVecs []*vector.Vector, removeAll bool, fn func(idx int, key []byte, row []byte) error) (int, error) { + if len(keyVecs) == 0 { + return 0, nil + } + + rowCount := keyVecs[0].Length() + + bh.metaMu.RLock() + if bh.closed { + bh.metaMu.RUnlock() + return 0, moerr.NewInternalErrorNoCtx("branchHashmap is closed") + } + keyTypes := bh.keyTypes + shardCount := bh.shardCount + bh.metaMu.RUnlock() + + if len(keyTypes) == 0 { + return 0, nil + } + if len(keyVecs) != len(keyTypes) { + return 0, moerr.NewInvalidInputNoCtxf("expected %d key vectors, got %d", len(keyTypes), len(keyVecs)) + } + for i := 1; i < len(keyVecs); i++ { + if keyVecs[i].Length() != rowCount { + return 0, moerr.NewInvalidInputNoCtxf("key vector length mismatch at column %d", i) + } + } + for i, vec := range keyVecs { + if *vec.GetType() != keyTypes[i] { + return 0, moerr.NewInvalidInputNoCtxf("key vector type mismatch at column %d", i) + } + } + + keyIndexes := make([]int, len(keyVecs)) + for i := range keyVecs { + keyIndexes[i] = i + } + + packer := bh.getPacker() + defer bh.putPacker(packer) + probesByShard := make(map[*hashShard][]*keyProbe, shardCount) + for idx := 0; idx < rowCount; idx++ { + packer.Reset() + if err := encodeRow(packer, keyVecs, keyIndexes, idx); err != nil { + return 0, err + } + keyBytes := packer.Bytes() + keyCopy := make([]byte, len(keyBytes)) + copy(keyCopy, keyBytes) + hash := hashKey(keyCopy) + shard := bh.shards[int(hash%uint64(shardCount))] + probe := &keyProbe{ + idx: idx, + key: keyCopy, + keyStr: string(keyCopy), + hash: hash, + plan: newRemovalPlan(removeAll), + } + probesByShard[shard] = append(probesByShard[shard], probe) + } + + var totalRemoved int64 + collectValues := fn != nil + for shard, probes := range probesByShard { + if shard == nil { + continue + } + shard.lock() + var removedTotal int64 + for _, probe := range probes { + rows, removedBytes, removedCount := shard.mem.collect(probe.hash, probe.key, probe.plan, true, collectValues) + if removedBytes > 0 { + shard.memInUse -= removedBytes + } + if removedCount > 0 { + removedTotal += int64(removedCount) + } + if collectValues { + for _, row := range rows { + if err := fn(probe.idx, probe.key, row); err != nil { + shard.unlock() + return int(totalRemoved), err + } + } + } + } + if shard.spill != nil { + if err := collectSpillPopStream(shard, probes, removeAll, fn, &removedTotal, collectValues); err != nil { + shard.unlock() + return int(totalRemoved), err + } + } + if removedTotal > 0 { + atomic.AddInt64(&shard.items, -removedTotal) + totalRemoved += removedTotal + } + shard.unlock() + } + + return int(totalRemoved), nil +} + func (bh *branchHashmap) lookupByVectors(keyVecs []*vector.Vector, removeAll *bool) ([]GetResult, error) { if len(keyVecs) == 0 { return nil, nil @@ -2809,6 +2916,114 @@ func collectSpillPop(shard *hashShard, probes []*keyProbe, results []GetResult, return nil } +func collectSpillPopStream(shard *hashShard, probes []*keyProbe, removeAll bool, fn func(idx int, key []byte, row []byte) error, removedTotal *int64, collectValues bool) error { + buckets := make(map[uint32][]*keyProbe, len(probes)) + seenKeys := map[string]struct{}{} + for _, probe := range probes { + if probe.plan == nil || !probe.plan.hasRemaining() { + continue + } + if removeAll { + if _, ok := seenKeys[probe.keyStr]; ok { + continue + } + seenKeys[probe.keyStr] = struct{}{} + } + bucketID := shard.spill.bucketID(probe.hash) + buckets[bucketID] = append(buckets[bucketID], probe) + } + + var scratch []byte + for bucketID, bucketProbes := range buckets { + if len(bucketProbes) == 0 { + continue + } + shard.spill.stats.recordProbe(scanReasonPop, len(bucketProbes), 1) + groupsByHash := make(map[uint64]map[string]*probeGroup, len(bucketProbes)) + remaining := 0 + for _, probe := range bucketProbes { + groups, ok := groupsByHash[probe.hash] + if !ok { + groups = make(map[string]*probeGroup, 1) + groupsByHash[probe.hash] = groups + } + group, ok := groups[probe.keyStr] + if !ok { + group = &probeGroup{} + groups[probe.keyStr] = group + } + group.indices = append(group.indices, probe.idx) + group.plans = append(group.plans, probe.plan) + if !removeAll && probe.plan.hasRemaining() { + remaining++ + } + } + + err := shard.spill.scanBucket(bucketID, scanReasonPop, &scratch, func(entryHash uint64, entryKey []byte, entryValue []byte, rid uint64) (bool, error) { + groups := groupsByHash[entryHash] + if len(groups) == 0 { + return false, nil + } + group := groups[string(entryKey)] + if group == nil { + return false, nil + } + if removeAll { + plan := group.plans[0] + if plan.matchesValue(entryValue) && plan.take() { + shard.spill.buckets[bucketID].setTombstone(rid) + shard.spill.stats.recordMatch(len(entryValue), true) + if removedTotal != nil { + *removedTotal = *removedTotal + 1 + } + if collectValues { + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) + if err := fn(group.indices[0], entryKey, payload); err != nil { + return true, err + } + } + } + return false, nil + } + + for group.next < len(group.plans) && !group.plans[group.next].hasRemaining() { + group.next++ + } + if group.next >= len(group.plans) { + return false, nil + } + plan := group.plans[group.next] + if plan.matchesValue(entryValue) && plan.take() { + shard.spill.buckets[bucketID].setTombstone(rid) + shard.spill.stats.recordMatch(len(entryValue), true) + if removedTotal != nil { + *removedTotal = *removedTotal + 1 + } + if collectValues { + payload := make([]byte, len(entryValue)) + copy(payload, entryValue) + if err := fn(group.indices[group.next], entryKey, payload); err != nil { + return true, err + } + } + if !plan.hasRemaining() { + group.next++ + remaining-- + if remaining <= 0 { + return true, nil + } + } + } + return false, nil + }) + if err != nil { + return err + } + } + return nil +} + func newRemovalPlan(removeAll bool) *removalPlan { if removeAll { return &removalPlan{remaining: -1} From cfa09c0ca27e516333215dd51c45b1684984f021 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Sun, 1 Feb 2026 22:09:11 +0800 Subject: [PATCH 07/23] restrict the memory peak when handle deletes on lca --- pkg/frontend/data_branch.go | 325 +++++++++++------- .../databranchutils/branch_hashmap.go | 11 + 2 files changed, 221 insertions(+), 115 deletions(-) diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 4552ea52c2306..8d46a3d477a87 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -97,6 +97,13 @@ func newBranchHashmapAllocator(limitRate float64) *branchHashmapAllocator { } } +func (a *branchHashmapAllocator) Available() int64 { + if a == nil || a.throttler == nil { + return 0 + } + return a.throttler.Available() +} + func (a *branchHashmapAllocator) Allocate( size uint64, hints malloc.Hints, @@ -156,8 +163,11 @@ const ( ) const ( - maxSqlBatchCnt = objectio.BlockMaxRows * 10 - maxSqlBatchSize = mpool.MB * 32 + maxSqlBatchCnt = objectio.BlockMaxRows * 10 + maxSqlBatchSize = mpool.MB * 32 + defaultRowBytes = int64(128) + tombstoneRowMult = int64(3) + tombstoneRowDiv = int64(2) ) func acquireBuffer(pool *sync.Pool) *bytes.Buffer { @@ -209,7 +219,9 @@ type tableStuff struct { pkKind int } - worker *ants.Pool + worker *ants.Pool + hashmapAllocator *branchHashmapAllocator + maxTombstoneBatchCnt int retPool *retBatchList @@ -2779,6 +2791,7 @@ func getTableStuff( return &bytes.Buffer{} }, } + tblStuff.hashmapAllocator = newBranchHashmapAllocator(dataBranchHashmapLimitRate) return @@ -3013,13 +3026,13 @@ func hashDiff( }() if baseDataHashmap, baseTombstoneHashmap, err = buildHashmapForTable( - ctx, ses.proc.Mp(), dagInfo.lcaType, tblStuff, baseHandle, + ctx, ses.proc.Mp(), dagInfo.lcaType, &tblStuff, baseHandle, ); err != nil { return } if tarDataHashmap, tarTombstoneHashmap, err = buildHashmapForTable( - ctx, ses.proc.Mp(), dagInfo.lcaType, tblStuff, tarHandle, + ctx, ses.proc.Mp(), dagInfo.lcaType, &tblStuff, tarHandle, ); err != nil { return } @@ -3469,15 +3482,16 @@ func findDeleteAndUpdateBat( dataHashmap, tombstoneHashmap databranchutils.BranchHashmap, ) (err error) { + maxTombstoneBatchCnt := tblStuff.maxTombstoneBatchCnt + if maxTombstoneBatchCnt <= 0 { + maxTombstoneBatchCnt = maxSqlBatchCnt + } + if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { var ( - err2 error - tuple types.Tuple - dBat *batch.Batch - tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) - tBat2 *batch.Batch - updateBat *batch.Batch - updateDeleteBat *batch.Batch + err2 error + tuple types.Tuple + tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) ) send := func(bwk batchWithKind) error { @@ -3490,139 +3504,181 @@ func findDeleteAndUpdateBat( } } - if err2 = cursor.ForEach(func(key []byte, _ []byte) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: + processBatch := func(tombBat *batch.Batch) error { + if tombBat.RowCount() == 0 { + tblStuff.retPool.releaseRetBatch(tombBat, true) + return nil } - if tuple, _, err2 = tombstoneHashmap.DecodeRow(key); err2 != nil { + dBat, err2 := handleDelsOnLCA( + ctx, ses, bh, tombBat, tblStuff, branchTS.ToTimestamp(), + ) + if err2 != nil { + tblStuff.retPool.releaseRetBatch(tombBat, true) return err2 } - if err2 = vector.AppendAny(tBat1.Vecs[0], tuple[0], false, ses.proc.Mp()); err2 != nil { - return err2 + + // merge inserts and deletes on the tar + // this deletes is not on the lca + if tombBat.RowCount() > 0 { + if _, err2 = dataHashmap.PopByVectorsStream( + []*vector.Vector{tombBat.Vecs[0]}, false, nil, + ); err2 != nil { + tblStuff.retPool.releaseRetBatch(tombBat, true) + tblStuff.retPool.releaseRetBatch(dBat, false) + return err2 + } + tblStuff.retPool.releaseRetBatch(tombBat, true) } - tBat1.SetRowCount(tBat1.Vecs[0].Length()) - return nil - }); err2 != nil { - return err2 - } + // find update + if dBat.RowCount() > 0 { + tBat2 := tblStuff.retPool.acquireRetBatch(tblStuff, false) + seen := make([]bool, dBat.RowCount()) + var updateBat *batch.Batch + var updateDeleteBat *batch.Batch + if _, err2 = dataHashmap.PopByVectorsStream( + []*vector.Vector{dBat.Vecs[tblStuff.def.pkColIdx]}, false, + func(idx int, _ []byte, row []byte) error { + seen[idx] = true + // delete on lca and insert into tar ==> update + if updateBat == nil { + updateBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } + if expandUpdate && updateDeleteBat == nil { + updateDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } - if tBat1.RowCount() == 0 { - tblStuff.retPool.releaseRetBatch(tBat1, true) - return nil - } + if tuple, _, err2 = dataHashmap.DecodeRow(row); err2 != nil { + return err2 + } - if dBat, err2 = handleDelsOnLCA( - ctx, ses, bh, tBat1, tblStuff, branchTS.ToTimestamp(), - ); err2 != nil { - return err2 - } + if expandUpdate { + if err2 = updateDeleteBat.UnionOne(dBat, int64(idx), ses.proc.Mp()); err2 != nil { + return err2 + } + } - // merge inserts and deletes on the tar - // this deletes is not on the lca - if tBat1.RowCount() > 0 { - if _, err2 = dataHashmap.PopByVectorsStream( - []*vector.Vector{tBat1.Vecs[0]}, false, nil, - ); err2 != nil { - return err2 - } - tblStuff.retPool.releaseRetBatch(tBat1, true) - } - - // find update - if dBat.RowCount() > 0 { - tBat2 = tblStuff.retPool.acquireRetBatch(tblStuff, false) - seen := make([]bool, dBat.RowCount()) - if _, err2 = dataHashmap.PopByVectorsStream( - []*vector.Vector{dBat.Vecs[tblStuff.def.pkColIdx]}, false, - func(idx int, _ []byte, row []byte) error { - seen[idx] = true - // delete on lca and insert into tar ==> update - if updateBat == nil { - updateBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + if err2 = appendTupleToBat(ses, updateBat, tuple, tblStuff); err2 != nil { + return err2 + } + return nil + }, + ); err2 != nil { + tblStuff.retPool.releaseRetBatch(dBat, false) + tblStuff.retPool.releaseRetBatch(tBat2, false) + if updateBat != nil { + tblStuff.retPool.releaseRetBatch(updateBat, false) } - if expandUpdate && updateDeleteBat == nil { - updateDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + if updateDeleteBat != nil { + tblStuff.retPool.releaseRetBatch(updateDeleteBat, false) } + return err2 + } - if tuple, _, err2 = dataHashmap.DecodeRow(row); err2 != nil { - return err2 + for i := 0; i < dBat.RowCount(); i++ { + if seen[i] { + continue } - - if expandUpdate { - if err2 = updateDeleteBat.UnionOne(dBat, int64(idx), ses.proc.Mp()); err2 != nil { - return err2 + // delete on lca + if err2 = tBat2.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { + tblStuff.retPool.releaseRetBatch(dBat, false) + tblStuff.retPool.releaseRetBatch(tBat2, false) + if updateBat != nil { + tblStuff.retPool.releaseRetBatch(updateBat, false) + } + if updateDeleteBat != nil { + tblStuff.retPool.releaseRetBatch(updateDeleteBat, false) } - } - - if err2 = appendTupleToBat(ses, updateBat, tuple, tblStuff); err2 != nil { return err2 } - return nil - }, - ); err2 != nil { - return err2 - } - - for i := 0; i < dBat.RowCount(); i++ { - if seen[i] { - continue } - // delete on lca - if err2 = tBat2.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { - return err2 - } - } - tblStuff.retPool.releaseRetBatch(dBat, false) - tBat2.SetRowCount(tBat2.Vecs[0].Length()) + tblStuff.retPool.releaseRetBatch(dBat, false) + tBat2.SetRowCount(tBat2.Vecs[0].Length()) - if updateBat != nil { - updateBat.SetRowCount(updateBat.Vecs[0].Length()) - if expandUpdate { - if updateDeleteBat != nil { - updateDeleteBat.SetRowCount(updateDeleteBat.Vecs[0].Length()) + if updateBat != nil { + updateBat.SetRowCount(updateBat.Vecs[0].Length()) + if expandUpdate { + if updateDeleteBat != nil { + updateDeleteBat.SetRowCount(updateDeleteBat.Vecs[0].Length()) + if err2 = send(batchWithKind{ + name: tblName, + batch: updateDeleteBat, + kind: diffDelete, + }); err2 != nil { + return err2 + } + } if err2 = send(batchWithKind{ name: tblName, - batch: updateDeleteBat, - kind: diffDelete, + batch: updateBat, + kind: diffInsert, + }); err2 != nil { + return err2 + } + } else { + if err2 = send(batchWithKind{ + name: tblName, + batch: updateBat, + kind: diffUpdate, }); err2 != nil { return err2 } - } - if err2 = send(batchWithKind{ - name: tblName, - batch: updateBat, - kind: diffInsert, - }); err2 != nil { - return err2 - } - } else { - if err2 = send(batchWithKind{ - name: tblName, - batch: updateBat, - kind: diffUpdate, - }); err2 != nil { - return err2 } } + + if err2 = send(batchWithKind{ + name: tblName, + batch: tBat2, + kind: diffDelete, + }); err2 != nil { + return err2 + } + return nil } - if err2 = send(batchWithKind{ - name: tblName, - batch: tBat2, - kind: diffDelete, - }); err2 != nil { + tblStuff.retPool.releaseRetBatch(dBat, false) + return nil + } + + if err2 = cursor.ForEach(func(key []byte, _ []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if tuple, _, err2 = tombstoneHashmap.DecodeRow(key); err2 != nil { + return err2 + } + if err2 = vector.AppendAny(tBat1.Vecs[0], tuple[0], false, ses.proc.Mp()); err2 != nil { return err2 } + + tBat1.SetRowCount(tBat1.Vecs[0].Length()) + if tBat1.RowCount() >= maxTombstoneBatchCnt { + tombBat := tBat1 + tBat1 = nil + if err2 = processBatch(tombBat); err2 != nil { + return err2 + } + tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) + } + return nil + }); err2 != nil { + if tBat1 != nil { + tblStuff.retPool.releaseRetBatch(tBat1, true) + } + return err2 } + if tBat1 != nil { + return processBatch(tBat1) + } return nil - }, 2); err != nil { + }, -1); err != nil { return } @@ -4339,7 +4395,7 @@ func buildHashmapForTable( ctx context.Context, mp *mpool.MPool, lcaType int, - tblStuff tableStuff, + tblStuff *tableStuff, handles []engine.ChangesHandle, ) ( dataHashmap databranchutils.BranchHashmap, @@ -4352,6 +4408,8 @@ func buildHashmapForTable( dataBat *batch.Batch tombstoneBat *batch.Batch wg sync.WaitGroup + totalRows int64 + totalBytes int64 ) defer func() { @@ -4366,15 +4424,14 @@ func buildHashmapForTable( } }() - sharedAllocator := newBranchHashmapAllocator(dataBranchHashmapLimitRate) if dataHashmap, err = databranchutils.NewBranchHashmap( - databranchutils.WithBranchHashmapAllocator(sharedAllocator), + databranchutils.WithBranchHashmapAllocator(tblStuff.hashmapAllocator), ); err != nil { return } if tombstoneHashmap, err = databranchutils.NewBranchHashmap( - databranchutils.WithBranchHashmapAllocator(sharedAllocator), + databranchutils.WithBranchHashmapAllocator(tblStuff.hashmapAllocator), ); err != nil { return } @@ -4438,6 +4495,11 @@ func buildHashmapForTable( break } + if dataBat != nil && dataBat.RowCount() > 0 { + totalRows += int64(dataBat.RowCount()) + totalBytes += int64(dataBat.Size()) + } + if atomicErr.Load() != nil { err = atomicErr.Load().(error) return @@ -4469,6 +4531,39 @@ func buildHashmapForTable( return } + if tombstoneHashmap.ItemCount() == 0 && dataHashmap.ItemCount() == 0 { + return + } + + if tblStuff.maxTombstoneBatchCnt == 0 { + rowBytes := defaultRowBytes + if totalRows > 0 { + rowBytes = totalBytes / totalRows + if rowBytes <= 0 { + rowBytes = defaultRowBytes + } + } + rowBytes = rowBytes * tombstoneRowMult / tombstoneRowDiv + + available := tblStuff.hashmapAllocator.Available() / 3 + + shardCount := 0 + if tombstoneHashmap != nil { + shardCount = tombstoneHashmap.ShardCount() + } else if dataHashmap != nil { + shardCount = dataHashmap.ShardCount() + } + + maxByMem := int(available / int64(shardCount) / rowBytes) + if maxByMem < 1 { + maxByMem = 1 + } else if maxByMem > maxSqlBatchCnt { + maxByMem = maxSqlBatchCnt + } + + tblStuff.maxTombstoneBatchCnt = maxByMem + } + if tblStuff.def.pkKind == fakeKind { return } diff --git a/pkg/frontend/databranchutils/branch_hashmap.go b/pkg/frontend/databranchutils/branch_hashmap.go index c5daa3c8224c0..1f27a22cc3ff3 100644 --- a/pkg/frontend/databranchutils/branch_hashmap.go +++ b/pkg/frontend/databranchutils/branch_hashmap.go @@ -91,6 +91,8 @@ type BranchHashmap interface { Migrate(keyCols []int, parallelism int) (BranchHashmap, error) // ItemCount reports the number of rows currently stored in the hashmap. ItemCount() int64 + // ShardCount reports the number of shards in the hashmap. + ShardCount() int // DecodeRow turns the encoded row emitted by Put/Get/Pop/ForEach back into a // tuple of column values in the same order that was originally supplied. DecodeRow(data []byte) (types.Tuple, []types.Type, error) @@ -1066,6 +1068,15 @@ func (bh *branchHashmap) ItemCount() int64 { return total } +func (bh *branchHashmap) ShardCount() int { + bh.metaMu.RLock() + defer bh.metaMu.RUnlock() + if bh.closed { + return 0 + } + return len(bh.shards) +} + type shardCursor struct { shard *hashShard } From 2e9d850d2462e1a5630a885c15795d37140ebfe9 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 26 Feb 2026 10:49:19 +0800 Subject: [PATCH 08/23] feat(data-branch): add diff output summary and strengthen diff tests # Conflicts: # pkg/sql/parsers/dialect/mysql/mysql_sql.go --- pkg/frontend/data_branch.go | 106 ++++++++++++++- pkg/sql/parsers/dialect/mysql/keywords.go | 1 + pkg/sql/parsers/dialect/mysql/mysql_sql.y | 9 +- .../parsers/dialect/mysql/mysql_sql_test.go | 20 +++ pkg/sql/parsers/tree/data_branch.go | 1 + pkg/sql/parsers/tree/data_branch_test.go | 2 +- pkg/tests/dml/dml_test.go | 125 ++++++++++++++++++ 7 files changed, 261 insertions(+), 3 deletions(-) diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 8d46a3d477a87..b7f655b1bf528 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -51,6 +51,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/objectio/mergeutil" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" "github.com/matrixorigin/matrixone/pkg/txn/client" @@ -72,6 +73,12 @@ const ( diffUpdate = "UPDATE" ) +const ( + diffSideUnknown = iota + diffSideTarget + diffSideBase +) + const dataBranchHashmapLimitRate = 0.8 type branchHashmapAllocator struct { @@ -231,6 +238,7 @@ type tableStuff struct { type batchWithKind struct { name string kind string + side int batch *batch.Batch } @@ -1705,6 +1713,74 @@ func satisfyDiffOutputOpt( } mrs.AddRow([]any{cnt}) + } else if stmt.OutputOpt.Summary { + var ( + targetInsertCnt int64 + targetDeleteCnt int64 + targetUpdateCnt int64 + baseInsertCnt int64 + baseDeleteCnt int64 + baseUpdateCnt int64 + ) + + for wrapped := range retCh { + if first != nil { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + if ctx.Err() != nil { + first = ctx.Err() + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + var ( + targetMetric *int64 + baseMetric *int64 + ) + + switch wrapped.kind { + case diffInsert: + targetMetric = &targetInsertCnt + baseMetric = &baseInsertCnt + case diffDelete: + targetMetric = &targetDeleteCnt + baseMetric = &baseDeleteCnt + case diffUpdate: + targetMetric = &targetUpdateCnt + baseMetric = &baseUpdateCnt + default: + first = moerr.NewInternalErrorNoCtxf("unknown diff kind %q", wrapped.kind) + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + cnt := int64(wrapped.batch.RowCount()) + switch wrapped.side { + case diffSideTarget: + *targetMetric += cnt + case diffSideBase: + *baseMetric += cnt + default: + first = moerr.NewInternalErrorNoCtxf("unknown diff side for summary, kind=%q, table=%q", wrapped.kind, wrapped.name) + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + } + + if first != nil { + return first + } + + mrs.AddRow([]any{"INSERTED", targetInsertCnt, baseInsertCnt}) + mrs.AddRow([]any{"DELETED", targetDeleteCnt, baseDeleteCnt}) + mrs.AddRow([]any{"UPDATED", targetUpdateCnt, baseUpdateCnt}) + } else if len(stmt.OutputOpt.DirPath) != 0 { var ( insertCnt int @@ -2376,6 +2452,18 @@ func buildOutputSchema( showCols = append(showCols, nCol) } + } else if stmt.OutputOpt.Summary { + targetName := tree.StringWithOpts(&stmt.TargetTable, dialect.MYSQL, tree.WithSingleQuoteString()) + baseName := tree.StringWithOpts(&stmt.BaseTable, dialect.MYSQL, tree.WithSingleQuoteString()) + + showCols = append(showCols, &MysqlColumn{}, &MysqlColumn{}, &MysqlColumn{}) + showCols[0].SetName("metric") + showCols[0].SetColumnType(defines.MYSQL_TYPE_VARCHAR) + showCols[1].SetName(targetName) + showCols[1].SetColumnType(defines.MYSQL_TYPE_LONGLONG) + showCols[2].SetName(baseName) + showCols[2].SetColumnType(defines.MYSQL_TYPE_LONGLONG) + } else if stmt.OutputOpt.Count { // count(*) of diff rows showCols = append(showCols, &MysqlColumn{}) @@ -3081,6 +3169,7 @@ func hashDiffIfHasLCA( ) handleBaseDeleteAndUpdates := func(wrapped batchWithKind) error { + wrapped.side = diffSideBase if err2 := mergeutil.SortColumnsByIndex( wrapped.batch.Vecs, tblStuff.def.pkColIdx, ses.proc.Mp(), ); err2 != nil { @@ -3096,6 +3185,7 @@ func hashDiffIfHasLCA( } handleTarDeleteAndUpdates := func(wrapped batchWithKind) (err2 error) { + wrapped.side = diffSideTarget if len(baseUpdateBatches) == 0 && len(baseDeleteBatches) == 0 { // no need to check conflict if stop, e := emitBatch(emit, wrapped, false, tblStuff.retPool); e != nil { @@ -3288,6 +3378,12 @@ func hashDiffIfHasLCA( if err3 := findDeleteAndUpdateBat( newCtx, ses, bh, tblStuff, name, + func() int { + if forBase { + return diffSideBase + } + return diffSideTarget + }(), tmpCh, branchTS, copt.expandUpdate, hashmap1, hashmap2, ); err3 != nil { atomicErr.Store(err3) @@ -3477,7 +3573,7 @@ func compareRowInWrappedBatches( func findDeleteAndUpdateBat( ctx context.Context, ses *Session, bh BackgroundExec, - tblStuff tableStuff, tblName string, tmpCh chan batchWithKind, branchTS types.TS, + tblStuff tableStuff, tblName string, side int, tmpCh chan batchWithKind, branchTS types.TS, expandUpdate bool, dataHashmap, tombstoneHashmap databranchutils.BranchHashmap, ) (err error) { @@ -3604,6 +3700,7 @@ func findDeleteAndUpdateBat( updateDeleteBat.SetRowCount(updateDeleteBat.Vecs[0].Length()) if err2 = send(batchWithKind{ name: tblName, + side: side, batch: updateDeleteBat, kind: diffDelete, }); err2 != nil { @@ -3612,6 +3709,7 @@ func findDeleteAndUpdateBat( } if err2 = send(batchWithKind{ name: tblName, + side: side, batch: updateBat, kind: diffInsert, }); err2 != nil { @@ -3620,6 +3718,7 @@ func findDeleteAndUpdateBat( } else { if err2 = send(batchWithKind{ name: tblName, + side: side, batch: updateBat, kind: diffUpdate, }); err2 != nil { @@ -3630,6 +3729,7 @@ func findDeleteAndUpdateBat( if err2 = send(batchWithKind{ name: tblName, + side: side, batch: tBat2, kind: diffDelete, }); err2 != nil { @@ -3883,6 +3983,7 @@ func diffDataHelper( batch: baseDeleteBat, kind: diffDelete, name: tblStuff.baseRel.GetTableName(), + side: diffSideBase, }, false, tblStuff.retPool); err3 != nil { return err3 } else if stop { @@ -3894,6 +3995,7 @@ func diffDataHelper( batch: tarBat, kind: diffInsert, name: tblStuff.tarRel.GetTableName(), + side: diffSideTarget, }, false, tblStuff.retPool); err3 != nil { return err3 } else if stop { @@ -3904,6 +4006,7 @@ func diffDataHelper( batch: baseBat, kind: diffInsert, name: tblStuff.baseRel.GetTableName(), + side: diffSideBase, }, false, tblStuff.retPool); err3 != nil { return err3 } else if stop { @@ -3960,6 +4063,7 @@ func diffDataHelper( batch: bat, kind: diffInsert, name: tblStuff.baseRel.GetTableName(), + side: diffSideBase, }, false, tblStuff.retPool); err3 != nil { return err3 } else if stop { diff --git a/pkg/sql/parsers/dialect/mysql/keywords.go b/pkg/sql/parsers/dialect/mysql/keywords.go index 45775f8cc734e..8812c1ca5fcd6 100644 --- a/pkg/sql/parsers/dialect/mysql/keywords.go +++ b/pkg/sql/parsers/dialect/mysql/keywords.go @@ -113,6 +113,7 @@ func init() { "subject": SUBJECT, "subpartition": SUBPARTITION, "subpartitions": SUBPARTITIONS, + "summary": SUMMARY, "snapshot": SNAPSHOT, "snapshots": SNAPSHOTS, "sysdate": SYSDATE, diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql.y b/pkg/sql/parsers/dialect/mysql/mysql_sql.y index 32f0afa1f3d2b..50054c1afafbe 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql.y +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql.y @@ -365,7 +365,7 @@ import ( %token EXTENSION %token RETENTION PERIOD %token CLONE BRANCH LOG REVERT REBASE DIFF -%token CONFLICT CONFLICT_FAIL CONFLICT_SKIP CONFLICT_ACCEPT OUTPUT +%token CONFLICT CONFLICT_FAIL CONFLICT_SKIP CONFLICT_ACCEPT OUTPUT SUMMARY // Sequence %token INCREMENT CYCLE MINVALUE @@ -8276,6 +8276,12 @@ diff_output_opt: Count: true, } } + | OUTPUT SUMMARY + { + $$ = &tree.DiffOutputOpt { + Summary: true, + } + } conflict_opt: %prec EMPTY @@ -13251,6 +13257,7 @@ non_reserved_keyword: | OPEN | OPTION | OUTPUT +| SUMMARY | PACK_KEYS | PARTIAL | PARTITIONS diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go b/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go index 029ff96e500a5..36186bb5adfdc 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql_test.go @@ -83,6 +83,26 @@ func TestOriginSQL(t *testing.T) { } } +func TestDataBranchDiffOutputModes(t *testing.T) { + stmt, err := ParseOne(context.TODO(), `data branch diff t1{snapshot="sp1"} against t2{snapshot="sp2"} output summary`, 1) + require.NoError(t, err) + + diffStmt, ok := stmt.(*tree.DataBranchDiff) + require.True(t, ok) + require.NotNil(t, diffStmt.OutputOpt) + require.True(t, diffStmt.OutputOpt.Summary) + require.False(t, diffStmt.OutputOpt.Count) + + stmt, err = ParseOne(context.TODO(), "data branch diff t1 against t2 output count", 1) + require.NoError(t, err) + + diffStmt, ok = stmt.(*tree.DataBranchDiff) + require.True(t, ok) + require.NotNil(t, diffStmt.OutputOpt) + require.False(t, diffStmt.OutputOpt.Summary) + require.True(t, diffStmt.OutputOpt.Count) +} + var ( partitionSQL = struct { input string diff --git a/pkg/sql/parsers/tree/data_branch.go b/pkg/sql/parsers/tree/data_branch.go index 02bc9ed76dbc1..527abe20baec6 100644 --- a/pkg/sql/parsers/tree/data_branch.go +++ b/pkg/sql/parsers/tree/data_branch.go @@ -297,6 +297,7 @@ type DiffOutputOpt struct { As TableName Limit *int64 Count bool + Summary bool DirPath string } diff --git a/pkg/sql/parsers/tree/data_branch_test.go b/pkg/sql/parsers/tree/data_branch_test.go index 3c658084accfe..ac06f13dde88a 100644 --- a/pkg/sql/parsers/tree/data_branch_test.go +++ b/pkg/sql/parsers/tree/data_branch_test.go @@ -127,7 +127,7 @@ func TestDataBranchDiffLifecycle(t *testing.T) { stmt.TargetTable.ObjectName = Identifier("target") stmt.BaseTable.ObjectName = Identifier("base") - stmt.OutputOpt = &DiffOutputOpt{Count: true} + stmt.OutputOpt = &DiffOutputOpt{Count: true, Summary: true} stmt.reset() require.Equal(t, Identifier(""), stmt.TargetTable.ObjectName) require.Nil(t, stmt.OutputOpt) diff --git a/pkg/tests/dml/dml_test.go b/pkg/tests/dml/dml_test.go index e708350d889cc..5d1c463b93d5d 100644 --- a/pkg/tests/dml/dml_test.go +++ b/pkg/tests/dml/dml_test.go @@ -173,6 +173,9 @@ func TestDataBranchDiffAsFile(t *testing.T) { t.Log("diff output limit with large base workload still returns subset of full diff") runDiffOutputLimitLargeBase(t, ctx, sqlDB) + t.Log("diff output summary validates complex snapshot and branch divergence scenarios") + runDiffOutputSummaryComplex(t, ctx, sqlDB) + t.Log("diff output to stage and load via datalink") runDiffOutputToStage(t, ctx, sqlDB) }) @@ -696,6 +699,66 @@ func runDiffOutputLimitLargeBase(t *testing.T, parentCtx context.Context, db *sq limitQuery(len(fullRows) * 20 / 100) } +func runDiffOutputSummaryComplex(t *testing.T, parentCtx context.Context, db *sql.DB) { + t.Helper() + + ctx, cancel := context.WithTimeout(parentCtx, time.Second*150) + defer cancel() + + dbName := testutils.GetDatabaseName(t) + seed := "summary_seed" + left := "summary_left" + right := "summary_right" + standaloneBase := "summary_standalone_base" + standaloneTarget := "summary_standalone_target" + + execSQLDB(t, ctx, db, fmt.Sprintf("create database `%s`", dbName)) + defer func() { + execSQLDB(t, ctx, db, "use mo_catalog") + execSQLDB(t, ctx, db, fmt.Sprintf("drop database if exists `%s`", dbName)) + }() + execSQLDB(t, ctx, db, fmt.Sprintf("use `%s`", dbName)) + + // Divergent branch scenario to verify both target/base columns can be non-zero per metric. + execSQLDB(t, ctx, db, fmt.Sprintf("create table %s (id int primary key, val int)", seed)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into %s values (1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)", seed)) + execSQLDB(t, ctx, db, fmt.Sprintf("data branch create table %s from %s", left, seed)) + execSQLDB(t, ctx, db, fmt.Sprintf("data branch create table %s from %s", right, seed)) + + execSQLDB(t, ctx, db, fmt.Sprintf("update %s set val = val + 100 where id in (1, 2)", left)) + execSQLDB(t, ctx, db, fmt.Sprintf("delete from %s where id = 4", left)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into %s values (7, 70)", left)) + + execSQLDB(t, ctx, db, fmt.Sprintf("update %s set val = val + 200 where id in (2, 3)", right)) + execSQLDB(t, ctx, db, fmt.Sprintf("delete from %s where id = 1", right)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into %s values (8, 80)", right)) + + leftSummaryStmt := fmt.Sprintf("data branch diff %s against %s output summary", left, right) + leftCountStmt := fmt.Sprintf("data branch diff %s against %s output count", left, right) + leftSummary := fetchDiffSummaryMetrics(t, ctx, db, leftSummaryStmt) + assertSummaryMetrics(t, leftSummary, [2]int64{1, 1}, [2]int64{1, 1}, [2]int64{2, 2}) + assertSummaryMatchesCount(t, leftSummary, fetchDiffCount(t, ctx, db, leftCountStmt)) + + rightSummaryStmt := fmt.Sprintf("data branch diff %s against %s output summary", right, left) + rightCountStmt := fmt.Sprintf("data branch diff %s against %s output count", right, left) + rightSummary := fetchDiffSummaryMetrics(t, ctx, db, rightSummaryStmt) + assertSummaryMetrics(t, rightSummary, [2]int64{1, 1}, [2]int64{1, 1}, [2]int64{2, 2}) + assertSummaryMatchesCount(t, rightSummary, fetchDiffCount(t, ctx, db, rightCountStmt)) + + // Non-branch baseline to ensure summary/count consistency still holds without branch lineage. + execSQLDB(t, ctx, db, fmt.Sprintf("create table %s (id int primary key, val int, note varchar(16))", standaloneBase)) + execSQLDB(t, ctx, db, fmt.Sprintf("create table %s (id int primary key, val int, note varchar(16))", standaloneTarget)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into %s values (1, 10, 'seed'), (2, 20, 'seed'), (3, 30, 'seed'), (4, 40, 'seed')", standaloneBase)) + execSQLDB(t, ctx, db, fmt.Sprintf("insert into %s values (1, 110, 'updated'), (2, 20, 'seed'), (5, 500, 'added'), (6, 600, 'added')", standaloneTarget)) + + standaloneSummaryStmt := fmt.Sprintf("data branch diff %s against %s output summary", standaloneTarget, standaloneBase) + standaloneCountStmt := fmt.Sprintf("data branch diff %s against %s output count", standaloneTarget, standaloneBase) + standaloneSummary := fetchDiffSummaryMetrics(t, ctx, db, standaloneSummaryStmt) + standaloneCount := fetchDiffCount(t, ctx, db, standaloneCountStmt) + assertSummaryMatchesCount(t, standaloneSummary, standaloneCount) + require.Greater(t, standaloneCount, int64(0), "standalone summary/count should report non-zero diff rows") +} + func runDiffOutputToStage(t *testing.T, parentCtx context.Context, db *sql.DB) { t.Helper() @@ -1072,6 +1135,68 @@ func fetchDiffRowsAsStrings(t *testing.T, ctx context.Context, db *sql.DB, stmt return result } +func fetchDiffSummaryMetrics(t *testing.T, ctx context.Context, db *sql.DB, stmt string) map[string][2]int64 { + t.Helper() + + rows, err := db.QueryContext(ctx, stmt) + require.NoErrorf(t, err, "sql: %s", stmt) + defer rows.Close() + + cols, err := rows.Columns() + require.NoError(t, err) + require.Equalf(t, 3, len(cols), "summary result should have 3 columns: %s", stmt) + + result := make(map[string][2]int64, 3) + for rows.Next() { + var ( + metric string + left int64 + right int64 + ) + require.NoError(t, rows.Scan(&metric, &left, &right)) + result[strings.ToUpper(metric)] = [2]int64{left, right} + } + require.NoErrorf(t, rows.Err(), "sql: %s", stmt) + require.Lenf(t, result, 3, "summary should include 3 metrics: %s", stmt) + require.Containsf(t, result, "INSERTED", "summary missing INSERTED: %s", stmt) + require.Containsf(t, result, "DELETED", "summary missing DELETED: %s", stmt) + require.Containsf(t, result, "UPDATED", "summary missing UPDATED: %s", stmt) + return result +} + +func fetchDiffCount(t *testing.T, ctx context.Context, db *sql.DB, stmt string) int64 { + t.Helper() + + var cnt int64 + err := db.QueryRowContext(ctx, stmt).Scan(&cnt) + require.NoErrorf(t, err, "sql: %s", stmt) + return cnt +} + +func assertSummaryMetrics( + t *testing.T, + summary map[string][2]int64, + inserted [2]int64, + deleted [2]int64, + updated [2]int64, +) { + t.Helper() + + require.Equal(t, inserted, summary["INSERTED"], "INSERTED metric mismatch") + require.Equal(t, deleted, summary["DELETED"], "DELETED metric mismatch") + require.Equal(t, updated, summary["UPDATED"], "UPDATED metric mismatch") +} + +func assertSummaryMatchesCount(t *testing.T, summary map[string][2]int64, count int64) { + t.Helper() + + total := int64(0) + for _, metric := range summary { + total += metric[0] + metric[1] + } + require.Equal(t, total, count, "summary total should match output count") +} + func execDiffAndFetchFile(t *testing.T, ctx context.Context, db *sql.DB, stmt string) string { t.Helper() From 2193d2208e1d117b2bf3e5c79d6484ffaea33102 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 26 Feb 2026 10:50:16 +0800 Subject: [PATCH 09/23] test(bvt): add data branch diff output summary cases --- .../cases/git4data/branch/diff/diff_8.result | 173 ++++++++++++++++++ .../cases/git4data/branch/diff/diff_8.sql | 136 ++++++++++++++ 2 files changed, 309 insertions(+) create mode 100644 test/distributed/cases/git4data/branch/diff/diff_8.result create mode 100644 test/distributed/cases/git4data/branch/diff/diff_8.sql diff --git a/test/distributed/cases/git4data/branch/diff/diff_8.result b/test/distributed/cases/git4data/branch/diff/diff_8.result new file mode 100644 index 0000000000000..67766139dcda7 --- /dev/null +++ b/test/distributed/cases/git4data/branch/diff/diff_8.result @@ -0,0 +1,173 @@ +drop database if exists test_summary; +create database test_summary; +use test_summary; +create table c1(a int primary key, b int); +insert into c1 values (1, 10), (2, 20); +drop snapshot if exists c1_sp0; +create snapshot c1_sp0 for table test_summary c1; +insert into c1 values (3, 30), (4, 40); +drop snapshot if exists c1_sp1; +create snapshot c1_sp1 for table test_summary c1; +data branch diff c1{snapshot="c1_sp1"} against c1{snapshot="c1_sp0"} output summary; +➤ metric[12,0,0] ¦ c1{snapshot = 'c1_sp1'}[-5,0,0] ¦ c1{snapshot = 'c1_sp0'}[-5,0,0] 𝄀 +INSERTED ¦ 2 ¦ 0 𝄀 +DELETED ¦ 0 ¦ 0 𝄀 +UPDATED ¦ 0 ¦ 0 +data branch diff c1{snapshot="c1_sp1"} against c1{snapshot="c1_sp0"} output count; +➤ COUNT(*)[-5,0,0] 𝄀 +2 +data branch diff c1{snapshot="c1_sp1"} against c1{snapshot="c1_sp0"}; +➤ diff c1 against c1[12,0,0] ¦ flag[12,0,0] ¦ a[4,0,0] ¦ b[4,0,0] 𝄀 +c1 ¦ INSERT ¦ 3 ¦ 30 𝄀 +c1 ¦ INSERT ¦ 4 ¦ 40 +data branch diff c1{snapshot="c1_sp0"} against c1{snapshot="c1_sp1"} output summary; +➤ metric[12,0,0] ¦ c1{snapshot = 'c1_sp0'}[-5,0,0] ¦ c1{snapshot = 'c1_sp1'}[-5,0,0] 𝄀 +INSERTED ¦ 0 ¦ 2 𝄀 +DELETED ¦ 0 ¦ 0 𝄀 +UPDATED ¦ 0 ¦ 0 +data branch diff c1{snapshot="c1_sp0"} against c1{snapshot="c1_sp1"} output count; +➤ COUNT(*)[-5,0,0] 𝄀 +2 +drop snapshot c1_sp0; +drop snapshot c1_sp1; +drop table c1; +create table c2(a int primary key, b int); +insert into c2 values (1, 10), (2, 20), (3, 30); +drop snapshot if exists c2_sp0; +create snapshot c2_sp0 for table test_summary c2; +update c2 set b = 200 where a = 2; +delete from c2 where a = 3; +insert into c2 values (4, 40); +drop snapshot if exists c2_sp1; +create snapshot c2_sp1 for table test_summary c2; +data branch diff c2{snapshot="c2_sp1"} against c2{snapshot="c2_sp0"} output summary; +➤ metric[12,0,0] ¦ c2{snapshot = 'c2_sp1'}[-5,0,0] ¦ c2{snapshot = 'c2_sp0'}[-5,0,0] 𝄀 +INSERTED ¦ 1 ¦ 0 𝄀 +DELETED ¦ 1 ¦ 0 𝄀 +UPDATED ¦ 1 ¦ 0 +data branch diff c2{snapshot="c2_sp1"} against c2{snapshot="c2_sp0"} output count; +➤ COUNT(*)[-5,0,0] 𝄀 +3 +data branch diff c2{snapshot="c2_sp1"} against c2{snapshot="c2_sp0"}; +➤ diff c2 against c2[12,0,0] ¦ flag[12,0,0] ¦ a[4,0,0] ¦ b[4,0,0] 𝄀 +c2 ¦ UPDATE ¦ 2 ¦ 200 𝄀 +c2 ¦ DELETE ¦ 3 ¦ 30 𝄀 +c2 ¦ INSERT ¦ 4 ¦ 40 +drop snapshot c2_sp0; +drop snapshot c2_sp1; +drop table c2; +create table c3_base(a int primary key, b int); +insert into c3_base values (1, 1), (2, 2), (3, 3); +drop snapshot if exists c3_sp0; +create snapshot c3_sp0 for table test_summary c3_base; +data branch create table c3_tar from c3_base{snapshot="c3_sp0"}; +update c3_tar set b = b + 100 where a = 1; +delete from c3_tar where a = 2; +insert into c3_tar values (4, 4); +data branch diff c3_tar against c3_base{snapshot="c3_sp0"} output summary; +➤ metric[12,0,0] ¦ c3_tar[-5,0,0] ¦ c3_base{snapshot = 'c3_sp0'}[-5,0,0] 𝄀 +INSERTED ¦ 1 ¦ 0 𝄀 +DELETED ¦ 1 ¦ 0 𝄀 +UPDATED ¦ 1 ¦ 0 +data branch diff c3_tar against c3_base{snapshot="c3_sp0"} output count; +➤ COUNT(*)[-5,0,0] 𝄀 +3 +data branch diff c3_tar against c3_base{snapshot="c3_sp0"}; +➤ diff c3_tar against c3_base[12,0,0] ¦ flag[12,0,0] ¦ a[4,0,0] ¦ b[4,0,0] 𝄀 +c3_tar ¦ UPDATE ¦ 1 ¦ 101 𝄀 +c3_tar ¦ DELETE ¦ 2 ¦ 2 𝄀 +c3_tar ¦ INSERT ¦ 4 ¦ 4 +data branch diff c3_base{snapshot="c3_sp0"} against c3_tar output summary; +➤ metric[12,0,0] ¦ c3_base{snapshot = 'c3_sp0'}[-5,0,0] ¦ c3_tar[-5,0,0] 𝄀 +INSERTED ¦ 0 ¦ 1 𝄀 +DELETED ¦ 0 ¦ 1 𝄀 +UPDATED ¦ 0 ¦ 1 +data branch diff c3_base{snapshot="c3_sp0"} against c3_tar output count; +➤ COUNT(*)[-5,0,0] 𝄀 +3 +drop snapshot c3_sp0; +drop table c3_base; +drop table c3_tar; +create table c4_base(a int, b int); +insert into c4_base values (1, 10), (2, 20), (3, 30); +drop snapshot if exists c4_sp0; +create snapshot c4_sp0 for table test_summary c4_base; +data branch create table c4_tar from c4_base{snapshot="c4_sp0"}; +update c4_tar set b = b + 100 where a = 1; +delete from c4_tar where a = 2; +insert into c4_tar values (5, 50); +data branch diff c4_tar against c4_base{snapshot="c4_sp0"} output summary; +➤ metric[12,0,0] ¦ c4_tar[-5,0,0] ¦ c4_base{snapshot = 'c4_sp0'}[-5,0,0] 𝄀 +INSERTED ¦ 1 ¦ 0 𝄀 +DELETED ¦ 1 ¦ 0 𝄀 +UPDATED ¦ 1 ¦ 0 +data branch diff c4_tar against c4_base{snapshot="c4_sp0"} output count; +➤ COUNT(*)[-5,0,0] 𝄀 +3 +data branch diff c4_tar against c4_base{snapshot="c4_sp0"}; +➤ diff c4_tar against c4_base[12,0,0] ¦ flag[12,0,0] ¦ a[4,0,0] ¦ b[4,0,0] 𝄀 +c4_tar ¦ UPDATE ¦ 1 ¦ 110 𝄀 +c4_tar ¦ DELETE ¦ 2 ¦ 20 𝄀 +c4_tar ¦ INSERT ¦ 5 ¦ 50 +drop snapshot c4_sp0; +drop table c4_base; +drop table c4_tar; +create table c5_seed(a int primary key, b int); +insert into c5_seed values (1, 10), (2, 20), (3, 30), (4, 40); +drop snapshot if exists c5_sp0; +create snapshot c5_sp0 for table test_summary c5_seed; +data branch create table c5_left from c5_seed{snapshot="c5_sp0"}; +data branch create table c5_right from c5_seed{snapshot="c5_sp0"}; +update c5_left set b = b + 100 where a in (1, 2); +delete from c5_left where a = 4; +insert into c5_left values (5, 50); +update c5_right set b = b + 200 where a in (2, 3); +delete from c5_right where a = 1; +insert into c5_right values (6, 60); +data branch diff c5_left against c5_right output summary; +➤ metric[12,0,0] ¦ c5_left[-5,0,0] ¦ c5_right[-5,0,0] 𝄀 +INSERTED ¦ 1 ¦ 1 𝄀 +DELETED ¦ 1 ¦ 1 𝄀 +UPDATED ¦ 2 ¦ 2 +data branch diff c5_left against c5_right output count; +➤ COUNT(*)[-5,0,0] 𝄀 +8 +data branch diff c5_left against c5_right; +➤ diff c5_left against c5_right[12,0,0] ¦ flag[12,0,0] ¦ a[4,0,0] ¦ b[4,0,0] 𝄀 +c5_left ¦ UPDATE ¦ 1 ¦ 110 𝄀 +c5_right ¦ DELETE ¦ 1 ¦ 10 𝄀 +c5_left ¦ UPDATE ¦ 2 ¦ 120 𝄀 +c5_right ¦ UPDATE ¦ 2 ¦ 220 𝄀 +c5_right ¦ UPDATE ¦ 3 ¦ 230 𝄀 +c5_left ¦ DELETE ¦ 4 ¦ 40 𝄀 +c5_left ¦ INSERT ¦ 5 ¦ 50 𝄀 +c5_right ¦ INSERT ¦ 6 ¦ 60 +data branch diff c5_right against c5_left output summary; +➤ metric[12,0,0] ¦ c5_right[-5,0,0] ¦ c5_left[-5,0,0] 𝄀 +INSERTED ¦ 1 ¦ 1 𝄀 +DELETED ¦ 1 ¦ 1 𝄀 +UPDATED ¦ 2 ¦ 2 +data branch diff c5_right against c5_left output count; +➤ COUNT(*)[-5,0,0] 𝄀 +8 +drop snapshot c5_sp0; +drop table c5_seed; +drop table c5_left; +drop table c5_right; +create table c6(a int primary key, b int); +insert into c6 values (1, 1), (2, 2); +drop snapshot if exists c6_sp0; +create snapshot c6_sp0 for table test_summary c6; +update c6 set b = b + 10 where a = 1; +insert into c6 values (3, 3); +data branch diff c6 against c6{snapshot="c6_sp0"} output count; +➤ COUNT(*)[-5,0,0] 𝄀 +2 +data branch diff c6 against c6{snapshot="c6_sp0"} output summary; +➤ metric[12,0,0] ¦ c6[-5,0,0] ¦ c6{snapshot = 'c6_sp0'}[-5,0,0] 𝄀 +INSERTED ¦ 1 ¦ 0 𝄀 +DELETED ¦ 0 ¦ 0 𝄀 +UPDATED ¦ 1 ¦ 0 +drop snapshot c6_sp0; +drop table c6; +drop database test_summary; diff --git a/test/distributed/cases/git4data/branch/diff/diff_8.sql b/test/distributed/cases/git4data/branch/diff/diff_8.sql new file mode 100644 index 0000000000000..384e475f9c2bf --- /dev/null +++ b/test/distributed/cases/git4data/branch/diff/diff_8.sql @@ -0,0 +1,136 @@ +drop database if exists test_summary; +create database test_summary; +use test_summary; + +-- Case 1: Same table, different snapshots, insert-only delta. +-- Verify output summary can separate target/base counts even when table names are identical. +create table c1(a int primary key, b int); +insert into c1 values (1, 10), (2, 20); +drop snapshot if exists c1_sp0; +create snapshot c1_sp0 for table test_summary c1; +insert into c1 values (3, 30), (4, 40); +drop snapshot if exists c1_sp1; +create snapshot c1_sp1 for table test_summary c1; + +data branch diff c1{snapshot="c1_sp1"} against c1{snapshot="c1_sp0"} output summary; +data branch diff c1{snapshot="c1_sp1"} against c1{snapshot="c1_sp0"} output count; +data branch diff c1{snapshot="c1_sp1"} against c1{snapshot="c1_sp0"}; + +data branch diff c1{snapshot="c1_sp0"} against c1{snapshot="c1_sp1"} output summary; +data branch diff c1{snapshot="c1_sp0"} against c1{snapshot="c1_sp1"} output count; + +drop snapshot c1_sp0; +drop snapshot c1_sp1; +drop table c1; + +-- Case 2: Same table, different snapshots, mixed update/delete/insert on PK table. +-- Verify summary contains UPDATED and both-side metrics. +create table c2(a int primary key, b int); +insert into c2 values (1, 10), (2, 20), (3, 30); +drop snapshot if exists c2_sp0; +create snapshot c2_sp0 for table test_summary c2; + +update c2 set b = 200 where a = 2; +delete from c2 where a = 3; +insert into c2 values (4, 40); + +drop snapshot if exists c2_sp1; +create snapshot c2_sp1 for table test_summary c2; + +data branch diff c2{snapshot="c2_sp1"} against c2{snapshot="c2_sp0"} output summary; +data branch diff c2{snapshot="c2_sp1"} against c2{snapshot="c2_sp0"} output count; +data branch diff c2{snapshot="c2_sp1"} against c2{snapshot="c2_sp0"}; + +drop snapshot c2_sp0; +drop snapshot c2_sp1; +drop table c2; + +-- Case 3: Data branch created from snapshot (PK table), then changed. +-- Verify summary works with branch lineage and includes UPDATE/DELETE/INSERT style deltas. +create table c3_base(a int primary key, b int); +insert into c3_base values (1, 1), (2, 2), (3, 3); +drop snapshot if exists c3_sp0; +create snapshot c3_sp0 for table test_summary c3_base; + +data branch create table c3_tar from c3_base{snapshot="c3_sp0"}; +update c3_tar set b = b + 100 where a = 1; +delete from c3_tar where a = 2; +insert into c3_tar values (4, 4); + +data branch diff c3_tar against c3_base{snapshot="c3_sp0"} output summary; +data branch diff c3_tar against c3_base{snapshot="c3_sp0"} output count; +data branch diff c3_tar against c3_base{snapshot="c3_sp0"}; + +data branch diff c3_base{snapshot="c3_sp0"} against c3_tar output summary; +data branch diff c3_base{snapshot="c3_sp0"} against c3_tar output count; + +drop snapshot c3_sp0; +drop table c3_base; +drop table c3_tar; + +-- Case 4: Data branch on table without PK. +-- Verify summary is still stable on fake PK path. +create table c4_base(a int, b int); +insert into c4_base values (1, 10), (2, 20), (3, 30); +drop snapshot if exists c4_sp0; +create snapshot c4_sp0 for table test_summary c4_base; + +data branch create table c4_tar from c4_base{snapshot="c4_sp0"}; +update c4_tar set b = b + 100 where a = 1; +delete from c4_tar where a = 2; +insert into c4_tar values (5, 50); + +data branch diff c4_tar against c4_base{snapshot="c4_sp0"} output summary; +data branch diff c4_tar against c4_base{snapshot="c4_sp0"} output count; +data branch diff c4_tar against c4_base{snapshot="c4_sp0"}; + +drop snapshot c4_sp0; +drop table c4_base; +drop table c4_tar; + +-- Case 5: Two branches diverge from the same snapshot. +-- Verify summary target/base columns can both be non-zero in one query. +create table c5_seed(a int primary key, b int); +insert into c5_seed values (1, 10), (2, 20), (3, 30), (4, 40); +drop snapshot if exists c5_sp0; +create snapshot c5_sp0 for table test_summary c5_seed; + +data branch create table c5_left from c5_seed{snapshot="c5_sp0"}; +data branch create table c5_right from c5_seed{snapshot="c5_sp0"}; + +update c5_left set b = b + 100 where a in (1, 2); +delete from c5_left where a = 4; +insert into c5_left values (5, 50); + +update c5_right set b = b + 200 where a in (2, 3); +delete from c5_right where a = 1; +insert into c5_right values (6, 60); + +data branch diff c5_left against c5_right output summary; +data branch diff c5_left against c5_right output count; +data branch diff c5_left against c5_right; + +data branch diff c5_right against c5_left output summary; +data branch diff c5_right against c5_left output count; + +drop snapshot c5_sp0; +drop table c5_seed; +drop table c5_left; +drop table c5_right; + +-- Case 6: Compatibility regression check for old syntax. +-- Verify output count remains usable after introducing output summary. +create table c6(a int primary key, b int); +insert into c6 values (1, 1), (2, 2); +drop snapshot if exists c6_sp0; +create snapshot c6_sp0 for table test_summary c6; +update c6 set b = b + 10 where a = 1; +insert into c6 values (3, 3); + +data branch diff c6 against c6{snapshot="c6_sp0"} output count; +data branch diff c6 against c6{snapshot="c6_sp0"} output summary; + +drop snapshot c6_sp0; +drop table c6; + +drop database test_summary; From 3ae43b23e7f4125e069fde5a59bfcc4f9d98fe88 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Fri, 27 Feb 2026 13:08:06 +0800 Subject: [PATCH 10/23] refactor(frontend): split data_branch into hashdiff/output/helpers/types --- pkg/frontend/data_branch.go | 4205 +------------------------- pkg/frontend/data_branch_hashdiff.go | 1528 ++++++++++ pkg/frontend/data_branch_helpers.go | 534 ++++ pkg/frontend/data_branch_output.go | 1746 +++++++++++ pkg/frontend/data_branch_types.go | 148 + 5 files changed, 4087 insertions(+), 4074 deletions(-) create mode 100644 pkg/frontend/data_branch_hashdiff.go create mode 100644 pkg/frontend/data_branch_helpers.go create mode 100644 pkg/frontend/data_branch_output.go create mode 100644 pkg/frontend/data_branch_types.go diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index b7f655b1bf528..2c0c1c07efbfc 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -17,14 +17,7 @@ package frontend import ( "bytes" "context" - "encoding/hex" - "encoding/json" - "errors" "fmt" - "io" - "os" - "path" - "path/filepath" "regexp" "runtime" "slices" @@ -32,26 +25,19 @@ import ( "strings" "sync" "sync/atomic" - "time" "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/malloc" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/common/rscthrottler" - moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" "github.com/matrixorigin/matrixone/pkg/container/batch" - "github.com/matrixorigin/matrixone/pkg/container/bytejson" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/defines" - "github.com/matrixorigin/matrixone/pkg/fileservice" "github.com/matrixorigin/matrixone/pkg/frontend/databranchutils" - "github.com/matrixorigin/matrixone/pkg/objectio" - "github.com/matrixorigin/matrixone/pkg/objectio/mergeutil" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" - "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" "github.com/matrixorigin/matrixone/pkg/txn/client" @@ -61,37 +47,6 @@ import ( "github.com/panjf2000/ants/v2" ) -const ( - fakeKind = iota - normalKind - compositeKind -) - -const ( - diffInsert = "INSERT" - diffDelete = "DELETE" - diffUpdate = "UPDATE" -) - -const ( - diffSideUnknown = iota - diffSideTarget - diffSideBase -) - -const dataBranchHashmapLimitRate = 0.8 - -type branchHashmapAllocator struct { - upstream malloc.Allocator - throttler rscthrottler.RSCThrottler -} - -type branchHashmapDeallocator struct { - upstream malloc.Deallocator - throttler rscthrottler.RSCThrottler - size uint64 -} - func newBranchHashmapAllocator(limitRate float64) *branchHashmapAllocator { throttler := rscthrottler.NewMemThrottler( "DataBranchHashmap", @@ -160,140 +115,6 @@ func (d *branchHashmapDeallocator) As(target malloc.Trait) bool { return false } -var diffTempTableSeq uint64 - -const ( - lcaEmpty = iota - lcaOther - lcaLeft - lcaRight -) - -const ( - maxSqlBatchCnt = objectio.BlockMaxRows * 10 - maxSqlBatchSize = mpool.MB * 32 - defaultRowBytes = int64(128) - tombstoneRowMult = int64(3) - tombstoneRowDiv = int64(2) -) - -func acquireBuffer(pool *sync.Pool) *bytes.Buffer { - if pool == nil { - return &bytes.Buffer{} - } - buf := pool.Get().(*bytes.Buffer) - buf.Reset() - return buf -} - -func releaseBuffer(pool *sync.Pool, buf *bytes.Buffer) { - if buf == nil { - return - } - buf.Reset() - if pool != nil { - pool.Put(buf) - } -} - -type collectRange struct { - from []types.TS - end []types.TS - rel []engine.Relation -} - -type branchMetaInfo struct { - lcaType int - lcaTableId uint64 - tarBranchTS types.TS - baseBranchTS types.TS -} - -type tableStuff struct { - tarRel engine.Relation - baseRel engine.Relation - tarSnap *plan.Snapshot - baseSnap *plan.Snapshot - - lcaRel engine.Relation - - def struct { - colNames []string // all columns - colTypes []types.Type // all columns - visibleIdxes []int - pkColIdx int - pkColIdxes []int // expanded pk columns - pkKind int - } - - worker *ants.Pool - hashmapAllocator *branchHashmapAllocator - maxTombstoneBatchCnt int - - retPool *retBatchList - - bufPool *sync.Pool -} - -type batchWithKind struct { - name string - kind string - side int - batch *batch.Batch -} - -type emitFunc func(batchWithKind) (stop bool, err error) - -func newEmitter( - ctx context.Context, stopCh <-chan struct{}, retCh chan batchWithKind, -) emitFunc { - return func(wrapped batchWithKind) (bool, error) { - select { - case <-ctx.Done(): - return false, ctx.Err() - case <-stopCh: - return true, nil - default: - } - - select { - case <-ctx.Done(): - return false, ctx.Err() - case <-stopCh: - return true, nil - case retCh <- wrapped: - return false, nil - } - } -} - -func emitBatch( - emit emitFunc, wrapped batchWithKind, forTombstone bool, pool *retBatchList, -) (bool, error) { - stop, err := emit(wrapped) - if stop || err != nil { - pool.releaseRetBatch(wrapped.batch, forTombstone) - return stop, err - } - return false, nil -} - -type retBatchList struct { - mu sync.Mutex - // 0: data - // 1: tombstone - dList []*batch.Batch - tList []*batch.Batch - - pinned map[*batch.Batch]struct{} - //debug map[*batch.Batch]retBatchDebug - - dataVecCnt int - tombVecCnt int - dataTypes []types.Type - tombstoneType types.Type -} - //type retBatchDebug struct { // acquire string // release string @@ -451,102 +272,6 @@ func (retBatchPool *retBatchList) freeAllRetBatches(mp *mpool.MPool) { } -type compositeOption struct { - conflictOpt *tree.ConflictOpt - outputSQL bool - expandUpdate bool -} - -func runSql( - ctx context.Context, ses *Session, bh BackgroundExec, sql string, - streamChan chan executor.Result, errChan chan error, -) (sqlRet executor.Result, err error) { - - useBackExec := false - trimmedLower := strings.ToLower(strings.TrimSpace(sql)) - if strings.HasPrefix(trimmedLower, "drop database") { - // Internal executor does not support DROP DATABASE (IsPublishing panics). - useBackExec = true - } else if strings.Contains(strings.ToLower(snapConditionRegex.FindString(sql)), "snapshot") { - // SQLExecutor cannot resolve snapshot by name. - useBackExec = true - } - - var exec executor.SQLExecutor - if !useBackExec { - rt := moruntime.ServiceRuntime(ses.service) - if rt == nil { - useBackExec = true - } else { - val, exist := rt.GetGlobalVariables(moruntime.InternalSQLExecutor) - if !exist { - useBackExec = true - } else { - exec = val.(executor.SQLExecutor) - } - } - } - - if useBackExec { - // export as CSV need this - // bh.(*backExec).backSes.SetMysqlResultSet(&MysqlResultSet{}) - //for range tblStuff.def.visibleIdxes { - // bh.(*backExec).backSes.mrs.AddColumn(&MysqlColumn{}) - //} - if err = bh.Exec(ctx, sql); err != nil { - return - } - if _, ok := bh.(*backExec); ok { - bh.ClearExecResultSet() - sqlRet.Mp = ses.proc.Mp() - sqlRet.Batches = bh.GetExecResultBatches() - return - } - - rs := bh.GetExecResultSet() - bh.ClearExecResultSet() - if len(rs) == 0 || rs[0] == nil { - return - } - mrs, ok := rs[0].(*MysqlResultSet) - if !ok { - return sqlRet, moerr.NewInternalError(ctx, "unexpected result set type") - } - if len(mrs.Columns) == 0 { - return - } - var bat *batch.Batch - bat, _, err = convertRowsIntoBatch(ses.proc.Mp(), mrs.Columns, mrs.Data) - if err != nil { - return sqlRet, err - } - sqlRet.Mp = ses.proc.Mp() - sqlRet.Batches = []*batch.Batch{bat} - return - } - - // we do not use the bh.Exec here, it's too slow. - // use internal sql instead. - - backSes := bh.(*backExec).backSes - - opts := executor.Options{}. - WithDisableIncrStatement(). - WithTxn(backSes.GetTxnHandler().GetTxn()). - WithKeepTxnAlive(). - WithTimeZone(ses.GetTimeZone()) - - if streamChan != nil && errChan != nil { - opts = opts.WithStreaming(streamChan, errChan) - } - - if sqlRet, err = exec.Exec(ctx, sql, opts); err != nil { - return sqlRet, err - } - - return sqlRet, nil -} - func handleDataBranch( execCtx *ExecCtx, ses *Session, @@ -1065,76 +790,26 @@ func handleBranchMerge( return diffMergeAgency(ses, execCtx, stmt) } -func tryFlushDeletesOrInserts( +func validate( ctx context.Context, ses *Session, - bh BackgroundExec, - tblStuff tableStuff, - newKind string, - newValsLen int, - newRowCnt int, - deleteByFullRow bool, - pkInfo *pkBatchInfo, - deleteCnt *int, - deletesBuf *bytes.Buffer, - insertCnt *int, - insertBuf *bytes.Buffer, - writeFile func([]byte) error, -) (err error) { - - flushDeletes := func() error { - if err = flushSqlValues( - ctx, ses, bh, tblStuff, deletesBuf, true, deleteByFullRow, pkInfo, writeFile, - ); err != nil { - return err - } - - *deleteCnt = 0 - deletesBuf.Reset() + stmt tree.Statement, +) error { + if stmt == nil { return nil } - flushInserts := func() error { - if err = flushSqlValues( - ctx, ses, bh, tblStuff, insertBuf, false, false, pkInfo, writeFile, - ); err != nil { - return err - } - - *insertCnt = 0 - insertBuf.Reset() - return nil - } + var ( + ok bool + diffStmt *tree.DataBranchDiff + ) - // if wrapped is nil, means force flush - if newKind != "" { - if newKind == diffDelete { - if deletesBuf.Len()+newValsLen >= maxSqlBatchSize || - *deleteCnt+newRowCnt >= maxSqlBatchCnt { - return flushDeletes() - } - } else { - if insertBuf.Len()+newValsLen >= maxSqlBatchSize || - *insertCnt+newRowCnt >= maxSqlBatchCnt { - if *deleteCnt > 0 { - if err = flushDeletes(); err != nil { - return err - } - } - return flushInserts() - } - } + if diffStmt, ok = stmt.(*tree.DataBranchDiff); !ok { return nil } - if *deleteCnt > 0 { - if err = flushDeletes(); err != nil { - return err - } - } - - if *insertCnt > 0 { - if err = flushInserts(); err != nil { + if diffStmt.OutputOpt != nil && len(diffStmt.OutputOpt.DirPath) > 0 { + if err := validateOutputDirPath(ctx, ses, diffStmt.OutputOpt.DirPath); err != nil { return err } } @@ -1142,2939 +817,168 @@ func tryFlushDeletesOrInserts( return nil } -type pkBatchInfo struct { - dbName string - baseTable string - deleteTable string - insertTable string - pkNames []string - visibleNames []string -} +func getTableStuff( + ctx context.Context, + ses *Session, + bh BackgroundExec, + srcTable tree.TableName, + dstTable tree.TableName, +) (tblStuff tableStuff, err error) { -func newPKBatchInfo(ctx context.Context, ses *Session, tblStuff tableStuff) *pkBatchInfo { - if tblStuff.def.pkKind == fakeKind { - return nil - } + var ( + tarTblDef *plan.TableDef + baseTblDef *plan.TableDef + ) + + defer func() { + if err == nil { + tblStuff.worker, err = ants.NewPool(runtime.NumCPU()) + } + }() - pkNames := make([]string, len(tblStuff.def.pkColIdxes)) - for i, idx := range tblStuff.def.pkColIdxes { - pkNames[i] = tblStuff.def.colNames[idx] + if tblStuff.tarRel, tblStuff.baseRel, tblStuff.tarSnap, tblStuff.baseSnap, err = getRelations( + ctx, ses, bh, srcTable, dstTable, + ); err != nil { + return } - visibleNames := make([]string, len(tblStuff.def.visibleIdxes)) - for i, idx := range tblStuff.def.visibleIdxes { - visibleNames[i] = tblStuff.def.colNames[idx] + tarTblDef = tblStuff.tarRel.GetTableDef(ctx) + baseTblDef = tblStuff.baseRel.GetTableDef(ctx) + + if !isSchemaEquivalent(tarTblDef, baseTblDef) { + err = moerr.NewInternalErrorNoCtx("the target table schema is not equivalent to the base table.") + return } - seq := atomic.AddUint64(&diffTempTableSeq, 1) - sessionTag := strings.ReplaceAll(ses.GetUUIDString(), "-", "") - return &pkBatchInfo{ - dbName: tblStuff.baseRel.GetTableDef(ctx).DbName, - baseTable: tblStuff.baseRel.GetTableName(), - deleteTable: fmt.Sprintf("__mo_diff_del_%s_%d", sessionTag, seq), - insertTable: fmt.Sprintf("__mo_diff_ins_%s_%d", sessionTag, seq), - pkNames: pkNames, - visibleNames: visibleNames, + if baseTblDef.Pkey.PkeyColName == catalog.FakePrimaryKeyColName { + tblStuff.def.pkKind = fakeKind + for i, col := range baseTblDef.Cols { + if col.Name != catalog.FakePrimaryKeyColName && col.Name != catalog.Row_ID { + tblStuff.def.pkColIdxes = append(tblStuff.def.pkColIdxes, i) + } + } + } else if baseTblDef.Pkey.CompPkeyCol != nil { + // case 2: composite pk, combined all pks columns as the PK + tblStuff.def.pkKind = compositeKind + pkNames := baseTblDef.Pkey.Names + for _, name := range pkNames { + idx := int(baseTblDef.Name2ColIndex[name]) + tblStuff.def.pkColIdxes = append(tblStuff.def.pkColIdxes, idx) + } + } else { + // normal pk + tblStuff.def.pkKind = normalKind + pkName := baseTblDef.Pkey.PkeyColName + idx := int(baseTblDef.Name2ColIndex[pkName]) + tblStuff.def.pkColIdxes = append(tblStuff.def.pkColIdxes, idx) } -} -func qualifiedTableName(dbName, tableName string) string { - return fmt.Sprintf("%s.%s", dbName, tableName) -} + tblStuff.def.pkColIdx = int(baseTblDef.Name2ColIndex[baseTblDef.Pkey.PkeyColName]) -func execSQLStatements( - ctx context.Context, - ses *Session, - bh BackgroundExec, - writeFile func([]byte) error, - stmts []string, -) error { - for _, stmt := range stmts { - if stmt == "" { + for i, col := range tarTblDef.Cols { + if col.Name == catalog.Row_ID { continue } - if writeFile != nil { - if err := writeFile([]byte(stmt + ";\n")); err != nil { - return err - } + + t := types.New(types.T(col.Typ.Id), col.Typ.Width, col.Typ.Scale) + + tblStuff.def.colNames = append(tblStuff.def.colNames, col.Name) + tblStuff.def.colTypes = append(tblStuff.def.colTypes, t) + + if col.Name == catalog.FakePrimaryKeyColName || + col.Name == catalog.CPrimaryKeyColName { continue } - ret, err := runSql(ctx, ses, bh, stmt, nil, nil) - if len(ret.Batches) > 0 && ret.Mp != nil { - ret.Close() - } - if err != nil { - return err - } - } - return nil -} -func initPKTables( - ctx context.Context, - ses *Session, - bh BackgroundExec, - pkInfo *pkBatchInfo, - writeFile func([]byte) error, -) error { - if pkInfo == nil { - return nil + tblStuff.def.visibleIdxes = append(tblStuff.def.visibleIdxes, i) } - baseTable := qualifiedTableName(pkInfo.dbName, pkInfo.baseTable) - deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) - insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) - - deleteCols := strings.Join(pkInfo.pkNames, ",") - insertCols := strings.Join(pkInfo.visibleNames, ",") - - stmts := []string{ - fmt.Sprintf("drop table if exists %s", deleteTable), - fmt.Sprintf("drop table if exists %s", insertTable), - fmt.Sprintf("create table %s as select %s from %s where 1=0", deleteTable, deleteCols, baseTable), - fmt.Sprintf("create table %s as select %s from %s where 1=0", insertTable, insertCols, baseTable), + tblStuff.retPool = &retBatchList{} + tblStuff.bufPool = &sync.Pool{ + New: func() any { + return &bytes.Buffer{} + }, } + tblStuff.hashmapAllocator = newBranchHashmapAllocator(dataBranchHashmapLimitRate) + + return - return execSQLStatements(ctx, ses, bh, writeFile, stmts) } -func dropPKTables( +func diffOnBase( ctx context.Context, ses *Session, bh BackgroundExec, - pkInfo *pkBatchInfo, - writeFile func([]byte) error, -) error { - if pkInfo == nil { - return nil - } - - deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) - insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) - - stmts := []string{ - fmt.Sprintf("drop table if exists %s", deleteTable), - fmt.Sprintf("drop table if exists %s", insertTable), - } - return execSQLStatements(ctx, ses, bh, writeFile, stmts) -} + wg *sync.WaitGroup, + dagInfo branchMetaInfo, + tblStuff tableStuff, + copt compositeOption, + emit emitFunc, +) (err error) { -type sqlValuesAppender struct { - ctx context.Context - ses *Session - bh BackgroundExec - tblStuff tableStuff - deleteByFullRow bool - pkInfo *pkBatchInfo - deleteCnt *int - deleteBuf *bytes.Buffer - insertCnt *int - insertBuf *bytes.Buffer - writeFile func([]byte) error -} + defer func() { + wg.Done() + }() -func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { var ( - targetBuf *bytes.Buffer - rowCnt *int + tarHandle []engine.ChangesHandle + baseHandle []engine.ChangesHandle ) - if kind == diffDelete { - targetBuf = sva.deleteBuf - rowCnt = sva.deleteCnt - if sva.deleteByFullRow { - newValsLen := len(rowValues) - if err := tryFlushDeletesOrInserts( - sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, - sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, - ); err != nil { - return err - } - - targetBuf.Write(rowValues) - *rowCnt++ - return nil + closeHandle := func() { + for _, h := range tarHandle { + _ = h.Close() } - } else { - targetBuf = sva.insertBuf - rowCnt = sva.insertCnt - } - - newValsLen := len(rowValues) - if targetBuf.Len() > 0 { - newValsLen++ - } - - if err := tryFlushDeletesOrInserts( - sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, - sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, - ); err != nil { - return err - } - - if targetBuf.Len() > 0 { - targetBuf.WriteString(",") + for _, h := range baseHandle { + _ = h.Close() + } + tarHandle = nil + baseHandle = nil } - targetBuf.Write(rowValues) - *rowCnt++ - return nil -} -func (sva sqlValuesAppender) flushAll() error { - return tryFlushDeletesOrInserts( - sva.ctx, sva.ses, sva.bh, sva.tblStuff, "", - 0, 0, sva.deleteByFullRow, sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, - ) -} + defer func() { + closeHandle() + }() -func writeInsertRowValues( - ses *Session, - tblStuff tableStuff, - row []any, - buf *bytes.Buffer, -) error { - buf.WriteString("(") - for i, idx := range tblStuff.def.visibleIdxes { - if err := formatValIntoString(ses, row[idx], tblStuff.def.colTypes[idx], buf); err != nil { - return err - } - if i != len(tblStuff.def.visibleIdxes)-1 { - buf.WriteString(",") - } - } - buf.WriteString(")") - - return nil -} - -func writeDeleteRowValues( - ses *Session, - tblStuff tableStuff, - row []any, - buf *bytes.Buffer, -) error { - if len(tblStuff.def.pkColIdxes) > 1 { - buf.WriteString("(") - } - for i, colIdx := range tblStuff.def.pkColIdxes { - if err := formatValIntoString(ses, row[colIdx], tblStuff.def.colTypes[colIdx], buf); err != nil { - return err - } - if i != len(tblStuff.def.pkColIdxes)-1 { - buf.WriteString(",") - } - } - if len(tblStuff.def.pkColIdxes) > 1 { - buf.WriteString(")") - } - - return nil -} - -func writeDeleteRowValuesAsTuple( - ses *Session, - tblStuff tableStuff, - row []any, - buf *bytes.Buffer, -) error { - buf.WriteString("(") - for i, colIdx := range tblStuff.def.pkColIdxes { - if err := formatValIntoString(ses, row[colIdx], tblStuff.def.colTypes[colIdx], buf); err != nil { - return err - } - if i != len(tblStuff.def.pkColIdxes)-1 { - buf.WriteString(",") - } - } - buf.WriteString(")") - return nil -} - -func writeDeleteRowSQLFull( - ctx context.Context, - ses *Session, - tblStuff tableStuff, - row []any, - buf *bytes.Buffer, -) error { - // Use NULL-aware equality and LIMIT 1 to preserve duplicate-row semantics. - buf.WriteString(fmt.Sprintf( - "delete from %s.%s where ", - tblStuff.baseRel.GetTableDef(ctx).DbName, - tblStuff.baseRel.GetTableDef(ctx).Name, - )) - for i, idx := range tblStuff.def.visibleIdxes { - if i > 0 { - buf.WriteString(" and ") - } - colName := tblStuff.def.colNames[idx] - if row[idx] == nil { - buf.WriteString(colName) - buf.WriteString(" is null") - } else { - buf.WriteString(colName) - buf.WriteString(" = ") - if err := formatValIntoString(ses, row[idx], tblStuff.def.colTypes[idx], buf); err != nil { - return err - } - } - } - buf.WriteString(" limit 1;\n") - return nil -} - -func appendBatchRowsAsSQLValues( - ctx context.Context, - ses *Session, - tblStuff tableStuff, - wrapped batchWithKind, - tmpValsBuffer *bytes.Buffer, - appender sqlValuesAppender, -) (err error) { - - //seenCols := make(map[int]struct{}, len(tblStuff.def.visibleIdxes)) - row := make([]any, len(tblStuff.def.colNames)) - - for rowIdx := range wrapped.batch.RowCount() { - if ctx.Err() != nil { - return ctx.Err() - } - - for _, colIdx := range tblStuff.def.visibleIdxes { - //seenCols[colIdx] = struct{}{} - vec := wrapped.batch.Vecs[colIdx] - if vec.GetNulls().Contains(uint64(rowIdx)) { - row[colIdx] = nil - continue - } - - switch vec.GetType().Oid { - case types.T_datetime, types.T_timestamp, types.T_decimal64, - types.T_decimal128, types.T_time: - bb := vec.GetRawBytesAt(rowIdx) - row[colIdx] = types.DecodeValue(bb, vec.GetType().Oid) - default: - if err = extractRowFromVector( - ctx, ses, vec, colIdx, row, rowIdx, false, - ); err != nil { - return - } - } - } - - //for _, pkIdx := range tblStuff.def.pkColIdxes { - // if _, ok := seenCols[pkIdx]; ok { - // continue - // } - // vec := wrapped.batch.Vecs[pkIdx] - // if vec.GetNulls().Contains(uint64(rowIdx)) { - // row[pkIdx] = nil - // continue - // } - // - // switch vec.GetType().Oid { - // case types.T_datetime, types.T_timestamp, types.T_decimal64, - // types.T_decimal128, types.T_time: - // bb := vec.GetRawBytesAt(rowIdx) - // row[pkIdx] = types.DecodeValue(bb, vec.GetType().Oid) - // default: - // if err = extractRowFromVector( - // ctx, ses, vec, pkIdx, row, rowIdx, false, - // ); err != nil { - // return - // } - // } - //} - - tmpValsBuffer.Reset() - if wrapped.kind == diffDelete { - if appender.deleteByFullRow { - if err = writeDeleteRowSQLFull(ctx, ses, tblStuff, row, tmpValsBuffer); err != nil { - return - } - } else if appender.pkInfo != nil { - if err = writeDeleteRowValuesAsTuple(ses, tblStuff, row, tmpValsBuffer); err != nil { - return - } - } else { - if err = writeDeleteRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { - return - } - } - } else { - if err = writeInsertRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { - return - } - } - - if tmpValsBuffer.Len() == 0 { - continue - } - - if err = appender.appendRow(wrapped.kind, tmpValsBuffer.Bytes()); err != nil { - return - } - } - - return nil -} - -func mergeDiffs( - ctx context.Context, - cancel context.CancelFunc, - ses *Session, - bh BackgroundExec, - stmt *tree.DataBranchMerge, - dagInfo branchMetaInfo, - tblStuff tableStuff, - retCh chan batchWithKind, -) (err error) { - - var ( - insertCnt int - deleteCnt int - - insertIntoVals = acquireBuffer(tblStuff.bufPool) - deleteFromVals = acquireBuffer(tblStuff.bufPool) - firstErr error - tmpValsBuffer = acquireBuffer(tblStuff.bufPool) - ) - - defer func() { - releaseBuffer(tblStuff.bufPool, insertIntoVals) - releaseBuffer(tblStuff.bufPool, deleteFromVals) - releaseBuffer(tblStuff.bufPool, tmpValsBuffer) - }() - - defer func() { - cancel() - }() - - appender := sqlValuesAppender{ - ctx: ctx, - ses: ses, - bh: bh, - tblStuff: tblStuff, - deleteByFullRow: tblStuff.def.pkKind == fakeKind, - pkInfo: newPKBatchInfo(ctx, ses, tblStuff), - deleteCnt: &deleteCnt, - deleteBuf: deleteFromVals, - insertCnt: &insertCnt, - insertBuf: insertIntoVals, - } - if err = initPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { - return err - } - defer func() { - if err2 := dropPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err2 != nil && err == nil { - err = err2 - } - }() - - // conflict option should be pushed down to the hash phase, - // so the batch we received is conflict-free. - for wrapped := range retCh { - - if firstErr != nil || ctx.Err() != nil { - if firstErr == nil { - firstErr = ctx.Err() - } - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - if err = appendBatchRowsAsSQLValues( - ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, - ); err != nil { - firstErr = err - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - } - - if err = appender.flushAll(); err != nil { - if firstErr == nil { - firstErr = err - } - } - - if firstErr != nil { - return firstErr - } - return -} - -func satisfyDiffOutputOpt( - ctx context.Context, - cancel context.CancelFunc, - stop func(), - ses *Session, - bh BackgroundExec, - stmt *tree.DataBranchDiff, - dagInfo branchMetaInfo, - tblStuff tableStuff, - retCh chan batchWithKind, -) (err error) { - - var ( - mrs = ses.GetMysqlResultSet() - first error - hitLimit bool - ) - - defer func() { - cancel() - }() - - if stmt.OutputOpt == nil || stmt.OutputOpt.Limit != nil { - var ( - rows = make([][]any, 0, 100) - ) - - for wrapped := range retCh { - if first != nil { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - if hitLimit { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - if ctx.Err() != nil { - first = ctx.Err() - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - for rowIdx := range wrapped.batch.RowCount() { - var ( - row = make([]any, len(tblStuff.def.visibleIdxes)+2) - ) - row[0] = wrapped.name - row[1] = wrapped.kind - - for _, colIdx := range tblStuff.def.visibleIdxes { - vec := wrapped.batch.Vecs[colIdx] - if err = extractRowFromVector( - ctx, ses, vec, colIdx+2, row, rowIdx, false, - ); err != nil { - return - } - } - - rows = append(rows, row) - if stmt.OutputOpt != nil && stmt.OutputOpt.Limit != nil && - int64(len(rows)) >= *stmt.OutputOpt.Limit { - // hit limit, cancel producers but keep draining the channel - hitLimit = true - stop() - break - } - } - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - } - - slices.SortFunc(rows, func(a, b []any) int { - for _, idx := range tblStuff.def.pkColIdxes { - if cmp := types.CompareValue( - a[idx+2], b[idx+2], - ); cmp != 0 { - return cmp - } - } - return 0 - }) - - for _, row := range rows { - mrs.AddRow(row) - } - - } else if stmt.OutputOpt.Count { - cnt := int64(0) - for wrapped := range retCh { - if first != nil { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - if ctx.Err() != nil { - first = ctx.Err() - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - cnt += int64(wrapped.batch.RowCount()) - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - } - mrs.AddRow([]any{cnt}) - - } else if stmt.OutputOpt.Summary { - var ( - targetInsertCnt int64 - targetDeleteCnt int64 - targetUpdateCnt int64 - baseInsertCnt int64 - baseDeleteCnt int64 - baseUpdateCnt int64 - ) - - for wrapped := range retCh { - if first != nil { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - if ctx.Err() != nil { - first = ctx.Err() - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - var ( - targetMetric *int64 - baseMetric *int64 - ) - - switch wrapped.kind { - case diffInsert: - targetMetric = &targetInsertCnt - baseMetric = &baseInsertCnt - case diffDelete: - targetMetric = &targetDeleteCnt - baseMetric = &baseDeleteCnt - case diffUpdate: - targetMetric = &targetUpdateCnt - baseMetric = &baseUpdateCnt - default: - first = moerr.NewInternalErrorNoCtxf("unknown diff kind %q", wrapped.kind) - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - cnt := int64(wrapped.batch.RowCount()) - switch wrapped.side { - case diffSideTarget: - *targetMetric += cnt - case diffSideBase: - *baseMetric += cnt - default: - first = moerr.NewInternalErrorNoCtxf("unknown diff side for summary, kind=%q, table=%q", wrapped.kind, wrapped.name) - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - } - - if first != nil { - return first - } - - mrs.AddRow([]any{"INSERTED", targetInsertCnt, baseInsertCnt}) - mrs.AddRow([]any{"DELETED", targetDeleteCnt, baseDeleteCnt}) - mrs.AddRow([]any{"UPDATED", targetUpdateCnt, baseUpdateCnt}) - - } else if len(stmt.OutputOpt.DirPath) != 0 { - var ( - insertCnt int - deleteCnt int - - deleteFromValsBuffer = acquireBuffer(tblStuff.bufPool) - insertIntoValsBuffer = acquireBuffer(tblStuff.bufPool) - tmpValsBuffer = acquireBuffer(tblStuff.bufPool) - - fileHint string - fullFilePath string - writeFile func([]byte) error - release func() - cleanup func() - succeeded bool - ) - - defer func() { - if !succeeded && cleanup != nil { - cleanup() - } - if release != nil { - release() - } - releaseBuffer(tblStuff.bufPool, deleteFromValsBuffer) - releaseBuffer(tblStuff.bufPool, insertIntoValsBuffer) - releaseBuffer(tblStuff.bufPool, tmpValsBuffer) - }() - - if fullFilePath, fileHint, writeFile, release, cleanup, err = prepareFSForDiffAsFile( - ctx, ses, stmt, tblStuff, - ); err != nil { - return - } - - appender := sqlValuesAppender{ - ctx: ctx, - ses: ses, - bh: bh, - tblStuff: tblStuff, - deleteByFullRow: tblStuff.def.pkKind == fakeKind, - pkInfo: newPKBatchInfo(ctx, ses, tblStuff), - deleteCnt: &deleteCnt, - deleteBuf: deleteFromValsBuffer, - insertCnt: &insertCnt, - insertBuf: insertIntoValsBuffer, - writeFile: writeFile, - } - if writeFile != nil { - // Make generated SQL runnable in one transaction. - if err = writeFile([]byte("BEGIN;\n")); err != nil { - return - } - } - if err = initPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { - return - } - - for wrapped := range retCh { - if first != nil { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - if ctx.Err() != nil { - first = ctx.Err() - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - if wrapped.name == tblStuff.tarRel.GetTableName() { - if err = appendBatchRowsAsSQLValues( - ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, - ); err != nil { - first = err - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - } else if wrapped.name == tblStuff.baseRel.GetTableName() { - if wrapped.kind == diffInsert { - wrapped.kind = diffDelete - } - if wrapped.kind == diffDelete { - if err = appendBatchRowsAsSQLValues( - ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, - ); err != nil { - first = err - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - } - } - - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - } - - if first != nil { - return first - } - - if err = appender.flushAll(); err != nil { - first = err - cancel() - } - if first == nil { - if err = dropPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { - return err - } - } - if first == nil && writeFile != nil { - if err = writeFile([]byte("COMMIT;\n")); err != nil { - return err - } - } - - succeeded = true - mrs.AddRow([]any{fullFilePath, fileHint}) - } - - if first != nil { - return first - } - if hitLimit { - return trySaveQueryResult(context.Background(), ses, mrs) - } - return trySaveQueryResult(ctx, ses, mrs) -} - -func makeFileName( - baseAtTsExpr *tree.AtTimeStamp, - tarAtTsExpr *tree.AtTimeStamp, - tblStuff tableStuff, -) string { - var ( - srcName = tblStuff.tarRel.GetTableName() - baseName = tblStuff.baseRel.GetTableName() - ) - - if baseAtTsExpr != nil { - baseName = fmt.Sprintf("%s_%s", baseName, baseAtTsExpr.SnapshotName) - } - - if tarAtTsExpr != nil { - srcName = fmt.Sprintf("%s_%s", srcName, tarAtTsExpr.SnapshotName) - } - - return fmt.Sprintf( - "diff_%s_%s_%s", - srcName, baseName, - time.Now().UTC().Format("20060102_150405"), - ) -} - -func validate( - ctx context.Context, - ses *Session, - stmt tree.Statement, -) error { - if stmt == nil { - return nil - } - - var ( - ok bool - diffStmt *tree.DataBranchDiff - ) - - if diffStmt, ok = stmt.(*tree.DataBranchDiff); !ok { - return nil - } - - if diffStmt.OutputOpt != nil && len(diffStmt.OutputOpt.DirPath) > 0 { - if err := validateOutputDirPath(ctx, ses, diffStmt.OutputOpt.DirPath); err != nil { - return err - } - } - - return nil -} - -func validateOutputDirPath(ctx context.Context, ses *Session, dirPath string) (err error) { - if len(dirPath) == 0 { - return nil - } - - var ( - stagePath string - ok bool - inputDirPath = dirPath - ) - - if stagePath, ok, err = tryDecodeStagePath(ses, dirPath); err != nil { - return - } else if ok { - dirPath = stagePath - } - - var fsPath fileservice.Path - if fsPath, err = fileservice.ParsePath(dirPath); err != nil { - return - } - - if fsPath.Service == "" { - var info os.FileInfo - if info, err = os.Stat(dirPath); err != nil { - if os.IsNotExist(err) { - return moerr.NewInvalidInputNoCtxf("output directory %s does not exist", inputDirPath) - } - return - } - if !info.IsDir() { - return moerr.NewInvalidInputNoCtxf("output directory %s is not a directory", inputDirPath) - } - return nil - } - - var ( - targetFS fileservice.FileService - targetPath string - entry *fileservice.DirEntry - ) - - if fsPath.Service == defines.SharedFileServiceName { - targetFS = getPu(ses.GetService()).FileService - targetPath = dirPath - } else { - var etlFS fileservice.ETLFileService - if etlFS, targetPath, err = fileservice.GetForETL(ctx, nil, dirPath); err != nil { - return - } - targetFS = etlFS - defer targetFS.Close(ctx) - } - - if len(strings.Trim(targetPath, "/")) == 0 { - // service root: try listing to ensure the bucket/root is reachable - for _, err = range targetFS.List(ctx, targetPath) { - if err != nil { - if moerr.IsMoErrCode(err, moerr.ErrFileNotFound) { - return moerr.NewInvalidInputNoCtxf("output directory %s does not exist", inputDirPath) - } - return err - } - // any entry means list works - break - } - return nil - } - - if entry, err = targetFS.StatFile(ctx, targetPath); err != nil { - if moerr.IsMoErrCode(err, moerr.ErrFileNotFound) { - // fallthrough to List-based directory detection - } else { - return - } - } - - // StatFile succeeded: reject if it's a file, accept if the FS can stat directories. - if entry != nil { - if !entry.IsDir { - return moerr.NewInvalidInputNoCtxf("output directory %s is not a directory", inputDirPath) - } - return nil - } - - // StatFile can't prove directory existence (common for object storage). Use parent List to - // detect the child entry and its type. - trimmedPath := strings.TrimRight(targetPath, "/") - if len(trimmedPath) == 0 { - // root of the service, treat as directory - return nil - } - parent, base := path.Split(trimmedPath) - parent = strings.TrimRight(parent, "/") - if len(base) == 0 { - // target is root - return nil - } - - for entry, err = range targetFS.List(ctx, parent) { - if err != nil { - return err - } - if entry.Name != base { - continue - } - if !entry.IsDir { - return moerr.NewInvalidInputNoCtxf("output directory %s is not a directory", inputDirPath) - } - return nil - } - - return moerr.NewInvalidInputNoCtxf("output directory %s does not exist", inputDirPath) -} - -func prepareFSForDiffAsFile( - ctx context.Context, - ses *Session, - stmt *tree.DataBranchDiff, - tblStuff tableStuff, -) ( - sqlRetPath, sqlRetHint string, - writeFile func([]byte) error, - release func(), - cleanup func(), - err error, -) { - var ( - ok bool - stagePath string - fileName string - fullFilePath string - ) - - fileName = makeFileName(stmt.BaseTable.AtTsExpr, stmt.TargetTable.AtTsExpr, tblStuff) - fileName += ".sql" - - sqlRetPath = path.Join(stmt.OutputOpt.DirPath, fileName) - - if stagePath, ok, err = tryDecodeStagePath(ses, stmt.OutputOpt.DirPath); err != nil { - return - } else if ok { - sqlRetPath = strings.Replace(sqlRetPath, "stage:/", "stage://", 1) - fullFilePath = path.Join(stagePath, fileName) - } else { - fullFilePath = path.Join(stmt.OutputOpt.DirPath, fileName) - } - - sqlRetHint = fmt.Sprintf( - "DELETE FROM %s.%s, INSERT INTO %s.%s", - tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableName(), - tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableName(), - ) - - var ( - targetFS fileservice.FileService - targetPath string - fsPath fileservice.Path - ) - - if fsPath, err = fileservice.ParsePath(fullFilePath); err != nil { - return - } - - if fsPath.Service == defines.SharedFileServiceName { - targetFS = getPu(ses.GetService()).FileService - targetPath = fullFilePath - } else { - // ensure local dir exists when using implicit local ETL path - if fsPath.Service == "" { - if mkErr := os.MkdirAll(filepath.Dir(fullFilePath), 0o755); mkErr != nil { - err = mkErr - return - } - } - - var etlFS fileservice.ETLFileService - if etlFS, targetPath, err = fileservice.GetForETL(ctx, nil, fullFilePath); err != nil { - return - } - targetFS = etlFS - } - - cleanup = func() { - _ = targetFS.Delete(context.Background(), targetPath) - } - - defer func() { - if err != nil { - if cleanup != nil { - cleanup() - } - targetFS.Close(ctx) - } - }() - - if err = targetFS.Delete(ctx, targetPath); err != nil && !moerr.IsMoErrCode(err, moerr.ErrFileNotFound) { - return - } - - if mfs, ok := targetFS.(fileservice.MutableFileService); ok { - // SQL diff needs append, so pre-create the file and return an appender. - if err = targetFS.Write(ctx, fileservice.IOVector{ - FilePath: targetPath, - Entries: []fileservice.IOEntry{ - {Size: 0, Data: []byte{}}, - }, - }); err != nil && !moerr.IsMoErrCode(err, moerr.ErrFileAlreadyExists) { - return - } - - var mut fileservice.Mutator - if mut, err = mfs.NewMutator(ctx, targetPath); err != nil { - return - } - - writeFile = func(fileContent []byte) error { - return mut.Append(ctx, fileservice.IOEntry{ - Size: int64(len(fileContent)), - Data: fileContent, - }) - } - - release = func() { - _ = mut.Close() - targetFS.Close(ctx) - } - } else { - if writeFile, release, err = newSingleWriteAppender( - ctx, tblStuff.worker, targetFS, targetPath, cleanup, - ); err != nil { - return - } - } - - return -} - -func newSingleWriteAppender( - ctx context.Context, - worker *ants.Pool, - targetFS fileservice.FileService, - targetPath string, - onError func(), -) (writeFile func([]byte) error, release func(), err error) { - pr, pw := io.Pipe() - done := make(chan error, 1) - - if worker == nil { - err = moerr.NewInternalErrorNoCtx("worker pool is nil") - return - } - - if err = worker.Submit(func() { - defer close(done) - vec := fileservice.IOVector{ - FilePath: targetPath, - Entries: []fileservice.IOEntry{ - { - ReaderForWrite: pr, - Size: -1, - }, - }, - } - if wErr := targetFS.Write(ctx, vec); wErr != nil { - _ = pr.CloseWithError(wErr) - done <- wErr - return - } - done <- pr.Close() - }); err != nil { - _ = pr.Close() - _ = pw.Close() - return - } - - writeFile = func(fileContent []byte) error { - if len(fileContent) == 0 { - return nil - } - _, err := pw.Write(fileContent) - return err - } - - release = func() { - _ = pw.Close() - if wErr := <-done; wErr != nil && onError != nil { - onError() - } - targetFS.Close(ctx) - } - - return -} - -func removeFileIgnoreError(ctx context.Context, service, filePath string) { - if len(filePath) == 0 { - return - } - - fsPath, err := fileservice.ParsePath(filePath) - if err != nil { - return - } - - var ( - targetFS fileservice.FileService - targetPath string - ) - - if fsPath.Service == defines.SharedFileServiceName { - targetFS = getPu(service).FileService - targetPath = filePath - } else { - var etlFS fileservice.ETLFileService - if etlFS, targetPath, err = fileservice.GetForETL(ctx, nil, filePath); err != nil { - return - } - targetFS = etlFS - } - - _ = targetFS.Delete(ctx, targetPath) - targetFS.Close(ctx) -} - -// if `writeFile` is not nil, the sql will be flushed down into this file, or -// the sql will be executed by bh. -func flushSqlValues( - ctx context.Context, - ses *Session, - bh BackgroundExec, - tblStuff tableStuff, - buf *bytes.Buffer, - isDeleteFrom bool, - deleteByFullRow bool, - pkInfo *pkBatchInfo, - writeFile func([]byte) error, -) (err error) { - - if buf.Len() == 0 { - return nil - } - - if isDeleteFrom && deleteByFullRow { - if writeFile != nil { - return writeFile(buf.Bytes()) - } - - statements := bytes.Split(buf.Bytes(), []byte(";\n")) - for _, stmt := range statements { - stmt = bytes.TrimSpace(stmt) - if len(stmt) == 0 { - continue - } - var ret executor.Result - ret, err = runSql(ctx, ses, bh, string(stmt)+";", nil, nil) - ret.Close() - if err != nil { - return err - } - } - return nil - } - - if pkInfo != nil { - baseTable := qualifiedTableName(pkInfo.dbName, pkInfo.baseTable) - deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) - insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) - - if isDeleteFrom { - insertStmt := fmt.Sprintf("insert into %s values %s", deleteTable, buf.String()) - pkExpr := pkInfo.pkNames[0] - if len(pkInfo.pkNames) > 1 { - pkExpr = fmt.Sprintf("(%s)", strings.Join(pkInfo.pkNames, ",")) - } - deleteStmt := fmt.Sprintf( - "delete from %s where %s in (select %s from %s)", - baseTable, pkExpr, strings.Join(pkInfo.pkNames, ","), deleteTable, - ) - clearStmt := fmt.Sprintf("delete from %s", deleteTable) - return execSQLStatements(ctx, ses, bh, writeFile, []string{insertStmt, deleteStmt, clearStmt}) - } - - insertStmt := fmt.Sprintf("insert into %s values %s", insertTable, buf.String()) - cols := strings.Join(pkInfo.visibleNames, ",") - applyStmt := fmt.Sprintf( - "insert into %s (%s) select %s from %s", - baseTable, cols, cols, insertTable, - ) - clearStmt := fmt.Sprintf("delete from %s", insertTable) - return execSQLStatements(ctx, ses, bh, writeFile, []string{insertStmt, applyStmt, clearStmt}) - } - - sqlBuffer := acquireBuffer(tblStuff.bufPool) - defer releaseBuffer(tblStuff.bufPool, sqlBuffer) - - initInsertIntoBuf := func() { - sqlBuffer.WriteString(fmt.Sprintf( - "insert into %s.%s values ", - tblStuff.baseRel.GetTableDef(ctx).DbName, - tblStuff.baseRel.GetTableDef(ctx).Name, - )) - } - - initDeleteFromBuf := func() { - if len(tblStuff.def.pkColIdxes) == 1 { - sqlBuffer.WriteString(fmt.Sprintf( - "delete from %s.%s where %s in (", - tblStuff.baseRel.GetTableDef(ctx).DbName, - tblStuff.baseRel.GetTableDef(ctx).Name, - tblStuff.def.colNames[tblStuff.def.pkColIdx], - )) - } else { - pkNames := make([]string, len(tblStuff.def.pkColIdxes)) - for i, pkColIdx := range tblStuff.def.pkColIdxes { - pkNames[i] = tblStuff.def.colNames[pkColIdx] - } - sqlBuffer.WriteString(fmt.Sprintf( - "delete from %s.%s where (%s) in (", - tblStuff.baseRel.GetTableDef(ctx).DbName, - tblStuff.baseRel.GetTableDef(ctx).Name, - strings.Join(pkNames, ","), - )) - } - } - - if isDeleteFrom { - initDeleteFromBuf() - sqlBuffer.Write(buf.Bytes()) - sqlBuffer.WriteString(")") - } else { - initInsertIntoBuf() - sqlBuffer.Write(buf.Bytes()) - } - - sqlBuffer.WriteString(";\n") - - if writeFile != nil { - err = writeFile(sqlBuffer.Bytes()) - } else { - var ( - ret executor.Result - ) - - defer func() { - ret.Close() - }() - ret, err = runSql(ctx, ses, bh, sqlBuffer.String(), nil, nil) - } - - return err -} - -func buildOutputSchema( - ctx context.Context, - ses *Session, - stmt *tree.DataBranchDiff, - tblStuff tableStuff, -) (err error) { - - var ( - mrs = ses.GetMysqlResultSet() - showCols []*MysqlColumn - ) - ses.ClearAllMysqlResultSet() - ses.ClearResultBatches() - - if stmt.OutputOpt == nil || stmt.OutputOpt.Limit != nil { - // output all rows OR - // output limited rows (is this can be pushed down to hash-phase?) - showCols = make([]*MysqlColumn, 0, 2) - showCols = append(showCols, new(MysqlColumn), new(MysqlColumn)) - showCols[0].SetColumnType(defines.MYSQL_TYPE_VARCHAR) - showCols[0].SetName(fmt.Sprintf( - "diff %s against %s", tblStuff.tarRel.GetTableName(), tblStuff.baseRel.GetTableName()), - ) - showCols[1].SetColumnType(defines.MYSQL_TYPE_VARCHAR) - showCols[1].SetName("flag") - - for _, idx := range tblStuff.def.visibleIdxes { - nCol := new(MysqlColumn) - if err = convertEngineTypeToMysqlType(ctx, tblStuff.def.colTypes[idx].Oid, nCol); err != nil { - return - } - - nCol.SetName(tblStuff.def.colNames[idx]) - showCols = append(showCols, nCol) - } - - } else if stmt.OutputOpt.Summary { - targetName := tree.StringWithOpts(&stmt.TargetTable, dialect.MYSQL, tree.WithSingleQuoteString()) - baseName := tree.StringWithOpts(&stmt.BaseTable, dialect.MYSQL, tree.WithSingleQuoteString()) - - showCols = append(showCols, &MysqlColumn{}, &MysqlColumn{}, &MysqlColumn{}) - showCols[0].SetName("metric") - showCols[0].SetColumnType(defines.MYSQL_TYPE_VARCHAR) - showCols[1].SetName(targetName) - showCols[1].SetColumnType(defines.MYSQL_TYPE_LONGLONG) - showCols[2].SetName(baseName) - showCols[2].SetColumnType(defines.MYSQL_TYPE_LONGLONG) - - } else if stmt.OutputOpt.Count { - // count(*) of diff rows - showCols = append(showCols, &MysqlColumn{}) - showCols[0].SetName("COUNT(*)") - showCols[0].SetColumnType(defines.MYSQL_TYPE_LONGLONG) - - } else if len(stmt.OutputOpt.DirPath) != 0 { - // output as file - col1 := new(MysqlColumn) - col1.SetName("FILE SAVED TO") - col1.SetColumnType(defines.MYSQL_TYPE_VARCHAR) - - col2 := new(MysqlColumn) - col2.SetName("HINT") - col2.SetColumnType(defines.MYSQL_TYPE_VARCHAR) - - showCols = append(showCols, col1, col2) - } else { - return moerr.NewNotSupportedNoCtx(fmt.Sprintf("%v", stmt.OutputOpt)) - } - - for _, col := range showCols { - mrs.AddColumn(col) - } - - return nil -} - -func tryDiffAsCSV( - ctx context.Context, - ses *Session, - bh BackgroundExec, - stmt *tree.DataBranchDiff, - tblStuff tableStuff, -) (bool, error) { - - if stmt.OutputOpt == nil { - return false, nil - } - - if len(stmt.OutputOpt.DirPath) == 0 { - return false, nil - } - - sql := fmt.Sprintf( - "SELECT COUNT(*) FROM %s.%s", - tblStuff.baseRel.GetTableDef(ctx).DbName, - tblStuff.baseRel.GetTableDef(ctx).Name, - ) - - if tblStuff.baseSnap != nil && tblStuff.baseSnap.TS != nil { - sql += fmt.Sprintf("{mo_ts=%d}", tblStuff.baseSnap.TS.PhysicalTime) - } - - var ( - err error - sqlRet executor.Result - ) - - if sqlRet, err = runSql(ctx, ses, bh, sql, nil, nil); err != nil { - return false, err - } - - if len(sqlRet.Batches) != 1 && - sqlRet.Batches[0].RowCount() != 1 && - sqlRet.Batches[0].VectorCount() != 1 { - return false, moerr.NewInternalErrorNoCtxf("cannot get count(*) of base table") - } - - if vector.GetFixedAtWithTypeCheck[uint64](sqlRet.Batches[0].Vecs[0], 0) != 0 { - return false, nil - } - - sqlRet.Close() - - return true, writeCSV(ctx, ses, tblStuff, bh, stmt) -} - -func writeCSV( - inputCtx context.Context, - ses *Session, - tblStuff tableStuff, - bh BackgroundExec, - stmt *tree.DataBranchDiff, -) (err error) { - - ctx, cancelCtx := context.WithCancel(inputCtx) - defer cancelCtx() - - // SQLExecutor do not support snapshot read, we must use the MO_TS - snap := "" - if tblStuff.tarSnap != nil { - snap = fmt.Sprintf("{MO_TS=%d}", tblStuff.tarSnap.TS.PhysicalTime) - } - - // output as csv - sql := fmt.Sprintf("SELECT * FROM %s.%s%s;", - tblStuff.tarRel.GetTableDef(ctx).DbName, - tblStuff.tarRel.GetTableDef(ctx).Name, - snap, - ) - - var ( - stop bool - wg sync.WaitGroup - errChan = make(chan error, 1) - streamChan = make(chan executor.Result, runtime.NumCPU()) - - writerWg sync.WaitGroup - workerWg sync.WaitGroup - writerErr = make(chan error, 1) - closeByte sync.Once - - mrs = &MysqlResultSet{} - sqlRetHint string - sqlRetPath string - fileName = makeFileName(stmt.BaseTable.AtTsExpr, stmt.TargetTable.AtTsExpr, tblStuff) - cleanup func() - ) - - ep := &ExportConfig{ - userConfig: newDiffCSVUserConfig(), - service: ses.service, - } - - for range tblStuff.def.visibleIdxes { - mrs.AddColumn(&MysqlColumn{}) - } - - ep.init() - ep.ctx = ctx - ep.mrs = mrs - ep.ByteChan = make(chan *BatchByte, runtime.NumCPU()) - - ep.DefaultBufSize = getPu(ses.GetService()).SV.ExportDataDefaultFlushSize - initExportFileParam(ep, mrs) - - sqlRetHint = ep.userConfig.String() - fileName += ".csv" - - var ( - ok bool - stagePath string - ) - - sqlRetPath = path.Join(stmt.OutputOpt.DirPath, fileName) - - if stagePath, ok, err = tryDecodeStagePath(ses, stmt.OutputOpt.DirPath); err != nil { - return - } else if ok { - sqlRetPath = strings.Replace(sqlRetPath, "stage:/", "stage://", 1) - ep.userConfig.StageFilePath = path.Join(stagePath, fileName) - if err = openNewFile(ctx, ep, mrs); err != nil { - return - } - cleanup = func() { - removeFileIgnoreError(context.Background(), ep.service, ep.userConfig.StageFilePath) - } - } else { - ep.userConfig.FilePath = path.Join(stmt.OutputOpt.DirPath, fileName) - if err = openNewFile(ctx, ep, mrs); err != nil { - return - } - cleanup = func() { - removeFileIgnoreError(context.Background(), ep.service, ep.userConfig.FilePath) - } - } - - writerWg.Add(1) - if err = tblStuff.worker.Submit(func() { - defer writerWg.Done() - for bb := range ep.ByteChan { - if bb.err != nil { - select { - case writerErr <- bb.err: - default: - } - return - } - ep.BatchMap[bb.index] = bb.writeByte - for { - value, ok := ep.BatchMap[ep.WriteIndex.Load()+1] - if !ok { - break - } - if err2 := writeToCSVFile(ep, value); err2 != nil { - select { - case writerErr <- err2: - default: - } - return - } - ep.WriteIndex.Add(1) - ep.BatchMap[ep.WriteIndex.Load()] = nil - } - } - if ep.WriteIndex.Load() != ep.Index.Load() { - if err2 := exportAllDataFromBatches(ep); err2 != nil { - select { - case writerErr <- err2: - default: - } - } - } - }); err != nil { - writerWg.Done() - return err - } - - defer func() { - if err != nil && cleanup != nil { - cleanup() - } - }() - - defer func() { - closeByte.Do(func() { - close(ep.ByteChan) - }) - writerWg.Wait() - closeErr := Close(ep) - ep.Close() - if err == nil { - err = closeErr - } else { - err = errors.Join(err, closeErr) - } - }() - - wg.Add(1) - if err = tblStuff.worker.Submit(func() { - defer func() { - wg.Done() - close(streamChan) - close(errChan) - }() - if _, err2 := runSql(ctx, ses, bh, sql, streamChan, errChan); err2 != nil { - select { - case errChan <- err2: - default: - } - } - }); err != nil { - wg.Done() - return err - } - - streamOpen, errOpen := true, true - for streamOpen || errOpen { - select { - case <-inputCtx.Done(): - err = errors.Join(err, inputCtx.Err()) - stop = true - case e := <-writerErr: - if e != nil { - err = errors.Join(err, e) - } - stop = true - cancelCtx() - case e, ok := <-errChan: - if !ok { - errOpen = false - continue - } - err = errors.Join(err, e) - cancelCtx() - stop = true - case sqlRet, ok := <-streamChan: - if !ok { - streamOpen = false - continue - } - if stop { - sqlRet.Close() - continue - } - for _, bat := range sqlRet.Batches { - copied, _ := bat.Dup(ses.proc.Mp()) - idx := ep.Index.Add(1) - workerWg.Add(1) - if submitErr := tblStuff.worker.Submit(func() { - defer workerWg.Done() - constructByte(ctx, ses, copied, idx, ep.ByteChan, ep) - }); submitErr != nil { - workerWg.Done() - err = errors.Join(err, submitErr) - stop = true - cancelCtx() - break - } - } - sqlRet.Close() - } - } - - wg.Wait() - workerWg.Wait() - closeByte.Do(func() { - close(ep.ByteChan) - }) - writerWg.Wait() - - select { - case e := <-writerErr: - err = errors.Join(err, e) - default: - } - - if err != nil { - return err - } - - mrs = ses.GetMysqlResultSet() - mrs.AddRow([]any{sqlRetPath, sqlRetHint}) - - return trySaveQueryResult(ctx, ses, mrs) -} - -func newDiffCSVUserConfig() *tree.ExportParam { - fields := tree.NewFields( - tree.DefaultFieldsTerminated, - false, - tree.DefaultFieldsEnclosedBy[0], - tree.DefaultFieldsEscapedBy[0], - ) - return &tree.ExportParam{ - Outfile: true, - Fields: fields, - Lines: tree.NewLines("", "\n"), - Header: false, - } -} - -func getTableStuff( - ctx context.Context, - ses *Session, - bh BackgroundExec, - srcTable tree.TableName, - dstTable tree.TableName, -) (tblStuff tableStuff, err error) { - - var ( - tarTblDef *plan.TableDef - baseTblDef *plan.TableDef - ) - - defer func() { - if err == nil { - tblStuff.worker, err = ants.NewPool(runtime.NumCPU()) - } - }() - - if tblStuff.tarRel, tblStuff.baseRel, tblStuff.tarSnap, tblStuff.baseSnap, err = getRelations( - ctx, ses, bh, srcTable, dstTable, - ); err != nil { - return - } - - tarTblDef = tblStuff.tarRel.GetTableDef(ctx) - baseTblDef = tblStuff.baseRel.GetTableDef(ctx) - - if !isSchemaEquivalent(tarTblDef, baseTblDef) { - err = moerr.NewInternalErrorNoCtx("the target table schema is not equivalent to the base table.") - return - } - - if baseTblDef.Pkey.PkeyColName == catalog.FakePrimaryKeyColName { - tblStuff.def.pkKind = fakeKind - for i, col := range baseTblDef.Cols { - if col.Name != catalog.FakePrimaryKeyColName && col.Name != catalog.Row_ID { - tblStuff.def.pkColIdxes = append(tblStuff.def.pkColIdxes, i) - } - } - } else if baseTblDef.Pkey.CompPkeyCol != nil { - // case 2: composite pk, combined all pks columns as the PK - tblStuff.def.pkKind = compositeKind - pkNames := baseTblDef.Pkey.Names - for _, name := range pkNames { - idx := int(baseTblDef.Name2ColIndex[name]) - tblStuff.def.pkColIdxes = append(tblStuff.def.pkColIdxes, idx) - } - } else { - // normal pk - tblStuff.def.pkKind = normalKind - pkName := baseTblDef.Pkey.PkeyColName - idx := int(baseTblDef.Name2ColIndex[pkName]) - tblStuff.def.pkColIdxes = append(tblStuff.def.pkColIdxes, idx) - } - - tblStuff.def.pkColIdx = int(baseTblDef.Name2ColIndex[baseTblDef.Pkey.PkeyColName]) - - for i, col := range tarTblDef.Cols { - if col.Name == catalog.Row_ID { - continue - } - - t := types.New(types.T(col.Typ.Id), col.Typ.Width, col.Typ.Scale) - - tblStuff.def.colNames = append(tblStuff.def.colNames, col.Name) - tblStuff.def.colTypes = append(tblStuff.def.colTypes, t) - - if col.Name == catalog.FakePrimaryKeyColName || - col.Name == catalog.CPrimaryKeyColName { - continue - } - - tblStuff.def.visibleIdxes = append(tblStuff.def.visibleIdxes, i) - } - - tblStuff.retPool = &retBatchList{} - tblStuff.bufPool = &sync.Pool{ - New: func() any { - return &bytes.Buffer{} - }, - } - tblStuff.hashmapAllocator = newBranchHashmapAllocator(dataBranchHashmapLimitRate) - - return - -} - -func diffOnBase( - ctx context.Context, - ses *Session, - bh BackgroundExec, - wg *sync.WaitGroup, - dagInfo branchMetaInfo, - tblStuff tableStuff, - copt compositeOption, - emit emitFunc, -) (err error) { - - defer func() { - wg.Done() - }() - - var ( - tarHandle []engine.ChangesHandle - baseHandle []engine.ChangesHandle - ) - - closeHandle := func() { - for _, h := range tarHandle { - _ = h.Close() - } - for _, h := range baseHandle { - _ = h.Close() - } - tarHandle = nil - baseHandle = nil - } - - defer func() { - closeHandle() - }() - - //if true || dagInfo.lcaTableId == 0 { - - if dagInfo.lcaType != lcaEmpty { - if dagInfo.lcaTableId == tblStuff.tarRel.GetTableID(ctx) { - tblStuff.lcaRel = tblStuff.tarRel - } else if dagInfo.lcaTableId == tblStuff.baseRel.GetTableID(ctx) { - tblStuff.lcaRel = tblStuff.baseRel - } else { - lcaSnapshot := &plan2.Snapshot{ - Tenant: &plan.SnapshotTenant{ - TenantID: ses.GetAccountId(), - }, - } - lcaSnapshot.TS = ×tamp.Timestamp{PhysicalTime: dagInfo.tarBranchTS.Physical()} - if dagInfo.baseBranchTS.LT(&dagInfo.tarBranchTS) { - lcaSnapshot.TS.PhysicalTime = dagInfo.baseBranchTS.Physical() - } - - if tblStuff.lcaRel, err = getRelationById( - ctx, ses, bh, dagInfo.lcaTableId, lcaSnapshot); err != nil { - return - } - } - } - - // has no lca - if tarHandle, baseHandle, err = constructChangeHandle( - ctx, ses, bh, tblStuff, &dagInfo, - ); err != nil { - return - } - - if err = hashDiff( - ctx, ses, bh, tblStuff, dagInfo, - copt, emit, tarHandle, baseHandle, - ); err != nil { - return - } - - closeHandle() - return - //} - - //return - // merge left into right - //var ( - // lcaRel engine.Relation - // lcaSnapshot *plan.Snapshot - //) - // - //lcaSnapshot = &plan2.Snapshot{ - // Tenant: &plan.SnapshotTenant{ - // TenantID: ses.GetAccountId(), - // }, - //} - // - //if dagInfo.lcaTableId == tblStuff.tarRel.GetTableID(ctx) { - // // left is the LCA - // lcaRel = tblStuff.tarRel - // lcaSnapshot.TS = ×tamp.Timestamp{PhysicalTime: dagInfo.baseBranchTS.Physical()} - // if tblStuff.tarSnap != nil && tblStuff.tarSnap.TS.Less(*lcaSnapshot.TS) { - // lcaSnapshot.TS = tblStuff.tarSnap.TS - // } - //} else if dagInfo.lcaTableId == tblStuff.baseRel.GetTableID(ctx) { - // // right is the LCA - // lcaRel = tblStuff.baseRel - // lcaSnapshot.TS = ×tamp.Timestamp{PhysicalTime: dagInfo.tarBranchTS.Physical()} - // if tblStuff.baseSnap != nil && tblStuff.baseSnap.TS.Less(*lcaSnapshot.TS) { - // lcaSnapshot.TS = tblStuff.baseSnap.TS - // } - //} else { - // // LCA is other table - // lcaSnapshot.TS = ×tamp.Timestamp{PhysicalTime: dagInfo.tarBranchTS.Physical()} - // if dagInfo.baseBranchTS.LT(&dagInfo.tarBranchTS) { - // lcaSnapshot.TS.PhysicalTime = dagInfo.baseBranchTS.Physical() - // } - // - // if lcaRel, err = getRelationById( - // ctx, ses, bh, dagInfo.lcaTableId, lcaSnapshot); err != nil { - // return - // } - //} - // - //tblStuff.lcaRel = lcaRel - // - //var ( - // tmpPair1 = tblStuff - // tmpPair2 = tblStuff - // - // dagInfo1 branchMetaInfo - // dagInfo2 branchMetaInfo - // - // finalTblStuff tableStuff - // finalDagInfo branchMetaInfo - //) - // - //tmpPair1.tarRel = tblStuff.tarRel - //tmpPair1.baseRel = lcaRel - //tmpPair1.tarSnap = tblStuff.tarSnap - //tmpPair1.baseSnap = lcaSnapshot - // - //if dagInfo1, err = decideLCABranchTSFromBranchDAG( - // ctx, ses, tmpPair1.tarRel, tmpPair1.baseRel, - //); err != nil { - // return - //} - // - //if dagInfo1.tarBranchTS.IsEmpty() { - // dagInfo1.tarBranchTS = types.TimestampToTS(*tmpPair1.baseSnap.TS) - //} - // - //if tarHandle, _, err = constructChangeHandle( - // ctx, ses, bh, tmpPair1, &dagInfo1, - //); err != nil { - // return - //} - // - //tmpPair2.tarRel = tblStuff.baseRel - //tmpPair2.baseRel = lcaRel - //tmpPair2.tarSnap = tblStuff.baseSnap - //tmpPair2.baseSnap = lcaSnapshot - // - //if dagInfo2, err = decideLCABranchTSFromBranchDAG( - // ctx, ses, tmpPair2.tarRel, tmpPair2.baseRel, - //); err != nil { - // return - //} - // - //if dagInfo2.tarBranchTS.IsEmpty() { - // dagInfo2.tarBranchTS = types.TimestampToTS(*tmpPair2.baseSnap.TS) - //} - // - //if copt.conflictOpt == nil || copt.conflictOpt.Opt != tree.CONFLICT_ACCEPT { - // // if we got a conflict_accept option, - // // then we should ignore all inserts/deletes/updates from the base. - // if baseHandle, _, err = constructChangeHandle( - // ctx, ses, bh, tmpPair2, &dagInfo2, - // ); err != nil { - // return - // } - //} - // - //finalDagInfo.lcaType = dagInfo.lcaType - //finalDagInfo.lcaTableId = dagInfo.lcaTableId - //finalDagInfo.tarBranchTS = dagInfo1.tarBranchTS - //finalDagInfo.baseBranchTS = dagInfo2.tarBranchTS - // - //finalTblStuff = tblStuff - //finalTblStuff.tarRel = tmpPair1.tarRel - //finalTblStuff.baseRel = tmpPair2.tarRel - //finalTblStuff.tarSnap = tmpPair1.tarSnap - //finalTblStuff.baseSnap = tmpPair2.tarSnap - // - //return hashDiff(ctx, ses, bh, finalTblStuff, finalDagInfo, retCh, copt, tarHandle, baseHandle) -} - -func hashDiff( - ctx context.Context, - ses *Session, - bh BackgroundExec, - tblStuff tableStuff, - dagInfo branchMetaInfo, - copt compositeOption, - emit emitFunc, - tarHandle []engine.ChangesHandle, - baseHandle []engine.ChangesHandle, -) ( - err error, -) { - - var ( - baseDataHashmap databranchutils.BranchHashmap - baseTombstoneHashmap databranchutils.BranchHashmap - - tarDataHashmap databranchutils.BranchHashmap - tarTombstoneHashmap databranchutils.BranchHashmap - ) - - defer func() { - if baseDataHashmap != nil { - baseDataHashmap.Close() - } - if baseTombstoneHashmap != nil { - baseTombstoneHashmap.Close() - } - if tarDataHashmap != nil { - tarDataHashmap.Close() - } - if tarTombstoneHashmap != nil { - tarTombstoneHashmap.Close() - } - }() - - if baseDataHashmap, baseTombstoneHashmap, err = buildHashmapForTable( - ctx, ses.proc.Mp(), dagInfo.lcaType, &tblStuff, baseHandle, - ); err != nil { - return - } - - if tarDataHashmap, tarTombstoneHashmap, err = buildHashmapForTable( - ctx, ses.proc.Mp(), dagInfo.lcaType, &tblStuff, tarHandle, - ); err != nil { - return - } - - if dagInfo.lcaType == lcaEmpty { - if err = hashDiffIfNoLCA( - ctx, ses, tblStuff, copt, emit, - tarDataHashmap, tarTombstoneHashmap, - baseDataHashmap, baseTombstoneHashmap, - ); err != nil { - return - } - } else { - if err = hashDiffIfHasLCA( - ctx, ses, bh, dagInfo, tblStuff, copt, emit, - tarDataHashmap, tarTombstoneHashmap, - baseDataHashmap, baseTombstoneHashmap, - ); err != nil { - return - } - } - - return -} - -func hashDiffIfHasLCA( - ctx context.Context, - ses *Session, - bh BackgroundExec, - dagInfo branchMetaInfo, - tblStuff tableStuff, - copt compositeOption, - emit emitFunc, - tarDataHashmap databranchutils.BranchHashmap, - tarTombstoneHashmap databranchutils.BranchHashmap, - baseDataHashmap databranchutils.BranchHashmap, - baseTombstoneHashmap databranchutils.BranchHashmap, -) (err error) { - - var ( - wg sync.WaitGroup - atomicErr atomic.Value - - baseDeleteBatches []batchWithKind - baseUpdateBatches []batchWithKind - ) - - handleBaseDeleteAndUpdates := func(wrapped batchWithKind) error { - wrapped.side = diffSideBase - if err2 := mergeutil.SortColumnsByIndex( - wrapped.batch.Vecs, tblStuff.def.pkColIdx, ses.proc.Mp(), - ); err2 != nil { - return err2 - } - if wrapped.kind == diffDelete { - baseDeleteBatches = append(baseDeleteBatches, wrapped) - } else { - baseUpdateBatches = append(baseUpdateBatches, wrapped) - } - - return nil - } - - handleTarDeleteAndUpdates := func(wrapped batchWithKind) (err2 error) { - wrapped.side = diffSideTarget - if len(baseUpdateBatches) == 0 && len(baseDeleteBatches) == 0 { - // no need to check conflict - if stop, e := emitBatch(emit, wrapped, false, tblStuff.retPool); e != nil { - return e - } else if stop { - return nil - } - return nil - } - - if err2 = mergeutil.SortColumnsByIndex( - wrapped.batch.Vecs, tblStuff.def.pkColIdx, ses.proc.Mp(), - ); err2 != nil { - return err2 - } - - checkConflict := func(tarWrapped, baseWrapped batchWithKind) (sels1, sels2 []int64, err3 error) { - var ( - cmp int - tarVec = tarWrapped.batch.Vecs[tblStuff.def.pkColIdx] - baseVec = baseWrapped.batch.Vecs[tblStuff.def.pkColIdx] - ) - - i, j := 0, 0 - for i < tarVec.Length() && j < baseVec.Length() { - if cmp, err3 = compareSingleValInVector( - ctx, ses, i, j, tarVec, baseVec, - ); err3 != nil { - return - } - - if cmp == 0 { - // conflict - // tar and base both deleted on pk1 => empty - // tar and base both updated on pk1 => we need compare the left columns, consider - // the conflict option. - if copt.conflictOpt == nil { - if tarWrapped.kind == baseWrapped.kind { - // compare the left column values - if cmp, err3 = compareRowInWrappedBatches( - ctx, ses, tblStuff, i, j, true, - tarWrapped, baseWrapped, - ); err3 != nil { - return - } else if cmp == 0 { - sels1 = append(sels1, int64(i)) - sels2 = append(sels2, int64(j)) - } - } - i++ - j++ - } else if copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT { - // only keep the rows from tar - sels2 = append(sels2, int64(j)) - i++ - j++ - } else if copt.conflictOpt.Opt == tree.CONFLICT_SKIP { - sels1 = append(sels1, int64(i)) - sels2 = append(sels2, int64(j)) - i++ - j++ - } else { - // copt.conflictOpt == tree.CONFLICT_FAIL - tarRow := make([]any, 1) - if err3 = extractRowFromVector( - ctx, ses, tarVec, 0, tarRow, i, false, - ); err3 != nil { - return - } - - buf := acquireBuffer(tblStuff.bufPool) - if err3 = formatValIntoString( - ses, tarRow[0], tblStuff.def.colTypes[tblStuff.def.pkColIdx], buf, - ); err3 != nil { - releaseBuffer(tblStuff.bufPool, buf) - return - } - - err3 = moerr.NewInternalErrorNoCtxf( - "conflict: %s %s and %s %s on pk(%v) with different values", - tarWrapped.name, tarWrapped.kind, - baseWrapped.name, baseWrapped.kind, buf.String(), - ) - releaseBuffer(tblStuff.bufPool, buf) - return - } - } else if cmp < 0 { - // tarVal < baseVal - i++ - } else { - // tarVal > baseVal - j++ - } - } - - return - } - - foo := func(baseWrappedList []batchWithKind) (err3 error) { - for _, baseWrapped := range baseWrappedList { - var ( - sels1 []int64 - sels2 []int64 - ) - if sels1, sels2, err3 = checkConflict(wrapped, baseWrapped); err3 != nil { - return - } else { - if len(sels1) != 0 { - wrapped.batch.Shrink(sels1, true) - } - - if len(sels2) != 0 { - baseWrapped.batch.Shrink(sels2, true) - } - } - - if wrapped.batch.RowCount() == 0 { - break - } - } - - return - } - - if err2 = foo(baseDeleteBatches); err2 != nil { - return - } - - baseDeleteBatches = plan2.RemoveIf(baseDeleteBatches, func(t batchWithKind) bool { - if t.batch.RowCount() == 0 { - tblStuff.retPool.releaseRetBatch(t.batch, false) - return true - } - return false - }) - - if err2 = foo(baseUpdateBatches); err2 != nil { - return - } - - baseUpdateBatches = plan2.RemoveIf(baseUpdateBatches, func(t batchWithKind) bool { - if t.batch.RowCount() == 0 { - tblStuff.retPool.releaseRetBatch(t.batch, false) - return true - } - return false - }) - - if wrapped.batch.RowCount() == 0 { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - return - } - - stop, e := emitBatch(emit, wrapped, false, tblStuff.retPool) - if e != nil { - return e - } - if stop { - return nil - } - - return - } - - newCtx, cancel := context.WithCancel(ctx) - defer cancel() - - asyncDelsAndUpdatesHandler := func(forBase bool, tmpCh chan batchWithKind) (err2 error) { - var ( - branchTS = dagInfo.baseBranchTS - hashmap1 = baseDataHashmap - hashmap2 = baseTombstoneHashmap - name = tblStuff.baseRel.GetTableName() - ) - - if !forBase { - branchTS = dagInfo.tarBranchTS - hashmap1 = tarDataHashmap - hashmap2 = tarTombstoneHashmap - name = tblStuff.tarRel.GetTableName() - } - - wg.Add(1) - if err2 = tblStuff.worker.Submit(func() { - defer func() { - close(tmpCh) - tmpCh = nil - wg.Done() - }() - - if err3 := findDeleteAndUpdateBat( - newCtx, ses, bh, tblStuff, name, - func() int { - if forBase { - return diffSideBase - } - return diffSideTarget - }(), - tmpCh, branchTS, copt.expandUpdate, hashmap1, hashmap2, - ); err3 != nil { - atomicErr.Store(err3) - } - }); err2 != nil { - wg.Done() - return - } - return nil - } - - stepHandler := func(forBase bool) (err2 error) { - var ( - tmpCh = make(chan batchWithKind, 1) - first error - ) - - if err2 = asyncDelsAndUpdatesHandler(forBase, tmpCh); err2 != nil { - return err2 - } - - for wrapped := range tmpCh { - if first != nil { - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - } - - select { - case <-ctx.Done(): - first = ctx.Err() - cancel() - tblStuff.retPool.releaseRetBatch(wrapped.batch, false) - continue - default: - if forBase { - err2 = handleBaseDeleteAndUpdates(wrapped) - } else { - err2 = handleTarDeleteAndUpdates(wrapped) - } - - if errors.Is(err2, context.Canceled) { - err2 = nil - cancel() - } - } - - if err2 != nil { - first = err2 - cancel() - } - } - - wg.Wait() - if first != nil { - return first - } - - if atomicErr.Load() != nil { - return atomicErr.Load().(error) - } - - return first - } - - // phase 1: handle base dels and updates on lca - if err = stepHandler(true); err != nil { - return - } - - // phase2: handle tar dels and updates on lca - if err = stepHandler(false); err != nil { - return - } - - // what can I do with these left base updates/inserts ? - if copt.conflictOpt == nil { - stopped := false - for i, w := range baseUpdateBatches { - var stop bool - if stop, err = emitBatch(emit, w, false, tblStuff.retPool); err != nil { - return err - } - if stop { - stopped = true - for j := i + 1; j < len(baseUpdateBatches); j++ { - tblStuff.retPool.releaseRetBatch(baseUpdateBatches[j].batch, false) - } - for _, bw := range baseDeleteBatches { - tblStuff.retPool.releaseRetBatch(bw.batch, false) - } - break - } - } - - if !stopped { - for i, w := range baseDeleteBatches { - var stop bool - if stop, err = emitBatch(emit, w, false, tblStuff.retPool); err != nil { - return err - } - if stop { - for j := i + 1; j < len(baseDeleteBatches); j++ { - tblStuff.retPool.releaseRetBatch(baseDeleteBatches[j].batch, false) - } - break - } - } - } - } - - return diffDataHelper(ctx, ses, copt, tblStuff, emit, tarDataHashmap, baseDataHashmap) -} - -func hashDiffIfNoLCA( - ctx context.Context, - ses *Session, - tblStuff tableStuff, - copt compositeOption, - emit emitFunc, - tarDataHashmap databranchutils.BranchHashmap, - tarTombstoneHashmap databranchutils.BranchHashmap, - baseDataHashmap databranchutils.BranchHashmap, - baseTombstoneHashmap databranchutils.BranchHashmap, -) (err error) { - - if err = tarTombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - return cursor.ForEach(func(key []byte, _ []byte) error { - _, err2 := tarDataHashmap.PopByEncodedKey(key, true) - return err2 - }) - - }, -1); err != nil { - return - } - - if err = baseTombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - return cursor.ForEach(func(key []byte, _ []byte) error { - _, err2 := baseDataHashmap.PopByEncodedKey(key, true) - return err2 - }) - - }, -1); err != nil { - return - } - - return diffDataHelper(ctx, ses, copt, tblStuff, emit, tarDataHashmap, baseDataHashmap) -} - -func compareRowInWrappedBatches( - ctx context.Context, - ses *Session, - tblStuff tableStuff, - rowIdx1 int, - rowIdx2 int, - skipPKCols bool, - wrapped1 batchWithKind, - wrapped2 batchWithKind, -) (int, error) { - if wrapped1.kind == wrapped2.kind && wrapped1.kind == diffDelete && skipPKCols { - return 0, nil - } - - for i, colIdx := range tblStuff.def.visibleIdxes { - if skipPKCols { - if slices.Index(tblStuff.def.pkColIdxes, colIdx) != -1 { - continue - } - } - - var ( - vec1 = wrapped1.batch.Vecs[i] - vec2 = wrapped2.batch.Vecs[i] - ) - - if cmp, err := compareSingleValInVector( - ctx, ses, rowIdx1, rowIdx2, vec1, vec2, - ); err != nil { - return 0, err - } else if cmp != 0 { - return cmp, nil - } - - } - - return 0, nil -} - -func findDeleteAndUpdateBat( - ctx context.Context, ses *Session, bh BackgroundExec, - tblStuff tableStuff, tblName string, side int, tmpCh chan batchWithKind, branchTS types.TS, - expandUpdate bool, - dataHashmap, tombstoneHashmap databranchutils.BranchHashmap, -) (err error) { - - maxTombstoneBatchCnt := tblStuff.maxTombstoneBatchCnt - if maxTombstoneBatchCnt <= 0 { - maxTombstoneBatchCnt = maxSqlBatchCnt - } - - if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - var ( - err2 error - tuple types.Tuple - tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) - ) - - send := func(bwk batchWithKind) error { - select { - case <-ctx.Done(): - tblStuff.retPool.releaseRetBatch(bwk.batch, false) - return ctx.Err() - case tmpCh <- bwk: - return nil - } - } - - processBatch := func(tombBat *batch.Batch) error { - if tombBat.RowCount() == 0 { - tblStuff.retPool.releaseRetBatch(tombBat, true) - return nil - } - - dBat, err2 := handleDelsOnLCA( - ctx, ses, bh, tombBat, tblStuff, branchTS.ToTimestamp(), - ) - if err2 != nil { - tblStuff.retPool.releaseRetBatch(tombBat, true) - return err2 - } - - // merge inserts and deletes on the tar - // this deletes is not on the lca - if tombBat.RowCount() > 0 { - if _, err2 = dataHashmap.PopByVectorsStream( - []*vector.Vector{tombBat.Vecs[0]}, false, nil, - ); err2 != nil { - tblStuff.retPool.releaseRetBatch(tombBat, true) - tblStuff.retPool.releaseRetBatch(dBat, false) - return err2 - } - tblStuff.retPool.releaseRetBatch(tombBat, true) - } - - // find update - if dBat.RowCount() > 0 { - tBat2 := tblStuff.retPool.acquireRetBatch(tblStuff, false) - seen := make([]bool, dBat.RowCount()) - var updateBat *batch.Batch - var updateDeleteBat *batch.Batch - if _, err2 = dataHashmap.PopByVectorsStream( - []*vector.Vector{dBat.Vecs[tblStuff.def.pkColIdx]}, false, - func(idx int, _ []byte, row []byte) error { - seen[idx] = true - // delete on lca and insert into tar ==> update - if updateBat == nil { - updateBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - } - if expandUpdate && updateDeleteBat == nil { - updateDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - } - - if tuple, _, err2 = dataHashmap.DecodeRow(row); err2 != nil { - return err2 - } - - if expandUpdate { - if err2 = updateDeleteBat.UnionOne(dBat, int64(idx), ses.proc.Mp()); err2 != nil { - return err2 - } - } - - if err2 = appendTupleToBat(ses, updateBat, tuple, tblStuff); err2 != nil { - return err2 - } - return nil - }, - ); err2 != nil { - tblStuff.retPool.releaseRetBatch(dBat, false) - tblStuff.retPool.releaseRetBatch(tBat2, false) - if updateBat != nil { - tblStuff.retPool.releaseRetBatch(updateBat, false) - } - if updateDeleteBat != nil { - tblStuff.retPool.releaseRetBatch(updateDeleteBat, false) - } - return err2 - } - - for i := 0; i < dBat.RowCount(); i++ { - if seen[i] { - continue - } - // delete on lca - if err2 = tBat2.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { - tblStuff.retPool.releaseRetBatch(dBat, false) - tblStuff.retPool.releaseRetBatch(tBat2, false) - if updateBat != nil { - tblStuff.retPool.releaseRetBatch(updateBat, false) - } - if updateDeleteBat != nil { - tblStuff.retPool.releaseRetBatch(updateDeleteBat, false) - } - return err2 - } - } - - tblStuff.retPool.releaseRetBatch(dBat, false) - tBat2.SetRowCount(tBat2.Vecs[0].Length()) - - if updateBat != nil { - updateBat.SetRowCount(updateBat.Vecs[0].Length()) - if expandUpdate { - if updateDeleteBat != nil { - updateDeleteBat.SetRowCount(updateDeleteBat.Vecs[0].Length()) - if err2 = send(batchWithKind{ - name: tblName, - side: side, - batch: updateDeleteBat, - kind: diffDelete, - }); err2 != nil { - return err2 - } - } - if err2 = send(batchWithKind{ - name: tblName, - side: side, - batch: updateBat, - kind: diffInsert, - }); err2 != nil { - return err2 - } - } else { - if err2 = send(batchWithKind{ - name: tblName, - side: side, - batch: updateBat, - kind: diffUpdate, - }); err2 != nil { - return err2 - } - } - } - - if err2 = send(batchWithKind{ - name: tblName, - side: side, - batch: tBat2, - kind: diffDelete, - }); err2 != nil { - return err2 - } - return nil - } - - tblStuff.retPool.releaseRetBatch(dBat, false) - return nil - } - - if err2 = cursor.ForEach(func(key []byte, _ []byte) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - if tuple, _, err2 = tombstoneHashmap.DecodeRow(key); err2 != nil { - return err2 - } - if err2 = vector.AppendAny(tBat1.Vecs[0], tuple[0], false, ses.proc.Mp()); err2 != nil { - return err2 - } - - tBat1.SetRowCount(tBat1.Vecs[0].Length()) - if tBat1.RowCount() >= maxTombstoneBatchCnt { - tombBat := tBat1 - tBat1 = nil - if err2 = processBatch(tombBat); err2 != nil { - return err2 - } - tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) - } - return nil - }); err2 != nil { - if tBat1 != nil { - tblStuff.retPool.releaseRetBatch(tBat1, true) - } - return err2 - } - - if tBat1 != nil { - return processBatch(tBat1) - } - return nil - - }, -1); err != nil { - return - } - - return nil -} - -func appendTupleToBat(ses *Session, bat *batch.Batch, tuple types.Tuple, tblStuff tableStuff) error { - // exclude the commit ts column - for j, val := range tuple[:len(tuple)-1] { - vec := bat.Vecs[j] - - if err := vector.AppendAny( - vec, val, val == nil, ses.proc.Mp(), - ); err != nil { - return err - } - } - - bat.SetRowCount(bat.Vecs[0].Length()) - - return nil -} - -func checkConflictAndAppendToBat( - ses *Session, copt compositeOption, tblStuff tableStuff, - tarBat, baseBat *batch.Batch, tarTuple, baseTuple types.Tuple, -) (err2 error) { - if copt.conflictOpt != nil { - switch copt.conflictOpt.Opt { - case tree.CONFLICT_FAIL: - buf := acquireBuffer(tblStuff.bufPool) - for i, idx := range tblStuff.def.pkColIdxes { - if err2 = formatValIntoString(ses, tarTuple[idx], tblStuff.def.colTypes[idx], buf); err2 != nil { - releaseBuffer(tblStuff.bufPool, buf) - return err2 - } - if i < len(tblStuff.def.pkColIdxes)-1 { - buf.WriteString(",") - } - } - - msg := buf.String() - releaseBuffer(tblStuff.bufPool, buf) - return moerr.NewInternalErrorNoCtxf( - "conflict: %s %s and %s %s on pk(%v) with different values", - tblStuff.tarRel.GetTableName(), diffInsert, - tblStuff.baseRel.GetTableName(), diffInsert, - msg, - ) - case tree.CONFLICT_SKIP: - return - case tree.CONFLICT_ACCEPT: - // accept the tar's insert - return appendTupleToBat(ses, tarBat, tarTuple, tblStuff) - } - } else { - if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { - return err2 - } - if err2 = appendTupleToBat(ses, baseBat, baseTuple, tblStuff); err2 != nil { - return err2 - } - } - return -} - -func diffDataHelper( - ctx context.Context, - ses *Session, - copt compositeOption, - tblStuff tableStuff, - emit emitFunc, - tarDataHashmap databranchutils.BranchHashmap, - baseDataHashmap databranchutils.BranchHashmap, -) (err error) { - - // if no pk, we cannot use the fake pk to probe. - // must probe with full columns - - if tblStuff.def.pkKind == fakeKind { - var ( - keyIdxes = tblStuff.def.visibleIdxes - newHashmap databranchutils.BranchHashmap - ) - - if newHashmap, err = baseDataHashmap.Migrate(keyIdxes, -1); err != nil { - return err - } - if err = baseDataHashmap.Close(); err != nil { - return err - } - baseDataHashmap = newHashmap - } - - if err = tarDataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - var ( - err2 error - tarBat *batch.Batch - baseBat *batch.Batch - baseDeleteBat *batch.Batch - tarTuple types.Tuple - baseTuple types.Tuple - checkRet databranchutils.GetResult - ) - - tarBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - baseBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - - if err2 = cursor.ForEach(func(key []byte, row []byte) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - if tblStuff.def.pkKind == fakeKind { - if checkRet, err2 = baseDataHashmap.PopByEncodedFullValue(row, false); err2 != nil { - return err2 - } - } else { - if checkRet, err2 = baseDataHashmap.PopByEncodedKey(key, false); err2 != nil { - return err2 - } - } - - if !checkRet.Exists { - if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { - return err2 - } - - if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { - return err2 - } - - } else { - // both has the key, we continue compare the left columns, - // if all columns are equal, exactly the same row, ignore. - if tblStuff.def.pkKind == fakeKind { - // all columns already compared. - // ignore - } else { - if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { - return err2 - } - - if baseTuple, _, err2 = baseDataHashmap.DecodeRow(checkRet.Rows[0]); err2 != nil { - return err2 - } - - notSame := false - for _, idx := range tblStuff.def.visibleIdxes { - if slices.Index(tblStuff.def.pkColIdxes, idx) != -1 { - // pk columns already compared - continue - } - - if types.CompareValue( - tarTuple[idx], baseTuple[idx], - ) != 0 { - notSame = true - break - } - } - - if notSame { - if copt.conflictOpt != nil && - copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT && - copt.expandUpdate { - if baseDeleteBat == nil { - baseDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - } - if err2 = appendTupleToBat(ses, baseDeleteBat, baseTuple, tblStuff); err2 != nil { - return err2 - } - if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { - return err2 - } - } else { - // conflict happened - if err2 = checkConflictAndAppendToBat( - ses, copt, tblStuff, tarBat, baseBat, tarTuple, baseTuple, - ); err2 != nil { - return err2 - } - } - } - } - } - return nil - }); err2 != nil { - return err2 - } - - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - if baseDeleteBat != nil { - if stop, err3 := emitBatch(emit, batchWithKind{ - batch: baseDeleteBat, - kind: diffDelete, - name: tblStuff.baseRel.GetTableName(), - side: diffSideBase, - }, false, tblStuff.retPool); err3 != nil { - return err3 - } else if stop { - return nil - } - } - - if stop, err3 := emitBatch(emit, batchWithKind{ - batch: tarBat, - kind: diffInsert, - name: tblStuff.tarRel.GetTableName(), - side: diffSideTarget, - }, false, tblStuff.retPool); err3 != nil { - return err3 - } else if stop { - return nil - } - - if stop, err3 := emitBatch(emit, batchWithKind{ - batch: baseBat, - kind: diffInsert, - name: tblStuff.baseRel.GetTableName(), - side: diffSideBase, - }, false, tblStuff.retPool); err3 != nil { - return err3 - } else if stop { - return nil - } - - return nil - }, -1); err != nil { - return - } - - if copt.conflictOpt != nil { - if !copt.outputSQL { - // merge doesnt need the base data - return nil - } - } - - if err = baseDataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - var ( - err2 error - tuple types.Tuple - bat *batch.Batch - ) - - bat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - - if err2 = cursor.ForEach(func(_ []byte, row []byte) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: + if dagInfo.lcaType != lcaEmpty { + if dagInfo.lcaTableId == tblStuff.tarRel.GetTableID(ctx) { + tblStuff.lcaRel = tblStuff.tarRel + } else if dagInfo.lcaTableId == tblStuff.baseRel.GetTableID(ctx) { + tblStuff.lcaRel = tblStuff.baseRel + } else { + lcaSnapshot := &plan2.Snapshot{ + Tenant: &plan.SnapshotTenant{ + TenantID: ses.GetAccountId(), + }, } - - if tuple, _, err2 = baseDataHashmap.DecodeRow(row); err2 != nil { - return err2 + lcaSnapshot.TS = ×tamp.Timestamp{PhysicalTime: dagInfo.tarBranchTS.Physical()} + if dagInfo.baseBranchTS.LT(&dagInfo.tarBranchTS) { + lcaSnapshot.TS.PhysicalTime = dagInfo.baseBranchTS.Physical() } - if err2 = appendTupleToBat(ses, bat, tuple, tblStuff); err2 != nil { - return err2 + if tblStuff.lcaRel, err = getRelationById( + ctx, ses, bh, dagInfo.lcaTableId, lcaSnapshot); err != nil { + return } - return nil - }); err2 != nil { - return err2 } + } - select { - case <-ctx.Done(): - return ctx.Err() - default: - } + // has no lca + if tarHandle, baseHandle, err = constructChangeHandle( + ctx, ses, bh, tblStuff, &dagInfo, + ); err != nil { + return + } - if stop, err3 := emitBatch(emit, batchWithKind{ - batch: bat, - kind: diffInsert, - name: tblStuff.baseRel.GetTableName(), - side: diffSideBase, - }, false, tblStuff.retPool); err3 != nil { - return err3 - } else if stop { - return nil - } - return nil - }, -1); err != nil { + if err = hashDiff( + ctx, ses, bh, tblStuff, dagInfo, + copt, emit, tarHandle, baseHandle, + ); err != nil { return } - return nil + closeHandle() + return } func isSchemaEquivalent(leftDef, rightDef *plan.TableDef) bool { @@ -4111,675 +1015,6 @@ func isSchemaEquivalent(leftDef, rightDef *plan.TableDef) bool { return true } -// should read the LCA table to get all column values. -func handleDelsOnLCA( - ctx context.Context, - ses *Session, - bh BackgroundExec, - tBat *batch.Batch, - tblStuff tableStuff, - snapshot timestamp.Timestamp, -) (dBat *batch.Batch, err error) { - - if snapshot.PhysicalTime == 0 { - return nil, moerr.NewInternalErrorNoCtxf("invalid branch ts: %s", snapshot.DebugString()) - } - - var ( - sql string - sqlRet executor.Result - mots = fmt.Sprintf("{MO_TS=%d} ", snapshot.PhysicalTime) - - sqlBuf = acquireBuffer(tblStuff.bufPool) - valsBuf = acquireBuffer(tblStuff.bufPool) - - lcaTblDef = tblStuff.lcaRel.GetTableDef(ctx) - baseTblDef = tblStuff.baseRel.GetTableDef(ctx) - - colTypes = tblStuff.def.colTypes - expandedPKColIdxes = tblStuff.def.pkColIdxes - ) - - defer func() { - releaseBuffer(tblStuff.bufPool, sqlBuf) - releaseBuffer(tblStuff.bufPool, valsBuf) - }() - - pkNames := lcaTblDef.Pkey.Names - - // composite pk - if baseTblDef.Pkey.CompPkeyCol != nil { - var ( - tuple types.Tuple - ) - - cols, area := vector.MustVarlenaRawData(tBat.Vecs[0]) - for i := range cols { - b := cols[i].GetByteSlice(area) - if tuple, err = types.Unpack(b); err != nil { - return nil, err - } - - valsBuf.WriteString(fmt.Sprintf("row(%d,", i)) - - for j := range tuple { - if err = formatValIntoString( - ses, tuple[j], colTypes[expandedPKColIdxes[j]], valsBuf, - ); err != nil { - return nil, err - } - if j != len(tuple)-1 { - valsBuf.WriteString(", ") - } - } - - valsBuf.WriteString(")") - - if i != len(cols)-1 { - valsBuf.WriteString(", ") - } - } - - // fake pk - } else if baseTblDef.Pkey.PkeyColName == catalog.FakePrimaryKeyColName { - - pks := vector.MustFixedColNoTypeCheck[uint64](tBat.Vecs[0]) - for i := range pks { - valsBuf.WriteString(fmt.Sprintf("row(%d,%d)", i, pks[i])) - if i != len(pks)-1 { - valsBuf.WriteString(", ") - } - } - - // real pk - } else { - valsBuf.Reset() - for i := range tBat.Vecs[0].Length() { - valsBuf.WriteString(fmt.Sprintf("row(%d,", i)) - b := tBat.Vecs[0].GetRawBytesAt(i) - val := types.DecodeValue(b, tBat.Vecs[0].GetType().Oid) - switch x := val.(type) { - case []byte: - valsBuf.WriteString("'") - valsBuf.WriteString(string(x)) - valsBuf.WriteString("'") - case string: - valsBuf.WriteString("'") - valsBuf.WriteString(string(x)) - valsBuf.WriteString("'") - default: - valsBuf.WriteString(fmt.Sprintf("%v", x)) - } - valsBuf.WriteString(")") - - if i != tBat.Vecs[0].Length()-1 { - valsBuf.WriteString(",") - } - } - } - - sqlBuf.Reset() - sqlBuf.WriteString(fmt.Sprintf( - "select pks.__idx_, lca.* from %s.%s%s as lca ", - lcaTblDef.DbName, lcaTblDef.Name, mots), - ) - - sqlBuf.WriteString(fmt.Sprintf( - "right join (values %s) as pks(__idx_,%s) on ", - valsBuf.String(), strings.Join(pkNames, ",")), - ) - - for i := range pkNames { - sqlBuf.WriteString(fmt.Sprintf("lca.%s = ", pkNames[i])) - switch typ := colTypes[expandedPKColIdxes[i]]; typ.Oid { - case types.T_int32: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as INT)", pkNames[i])) - case types.T_int64: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as BIGINT)", pkNames[i])) - case types.T_uint32: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as INT UNSIGNED)", pkNames[i])) - case types.T_uint64: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as BIGINT UNSIGNED)", pkNames[i])) - case types.T_float32: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as FLOAT)", pkNames[i])) - case types.T_float64: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as DOUBLE)", pkNames[i])) - case types.T_varchar: - sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as VARCHAR)", pkNames[i])) - default: - sqlBuf.WriteString(fmt.Sprintf("pks.%s", pkNames[i])) - } - if i != len(pkNames)-1 { - sqlBuf.WriteString(" AND ") - } - } - - sqlBuf.WriteString(" order by pks.__idx_") - - sql = sqlBuf.String() - if sqlRet, err = runSql(ctx, ses, bh, sql, nil, nil); err != nil { - return - } - - notExist := func(cols []*vector.Vector, r int) bool { - exist := false - for _, col := range cols { - if !col.GetNulls().Contains(uint64(r)) { - exist = true - break - } - } - return !exist - } - - dBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) - - endIdx := dBat.VectorCount() - 1 - - sels := make([]int64, 0, 100) - sqlRet.ReadRows(func(rowCnt int, cols []*vector.Vector) bool { - for i := range rowCnt { - if notExist(cols[1:], i) { - idx := vector.GetFixedAtNoTypeCheck[int64](cols[0], i) - sels = append(sels, int64(idx)) - continue - } - - for j := 1; j < len(cols); j++ { - if err = dBat.Vecs[j-1].UnionOne(cols[j], int64(i), ses.proc.Mp()); err != nil { - return false - } - } - - if tblStuff.def.pkKind != normalKind { - if err = dBat.Vecs[endIdx].UnionOne(tBat.Vecs[0], int64(i), ses.proc.Mp()); err != nil { - return false - } - } - } - - dBat.SetRowCount(dBat.Vecs[0].Length()) - return true - }) - - sqlRet.Close() - - if len(sels) == 0 { - tBat.Vecs[0].CleanOnlyData() - tBat.SetRowCount(0) - } else { - tBat.Vecs[0].Shrink(sels, false) - tBat.SetRowCount(tBat.Vecs[0].Length()) - } - - return -} - -func formatValIntoString(ses *Session, val any, t types.Type, buf *bytes.Buffer) error { - if val == nil { - buf.WriteString("NULL") - return nil - } - - var scratch [64]byte - - writeInt := func(v int64) { - buf.Write(strconv.AppendInt(scratch[:0], v, 10)) - } - - writeUint := func(v uint64) { - buf.Write(strconv.AppendUint(scratch[:0], v, 10)) - } - - writeFloat := func(v float64, bitSize int) { - buf.Write(strconv.AppendFloat(scratch[:0], v, 'g', -1, bitSize)) - } - - writeBool := func(v bool) { - buf.WriteString(strconv.FormatBool(v)) - } - - switch t.Oid { - case types.T_varchar, types.T_text, types.T_json, types.T_char, types. - T_varbinary, types.T_binary: - if t.Oid == types.T_json { - var strVal string - switch x := val.(type) { - case bytejson.ByteJson: - strVal = x.String() - case *bytejson.ByteJson: - if x == nil { - return moerr.NewInternalErrorNoCtx("formatValIntoString: nil *bytejson.ByteJson") - } - strVal = x.String() - case []byte: - strVal = string(x) - case string: - strVal = x - default: - return moerr.NewInternalErrorNoCtxf("formatValIntoString: unexpected json type %T", val) - } - jsonLiteral := escapeJSONControlBytes([]byte(strVal)) - if !json.Valid(jsonLiteral) { - return moerr.NewInternalErrorNoCtxf("formatValIntoString: invalid json input %q", strVal) - } - writeEscapedSQLString(buf, jsonLiteral) - return nil - } - switch x := val.(type) { - case []byte: - writeEscapedSQLString(buf, x) - case string: - writeEscapedSQLString(buf, []byte(x)) - default: - return moerr.NewInternalErrorNoCtxf("formatValIntoString: unexpected string type %T", val) - } - case types.T_timestamp: - buf.WriteString("'") - buf.WriteString(val.(types.Timestamp).String2(ses.timeZone, t.Scale)) - buf.WriteString("'") - case types.T_datetime: - buf.WriteString("'") - buf.WriteString(val.(types.Datetime).String2(t.Scale)) - buf.WriteString("'") - case types.T_time: - buf.WriteString("'") - buf.WriteString(val.(types.Time).String2(t.Scale)) - buf.WriteString("'") - case types.T_date: - buf.WriteString("'") - buf.WriteString(val.(types.Date).String()) - buf.WriteString("'") - case types.T_year: - buf.WriteString(val.(types.MoYear).String()) - case types.T_decimal64: - buf.WriteString(val.(types.Decimal64).Format(t.Scale)) - case types.T_decimal128: - buf.WriteString(val.(types.Decimal128).Format(t.Scale)) - case types.T_decimal256: - buf.WriteString(val.(types.Decimal256).Format(t.Scale)) - case types.T_bool: - writeBool(val.(bool)) - case types.T_uint8: - writeUint(uint64(val.(uint8))) - case types.T_uint16: - writeUint(uint64(val.(uint16))) - case types.T_uint32: - writeUint(uint64(val.(uint32))) - case types.T_uint64: - writeUint(val.(uint64)) - case types.T_int8: - writeInt(int64(val.(int8))) - case types.T_int16: - writeInt(int64(val.(int16))) - case types.T_int32: - writeInt(int64(val.(int32))) - case types.T_int64: - writeInt(val.(int64)) - case types.T_float32: - writeFloat(float64(val.(float32)), 32) - case types.T_float64: - writeFloat(val.(float64), 64) - case types.T_array_float32: - buf.WriteString("'") - buf.WriteString(types.ArrayToString[float32](val.([]float32))) - buf.WriteString("'") - case types.T_array_float64: - buf.WriteString("'") - buf.WriteString(types.ArrayToString[float64](val.([]float64))) - buf.WriteString("'") - default: - return moerr.NewNotSupportedNoCtxf("formatValIntoString: not support type %v", t.Oid) - } - - return nil -} - -// writeEscapedSQLString escapes special and control characters for SQL literal output. -func writeEscapedSQLString(buf *bytes.Buffer, b []byte) { - buf.WriteByte('\'') - for _, c := range b { - switch c { - case '\'': - buf.WriteString("\\'") - //case '"': - // buf.WriteString("\\\"") - case '\\': - buf.WriteString("\\\\") - case 0: - buf.WriteString("\\0") - case '\b': - buf.WriteString("\\b") - case '\n': - buf.WriteString("\\n") - case '\r': - buf.WriteString("\\r") - case '\t': - buf.WriteString("\\t") - case 0x1A: - buf.WriteString("\\Z") - default: - if c < 0x20 || c == 0x7f { - buf.WriteString("\\x") - buf.WriteString(hex.EncodeToString([]byte{c})) - } else { - buf.WriteByte(c) - } - } - } - buf.WriteByte('\'') -} - -// escapeJSONControlChars converts control characters to JSON-compliant \u00XX escapes. -func escapeJSONControlBytes(b []byte) []byte { - var out []byte - hexDigits := "0123456789abcdef" - - for i, c := range b { - if c < 0x20 || c == 0x7f { - if out == nil { - out = make([]byte, 0, len(b)+8) - out = append(out, b[:i]...) - } - out = append(out, '\\', 'u', '0', '0', hexDigits[c>>4], hexDigits[c&0xf]) - continue - } - if out != nil { - out = append(out, c) - } - } - - if out == nil { - return b - } - return out -} - -func buildHashmapForTable( - ctx context.Context, - mp *mpool.MPool, - lcaType int, - tblStuff *tableStuff, - handles []engine.ChangesHandle, -) ( - dataHashmap databranchutils.BranchHashmap, - tombstoneHashmap databranchutils.BranchHashmap, - err error, -) { - - var ( - atomicErr atomic.Value - dataBat *batch.Batch - tombstoneBat *batch.Batch - wg sync.WaitGroup - totalRows int64 - totalBytes int64 - ) - - defer func() { - wg.Wait() - - if dataBat != nil { - dataBat.Clean(mp) - } - - if tombstoneBat != nil { - tombstoneBat.Clean(mp) - } - }() - - if dataHashmap, err = databranchutils.NewBranchHashmap( - databranchutils.WithBranchHashmapAllocator(tblStuff.hashmapAllocator), - ); err != nil { - return - } - - if tombstoneHashmap, err = databranchutils.NewBranchHashmap( - databranchutils.WithBranchHashmapAllocator(tblStuff.hashmapAllocator), - ); err != nil { - return - } - - putVectors := func(bat *batch.Batch, isTombstone bool) error { - if bat == nil { - return nil - } - select { - case <-ctx.Done(): - bat.Clean(mp) - return ctx.Err() - default: - } - - wg.Add(1) - - if err = tblStuff.worker.Submit(func() { - defer wg.Done() - defer bat.Clean(mp) - - ll := bat.VectorCount() - var taskErr error - select { - case <-ctx.Done(): - taskErr = ctx.Err() - default: - if isTombstone { - // keep the commit ts - taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll], []int{0}) - } else { - // keep the commit ts - taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll], []int{tblStuff.def.pkColIdx}) - } - } - if taskErr != nil { - atomicErr.Store(taskErr) - } - }); err != nil { - wg.Done() - bat.Clean(mp) - } - - return err - } - - for _, handle := range handles { - for { - select { - case <-ctx.Done(): - err = ctx.Err() - return - default: - } - if dataBat, tombstoneBat, _, err = handle.Next( - ctx, mp, - ); err != nil { - return - } else if dataBat == nil && tombstoneBat == nil { - // out of data - break - } - - if dataBat != nil && dataBat.RowCount() > 0 { - totalRows += int64(dataBat.RowCount()) - totalBytes += int64(dataBat.Size()) - } - - if atomicErr.Load() != nil { - err = atomicErr.Load().(error) - return - } - - if err = putVectors(dataBat, false); err != nil { - return - } - - if err = putVectors(tombstoneBat, true); err != nil { - return - } - } - } - - wg.Wait() - - if atomicErr.Load() != nil { - err = atomicErr.Load().(error) - } else { - select { - case <-ctx.Done(): - err = ctx.Err() - default: - } - } - - if err != nil { - return - } - - if tombstoneHashmap.ItemCount() == 0 && dataHashmap.ItemCount() == 0 { - return - } - - if tblStuff.maxTombstoneBatchCnt == 0 { - rowBytes := defaultRowBytes - if totalRows > 0 { - rowBytes = totalBytes / totalRows - if rowBytes <= 0 { - rowBytes = defaultRowBytes - } - } - rowBytes = rowBytes * tombstoneRowMult / tombstoneRowDiv - - available := tblStuff.hashmapAllocator.Available() / 3 - - shardCount := 0 - if tombstoneHashmap != nil { - shardCount = tombstoneHashmap.ShardCount() - } else if dataHashmap != nil { - shardCount = dataHashmap.ShardCount() - } - - maxByMem := int(available / int64(shardCount) / rowBytes) - if maxByMem < 1 { - maxByMem = 1 - } else if maxByMem > maxSqlBatchCnt { - maxByMem = maxSqlBatchCnt - } - - tblStuff.maxTombstoneBatchCnt = maxByMem - } - - if tblStuff.def.pkKind == fakeKind { - return - } - - /* - case 1: - insert update update update - pk1 pk1 pk1 pk1 .... - |------|-------------------------------------| - | collect range | - 1.1. the last one is an update: only keep the last update op - 1.2. the last one is a deletion: only keep the last deletion op - - case 2: - insert update update - pk1 pk1 pk1 .... - |------|-------------------------------------| - | collect range | - 2.1. the last one is an update: only keep the last update op - 2.2. the last one is a deletion: only keep the last deletion op - - case 3: - insert delete update update - pk1 pk1 pk1 pk1 .... - |------|-------------------------------------| - | collect range | - 3.1. the last one is an update: only keep the last update op - 3.2. the last one is a deletion: only keep the last deletion op - */ - - if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { - var ( - err2 error - err3 error - maxTs types.TS - maxIdx int - tuple types.Tuple - dataRet databranchutils.GetResult - ) - if err2 = cursor.ForEach(func(key []byte, _ []byte) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - var tombstoneRet databranchutils.GetResult - if tombstoneRet, err3 = cursor.GetByEncodedKey(key); err3 != nil { - return err3 - } - if len(tombstoneRet.Rows) <= 1 { - return nil - } - - //tsMap := make(map[types.TS]struct{}) - maxIdx = 0 - maxTs = types.MinTs() - for i := 0; i < len(tombstoneRet.Rows); i++ { - if tuple, _, err3 = tombstoneHashmap.DecodeRow(tombstoneRet.Rows[i]); err3 != nil { - return err3 - } - cur := types.TS(tuple[len(tuple)-1].([]uint8)) - if cur.GT(&maxTs) { - maxTs = cur - maxIdx = i - } - //tsMap[cur] = struct{}{} - } - //delete(tsMap, maxTs) - - for i := range tombstoneRet.Rows { - if i != maxIdx { - if _, err3 = cursor.PopByEncodedKeyValue( - key, tombstoneRet.Rows[i], false, - ); err3 != nil { - return err3 - } - } - } - - if dataRet, err3 = dataHashmap.GetByEncodedKey(key); err3 != nil { - return err3 - } - - if dataRet.Exists { - for i := range dataRet.Rows { - if tuple, _, err3 = dataHashmap.DecodeRow(dataRet.Rows[i]); err3 != nil { - return err3 - } - cur := types.TS(tuple[len(tuple)-1].([]uint8)) - // cannot use tsMap to filter, why? - // cannot use cur != maxTS to filter, why? - if cur.LT(&maxTs) { - if _, err3 = dataHashmap.PopByEncodedKeyValue( - key, dataRet.Rows[i], false, - ); err3 != nil { - return err3 - } - } - } - } - return nil - }); err2 != nil { - return err2 - } - return nil - }, -1); err != nil { - return nil, nil, err - } - - return -} - func getRelationById( ctx context.Context, ses *Session, @@ -5426,181 +1661,3 @@ func constructBranchDAG( return databranchutils.NewDAG(rowData), nil } - -func compareSingleValInVector( - ctx context.Context, - ses *Session, - rowIdx1 int, - rowIdx2 int, - vec1 *vector.Vector, - vec2 *vector.Vector, -) (int, error) { - - if !vec1.GetType().Eq(*vec2.GetType()) { - return 0, moerr.NewInternalErrorNoCtxf( - "type not matched: %v <-> %v", - vec1.GetType().String(), vec2.GetType().String(), - ) - } - - if vec1.IsConst() { - rowIdx1 = 0 - } - if vec2.IsConst() { - rowIdx2 = 0 - } - - // Treat NULL as equal only when both sides are NULL. - if vec1.IsNull(uint64(rowIdx1)) || vec2.IsNull(uint64(rowIdx2)) { - if vec1.IsNull(uint64(rowIdx1)) && vec2.IsNull(uint64(rowIdx2)) { - return 0, nil - } - return 1, nil - } - - // Use raw values to avoid format conversions in extractRowFromVector. - switch vec1.GetType().Oid { - case types.T_json: - return bytejson.CompareByteJson( - types.DecodeJson(vec1.GetBytesAt(rowIdx1)), - types.DecodeJson(vec2.GetBytesAt(rowIdx2)), - ), nil - case types.T_bool: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[bool](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[bool](vec2, rowIdx2), - ), nil - case types.T_bit: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[uint64](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[uint64](vec2, rowIdx2), - ), nil - case types.T_int8: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[int8](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[int8](vec2, rowIdx2), - ), nil - case types.T_uint8: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[uint8](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[uint8](vec2, rowIdx2), - ), nil - case types.T_int16: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[int16](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[int16](vec2, rowIdx2), - ), nil - case types.T_uint16: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[uint16](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[uint16](vec2, rowIdx2), - ), nil - case types.T_int32: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[int32](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[int32](vec2, rowIdx2), - ), nil - case types.T_uint32: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[uint32](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[uint32](vec2, rowIdx2), - ), nil - case types.T_int64: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[int64](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[int64](vec2, rowIdx2), - ), nil - case types.T_uint64: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[uint64](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[uint64](vec2, rowIdx2), - ), nil - case types.T_float32: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[float32](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[float32](vec2, rowIdx2), - ), nil - case types.T_float64: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[float64](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[float64](vec2, rowIdx2), - ), nil - case types.T_char, types.T_varchar, types.T_blob, types.T_text, types.T_binary, types.T_varbinary, types.T_datalink: - return bytes.Compare( - vec1.GetBytesAt(rowIdx1), - vec2.GetBytesAt(rowIdx2), - ), nil - case types.T_array_float32: - return types.CompareValue( - vector.GetArrayAt[float32](vec1, rowIdx1), - vector.GetArrayAt[float32](vec2, rowIdx2), - ), nil - case types.T_array_float64: - return types.CompareValue( - vector.GetArrayAt[float64](vec1, rowIdx1), - vector.GetArrayAt[float64](vec2, rowIdx2), - ), nil - case types.T_date: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Date](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Date](vec2, rowIdx2), - ), nil - case types.T_datetime: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Datetime](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Datetime](vec2, rowIdx2), - ), nil - case types.T_time: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Time](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Time](vec2, rowIdx2), - ), nil - case types.T_timestamp: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Timestamp](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Timestamp](vec2, rowIdx2), - ), nil - case types.T_year: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.MoYear](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.MoYear](vec2, rowIdx2), - ), nil - case types.T_decimal64: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Decimal64](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Decimal64](vec2, rowIdx2), - ), nil - case types.T_decimal128: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Decimal128](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Decimal128](vec2, rowIdx2), - ), nil - case types.T_uuid: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Uuid](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Uuid](vec2, rowIdx2), - ), nil - case types.T_Rowid: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Rowid](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Rowid](vec2, rowIdx2), - ), nil - case types.T_Blockid: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Blockid](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Blockid](vec2, rowIdx2), - ), nil - case types.T_TS: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.TS](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.TS](vec2, rowIdx2), - ), nil - case types.T_enum: - return types.CompareValue( - vector.GetFixedAtNoTypeCheck[types.Enum](vec1, rowIdx1), - vector.GetFixedAtNoTypeCheck[types.Enum](vec2, rowIdx2), - ), nil - default: - return 0, moerr.NewInternalErrorNoCtxf("compareSingleValInVector : unsupported type %d", vec1.GetType().Oid) - } -} diff --git a/pkg/frontend/data_branch_hashdiff.go b/pkg/frontend/data_branch_hashdiff.go new file mode 100644 index 0000000000000..bdd47974ef29d --- /dev/null +++ b/pkg/frontend/data_branch_hashdiff.go @@ -0,0 +1,1528 @@ +// Copyright 2025 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "context" + "errors" + "fmt" + "slices" + "strings" + "sync" + "sync/atomic" + + "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/frontend/databranchutils" + "github.com/matrixorigin/matrixone/pkg/objectio/mergeutil" + "github.com/matrixorigin/matrixone/pkg/pb/timestamp" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" + "github.com/matrixorigin/matrixone/pkg/util/executor" + "github.com/matrixorigin/matrixone/pkg/vm/engine" +) + +// should read the LCA table to get all column values. +func handleDelsOnLCA( + ctx context.Context, + ses *Session, + bh BackgroundExec, + tBat *batch.Batch, + tblStuff tableStuff, + snapshot timestamp.Timestamp, +) (dBat *batch.Batch, err error) { + + if snapshot.PhysicalTime == 0 { + return nil, moerr.NewInternalErrorNoCtxf("invalid branch ts: %s", snapshot.DebugString()) + } + + var ( + sql string + sqlRet executor.Result + mots = fmt.Sprintf("{MO_TS=%d} ", snapshot.PhysicalTime) + + sqlBuf = acquireBuffer(tblStuff.bufPool) + valsBuf = acquireBuffer(tblStuff.bufPool) + + lcaTblDef = tblStuff.lcaRel.GetTableDef(ctx) + baseTblDef = tblStuff.baseRel.GetTableDef(ctx) + + colTypes = tblStuff.def.colTypes + expandedPKColIdxes = tblStuff.def.pkColIdxes + ) + + defer func() { + releaseBuffer(tblStuff.bufPool, sqlBuf) + releaseBuffer(tblStuff.bufPool, valsBuf) + }() + + pkNames := lcaTblDef.Pkey.Names + + // composite pk + if baseTblDef.Pkey.CompPkeyCol != nil { + var ( + tuple types.Tuple + ) + + cols, area := vector.MustVarlenaRawData(tBat.Vecs[0]) + for i := range cols { + b := cols[i].GetByteSlice(area) + if tuple, err = types.Unpack(b); err != nil { + return nil, err + } + + valsBuf.WriteString(fmt.Sprintf("row(%d,", i)) + + for j := range tuple { + if err = formatValIntoString( + ses, tuple[j], colTypes[expandedPKColIdxes[j]], valsBuf, + ); err != nil { + return nil, err + } + if j != len(tuple)-1 { + valsBuf.WriteString(", ") + } + } + + valsBuf.WriteString(")") + + if i != len(cols)-1 { + valsBuf.WriteString(", ") + } + } + + // fake pk + } else if baseTblDef.Pkey.PkeyColName == catalog.FakePrimaryKeyColName { + + pks := vector.MustFixedColNoTypeCheck[uint64](tBat.Vecs[0]) + for i := range pks { + valsBuf.WriteString(fmt.Sprintf("row(%d,%d)", i, pks[i])) + if i != len(pks)-1 { + valsBuf.WriteString(", ") + } + } + + // real pk + } else { + valsBuf.Reset() + for i := range tBat.Vecs[0].Length() { + valsBuf.WriteString(fmt.Sprintf("row(%d,", i)) + b := tBat.Vecs[0].GetRawBytesAt(i) + val := types.DecodeValue(b, tBat.Vecs[0].GetType().Oid) + switch x := val.(type) { + case []byte: + valsBuf.WriteString("'") + valsBuf.WriteString(string(x)) + valsBuf.WriteString("'") + case string: + valsBuf.WriteString("'") + valsBuf.WriteString(string(x)) + valsBuf.WriteString("'") + default: + valsBuf.WriteString(fmt.Sprintf("%v", x)) + } + valsBuf.WriteString(")") + + if i != tBat.Vecs[0].Length()-1 { + valsBuf.WriteString(",") + } + } + } + + sqlBuf.Reset() + sqlBuf.WriteString(fmt.Sprintf( + "select pks.__idx_, lca.* from %s.%s%s as lca ", + lcaTblDef.DbName, lcaTblDef.Name, mots), + ) + + sqlBuf.WriteString(fmt.Sprintf( + "right join (values %s) as pks(__idx_,%s) on ", + valsBuf.String(), strings.Join(pkNames, ",")), + ) + + for i := range pkNames { + sqlBuf.WriteString(fmt.Sprintf("lca.%s = ", pkNames[i])) + switch typ := colTypes[expandedPKColIdxes[i]]; typ.Oid { + case types.T_int32: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as INT)", pkNames[i])) + case types.T_int64: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as BIGINT)", pkNames[i])) + case types.T_uint32: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as INT UNSIGNED)", pkNames[i])) + case types.T_uint64: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as BIGINT UNSIGNED)", pkNames[i])) + case types.T_float32: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as FLOAT)", pkNames[i])) + case types.T_float64: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as DOUBLE)", pkNames[i])) + case types.T_varchar: + sqlBuf.WriteString(fmt.Sprintf("cast(pks.%s as VARCHAR)", pkNames[i])) + default: + sqlBuf.WriteString(fmt.Sprintf("pks.%s", pkNames[i])) + } + if i != len(pkNames)-1 { + sqlBuf.WriteString(" AND ") + } + } + + sqlBuf.WriteString(" order by pks.__idx_") + + sql = sqlBuf.String() + if sqlRet, err = runSql(ctx, ses, bh, sql, nil, nil); err != nil { + return + } + + notExist := func(cols []*vector.Vector, r int) bool { + exist := false + for _, col := range cols { + if !col.GetNulls().Contains(uint64(r)) { + exist = true + break + } + } + return !exist + } + + dBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + + endIdx := dBat.VectorCount() - 1 + + sels := make([]int64, 0, 100) + sqlRet.ReadRows(func(rowCnt int, cols []*vector.Vector) bool { + for i := range rowCnt { + if notExist(cols[1:], i) { + idx := vector.GetFixedAtNoTypeCheck[int64](cols[0], i) + sels = append(sels, int64(idx)) + continue + } + + for j := 1; j < len(cols); j++ { + if err = dBat.Vecs[j-1].UnionOne(cols[j], int64(i), ses.proc.Mp()); err != nil { + return false + } + } + + if tblStuff.def.pkKind != normalKind { + if err = dBat.Vecs[endIdx].UnionOne(tBat.Vecs[0], int64(i), ses.proc.Mp()); err != nil { + return false + } + } + } + + dBat.SetRowCount(dBat.Vecs[0].Length()) + return true + }) + + sqlRet.Close() + + if len(sels) == 0 { + tBat.Vecs[0].CleanOnlyData() + tBat.SetRowCount(0) + } else { + tBat.Vecs[0].Shrink(sels, false) + tBat.SetRowCount(tBat.Vecs[0].Length()) + } + + return +} + +func hashDiff( + ctx context.Context, + ses *Session, + bh BackgroundExec, + tblStuff tableStuff, + dagInfo branchMetaInfo, + copt compositeOption, + emit emitFunc, + tarHandle []engine.ChangesHandle, + baseHandle []engine.ChangesHandle, +) ( + err error, +) { + + var ( + baseDataHashmap databranchutils.BranchHashmap + baseTombstoneHashmap databranchutils.BranchHashmap + + tarDataHashmap databranchutils.BranchHashmap + tarTombstoneHashmap databranchutils.BranchHashmap + ) + + defer func() { + if baseDataHashmap != nil { + baseDataHashmap.Close() + } + if baseTombstoneHashmap != nil { + baseTombstoneHashmap.Close() + } + if tarDataHashmap != nil { + tarDataHashmap.Close() + } + if tarTombstoneHashmap != nil { + tarTombstoneHashmap.Close() + } + }() + + if baseDataHashmap, baseTombstoneHashmap, err = buildHashmapForTable( + ctx, ses.proc.Mp(), dagInfo.lcaType, &tblStuff, baseHandle, + ); err != nil { + return + } + + if tarDataHashmap, tarTombstoneHashmap, err = buildHashmapForTable( + ctx, ses.proc.Mp(), dagInfo.lcaType, &tblStuff, tarHandle, + ); err != nil { + return + } + + if dagInfo.lcaType == lcaEmpty { + if err = hashDiffIfNoLCA( + ctx, ses, tblStuff, copt, emit, + tarDataHashmap, tarTombstoneHashmap, + baseDataHashmap, baseTombstoneHashmap, + ); err != nil { + return + } + } else { + if err = hashDiffIfHasLCA( + ctx, ses, bh, dagInfo, tblStuff, copt, emit, + tarDataHashmap, tarTombstoneHashmap, + baseDataHashmap, baseTombstoneHashmap, + ); err != nil { + return + } + } + + return +} + +func hashDiffIfHasLCA( + ctx context.Context, + ses *Session, + bh BackgroundExec, + dagInfo branchMetaInfo, + tblStuff tableStuff, + copt compositeOption, + emit emitFunc, + tarDataHashmap databranchutils.BranchHashmap, + tarTombstoneHashmap databranchutils.BranchHashmap, + baseDataHashmap databranchutils.BranchHashmap, + baseTombstoneHashmap databranchutils.BranchHashmap, +) (err error) { + + var ( + wg sync.WaitGroup + atomicErr atomic.Value + + baseDeleteBatches []batchWithKind + baseUpdateBatches []batchWithKind + ) + + handleBaseDeleteAndUpdates := func(wrapped batchWithKind) error { + wrapped.side = diffSideBase + if err2 := mergeutil.SortColumnsByIndex( + wrapped.batch.Vecs, tblStuff.def.pkColIdx, ses.proc.Mp(), + ); err2 != nil { + return err2 + } + if wrapped.kind == diffDelete { + baseDeleteBatches = append(baseDeleteBatches, wrapped) + } else { + baseUpdateBatches = append(baseUpdateBatches, wrapped) + } + + return nil + } + + handleTarDeleteAndUpdates := func(wrapped batchWithKind) (err2 error) { + wrapped.side = diffSideTarget + if len(baseUpdateBatches) == 0 && len(baseDeleteBatches) == 0 { + // no need to check conflict + if stop, e := emitBatch(emit, wrapped, false, tblStuff.retPool); e != nil { + return e + } else if stop { + return nil + } + return nil + } + + if err2 = mergeutil.SortColumnsByIndex( + wrapped.batch.Vecs, tblStuff.def.pkColIdx, ses.proc.Mp(), + ); err2 != nil { + return err2 + } + + checkConflict := func(tarWrapped, baseWrapped batchWithKind) (sels1, sels2 []int64, err3 error) { + var ( + cmp int + tarVec = tarWrapped.batch.Vecs[tblStuff.def.pkColIdx] + baseVec = baseWrapped.batch.Vecs[tblStuff.def.pkColIdx] + ) + + i, j := 0, 0 + for i < tarVec.Length() && j < baseVec.Length() { + if cmp, err3 = compareSingleValInVector( + ctx, ses, i, j, tarVec, baseVec, + ); err3 != nil { + return + } + + if cmp == 0 { + // conflict + // tar and base both deleted on pk1 => empty + // tar and base both updated on pk1 => we need compare the left columns, consider + // the conflict option. + if copt.conflictOpt == nil { + if tarWrapped.kind == baseWrapped.kind { + // compare the left column values + if cmp, err3 = compareRowInWrappedBatches( + ctx, ses, tblStuff, i, j, true, + tarWrapped, baseWrapped, + ); err3 != nil { + return + } else if cmp == 0 { + sels1 = append(sels1, int64(i)) + sels2 = append(sels2, int64(j)) + } + } + i++ + j++ + } else if copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT { + // only keep the rows from tar + sels2 = append(sels2, int64(j)) + i++ + j++ + } else if copt.conflictOpt.Opt == tree.CONFLICT_SKIP { + sels1 = append(sels1, int64(i)) + sels2 = append(sels2, int64(j)) + i++ + j++ + } else { + // copt.conflictOpt == tree.CONFLICT_FAIL + tarRow := make([]any, 1) + if err3 = extractRowFromVector( + ctx, ses, tarVec, 0, tarRow, i, false, + ); err3 != nil { + return + } + + buf := acquireBuffer(tblStuff.bufPool) + if err3 = formatValIntoString( + ses, tarRow[0], tblStuff.def.colTypes[tblStuff.def.pkColIdx], buf, + ); err3 != nil { + releaseBuffer(tblStuff.bufPool, buf) + return + } + + err3 = moerr.NewInternalErrorNoCtxf( + "conflict: %s %s and %s %s on pk(%v) with different values", + tarWrapped.name, tarWrapped.kind, + baseWrapped.name, baseWrapped.kind, buf.String(), + ) + releaseBuffer(tblStuff.bufPool, buf) + return + } + } else if cmp < 0 { + // tarVal < baseVal + i++ + } else { + // tarVal > baseVal + j++ + } + } + + return + } + + foo := func(baseWrappedList []batchWithKind) (err3 error) { + for _, baseWrapped := range baseWrappedList { + var ( + sels1 []int64 + sels2 []int64 + ) + if sels1, sels2, err3 = checkConflict(wrapped, baseWrapped); err3 != nil { + return + } else { + if len(sels1) != 0 { + wrapped.batch.Shrink(sels1, true) + } + + if len(sels2) != 0 { + baseWrapped.batch.Shrink(sels2, true) + } + } + + if wrapped.batch.RowCount() == 0 { + break + } + } + + return + } + + if err2 = foo(baseDeleteBatches); err2 != nil { + return + } + + baseDeleteBatches = plan2.RemoveIf(baseDeleteBatches, func(t batchWithKind) bool { + if t.batch.RowCount() == 0 { + tblStuff.retPool.releaseRetBatch(t.batch, false) + return true + } + return false + }) + + if err2 = foo(baseUpdateBatches); err2 != nil { + return + } + + baseUpdateBatches = plan2.RemoveIf(baseUpdateBatches, func(t batchWithKind) bool { + if t.batch.RowCount() == 0 { + tblStuff.retPool.releaseRetBatch(t.batch, false) + return true + } + return false + }) + + if wrapped.batch.RowCount() == 0 { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + return + } + + stop, e := emitBatch(emit, wrapped, false, tblStuff.retPool) + if e != nil { + return e + } + if stop { + return nil + } + + return + } + + newCtx, cancel := context.WithCancel(ctx) + defer cancel() + + asyncDelsAndUpdatesHandler := func(forBase bool, tmpCh chan batchWithKind) (err2 error) { + var ( + branchTS = dagInfo.baseBranchTS + hashmap1 = baseDataHashmap + hashmap2 = baseTombstoneHashmap + name = tblStuff.baseRel.GetTableName() + ) + + if !forBase { + branchTS = dagInfo.tarBranchTS + hashmap1 = tarDataHashmap + hashmap2 = tarTombstoneHashmap + name = tblStuff.tarRel.GetTableName() + } + + wg.Add(1) + if err2 = tblStuff.worker.Submit(func() { + defer func() { + close(tmpCh) + tmpCh = nil + wg.Done() + }() + + if err3 := findDeleteAndUpdateBat( + newCtx, ses, bh, tblStuff, name, + func() int { + if forBase { + return diffSideBase + } + return diffSideTarget + }(), + tmpCh, branchTS, copt.expandUpdate, hashmap1, hashmap2, + ); err3 != nil { + atomicErr.Store(err3) + } + }); err2 != nil { + wg.Done() + return + } + return nil + } + + stepHandler := func(forBase bool) (err2 error) { + var ( + tmpCh = make(chan batchWithKind, 1) + first error + ) + + if err2 = asyncDelsAndUpdatesHandler(forBase, tmpCh); err2 != nil { + return err2 + } + + for wrapped := range tmpCh { + if first != nil { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + select { + case <-ctx.Done(): + first = ctx.Err() + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + default: + if forBase { + err2 = handleBaseDeleteAndUpdates(wrapped) + } else { + err2 = handleTarDeleteAndUpdates(wrapped) + } + + if errors.Is(err2, context.Canceled) { + err2 = nil + cancel() + } + } + + if err2 != nil { + first = err2 + cancel() + } + } + + wg.Wait() + if first != nil { + return first + } + + if atomicErr.Load() != nil { + return atomicErr.Load().(error) + } + + return first + } + + // phase 1: handle base dels and updates on lca + if err = stepHandler(true); err != nil { + return + } + + // phase2: handle tar dels and updates on lca + if err = stepHandler(false); err != nil { + return + } + + // what can I do with these left base updates/inserts ? + if copt.conflictOpt == nil { + stopped := false + for i, w := range baseUpdateBatches { + var stop bool + if stop, err = emitBatch(emit, w, false, tblStuff.retPool); err != nil { + return err + } + if stop { + stopped = true + for j := i + 1; j < len(baseUpdateBatches); j++ { + tblStuff.retPool.releaseRetBatch(baseUpdateBatches[j].batch, false) + } + for _, bw := range baseDeleteBatches { + tblStuff.retPool.releaseRetBatch(bw.batch, false) + } + break + } + } + + if !stopped { + for i, w := range baseDeleteBatches { + var stop bool + if stop, err = emitBatch(emit, w, false, tblStuff.retPool); err != nil { + return err + } + if stop { + for j := i + 1; j < len(baseDeleteBatches); j++ { + tblStuff.retPool.releaseRetBatch(baseDeleteBatches[j].batch, false) + } + break + } + } + } + } + + return diffDataHelper(ctx, ses, copt, tblStuff, emit, tarDataHashmap, baseDataHashmap) +} + +func hashDiffIfNoLCA( + ctx context.Context, + ses *Session, + tblStuff tableStuff, + copt compositeOption, + emit emitFunc, + tarDataHashmap databranchutils.BranchHashmap, + tarTombstoneHashmap databranchutils.BranchHashmap, + baseDataHashmap databranchutils.BranchHashmap, + baseTombstoneHashmap databranchutils.BranchHashmap, +) (err error) { + + if err = tarTombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + return cursor.ForEach(func(key []byte, _ []byte) error { + _, err2 := tarDataHashmap.PopByEncodedKey(key, true) + return err2 + }) + + }, -1); err != nil { + return + } + + if err = baseTombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + return cursor.ForEach(func(key []byte, _ []byte) error { + _, err2 := baseDataHashmap.PopByEncodedKey(key, true) + return err2 + }) + + }, -1); err != nil { + return + } + + return diffDataHelper(ctx, ses, copt, tblStuff, emit, tarDataHashmap, baseDataHashmap) +} + +func compareRowInWrappedBatches( + ctx context.Context, + ses *Session, + tblStuff tableStuff, + rowIdx1 int, + rowIdx2 int, + skipPKCols bool, + wrapped1 batchWithKind, + wrapped2 batchWithKind, +) (int, error) { + if wrapped1.kind == wrapped2.kind && wrapped1.kind == diffDelete && skipPKCols { + return 0, nil + } + + for i, colIdx := range tblStuff.def.visibleIdxes { + if skipPKCols { + if slices.Index(tblStuff.def.pkColIdxes, colIdx) != -1 { + continue + } + } + + var ( + vec1 = wrapped1.batch.Vecs[i] + vec2 = wrapped2.batch.Vecs[i] + ) + + if cmp, err := compareSingleValInVector( + ctx, ses, rowIdx1, rowIdx2, vec1, vec2, + ); err != nil { + return 0, err + } else if cmp != 0 { + return cmp, nil + } + + } + + return 0, nil +} + +func findDeleteAndUpdateBat( + ctx context.Context, ses *Session, bh BackgroundExec, + tblStuff tableStuff, tblName string, side int, tmpCh chan batchWithKind, branchTS types.TS, + expandUpdate bool, + dataHashmap, tombstoneHashmap databranchutils.BranchHashmap, +) (err error) { + + maxTombstoneBatchCnt := tblStuff.maxTombstoneBatchCnt + if maxTombstoneBatchCnt <= 0 { + maxTombstoneBatchCnt = maxSqlBatchCnt + } + + if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + var ( + err2 error + tuple types.Tuple + tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) + ) + + send := func(bwk batchWithKind) error { + select { + case <-ctx.Done(): + tblStuff.retPool.releaseRetBatch(bwk.batch, false) + return ctx.Err() + case tmpCh <- bwk: + return nil + } + } + + processBatch := func(tombBat *batch.Batch) error { + if tombBat.RowCount() == 0 { + tblStuff.retPool.releaseRetBatch(tombBat, true) + return nil + } + + dBat, err2 := handleDelsOnLCA( + ctx, ses, bh, tombBat, tblStuff, branchTS.ToTimestamp(), + ) + if err2 != nil { + tblStuff.retPool.releaseRetBatch(tombBat, true) + return err2 + } + + // merge inserts and deletes on the tar + // this deletes is not on the lca + if tombBat.RowCount() > 0 { + if _, err2 = dataHashmap.PopByVectorsStream( + []*vector.Vector{tombBat.Vecs[0]}, false, nil, + ); err2 != nil { + tblStuff.retPool.releaseRetBatch(tombBat, true) + tblStuff.retPool.releaseRetBatch(dBat, false) + return err2 + } + tblStuff.retPool.releaseRetBatch(tombBat, true) + } + + // find update + if dBat.RowCount() > 0 { + tBat2 := tblStuff.retPool.acquireRetBatch(tblStuff, false) + seen := make([]bool, dBat.RowCount()) + var updateBat *batch.Batch + var updateDeleteBat *batch.Batch + if _, err2 = dataHashmap.PopByVectorsStream( + []*vector.Vector{dBat.Vecs[tblStuff.def.pkColIdx]}, false, + func(idx int, _ []byte, row []byte) error { + seen[idx] = true + // delete on lca and insert into tar ==> update + if updateBat == nil { + updateBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } + if expandUpdate && updateDeleteBat == nil { + updateDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } + + if tuple, _, err2 = dataHashmap.DecodeRow(row); err2 != nil { + return err2 + } + + if expandUpdate { + if err2 = updateDeleteBat.UnionOne(dBat, int64(idx), ses.proc.Mp()); err2 != nil { + return err2 + } + } + + if err2 = appendTupleToBat(ses, updateBat, tuple, tblStuff); err2 != nil { + return err2 + } + return nil + }, + ); err2 != nil { + tblStuff.retPool.releaseRetBatch(dBat, false) + tblStuff.retPool.releaseRetBatch(tBat2, false) + if updateBat != nil { + tblStuff.retPool.releaseRetBatch(updateBat, false) + } + if updateDeleteBat != nil { + tblStuff.retPool.releaseRetBatch(updateDeleteBat, false) + } + return err2 + } + + for i := 0; i < dBat.RowCount(); i++ { + if seen[i] { + continue + } + // delete on lca + if err2 = tBat2.UnionOne(dBat, int64(i), ses.proc.Mp()); err2 != nil { + tblStuff.retPool.releaseRetBatch(dBat, false) + tblStuff.retPool.releaseRetBatch(tBat2, false) + if updateBat != nil { + tblStuff.retPool.releaseRetBatch(updateBat, false) + } + if updateDeleteBat != nil { + tblStuff.retPool.releaseRetBatch(updateDeleteBat, false) + } + return err2 + } + } + + tblStuff.retPool.releaseRetBatch(dBat, false) + tBat2.SetRowCount(tBat2.Vecs[0].Length()) + + if updateBat != nil { + updateBat.SetRowCount(updateBat.Vecs[0].Length()) + if expandUpdate { + if updateDeleteBat != nil { + updateDeleteBat.SetRowCount(updateDeleteBat.Vecs[0].Length()) + if err2 = send(batchWithKind{ + name: tblName, + side: side, + batch: updateDeleteBat, + kind: diffDelete, + }); err2 != nil { + return err2 + } + } + if err2 = send(batchWithKind{ + name: tblName, + side: side, + batch: updateBat, + kind: diffInsert, + }); err2 != nil { + return err2 + } + } else { + if err2 = send(batchWithKind{ + name: tblName, + side: side, + batch: updateBat, + kind: diffUpdate, + }); err2 != nil { + return err2 + } + } + } + + if err2 = send(batchWithKind{ + name: tblName, + side: side, + batch: tBat2, + kind: diffDelete, + }); err2 != nil { + return err2 + } + return nil + } + + tblStuff.retPool.releaseRetBatch(dBat, false) + return nil + } + + if err2 = cursor.ForEach(func(key []byte, _ []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if tuple, _, err2 = tombstoneHashmap.DecodeRow(key); err2 != nil { + return err2 + } + if err2 = vector.AppendAny(tBat1.Vecs[0], tuple[0], false, ses.proc.Mp()); err2 != nil { + return err2 + } + + tBat1.SetRowCount(tBat1.Vecs[0].Length()) + if tBat1.RowCount() >= maxTombstoneBatchCnt { + tombBat := tBat1 + tBat1 = nil + if err2 = processBatch(tombBat); err2 != nil { + return err2 + } + tBat1 = tblStuff.retPool.acquireRetBatch(tblStuff, true) + } + return nil + }); err2 != nil { + if tBat1 != nil { + tblStuff.retPool.releaseRetBatch(tBat1, true) + } + return err2 + } + + if tBat1 != nil { + return processBatch(tBat1) + } + return nil + + }, -1); err != nil { + return + } + + return nil +} + +func appendTupleToBat(ses *Session, bat *batch.Batch, tuple types.Tuple, tblStuff tableStuff) error { + // exclude the commit ts column + for j, val := range tuple[:len(tuple)-1] { + vec := bat.Vecs[j] + + if err := vector.AppendAny( + vec, val, val == nil, ses.proc.Mp(), + ); err != nil { + return err + } + } + + bat.SetRowCount(bat.Vecs[0].Length()) + + return nil +} + +func checkConflictAndAppendToBat( + ses *Session, copt compositeOption, tblStuff tableStuff, + tarBat, baseBat *batch.Batch, tarTuple, baseTuple types.Tuple, +) (err2 error) { + if copt.conflictOpt != nil { + switch copt.conflictOpt.Opt { + case tree.CONFLICT_FAIL: + buf := acquireBuffer(tblStuff.bufPool) + for i, idx := range tblStuff.def.pkColIdxes { + if err2 = formatValIntoString(ses, tarTuple[idx], tblStuff.def.colTypes[idx], buf); err2 != nil { + releaseBuffer(tblStuff.bufPool, buf) + return err2 + } + if i < len(tblStuff.def.pkColIdxes)-1 { + buf.WriteString(",") + } + } + + msg := buf.String() + releaseBuffer(tblStuff.bufPool, buf) + return moerr.NewInternalErrorNoCtxf( + "conflict: %s %s and %s %s on pk(%v) with different values", + tblStuff.tarRel.GetTableName(), diffInsert, + tblStuff.baseRel.GetTableName(), diffInsert, + msg, + ) + case tree.CONFLICT_SKIP: + return + case tree.CONFLICT_ACCEPT: + // accept the tar's insert + return appendTupleToBat(ses, tarBat, tarTuple, tblStuff) + } + } else { + if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + return err2 + } + if err2 = appendTupleToBat(ses, baseBat, baseTuple, tblStuff); err2 != nil { + return err2 + } + } + return +} + +func diffDataHelper( + ctx context.Context, + ses *Session, + copt compositeOption, + tblStuff tableStuff, + emit emitFunc, + tarDataHashmap databranchutils.BranchHashmap, + baseDataHashmap databranchutils.BranchHashmap, +) (err error) { + + // if no pk, we cannot use the fake pk to probe. + // must probe with full columns + + if tblStuff.def.pkKind == fakeKind { + var ( + keyIdxes = tblStuff.def.visibleIdxes + newHashmap databranchutils.BranchHashmap + ) + + if newHashmap, err = baseDataHashmap.Migrate(keyIdxes, -1); err != nil { + return err + } + if err = baseDataHashmap.Close(); err != nil { + return err + } + baseDataHashmap = newHashmap + } + + if err = tarDataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + var ( + err2 error + tarBat *batch.Batch + baseBat *batch.Batch + baseDeleteBat *batch.Batch + tarTuple types.Tuple + baseTuple types.Tuple + checkRet databranchutils.GetResult + ) + + tarBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + baseBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + + if err2 = cursor.ForEach(func(key []byte, row []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if tblStuff.def.pkKind == fakeKind { + if checkRet, err2 = baseDataHashmap.PopByEncodedFullValue(row, false); err2 != nil { + return err2 + } + } else { + if checkRet, err2 = baseDataHashmap.PopByEncodedKey(key, false); err2 != nil { + return err2 + } + } + + if !checkRet.Exists { + if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { + return err2 + } + + if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + return err2 + } + + } else { + // both has the key, we continue compare the left columns, + // if all columns are equal, exactly the same row, ignore. + if tblStuff.def.pkKind == fakeKind { + // all columns already compared. + // ignore + } else { + if tarTuple, _, err2 = tarDataHashmap.DecodeRow(row); err2 != nil { + return err2 + } + + if baseTuple, _, err2 = baseDataHashmap.DecodeRow(checkRet.Rows[0]); err2 != nil { + return err2 + } + + notSame := false + for _, idx := range tblStuff.def.visibleIdxes { + if slices.Index(tblStuff.def.pkColIdxes, idx) != -1 { + // pk columns already compared + continue + } + + if types.CompareValue( + tarTuple[idx], baseTuple[idx], + ) != 0 { + notSame = true + break + } + } + + if notSame { + if copt.conflictOpt != nil && + copt.conflictOpt.Opt == tree.CONFLICT_ACCEPT && + copt.expandUpdate { + if baseDeleteBat == nil { + baseDeleteBat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + } + if err2 = appendTupleToBat(ses, baseDeleteBat, baseTuple, tblStuff); err2 != nil { + return err2 + } + if err2 = appendTupleToBat(ses, tarBat, tarTuple, tblStuff); err2 != nil { + return err2 + } + } else { + // conflict happened + if err2 = checkConflictAndAppendToBat( + ses, copt, tblStuff, tarBat, baseBat, tarTuple, baseTuple, + ); err2 != nil { + return err2 + } + } + } + } + } + return nil + }); err2 != nil { + return err2 + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if baseDeleteBat != nil { + if stop, err3 := emitBatch(emit, batchWithKind{ + batch: baseDeleteBat, + kind: diffDelete, + name: tblStuff.baseRel.GetTableName(), + side: diffSideBase, + }, false, tblStuff.retPool); err3 != nil { + return err3 + } else if stop { + return nil + } + } + + if stop, err3 := emitBatch(emit, batchWithKind{ + batch: tarBat, + kind: diffInsert, + name: tblStuff.tarRel.GetTableName(), + side: diffSideTarget, + }, false, tblStuff.retPool); err3 != nil { + return err3 + } else if stop { + return nil + } + + if stop, err3 := emitBatch(emit, batchWithKind{ + batch: baseBat, + kind: diffInsert, + name: tblStuff.baseRel.GetTableName(), + side: diffSideBase, + }, false, tblStuff.retPool); err3 != nil { + return err3 + } else if stop { + return nil + } + + return nil + }, -1); err != nil { + return + } + + if copt.conflictOpt != nil { + if !copt.outputSQL { + // merge doesnt need the base data + return nil + } + } + + if err = baseDataHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + var ( + err2 error + tuple types.Tuple + bat *batch.Batch + ) + + bat = tblStuff.retPool.acquireRetBatch(tblStuff, false) + + if err2 = cursor.ForEach(func(_ []byte, row []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if tuple, _, err2 = baseDataHashmap.DecodeRow(row); err2 != nil { + return err2 + } + + if err2 = appendTupleToBat(ses, bat, tuple, tblStuff); err2 != nil { + return err2 + } + return nil + }); err2 != nil { + return err2 + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if stop, err3 := emitBatch(emit, batchWithKind{ + batch: bat, + kind: diffInsert, + name: tblStuff.baseRel.GetTableName(), + side: diffSideBase, + }, false, tblStuff.retPool); err3 != nil { + return err3 + } else if stop { + return nil + } + return nil + }, -1); err != nil { + return + } + + return nil +} +func buildHashmapForTable( + ctx context.Context, + mp *mpool.MPool, + lcaType int, + tblStuff *tableStuff, + handles []engine.ChangesHandle, +) ( + dataHashmap databranchutils.BranchHashmap, + tombstoneHashmap databranchutils.BranchHashmap, + err error, +) { + + var ( + atomicErr atomic.Value + dataBat *batch.Batch + tombstoneBat *batch.Batch + wg sync.WaitGroup + totalRows int64 + totalBytes int64 + ) + + defer func() { + wg.Wait() + + if dataBat != nil { + dataBat.Clean(mp) + } + + if tombstoneBat != nil { + tombstoneBat.Clean(mp) + } + }() + + if dataHashmap, err = databranchutils.NewBranchHashmap( + databranchutils.WithBranchHashmapAllocator(tblStuff.hashmapAllocator), + ); err != nil { + return + } + + if tombstoneHashmap, err = databranchutils.NewBranchHashmap( + databranchutils.WithBranchHashmapAllocator(tblStuff.hashmapAllocator), + ); err != nil { + return + } + + putVectors := func(bat *batch.Batch, isTombstone bool) error { + if bat == nil { + return nil + } + select { + case <-ctx.Done(): + bat.Clean(mp) + return ctx.Err() + default: + } + + wg.Add(1) + + if err = tblStuff.worker.Submit(func() { + defer wg.Done() + defer bat.Clean(mp) + + ll := bat.VectorCount() + var taskErr error + select { + case <-ctx.Done(): + taskErr = ctx.Err() + default: + if isTombstone { + // keep the commit ts + taskErr = tombstoneHashmap.PutByVectors(bat.Vecs[:ll], []int{0}) + } else { + // keep the commit ts + taskErr = dataHashmap.PutByVectors(bat.Vecs[:ll], []int{tblStuff.def.pkColIdx}) + } + } + if taskErr != nil { + atomicErr.Store(taskErr) + } + }); err != nil { + wg.Done() + bat.Clean(mp) + } + + return err + } + + for _, handle := range handles { + for { + select { + case <-ctx.Done(): + err = ctx.Err() + return + default: + } + if dataBat, tombstoneBat, _, err = handle.Next( + ctx, mp, + ); err != nil { + return + } else if dataBat == nil && tombstoneBat == nil { + // out of data + break + } + + if dataBat != nil && dataBat.RowCount() > 0 { + totalRows += int64(dataBat.RowCount()) + totalBytes += int64(dataBat.Size()) + } + + if atomicErr.Load() != nil { + err = atomicErr.Load().(error) + return + } + + if err = putVectors(dataBat, false); err != nil { + return + } + + if err = putVectors(tombstoneBat, true); err != nil { + return + } + } + } + + wg.Wait() + + if atomicErr.Load() != nil { + err = atomicErr.Load().(error) + } else { + select { + case <-ctx.Done(): + err = ctx.Err() + default: + } + } + + if err != nil { + return + } + + if tombstoneHashmap.ItemCount() == 0 && dataHashmap.ItemCount() == 0 { + return + } + + if tblStuff.maxTombstoneBatchCnt == 0 { + rowBytes := defaultRowBytes + if totalRows > 0 { + rowBytes = totalBytes / totalRows + if rowBytes <= 0 { + rowBytes = defaultRowBytes + } + } + rowBytes = rowBytes * tombstoneRowMult / tombstoneRowDiv + + available := tblStuff.hashmapAllocator.Available() / 3 + + shardCount := 0 + if tombstoneHashmap != nil { + shardCount = tombstoneHashmap.ShardCount() + } else if dataHashmap != nil { + shardCount = dataHashmap.ShardCount() + } + + maxByMem := int(available / int64(shardCount) / rowBytes) + if maxByMem < 1 { + maxByMem = 1 + } else if maxByMem > maxSqlBatchCnt { + maxByMem = maxSqlBatchCnt + } + + tblStuff.maxTombstoneBatchCnt = maxByMem + } + + if tblStuff.def.pkKind == fakeKind { + return + } + + /* + case 1: + insert update update update + pk1 pk1 pk1 pk1 .... + |------|-------------------------------------| + | collect range | + 1.1. the last one is an update: only keep the last update op + 1.2. the last one is a deletion: only keep the last deletion op + + case 2: + insert update update + pk1 pk1 pk1 .... + |------|-------------------------------------| + | collect range | + 2.1. the last one is an update: only keep the last update op + 2.2. the last one is a deletion: only keep the last deletion op + + case 3: + insert delete update update + pk1 pk1 pk1 pk1 .... + |------|-------------------------------------| + | collect range | + 3.1. the last one is an update: only keep the last update op + 3.2. the last one is a deletion: only keep the last deletion op + */ + + if err = tombstoneHashmap.ForEachShardParallel(func(cursor databranchutils.ShardCursor) error { + var ( + err2 error + err3 error + maxTs types.TS + maxIdx int + tuple types.Tuple + dataRet databranchutils.GetResult + ) + if err2 = cursor.ForEach(func(key []byte, _ []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + var tombstoneRet databranchutils.GetResult + if tombstoneRet, err3 = cursor.GetByEncodedKey(key); err3 != nil { + return err3 + } + if len(tombstoneRet.Rows) <= 1 { + return nil + } + + //tsMap := make(map[types.TS]struct{}) + maxIdx = 0 + maxTs = types.MinTs() + for i := 0; i < len(tombstoneRet.Rows); i++ { + if tuple, _, err3 = tombstoneHashmap.DecodeRow(tombstoneRet.Rows[i]); err3 != nil { + return err3 + } + cur := types.TS(tuple[len(tuple)-1].([]uint8)) + if cur.GT(&maxTs) { + maxTs = cur + maxIdx = i + } + //tsMap[cur] = struct{}{} + } + //delete(tsMap, maxTs) + + for i := range tombstoneRet.Rows { + if i != maxIdx { + if _, err3 = cursor.PopByEncodedKeyValue( + key, tombstoneRet.Rows[i], false, + ); err3 != nil { + return err3 + } + } + } + + if dataRet, err3 = dataHashmap.GetByEncodedKey(key); err3 != nil { + return err3 + } + + if dataRet.Exists { + for i := range dataRet.Rows { + if tuple, _, err3 = dataHashmap.DecodeRow(dataRet.Rows[i]); err3 != nil { + return err3 + } + cur := types.TS(tuple[len(tuple)-1].([]uint8)) + // cannot use tsMap to filter, why? + // cannot use cur != maxTS to filter, why? + if cur.LT(&maxTs) { + if _, err3 = dataHashmap.PopByEncodedKeyValue( + key, dataRet.Rows[i], false, + ); err3 != nil { + return err3 + } + } + } + } + return nil + }); err2 != nil { + return err2 + } + return nil + }, -1); err != nil { + return nil, nil, err + } + + return +} diff --git a/pkg/frontend/data_branch_helpers.go b/pkg/frontend/data_branch_helpers.go new file mode 100644 index 0000000000000..f2a369c177224 --- /dev/null +++ b/pkg/frontend/data_branch_helpers.go @@ -0,0 +1,534 @@ +// Copyright 2025 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "strconv" + "strings" + "sync" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" + moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime" + "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/bytejson" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/util/executor" +) + +func acquireBuffer(pool *sync.Pool) *bytes.Buffer { + if pool == nil { + return &bytes.Buffer{} + } + buf := pool.Get().(*bytes.Buffer) + buf.Reset() + return buf +} + +func releaseBuffer(pool *sync.Pool, buf *bytes.Buffer) { + if buf == nil { + return + } + buf.Reset() + if pool != nil { + pool.Put(buf) + } +} + +func newEmitter( + ctx context.Context, stopCh <-chan struct{}, retCh chan batchWithKind, +) emitFunc { + return func(wrapped batchWithKind) (bool, error) { + select { + case <-ctx.Done(): + return false, ctx.Err() + case <-stopCh: + return true, nil + default: + } + + select { + case <-ctx.Done(): + return false, ctx.Err() + case <-stopCh: + return true, nil + case retCh <- wrapped: + return false, nil + } + } +} + +func emitBatch( + emit emitFunc, wrapped batchWithKind, forTombstone bool, pool *retBatchList, +) (bool, error) { + stop, err := emit(wrapped) + if stop || err != nil { + pool.releaseRetBatch(wrapped.batch, forTombstone) + return stop, err + } + return false, nil +} + +func runSql( + ctx context.Context, ses *Session, bh BackgroundExec, sql string, + streamChan chan executor.Result, errChan chan error, +) (sqlRet executor.Result, err error) { + + useBackExec := false + trimmedLower := strings.ToLower(strings.TrimSpace(sql)) + if strings.HasPrefix(trimmedLower, "drop database") { + // Internal executor does not support DROP DATABASE (IsPublishing panics). + useBackExec = true + } else if strings.Contains(strings.ToLower(snapConditionRegex.FindString(sql)), "snapshot") { + // SQLExecutor cannot resolve snapshot by name. + useBackExec = true + } + + var exec executor.SQLExecutor + if !useBackExec { + rt := moruntime.ServiceRuntime(ses.service) + if rt == nil { + useBackExec = true + } else { + val, exist := rt.GetGlobalVariables(moruntime.InternalSQLExecutor) + if !exist { + useBackExec = true + } else { + exec = val.(executor.SQLExecutor) + } + } + } + + if useBackExec { + // export as CSV need this + // bh.(*backExec).backSes.SetMysqlResultSet(&MysqlResultSet{}) + //for range tblStuff.def.visibleIdxes { + // bh.(*backExec).backSes.mrs.AddColumn(&MysqlColumn{}) + //} + if err = bh.Exec(ctx, sql); err != nil { + return + } + if _, ok := bh.(*backExec); ok { + bh.ClearExecResultSet() + sqlRet.Mp = ses.proc.Mp() + sqlRet.Batches = bh.GetExecResultBatches() + return + } + + rs := bh.GetExecResultSet() + bh.ClearExecResultSet() + if len(rs) == 0 || rs[0] == nil { + return + } + mrs, ok := rs[0].(*MysqlResultSet) + if !ok { + return sqlRet, moerr.NewInternalError(ctx, "unexpected result set type") + } + if len(mrs.Columns) == 0 { + return + } + var bat *batch.Batch + bat, _, err = convertRowsIntoBatch(ses.proc.Mp(), mrs.Columns, mrs.Data) + if err != nil { + return sqlRet, err + } + sqlRet.Mp = ses.proc.Mp() + sqlRet.Batches = []*batch.Batch{bat} + return + } + + // we do not use the bh.Exec here, it's too slow. + // use internal sql instead. + + backSes := bh.(*backExec).backSes + + opts := executor.Options{}. + WithDisableIncrStatement(). + WithTxn(backSes.GetTxnHandler().GetTxn()). + WithKeepTxnAlive(). + WithTimeZone(ses.GetTimeZone()) + + if streamChan != nil && errChan != nil { + opts = opts.WithStreaming(streamChan, errChan) + } + + if sqlRet, err = exec.Exec(ctx, sql, opts); err != nil { + return sqlRet, err + } + + return sqlRet, nil +} + +func formatValIntoString(ses *Session, val any, t types.Type, buf *bytes.Buffer) error { + if val == nil { + buf.WriteString("NULL") + return nil + } + + var scratch [64]byte + + writeInt := func(v int64) { + buf.Write(strconv.AppendInt(scratch[:0], v, 10)) + } + + writeUint := func(v uint64) { + buf.Write(strconv.AppendUint(scratch[:0], v, 10)) + } + + writeFloat := func(v float64, bitSize int) { + buf.Write(strconv.AppendFloat(scratch[:0], v, 'g', -1, bitSize)) + } + + writeBool := func(v bool) { + buf.WriteString(strconv.FormatBool(v)) + } + + switch t.Oid { + case types.T_varchar, types.T_text, types.T_json, types.T_char, types. + T_varbinary, types.T_binary: + if t.Oid == types.T_json { + var strVal string + switch x := val.(type) { + case bytejson.ByteJson: + strVal = x.String() + case *bytejson.ByteJson: + if x == nil { + return moerr.NewInternalErrorNoCtx("formatValIntoString: nil *bytejson.ByteJson") + } + strVal = x.String() + case []byte: + strVal = string(x) + case string: + strVal = x + default: + return moerr.NewInternalErrorNoCtxf("formatValIntoString: unexpected json type %T", val) + } + jsonLiteral := escapeJSONControlBytes([]byte(strVal)) + if !json.Valid(jsonLiteral) { + return moerr.NewInternalErrorNoCtxf("formatValIntoString: invalid json input %q", strVal) + } + writeEscapedSQLString(buf, jsonLiteral) + return nil + } + switch x := val.(type) { + case []byte: + writeEscapedSQLString(buf, x) + case string: + writeEscapedSQLString(buf, []byte(x)) + default: + return moerr.NewInternalErrorNoCtxf("formatValIntoString: unexpected string type %T", val) + } + case types.T_timestamp: + buf.WriteString("'") + buf.WriteString(val.(types.Timestamp).String2(ses.timeZone, t.Scale)) + buf.WriteString("'") + case types.T_datetime: + buf.WriteString("'") + buf.WriteString(val.(types.Datetime).String2(t.Scale)) + buf.WriteString("'") + case types.T_time: + buf.WriteString("'") + buf.WriteString(val.(types.Time).String2(t.Scale)) + buf.WriteString("'") + case types.T_date: + buf.WriteString("'") + buf.WriteString(val.(types.Date).String()) + buf.WriteString("'") + case types.T_year: + buf.WriteString(val.(types.MoYear).String()) + case types.T_decimal64: + buf.WriteString(val.(types.Decimal64).Format(t.Scale)) + case types.T_decimal128: + buf.WriteString(val.(types.Decimal128).Format(t.Scale)) + case types.T_decimal256: + buf.WriteString(val.(types.Decimal256).Format(t.Scale)) + case types.T_bool: + writeBool(val.(bool)) + case types.T_uint8: + writeUint(uint64(val.(uint8))) + case types.T_uint16: + writeUint(uint64(val.(uint16))) + case types.T_uint32: + writeUint(uint64(val.(uint32))) + case types.T_uint64: + writeUint(val.(uint64)) + case types.T_int8: + writeInt(int64(val.(int8))) + case types.T_int16: + writeInt(int64(val.(int16))) + case types.T_int32: + writeInt(int64(val.(int32))) + case types.T_int64: + writeInt(val.(int64)) + case types.T_float32: + writeFloat(float64(val.(float32)), 32) + case types.T_float64: + writeFloat(val.(float64), 64) + case types.T_array_float32: + buf.WriteString("'") + buf.WriteString(types.ArrayToString[float32](val.([]float32))) + buf.WriteString("'") + case types.T_array_float64: + buf.WriteString("'") + buf.WriteString(types.ArrayToString[float64](val.([]float64))) + buf.WriteString("'") + default: + return moerr.NewNotSupportedNoCtxf("formatValIntoString: not support type %v", t.Oid) + } + + return nil +} + +// writeEscapedSQLString escapes special and control characters for SQL literal output. +func writeEscapedSQLString(buf *bytes.Buffer, b []byte) { + buf.WriteByte('\'') + for _, c := range b { + switch c { + case '\'': + buf.WriteString("\\'") + //case '"': + // buf.WriteString("\\\"") + case '\\': + buf.WriteString("\\\\") + case 0: + buf.WriteString("\\0") + case '\b': + buf.WriteString("\\b") + case '\n': + buf.WriteString("\\n") + case '\r': + buf.WriteString("\\r") + case '\t': + buf.WriteString("\\t") + case 0x1A: + buf.WriteString("\\Z") + default: + if c < 0x20 || c == 0x7f { + buf.WriteString("\\x") + buf.WriteString(hex.EncodeToString([]byte{c})) + } else { + buf.WriteByte(c) + } + } + } + buf.WriteByte('\'') +} + +// escapeJSONControlChars converts control characters to JSON-compliant \u00XX escapes. +func escapeJSONControlBytes(b []byte) []byte { + var out []byte + hexDigits := "0123456789abcdef" + + for i, c := range b { + if c < 0x20 || c == 0x7f { + if out == nil { + out = make([]byte, 0, len(b)+8) + out = append(out, b[:i]...) + } + out = append(out, '\\', 'u', '0', '0', hexDigits[c>>4], hexDigits[c&0xf]) + continue + } + if out != nil { + out = append(out, c) + } + } + + if out == nil { + return b + } + return out +} + +func compareSingleValInVector( + ctx context.Context, + ses *Session, + rowIdx1 int, + rowIdx2 int, + vec1 *vector.Vector, + vec2 *vector.Vector, +) (int, error) { + + if !vec1.GetType().Eq(*vec2.GetType()) { + return 0, moerr.NewInternalErrorNoCtxf( + "type not matched: %v <-> %v", + vec1.GetType().String(), vec2.GetType().String(), + ) + } + + if vec1.IsConst() { + rowIdx1 = 0 + } + if vec2.IsConst() { + rowIdx2 = 0 + } + + // Treat NULL as equal only when both sides are NULL. + if vec1.IsNull(uint64(rowIdx1)) || vec2.IsNull(uint64(rowIdx2)) { + if vec1.IsNull(uint64(rowIdx1)) && vec2.IsNull(uint64(rowIdx2)) { + return 0, nil + } + return 1, nil + } + + // Use raw values to avoid format conversions in extractRowFromVector. + switch vec1.GetType().Oid { + case types.T_json: + return bytejson.CompareByteJson( + types.DecodeJson(vec1.GetBytesAt(rowIdx1)), + types.DecodeJson(vec2.GetBytesAt(rowIdx2)), + ), nil + case types.T_bool: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[bool](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[bool](vec2, rowIdx2), + ), nil + case types.T_bit: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[uint64](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[uint64](vec2, rowIdx2), + ), nil + case types.T_int8: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[int8](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[int8](vec2, rowIdx2), + ), nil + case types.T_uint8: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[uint8](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[uint8](vec2, rowIdx2), + ), nil + case types.T_int16: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[int16](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[int16](vec2, rowIdx2), + ), nil + case types.T_uint16: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[uint16](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[uint16](vec2, rowIdx2), + ), nil + case types.T_int32: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[int32](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[int32](vec2, rowIdx2), + ), nil + case types.T_uint32: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[uint32](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[uint32](vec2, rowIdx2), + ), nil + case types.T_int64: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[int64](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[int64](vec2, rowIdx2), + ), nil + case types.T_uint64: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[uint64](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[uint64](vec2, rowIdx2), + ), nil + case types.T_float32: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[float32](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[float32](vec2, rowIdx2), + ), nil + case types.T_float64: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[float64](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[float64](vec2, rowIdx2), + ), nil + case types.T_char, types.T_varchar, types.T_blob, types.T_text, types.T_binary, types.T_varbinary, types.T_datalink: + return bytes.Compare( + vec1.GetBytesAt(rowIdx1), + vec2.GetBytesAt(rowIdx2), + ), nil + case types.T_array_float32: + return types.CompareValue( + vector.GetArrayAt[float32](vec1, rowIdx1), + vector.GetArrayAt[float32](vec2, rowIdx2), + ), nil + case types.T_array_float64: + return types.CompareValue( + vector.GetArrayAt[float64](vec1, rowIdx1), + vector.GetArrayAt[float64](vec2, rowIdx2), + ), nil + case types.T_date: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Date](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Date](vec2, rowIdx2), + ), nil + case types.T_datetime: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Datetime](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Datetime](vec2, rowIdx2), + ), nil + case types.T_time: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Time](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Time](vec2, rowIdx2), + ), nil + case types.T_timestamp: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Timestamp](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Timestamp](vec2, rowIdx2), + ), nil + case types.T_year: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.MoYear](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.MoYear](vec2, rowIdx2), + ), nil + case types.T_decimal64: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Decimal64](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Decimal64](vec2, rowIdx2), + ), nil + case types.T_decimal128: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Decimal128](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Decimal128](vec2, rowIdx2), + ), nil + case types.T_uuid: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Uuid](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Uuid](vec2, rowIdx2), + ), nil + case types.T_Rowid: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Rowid](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Rowid](vec2, rowIdx2), + ), nil + case types.T_Blockid: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Blockid](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Blockid](vec2, rowIdx2), + ), nil + case types.T_TS: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.TS](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.TS](vec2, rowIdx2), + ), nil + case types.T_enum: + return types.CompareValue( + vector.GetFixedAtNoTypeCheck[types.Enum](vec1, rowIdx1), + vector.GetFixedAtNoTypeCheck[types.Enum](vec2, rowIdx2), + ), nil + default: + return 0, moerr.NewInternalErrorNoCtxf("compareSingleValInVector : unsupported type %d", vec1.GetType().Oid) + } +} diff --git a/pkg/frontend/data_branch_output.go b/pkg/frontend/data_branch_output.go new file mode 100644 index 0000000000000..0749bd81d32ed --- /dev/null +++ b/pkg/frontend/data_branch_output.go @@ -0,0 +1,1746 @@ +// Copyright 2025 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "os" + "path" + "path/filepath" + "runtime" + "slices" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/fileservice" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/matrixorigin/matrixone/pkg/util/executor" + "github.com/panjf2000/ants/v2" +) + +func makeFileName( + baseAtTsExpr *tree.AtTimeStamp, + tarAtTsExpr *tree.AtTimeStamp, + tblStuff tableStuff, +) string { + var ( + srcName = tblStuff.tarRel.GetTableName() + baseName = tblStuff.baseRel.GetTableName() + ) + + if baseAtTsExpr != nil { + baseName = fmt.Sprintf("%s_%s", baseName, baseAtTsExpr.SnapshotName) + } + + if tarAtTsExpr != nil { + srcName = fmt.Sprintf("%s_%s", srcName, tarAtTsExpr.SnapshotName) + } + + return fmt.Sprintf( + "diff_%s_%s_%s", + srcName, baseName, + time.Now().UTC().Format("20060102_150405"), + ) +} + +func mergeDiffs( + ctx context.Context, + cancel context.CancelFunc, + ses *Session, + bh BackgroundExec, + stmt *tree.DataBranchMerge, + dagInfo branchMetaInfo, + tblStuff tableStuff, + retCh chan batchWithKind, +) (err error) { + + var ( + insertCnt int + deleteCnt int + + insertIntoVals = acquireBuffer(tblStuff.bufPool) + deleteFromVals = acquireBuffer(tblStuff.bufPool) + firstErr error + tmpValsBuffer = acquireBuffer(tblStuff.bufPool) + ) + + defer func() { + releaseBuffer(tblStuff.bufPool, insertIntoVals) + releaseBuffer(tblStuff.bufPool, deleteFromVals) + releaseBuffer(tblStuff.bufPool, tmpValsBuffer) + }() + + defer func() { + cancel() + }() + + appender := sqlValuesAppender{ + ctx: ctx, + ses: ses, + bh: bh, + tblStuff: tblStuff, + deleteByFullRow: tblStuff.def.pkKind == fakeKind, + pkInfo: newPKBatchInfo(ctx, ses, tblStuff), + deleteCnt: &deleteCnt, + deleteBuf: deleteFromVals, + insertCnt: &insertCnt, + insertBuf: insertIntoVals, + } + if err = initPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { + return err + } + defer func() { + if err2 := dropPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err2 != nil && err == nil { + err = err2 + } + }() + + // conflict option should be pushed down to the hash phase, + // so the batch we received is conflict-free. + for wrapped := range retCh { + + if firstErr != nil || ctx.Err() != nil { + if firstErr == nil { + firstErr = ctx.Err() + } + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + if err = appendBatchRowsAsSQLValues( + ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, + ); err != nil { + firstErr = err + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + } + + if err = appender.flushAll(); err != nil { + if firstErr == nil { + firstErr = err + } + } + + if firstErr != nil { + return firstErr + } + return +} + +func satisfyDiffOutputOpt( + ctx context.Context, + cancel context.CancelFunc, + stop func(), + ses *Session, + bh BackgroundExec, + stmt *tree.DataBranchDiff, + dagInfo branchMetaInfo, + tblStuff tableStuff, + retCh chan batchWithKind, +) (err error) { + + var ( + mrs = ses.GetMysqlResultSet() + first error + hitLimit bool + ) + + defer func() { + cancel() + }() + + if stmt.OutputOpt == nil || stmt.OutputOpt.Limit != nil { + var ( + rows = make([][]any, 0, 100) + ) + + for wrapped := range retCh { + if first != nil { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + if hitLimit { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + if ctx.Err() != nil { + first = ctx.Err() + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + for rowIdx := range wrapped.batch.RowCount() { + var ( + row = make([]any, len(tblStuff.def.visibleIdxes)+2) + ) + row[0] = wrapped.name + row[1] = wrapped.kind + + for _, colIdx := range tblStuff.def.visibleIdxes { + vec := wrapped.batch.Vecs[colIdx] + if err = extractRowFromVector( + ctx, ses, vec, colIdx+2, row, rowIdx, false, + ); err != nil { + return + } + } + + rows = append(rows, row) + if stmt.OutputOpt != nil && stmt.OutputOpt.Limit != nil && + int64(len(rows)) >= *stmt.OutputOpt.Limit { + // hit limit, cancel producers but keep draining the channel + hitLimit = true + stop() + break + } + } + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + } + + slices.SortFunc(rows, func(a, b []any) int { + for _, idx := range tblStuff.def.pkColIdxes { + if cmp := types.CompareValue( + a[idx+2], b[idx+2], + ); cmp != 0 { + return cmp + } + } + return 0 + }) + + for _, row := range rows { + mrs.AddRow(row) + } + + } else if stmt.OutputOpt.Count { + cnt := int64(0) + for wrapped := range retCh { + if first != nil { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + if ctx.Err() != nil { + first = ctx.Err() + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + cnt += int64(wrapped.batch.RowCount()) + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + } + mrs.AddRow([]any{cnt}) + + } else if stmt.OutputOpt.Summary { + var ( + targetInsertCnt int64 + targetDeleteCnt int64 + targetUpdateCnt int64 + baseInsertCnt int64 + baseDeleteCnt int64 + baseUpdateCnt int64 + ) + + for wrapped := range retCh { + if first != nil { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + if ctx.Err() != nil { + first = ctx.Err() + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + var ( + targetMetric *int64 + baseMetric *int64 + ) + + switch wrapped.kind { + case diffInsert: + targetMetric = &targetInsertCnt + baseMetric = &baseInsertCnt + case diffDelete: + targetMetric = &targetDeleteCnt + baseMetric = &baseDeleteCnt + case diffUpdate: + targetMetric = &targetUpdateCnt + baseMetric = &baseUpdateCnt + default: + first = moerr.NewInternalErrorNoCtxf("unknown diff kind %q", wrapped.kind) + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + cnt := int64(wrapped.batch.RowCount()) + switch wrapped.side { + case diffSideTarget: + *targetMetric += cnt + case diffSideBase: + *baseMetric += cnt + default: + first = moerr.NewInternalErrorNoCtxf("unknown diff side for summary, kind=%q, table=%q", wrapped.kind, wrapped.name) + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + } + + if first != nil { + return first + } + + mrs.AddRow([]any{"INSERTED", targetInsertCnt, baseInsertCnt}) + mrs.AddRow([]any{"DELETED", targetDeleteCnt, baseDeleteCnt}) + mrs.AddRow([]any{"UPDATED", targetUpdateCnt, baseUpdateCnt}) + + } else if len(stmt.OutputOpt.DirPath) != 0 { + var ( + insertCnt int + deleteCnt int + + deleteFromValsBuffer = acquireBuffer(tblStuff.bufPool) + insertIntoValsBuffer = acquireBuffer(tblStuff.bufPool) + tmpValsBuffer = acquireBuffer(tblStuff.bufPool) + + fileHint string + fullFilePath string + writeFile func([]byte) error + release func() + cleanup func() + succeeded bool + ) + + defer func() { + if !succeeded && cleanup != nil { + cleanup() + } + if release != nil { + release() + } + releaseBuffer(tblStuff.bufPool, deleteFromValsBuffer) + releaseBuffer(tblStuff.bufPool, insertIntoValsBuffer) + releaseBuffer(tblStuff.bufPool, tmpValsBuffer) + }() + + if fullFilePath, fileHint, writeFile, release, cleanup, err = prepareFSForDiffAsFile( + ctx, ses, stmt, tblStuff, + ); err != nil { + return + } + + appender := sqlValuesAppender{ + ctx: ctx, + ses: ses, + bh: bh, + tblStuff: tblStuff, + deleteByFullRow: tblStuff.def.pkKind == fakeKind, + pkInfo: newPKBatchInfo(ctx, ses, tblStuff), + deleteCnt: &deleteCnt, + deleteBuf: deleteFromValsBuffer, + insertCnt: &insertCnt, + insertBuf: insertIntoValsBuffer, + writeFile: writeFile, + } + if writeFile != nil { + // Make generated SQL runnable in one transaction. + if err = writeFile([]byte("BEGIN;\n")); err != nil { + return + } + } + if err = initPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { + return + } + + for wrapped := range retCh { + if first != nil { + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + if ctx.Err() != nil { + first = ctx.Err() + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + + if wrapped.name == tblStuff.tarRel.GetTableName() { + if err = appendBatchRowsAsSQLValues( + ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, + ); err != nil { + first = err + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + } else if wrapped.name == tblStuff.baseRel.GetTableName() { + if wrapped.kind == diffInsert { + wrapped.kind = diffDelete + } + if wrapped.kind == diffDelete { + if err = appendBatchRowsAsSQLValues( + ctx, ses, tblStuff, wrapped, tmpValsBuffer, appender, + ); err != nil { + first = err + cancel() + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + continue + } + } + } + + tblStuff.retPool.releaseRetBatch(wrapped.batch, false) + } + + if first != nil { + return first + } + + if err = appender.flushAll(); err != nil { + first = err + cancel() + } + if first == nil { + if err = dropPKTables(ctx, ses, bh, appender.pkInfo, appender.writeFile); err != nil { + return err + } + } + if first == nil && writeFile != nil { + if err = writeFile([]byte("COMMIT;\n")); err != nil { + return err + } + } + + succeeded = true + mrs.AddRow([]any{fullFilePath, fileHint}) + } + + if first != nil { + return first + } + if hitLimit { + return trySaveQueryResult(context.Background(), ses, mrs) + } + return trySaveQueryResult(ctx, ses, mrs) +} + +func buildOutputSchema( + ctx context.Context, + ses *Session, + stmt *tree.DataBranchDiff, + tblStuff tableStuff, +) (err error) { + + var ( + mrs = ses.GetMysqlResultSet() + showCols []*MysqlColumn + ) + ses.ClearAllMysqlResultSet() + ses.ClearResultBatches() + + if stmt.OutputOpt == nil || stmt.OutputOpt.Limit != nil { + // output all rows OR + // output limited rows (is this can be pushed down to hash-phase?) + showCols = make([]*MysqlColumn, 0, 2) + showCols = append(showCols, new(MysqlColumn), new(MysqlColumn)) + showCols[0].SetColumnType(defines.MYSQL_TYPE_VARCHAR) + showCols[0].SetName(fmt.Sprintf( + "diff %s against %s", tblStuff.tarRel.GetTableName(), tblStuff.baseRel.GetTableName()), + ) + showCols[1].SetColumnType(defines.MYSQL_TYPE_VARCHAR) + showCols[1].SetName("flag") + + for _, idx := range tblStuff.def.visibleIdxes { + nCol := new(MysqlColumn) + if err = convertEngineTypeToMysqlType(ctx, tblStuff.def.colTypes[idx].Oid, nCol); err != nil { + return + } + + nCol.SetName(tblStuff.def.colNames[idx]) + showCols = append(showCols, nCol) + } + + } else if stmt.OutputOpt.Summary { + targetName := tree.StringWithOpts(&stmt.TargetTable, dialect.MYSQL, tree.WithSingleQuoteString()) + baseName := tree.StringWithOpts(&stmt.BaseTable, dialect.MYSQL, tree.WithSingleQuoteString()) + + showCols = append(showCols, &MysqlColumn{}, &MysqlColumn{}, &MysqlColumn{}) + showCols[0].SetName("metric") + showCols[0].SetColumnType(defines.MYSQL_TYPE_VARCHAR) + showCols[1].SetName(targetName) + showCols[1].SetColumnType(defines.MYSQL_TYPE_LONGLONG) + showCols[2].SetName(baseName) + showCols[2].SetColumnType(defines.MYSQL_TYPE_LONGLONG) + + } else if stmt.OutputOpt.Count { + // count(*) of diff rows + showCols = append(showCols, &MysqlColumn{}) + showCols[0].SetName("COUNT(*)") + showCols[0].SetColumnType(defines.MYSQL_TYPE_LONGLONG) + + } else if len(stmt.OutputOpt.DirPath) != 0 { + // output as file + col1 := new(MysqlColumn) + col1.SetName("FILE SAVED TO") + col1.SetColumnType(defines.MYSQL_TYPE_VARCHAR) + + col2 := new(MysqlColumn) + col2.SetName("HINT") + col2.SetColumnType(defines.MYSQL_TYPE_VARCHAR) + + showCols = append(showCols, col1, col2) + } else { + return moerr.NewNotSupportedNoCtx(fmt.Sprintf("%v", stmt.OutputOpt)) + } + + for _, col := range showCols { + mrs.AddColumn(col) + } + + return nil +} + +func tryDiffAsCSV( + ctx context.Context, + ses *Session, + bh BackgroundExec, + stmt *tree.DataBranchDiff, + tblStuff tableStuff, +) (bool, error) { + + if stmt.OutputOpt == nil { + return false, nil + } + + if len(stmt.OutputOpt.DirPath) == 0 { + return false, nil + } + + sql := fmt.Sprintf( + "SELECT COUNT(*) FROM %s.%s", + tblStuff.baseRel.GetTableDef(ctx).DbName, + tblStuff.baseRel.GetTableDef(ctx).Name, + ) + + if tblStuff.baseSnap != nil && tblStuff.baseSnap.TS != nil { + sql += fmt.Sprintf("{mo_ts=%d}", tblStuff.baseSnap.TS.PhysicalTime) + } + + var ( + err error + sqlRet executor.Result + ) + + if sqlRet, err = runSql(ctx, ses, bh, sql, nil, nil); err != nil { + return false, err + } + + if len(sqlRet.Batches) != 1 && + sqlRet.Batches[0].RowCount() != 1 && + sqlRet.Batches[0].VectorCount() != 1 { + return false, moerr.NewInternalErrorNoCtxf("cannot get count(*) of base table") + } + + if vector.GetFixedAtWithTypeCheck[uint64](sqlRet.Batches[0].Vecs[0], 0) != 0 { + return false, nil + } + + sqlRet.Close() + + return true, writeCSV(ctx, ses, tblStuff, bh, stmt) +} + +func writeCSV( + inputCtx context.Context, + ses *Session, + tblStuff tableStuff, + bh BackgroundExec, + stmt *tree.DataBranchDiff, +) (err error) { + + ctx, cancelCtx := context.WithCancel(inputCtx) + defer cancelCtx() + + // SQLExecutor do not support snapshot read, we must use the MO_TS + snap := "" + if tblStuff.tarSnap != nil { + snap = fmt.Sprintf("{MO_TS=%d}", tblStuff.tarSnap.TS.PhysicalTime) + } + + // output as csv + sql := fmt.Sprintf("SELECT * FROM %s.%s%s;", + tblStuff.tarRel.GetTableDef(ctx).DbName, + tblStuff.tarRel.GetTableDef(ctx).Name, + snap, + ) + + var ( + stop bool + wg sync.WaitGroup + errChan = make(chan error, 1) + streamChan = make(chan executor.Result, runtime.NumCPU()) + + writerWg sync.WaitGroup + workerWg sync.WaitGroup + writerErr = make(chan error, 1) + closeByte sync.Once + + mrs = &MysqlResultSet{} + sqlRetHint string + sqlRetPath string + fileName = makeFileName(stmt.BaseTable.AtTsExpr, stmt.TargetTable.AtTsExpr, tblStuff) + cleanup func() + ) + + ep := &ExportConfig{ + userConfig: newDiffCSVUserConfig(), + service: ses.service, + } + + for range tblStuff.def.visibleIdxes { + mrs.AddColumn(&MysqlColumn{}) + } + + ep.init() + ep.ctx = ctx + ep.mrs = mrs + ep.ByteChan = make(chan *BatchByte, runtime.NumCPU()) + + ep.DefaultBufSize = getPu(ses.GetService()).SV.ExportDataDefaultFlushSize + initExportFileParam(ep, mrs) + + sqlRetHint = ep.userConfig.String() + fileName += ".csv" + + var ( + ok bool + stagePath string + ) + + sqlRetPath = path.Join(stmt.OutputOpt.DirPath, fileName) + + if stagePath, ok, err = tryDecodeStagePath(ses, stmt.OutputOpt.DirPath); err != nil { + return + } else if ok { + sqlRetPath = strings.Replace(sqlRetPath, "stage:/", "stage://", 1) + ep.userConfig.StageFilePath = path.Join(stagePath, fileName) + if err = openNewFile(ctx, ep, mrs); err != nil { + return + } + cleanup = func() { + removeFileIgnoreError(context.Background(), ep.service, ep.userConfig.StageFilePath) + } + } else { + ep.userConfig.FilePath = path.Join(stmt.OutputOpt.DirPath, fileName) + if err = openNewFile(ctx, ep, mrs); err != nil { + return + } + cleanup = func() { + removeFileIgnoreError(context.Background(), ep.service, ep.userConfig.FilePath) + } + } + + writerWg.Add(1) + if err = tblStuff.worker.Submit(func() { + defer writerWg.Done() + for bb := range ep.ByteChan { + if bb.err != nil { + select { + case writerErr <- bb.err: + default: + } + return + } + ep.BatchMap[bb.index] = bb.writeByte + for { + value, ok := ep.BatchMap[ep.WriteIndex.Load()+1] + if !ok { + break + } + if err2 := writeToCSVFile(ep, value); err2 != nil { + select { + case writerErr <- err2: + default: + } + return + } + ep.WriteIndex.Add(1) + ep.BatchMap[ep.WriteIndex.Load()] = nil + } + } + if ep.WriteIndex.Load() != ep.Index.Load() { + if err2 := exportAllDataFromBatches(ep); err2 != nil { + select { + case writerErr <- err2: + default: + } + } + } + }); err != nil { + writerWg.Done() + return err + } + + defer func() { + if err != nil && cleanup != nil { + cleanup() + } + }() + + defer func() { + closeByte.Do(func() { + close(ep.ByteChan) + }) + writerWg.Wait() + closeErr := Close(ep) + ep.Close() + if err == nil { + err = closeErr + } else { + err = errors.Join(err, closeErr) + } + }() + + wg.Add(1) + if err = tblStuff.worker.Submit(func() { + defer func() { + wg.Done() + close(streamChan) + close(errChan) + }() + if _, err2 := runSql(ctx, ses, bh, sql, streamChan, errChan); err2 != nil { + select { + case errChan <- err2: + default: + } + } + }); err != nil { + wg.Done() + return err + } + + streamOpen, errOpen := true, true + for streamOpen || errOpen { + select { + case <-inputCtx.Done(): + err = errors.Join(err, inputCtx.Err()) + stop = true + case e := <-writerErr: + if e != nil { + err = errors.Join(err, e) + } + stop = true + cancelCtx() + case e, ok := <-errChan: + if !ok { + errOpen = false + continue + } + err = errors.Join(err, e) + cancelCtx() + stop = true + case sqlRet, ok := <-streamChan: + if !ok { + streamOpen = false + continue + } + if stop { + sqlRet.Close() + continue + } + for _, bat := range sqlRet.Batches { + copied, _ := bat.Dup(ses.proc.Mp()) + idx := ep.Index.Add(1) + workerWg.Add(1) + if submitErr := tblStuff.worker.Submit(func() { + defer workerWg.Done() + constructByte(ctx, ses, copied, idx, ep.ByteChan, ep) + }); submitErr != nil { + workerWg.Done() + err = errors.Join(err, submitErr) + stop = true + cancelCtx() + break + } + } + sqlRet.Close() + } + } + + wg.Wait() + workerWg.Wait() + closeByte.Do(func() { + close(ep.ByteChan) + }) + writerWg.Wait() + + select { + case e := <-writerErr: + err = errors.Join(err, e) + default: + } + + if err != nil { + return err + } + + mrs = ses.GetMysqlResultSet() + mrs.AddRow([]any{sqlRetPath, sqlRetHint}) + + return trySaveQueryResult(ctx, ses, mrs) +} + +func newDiffCSVUserConfig() *tree.ExportParam { + fields := tree.NewFields( + tree.DefaultFieldsTerminated, + false, + tree.DefaultFieldsEnclosedBy[0], + tree.DefaultFieldsEscapedBy[0], + ) + return &tree.ExportParam{ + Outfile: true, + Fields: fields, + Lines: tree.NewLines("", "\n"), + Header: false, + } +} + +func writeDeleteRowSQLFull( + ctx context.Context, + ses *Session, + tblStuff tableStuff, + row []any, + buf *bytes.Buffer, +) error { + // Use NULL-aware equality and LIMIT 1 to preserve duplicate-row semantics. + buf.WriteString(fmt.Sprintf( + "delete from %s.%s where ", + tblStuff.baseRel.GetTableDef(ctx).DbName, + tblStuff.baseRel.GetTableDef(ctx).Name, + )) + for i, idx := range tblStuff.def.visibleIdxes { + if i > 0 { + buf.WriteString(" and ") + } + colName := tblStuff.def.colNames[idx] + if row[idx] == nil { + buf.WriteString(colName) + buf.WriteString(" is null") + } else { + buf.WriteString(colName) + buf.WriteString(" = ") + if err := formatValIntoString(ses, row[idx], tblStuff.def.colTypes[idx], buf); err != nil { + return err + } + } + } + buf.WriteString(" limit 1;\n") + return nil +} + +func appendBatchRowsAsSQLValues( + ctx context.Context, + ses *Session, + tblStuff tableStuff, + wrapped batchWithKind, + tmpValsBuffer *bytes.Buffer, + appender sqlValuesAppender, +) (err error) { + + //seenCols := make(map[int]struct{}, len(tblStuff.def.visibleIdxes)) + row := make([]any, len(tblStuff.def.colNames)) + + for rowIdx := range wrapped.batch.RowCount() { + if ctx.Err() != nil { + return ctx.Err() + } + + for _, colIdx := range tblStuff.def.visibleIdxes { + //seenCols[colIdx] = struct{}{} + vec := wrapped.batch.Vecs[colIdx] + if vec.GetNulls().Contains(uint64(rowIdx)) { + row[colIdx] = nil + continue + } + + switch vec.GetType().Oid { + case types.T_datetime, types.T_timestamp, types.T_decimal64, + types.T_decimal128, types.T_time: + bb := vec.GetRawBytesAt(rowIdx) + row[colIdx] = types.DecodeValue(bb, vec.GetType().Oid) + default: + if err = extractRowFromVector( + ctx, ses, vec, colIdx, row, rowIdx, false, + ); err != nil { + return + } + } + } + + //for _, pkIdx := range tblStuff.def.pkColIdxes { + // if _, ok := seenCols[pkIdx]; ok { + // continue + // } + // vec := wrapped.batch.Vecs[pkIdx] + // if vec.GetNulls().Contains(uint64(rowIdx)) { + // row[pkIdx] = nil + // continue + // } + // + // switch vec.GetType().Oid { + // case types.T_datetime, types.T_timestamp, types.T_decimal64, + // types.T_decimal128, types.T_time: + // bb := vec.GetRawBytesAt(rowIdx) + // row[pkIdx] = types.DecodeValue(bb, vec.GetType().Oid) + // default: + // if err = extractRowFromVector( + // ctx, ses, vec, pkIdx, row, rowIdx, false, + // ); err != nil { + // return + // } + // } + //} + + tmpValsBuffer.Reset() + if wrapped.kind == diffDelete { + if appender.deleteByFullRow { + if err = writeDeleteRowSQLFull(ctx, ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } + } else if appender.pkInfo != nil { + if err = writeDeleteRowValuesAsTuple(ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } + } else { + if err = writeDeleteRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } + } + } else { + if err = writeInsertRowValues(ses, tblStuff, row, tmpValsBuffer); err != nil { + return + } + } + + if tmpValsBuffer.Len() == 0 { + continue + } + + if err = appender.appendRow(wrapped.kind, tmpValsBuffer.Bytes()); err != nil { + return + } + } + + return nil +} + +func prepareFSForDiffAsFile( + ctx context.Context, + ses *Session, + stmt *tree.DataBranchDiff, + tblStuff tableStuff, +) ( + sqlRetPath, sqlRetHint string, + writeFile func([]byte) error, + release func(), + cleanup func(), + err error, +) { + var ( + ok bool + stagePath string + fileName string + fullFilePath string + ) + + fileName = makeFileName(stmt.BaseTable.AtTsExpr, stmt.TargetTable.AtTsExpr, tblStuff) + fileName += ".sql" + + sqlRetPath = path.Join(stmt.OutputOpt.DirPath, fileName) + + if stagePath, ok, err = tryDecodeStagePath(ses, stmt.OutputOpt.DirPath); err != nil { + return + } else if ok { + sqlRetPath = strings.Replace(sqlRetPath, "stage:/", "stage://", 1) + fullFilePath = path.Join(stagePath, fileName) + } else { + fullFilePath = path.Join(stmt.OutputOpt.DirPath, fileName) + } + + sqlRetHint = fmt.Sprintf( + "DELETE FROM %s.%s, INSERT INTO %s.%s", + tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableName(), + tblStuff.baseRel.GetTableDef(ctx).DbName, tblStuff.baseRel.GetTableName(), + ) + + var ( + targetFS fileservice.FileService + targetPath string + fsPath fileservice.Path + ) + + if fsPath, err = fileservice.ParsePath(fullFilePath); err != nil { + return + } + + if fsPath.Service == defines.SharedFileServiceName { + targetFS = getPu(ses.GetService()).FileService + targetPath = fullFilePath + } else { + // ensure local dir exists when using implicit local ETL path + if fsPath.Service == "" { + if mkErr := os.MkdirAll(filepath.Dir(fullFilePath), 0o755); mkErr != nil { + err = mkErr + return + } + } + + var etlFS fileservice.ETLFileService + if etlFS, targetPath, err = fileservice.GetForETL(ctx, nil, fullFilePath); err != nil { + return + } + targetFS = etlFS + } + + cleanup = func() { + _ = targetFS.Delete(context.Background(), targetPath) + } + + defer func() { + if err != nil { + if cleanup != nil { + cleanup() + } + targetFS.Close(ctx) + } + }() + + if err = targetFS.Delete(ctx, targetPath); err != nil && !moerr.IsMoErrCode(err, moerr.ErrFileNotFound) { + return + } + + if mfs, ok := targetFS.(fileservice.MutableFileService); ok { + // SQL diff needs append, so pre-create the file and return an appender. + if err = targetFS.Write(ctx, fileservice.IOVector{ + FilePath: targetPath, + Entries: []fileservice.IOEntry{ + {Size: 0, Data: []byte{}}, + }, + }); err != nil && !moerr.IsMoErrCode(err, moerr.ErrFileAlreadyExists) { + return + } + + var mut fileservice.Mutator + if mut, err = mfs.NewMutator(ctx, targetPath); err != nil { + return + } + + writeFile = func(fileContent []byte) error { + return mut.Append(ctx, fileservice.IOEntry{ + Size: int64(len(fileContent)), + Data: fileContent, + }) + } + + release = func() { + _ = mut.Close() + targetFS.Close(ctx) + } + } else { + if writeFile, release, err = newSingleWriteAppender( + ctx, tblStuff.worker, targetFS, targetPath, cleanup, + ); err != nil { + return + } + } + + return +} + +func newSingleWriteAppender( + ctx context.Context, + worker *ants.Pool, + targetFS fileservice.FileService, + targetPath string, + onError func(), +) (writeFile func([]byte) error, release func(), err error) { + pr, pw := io.Pipe() + done := make(chan error, 1) + + if worker == nil { + err = moerr.NewInternalErrorNoCtx("worker pool is nil") + return + } + + if err = worker.Submit(func() { + defer close(done) + vec := fileservice.IOVector{ + FilePath: targetPath, + Entries: []fileservice.IOEntry{ + { + ReaderForWrite: pr, + Size: -1, + }, + }, + } + if wErr := targetFS.Write(ctx, vec); wErr != nil { + _ = pr.CloseWithError(wErr) + done <- wErr + return + } + done <- pr.Close() + }); err != nil { + _ = pr.Close() + _ = pw.Close() + return + } + + writeFile = func(fileContent []byte) error { + if len(fileContent) == 0 { + return nil + } + _, err := pw.Write(fileContent) + return err + } + + release = func() { + _ = pw.Close() + if wErr := <-done; wErr != nil && onError != nil { + onError() + } + targetFS.Close(ctx) + } + + return +} + +func removeFileIgnoreError(ctx context.Context, service, filePath string) { + if len(filePath) == 0 { + return + } + + fsPath, err := fileservice.ParsePath(filePath) + if err != nil { + return + } + + var ( + targetFS fileservice.FileService + targetPath string + ) + + if fsPath.Service == defines.SharedFileServiceName { + targetFS = getPu(service).FileService + targetPath = filePath + } else { + var etlFS fileservice.ETLFileService + if etlFS, targetPath, err = fileservice.GetForETL(ctx, nil, filePath); err != nil { + return + } + targetFS = etlFS + } + + _ = targetFS.Delete(ctx, targetPath) + targetFS.Close(ctx) +} + +func tryFlushDeletesOrInserts( + ctx context.Context, + ses *Session, + bh BackgroundExec, + tblStuff tableStuff, + newKind string, + newValsLen int, + newRowCnt int, + deleteByFullRow bool, + pkInfo *pkBatchInfo, + deleteCnt *int, + deletesBuf *bytes.Buffer, + insertCnt *int, + insertBuf *bytes.Buffer, + writeFile func([]byte) error, +) (err error) { + + flushDeletes := func() error { + if err = flushSqlValues( + ctx, ses, bh, tblStuff, deletesBuf, true, deleteByFullRow, pkInfo, writeFile, + ); err != nil { + return err + } + + *deleteCnt = 0 + deletesBuf.Reset() + return nil + } + + flushInserts := func() error { + if err = flushSqlValues( + ctx, ses, bh, tblStuff, insertBuf, false, false, pkInfo, writeFile, + ); err != nil { + return err + } + + *insertCnt = 0 + insertBuf.Reset() + return nil + } + + // if wrapped is nil, means force flush + if newKind != "" { + if newKind == diffDelete { + if deletesBuf.Len()+newValsLen >= maxSqlBatchSize || + *deleteCnt+newRowCnt >= maxSqlBatchCnt { + return flushDeletes() + } + } else { + if insertBuf.Len()+newValsLen >= maxSqlBatchSize || + *insertCnt+newRowCnt >= maxSqlBatchCnt { + if *deleteCnt > 0 { + if err = flushDeletes(); err != nil { + return err + } + } + return flushInserts() + } + } + return nil + } + + if *deleteCnt > 0 { + if err = flushDeletes(); err != nil { + return err + } + } + + if *insertCnt > 0 { + if err = flushInserts(); err != nil { + return err + } + } + + return nil +} + +type pkBatchInfo struct { + dbName string + baseTable string + deleteTable string + insertTable string + pkNames []string + visibleNames []string +} + +func newPKBatchInfo(ctx context.Context, ses *Session, tblStuff tableStuff) *pkBatchInfo { + if tblStuff.def.pkKind == fakeKind { + return nil + } + + pkNames := make([]string, len(tblStuff.def.pkColIdxes)) + for i, idx := range tblStuff.def.pkColIdxes { + pkNames[i] = tblStuff.def.colNames[idx] + } + + visibleNames := make([]string, len(tblStuff.def.visibleIdxes)) + for i, idx := range tblStuff.def.visibleIdxes { + visibleNames[i] = tblStuff.def.colNames[idx] + } + + seq := atomic.AddUint64(&diffTempTableSeq, 1) + sessionTag := strings.ReplaceAll(ses.GetUUIDString(), "-", "") + return &pkBatchInfo{ + dbName: tblStuff.baseRel.GetTableDef(ctx).DbName, + baseTable: tblStuff.baseRel.GetTableName(), + deleteTable: fmt.Sprintf("__mo_diff_del_%s_%d", sessionTag, seq), + insertTable: fmt.Sprintf("__mo_diff_ins_%s_%d", sessionTag, seq), + pkNames: pkNames, + visibleNames: visibleNames, + } +} + +type sqlValuesAppender struct { + ctx context.Context + ses *Session + bh BackgroundExec + tblStuff tableStuff + deleteByFullRow bool + pkInfo *pkBatchInfo + deleteCnt *int + deleteBuf *bytes.Buffer + insertCnt *int + insertBuf *bytes.Buffer + writeFile func([]byte) error +} + +func (sva sqlValuesAppender) flushAll() error { + return tryFlushDeletesOrInserts( + sva.ctx, sva.ses, sva.bh, sva.tblStuff, "", + 0, 0, sva.deleteByFullRow, sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + ) +} + +func writeInsertRowValues( + ses *Session, + tblStuff tableStuff, + row []any, + buf *bytes.Buffer, +) error { + buf.WriteString("(") + for i, idx := range tblStuff.def.visibleIdxes { + if err := formatValIntoString(ses, row[idx], tblStuff.def.colTypes[idx], buf); err != nil { + return err + } + if i != len(tblStuff.def.visibleIdxes)-1 { + buf.WriteString(",") + } + } + buf.WriteString(")") + + return nil +} + +func writeDeleteRowValues( + ses *Session, + tblStuff tableStuff, + row []any, + buf *bytes.Buffer, +) error { + if len(tblStuff.def.pkColIdxes) > 1 { + buf.WriteString("(") + } + for i, colIdx := range tblStuff.def.pkColIdxes { + if err := formatValIntoString(ses, row[colIdx], tblStuff.def.colTypes[colIdx], buf); err != nil { + return err + } + if i != len(tblStuff.def.pkColIdxes)-1 { + buf.WriteString(",") + } + } + if len(tblStuff.def.pkColIdxes) > 1 { + buf.WriteString(")") + } + + return nil +} + +func writeDeleteRowValuesAsTuple( + ses *Session, + tblStuff tableStuff, + row []any, + buf *bytes.Buffer, +) error { + buf.WriteString("(") + for i, colIdx := range tblStuff.def.pkColIdxes { + if err := formatValIntoString(ses, row[colIdx], tblStuff.def.colTypes[colIdx], buf); err != nil { + return err + } + if i != len(tblStuff.def.pkColIdxes)-1 { + buf.WriteString(",") + } + } + buf.WriteString(")") + return nil +} + +func (sva sqlValuesAppender) appendRow(kind string, rowValues []byte) error { + var ( + targetBuf *bytes.Buffer + rowCnt *int + ) + + if kind == diffDelete { + targetBuf = sva.deleteBuf + rowCnt = sva.deleteCnt + if sva.deleteByFullRow { + newValsLen := len(rowValues) + if err := tryFlushDeletesOrInserts( + sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, + sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + ); err != nil { + return err + } + + targetBuf.Write(rowValues) + *rowCnt++ + return nil + } + } else { + targetBuf = sva.insertBuf + rowCnt = sva.insertCnt + } + + newValsLen := len(rowValues) + if targetBuf.Len() > 0 { + newValsLen++ + } + + if err := tryFlushDeletesOrInserts( + sva.ctx, sva.ses, sva.bh, sva.tblStuff, kind, newValsLen, 1, sva.deleteByFullRow, + sva.pkInfo, sva.deleteCnt, sva.deleteBuf, sva.insertCnt, sva.insertBuf, sva.writeFile, + ); err != nil { + return err + } + + if targetBuf.Len() > 0 { + targetBuf.WriteString(",") + } + targetBuf.Write(rowValues) + *rowCnt++ + return nil +} + +func qualifiedTableName(dbName, tableName string) string { + return fmt.Sprintf("%s.%s", dbName, tableName) +} + +func execSQLStatements( + ctx context.Context, + ses *Session, + bh BackgroundExec, + writeFile func([]byte) error, + stmts []string, +) error { + for _, stmt := range stmts { + if stmt == "" { + continue + } + if writeFile != nil { + if err := writeFile([]byte(stmt + ";\n")); err != nil { + return err + } + continue + } + ret, err := runSql(ctx, ses, bh, stmt, nil, nil) + if len(ret.Batches) > 0 && ret.Mp != nil { + ret.Close() + } + if err != nil { + return err + } + } + return nil +} + +func initPKTables( + ctx context.Context, + ses *Session, + bh BackgroundExec, + pkInfo *pkBatchInfo, + writeFile func([]byte) error, +) error { + if pkInfo == nil { + return nil + } + + baseTable := qualifiedTableName(pkInfo.dbName, pkInfo.baseTable) + deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) + insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) + + deleteCols := strings.Join(pkInfo.pkNames, ",") + insertCols := strings.Join(pkInfo.visibleNames, ",") + + stmts := []string{ + fmt.Sprintf("drop table if exists %s", deleteTable), + fmt.Sprintf("drop table if exists %s", insertTable), + fmt.Sprintf("create table %s as select %s from %s where 1=0", deleteTable, deleteCols, baseTable), + fmt.Sprintf("create table %s as select %s from %s where 1=0", insertTable, insertCols, baseTable), + } + + return execSQLStatements(ctx, ses, bh, writeFile, stmts) +} + +func dropPKTables( + ctx context.Context, + ses *Session, + bh BackgroundExec, + pkInfo *pkBatchInfo, + writeFile func([]byte) error, +) error { + if pkInfo == nil { + return nil + } + + deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) + insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) + + stmts := []string{ + fmt.Sprintf("drop table if exists %s", deleteTable), + fmt.Sprintf("drop table if exists %s", insertTable), + } + return execSQLStatements(ctx, ses, bh, writeFile, stmts) +} + +// if `writeFile` is not nil, the sql will be flushed down into this file, or +// the sql will be executed by bh. +func flushSqlValues( + ctx context.Context, + ses *Session, + bh BackgroundExec, + tblStuff tableStuff, + buf *bytes.Buffer, + isDeleteFrom bool, + deleteByFullRow bool, + pkInfo *pkBatchInfo, + writeFile func([]byte) error, +) (err error) { + + if buf.Len() == 0 { + return nil + } + + if isDeleteFrom && deleteByFullRow { + if writeFile != nil { + return writeFile(buf.Bytes()) + } + + statements := bytes.Split(buf.Bytes(), []byte(";\n")) + for _, stmt := range statements { + stmt = bytes.TrimSpace(stmt) + if len(stmt) == 0 { + continue + } + var ret executor.Result + ret, err = runSql(ctx, ses, bh, string(stmt)+";", nil, nil) + ret.Close() + if err != nil { + return err + } + } + return nil + } + + if pkInfo != nil { + baseTable := qualifiedTableName(pkInfo.dbName, pkInfo.baseTable) + deleteTable := qualifiedTableName(pkInfo.dbName, pkInfo.deleteTable) + insertTable := qualifiedTableName(pkInfo.dbName, pkInfo.insertTable) + + if isDeleteFrom { + insertStmt := fmt.Sprintf("insert into %s values %s", deleteTable, buf.String()) + pkExpr := pkInfo.pkNames[0] + if len(pkInfo.pkNames) > 1 { + pkExpr = fmt.Sprintf("(%s)", strings.Join(pkInfo.pkNames, ",")) + } + deleteStmt := fmt.Sprintf( + "delete from %s where %s in (select %s from %s)", + baseTable, pkExpr, strings.Join(pkInfo.pkNames, ","), deleteTable, + ) + clearStmt := fmt.Sprintf("delete from %s", deleteTable) + return execSQLStatements(ctx, ses, bh, writeFile, []string{insertStmt, deleteStmt, clearStmt}) + } + + insertStmt := fmt.Sprintf("insert into %s values %s", insertTable, buf.String()) + cols := strings.Join(pkInfo.visibleNames, ",") + applyStmt := fmt.Sprintf( + "insert into %s (%s) select %s from %s", + baseTable, cols, cols, insertTable, + ) + clearStmt := fmt.Sprintf("delete from %s", insertTable) + return execSQLStatements(ctx, ses, bh, writeFile, []string{insertStmt, applyStmt, clearStmt}) + } + + sqlBuffer := acquireBuffer(tblStuff.bufPool) + defer releaseBuffer(tblStuff.bufPool, sqlBuffer) + + initInsertIntoBuf := func() { + sqlBuffer.WriteString(fmt.Sprintf( + "insert into %s.%s values ", + tblStuff.baseRel.GetTableDef(ctx).DbName, + tblStuff.baseRel.GetTableDef(ctx).Name, + )) + } + + initDeleteFromBuf := func() { + if len(tblStuff.def.pkColIdxes) == 1 { + sqlBuffer.WriteString(fmt.Sprintf( + "delete from %s.%s where %s in (", + tblStuff.baseRel.GetTableDef(ctx).DbName, + tblStuff.baseRel.GetTableDef(ctx).Name, + tblStuff.def.colNames[tblStuff.def.pkColIdx], + )) + } else { + pkNames := make([]string, len(tblStuff.def.pkColIdxes)) + for i, pkColIdx := range tblStuff.def.pkColIdxes { + pkNames[i] = tblStuff.def.colNames[pkColIdx] + } + sqlBuffer.WriteString(fmt.Sprintf( + "delete from %s.%s where (%s) in (", + tblStuff.baseRel.GetTableDef(ctx).DbName, + tblStuff.baseRel.GetTableDef(ctx).Name, + strings.Join(pkNames, ","), + )) + } + } + + if isDeleteFrom { + initDeleteFromBuf() + sqlBuffer.Write(buf.Bytes()) + sqlBuffer.WriteString(")") + } else { + initInsertIntoBuf() + sqlBuffer.Write(buf.Bytes()) + } + + sqlBuffer.WriteString(";\n") + + if writeFile != nil { + err = writeFile(sqlBuffer.Bytes()) + } else { + var ( + ret executor.Result + ) + + defer func() { + ret.Close() + }() + ret, err = runSql(ctx, ses, bh, sqlBuffer.String(), nil, nil) + } + + return err +} +func validateOutputDirPath(ctx context.Context, ses *Session, dirPath string) (err error) { + if len(dirPath) == 0 { + return nil + } + + var ( + stagePath string + ok bool + inputDirPath = dirPath + ) + + if stagePath, ok, err = tryDecodeStagePath(ses, dirPath); err != nil { + return + } else if ok { + dirPath = stagePath + } + + var fsPath fileservice.Path + if fsPath, err = fileservice.ParsePath(dirPath); err != nil { + return + } + + if fsPath.Service == "" { + var info os.FileInfo + if info, err = os.Stat(dirPath); err != nil { + if os.IsNotExist(err) { + return moerr.NewInvalidInputNoCtxf("output directory %s does not exist", inputDirPath) + } + return + } + if !info.IsDir() { + return moerr.NewInvalidInputNoCtxf("output directory %s is not a directory", inputDirPath) + } + return nil + } + + var ( + targetFS fileservice.FileService + targetPath string + entry *fileservice.DirEntry + ) + + if fsPath.Service == defines.SharedFileServiceName { + targetFS = getPu(ses.GetService()).FileService + targetPath = dirPath + } else { + var etlFS fileservice.ETLFileService + if etlFS, targetPath, err = fileservice.GetForETL(ctx, nil, dirPath); err != nil { + return + } + targetFS = etlFS + defer targetFS.Close(ctx) + } + + if len(strings.Trim(targetPath, "/")) == 0 { + // service root: try listing to ensure the bucket/root is reachable + for _, err = range targetFS.List(ctx, targetPath) { + if err != nil { + if moerr.IsMoErrCode(err, moerr.ErrFileNotFound) { + return moerr.NewInvalidInputNoCtxf("output directory %s does not exist", inputDirPath) + } + return err + } + // any entry means list works + break + } + return nil + } + + if entry, err = targetFS.StatFile(ctx, targetPath); err != nil { + if moerr.IsMoErrCode(err, moerr.ErrFileNotFound) { + // fallthrough to List-based directory detection + } else { + return + } + } + + // StatFile succeeded: reject if it's a file, accept if the FS can stat directories. + if entry != nil { + if !entry.IsDir { + return moerr.NewInvalidInputNoCtxf("output directory %s is not a directory", inputDirPath) + } + return nil + } + + // StatFile can't prove directory existence (common for object storage). Use parent List to + // detect the child entry and its type. + trimmedPath := strings.TrimRight(targetPath, "/") + if len(trimmedPath) == 0 { + // root of the service, treat as directory + return nil + } + parent, base := path.Split(trimmedPath) + parent = strings.TrimRight(parent, "/") + if len(base) == 0 { + // target is root + return nil + } + + for entry, err = range targetFS.List(ctx, parent) { + if err != nil { + return err + } + if entry.Name != base { + continue + } + if !entry.IsDir { + return moerr.NewInvalidInputNoCtxf("output directory %s is not a directory", inputDirPath) + } + return nil + } + + return moerr.NewInvalidInputNoCtxf("output directory %s does not exist", inputDirPath) +} diff --git a/pkg/frontend/data_branch_types.go b/pkg/frontend/data_branch_types.go new file mode 100644 index 0000000000000..45473446aa69f --- /dev/null +++ b/pkg/frontend/data_branch_types.go @@ -0,0 +1,148 @@ +// Copyright 2025 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "sync" + + "github.com/matrixorigin/matrixone/pkg/common/malloc" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/common/rscthrottler" + "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/objectio" + "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/matrixorigin/matrixone/pkg/vm/engine" + "github.com/panjf2000/ants/v2" +) + +const ( + fakeKind = iota + normalKind + compositeKind +) + +const ( + diffInsert = "INSERT" + diffDelete = "DELETE" + diffUpdate = "UPDATE" +) + +const ( + diffSideUnknown = iota + diffSideTarget + diffSideBase +) + +const dataBranchHashmapLimitRate = 0.8 + +type branchHashmapAllocator struct { + upstream malloc.Allocator + throttler rscthrottler.RSCThrottler +} + +type branchHashmapDeallocator struct { + upstream malloc.Deallocator + throttler rscthrottler.RSCThrottler + size uint64 +} + +var diffTempTableSeq uint64 + +const ( + lcaEmpty = iota + lcaOther + lcaLeft + lcaRight +) + +const ( + maxSqlBatchCnt = objectio.BlockMaxRows * 10 + maxSqlBatchSize = mpool.MB * 32 + defaultRowBytes = int64(128) + tombstoneRowMult = int64(3) + tombstoneRowDiv = int64(2) +) + +type collectRange struct { + from []types.TS + end []types.TS + rel []engine.Relation +} + +type branchMetaInfo struct { + lcaType int + lcaTableId uint64 + tarBranchTS types.TS + baseBranchTS types.TS +} + +type tableStuff struct { + tarRel engine.Relation + baseRel engine.Relation + tarSnap *plan.Snapshot + baseSnap *plan.Snapshot + + lcaRel engine.Relation + + def struct { + colNames []string // all columns + colTypes []types.Type // all columns + visibleIdxes []int + pkColIdx int + pkColIdxes []int // expanded pk columns + pkKind int + } + + worker *ants.Pool + hashmapAllocator *branchHashmapAllocator + maxTombstoneBatchCnt int + + retPool *retBatchList + + bufPool *sync.Pool +} + +type batchWithKind struct { + name string + kind string + side int + batch *batch.Batch +} + +type emitFunc func(batchWithKind) (stop bool, err error) + +type retBatchList struct { + mu sync.Mutex + // 0: data + // 1: tombstone + dList []*batch.Batch + tList []*batch.Batch + + pinned map[*batch.Batch]struct{} + //debug map[*batch.Batch]retBatchDebug + + dataVecCnt int + tombVecCnt int + dataTypes []types.Type + tombstoneType types.Type +} + +type compositeOption struct { + conflictOpt *tree.ConflictOpt + outputSQL bool + expandUpdate bool +} From 2a0767be5224a2f0b94919a58ba191026d675d03 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Fri, 27 Feb 2026 19:21:06 +0800 Subject: [PATCH 11/23] debug get commit ts --- pkg/frontend/data_branch.go | 223 ++++++++++-------- pkg/objectio/funcs.go | 13 + .../disttae/local_disttae_datasource.go | 34 ++- .../disttae/logtailreplay/partition_state.go | 13 + .../disttae/txn_table_sharding_handle.go | 2 + pkg/vm/engine/readutil/reader.go | 3 + pkg/vm/engine/tae/blockio/read.go | 93 +++++++- .../engine/tae/blockio/read_cn_commit_test.go | 78 ++++++ 8 files changed, 352 insertions(+), 107 deletions(-) create mode 100644 pkg/vm/engine/tae/blockio/read_cn_commit_test.go diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 2c0c1c07efbfc..3f7eb57db40db 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -20,7 +20,6 @@ import ( "fmt" "regexp" "runtime" - "slices" "strconv" "strings" "sync" @@ -36,14 +35,14 @@ import ( "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/defines" "github.com/matrixorigin/matrixone/pkg/frontend/databranchutils" + "github.com/matrixorigin/matrixone/pkg/objectio" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/pb/timestamp" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" - "github.com/matrixorigin/matrixone/pkg/txn/client" "github.com/matrixorigin/matrixone/pkg/util/executor" - "github.com/matrixorigin/matrixone/pkg/vectorindex/sqlexec" "github.com/matrixorigin/matrixone/pkg/vm/engine" + "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" "github.com/panjf2000/ants/v2" ) @@ -1202,11 +1201,7 @@ func decideCollectRange( tarTableID = tables.tarRel.GetTableID(ctx) baseTableID = tables.baseRel.GetTableID(ctx) - mp = ses.proc.Mp() - eng = ses.proc.GetSessionInfo().StorageEngine - txnOp = ses.GetTxnHandler().GetTxn() - - txnSnapshot = types.TimestampToTS(txnOp.SnapshotTS()) + txnSnapshot = types.TimestampToTS(ses.GetTxnHandler().GetTxn().SnapshotTS()) ) tarSp = txnSnapshot @@ -1220,10 +1215,8 @@ func decideCollectRange( } if tblCommitTS, err = getTablesCreationCommitTS( - ctx, ses, eng, mp, - tables.tarRel, tables.baseRel, + ctx, ses, tables.tarRel, tables.baseRel, []types.TS{tarSp, baseSp}, - txnOp, ); err != nil { return } @@ -1413,119 +1406,141 @@ func decideCollectRange( func getTablesCreationCommitTS( ctx context.Context, ses *Session, - eng engine.Engine, - mp *mpool.MPool, tar engine.Relation, base engine.Relation, snapshot []types.TS, - txnOp client.TxnOperator, ) (commitTS []types.TS, err error) { - var ( - sqlRet executor.Result - data *batch.Batch - tombstone *batch.Batch - moTableRel engine.Relation - moTableHandle engine.ChangesHandle - - from types.TS - end types.TS - ) - - defer func() { - if data != nil { - data.Clean(mp) - } - if moTableHandle != nil { - moTableHandle.Close() + resolveSnapshot := func(idx int) types.TS { + if idx >= 0 && idx < len(snapshot) && !snapshot[idx].IsEmpty() { + return snapshot[idx] } - }() - - if _, _, moTableRel, err = eng.GetRelationById( - ctx, txnOp, catalog.MO_TABLES_ID, - ); err != nil { - return + return types.TimestampToTS(ses.GetTxnHandler().GetTxn().SnapshotTS()) } - buf := &bytes.Buffer{} - defer func() { - sqlRet.Close() - }() - - // pk ==> account_id and reldatabase and relname - buf.WriteString("select min(created_time) from mo_catalog.mo_tables where ") - buf.WriteString(fmt.Sprintf( - "(account_id = %d and reldatabase = '%s' and relname = '%s')", - ses.accountId, tar.GetTableDef(ctx).DbName, tar.GetTableName(), - )) - buf.WriteString(" OR ") - buf.WriteString(fmt.Sprintf( - "(account_id = %d and reldatabase = '%s' and relname = '%s')", - ses.accountId, base.GetTableDef(ctx).DbName, base.GetTableName(), - )) - - if sqlRet, err = sqlexec.RunSql(sqlexec.NewSqlProcess(ses.proc), buf.String()); err != nil { - return - } - - if len(sqlRet.Batches) != 1 && sqlRet.Batches[0].RowCount() != 1 { - return nil, moerr.NewInternalErrorNoCtxf( - "get table created time for (%s, %s) failed(%s)", - tar.GetTableName(), base.GetTableName(), buf.String(), - ) - } - - ts := vector.GetFixedAtWithTypeCheck[types.Timestamp](sqlRet.Batches[0].Vecs[0], 0) - from = types.BuildTS( - ts.ToDatetime(ses.timeZone).ConvertToGoTime(ses.timeZone).UnixNano(), - 0, - ) - - end = slices.MaxFunc(snapshot, func(a, b types.TS) int { return a.Compare(&b) }) - - if moTableHandle, err = moTableRel.CollectChanges( - ctx, from, end, true, mp, - ); err != nil { - return - } + resolveOne := func(tableID uint64, sp types.TS) (types.TS, error) { + resolveAt := func(snapshotTS types.TS) (commit types.TS, ok bool, err error) { + txnOp := ses.GetTxnHandler().GetTxn().CloneSnapshotOp(snapshotTS.ToTimestamp()) + _, _, moTablesRel, rerr := ses.GetTxnHandler().GetStorage().GetRelationById(ctx, txnOp, catalog.MO_TABLES_ID) + if rerr != nil { + return types.TS{}, false, rerr + } - commitTS = make([]types.TS, 2) + relData, rerr := moTablesRel.Ranges(ctx, engine.DefaultRangesParam) + if rerr != nil { + return types.TS{}, false, rerr + } + readers, rerr := moTablesRel.BuildReaders( + ctx, + ses.proc, + nil, + relData, + 1, + 0, + false, + engine.Policy_CheckCommittedOnly, + engine.FilterHint{}, + ) + if rerr != nil { + return types.TS{}, false, rerr + } + defer func() { + for _, rd := range readers { + if rd != nil { + _ = rd.Close() + } + } + }() + + attrs := []string{ + catalog.SystemRelAttr_ID, + objectio.DefaultCommitTS_Attr, + } + readBatch := batch.NewWithSize(len(attrs)) + readBatch.SetAttributes(attrs) + readBatch.Vecs[0] = vector.NewVec(types.T_uint64.ToType()) + readBatch.Vecs[1] = vector.NewVec(types.T_TS.ToType()) + defer readBatch.Clean(ses.proc.Mp()) + + rowFound := false + commitFound := false + commitTS := types.TS{} + for _, rd := range readers { + for { + var isEnd bool + isEnd, rerr = rd.Read(ctx, attrs, nil, ses.proc.Mp(), readBatch) + if rerr != nil { + return types.TS{}, false, rerr + } + if isEnd { + break + } + if readBatch.RowCount() == 0 { + continue + } + + fmt.Printf("AAAA tableId=%d, bat=%s\n", + tableID, common.MoBatchToString(readBatch, readBatch.RowCount())) + + relIDs := vector.MustFixedColWithTypeCheck[uint64](readBatch.Vecs[0]) + commitCol := vector.MustFixedColWithTypeCheck[types.TS](readBatch.Vecs[1]) + for i := range relIDs { + if relIDs[i] != tableID { + continue + } + rowFound = true + if !readBatch.Vecs[1].IsNull(uint64(i)) { + if !commitFound || commitCol[i].LT(&commitTS) { + commitTS = commitCol[i] + } + commitFound = true + fmt.Printf("AAAA tableId=%d row=%d commit=%s\n", + tableID, i, commitCol[i].ToString()) + } else { + fmt.Printf("AAAA tableId=%d row=%d commit=NULL\n", + tableID, i) + } + } + } + } - for commitTS[0].IsEmpty() || commitTS[1].IsEmpty() { - if data, tombstone, _, err = moTableHandle.Next(ctx, mp); err != nil { - return - } else if data == nil && tombstone == nil { - break + if commitFound { + return commitTS, true, nil + } + return types.TS{}, rowFound, nil } - if tombstone != nil { - tombstone.Clean(mp) + if commit, ok, rerr := resolveAt(sp); rerr != nil { + return types.TS{}, rerr + } else if ok { + return commit, nil } - if data != nil { - relIdCol := vector.MustFixedColNoTypeCheck[uint64](data.Vecs[0]) - commitTSCol := vector.MustFixedColNoTypeCheck[types.TS](data.Vecs[len(data.Vecs)-1]) - - if idx := slices.Index(relIdCol, tar.GetTableID(ctx)); idx != -1 { - commitTS[0] = commitTSCol[idx] + curSnapshot := types.TimestampToTS(ses.GetTxnHandler().GetTxn().SnapshotTS()) + if !curSnapshot.EQ(&sp) { + if commit, ok, rerr := resolveAt(curSnapshot); rerr != nil { + return types.TS{}, rerr + } else if ok { + return commit, nil } - - if idx := slices.Index(relIdCol, base.GetTableID(ctx)); idx != -1 { - commitTS[1] = commitTSCol[idx] - } - - data.Clean(mp) } - } - if commitTS[0].IsEmpty() || commitTS[1].IsEmpty() { - err = moerr.NewInternalErrorNoCtxf( - "get table created time for (%s, %s) failed", - tar.GetTableName(), base.GetTableName(), + return types.TS{}, moerr.NewInternalErrorNoCtxf( + "cannot find table %d commit ts at snapshot %s", + tableID, + sp.ToString(), ) } - return commitTS, err + tarCommitTS, err := resolveOne(tar.GetTableID(ctx), resolveSnapshot(0)) + if err != nil { + return nil, err + } + baseCommitTS, err := resolveOne(base.GetTableID(ctx), resolveSnapshot(1)) + if err != nil { + return nil, err + } + return []types.TS{tarCommitTS, baseCommitTS}, nil } func decideLCABranchTSFromBranchDAG( diff --git a/pkg/objectio/funcs.go b/pkg/objectio/funcs.go index f100c33a2ec03..2eb0aa0b8bd98 100644 --- a/pkg/objectio/funcs.go +++ b/pkg/objectio/funcs.go @@ -160,6 +160,7 @@ func ReadOneBlockWithMeta( blkmeta := meta.GetBlockMeta(uint32(blk)) maxSeqnum := blkmeta.GetMaxSeqnum() for i, seqnum := range seqnums { + reqSeqnum := seqnum // special columns if seqnum >= SEQNUM_UPPER { metaColCnt := blkmeta.GetMetaColumnCount() @@ -176,6 +177,18 @@ func ReadOneBlockWithMeta( // 2. old version tn nonappendable block col := blkmeta.ColumnMeta(seqnum) if col.DataType() != uint8(types.T_TS) { + if reqSeqnum == SEQNUM_COMMITTS { + logutil.Infof( + "AAAA objectio commit placeholder: file=%s blk=%d reqSeq=%d mappedSeq=%d metaColCnt=%d dtype=%d rows=%d", + name, + blk, + reqSeqnum, + seqnum, + metaColCnt, + col.DataType(), + blkmeta.GetRows(), + ) + } putFillHolder(i, seqnum) } else { ext := col.Location() diff --git a/pkg/vm/engine/disttae/local_disttae_datasource.go b/pkg/vm/engine/disttae/local_disttae_datasource.go index e50844c147ceb..f16f06e815450 100644 --- a/pkg/vm/engine/disttae/local_disttae_datasource.go +++ b/pkg/vm/engine/disttae/local_disttae_datasource.go @@ -155,6 +155,15 @@ func (ls *LocalDisttaeDataSource) String() string { blks) } +func (ls *LocalDisttaeDataSource) GetObjectCreateTS( + bid *objectio.Blockid, +) (types.TS, bool) { + if ls == nil || ls.pState == nil || bid == nil { + return types.TS{}, false + } + return ls.pState.GetDataObjectCreateTS(bid.Object()) +} + func (ls *LocalDisttaeDataSource) SetOrderBy(orderby []*plan.OrderBySpec) { ls.OrderBy = orderby } @@ -849,9 +858,30 @@ func (ls *LocalDisttaeDataSource) filterInMemCommittedInserts( if i == physicalColumnPos { continue } - idx := 2 /*rowid and commits*/ + seqNums[i] + + var idx uint16 + switch seqNums[i] { + case objectio.SEQNUM_COMMITTS: + // in-memory committed row batch layout: + // [0]=rowid, [1]=commitTS, [2+seq]=user columns + idx = 1 + default: + idx = 2 /*rowid and commits*/ + seqNums[i] + } + if int(idx) >= len(entry.Batch.Vecs) /*add column*/ || entry.Batch.Attrs[idx] == "" /*drop column*/ { + if seqNums[i] == objectio.SEQNUM_COMMITTS { + logutil.Infof( + "AAAA inmem commit missing: tableId=%d idx=%d vecs=%d attrs=%d rowOffset=%d rowTime=%s", + ls.table.tableId, + idx, + len(entry.Batch.Vecs), + len(entry.Batch.Attrs), + entry.Offset, + entry.Time.ToString(), + ) + } err = vector.AppendAny( outBatch.Vecs[i], nil, @@ -859,7 +889,7 @@ func (ls *LocalDisttaeDataSource) filterInMemCommittedInserts( mp) } else { err = outBatch.Vecs[i].UnionOne( - entry.Batch.Vecs[int(2+seqNums[i])], + entry.Batch.Vecs[int(idx)], entry.Offset, mp, ) diff --git a/pkg/vm/engine/disttae/logtailreplay/partition_state.go b/pkg/vm/engine/disttae/logtailreplay/partition_state.go index e5a41490e109d..65b786cdbf2d8 100644 --- a/pkg/vm/engine/disttae/logtailreplay/partition_state.go +++ b/pkg/vm/engine/disttae/logtailreplay/partition_state.go @@ -1588,6 +1588,19 @@ func (p *PartitionState) IsDataObjectVisible(objId *types.Objectid, snapshot typ return false } +// GetDataObjectCreateTS returns the create timestamp of a persisted data object. +func (p *PartitionState) GetDataObjectCreateTS(objID *types.Objectid) (types.TS, bool) { + var stats objectio.ObjectStats + objectio.SetObjectStatsObjectName(&stats, objectio.BuildObjectNameWithObjectID(objID)) + + entry := objectio.ObjectEntry{ObjectStats: stats} + if obj, exists := p.dataObjectsNameIndex.Get(entry); exists { + return obj.CreateTime, true + } + + return types.TS{}, false +} + // countTombstoneStatsLinear uses linear deduplication for single object // Single object is already sorted, no cross-object duplicates possible func (p *PartitionState) countTombstoneStatsLinear( diff --git a/pkg/vm/engine/disttae/txn_table_sharding_handle.go b/pkg/vm/engine/disttae/txn_table_sharding_handle.go index cccd95c7569f8..85cf7bb3c87de 100644 --- a/pkg/vm/engine/disttae/txn_table_sharding_handle.go +++ b/pkg/vm/engine/disttae/txn_table_sharding_handle.go @@ -52,6 +52,8 @@ func (sr *shardingRemoteReader) updateCols(cols []string, tblDef *plan.TableDef) column = strings.ToLower(column) if objectio.IsPhysicalAddr(column) { sr.colTypes[i] = objectio.RowidType + } else if strings.EqualFold(column, objectio.DefaultCommitTS_Attr) { + sr.colTypes[i] = types.T_TS.ToType() } else { colIdx := tblDef.Name2ColIndex[column] colDef := tblDef.Cols[colIdx] diff --git a/pkg/vm/engine/readutil/reader.go b/pkg/vm/engine/readutil/reader.go index 08945e2d9fa73..f1eb62884a4df 100644 --- a/pkg/vm/engine/readutil/reader.go +++ b/pkg/vm/engine/readutil/reader.go @@ -127,6 +127,9 @@ func (mixin *withFilterMixin) tryUpdateColumns(cols []string) { mixin.columns.seqnums[i] = objectio.SEQNUM_ROWID mixin.columns.colTypes[i] = objectio.RowidType mixin.columns.phyAddrPos = i + } else if strings.EqualFold(column, objectio.DefaultCommitTS_Attr) { + mixin.columns.seqnums[i] = objectio.SEQNUM_COMMITTS + mixin.columns.colTypes[i] = types.T_TS.ToType() } else { if plan2.GetSortOrderByName(mixin.tableDef, column) == 0 { mixin.columns.indexOfFirstSortedColumn = i diff --git a/pkg/vm/engine/tae/blockio/read.go b/pkg/vm/engine/tae/blockio/read.go index a803e3795812e..ffeb23ad347a3 100644 --- a/pkg/vm/engine/tae/blockio/read.go +++ b/pkg/vm/engine/tae/blockio/read.go @@ -82,6 +82,7 @@ func ReadDataByFilter( colTypes, -1, info, + ds, ts, fileservice.Policy(0), cacheVectors, @@ -149,7 +150,7 @@ func BlockDataReadNoCopy( // read block data from storage specified by meta location if deleteMask, release, err = readBlockData( - ctx, columns, colTypes, phyAddrColumnPos, info, ts, policy, cacheVectors, mp, fs, + ctx, columns, colTypes, phyAddrColumnPos, info, ds, ts, policy, cacheVectors, mp, fs, ); err != nil { return nil, nil, nil, err } @@ -545,6 +546,7 @@ func BlockDataReadInner( colTypes, phyAddrColumnPos, info, + ds, ts, policy, cacheVectors, @@ -717,6 +719,72 @@ func buildRowidColumn( return } +type cnCreatedObjectCreateTSProvider interface { + GetObjectCreateTS(bid *objectio.Blockid) (types.TS, bool) +} + +func getCreateTSLookup( + ds engine.DataSource, + info *objectio.BlockInfo, +) func() (types.TS, bool) { + if ds == nil || info == nil || !info.IsCNCreated() { + return nil + } + p, ok := ds.(cnCreatedObjectCreateTSProvider) + if !ok { + return nil + } + return func() (types.TS, bool) { + return p.GetObjectCreateTS(&info.BlockID) + } +} + +func fillCNCreatedCommitTSIfNeeded( + cols []uint16, + cacheVectors containers.Vectors, + m *mpool.MPool, + info *objectio.BlockInfo, + getCreateTS func() (types.TS, bool), +) error { + if getCreateTS == nil { + return nil + } + + createTS, ok := getCreateTS() + if !ok { + logutil.Infof( + "AAAA blockio commit fill skipped: no createTS, blk=%s", + info.BlockID.String(), + ) + return nil + } + + for i, seq := range cols { + if seq != objectio.SEQNUM_COMMITTS || i >= len(cacheVectors) { + continue + } + + vec := &cacheVectors[i] + if vec.Length() == 0 || !vec.AllNull() { + continue + } + + filled, err := vector.NewConstFixed(types.T_TS.ToType(), createTS, vec.Length(), m) + if err != nil { + return err + } + cacheVectors[i] = *filled + logutil.Infof( + "AAAA blockio commit filled from createTS: blk=%s rows=%d createTS=%s", + info.BlockID.String(), + vec.Length(), + createTS.ToString(), + ) + } + + return nil +} + // This func load columns from storage of specified column indexes // No memory copy, the loaded data is directly stored in the cacheVectors // if `phyAddrColumnPos` >= 0, it means one of the columns is the physical address column, @@ -735,6 +803,7 @@ func readBlockData( colTypes []types.Type, phyAddrColumnPos int, info *objectio.BlockInfo, + ds engine.DataSource, ts types.TS, policy fileservice.Policy, cacheVectors containers.Vectors, @@ -748,6 +817,7 @@ func readBlockData( cacheVectors.Free(m) idxes, typs := excludePhyAddrColumn(colIndexes, colTypes, phyAddrColumnPos) + createTSLookup := getCreateTSLookup(ds, info) readColumns := func( cols []uint16, @@ -762,6 +832,27 @@ func readBlockData( release, err2 = ioutil.LoadColumns( ctx, cols, typs, fs, info.MetaLocation(), cacheVectors2, m, policy, ) + if err2 != nil { + return + } + + err2 = fillCNCreatedCommitTSIfNeeded(cols, cacheVectors2, m, info, createTSLookup) + if err2 != nil { + return + } + + for i, seq := range cols { + if seq != objectio.SEQNUM_COMMITTS || i >= len(cacheVectors2) { + continue + } + if cacheVectors2[i].Length() > 0 && cacheVectors2[i].AllNull() { + logutil.Infof( + "AAAA blockio commit remains null after fill: blk=%s rows=%d", + info.BlockID.String(), + cacheVectors2[i].Length(), + ) + } + } return } diff --git a/pkg/vm/engine/tae/blockio/read_cn_commit_test.go b/pkg/vm/engine/tae/blockio/read_cn_commit_test.go new file mode 100644 index 0000000000000..0afe50f4fb408 --- /dev/null +++ b/pkg/vm/engine/tae/blockio/read_cn_commit_test.go @@ -0,0 +1,78 @@ +// Copyright 2021 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package blockio + +import ( + "testing" + + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" + "github.com/matrixorigin/matrixone/pkg/objectio" + "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" + "github.com/stretchr/testify/require" +) + +func TestFillCNCreatedCommitTSIfNeeded(t *testing.T) { + mp := mpool.MustNewZero() + cacheVectors := containers.NewVectors(1) + defer cacheVectors.Free(mp) + + nullVec := vector.NewConstNull(types.T_TS.ToType(), 4, mp) + cacheVectors[0] = *nullVec + + expected := types.BuildTS(123, 7) + err := fillCNCreatedCommitTSIfNeeded( + []uint16{objectio.SEQNUM_COMMITTS}, + cacheVectors, + mp, + &objectio.BlockInfo{}, + func() (types.TS, bool) { + return expected, true + }, + ) + require.NoError(t, err) + + commitVec := &cacheVectors[0] + require.False(t, commitVec.AllNull()) + require.Equal(t, 4, commitVec.Length()) + require.Equal(t, expected, vector.GetFixedAtNoTypeCheck[types.TS](commitVec, 0)) + require.Equal(t, expected, vector.GetFixedAtNoTypeCheck[types.TS](commitVec, 3)) +} + +func TestFillCNCreatedCommitTSIfNeededKeepExistingValue(t *testing.T) { + mp := mpool.MustNewZero() + cacheVectors := containers.NewVectors(1) + defer cacheVectors.Free(mp) + + existing := types.BuildTS(100, 1) + existingVec, err := vector.NewConstFixed(types.T_TS.ToType(), existing, 3, mp) + require.NoError(t, err) + cacheVectors[0] = *existingVec + + err = fillCNCreatedCommitTSIfNeeded( + []uint16{objectio.SEQNUM_COMMITTS}, + cacheVectors, + mp, + &objectio.BlockInfo{}, + func() (types.TS, bool) { + return types.BuildTS(200, 2), true + }, + ) + require.NoError(t, err) + + commitVec := &cacheVectors[0] + require.Equal(t, existing, vector.GetFixedAtNoTypeCheck[types.TS](commitVec, 0)) +} From 8687aab40622f84b7ac5cd290ea50c720631e04c Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 2 Mar 2026 11:07:46 +0800 Subject: [PATCH 12/23] commit ts ok --- pkg/vm/engine/tae/blockio/read.go | 87 +------------------ .../engine/tae/blockio/read_cn_commit_test.go | 78 ----------------- 2 files changed, 1 insertion(+), 164 deletions(-) delete mode 100644 pkg/vm/engine/tae/blockio/read_cn_commit_test.go diff --git a/pkg/vm/engine/tae/blockio/read.go b/pkg/vm/engine/tae/blockio/read.go index ffeb23ad347a3..2a8def699fc08 100644 --- a/pkg/vm/engine/tae/blockio/read.go +++ b/pkg/vm/engine/tae/blockio/read.go @@ -719,72 +719,6 @@ func buildRowidColumn( return } -type cnCreatedObjectCreateTSProvider interface { - GetObjectCreateTS(bid *objectio.Blockid) (types.TS, bool) -} - -func getCreateTSLookup( - ds engine.DataSource, - info *objectio.BlockInfo, -) func() (types.TS, bool) { - if ds == nil || info == nil || !info.IsCNCreated() { - return nil - } - p, ok := ds.(cnCreatedObjectCreateTSProvider) - if !ok { - return nil - } - return func() (types.TS, bool) { - return p.GetObjectCreateTS(&info.BlockID) - } -} - -func fillCNCreatedCommitTSIfNeeded( - cols []uint16, - cacheVectors containers.Vectors, - m *mpool.MPool, - info *objectio.BlockInfo, - getCreateTS func() (types.TS, bool), -) error { - if getCreateTS == nil { - return nil - } - - createTS, ok := getCreateTS() - if !ok { - logutil.Infof( - "AAAA blockio commit fill skipped: no createTS, blk=%s", - info.BlockID.String(), - ) - return nil - } - - for i, seq := range cols { - if seq != objectio.SEQNUM_COMMITTS || i >= len(cacheVectors) { - continue - } - - vec := &cacheVectors[i] - if vec.Length() == 0 || !vec.AllNull() { - continue - } - - filled, err := vector.NewConstFixed(types.T_TS.ToType(), createTS, vec.Length(), m) - if err != nil { - return err - } - cacheVectors[i] = *filled - logutil.Infof( - "AAAA blockio commit filled from createTS: blk=%s rows=%d createTS=%s", - info.BlockID.String(), - vec.Length(), - createTS.ToString(), - ) - } - - return nil -} - // This func load columns from storage of specified column indexes // No memory copy, the loaded data is directly stored in the cacheVectors // if `phyAddrColumnPos` >= 0, it means one of the columns is the physical address column, @@ -803,7 +737,7 @@ func readBlockData( colTypes []types.Type, phyAddrColumnPos int, info *objectio.BlockInfo, - ds engine.DataSource, + _ engine.DataSource, ts types.TS, policy fileservice.Policy, cacheVectors containers.Vectors, @@ -817,7 +751,6 @@ func readBlockData( cacheVectors.Free(m) idxes, typs := excludePhyAddrColumn(colIndexes, colTypes, phyAddrColumnPos) - createTSLookup := getCreateTSLookup(ds, info) readColumns := func( cols []uint16, @@ -835,24 +768,6 @@ func readBlockData( if err2 != nil { return } - - err2 = fillCNCreatedCommitTSIfNeeded(cols, cacheVectors2, m, info, createTSLookup) - if err2 != nil { - return - } - - for i, seq := range cols { - if seq != objectio.SEQNUM_COMMITTS || i >= len(cacheVectors2) { - continue - } - if cacheVectors2[i].Length() > 0 && cacheVectors2[i].AllNull() { - logutil.Infof( - "AAAA blockio commit remains null after fill: blk=%s rows=%d", - info.BlockID.String(), - cacheVectors2[i].Length(), - ) - } - } return } diff --git a/pkg/vm/engine/tae/blockio/read_cn_commit_test.go b/pkg/vm/engine/tae/blockio/read_cn_commit_test.go deleted file mode 100644 index 0afe50f4fb408..0000000000000 --- a/pkg/vm/engine/tae/blockio/read_cn_commit_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2021 Matrix Origin -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package blockio - -import ( - "testing" - - "github.com/matrixorigin/matrixone/pkg/common/mpool" - "github.com/matrixorigin/matrixone/pkg/container/types" - "github.com/matrixorigin/matrixone/pkg/container/vector" - "github.com/matrixorigin/matrixone/pkg/objectio" - "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" - "github.com/stretchr/testify/require" -) - -func TestFillCNCreatedCommitTSIfNeeded(t *testing.T) { - mp := mpool.MustNewZero() - cacheVectors := containers.NewVectors(1) - defer cacheVectors.Free(mp) - - nullVec := vector.NewConstNull(types.T_TS.ToType(), 4, mp) - cacheVectors[0] = *nullVec - - expected := types.BuildTS(123, 7) - err := fillCNCreatedCommitTSIfNeeded( - []uint16{objectio.SEQNUM_COMMITTS}, - cacheVectors, - mp, - &objectio.BlockInfo{}, - func() (types.TS, bool) { - return expected, true - }, - ) - require.NoError(t, err) - - commitVec := &cacheVectors[0] - require.False(t, commitVec.AllNull()) - require.Equal(t, 4, commitVec.Length()) - require.Equal(t, expected, vector.GetFixedAtNoTypeCheck[types.TS](commitVec, 0)) - require.Equal(t, expected, vector.GetFixedAtNoTypeCheck[types.TS](commitVec, 3)) -} - -func TestFillCNCreatedCommitTSIfNeededKeepExistingValue(t *testing.T) { - mp := mpool.MustNewZero() - cacheVectors := containers.NewVectors(1) - defer cacheVectors.Free(mp) - - existing := types.BuildTS(100, 1) - existingVec, err := vector.NewConstFixed(types.T_TS.ToType(), existing, 3, mp) - require.NoError(t, err) - cacheVectors[0] = *existingVec - - err = fillCNCreatedCommitTSIfNeeded( - []uint16{objectio.SEQNUM_COMMITTS}, - cacheVectors, - mp, - &objectio.BlockInfo{}, - func() (types.TS, bool) { - return types.BuildTS(200, 2), true - }, - ) - require.NoError(t, err) - - commitVec := &cacheVectors[0] - require.Equal(t, existing, vector.GetFixedAtNoTypeCheck[types.TS](commitVec, 0)) -} From 77627b17a882042d3b358d3bb7b1e1606c41a616 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 2 Mar 2026 11:39:42 +0800 Subject: [PATCH 13/23] rebabse main --- pkg/sql/parsers/dialect/mysql/mysql_sql.go | 17658 ++++++++++--------- 1 file changed, 8838 insertions(+), 8820 deletions(-) diff --git a/pkg/sql/parsers/dialect/mysql/mysql_sql.go b/pkg/sql/parsers/dialect/mysql/mysql_sql.go index e25b7bebc2ead..eecc31cf61b85 100644 --- a/pkg/sql/parsers/dialect/mysql/mysql_sql.go +++ b/pkg/sql/parsers/dialect/mysql/mysql_sql.go @@ -356,343 +356,344 @@ const CONFLICT_FAIL = 57679 const CONFLICT_SKIP = 57680 const CONFLICT_ACCEPT = 57681 const OUTPUT = 57682 -const INCREMENT = 57683 -const CYCLE = 57684 -const MINVALUE = 57685 -const PUBLICATION = 57686 -const SUBSCRIPTIONS = 57687 -const PUBLICATIONS = 57688 -const PROPERTIES = 57689 -const PARSER = 57690 -const VISIBLE = 57691 -const INVISIBLE = 57692 -const BTREE = 57693 -const HASH = 57694 -const RTREE = 57695 -const BSI = 57696 -const IVFFLAT = 57697 -const MASTER = 57698 -const HNSW = 57699 -const ZONEMAP = 57700 -const LEADING = 57701 -const BOTH = 57702 -const TRAILING = 57703 -const UNKNOWN = 57704 -const LISTS = 57705 -const OP_TYPE = 57706 -const REINDEX = 57707 -const EF_SEARCH = 57708 -const EF_CONSTRUCTION = 57709 -const M = 57710 -const ASYNC = 57711 -const FORCE_SYNC = 57712 -const AUTO_UPDATE = 57713 -const EXPIRE = 57714 -const ACCOUNT = 57715 -const ACCOUNTS = 57716 -const UNLOCK = 57717 -const DAY = 57718 -const NEVER = 57719 -const PUMP = 57720 -const MYSQL_COMPATIBILITY_MODE = 57721 -const UNIQUE_CHECK_ON_AUTOINCR = 57722 -const MODIFY = 57723 -const CHANGE = 57724 -const SECOND = 57725 -const ASCII = 57726 -const COALESCE = 57727 -const COLLATION = 57728 -const HOUR = 57729 -const MICROSECOND = 57730 -const MINUTE = 57731 -const MONTH = 57732 -const QUARTER = 57733 -const REPEAT = 57734 -const REVERSE = 57735 -const ROW_COUNT = 57736 -const WEEK = 57737 -const REVOKE = 57738 -const FUNCTION = 57739 -const PRIVILEGES = 57740 -const TABLESPACE = 57741 -const EXECUTE = 57742 -const SUPER = 57743 -const GRANT = 57744 -const OPTION = 57745 -const REFERENCES = 57746 -const REPLICATION = 57747 -const SLAVE = 57748 -const CLIENT = 57749 -const USAGE = 57750 -const RELOAD = 57751 -const FILE = 57752 -const FILES = 57753 -const TEMPORARY = 57754 -const ROUTINE = 57755 -const EVENT = 57756 -const SHUTDOWN = 57757 -const NULLX = 57758 -const AUTO_INCREMENT = 57759 -const APPROXNUM = 57760 -const ENGINES = 57761 -const LOW_CARDINALITY = 57762 -const AUTOEXTEND_SIZE = 57763 -const ADMIN_NAME = 57764 -const RANDOM = 57765 -const SUSPEND = 57766 -const ATTRIBUTE = 57767 -const HISTORY = 57768 -const REUSE = 57769 -const CURRENT = 57770 -const OPTIONAL = 57771 -const FAILED_LOGIN_ATTEMPTS = 57772 -const PASSWORD_LOCK_TIME = 57773 -const UNBOUNDED = 57774 -const SECONDARY = 57775 -const RESTRICTED = 57776 -const USER = 57777 -const IDENTIFIED = 57778 -const CIPHER = 57779 -const ISSUER = 57780 -const X509 = 57781 -const SUBJECT = 57782 -const SAN = 57783 -const REQUIRE = 57784 -const SSL = 57785 -const NONE = 57786 -const PASSWORD = 57787 -const SHARED = 57788 -const EXCLUSIVE = 57789 -const MAX_QUERIES_PER_HOUR = 57790 -const MAX_UPDATES_PER_HOUR = 57791 -const MAX_CONNECTIONS_PER_HOUR = 57792 -const MAX_USER_CONNECTIONS = 57793 -const FORMAT = 57794 -const VERBOSE = 57795 -const CONNECTION = 57796 -const TRIGGERS = 57797 -const PROFILES = 57798 -const LOAD = 57799 -const INLINE = 57800 -const INFILE = 57801 -const TERMINATED = 57802 -const OPTIONALLY = 57803 -const ENCLOSED = 57804 -const ESCAPED = 57805 -const STARTING = 57806 -const LINES = 57807 -const ROWS = 57808 -const IMPORT = 57809 -const DISCARD = 57810 -const JSONTYPE = 57811 -const MODUMP = 57812 -const OVER = 57813 -const PRECEDING = 57814 -const FOLLOWING = 57815 -const GROUPS = 57816 -const DATABASES = 57817 -const TABLES = 57818 -const SEQUENCES = 57819 -const EXTENDED = 57820 -const FULL = 57821 -const PROCESSLIST = 57822 -const FIELDS = 57823 -const COLUMNS = 57824 -const OPEN = 57825 -const ERRORS = 57826 -const WARNINGS = 57827 -const INDEXES = 57828 -const SCHEMAS = 57829 -const NODE = 57830 -const LOCKS = 57831 -const ROLES = 57832 -const TABLE_NUMBER = 57833 -const COLUMN_NUMBER = 57834 -const TABLE_VALUES = 57835 -const TABLE_SIZE = 57836 -const NAMES = 57837 -const GLOBAL = 57838 -const PERSIST = 57839 -const SESSION = 57840 -const ISOLATION = 57841 -const LEVEL = 57842 -const READ = 57843 -const WRITE = 57844 -const ONLY = 57845 -const REPEATABLE = 57846 -const COMMITTED = 57847 -const UNCOMMITTED = 57848 -const SERIALIZABLE = 57849 -const LOCAL = 57850 -const EVENTS = 57851 -const PLUGINS = 57852 -const CURRENT_TIMESTAMP = 57853 -const DATABASE = 57854 -const CURRENT_TIME = 57855 -const LOCALTIME = 57856 -const LOCALTIMESTAMP = 57857 -const UTC_DATE = 57858 -const UTC_TIME = 57859 -const UTC_TIMESTAMP = 57860 -const REPLACE = 57861 -const CONVERT = 57862 -const SEPARATOR = 57863 -const TIMESTAMPDIFF = 57864 -const TIMESTAMPADD = 57865 -const CURRENT_DATE = 57866 -const CURRENT_USER = 57867 -const CURRENT_ROLE = 57868 -const SECOND_MICROSECOND = 57869 -const MINUTE_MICROSECOND = 57870 -const MINUTE_SECOND = 57871 -const HOUR_MICROSECOND = 57872 -const HOUR_SECOND = 57873 -const HOUR_MINUTE = 57874 -const DAY_MICROSECOND = 57875 -const DAY_SECOND = 57876 -const DAY_MINUTE = 57877 -const DAY_HOUR = 57878 -const YEAR_MONTH = 57879 -const SQL_TSI_HOUR = 57880 -const SQL_TSI_DAY = 57881 -const SQL_TSI_WEEK = 57882 -const SQL_TSI_MONTH = 57883 -const SQL_TSI_QUARTER = 57884 -const SQL_TSI_YEAR = 57885 -const SQL_TSI_SECOND = 57886 -const SQL_TSI_MINUTE = 57887 -const RECURSIVE = 57888 -const CONFIG = 57889 -const DRAINER = 57890 -const SOURCE = 57891 -const STREAM = 57892 -const HEADERS = 57893 -const CONNECTOR = 57894 -const CONNECTORS = 57895 -const DAEMON = 57896 -const PAUSE = 57897 -const CANCEL = 57898 -const TASK = 57899 -const RESUME = 57900 -const MATCH = 57901 -const AGAINST = 57902 -const BOOLEAN = 57903 -const LANGUAGE = 57904 -const QUERY = 57905 -const EXPANSION = 57906 -const WITHOUT = 57907 -const VALIDATION = 57908 -const UPGRADE = 57909 -const RETRY = 57910 -const ADDDATE = 57911 -const BIT_AND = 57912 -const BIT_OR = 57913 -const BIT_XOR = 57914 -const CAST = 57915 -const COUNT = 57916 -const APPROX_COUNT = 57917 -const APPROX_COUNT_DISTINCT = 57918 -const SERIAL_EXTRACT = 57919 -const APPROX_PERCENTILE = 57920 -const CURDATE = 57921 -const CURTIME = 57922 -const DATE_ADD = 57923 -const DATE_SUB = 57924 -const EXTRACT = 57925 -const GROUP_CONCAT = 57926 -const MAX = 57927 -const MID = 57928 -const MIN = 57929 -const NOW = 57930 -const POSITION = 57931 -const SESSION_USER = 57932 -const STD = 57933 -const STDDEV = 57934 -const MEDIAN = 57935 -const CLUSTER_CENTERS = 57936 -const KMEANS = 57937 -const STDDEV_POP = 57938 -const STDDEV_SAMP = 57939 -const SUBDATE = 57940 -const SUBSTR = 57941 -const SUBSTRING = 57942 -const SUM = 57943 -const SYSDATE = 57944 -const SYSTEM_USER = 57945 -const TRANSLATE = 57946 -const TRIM = 57947 -const VARIANCE = 57948 -const VAR_POP = 57949 -const VAR_SAMP = 57950 -const AVG = 57951 -const RANK = 57952 -const ROW_NUMBER = 57953 -const DENSE_RANK = 57954 -const CUME_DIST = 57955 -const BIT_CAST = 57956 -const LAG = 57957 -const LEAD = 57958 -const FIRST_VALUE = 57959 -const LAST_VALUE = 57960 -const NTH_VALUE = 57961 -const NTILE = 57962 -const PERCENT_RANK = 57963 -const BITMAP_BIT_POSITION = 57964 -const BITMAP_BUCKET_NUMBER = 57965 -const BITMAP_COUNT = 57966 -const BITMAP_CONSTRUCT_AGG = 57967 -const BITMAP_OR_AGG = 57968 -const GET_FORMAT = 57969 -const NEXTVAL = 57970 -const SETVAL = 57971 -const CURRVAL = 57972 -const LASTVAL = 57973 -const ROW = 57974 -const OUTFILE = 57975 -const HEADER = 57976 -const MAX_FILE_SIZE = 57977 -const FORCE_QUOTE = 57978 -const PARALLEL = 57979 -const STRICT = 57980 -const SPLITSIZE = 57981 -const UNUSED = 57982 -const BINDINGS = 57983 -const DO = 57984 -const DECLARE = 57985 -const LOOP = 57986 -const WHILE = 57987 -const LEAVE = 57988 -const ITERATE = 57989 -const UNTIL = 57990 -const CALL = 57991 -const PREV = 57992 -const SLIDING = 57993 -const FILL = 57994 -const SPBEGIN = 57995 -const BACKEND = 57996 -const SERVERS = 57997 -const HANDLER = 57998 -const PERCENT = 57999 -const SAMPLE = 58000 -const MO_TS = 58001 -const PITR = 58002 -const RECOVERY_WINDOW = 58003 -const INTERNAL = 58004 -const CDC = 58005 -const GROUPING = 58006 -const SETS = 58007 -const CUBE = 58008 -const ROLLUP = 58009 -const LOGSERVICE = 58010 -const REPLICAS = 58011 -const STORES = 58012 -const SETTINGS = 58013 -const KILL = 58014 -const BACKUP = 58015 -const FILESYSTEM = 58016 -const PARALLELISM = 58017 -const RESTORE = 58018 -const QUERY_RESULT = 58019 +const SUMMARY = 57683 +const INCREMENT = 57684 +const CYCLE = 57685 +const MINVALUE = 57686 +const PUBLICATION = 57687 +const SUBSCRIPTIONS = 57688 +const PUBLICATIONS = 57689 +const PROPERTIES = 57690 +const PARSER = 57691 +const VISIBLE = 57692 +const INVISIBLE = 57693 +const BTREE = 57694 +const HASH = 57695 +const RTREE = 57696 +const BSI = 57697 +const IVFFLAT = 57698 +const MASTER = 57699 +const HNSW = 57700 +const ZONEMAP = 57701 +const LEADING = 57702 +const BOTH = 57703 +const TRAILING = 57704 +const UNKNOWN = 57705 +const LISTS = 57706 +const OP_TYPE = 57707 +const REINDEX = 57708 +const EF_SEARCH = 57709 +const EF_CONSTRUCTION = 57710 +const M = 57711 +const ASYNC = 57712 +const FORCE_SYNC = 57713 +const AUTO_UPDATE = 57714 +const EXPIRE = 57715 +const ACCOUNT = 57716 +const ACCOUNTS = 57717 +const UNLOCK = 57718 +const DAY = 57719 +const NEVER = 57720 +const PUMP = 57721 +const MYSQL_COMPATIBILITY_MODE = 57722 +const UNIQUE_CHECK_ON_AUTOINCR = 57723 +const MODIFY = 57724 +const CHANGE = 57725 +const SECOND = 57726 +const ASCII = 57727 +const COALESCE = 57728 +const COLLATION = 57729 +const HOUR = 57730 +const MICROSECOND = 57731 +const MINUTE = 57732 +const MONTH = 57733 +const QUARTER = 57734 +const REPEAT = 57735 +const REVERSE = 57736 +const ROW_COUNT = 57737 +const WEEK = 57738 +const REVOKE = 57739 +const FUNCTION = 57740 +const PRIVILEGES = 57741 +const TABLESPACE = 57742 +const EXECUTE = 57743 +const SUPER = 57744 +const GRANT = 57745 +const OPTION = 57746 +const REFERENCES = 57747 +const REPLICATION = 57748 +const SLAVE = 57749 +const CLIENT = 57750 +const USAGE = 57751 +const RELOAD = 57752 +const FILE = 57753 +const FILES = 57754 +const TEMPORARY = 57755 +const ROUTINE = 57756 +const EVENT = 57757 +const SHUTDOWN = 57758 +const NULLX = 57759 +const AUTO_INCREMENT = 57760 +const APPROXNUM = 57761 +const ENGINES = 57762 +const LOW_CARDINALITY = 57763 +const AUTOEXTEND_SIZE = 57764 +const ADMIN_NAME = 57765 +const RANDOM = 57766 +const SUSPEND = 57767 +const ATTRIBUTE = 57768 +const HISTORY = 57769 +const REUSE = 57770 +const CURRENT = 57771 +const OPTIONAL = 57772 +const FAILED_LOGIN_ATTEMPTS = 57773 +const PASSWORD_LOCK_TIME = 57774 +const UNBOUNDED = 57775 +const SECONDARY = 57776 +const RESTRICTED = 57777 +const USER = 57778 +const IDENTIFIED = 57779 +const CIPHER = 57780 +const ISSUER = 57781 +const X509 = 57782 +const SUBJECT = 57783 +const SAN = 57784 +const REQUIRE = 57785 +const SSL = 57786 +const NONE = 57787 +const PASSWORD = 57788 +const SHARED = 57789 +const EXCLUSIVE = 57790 +const MAX_QUERIES_PER_HOUR = 57791 +const MAX_UPDATES_PER_HOUR = 57792 +const MAX_CONNECTIONS_PER_HOUR = 57793 +const MAX_USER_CONNECTIONS = 57794 +const FORMAT = 57795 +const VERBOSE = 57796 +const CONNECTION = 57797 +const TRIGGERS = 57798 +const PROFILES = 57799 +const LOAD = 57800 +const INLINE = 57801 +const INFILE = 57802 +const TERMINATED = 57803 +const OPTIONALLY = 57804 +const ENCLOSED = 57805 +const ESCAPED = 57806 +const STARTING = 57807 +const LINES = 57808 +const ROWS = 57809 +const IMPORT = 57810 +const DISCARD = 57811 +const JSONTYPE = 57812 +const MODUMP = 57813 +const OVER = 57814 +const PRECEDING = 57815 +const FOLLOWING = 57816 +const GROUPS = 57817 +const DATABASES = 57818 +const TABLES = 57819 +const SEQUENCES = 57820 +const EXTENDED = 57821 +const FULL = 57822 +const PROCESSLIST = 57823 +const FIELDS = 57824 +const COLUMNS = 57825 +const OPEN = 57826 +const ERRORS = 57827 +const WARNINGS = 57828 +const INDEXES = 57829 +const SCHEMAS = 57830 +const NODE = 57831 +const LOCKS = 57832 +const ROLES = 57833 +const TABLE_NUMBER = 57834 +const COLUMN_NUMBER = 57835 +const TABLE_VALUES = 57836 +const TABLE_SIZE = 57837 +const NAMES = 57838 +const GLOBAL = 57839 +const PERSIST = 57840 +const SESSION = 57841 +const ISOLATION = 57842 +const LEVEL = 57843 +const READ = 57844 +const WRITE = 57845 +const ONLY = 57846 +const REPEATABLE = 57847 +const COMMITTED = 57848 +const UNCOMMITTED = 57849 +const SERIALIZABLE = 57850 +const LOCAL = 57851 +const EVENTS = 57852 +const PLUGINS = 57853 +const CURRENT_TIMESTAMP = 57854 +const DATABASE = 57855 +const CURRENT_TIME = 57856 +const LOCALTIME = 57857 +const LOCALTIMESTAMP = 57858 +const UTC_DATE = 57859 +const UTC_TIME = 57860 +const UTC_TIMESTAMP = 57861 +const REPLACE = 57862 +const CONVERT = 57863 +const SEPARATOR = 57864 +const TIMESTAMPDIFF = 57865 +const TIMESTAMPADD = 57866 +const CURRENT_DATE = 57867 +const CURRENT_USER = 57868 +const CURRENT_ROLE = 57869 +const SECOND_MICROSECOND = 57870 +const MINUTE_MICROSECOND = 57871 +const MINUTE_SECOND = 57872 +const HOUR_MICROSECOND = 57873 +const HOUR_SECOND = 57874 +const HOUR_MINUTE = 57875 +const DAY_MICROSECOND = 57876 +const DAY_SECOND = 57877 +const DAY_MINUTE = 57878 +const DAY_HOUR = 57879 +const YEAR_MONTH = 57880 +const SQL_TSI_HOUR = 57881 +const SQL_TSI_DAY = 57882 +const SQL_TSI_WEEK = 57883 +const SQL_TSI_MONTH = 57884 +const SQL_TSI_QUARTER = 57885 +const SQL_TSI_YEAR = 57886 +const SQL_TSI_SECOND = 57887 +const SQL_TSI_MINUTE = 57888 +const RECURSIVE = 57889 +const CONFIG = 57890 +const DRAINER = 57891 +const SOURCE = 57892 +const STREAM = 57893 +const HEADERS = 57894 +const CONNECTOR = 57895 +const CONNECTORS = 57896 +const DAEMON = 57897 +const PAUSE = 57898 +const CANCEL = 57899 +const TASK = 57900 +const RESUME = 57901 +const MATCH = 57902 +const AGAINST = 57903 +const BOOLEAN = 57904 +const LANGUAGE = 57905 +const QUERY = 57906 +const EXPANSION = 57907 +const WITHOUT = 57908 +const VALIDATION = 57909 +const UPGRADE = 57910 +const RETRY = 57911 +const ADDDATE = 57912 +const BIT_AND = 57913 +const BIT_OR = 57914 +const BIT_XOR = 57915 +const CAST = 57916 +const COUNT = 57917 +const APPROX_COUNT = 57918 +const APPROX_COUNT_DISTINCT = 57919 +const SERIAL_EXTRACT = 57920 +const APPROX_PERCENTILE = 57921 +const CURDATE = 57922 +const CURTIME = 57923 +const DATE_ADD = 57924 +const DATE_SUB = 57925 +const EXTRACT = 57926 +const GROUP_CONCAT = 57927 +const MAX = 57928 +const MID = 57929 +const MIN = 57930 +const NOW = 57931 +const POSITION = 57932 +const SESSION_USER = 57933 +const STD = 57934 +const STDDEV = 57935 +const MEDIAN = 57936 +const CLUSTER_CENTERS = 57937 +const KMEANS = 57938 +const STDDEV_POP = 57939 +const STDDEV_SAMP = 57940 +const SUBDATE = 57941 +const SUBSTR = 57942 +const SUBSTRING = 57943 +const SUM = 57944 +const SYSDATE = 57945 +const SYSTEM_USER = 57946 +const TRANSLATE = 57947 +const TRIM = 57948 +const VARIANCE = 57949 +const VAR_POP = 57950 +const VAR_SAMP = 57951 +const AVG = 57952 +const RANK = 57953 +const ROW_NUMBER = 57954 +const DENSE_RANK = 57955 +const CUME_DIST = 57956 +const BIT_CAST = 57957 +const LAG = 57958 +const LEAD = 57959 +const FIRST_VALUE = 57960 +const LAST_VALUE = 57961 +const NTH_VALUE = 57962 +const NTILE = 57963 +const PERCENT_RANK = 57964 +const BITMAP_BIT_POSITION = 57965 +const BITMAP_BUCKET_NUMBER = 57966 +const BITMAP_COUNT = 57967 +const BITMAP_CONSTRUCT_AGG = 57968 +const BITMAP_OR_AGG = 57969 +const GET_FORMAT = 57970 +const NEXTVAL = 57971 +const SETVAL = 57972 +const CURRVAL = 57973 +const LASTVAL = 57974 +const ROW = 57975 +const OUTFILE = 57976 +const HEADER = 57977 +const MAX_FILE_SIZE = 57978 +const FORCE_QUOTE = 57979 +const PARALLEL = 57980 +const STRICT = 57981 +const SPLITSIZE = 57982 +const UNUSED = 57983 +const BINDINGS = 57984 +const DO = 57985 +const DECLARE = 57986 +const LOOP = 57987 +const WHILE = 57988 +const LEAVE = 57989 +const ITERATE = 57990 +const UNTIL = 57991 +const CALL = 57992 +const PREV = 57993 +const SLIDING = 57994 +const FILL = 57995 +const SPBEGIN = 57996 +const BACKEND = 57997 +const SERVERS = 57998 +const HANDLER = 57999 +const PERCENT = 58000 +const SAMPLE = 58001 +const MO_TS = 58002 +const PITR = 58003 +const RECOVERY_WINDOW = 58004 +const INTERNAL = 58005 +const CDC = 58006 +const GROUPING = 58007 +const SETS = 58008 +const CUBE = 58009 +const ROLLUP = 58010 +const LOGSERVICE = 58011 +const REPLICAS = 58012 +const STORES = 58013 +const SETTINGS = 58014 +const KILL = 58015 +const BACKUP = 58016 +const FILESYSTEM = 58017 +const PARALLELISM = 58018 +const RESTORE = 58019 +const QUERY_RESULT = 58020 var yyToknames = [...]string{ "$end", @@ -1052,6 +1053,7 @@ var yyToknames = [...]string{ "CONFLICT_SKIP", "CONFLICT_ACCEPT", "OUTPUT", + "SUMMARY", "INCREMENT", "CYCLE", "MINVALUE", @@ -1402,7 +1404,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line mysql_sql.y:13577 +//line mysql_sql.y:13584 //line yacctab:1 var yyExca = [...]int{ @@ -1414,7 +1416,7 @@ var yyExca = [...]int{ 24, 835, -2, 828, -1, 172, - 259, 1305, + 259, 1306, 261, 1173, -2, 1233, -1, 200, @@ -1422,269 +1424,261 @@ var yyExca = [...]int{ 261, 652, 288, 659, 289, 659, - 503, 652, + 504, 652, -2, 687, -1, 240, - 698, 2111, + 699, 2113, -2, 551, - -1, 565, - 698, 2236, + -1, 566, + 699, 2238, -2, 423, - -1, 623, - 698, 2295, - -2, 421, -1, 624, - 698, 2296, - -2, 422, + 699, 2297, + -2, 421, -1, 625, - 698, 2297, + 699, 2298, + -2, 422, + -1, 626, + 699, 2299, -2, 424, - -1, 776, + -1, 777, 340, 190, - 475, 190, 476, 190, - -2, 2007, - -1, 843, - 88, 1785, - -2, 2172, + 477, 190, + -2, 2008, -1, 844, - 88, 1804, - -2, 2142, - -1, 848, + 88, 1786, + -2, 2174, + -1, 845, 88, 1805, - -2, 2171, - -1, 892, - 88, 1706, - -2, 2380, + -2, 2144, + -1, 849, + 88, 1806, + -2, 2173, -1, 893, 88, 1707, - -2, 2379, + -2, 2382, -1, 894, 88, 1708, - -2, 2369, + -2, 2381, -1, 895, - 88, 2341, - -2, 2362, + 88, 1709, + -2, 2371, -1, 896, - 88, 2342, - -2, 2363, - -1, 897, 88, 2343, - -2, 2371, - -1, 898, + -2, 2364, + -1, 897, 88, 2344, - -2, 2351, - -1, 899, + -2, 2365, + -1, 898, 88, 2345, - -2, 2360, - -1, 900, + -2, 2373, + -1, 899, 88, 2346, - -2, 2372, - -1, 901, + -2, 2353, + -1, 900, 88, 2347, - -2, 2373, - -1, 902, + -2, 2362, + -1, 901, 88, 2348, - -2, 2378, - -1, 903, + -2, 2374, + -1, 902, 88, 2349, - -2, 2383, - -1, 904, + -2, 2375, + -1, 903, 88, 2350, - -2, 2384, + -2, 2380, + -1, 904, + 88, 2351, + -2, 2385, -1, 905, - 88, 1781, - -2, 2210, + 88, 2352, + -2, 2386, -1, 906, 88, 1782, - -2, 1987, + -2, 2212, -1, 907, 88, 1783, - -2, 2219, + -2, 1988, -1, 908, 88, 1784, - -2, 2000, - -1, 910, - 88, 1787, - -2, 2009, - -1, 912, - 88, 1789, - -2, 2244, - -1, 914, - 88, 1792, - -2, 2030, - -1, 916, - 88, 1794, - -2, 2256, + -2, 2221, + -1, 909, + 88, 1785, + -2, 2001, + -1, 911, + 88, 1788, + -2, 2010, + -1, 913, + 88, 1790, + -2, 2246, + -1, 915, + 88, 1793, + -2, 2031, -1, 917, 88, 1795, - -2, 2255, + -2, 2258, -1, 918, 88, 1796, - -2, 2077, + -2, 2257, -1, 919, 88, 1797, - -2, 2167, - -1, 922, - 88, 1800, - -2, 2267, - -1, 924, - 88, 1802, - -2, 2270, + -2, 2078, + -1, 920, + 88, 1798, + -2, 2169, + -1, 923, + 88, 1801, + -2, 2269, -1, 925, 88, 1803, -2, 2272, -1, 926, - 88, 1806, - -2, 2279, + 88, 1804, + -2, 2274, -1, 927, 88, 1807, - -2, 2151, + -2, 2281, -1, 928, 88, 1808, - -2, 2197, + -2, 2153, -1, 929, 88, 1809, - -2, 2161, + -2, 2199, -1, 930, 88, 1810, - -2, 2187, - -1, 941, - 88, 1684, - -2, 2374, + -2, 2163, + -1, 931, + 88, 1811, + -2, 2189, -1, 942, 88, 1685, - -2, 2375, + -2, 2376, -1, 943, 88, 1686, - -2, 2376, - -1, 1051, - 498, 687, + -2, 2377, + -1, 944, + 88, 1687, + -2, 2378, + -1, 1052, 499, 687, + 500, 687, -2, 653, - -1, 1103, - 130, 1987, - 141, 1987, - 173, 1987, - -2, 1958, - -1, 1216, + -1, 1104, + 130, 1988, + 141, 1988, + 173, 1988, + -2, 1959, + -1, 1217, 24, 864, -2, 807, - -1, 1337, + -1, 1338, 11, 835, 24, 835, - -2, 1546, - -1, 1431, + -2, 1547, + -1, 1432, 24, 864, -2, 807, - -1, 1799, - 88, 1857, - -2, 2169, -1, 1800, 88, 1858, - -2, 2170, - -1, 2467, + -2, 2171, + -1, 1801, + 88, 1859, + -2, 2172, + -1, 2468, 89, 1037, -2, 1043, - -1, 2483, + -1, 2484, 113, 1225, 160, 1225, 207, 1225, 210, 1225, 301, 1225, -2, 1218, - -1, 2656, + -1, 2657, 11, 835, 24, 835, -2, 978, - -1, 2690, - 89, 1944, - 174, 1944, - -2, 2153, -1, 2691, - 89, 1944, - 174, 1944, - -2, 2152, + 89, 1945, + 174, 1945, + -2, 2155, -1, 2692, - 89, 1920, - 174, 1920, - -2, 2139, + 89, 1945, + 174, 1945, + -2, 2154, -1, 2693, 89, 1921, 174, 1921, - -2, 2144, + -2, 2141, -1, 2694, 89, 1922, 174, 1922, - -2, 2065, + -2, 2146, -1, 2695, 89, 1923, 174, 1923, - -2, 2058, + -2, 2066, -1, 2696, 89, 1924, 174, 1924, - -2, 1975, + -2, 2059, -1, 2697, 89, 1925, 174, 1925, - -2, 2141, + -2, 1976, -1, 2698, 89, 1926, 174, 1926, - -2, 2063, + -2, 2143, -1, 2699, 89, 1927, 174, 1927, - -2, 2057, + -2, 2064, -1, 2700, 89, 1928, 174, 1928, - -2, 2045, + -2, 2058, -1, 2701, - 89, 1944, - 174, 1944, + 89, 1929, + 174, 1929, -2, 2046, -1, 2702, - 89, 1944, - 174, 1944, + 89, 1945, + 174, 1945, -2, 2047, - -1, 2704, - 89, 1933, - 174, 1933, - -2, 2187, + -1, 2703, + 89, 1945, + 174, 1945, + -2, 2048, -1, 2705, - 89, 1910, - 174, 1910, - -2, 2172, + 89, 1934, + 174, 1934, + -2, 2189, -1, 2706, - 89, 1942, - 174, 1942, - -2, 2142, + 89, 1911, + 174, 1911, + -2, 2174, -1, 2707, - 89, 1942, - 174, 1942, - -2, 2171, + 89, 1943, + 174, 1943, + -2, 2144, -1, 2708, - 89, 1942, - 174, 1942, - -2, 2010, + 89, 1943, + 174, 1943, + -2, 2173, -1, 2709, - 89, 1940, - 174, 1940, - -2, 2161, + 89, 1943, + 174, 1943, + -2, 2011, -1, 2710, - 89, 1937, - 174, 1937, - -2, 2035, + 89, 1941, + 174, 1941, + -2, 2163, -1, 2711, - 88, 1891, - 89, 1891, - 163, 1891, - 164, 1891, - 166, 1891, - 174, 1891, - -2, 1974, + 89, 1938, + 174, 1938, + -2, 2036, -1, 2712, 88, 1892, 89, 1892, @@ -1692,7 +1686,7 @@ var yyExca = [...]int{ 164, 1892, 166, 1892, 174, 1892, - -2, 1976, + -2, 1975, -1, 2713, 88, 1893, 89, 1893, @@ -1700,39 +1694,39 @@ var yyExca = [...]int{ 164, 1893, 166, 1893, 174, 1893, - -2, 2215, + -2, 1977, -1, 2714, - 88, 1895, - 89, 1895, - 163, 1895, - 164, 1895, - 166, 1895, - 174, 1895, - -2, 2143, + 88, 1894, + 89, 1894, + 163, 1894, + 164, 1894, + 166, 1894, + 174, 1894, + -2, 2217, -1, 2715, - 88, 1897, - 89, 1897, - 163, 1897, - 164, 1897, - 166, 1897, - 174, 1897, - -2, 2121, + 88, 1896, + 89, 1896, + 163, 1896, + 164, 1896, + 166, 1896, + 174, 1896, + -2, 2145, -1, 2716, - 88, 1899, - 89, 1899, - 163, 1899, - 164, 1899, - 166, 1899, - 174, 1899, - -2, 2064, + 88, 1898, + 89, 1898, + 163, 1898, + 164, 1898, + 166, 1898, + 174, 1898, + -2, 2123, -1, 2717, - 88, 1901, - 89, 1901, - 163, 1901, - 164, 1901, - 166, 1901, - 174, 1901, - -2, 2041, + 88, 1900, + 89, 1900, + 163, 1900, + 164, 1900, + 166, 1900, + 174, 1900, + -2, 2065, -1, 2718, 88, 1902, 89, 1902, @@ -1742,6004 +1736,6017 @@ var yyExca = [...]int{ 174, 1902, -2, 2042, -1, 2719, - 88, 1904, - 89, 1904, - 163, 1904, - 164, 1904, - 166, 1904, - 174, 1904, - -2, 1973, + 88, 1903, + 89, 1903, + 163, 1903, + 164, 1903, + 166, 1903, + 174, 1903, + -2, 2043, -1, 2720, - 89, 1947, - 163, 1947, - 164, 1947, - 166, 1947, - 174, 1947, - -2, 2015, + 88, 1905, + 89, 1905, + 163, 1905, + 164, 1905, + 166, 1905, + 174, 1905, + -2, 1974, -1, 2721, - 89, 1947, - 163, 1947, - 164, 1947, - 166, 1947, - 174, 1947, - -2, 2031, + 89, 1948, + 163, 1948, + 164, 1948, + 166, 1948, + 174, 1948, + -2, 2016, -1, 2722, - 89, 1950, - 163, 1950, - 164, 1950, - 166, 1950, - 174, 1950, - -2, 2011, + 89, 1948, + 163, 1948, + 164, 1948, + 166, 1948, + 174, 1948, + -2, 2032, -1, 2723, - 89, 1950, - 163, 1950, - 164, 1950, - 166, 1950, - 174, 1950, - -2, 2080, + 89, 1951, + 163, 1951, + 164, 1951, + 166, 1951, + 174, 1951, + -2, 2012, -1, 2724, - 89, 1947, - 163, 1947, - 164, 1947, - 166, 1947, - 174, 1947, - -2, 2103, - -1, 2964, + 89, 1951, + 163, 1951, + 164, 1951, + 166, 1951, + 174, 1951, + -2, 2081, + -1, 2725, + 89, 1948, + 163, 1948, + 164, 1948, + 166, 1948, + 174, 1948, + -2, 2105, + -1, 2965, 113, 1225, 160, 1225, 207, 1225, 210, 1225, 301, 1225, -2, 1219, - -1, 2989, + -1, 2990, 86, 749, 174, 749, - -2, 1420, - -1, 3431, + -2, 1421, + -1, 3432, 210, 1225, - 325, 1509, - -2, 1481, - -1, 3640, + 325, 1510, + -2, 1482, + -1, 3642, 113, 1225, 160, 1225, 207, 1225, 210, 1225, - -2, 1361, - -1, 3643, + -2, 1362, + -1, 3645, 113, 1225, 160, 1225, 207, 1225, 210, 1225, - -2, 1361, - -1, 3658, + -2, 1362, + -1, 3660, 86, 749, 174, 749, - -2, 1420, - -1, 3679, + -2, 1421, + -1, 3681, 210, 1225, - 325, 1509, - -2, 1482, - -1, 3848, + 325, 1510, + -2, 1483, + -1, 3850, 113, 1225, 160, 1225, 207, 1225, 210, 1225, - -2, 1362, - -1, 3875, - 89, 1323, - 174, 1323, + -2, 1363, + -1, 3877, + 89, 1324, + 174, 1324, -2, 1225, - -1, 4042, - 89, 1323, - 174, 1323, + -1, 4044, + 89, 1324, + 174, 1324, -2, 1225, - -1, 4226, - 89, 1327, - 174, 1327, - -2, 1225, - -1, 4274, + -1, 4228, 89, 1328, 174, 1328, -2, 1225, + -1, 4276, + 89, 1329, + 174, 1329, + -2, 1225, } const yyPrivate = 57344 -const yyLast = 58558 +const yyLast = 58620 var yyAct = [...]int{ - 810, 786, 4321, 812, 4296, 3018, 229, 4313, 1704, 4230, - 3766, 1779, 3664, 4236, 2099, 4237, 3452, 4229, 4042, 2211, - 3417, 4146, 795, 4101, 4192, 3954, 3530, 3903, 3693, 4020, - 3722, 3012, 3987, 788, 3531, 3761, 1616, 4041, 3836, 4092, - 1373, 4124, 2921, 3528, 1775, 840, 1547, 1217, 670, 4011, - 1845, 3015, 38, 1102, 3771, 3621, 1553, 4102, 4104, 2043, - 3626, 2541, 1832, 3199, 3426, 689, 3680, 2992, 1782, 700, - 3855, 3131, 1705, 3850, 700, 713, 722, 3845, 3383, 722, - 3368, 3344, 3818, 2758, 3132, 2213, 3644, 3371, 3613, 3130, - 3107, 2195, 3041, 784, 3446, 3435, 2650, 1222, 3586, 3428, - 3646, 2236, 3127, 2926, 3580, 1850, 3513, 2686, 3160, 2160, - 1829, 1828, 2544, 3492, 214, 2305, 3118, 2198, 734, 2952, - 2851, 3349, 3351, 3345, 2765, 739, 3434, 719, 1477, 3393, - 1609, 730, 2505, 2435, 3342, 2339, 3347, 3346, 3308, 2059, - 2273, 2434, 2965, 778, 2191, 145, 37, 2282, 2740, 1219, - 2281, 783, 2241, 1957, 1697, 1693, 2274, 1689, 980, 2300, - 2651, 2271, 1847, 2634, 2164, 2301, 2941, 2629, 1694, 1510, - 1709, 2936, 2542, 2089, 700, 1017, 3043, 3023, 67, 2979, - 2504, 1846, 2483, 1556, 225, 8, 224, 7, 6, 2014, - 2684, 2161, 1682, 1773, 1163, 2302, 787, 2268, 1656, 688, - 1625, 2335, 1594, 1588, 2537, 670, 2035, 1536, 2474, 2058, - 2280, 777, 2437, 2277, 796, 1839, 779, 2850, 1815, 2477, - 1764, 1240, 2257, 2010, 24, 1663, 727, 1772, 1095, 229, - 1593, 229, 2658, 1154, 1155, 2013, 1016, 704, 2630, 1532, - 700, 1590, 1778, 1518, 15, 736, 1647, 1548, 945, 25, - 1134, 215, 1458, 1014, 1060, 1851, 737, 996, 26, 17, - 697, 10, 1429, 721, 1453, 28, 1002, 207, 1046, 733, - 2309, 1557, 211, 4111, 4008, 2896, 1096, 1374, 2896, 2896, - 707, 2660, 1302, 1303, 1304, 1301, 1151, 16, 1302, 1303, - 1304, 1301, 1302, 1303, 1304, 1301, 3661, 14, 3544, 3405, - 3318, 3317, 3222, 3221, 2319, 1223, 1980, 1454, 34, 947, - 1010, 3807, 1011, 3629, 948, 779, 1224, 1129, 3523, 717, - 2803, 1455, 2743, 2746, 669, 2744, 1970, 1670, 2741, 1147, - 1666, 1146, 213, 690, 2433, 695, 1592, 1448, 4079, 1081, - 718, 968, 725, 1150, 1414, 1152, 1515, 1516, 1517, 966, - 2212, 991, 1147, 3315, 1108, 1110, 2447, 1147, 2440, 1977, - 1457, 3303, 714, 3300, 1723, 1005, 1223, 1001, 4308, 3301, - 1570, 1964, 716, 3298, 1444, 3759, 3195, 2888, 2886, 3193, - 1668, 2246, 3537, 715, 4087, 3961, 3955, 1111, 174, 212, - 173, 203, 175, 3762, 3529, 2267, 1368, 4106, 8, 2276, - 7, 1130, 1145, 946, 2763, 3272, 2263, 2582, 204, 1302, - 1303, 1304, 1301, 3591, 4327, 195, 4100, 957, 4305, 205, - 3969, 2890, 1302, 1303, 1304, 1301, 2186, 3589, 768, 4098, - 3995, 770, 3967, 3604, 1012, 983, 769, 2830, 144, 2454, - 4157, 1885, 1459, 1633, 1463, 1462, 1461, 968, 966, 1112, - 967, 732, 3270, 130, 2317, 1502, 1485, 3125, 965, 1871, - 2478, 3997, 208, 2678, 936, 785, 935, 937, 938, 1299, - 939, 940, 1988, 1986, 2679, 1124, 1119, 1114, 1118, 1122, - 1483, 3167, 768, 2665, 1566, 770, 2664, 1567, 2759, 2666, - 769, 3168, 3169, 174, 212, 173, 203, 175, 1075, 1073, - 1595, 1074, 1597, 1127, 2208, 2175, 2176, 1117, 2920, 1007, - 1721, 1000, 1992, 1993, 2052, 2174, 1469, 1106, 2938, 2916, - 1004, 1003, 1107, 1554, 1555, 964, 958, 1552, 2939, 1077, - 1720, 1551, 1554, 1555, 4240, 4241, 1544, 1069, 2073, 1292, - 3421, 992, 1781, 1297, 1105, 3788, 1104, 4109, 4206, 4108, - 4205, 153, 154, 4109, 155, 156, 3419, 4108, 1125, 157, - 3302, 999, 158, 4107, 3299, 4107, 4204, 208, 2412, 4265, - 3532, 891, 4090, 1745, 4194, 4213, 3200, 2937, 1128, 1279, - 1009, 4197, 1280, 2918, 4194, 998, 1569, 1785, 3958, 997, - 4300, 4301, 3532, 2784, 2913, 985, 4093, 4094, 4095, 4096, - 1082, 1229, 174, 212, 173, 203, 175, 1115, 1484, 3205, - 1282, 2321, 990, 174, 212, 173, 203, 175, 174, 212, - 173, 203, 175, 172, 201, 210, 202, 72, 128, 1078, - 3062, 1126, 1669, 1667, 174, 212, 173, 203, 175, 2917, - 2182, 988, 2891, 2192, 4120, 2050, 1867, 200, 194, 193, - 2914, 3547, 2624, 1864, 73, 3614, 1760, 1866, 1863, 1865, - 1869, 1870, 3201, 1765, 3202, 1868, 1769, 3619, 1235, 1116, - 3364, 2617, 152, 2313, 2473, 1272, 208, 3828, 1274, 3362, - 1008, 1008, 701, 2944, 1730, 1243, 1246, 208, 3119, 2923, - 1768, 1080, 208, 174, 212, 173, 203, 175, 4215, 700, - 1232, 3787, 3235, 989, 700, 1228, 1275, 4239, 208, 3789, - 1277, 3999, 4000, 3705, 3539, 196, 197, 198, 1295, 1296, - 3233, 1294, 1784, 1783, 722, 722, 2318, 700, 172, 201, - 210, 202, 2794, 3359, 3360, 199, 3760, 2580, 1267, 3194, - 2620, 2621, 1989, 1987, 3113, 2619, 1123, 2681, 2574, 3361, - 1581, 1542, 200, 4004, 1568, 3825, 1247, 3369, 3799, 3358, - 1486, 719, 719, 719, 3721, 961, 206, 208, 1079, 1290, - 1291, 2898, 1278, 2889, 2627, 1289, 2206, 2207, 2919, 1157, - 1006, 3381, 687, 1120, 2051, 3423, 1121, 140, 1447, 2915, - 3450, 199, 3451, 141, 1770, 1345, 4110, 4007, 3550, 3448, - 3449, 3239, 2895, 4067, 731, 3447, 1268, 3394, 1874, 1875, - 1876, 1877, 1878, 1879, 1872, 1873, 3590, 4139, 1767, 1224, - 995, 3717, 1224, 3926, 3977, 4134, 3978, 2980, 1224, 3323, - 3593, 4032, 1270, 2485, 969, 724, 1791, 1794, 1795, 3123, - 962, 723, 1228, 2480, 3710, 1273, 1276, 1792, 142, 1281, - 1259, 3309, 2185, 1238, 4125, 4141, 4024, 1108, 1110, 3665, - 4147, 65, 1339, 3223, 2324, 2326, 2327, 1227, 1269, 3220, - 174, 212, 3418, 2344, 3017, 1377, 3672, 2308, 3804, 3805, - 3806, 1531, 1284, 2464, 3454, 1285, 1147, 3356, 3370, 1224, - 1111, 1147, 3980, 1147, 1131, 1147, 963, 1113, 1147, 1147, - 1245, 1244, 3013, 3014, 3993, 3017, 2320, 3925, 3813, 780, - 68, 3597, 1010, 1287, 1011, 3723, 1076, 4316, 3332, 2614, - 144, 4119, 3979, 3998, 4333, 3894, 3600, 2592, 984, 2591, - 3774, 982, 3968, 1766, 1250, 1108, 1110, 1248, 3949, 2547, - 2950, 3883, 2612, 2613, 208, 1271, 150, 209, 3889, 151, - 1554, 1555, 2742, 717, 717, 717, 1605, 946, 63, 1216, - 1529, 1450, 1452, 3370, 1456, 1671, 1554, 1555, 1111, 771, - 772, 773, 774, 775, 718, 718, 718, 1604, 1473, 2887, - 3592, 1460, 1476, 1455, 1455, 1256, 1482, 1252, 1253, 1231, - 1233, 1236, 1427, 1543, 3599, 1432, 714, 714, 714, 2623, - 1257, 1258, 1722, 4033, 1378, 1215, 716, 716, 716, 1528, - 1107, 2193, 1346, 1283, 700, 3365, 1017, 715, 715, 715, - 1468, 4214, 1465, 771, 772, 773, 774, 775, 4025, 1527, - 2943, 2560, 3120, 143, 47, 960, 4148, 2540, 2563, 3424, - 64, 2681, 1546, 1545, 5, 4012, 3647, 3063, 3236, 3064, - 3065, 1755, 209, 1288, 1756, 3427, 4046, 4001, 1234, 4228, - 2313, 1467, 720, 147, 148, 1220, 2183, 149, 3292, 1237, - 4317, 2583, 3091, 720, 2540, 1286, 700, 3757, 720, 3829, - 1583, 3922, 1761, 1478, 700, 2947, 2948, 732, 670, 670, - 3453, 2546, 1550, 4191, 720, 2562, 2548, 1591, 670, 670, - 2946, 3587, 1620, 1620, 2557, 700, 1793, 3443, 3110, 3357, - 1243, 1246, 1479, 1480, 2790, 1487, 3653, 1489, 1490, 1491, - 1492, 1493, 2670, 1495, 68, 2578, 722, 1648, 689, 1501, - 1389, 1390, 2438, 1659, 2325, 68, 1148, 1149, 1264, 1622, - 68, 1153, 2310, 3448, 3449, 2181, 1618, 1618, 229, 2158, - 2549, 1475, 2561, 720, 1627, 2550, 68, 670, 1336, 1335, - 1494, 2484, 1506, 3162, 3164, 3973, 3483, 1973, 3238, 4103, - 1500, 1499, 1498, 1497, 1083, 3927, 3928, 726, 3607, 2615, - 3896, 1247, 1009, 3977, 2465, 3978, 1070, 3178, 3179, 3923, - 3924, 3444, 3931, 3930, 3929, 3932, 3933, 3934, 3890, 3891, - 4045, 3972, 3935, 4314, 4315, 2322, 2323, 3885, 2910, 1701, - 1431, 3884, 3060, 3936, 1706, 68, 1916, 1918, 1917, 1582, - 3581, 1433, 2781, 1513, 1719, 2457, 1018, 1263, 2459, 2458, - 1614, 1615, 3904, 3905, 3906, 3910, 3908, 3909, 3911, 3907, - 2956, 2960, 2961, 2962, 2957, 2959, 2958, 1538, 1539, 1472, - 1743, 3980, 4227, 1464, 1488, 1746, 1341, 1342, 1343, 1344, - 1020, 1021, 1022, 1708, 1620, 1995, 1620, 1228, 1996, 1509, - 1521, 981, 1715, 2456, 1507, 2336, 1514, 1978, 1530, 1994, - 1072, 3979, 974, 1071, 970, 1540, 2604, 719, 971, 1915, - 719, 719, 3856, 1559, 1560, 2378, 1562, 1563, 2377, 1564, - 4329, 2551, 1571, 1572, 1754, 4323, 1070, 1470, 1471, 1533, - 1537, 1537, 1537, 3948, 3404, 1740, 4311, 1558, 1677, 974, - 1561, 1972, 4342, 3082, 3083, 1245, 1244, 1649, 4335, 2556, - 4201, 1737, 1738, 2554, 1533, 1533, 1762, 1620, 3092, 3094, - 3095, 3096, 3093, 1691, 1692, 978, 3489, 1603, 3163, 1300, - 976, 975, 2681, 3378, 1228, 1849, 1466, 1680, 2768, 1683, - 1684, 1699, 3485, 3654, 1599, 1601, 1634, 1880, 1881, 1898, - 1884, 1685, 1686, 1696, 1612, 1613, 1700, 1640, 1899, 695, - 1628, 1833, 973, 1300, 1660, 2315, 2929, 976, 975, 1646, - 4324, 1906, 1264, 1908, 1218, 1909, 1910, 1911, 1111, 1661, - 1072, 4277, 2991, 1071, 4276, 3610, 1523, 1974, 3445, 1801, + 811, 787, 4323, 813, 4298, 3019, 229, 4315, 1705, 3666, + 4232, 1780, 2100, 3768, 4238, 3453, 4231, 4239, 4148, 4044, + 3418, 796, 4103, 3531, 4194, 2212, 3956, 3905, 3695, 4022, + 3013, 3989, 3763, 3724, 4094, 1617, 3532, 1374, 4043, 4126, + 3838, 3529, 2922, 1776, 841, 789, 1548, 3016, 671, 1218, + 1846, 1103, 4013, 3623, 4104, 3773, 4106, 1554, 3200, 38, + 2044, 3628, 1833, 2542, 3427, 690, 3682, 2993, 1783, 701, + 3857, 1706, 3384, 1223, 701, 714, 723, 3847, 3369, 723, + 3820, 3132, 3345, 3133, 3646, 2759, 2214, 3372, 3615, 3587, + 3108, 2196, 3042, 785, 3447, 3436, 3131, 2651, 3648, 3429, + 3128, 2237, 2927, 1851, 3581, 3852, 3514, 2687, 3161, 3493, + 1829, 2545, 1830, 2161, 2060, 2306, 2199, 740, 2852, 2953, + 3352, 3394, 1610, 3119, 3350, 2766, 3435, 3346, 2506, 3309, + 3348, 731, 2435, 2966, 720, 2302, 3347, 3343, 2436, 735, + 2274, 784, 2283, 779, 2272, 145, 214, 2192, 2282, 1220, + 2275, 2242, 2340, 1958, 2741, 2301, 2652, 2165, 981, 1694, + 2635, 37, 1848, 2162, 2942, 2937, 2630, 3044, 1698, 2543, + 3024, 1710, 2090, 2505, 701, 1018, 1695, 2980, 67, 1690, + 225, 8, 2484, 6, 1511, 224, 7, 2015, 1779, 1478, + 1847, 2685, 1774, 1683, 1097, 1164, 2303, 2269, 1657, 788, + 1626, 2336, 689, 1589, 2475, 671, 1595, 2538, 2059, 1557, + 2036, 2278, 1537, 2281, 797, 780, 778, 2438, 1840, 2478, + 1765, 1816, 1241, 2258, 2011, 1773, 1096, 28, 1664, 229, + 728, 229, 2014, 1155, 1156, 1594, 24, 2659, 705, 2631, + 701, 1533, 670, 1591, 1017, 737, 1558, 1648, 1454, 25, + 1459, 946, 1061, 1135, 26, 1852, 215, 997, 738, 722, + 1015, 17, 10, 211, 207, 16, 1047, 698, 1549, 786, + 1003, 1375, 1430, 4113, 2310, 4010, 734, 2897, 2897, 1011, + 14, 1012, 1303, 1304, 1305, 1302, 2897, 1303, 1304, 1305, + 1302, 2661, 1152, 3663, 1519, 3545, 15, 1303, 1304, 1305, + 1302, 3406, 719, 3319, 3318, 1130, 3223, 3222, 2320, 2851, + 1523, 1981, 1224, 34, 780, 1455, 3809, 948, 3631, 949, + 992, 1225, 2804, 3524, 708, 2747, 2745, 2744, 2742, 1456, + 1971, 1671, 696, 1667, 1006, 1147, 1002, 1148, 726, 213, + 715, 691, 2434, 1516, 1517, 1518, 1449, 1593, 4081, 1415, + 969, 967, 2213, 3316, 1109, 717, 2448, 1148, 2441, 1978, + 1724, 1148, 1458, 3304, 3302, 3299, 3301, 4310, 2889, 2887, + 1111, 718, 1571, 1965, 1445, 1151, 1224, 1153, 1669, 1082, + 3761, 1303, 1304, 1305, 1302, 3196, 3194, 1112, 716, 1131, + 1303, 1304, 1305, 1302, 8, 2247, 3538, 1146, 4089, 7, + 3963, 3957, 3764, 3530, 984, 2268, 4108, 2277, 947, 2764, + 3273, 1369, 2891, 2264, 3592, 2583, 4329, 4102, 4307, 958, + 3971, 4100, 3997, 3606, 2831, 2455, 3969, 4159, 3590, 2187, + 1634, 1464, 1460, 1463, 1462, 969, 967, 1113, 1486, 733, + 3271, 1013, 1503, 3685, 174, 212, 173, 203, 175, 937, + 2318, 936, 938, 939, 3126, 940, 941, 2479, 3999, 968, + 966, 2679, 1484, 1125, 1120, 1115, 1119, 1123, 1300, 965, + 1989, 1766, 3169, 3170, 1770, 2680, 1567, 3168, 1008, 1568, + 1001, 2053, 2921, 1987, 3697, 769, 2176, 2177, 771, 1005, + 1004, 1128, 1596, 770, 1598, 1118, 769, 3688, 1769, 771, + 1993, 1994, 1280, 2917, 770, 1281, 1722, 1470, 3683, 2666, + 993, 2175, 2665, 3705, 3706, 2667, 1545, 3422, 208, 3684, + 174, 212, 173, 203, 175, 1107, 1721, 1108, 959, 3420, + 1000, 1553, 2760, 1283, 2209, 1552, 1555, 1556, 1076, 1074, + 204, 1075, 1555, 1556, 4242, 4243, 1126, 195, 1070, 1010, + 2939, 205, 2074, 1782, 999, 3303, 3300, 2919, 998, 3689, + 2940, 1293, 1298, 1106, 986, 3790, 1105, 1129, 4111, 1078, + 144, 174, 212, 173, 203, 175, 4111, 4208, 2914, 1570, + 4110, 4207, 991, 4109, 4206, 130, 174, 212, 173, 203, + 175, 1485, 4110, 4196, 208, 4109, 1116, 4267, 174, 212, + 173, 203, 175, 1771, 2413, 4215, 4302, 4303, 3533, 2938, + 4092, 989, 4196, 2051, 2918, 174, 212, 173, 203, 175, + 1127, 4095, 4096, 4097, 4098, 3201, 3202, 1768, 3203, 4199, + 1670, 1668, 3960, 2892, 1278, 2915, 3533, 1731, 3206, 2785, + 1786, 1083, 1230, 2322, 3616, 208, 4122, 3063, 3548, 2193, + 1009, 2183, 1233, 2945, 702, 2314, 1761, 3363, 1117, 3621, + 208, 1009, 2924, 3830, 3365, 3704, 3120, 2546, 2618, 2474, + 1079, 3707, 208, 990, 1296, 1297, 4217, 3540, 2625, 3234, + 1295, 1236, 1273, 153, 154, 1275, 155, 156, 2795, 208, + 3236, 157, 3693, 199, 158, 2581, 1279, 1244, 1247, 1268, + 701, 4001, 4002, 3762, 3195, 701, 1229, 2621, 2622, 962, + 3114, 3360, 3361, 1276, 3690, 3694, 3692, 3691, 4241, 1886, + 4006, 2620, 3789, 2319, 3359, 723, 723, 3362, 701, 3827, + 3791, 1543, 1081, 3801, 3370, 1124, 2899, 2682, 2628, 1582, + 1290, 1990, 1767, 1487, 688, 3723, 2575, 1569, 3594, 3451, + 1007, 3452, 2052, 2920, 1988, 172, 201, 210, 202, 72, + 128, 3395, 2325, 2327, 2328, 2890, 3699, 3700, 1248, 720, + 720, 720, 1121, 1282, 2916, 1122, 1785, 1784, 3719, 200, + 194, 193, 1158, 4069, 963, 4034, 73, 3382, 4141, 3979, + 996, 3980, 1291, 1292, 3449, 3450, 1346, 4112, 1448, 4009, + 3448, 3551, 3240, 3424, 152, 4026, 732, 2207, 2208, 1080, + 2896, 4136, 2981, 2561, 1269, 3324, 3595, 1225, 3591, 2541, + 2564, 3707, 3806, 3807, 3808, 1225, 970, 725, 1285, 724, + 3124, 1286, 2486, 3712, 3686, 2481, 1225, 3698, 1239, 3310, + 1271, 964, 4127, 1229, 1792, 1795, 1796, 196, 197, 198, + 4143, 3667, 3357, 1274, 1277, 1793, 2186, 3982, 1109, 1288, + 4149, 3419, 1340, 3979, 3224, 3980, 3371, 1466, 1228, 3221, + 3014, 3015, 1260, 3018, 1111, 3018, 1270, 2563, 3674, 2345, + 3455, 3974, 2309, 1132, 1532, 2465, 1114, 3981, 1378, 3995, + 3725, 1112, 1148, 3815, 1148, 1148, 1148, 2548, 985, 206, + 1225, 983, 1148, 3599, 1148, 721, 1468, 3333, 2615, 781, + 4121, 2321, 3896, 1246, 1245, 4335, 4318, 2951, 3602, 2593, + 140, 4000, 2592, 3885, 199, 2743, 141, 3970, 1555, 1556, + 3776, 3982, 1251, 1606, 1672, 2562, 1109, 719, 719, 719, + 1555, 1556, 2613, 2614, 3951, 1605, 1258, 174, 212, 2682, + 1249, 1530, 1111, 1272, 3371, 1529, 3891, 1077, 4035, 1528, + 1284, 3981, 1451, 1453, 4150, 1457, 4048, 68, 3703, 1112, + 1217, 2888, 1461, 947, 1544, 715, 715, 715, 4027, 1474, + 961, 142, 3593, 1477, 1253, 1254, 3601, 1483, 1257, 1456, + 717, 717, 717, 1456, 65, 1428, 4014, 144, 1433, 1723, + 1289, 2944, 3428, 3092, 1221, 1379, 718, 718, 718, 1259, + 3366, 3121, 1469, 1347, 1216, 701, 1108, 1018, 2194, 1547, + 1546, 208, 1287, 716, 716, 716, 2624, 772, 773, 774, + 775, 776, 721, 2326, 1232, 1234, 1237, 3237, 772, 773, + 774, 775, 776, 68, 1011, 4230, 1012, 721, 4003, 2547, + 3293, 3702, 4216, 2584, 2549, 1238, 2948, 2949, 3425, 721, + 3649, 1342, 1343, 1344, 1345, 3064, 3831, 3065, 3066, 4319, + 2541, 2947, 1235, 1337, 1336, 3358, 721, 701, 2184, 150, + 209, 1584, 151, 1762, 2558, 701, 3454, 2314, 3759, 671, + 671, 63, 3655, 1551, 68, 3179, 3180, 1479, 1465, 671, + 671, 3449, 3450, 1621, 1621, 733, 701, 4193, 2550, 68, + 4047, 1917, 1919, 1918, 1071, 1794, 3163, 3165, 174, 212, + 1592, 68, 3484, 2486, 3588, 1390, 1391, 723, 1649, 690, + 1265, 3975, 3444, 3111, 1660, 4105, 1149, 1150, 68, 1623, + 2791, 1154, 2973, 2671, 2579, 2551, 1619, 1619, 2439, 229, + 2957, 2961, 2962, 2963, 2958, 2960, 2959, 1628, 671, 2311, + 2485, 3379, 2182, 1507, 2159, 1476, 143, 47, 1495, 3239, + 1501, 975, 3609, 64, 1480, 1481, 1500, 5, 1499, 1490, + 1491, 1492, 1493, 1494, 1916, 1496, 2466, 1244, 1247, 3887, + 2337, 1502, 2971, 3886, 1498, 1583, 147, 148, 1084, 1974, + 149, 1467, 4316, 4317, 727, 3975, 3892, 3893, 1073, 3976, + 1702, 1072, 2616, 1434, 3898, 1707, 3445, 2323, 2324, 1264, + 3061, 1432, 3582, 1615, 1616, 1720, 3906, 3907, 3908, 3912, + 3910, 3911, 3913, 3909, 979, 1021, 1022, 1023, 4229, 977, + 976, 1019, 2974, 2782, 1514, 3083, 3084, 1488, 2460, 2459, + 1071, 1744, 2911, 1539, 1540, 2458, 1747, 1473, 1248, 1489, + 1071, 1996, 1471, 1472, 975, 1621, 1709, 1621, 1229, 3093, + 3095, 3096, 3097, 3094, 1997, 1515, 982, 1510, 2457, 1979, + 1716, 1995, 1508, 1600, 1602, 1534, 1538, 1538, 1538, 971, + 2605, 2552, 972, 1613, 1614, 720, 3858, 2578, 720, 720, + 2930, 3164, 3380, 1524, 1741, 1572, 1573, 1524, 4331, 2557, + 1534, 1534, 1755, 2555, 1010, 978, 1559, 4337, 2649, 1562, + 1738, 1739, 1522, 1678, 4325, 4203, 3490, 974, 3950, 2308, + 1531, 1650, 977, 976, 3405, 2931, 2932, 1541, 1621, 3656, + 1525, 1301, 1763, 2682, 1073, 1560, 1561, 1072, 1563, 1564, + 1604, 1565, 1673, 1973, 1073, 1229, 1850, 1072, 2769, 1681, + 2379, 1684, 1685, 2378, 3486, 1635, 1692, 1693, 1881, 1882, + 1899, 1885, 1629, 1686, 1687, 4313, 1700, 696, 1641, 1900, + 2308, 1834, 1697, 2991, 3082, 1701, 1647, 2477, 1661, 4278, + 2548, 2551, 1907, 2316, 1909, 1262, 1910, 1911, 1912, 1112, + 1265, 2308, 1778, 1246, 1245, 1662, 1143, 1144, 1145, 4326, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, - 1812, 2930, 2931, 2476, 2307, 1262, 977, 1826, 1827, 1780, - 1084, 1777, 3549, 1672, 1742, 1523, 1888, 1889, 1890, 950, - 951, 952, 953, 1741, 2427, 4251, 1228, 2547, 2550, 1904, - 2307, 1758, 1905, 2307, 1218, 4248, 4242, 1728, 1981, 1796, - 1731, 1982, 3081, 1984, 2789, 1711, 1883, 700, 700, 4224, - 4184, 1924, 1925, 1300, 1955, 1997, 1999, 1907, 2000, 717, - 2002, 2003, 717, 717, 689, 1648, 1142, 1143, 1144, 4277, - 2011, 1620, 2016, 2017, 3379, 2019, 1583, 700, 1070, 1954, - 718, 1752, 700, 718, 718, 1620, 1774, 2990, 1771, 1017, - 1748, 1751, 2044, 1747, 3458, 1729, 1897, 1753, 1732, 1733, - 1141, 1776, 714, 1138, 3973, 714, 714, 1620, 3974, 2520, - 4252, 3456, 716, 1583, 3295, 716, 716, 2235, 713, 1750, - 4249, 2354, 3338, 715, 1817, 2577, 715, 715, 1958, 1749, - 2648, 174, 212, 2475, 4225, 1300, 2485, 1300, 2072, 2037, - 2649, 1302, 1303, 1304, 1301, 4183, 3307, 2079, 2079, 3305, - 1583, 4167, 1583, 1583, 2649, 2972, 700, 700, 4142, 2146, - 4130, 2011, 2151, 4077, 1264, 1620, 2155, 2156, 3181, 3489, - 1261, 2171, 1072, 670, 2551, 1071, 4076, 4059, 1763, 2546, - 2540, 2545, 1961, 2543, 2548, 955, 2773, 670, 1966, 1620, - 2789, 2892, 2018, 2306, 2007, 2008, 2009, 1428, 2076, 3296, - 1302, 1303, 1304, 1301, 2764, 2970, 2022, 2023, 2024, 2025, - 1302, 1303, 1304, 1301, 2306, 2020, 700, 2011, 1620, 2173, - 2218, 2533, 700, 700, 700, 730, 730, 1912, 1913, 2432, - 1300, 2101, 2228, 2229, 2230, 2231, 2354, 2040, 2549, 2237, - 2426, 2425, 2991, 2315, 2387, 4131, 229, 4058, 4078, 229, - 229, 2149, 229, 3293, 2209, 2973, 2386, 1956, 2519, 1262, - 1962, 2502, 2354, 2005, 2385, 1111, 4057, 2297, 3267, 2204, - 2649, 1305, 2233, 1135, 1136, 1137, 1140, 2081, 1139, 1338, - 1302, 1303, 1304, 1301, 2157, 2147, 2201, 2202, 1348, 2082, - 2420, 4056, 1508, 1836, 1971, 4036, 1975, 1898, 1898, 2284, - 2060, 1979, 2062, 2063, 2187, 1606, 2291, 2220, 2221, 2222, - 2178, 2006, 2180, 2015, 1357, 4325, 2069, 1302, 1303, 1304, - 1301, 4035, 3661, 2199, 2200, 2041, 2353, 2031, 4010, 2065, - 2547, 2550, 2354, 1264, 2045, 2266, 3728, 2217, 3294, 3185, - 2044, 2070, 2993, 2901, 1620, 2304, 2792, 2055, 2791, 2053, - 3618, 2354, 2056, 2057, 2194, 2061, 1302, 1303, 1304, 1301, - 2245, 2083, 2084, 2248, 2249, 2783, 2251, 719, 2527, 2066, - 2067, 2373, 2358, 1813, 1814, 2421, 2354, 1824, 1825, 1533, - 2315, 2296, 825, 146, 2148, 2078, 2080, 3674, 146, 2077, - 2240, 3636, 2226, 1537, 1976, 1725, 1354, 2285, 1249, 2298, - 2153, 1213, 1208, 2159, 3573, 1537, 2315, 2154, 2254, 2177, - 3938, 2179, 3726, 2354, 2352, 2188, 1919, 1920, 1921, 1922, - 2203, 2681, 1926, 1927, 1928, 1929, 1931, 1932, 1933, 1934, - 1935, 1936, 1937, 1938, 1939, 1940, 1941, 972, 3569, 3466, - 2215, 3157, 1108, 1110, 2279, 2216, 1317, 2983, 2869, 2172, - 696, 2223, 2224, 1302, 1303, 1304, 1301, 146, 1575, 1576, - 1774, 1578, 1579, 1580, 2975, 1584, 1585, 1586, 2242, 2857, - 3409, 2329, 3675, 2341, 2340, 1111, 3637, 2551, 1302, 1303, - 1304, 1301, 2546, 2540, 2545, 3230, 2543, 2548, 4135, 3574, - 3521, 2259, 1302, 1303, 1304, 1301, 2333, 2334, 2535, 1635, - 1636, 1637, 1638, 1639, 4336, 1641, 1642, 1643, 1644, 1645, - 3857, 3266, 2849, 1651, 1652, 1653, 1654, 1676, 1675, 4026, - 1336, 1335, 2044, 3570, 3467, 2805, 2649, 1610, 4304, 2575, - 2787, 1522, 2771, 2502, 4136, 2293, 2424, 2295, 1611, 2775, - 2770, 2549, 2755, 2753, 1108, 1110, 4112, 2342, 4071, 1534, - 2350, 4009, 2751, 2439, 1300, 2441, 3858, 2443, 2444, 717, - 3965, 3920, 3650, 2299, 2749, 2047, 2048, 700, 1583, 700, - 1583, 2418, 2388, 2389, 2501, 2391, 3887, 1111, 2312, 2460, - 718, 2410, 2398, 2356, 2428, 778, 2394, 2393, 700, 700, - 700, 1109, 2328, 2741, 979, 2294, 146, 1300, 1302, 1303, - 1304, 1301, 714, 700, 700, 700, 700, 2337, 3651, 4027, - 1300, 146, 716, 146, 1817, 2502, 1887, 1886, 2330, 1898, - 1898, 2376, 1658, 715, 2776, 2771, 2506, 2756, 2754, 2367, - 2366, 2507, 2508, 2509, 2346, 2512, 1583, 2750, 2365, 2355, - 2826, 2827, 2314, 2411, 2413, 2414, 2415, 2820, 2417, 2750, - 3395, 813, 823, 1887, 1886, 4028, 2419, 1734, 3648, 2502, - 3778, 814, 1583, 815, 819, 822, 818, 816, 817, 2427, - 1535, 1300, 1300, 2037, 1207, 1203, 1204, 1205, 1206, 2569, - 2825, 3886, 2824, 2823, 2821, 1316, 1315, 1325, 1326, 1327, - 1328, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1317, 950, - 951, 952, 953, 3872, 3649, 3832, 1300, 2451, 1519, 2453, - 1565, 1608, 1520, 3628, 1300, 1300, 2380, 1320, 1321, 1322, - 1323, 1324, 1317, 1300, 2354, 3490, 3481, 2315, 820, 3473, - 3468, 3396, 1930, 3373, 3116, 2576, 3115, 2954, 700, 2079, - 2429, 2897, 1735, 2802, 2774, 2672, 2445, 2653, 2653, 2171, - 2653, 2288, 2524, 2822, 2287, 2286, 2526, 2495, 2528, 821, - 1504, 1503, 1230, 1823, 1108, 1110, 2279, 2812, 2442, 1923, - 670, 670, 2446, 1840, 2735, 2347, 2243, 3397, 1228, 1820, - 1822, 1819, 1631, 1821, 1620, 700, 3777, 1664, 3325, 2243, - 1786, 1787, 1788, 1789, 1790, 1840, 2466, 1111, 2001, 1111, - 700, 2529, 3186, 4203, 1304, 1301, 1228, 2725, 689, 2539, - 2538, 1377, 3899, 1519, 1659, 1607, 2171, 1520, 1301, 2731, - 3898, 2733, 3398, 3052, 229, 3050, 4233, 2499, 2676, 2516, - 2498, 2727, 2496, 3029, 2522, 1837, 2532, 2523, 3027, 1841, - 1842, 1843, 1844, 3878, 2655, 2513, 2659, 2953, 1902, 1882, - 2667, 4256, 2668, 1302, 1303, 1304, 1301, 1892, 2657, 1302, - 1303, 1304, 1301, 1903, 2525, 955, 2331, 2332, 2778, 1356, - 3524, 2673, 2674, 1302, 1303, 1304, 1301, 2785, 2552, 2553, - 2304, 2558, 1355, 2661, 2745, 2683, 4332, 1620, 2879, 1620, - 2880, 1620, 3826, 2521, 1108, 1110, 1228, 1302, 1303, 1304, - 1301, 4174, 4175, 4223, 2804, 4222, 3522, 4061, 4062, 1946, - 4177, 1948, 1949, 1950, 1951, 1952, 2688, 3833, 3834, 4176, - 1959, 1302, 1303, 1304, 1301, 2730, 3616, 1111, 1537, 3103, - 2814, 4173, 2369, 2795, 1620, 1228, 3101, 3099, 2736, 2833, - 1378, 2628, 2622, 1318, 1319, 1320, 1321, 1322, 1323, 1324, - 1317, 4331, 3827, 4172, 2840, 3088, 2662, 4171, 4169, 1620, - 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1306, 2689, 1724, - 2828, 1302, 1303, 1304, 1301, 4168, 4137, 2922, 1618, 3622, - 2737, 1302, 1303, 1304, 1301, 2677, 3617, 2680, 4049, 3102, - 1665, 1302, 1303, 1304, 1301, 2841, 3100, 3098, 4039, 1664, - 2766, 2767, 2368, 1618, 4029, 3259, 3956, 2726, 3245, 3860, - 3859, 3803, 2729, 2049, 3666, 3087, 2846, 2847, 3652, 2762, - 3615, 2899, 3363, 3226, 3198, 2219, 2903, 3197, 2905, 1302, - 1303, 1304, 1301, 3086, 3085, 700, 700, 3084, 3076, 2068, - 3070, 2815, 2801, 2817, 2760, 3069, 1599, 1601, 3068, 1228, - 2796, 3067, 2893, 2757, 2842, 2669, 1620, 2431, 2799, 1583, - 2262, 2831, 2261, 2260, 3627, 1583, 2151, 2256, 3258, 2255, - 2810, 2210, 1985, 3795, 2786, 2788, 1302, 1303, 1304, 1301, - 2793, 1983, 1726, 2986, 2989, 1446, 1302, 1303, 1304, 1301, - 2994, 146, 146, 146, 1109, 1302, 1303, 1304, 1301, 1959, - 1302, 1303, 1304, 1301, 1959, 1959, 3350, 4328, 3004, 2290, - 4002, 4003, 1211, 2806, 2807, 4326, 2829, 2871, 1228, 2872, - 2971, 2874, 3767, 2876, 2877, 2883, 3026, 2819, 4302, 1774, - 4269, 4210, 4209, 1228, 1228, 1228, 2079, 2966, 3792, 1228, - 3988, 3036, 3037, 3038, 3039, 1228, 3046, 4189, 3047, 3048, - 4122, 3049, 3837, 3051, 2244, 2968, 4116, 2247, 4097, 2688, - 2250, 4088, 4066, 2252, 3046, 1302, 1303, 1304, 1301, 4065, - 4053, 1210, 1337, 4048, 4047, 4006, 2653, 3992, 3990, 3957, - 2884, 3880, 3841, 2981, 3830, 3815, 3814, 2101, 3810, 3808, - 3104, 2852, 2853, 3802, 3798, 3797, 3791, 2858, 2951, 3794, - 670, 1602, 2272, 3793, 2967, 3769, 3765, 3005, 2151, 3763, - 2995, 2689, 1228, 2171, 2171, 2171, 2171, 2171, 2171, 2933, - 3735, 2935, 3007, 1302, 1303, 1304, 1301, 3732, 3730, 1228, - 2171, 3781, 3108, 2653, 3612, 3594, 3024, 3109, 3582, 2932, - 3024, 3020, 3561, 3780, 2839, 2949, 1111, 3779, 4334, 3165, - 2974, 1620, 3019, 3025, 3714, 3559, 3031, 3553, 1302, 1303, - 1304, 1301, 700, 700, 2988, 8, 3538, 7, 3501, 2985, - 1302, 1303, 1304, 1301, 1302, 1303, 1304, 1301, 3479, 3478, - 3021, 1302, 1303, 1304, 1301, 3555, 4166, 3009, 3476, 3003, - 3006, 3475, 3469, 3464, 3022, 3021, 3032, 3033, 2015, 3463, - 3153, 3035, 3374, 3034, 3336, 3028, 3335, 3042, 1302, 1303, - 1304, 1301, 1302, 1303, 1304, 1301, 3326, 3319, 229, 3152, - 3314, 3121, 3312, 229, 2436, 3240, 2343, 3237, 3224, 3196, - 2348, 1434, 3297, 3166, 2351, 3172, 3078, 2996, 2357, 3097, - 3066, 1302, 1303, 1304, 1301, 3089, 3001, 3002, 3079, 3268, - 3077, 3073, 1898, 3072, 1898, 3071, 2911, 3219, 3262, 1302, - 1303, 1304, 1301, 4290, 3225, 2902, 2894, 2782, 3111, 3117, - 1620, 891, 890, 3232, 3133, 2364, 1302, 1303, 1304, 1301, - 3182, 2761, 2809, 2371, 2461, 1302, 1303, 1304, 1301, 3150, - 3503, 3133, 2449, 3156, 3154, 2448, 2265, 3173, 2258, 1969, - 3155, 1968, 1727, 3214, 3134, 3135, 3136, 3137, 3138, 3139, - 3170, 2390, 1302, 1303, 1304, 1301, 2395, 2396, 2397, 1385, - 1381, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, - 2409, 3174, 3187, 2169, 1380, 2581, 1214, 3191, 2584, 2585, - 2586, 2587, 2588, 2589, 2590, 1691, 1692, 2593, 2594, 2595, - 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 1699, 2605, - 2606, 2607, 2608, 2609, 1684, 2610, 959, 1958, 3189, 4154, - 1696, 3188, 3218, 1700, 1685, 1686, 3114, 4150, 3984, 3313, - 3983, 3970, 3316, 3966, 3796, 3775, 3745, 700, 1583, 3229, - 1629, 3643, 3234, 3216, 696, 3327, 3328, 3329, 3331, 3215, - 3333, 3334, 699, 3212, 3217, 3210, 3207, 702, 3642, 1228, - 3640, 3203, 3609, 3578, 3576, 1228, 3575, 3261, 3572, 3571, - 3560, 3353, 3558, 3542, 4289, 3241, 3527, 174, 212, 1111, - 146, 3367, 3526, 3512, 3511, 3228, 700, 3257, 3260, 3402, - 3242, 3340, 3253, 3254, 1302, 1303, 1304, 1301, 3337, 3304, - 3384, 1228, 174, 212, 700, 3264, 700, 1228, 1228, 3250, - 1524, 3252, 3251, 3255, 3247, 1302, 1303, 1304, 1301, 2868, - 3246, 2171, 2506, 3244, 3408, 3180, 2752, 3399, 3306, 1315, - 1325, 1326, 1327, 1328, 1318, 1319, 1320, 1321, 1322, 1323, - 1324, 1317, 2569, 3248, 3249, 2867, 1302, 1303, 1304, 1301, - 3377, 208, 146, 2361, 3433, 3387, 3436, 699, 3436, 3436, - 3311, 3392, 2748, 1228, 3310, 2747, 3400, 146, 2966, 2399, - 146, 146, 1302, 1303, 1304, 1301, 208, 3321, 2392, 2384, - 2383, 3459, 2382, 2381, 146, 2379, 3455, 2375, 3355, 1620, - 1620, 3416, 2374, 2372, 2363, 3380, 3273, 3274, 174, 212, - 3420, 3422, 3275, 3276, 3277, 3278, 2360, 3279, 3280, 3281, - 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 1959, 2359, - 1959, 3339, 2264, 702, 1947, 3460, 3461, 3021, 3411, 1945, - 3406, 1944, 1943, 1618, 1618, 3386, 700, 3376, 1942, 1959, - 1959, 3390, 3391, 3353, 174, 212, 1108, 1110, 3213, 3432, - 1302, 1303, 1304, 1301, 3407, 3401, 1583, 1901, 1900, 2151, - 2151, 3441, 3431, 3021, 2039, 1891, 3415, 3403, 1632, 3021, - 3021, 1630, 208, 1658, 4255, 4182, 1375, 2539, 2538, 1111, - 212, 1111, 4149, 4083, 3437, 3438, 3442, 1111, 3439, 4080, - 4055, 4050, 1111, 3951, 2036, 3950, 3915, 3457, 1325, 1326, - 1327, 1328, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1317, - 3897, 1330, 1228, 1334, 3893, 3871, 2833, 1111, 2038, 3854, - 3746, 3465, 3743, 3712, 3525, 3021, 2777, 2866, 2780, 1331, - 1333, 1329, 3711, 1332, 1316, 1315, 1325, 1326, 1327, 1328, - 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1317, 212, 173, - 203, 175, 2940, 208, 1302, 1303, 1304, 1301, 3708, 3707, - 3673, 3486, 3487, 3471, 3477, 3472, 3470, 3670, 3668, 700, - 174, 212, 3480, 174, 212, 3474, 3630, 3414, 3256, 1679, - 3497, 1690, 3498, 4202, 2865, 1681, 1695, 2813, 2864, 1698, - 2816, 1687, 1511, 1717, 3144, 3484, 3105, 3030, 3505, 2977, - 2976, 2834, 2835, 2863, 2969, 3508, 3509, 3510, 2862, 2837, - 2838, 1302, 1303, 1304, 1301, 1302, 1303, 1304, 1301, 3515, - 144, 208, 2688, 1714, 2861, 2843, 2844, 2845, 2934, 2870, - 1302, 1303, 1304, 1301, 2769, 1302, 1303, 1304, 1301, 146, - 3535, 2349, 2671, 2611, 208, 2500, 3584, 1716, 2468, 2467, - 2237, 1302, 1303, 1304, 1301, 3058, 3059, 2430, 1818, 2873, - 3595, 2875, 2860, 208, 2878, 3601, 1786, 1959, 3562, 2225, - 3074, 3075, 1965, 1759, 2689, 3546, 3545, 1718, 4099, 2859, - 1688, 1445, 1430, 1426, 3543, 3602, 2856, 3551, 1425, 1302, - 1303, 1304, 1301, 1424, 1423, 1422, 3112, 4282, 2855, 1421, - 700, 2151, 1420, 3596, 1419, 3598, 1302, 1303, 1304, 1301, - 2854, 1418, 3635, 1302, 1303, 1304, 1301, 1417, 1416, 1302, - 1303, 1304, 1301, 2170, 3608, 1302, 1303, 1304, 1301, 1415, - 1414, 3611, 1413, 1412, 2653, 2171, 3658, 1302, 1303, 1304, - 1301, 1411, 1410, 3579, 3564, 3583, 3566, 1409, 3568, 3588, - 1408, 3585, 1407, 3502, 2848, 1406, 1405, 1404, 3676, 2998, - 2999, 1228, 1403, 1402, 1401, 1400, 3499, 2836, 1399, 1398, - 3433, 1397, 3605, 1396, 1228, 1395, 1394, 1393, 1392, 1391, - 3606, 1302, 1303, 1304, 1301, 3623, 1388, 1228, 1387, 3725, - 1386, 1384, 1383, 1620, 1302, 1303, 1304, 1301, 146, 1382, - 2046, 146, 146, 3625, 146, 1379, 3660, 1372, 1371, 3634, - 1369, 1368, 1367, 1366, 700, 1365, 2151, 1364, 3641, 1363, - 1228, 1362, 2064, 3706, 1361, 1360, 1359, 1358, 1353, 3727, - 3656, 2832, 1352, 1351, 1350, 3699, 1349, 1618, 2071, 1266, - 1212, 2074, 2075, 3667, 3657, 3669, 3663, 2811, 4164, 1109, - 1111, 3493, 3494, 229, 4162, 4160, 2423, 1111, 1302, 1303, - 1304, 1301, 3709, 2511, 2482, 3713, 3739, 146, 3736, 3718, - 3655, 1254, 3715, 4280, 1302, 1303, 1304, 1301, 4238, 3724, - 3751, 3496, 1221, 1302, 1303, 1304, 1301, 1226, 3729, 2422, - 2955, 3731, 2682, 3151, 2494, 1265, 3733, 2416, 3734, 3737, - 3142, 1959, 3147, 3145, 3740, 3738, 3140, 3148, 3146, 129, - 1255, 3141, 3149, 3876, 2643, 2644, 1302, 1303, 1304, 1301, - 700, 2984, 3753, 3677, 1302, 1303, 1304, 1301, 1835, 3748, - 2772, 3812, 3773, 1505, 2033, 2034, 3716, 70, 3741, 3749, - 69, 1228, 3770, 3372, 3209, 66, 2028, 2029, 2030, 3042, - 3768, 1337, 3429, 2579, 3430, 1302, 1303, 1304, 1301, 3540, - 3541, 1228, 1620, 1620, 3719, 3516, 3790, 3758, 3384, 2138, - 3809, 3054, 3811, 1673, 2982, 2766, 2767, 691, 3055, 3056, - 3057, 3190, 3133, 3192, 1228, 3849, 1710, 2800, 3849, 3747, - 2455, 1707, 2462, 2227, 1260, 3348, 3341, 3008, 3839, 1228, - 3865, 1228, 3843, 3844, 2272, 692, 1618, 1833, 693, 1959, - 3868, 3838, 3870, 694, 1959, 2978, 2531, 3800, 1620, 2492, - 2042, 2004, 3821, 3846, 3822, 3840, 3820, 1887, 1886, 1441, - 1442, 1439, 1440, 4293, 3831, 4052, 700, 3462, 1228, 1228, - 2625, 3852, 1228, 1228, 1437, 1438, 3842, 2618, 3817, 1435, - 1436, 3853, 2152, 1574, 3243, 3861, 3660, 1573, 1293, 2289, - 3514, 3917, 1833, 3507, 3864, 2463, 2292, 1526, 3912, 1525, - 3874, 3706, 1549, 1496, 2044, 3824, 3877, 3943, 2798, 3263, - 3881, 3919, 4262, 3699, 3823, 4260, 2285, 2797, 3901, 3902, - 3952, 3953, 3913, 3914, 4216, 4199, 4198, 3873, 4196, 4126, - 4084, 3946, 3945, 3021, 1620, 3866, 3782, 3879, 3783, 3764, - 3563, 3534, 3533, 3519, 2269, 2564, 3940, 2638, 2642, 2643, - 2644, 2639, 2647, 2640, 2645, 3939, 2534, 2641, 1712, 2646, - 3985, 3518, 3184, 3941, 1523, 4284, 4283, 4284, 3227, 3976, - 3964, 3918, 2907, 2906, 2900, 2362, 3133, 1251, 1618, 1111, - 1225, 1218, 4283, 3895, 3750, 4266, 3819, 3645, 3989, 3963, - 3991, 1780, 3959, 1780, 3206, 2486, 1703, 2631, 216, 3, - 1541, 1109, 78, 146, 3971, 3975, 950, 951, 952, 953, - 2, 1218, 4306, 4307, 1, 4021, 3994, 2885, 1963, 1443, - 954, 949, 1596, 4015, 2663, 2205, 1624, 699, 1967, 956, - 3158, 3159, 1228, 3506, 2638, 2642, 2643, 2644, 2639, 2647, - 2640, 2645, 3161, 4038, 2641, 2912, 2646, 4005, 4040, 2311, - 4044, 3122, 2616, 2472, 3366, 1512, 1019, 1893, 1739, 1242, - 4013, 1736, 1241, 4018, 4016, 1239, 3773, 4017, 1838, 1914, - 4030, 827, 3981, 3982, 2275, 3106, 1228, 3080, 4034, 3942, - 4292, 4320, 4254, 4295, 1757, 811, 4190, 3536, 3204, 1577, - 4089, 4258, 4091, 3962, 2316, 1298, 3211, 1589, 1620, 1042, - 3440, 4051, 1316, 1315, 1325, 1326, 1327, 1328, 1318, 1319, - 1320, 1321, 1322, 1323, 1324, 1317, 870, 838, 1626, 1370, - 1713, 3271, 3269, 837, 3620, 2945, 4060, 3947, 3177, 4023, - 1043, 2656, 2253, 4086, 4074, 3960, 1674, 1678, 2530, 4031, - 4145, 3875, 1618, 3425, 3016, 1702, 4140, 3671, 3786, 3784, - 3785, 738, 2184, 668, 1093, 4105, 4118, 3916, 2493, 2510, - 3921, 4054, 993, 4085, 3603, 2481, 994, 986, 2514, 2515, - 4113, 2964, 4114, 2963, 1797, 1307, 1816, 3290, 2517, 2518, - 3291, 1347, 782, 4081, 4082, 2345, 1111, 2942, 3694, 4127, - 3171, 77, 76, 75, 1780, 74, 4115, 237, 2170, 829, - 236, 4123, 3986, 3835, 4185, 4297, 146, 4121, 808, 807, - 806, 805, 804, 803, 2636, 2637, 1228, 4144, 2635, 2633, - 4129, 2632, 2166, 2165, 3183, 3517, 2232, 2234, 4170, 3382, - 3045, 3720, 3040, 2090, 2088, 1587, 1620, 4138, 2559, 4179, - 4143, 2566, 2087, 4235, 4186, 3552, 3776, 4159, 4161, 4163, - 4165, 4155, 4152, 4156, 3892, 4187, 3090, 3772, 2027, 2555, - 2107, 3061, 2104, 2103, 3053, 3888, 4158, 3882, 2135, 3683, - 4019, 3848, 4178, 3678, 3679, 3685, 2491, 1162, 1158, 1160, - 1618, 4188, 1161, 1159, 2818, 4193, 3631, 3632, 3633, 1620, - 4207, 4195, 4021, 3638, 3639, 3482, 4211, 2536, 3343, 2928, - 2927, 2925, 2924, 1481, 4208, 4117, 4212, 3816, 4226, 2687, - 3695, 2685, 1209, 3495, 4234, 3491, 1451, 1449, 4217, 2283, - 3500, 4219, 3143, 3686, 2270, 4218, 4220, 4221, 3208, 3554, - 2167, 2163, 2162, 1618, 3681, 1133, 3556, 3557, 1132, 3703, - 3704, 1655, 3322, 3324, 2728, 3682, 46, 3124, 4243, 2626, - 4244, 4250, 4245, 3996, 4246, 2032, 4247, 987, 2479, 112, - 42, 125, 111, 191, 3565, 61, 3567, 4261, 190, 4263, - 4264, 60, 18, 123, 4253, 3577, 188, 1228, 4259, 4257, - 59, 106, 105, 122, 186, 3687, 4105, 4267, 58, 221, - 4268, 220, 223, 222, 219, 2738, 2739, 218, 4272, 1662, - 217, 4044, 4200, 3851, 4181, 4274, 4275, 4273, 944, 45, - 4278, 4281, 4279, 4291, 44, 192, 4299, 43, 113, 4298, - 62, 41, 40, 39, 35, 13, 12, 36, 23, 22, - 1744, 21, 1228, 4303, 4285, 4286, 4287, 4288, 27, 33, - 32, 139, 138, 4309, 31, 4310, 137, 4312, 136, 4144, - 146, 135, 4318, 134, 133, 4322, 132, 131, 4319, 30, - 20, 53, 52, 146, 51, 3869, 50, 49, 48, 9, - 127, 126, 121, 119, 29, 120, 4330, 117, 118, 116, - 1990, 1991, 115, 114, 109, 4299, 4338, 107, 4298, 4337, - 89, 3702, 88, 2545, 87, 102, 101, 4322, 4339, 100, - 99, 98, 97, 4343, 95, 96, 1041, 86, 85, 84, - 2021, 83, 82, 104, 110, 2026, 108, 93, 3691, 1316, - 1315, 1325, 1326, 1327, 1328, 1318, 1319, 1320, 1321, 1322, - 1323, 1324, 1317, 103, 94, 92, 91, 90, 81, 4270, - 3688, 3692, 3690, 3689, 1959, 80, 79, 171, 170, 169, - 168, 174, 212, 173, 203, 175, 167, 165, 166, 164, - 1959, 163, 162, 3742, 161, 160, 3744, 159, 54, 55, - 56, 204, 57, 182, 181, 183, 185, 187, 195, 184, - 189, 179, 205, 177, 180, 178, 176, 71, 3752, 2085, - 2086, 3697, 3698, 11, 1780, 2170, 2170, 2170, 2170, 2170, - 2170, 144, 124, 19, 1030, 4, 0, 0, 0, 0, - 0, 0, 2170, 0, 0, 0, 130, 0, 0, 0, - 0, 0, 0, 0, 0, 208, 0, 0, 2997, 0, - 0, 0, 0, 3000, 0, 3937, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3705, 0, 0, 2214, - 0, 0, 0, 0, 0, 2214, 2214, 2214, 0, 3684, - 0, 0, 3696, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1026, 1027, 0, 0, - 3867, 0, 0, 0, 0, 0, 0, 1070, 0, 0, - 0, 0, 0, 0, 3265, 0, 0, 0, 0, 0, - 146, 0, 0, 0, 0, 146, 0, 0, 0, 0, - 0, 0, 0, 0, 153, 154, 0, 155, 156, 0, - 0, 0, 157, 0, 0, 158, 0, 0, 0, 0, - 0, 0, 0, 146, 1316, 1315, 1325, 1326, 1327, 1328, - 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1317, 1316, 1315, - 1325, 1326, 1327, 1328, 1318, 1319, 1320, 1321, 1322, 1323, - 1324, 1317, 750, 749, 756, 746, 0, 0, 0, 0, - 2808, 0, 0, 0, 0, 753, 754, 0, 755, 759, - 0, 1072, 740, 0, 1071, 0, 172, 201, 210, 202, - 72, 128, 764, 3701, 1316, 1315, 1325, 1326, 1327, 1328, - 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1317, 0, 0, - 200, 194, 193, 0, 0, 0, 0, 73, 0, 0, - 0, 0, 0, 1056, 0, 0, 0, 0, 0, 0, - 0, 4063, 4064, 1031, 0, 152, 0, 2338, 4068, 4069, - 4070, 0, 0, 0, 4072, 4073, 0, 4075, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1033, 1316, 1315, 1325, 1326, 1327, 1328, 1318, 1319, 1320, - 1321, 1322, 1323, 1324, 1317, 0, 3700, 0, 196, 197, - 198, 0, 0, 750, 749, 756, 746, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 753, 754, 0, 755, - 759, 0, 0, 740, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 764, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4128, 0, 0, 0, 206, - 4132, 4133, 0, 1109, 0, 146, 1055, 1053, 0, 0, - 0, 146, 0, 0, 0, 0, 146, 0, 0, 0, - 140, 0, 0, 2170, 199, 0, 141, 0, 0, 768, - 0, 4153, 770, 0, 0, 1052, 0, 769, 0, 0, - 0, 146, 0, 0, 0, 0, 0, 1025, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1032, 1065, - 0, 0, 0, 0, 0, 0, 741, 743, 742, 0, - 2450, 0, 2452, 0, 0, 0, 0, 0, 748, 0, - 1061, 142, 750, 749, 756, 746, 0, 0, 0, 0, - 752, 2469, 2470, 2471, 65, 753, 754, 767, 755, 759, - 0, 0, 740, 0, 745, 0, 2487, 2488, 2489, 2490, - 0, 0, 764, 0, 0, 0, 1062, 1066, 0, 0, - 1357, 1316, 1315, 1325, 1326, 1327, 1328, 1318, 1319, 1320, - 1321, 1322, 1323, 1324, 1317, 0, 1049, 0, 1047, 1051, - 1069, 0, 0, 68, 1048, 1045, 1044, 0, 1050, 1035, - 1036, 1034, 1037, 1038, 1039, 1040, 0, 1067, 768, 1068, - 0, 770, 0, 0, 0, 0, 769, 0, 0, 0, - 1063, 1064, 1302, 1303, 1304, 1301, 0, 0, 3410, 150, - 209, 0, 151, 3412, 3413, 0, 0, 741, 743, 742, - 4151, 63, 0, 0, 0, 0, 0, 0, 0, 748, - 0, 0, 0, 0, 0, 0, 0, 0, 1059, 0, - 0, 752, 0, 0, 1058, 0, 0, 0, 767, 0, - 0, 0, 0, 0, 0, 745, 0, 0, 1054, 735, - 0, 0, 0, 0, 747, 751, 757, 0, 758, 760, - 0, 1589, 761, 762, 763, 0, 0, 0, 765, 766, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1871, 0, 0, 0, 143, 47, 0, 0, - 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1626, 4231, - 0, 0, 0, 0, 0, 0, 147, 148, 0, 0, - 149, 0, 0, 2214, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 3488, 0, 1057, 741, 743, 742, 0, - 0, 1028, 1029, 0, 1023, 0, 0, 0, 748, 1024, - 0, 0, 0, 0, 0, 3504, 0, 0, 0, 0, - 752, 0, 0, 0, 1181, 0, 0, 767, 0, 0, - 0, 0, 0, 0, 745, 747, 751, 757, 0, 758, - 760, 0, 0, 761, 762, 763, 0, 0, 4231, 765, - 766, 0, 0, 0, 146, 0, 0, 0, 0, 0, - 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2136, 0, 0, 0, 0, - 2097, 744, 0, 2144, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4231, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2138, 2106, 0, 0, 2170, 0, 0, - 0, 0, 0, 2139, 2140, 0, 0, 0, 0, 1867, - 0, 0, 0, 0, 0, 0, 1864, 0, 0, 0, - 1866, 1863, 1865, 1869, 1870, 0, 0, 0, 1868, 2105, - 0, 0, 0, 1830, 1831, 0, 4341, 0, 1199, 1200, - 1166, 0, 0, 0, 747, 751, 757, 2113, 758, 760, - 0, 0, 761, 762, 763, 0, 0, 0, 765, 766, - 0, 1189, 1193, 1195, 1197, 1202, 0, 1207, 1203, 1204, - 1205, 1206, 0, 1184, 1185, 1186, 1187, 1164, 1165, 1190, - 0, 1167, 744, 1169, 1170, 1171, 1172, 1168, 1173, 1174, - 1175, 1176, 1177, 1180, 1182, 1178, 1179, 1188, 2908, 2909, - 0, 0, 0, 0, 0, 1192, 1194, 1196, 1198, 1201, + 1812, 1813, 2992, 1743, 951, 952, 953, 954, 1827, 1828, + 1781, 1263, 1742, 3446, 3612, 3550, 1889, 1890, 1891, 1975, + 1142, 4253, 1219, 1139, 4250, 1085, 4244, 1229, 1301, 1905, + 1797, 2976, 1906, 1775, 1219, 1759, 4226, 2650, 2650, 1982, + 4279, 3490, 1983, 719, 1985, 1884, 719, 719, 701, 701, + 1729, 1925, 1926, 1732, 4279, 1956, 1998, 2000, 1908, 2001, + 1754, 2003, 2004, 2428, 1263, 690, 1649, 1712, 1301, 1265, + 4186, 2012, 1621, 2017, 2018, 2790, 2020, 1584, 701, 1955, + 4185, 715, 1753, 701, 715, 715, 1621, 1749, 4169, 1772, + 1018, 4144, 1898, 2045, 1752, 1748, 717, 2476, 1751, 717, + 717, 4132, 4079, 3459, 1777, 3457, 4254, 3296, 1621, 4251, + 3339, 2355, 718, 1750, 1584, 718, 718, 2552, 2992, 714, + 2790, 4227, 2547, 2541, 2546, 1818, 2544, 2549, 1959, 716, + 4078, 3308, 716, 716, 1303, 1304, 1305, 1302, 2536, 2073, + 1730, 2307, 3306, 1733, 1734, 4061, 4060, 2038, 2080, 2080, + 2650, 1584, 4059, 1584, 1584, 1301, 4058, 701, 701, 2236, + 2147, 3182, 2012, 2152, 4038, 1301, 1621, 2156, 2157, 4037, + 956, 2774, 2172, 2355, 671, 2354, 2316, 1872, 1814, 1815, + 2893, 2550, 1825, 1826, 1962, 1301, 4133, 4080, 671, 1967, + 1621, 2021, 3297, 1136, 1137, 1138, 1141, 1429, 1140, 2521, + 2077, 951, 952, 953, 954, 1303, 1304, 1305, 1302, 4012, + 3730, 1764, 3676, 2765, 2019, 2503, 3294, 701, 2012, 1621, + 2307, 2219, 2174, 701, 701, 701, 731, 731, 1913, 1914, + 2355, 2355, 2534, 2229, 2230, 2231, 2232, 2355, 2041, 3638, + 2238, 2355, 2433, 1303, 1304, 1305, 1302, 229, 3574, 2316, + 229, 229, 2427, 229, 2316, 2210, 2008, 2009, 2010, 2150, + 2016, 1957, 2426, 2353, 2102, 2083, 1112, 2006, 2023, 2024, + 2025, 2026, 1306, 3570, 2032, 3467, 2388, 2387, 2148, 1972, + 1339, 1976, 1963, 2386, 1632, 2298, 1980, 2202, 2203, 1349, + 1303, 1304, 1305, 1302, 2355, 2682, 2054, 3677, 1899, 1899, + 2285, 3295, 2205, 2179, 2158, 2181, 1509, 2292, 1837, 2221, + 2222, 2223, 1607, 2007, 2234, 1358, 2200, 2201, 3158, 4344, + 4327, 3663, 3186, 2984, 3639, 2195, 2188, 2061, 2870, 2063, + 2064, 2548, 2551, 3575, 2042, 2066, 2267, 2046, 2994, 2082, + 2902, 2045, 2858, 2070, 2793, 1621, 2305, 2071, 2520, 2792, + 2056, 2784, 2850, 2806, 2155, 1534, 2528, 2062, 3571, 2218, + 3468, 2084, 2085, 2374, 2788, 1868, 1265, 956, 2173, 1538, + 2048, 2049, 1865, 2776, 2286, 720, 1867, 1864, 1866, 1870, + 1871, 1538, 2771, 2359, 1869, 2297, 2149, 2079, 2081, 1303, + 1304, 1305, 1302, 2246, 2756, 2754, 2249, 2250, 2154, 2252, + 2241, 2299, 3620, 2650, 2057, 2058, 2421, 1775, 2772, 2160, + 2047, 2752, 3940, 2503, 2189, 2178, 2750, 2180, 2227, 1977, + 1726, 2067, 2068, 1303, 1304, 1305, 1302, 1301, 1303, 1304, + 1305, 1302, 2065, 1303, 1304, 1305, 1302, 1301, 1301, 2502, + 2280, 2078, 2216, 1109, 2217, 1355, 2255, 3268, 2072, 2503, + 2429, 2075, 2076, 2395, 1250, 2394, 2224, 2225, 2777, 1111, + 1214, 1576, 1577, 1209, 1579, 1580, 1581, 2772, 1585, 1586, + 1587, 2330, 2243, 1677, 1676, 2377, 1112, 2368, 2552, 2757, + 2755, 3267, 2367, 2547, 2541, 2546, 2425, 2544, 2549, 2366, + 3728, 2422, 2356, 2260, 2342, 2341, 2751, 2334, 2335, 2315, + 1735, 2751, 1636, 1637, 1638, 1639, 1640, 2204, 1642, 1643, + 1644, 1645, 1646, 1337, 1336, 1318, 1652, 1653, 1654, 1655, + 4137, 3396, 973, 2045, 2503, 1888, 1887, 1875, 1876, 1877, + 1878, 1879, 1880, 1873, 1874, 2428, 3410, 1535, 1301, 2296, + 1301, 3859, 2550, 719, 1611, 1109, 1888, 1887, 2294, 3652, + 3231, 3650, 4338, 1520, 2440, 1612, 2442, 1521, 2444, 2445, + 1301, 1111, 1301, 3780, 2300, 2343, 4138, 1301, 701, 1584, + 701, 1584, 2389, 2390, 1301, 2392, 4306, 2355, 1112, 2313, + 2461, 715, 2399, 2411, 2316, 1736, 779, 3860, 2357, 701, + 701, 701, 4028, 2329, 2576, 3653, 717, 3651, 1303, 1304, + 1305, 1302, 3397, 4114, 701, 701, 701, 701, 2338, 4073, + 4011, 3967, 718, 3922, 3889, 1818, 3888, 2827, 2828, 3874, + 1899, 1899, 2331, 1659, 2821, 3834, 3630, 2507, 1609, 716, + 3491, 3482, 2508, 2509, 2510, 1566, 2513, 1584, 2347, 2419, + 2295, 1931, 2412, 2414, 2415, 2416, 3474, 2418, 3398, 3469, + 3374, 1208, 1204, 1205, 1206, 1207, 2351, 2826, 1536, 2825, + 2824, 2822, 1924, 1584, 3117, 3116, 1303, 1304, 1305, 1302, + 1824, 2332, 2333, 1321, 1322, 1323, 1324, 1325, 1318, 980, + 2570, 2038, 4029, 2452, 2955, 2454, 1821, 1823, 1820, 3779, + 1822, 2898, 2803, 826, 146, 1920, 1921, 1922, 1923, 146, + 2775, 1927, 1928, 1929, 1930, 1932, 1933, 1934, 1935, 1936, + 1937, 1938, 1939, 1940, 1941, 1942, 1319, 1320, 1321, 1322, + 1323, 1324, 1325, 1318, 2420, 2673, 2446, 2289, 4030, 2525, + 2823, 2288, 1608, 2527, 2577, 2529, 2287, 1505, 1520, 701, + 2080, 2430, 1521, 1303, 1304, 1305, 1302, 1504, 2654, 2654, + 2172, 2654, 1231, 2742, 3525, 3522, 2813, 2736, 2496, 2244, + 3326, 697, 2280, 1841, 1841, 1109, 2348, 1665, 146, 2244, + 3187, 671, 671, 2002, 2443, 1305, 1302, 2530, 2447, 1229, + 4205, 1111, 1302, 3901, 3900, 1621, 701, 1303, 1304, 1305, + 1302, 1787, 1788, 1789, 1790, 1791, 3523, 3399, 1112, 3053, + 1112, 701, 2467, 3051, 2540, 3030, 3028, 1229, 2726, 690, + 2539, 1303, 1304, 1305, 1302, 1660, 3880, 2172, 4258, 1665, + 2732, 4334, 2734, 2954, 1378, 229, 4176, 4177, 2677, 4063, + 4064, 2497, 2500, 2880, 2499, 2881, 1838, 4225, 2728, 4224, + 1842, 1843, 1844, 1845, 1357, 2514, 2656, 1903, 2660, 4179, + 1883, 2668, 2533, 2669, 3835, 3836, 2517, 1356, 1893, 4178, + 3260, 2523, 1904, 2658, 2524, 1303, 1304, 1305, 1302, 2779, + 2526, 3828, 2674, 2675, 2815, 4175, 2662, 3618, 2786, 4174, + 4173, 2305, 2553, 2554, 3104, 2559, 4333, 2684, 1621, 4171, + 1621, 4170, 1621, 4139, 3102, 1109, 3100, 1229, 1303, 1304, + 1305, 1302, 1110, 3089, 1538, 2805, 2923, 146, 4051, 2746, + 1947, 1111, 1949, 1950, 1951, 1952, 1953, 4041, 4031, 2689, + 3958, 1960, 146, 3259, 146, 3862, 2370, 3861, 1112, 3805, + 2731, 3829, 3668, 2796, 3654, 1621, 1229, 3619, 1725, 2623, + 2834, 1379, 2629, 3617, 3103, 2522, 3364, 3227, 2515, 2516, + 1303, 1304, 1305, 1302, 3101, 2841, 3099, 3199, 2518, 2519, + 1621, 2663, 3198, 3088, 3087, 1600, 1602, 814, 824, 2690, + 2829, 2737, 3086, 3085, 3077, 2767, 2768, 815, 1619, 816, + 820, 823, 819, 817, 818, 3071, 2678, 3070, 2681, 2840, + 1303, 1304, 1305, 1302, 1603, 2842, 2369, 3069, 3068, 2738, + 2894, 2758, 2670, 1619, 2432, 2263, 1303, 1304, 1305, 1302, + 2262, 2727, 2261, 2730, 2050, 1666, 2257, 2256, 2211, 2847, + 2848, 2763, 2900, 1303, 1304, 1305, 1302, 2904, 2220, 2906, + 1986, 1984, 1727, 2362, 2802, 1447, 701, 701, 3624, 3629, + 2069, 2816, 4235, 2818, 821, 2761, 3351, 2797, 4004, 4005, + 1229, 1303, 1304, 1305, 1302, 2843, 4336, 1621, 4330, 2800, + 1584, 2811, 1212, 2832, 4292, 4328, 1584, 2152, 3769, 1303, + 1304, 1305, 1302, 4304, 3797, 822, 1775, 2789, 2787, 4156, + 2794, 4271, 4212, 4211, 2987, 2990, 1303, 1304, 1305, 1302, + 3990, 2995, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1307, + 1960, 1303, 1304, 1305, 1302, 1960, 1960, 4191, 3020, 3005, + 4124, 3839, 2291, 4118, 2807, 2808, 2872, 3246, 2873, 1229, + 2875, 1211, 2877, 2878, 2729, 2884, 2830, 3027, 2972, 2820, + 1303, 1304, 1305, 1302, 1229, 1229, 1229, 2080, 4099, 3794, + 1229, 4090, 3037, 3038, 3039, 3040, 1229, 3047, 4068, 3048, + 3049, 4067, 3050, 4055, 3052, 2245, 4050, 4049, 2248, 4008, + 3994, 2251, 2689, 2969, 2253, 3047, 1303, 1304, 1305, 1302, + 2967, 3992, 3959, 4152, 2952, 2352, 3882, 2654, 3793, 3843, + 2968, 3832, 2885, 4168, 3006, 3817, 2982, 2810, 3816, 3812, + 3810, 3105, 3804, 3800, 3783, 1303, 1304, 1305, 1302, 3782, + 3799, 671, 3796, 2273, 3986, 1303, 1304, 1305, 1302, 2152, + 3795, 3771, 2690, 1229, 2172, 2172, 2172, 2172, 2172, 2172, + 2102, 1303, 1304, 1305, 1302, 3008, 1303, 1304, 1305, 1302, + 1229, 2172, 2996, 3767, 2654, 2934, 3025, 2936, 3110, 3765, + 3025, 2933, 3737, 3734, 2950, 2016, 3021, 1112, 3732, 3109, + 3166, 2975, 1621, 1303, 1304, 1305, 1302, 2350, 2989, 3614, + 3596, 3032, 8, 701, 701, 2986, 3583, 7, 1316, 1326, + 1327, 1328, 1329, 1319, 1320, 1321, 1322, 1323, 1324, 1325, + 1318, 3022, 3985, 3562, 2853, 2854, 3560, 3010, 3554, 3007, + 2859, 3539, 3023, 3781, 3502, 3480, 3022, 3033, 3034, 3029, + 3479, 3477, 3036, 3035, 1303, 1304, 1305, 1302, 3043, 3476, + 3470, 3154, 3465, 4291, 3464, 3026, 3004, 3375, 3337, 229, + 1303, 1304, 1305, 1302, 229, 3336, 3327, 2344, 3320, 3122, + 3315, 2349, 3067, 3079, 3167, 1303, 1304, 1305, 1302, 2358, + 1326, 1327, 1328, 1329, 1319, 1320, 1321, 1322, 1323, 1324, + 1325, 1318, 3313, 1899, 2437, 1899, 3241, 3238, 3220, 3225, + 3197, 3173, 3098, 3112, 3090, 3226, 3080, 3078, 3118, 3074, + 3073, 1621, 3072, 2912, 3233, 3134, 2365, 3135, 3136, 3137, + 3138, 3139, 3140, 3183, 2372, 2903, 2895, 3151, 3155, 2997, + 3157, 2783, 3134, 892, 891, 3115, 2762, 2462, 3002, 3003, + 2450, 3174, 2449, 146, 146, 146, 1110, 3171, 2998, 2266, + 2259, 3215, 2391, 3001, 1970, 1969, 3156, 2396, 2397, 2398, + 1728, 1386, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, + 2409, 2410, 1382, 3175, 2582, 1381, 1215, 2585, 2586, 2587, + 2588, 2589, 2590, 2591, 960, 3972, 2594, 2595, 2596, 2597, + 2598, 2599, 2600, 2601, 2602, 2603, 2604, 3968, 2606, 2607, + 2608, 2609, 2610, 3798, 2611, 3188, 1685, 1959, 1692, 1693, + 3192, 3189, 3219, 1700, 3777, 3190, 1686, 1687, 3747, 1697, + 3314, 3645, 1701, 3317, 1338, 3644, 3642, 3611, 701, 1584, + 3208, 3716, 3579, 3235, 3217, 3216, 3328, 3329, 3330, 3332, + 3211, 3334, 3335, 3218, 3213, 3577, 3229, 3576, 3573, 3572, + 1229, 3230, 3561, 3204, 174, 212, 1229, 3242, 1303, 1304, + 1305, 1302, 3354, 3559, 3543, 3528, 174, 212, 174, 212, + 1112, 3243, 3368, 3527, 174, 212, 3513, 701, 3512, 3258, + 3556, 3403, 3341, 2170, 174, 212, 2040, 3338, 1718, 3305, + 3265, 3385, 1229, 3298, 3256, 701, 3248, 701, 1229, 1229, + 3254, 3255, 3269, 3247, 3251, 3245, 3253, 1303, 1304, 1305, + 1302, 3181, 2172, 2507, 2753, 3409, 2037, 3307, 1715, 2749, + 1303, 1304, 1305, 1302, 3400, 3252, 2748, 2400, 208, 1303, + 1304, 1305, 1302, 2570, 3214, 3249, 3250, 2393, 3263, 3378, + 2039, 212, 1717, 3322, 2385, 3434, 3311, 3437, 208, 3437, + 3437, 2384, 700, 3388, 1229, 2383, 3312, 703, 208, 3393, + 2382, 2380, 3381, 2376, 3401, 1303, 1304, 1305, 1302, 3262, + 174, 212, 3460, 3261, 2375, 2373, 3456, 2869, 2364, 2361, + 1621, 1621, 2360, 1435, 2265, 1948, 3356, 1946, 1945, 3417, + 1944, 2967, 3421, 3423, 1943, 3412, 1303, 1304, 1305, 1302, + 1303, 1304, 1305, 1302, 1303, 1304, 1305, 1302, 1902, 1960, + 1901, 1960, 3340, 1892, 208, 3461, 3462, 1633, 3022, 3377, + 144, 1631, 4257, 1619, 1619, 3407, 4184, 701, 1376, 3387, + 1960, 1960, 4151, 4085, 3354, 3391, 3392, 1109, 4082, 4057, + 3433, 3408, 4052, 3953, 208, 3952, 3402, 1584, 3917, 3416, + 2152, 2152, 3442, 1111, 3022, 3432, 3899, 700, 3404, 3895, + 3022, 3022, 2540, 3873, 1659, 3856, 3748, 3745, 2539, 3714, + 1112, 3713, 1112, 3710, 3709, 3438, 3439, 3675, 1112, 3274, + 3275, 3443, 2868, 1112, 3672, 3276, 3277, 3278, 3279, 3458, + 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, + 3290, 3670, 3632, 1229, 3257, 1680, 1691, 2834, 1112, 1303, + 1304, 1305, 1302, 3466, 1682, 3526, 3022, 2778, 1696, 2781, + 1699, 1688, 1512, 703, 3145, 212, 173, 203, 175, 3106, + 3031, 174, 212, 173, 203, 175, 2978, 2977, 2970, 2935, + 3440, 2941, 1630, 2867, 2871, 2770, 697, 2866, 2672, 3471, + 3487, 3488, 2612, 2501, 3473, 4166, 2865, 3472, 3475, 2469, + 701, 3485, 3478, 3481, 2468, 2431, 1819, 3498, 208, 3499, + 1303, 1304, 1305, 1302, 1303, 1304, 1305, 1302, 2814, 2226, + 1966, 2817, 146, 1303, 1304, 1305, 1302, 1760, 1719, 3506, + 1689, 1446, 2835, 2836, 2864, 3509, 3510, 3511, 208, 1431, + 2838, 2839, 1427, 1426, 1425, 208, 1424, 1423, 1422, 892, + 3516, 1746, 1421, 1420, 1419, 2689, 2844, 2845, 2846, 3415, + 1418, 1303, 1304, 1305, 1302, 1417, 1416, 1415, 3411, 1414, + 1413, 3536, 1412, 3413, 3414, 1411, 1410, 3585, 1409, 1408, + 1407, 2238, 1406, 1405, 3059, 3060, 1404, 1403, 1402, 1401, + 2874, 3597, 2876, 1400, 146, 2879, 3603, 1787, 1960, 3075, + 3076, 3563, 1399, 1398, 1397, 2690, 3547, 1396, 1395, 146, + 2863, 1394, 146, 146, 1393, 3544, 1392, 3552, 2862, 1389, + 1388, 1387, 3604, 2861, 1385, 3113, 146, 1384, 3546, 4164, + 2860, 701, 2152, 1383, 3598, 1380, 3600, 1303, 1304, 1305, + 1302, 1373, 1372, 3637, 1370, 1303, 1304, 1305, 1302, 1369, + 1303, 1304, 1305, 1302, 1368, 1367, 3589, 1303, 1304, 1305, + 1302, 1366, 3610, 1365, 1364, 2654, 2172, 3660, 2857, 3613, + 1363, 1362, 3580, 3565, 1361, 3567, 3584, 3569, 1360, 1359, + 1354, 1353, 3586, 1352, 1351, 1350, 1267, 1213, 4162, 3678, + 2999, 3000, 1229, 3494, 3495, 1303, 1304, 1305, 1302, 2856, + 3711, 3434, 3607, 3489, 2512, 1229, 172, 201, 210, 202, + 2483, 3153, 1255, 3608, 2855, 4284, 4282, 3625, 1229, 4240, + 3727, 3497, 2956, 2683, 1621, 3505, 1303, 1304, 1305, 1302, + 200, 3636, 3627, 2495, 1266, 3143, 2849, 3662, 3504, 3503, + 3643, 1303, 1304, 1305, 1302, 701, 3142, 2152, 3148, 3146, + 3500, 1229, 3152, 3149, 3147, 3150, 3708, 2644, 2645, 3729, + 3750, 3141, 3658, 1303, 1304, 1305, 1302, 1619, 4204, 4101, + 3751, 3878, 2985, 2773, 3669, 3665, 3671, 2837, 1506, 3659, + 3373, 1112, 129, 3210, 229, 2833, 2034, 2035, 1112, 2029, + 2030, 2031, 70, 3430, 69, 3431, 3715, 3738, 3701, 3741, + 3720, 3657, 66, 3717, 1303, 1304, 1305, 1302, 3541, 3542, + 3726, 2812, 1303, 1304, 1305, 1302, 2983, 2424, 2580, 3731, + 3749, 3721, 3733, 3753, 3517, 2139, 1674, 3735, 2423, 3736, + 1711, 3739, 1960, 2801, 3742, 2456, 3928, 1708, 1303, 1304, + 1305, 1302, 2463, 3740, 1303, 1304, 1305, 1302, 2417, 2228, + 692, 701, 3755, 1261, 3679, 1303, 1304, 1305, 1302, 1836, + 693, 3775, 694, 3814, 2767, 2768, 3349, 3718, 3743, 3342, + 695, 3009, 3772, 1229, 2979, 1303, 1304, 1305, 1302, 2532, + 3043, 146, 2493, 3770, 4295, 2043, 1303, 1304, 1305, 1302, + 3055, 2005, 4054, 1229, 1621, 1621, 3792, 3056, 3057, 3058, + 3385, 3463, 3811, 2626, 3813, 1888, 1887, 1442, 1443, 1440, + 1441, 2619, 3191, 3134, 3193, 3851, 1229, 2153, 3851, 1575, + 3927, 1438, 1439, 1222, 1436, 1437, 1574, 1294, 1227, 3841, + 3760, 1229, 3867, 1229, 2290, 2273, 3515, 1619, 1834, 3802, + 1960, 3508, 3870, 3840, 3872, 1960, 3845, 3846, 2464, 2293, + 1621, 1256, 1527, 1526, 3824, 3823, 3822, 3842, 1497, 1550, + 3826, 4264, 3848, 4262, 3833, 2171, 4218, 2799, 701, 3825, + 1229, 1229, 3844, 3854, 1229, 1229, 2798, 4201, 3661, 4200, + 4198, 4128, 3819, 3855, 4086, 3244, 3664, 3948, 3662, 3947, + 3868, 3766, 3919, 1834, 2286, 3564, 3866, 3863, 3535, 3534, + 3914, 3519, 3876, 3520, 2270, 3708, 2045, 2565, 3879, 3945, + 3264, 2535, 3883, 1713, 3185, 1524, 3921, 4286, 4285, 4285, + 3903, 3904, 3954, 3955, 3915, 3916, 3228, 2908, 2907, 3875, + 1756, 209, 2901, 1757, 2363, 3022, 1621, 1252, 1226, 3881, + 146, 4286, 3897, 146, 146, 3752, 146, 3701, 3942, 2639, + 2643, 2644, 2645, 2640, 2648, 2641, 2646, 4268, 3941, 2642, + 3821, 2647, 3987, 3647, 3207, 2487, 3943, 1704, 1219, 1542, + 3978, 3966, 78, 3920, 216, 3, 2, 4308, 3134, 1619, + 4309, 1112, 951, 952, 953, 954, 1, 1219, 2886, 3961, + 1964, 1110, 3965, 1781, 3924, 1781, 3991, 1444, 3993, 2632, + 955, 950, 1597, 3973, 2664, 3977, 2206, 1625, 1968, 146, + 957, 3159, 3160, 3507, 3162, 2913, 2312, 4023, 3996, 3123, + 2617, 2473, 3367, 4017, 1513, 1020, 1894, 1740, 1243, 3784, + 1737, 3785, 1242, 1240, 1229, 1839, 2639, 2643, 2644, 2645, + 2640, 2648, 2641, 2646, 1915, 4040, 2642, 4007, 2647, 828, + 4046, 2276, 3107, 3081, 3944, 4294, 4322, 4256, 4297, 1758, + 812, 4192, 3537, 3205, 4018, 4091, 3775, 4260, 4020, 4015, + 4019, 4093, 3983, 3984, 4032, 3964, 4036, 2317, 1229, 1299, + 3212, 1043, 871, 839, 1371, 1714, 3272, 3270, 838, 3929, + 3930, 3622, 2946, 1338, 3949, 3178, 4025, 1044, 2254, 4088, + 1621, 3441, 4053, 3925, 3926, 3962, 3933, 3932, 3931, 3934, + 3935, 3936, 1675, 1679, 2531, 4033, 3937, 4147, 3877, 3426, + 3017, 1703, 4142, 3673, 3788, 3786, 3787, 3938, 4062, 3864, + 3865, 739, 2185, 669, 1094, 4076, 3918, 2494, 700, 2511, + 3923, 4056, 994, 1619, 3605, 2482, 995, 987, 2965, 2964, + 1798, 1308, 1817, 3291, 3292, 1348, 4107, 783, 4120, 2346, + 2943, 3696, 3172, 4087, 1317, 1316, 1326, 1327, 1328, 1329, + 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1318, 4115, 77, + 4116, 76, 75, 74, 4083, 4084, 237, 830, 1112, 4129, + 236, 3988, 3837, 4187, 4299, 2381, 1781, 809, 4117, 808, + 1578, 807, 806, 805, 804, 2637, 4125, 2638, 1590, 2636, + 2634, 4123, 2633, 2167, 2166, 3184, 3518, 4146, 1229, 2233, + 4131, 2235, 3383, 3046, 3722, 3041, 2091, 2089, 1588, 1627, + 4172, 2560, 2567, 2088, 4237, 3553, 3778, 4157, 1621, 4140, + 4158, 4181, 3894, 4145, 3091, 3774, 4188, 2028, 2556, 2108, + 3062, 4154, 4161, 4163, 4165, 4167, 2105, 2104, 3054, 3890, + 4189, 3884, 2136, 4021, 3850, 3680, 3681, 3687, 4160, 2492, + 1163, 1159, 1161, 4180, 1162, 1160, 2819, 3483, 2537, 3344, + 4190, 1619, 2929, 2928, 2926, 3633, 3634, 3635, 4197, 4195, + 2925, 1621, 3640, 3641, 4023, 1482, 4119, 4214, 4209, 3818, + 2688, 2686, 1210, 3496, 4213, 4210, 3492, 1452, 1450, 2284, + 4228, 3501, 3144, 1110, 2271, 146, 4236, 3209, 2168, 4219, + 2164, 2163, 1134, 4221, 1133, 1656, 4220, 3323, 3325, 46, + 3555, 3125, 2627, 3998, 1619, 2033, 988, 3557, 3558, 2480, + 4222, 4223, 112, 42, 125, 111, 191, 61, 190, 60, + 4245, 18, 4246, 4252, 4247, 123, 4248, 188, 4249, 59, + 106, 105, 122, 186, 58, 3566, 221, 3568, 220, 223, + 222, 219, 4263, 2739, 4265, 4266, 3578, 4255, 4259, 1229, + 4261, 2740, 218, 1663, 217, 4202, 3853, 4107, 4269, 4183, + 945, 45, 44, 192, 43, 113, 62, 41, 4270, 40, + 4274, 4046, 39, 35, 13, 12, 4275, 4277, 4276, 36, + 23, 4280, 22, 1745, 4283, 4293, 4281, 21, 4301, 27, + 33, 4300, 32, 139, 138, 31, 137, 136, 135, 134, + 133, 132, 131, 30, 1229, 20, 53, 52, 4305, 4287, + 4288, 4289, 4290, 2657, 4312, 4311, 51, 50, 49, 4146, + 4314, 48, 9, 127, 4320, 126, 121, 4324, 119, 29, + 4321, 120, 117, 118, 116, 115, 114, 109, 107, 89, + 88, 87, 102, 1182, 101, 100, 99, 98, 4332, 97, + 95, 96, 1042, 86, 85, 84, 83, 4301, 4340, 82, + 4300, 4339, 104, 110, 108, 93, 103, 94, 92, 4324, + 4341, 1331, 91, 1335, 90, 4345, 81, 80, 79, 171, + 2171, 170, 169, 168, 167, 165, 166, 164, 146, 1332, + 1334, 1330, 163, 1333, 1317, 1316, 1326, 1327, 1328, 1329, + 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1318, 162, 161, + 160, 4272, 159, 54, 55, 1960, 56, 57, 182, 181, + 174, 212, 173, 203, 175, 183, 185, 187, 184, 189, + 179, 1960, 177, 180, 3744, 178, 176, 3746, 71, 11, + 204, 124, 19, 4, 0, 0, 0, 195, 0, 0, + 0, 205, 0, 0, 0, 0, 0, 0, 0, 3754, + 0, 1991, 1992, 0, 0, 0, 1781, 0, 0, 0, + 144, 0, 1831, 1832, 0, 0, 0, 1200, 1201, 1167, + 0, 0, 0, 0, 0, 130, 0, 0, 0, 0, + 0, 2022, 0, 0, 208, 0, 2027, 4042, 0, 0, + 1190, 1194, 1196, 1198, 1203, 3939, 1208, 1204, 1205, 1206, + 1207, 0, 1185, 1186, 1187, 1188, 1165, 1166, 1191, 0, + 1168, 0, 1170, 1171, 1172, 1173, 1169, 1174, 1175, 1176, + 1177, 1178, 1181, 1183, 1179, 1180, 1189, 0, 0, 0, + 0, 3871, 0, 0, 1193, 1195, 1197, 1199, 1202, 0, + 0, 1317, 1316, 1326, 1327, 1328, 1329, 1319, 1320, 1321, + 1322, 1323, 1324, 1325, 1318, 0, 0, 0, 0, 0, + 2086, 2087, 0, 0, 0, 0, 0, 0, 1031, 0, + 0, 0, 0, 153, 154, 1184, 155, 156, 2809, 0, + 0, 157, 0, 0, 158, 1317, 1316, 1326, 1327, 1328, + 1329, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1318, 3869, + 0, 0, 1317, 1316, 1326, 1327, 1328, 1329, 1319, 1320, + 1321, 1322, 1323, 1324, 1325, 1318, 0, 0, 0, 0, + 2215, 0, 146, 3266, 0, 0, 2215, 2215, 2215, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2129, 0, 0, - 771, 772, 773, 774, 775, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1183, 2987, 3659, 0, - 0, 0, 0, 0, 0, 0, 3662, 0, 0, 0, - 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, - 1862, 1874, 1875, 1876, 1877, 1878, 1879, 1872, 1873, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2096, - 2098, 2095, 0, 0, 0, 2092, 0, 0, 0, 0, - 2117, 744, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2123, 0, 0, 0, 0, 0, 0, 0, 2108, - 0, 2091, 0, 146, 0, 0, 0, 0, 0, 0, - 0, 2111, 2145, 0, 0, 2112, 2114, 2116, 0, 2118, - 2119, 2120, 2124, 2125, 2126, 2128, 2131, 2132, 2133, 771, - 772, 773, 774, 775, 0, 0, 2121, 2130, 2122, 2136, - 0, 0, 0, 0, 2097, 0, 0, 2144, 2100, 0, + 1027, 1028, 0, 0, 0, 172, 201, 210, 202, 72, + 128, 1071, 0, 1317, 1316, 1326, 1327, 1328, 1329, 1319, + 1320, 1321, 1322, 1323, 1324, 1325, 1318, 0, 0, 200, + 194, 193, 0, 0, 0, 0, 73, 1317, 1316, 1326, + 1327, 1328, 1329, 1319, 1320, 1321, 1322, 1323, 1324, 1325, + 1318, 4065, 4066, 2339, 152, 0, 0, 0, 4070, 4071, + 4072, 0, 0, 0, 4074, 4075, 0, 4077, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1317, 1316, 1326, + 1327, 1328, 1329, 1319, 1320, 1321, 1322, 1323, 1324, 1325, + 1318, 0, 0, 0, 0, 0, 0, 196, 197, 198, + 0, 0, 0, 0, 0, 1073, 0, 0, 1072, 1317, + 1316, 1326, 1327, 1328, 1329, 1319, 1320, 1321, 1322, 1323, + 1324, 1325, 1318, 0, 0, 0, 0, 2171, 2171, 2171, + 2171, 2171, 2171, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2171, 4130, 0, 1057, 0, 206, + 4134, 4135, 0, 0, 0, 0, 0, 1032, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 199, 0, 141, 0, 0, 0, + 0, 4155, 0, 0, 1034, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 751, 750, 757, 747, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 754, 755, 0, + 756, 760, 0, 0, 741, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 765, 0, 0, 0, 0, 0, + 0, 142, 146, 0, 0, 0, 0, 146, 1192, 0, + 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1056, 1054, 0, 0, 146, 0, 0, 0, 0, + 769, 0, 1358, 771, 0, 0, 0, 0, 770, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1053, 0, 0, 68, 0, 0, 0, 0, 1872, 0, + 0, 0, 1026, 0, 0, 0, 0, 0, 751, 750, + 757, 747, 0, 1033, 1066, 0, 0, 0, 0, 0, + 0, 754, 755, 0, 756, 760, 0, 0, 741, 150, + 209, 2451, 151, 2453, 0, 1062, 0, 0, 765, 0, + 0, 63, 4153, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2470, 2471, 2472, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2488, 2489, 2490, + 2491, 1063, 1067, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 769, 0, 0, 771, 0, 0, + 0, 1050, 770, 1048, 1052, 1070, 0, 0, 0, 1049, + 1046, 1045, 0, 1051, 1036, 1037, 1035, 1038, 1039, 1040, + 1041, 0, 1068, 0, 1069, 0, 143, 47, 0, 0, + 0, 0, 0, 64, 0, 1064, 1065, 0, 742, 744, + 743, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 749, 4233, 0, 0, 0, 0, 147, 148, 0, 0, + 149, 0, 753, 0, 0, 0, 0, 0, 0, 768, + 0, 0, 0, 1060, 0, 1110, 746, 146, 0, 1059, + 736, 0, 0, 146, 0, 0, 0, 0, 146, 0, + 0, 0, 0, 1055, 0, 2171, 1868, 0, 0, 0, + 0, 0, 0, 1865, 0, 0, 0, 1867, 1864, 1866, + 1870, 1871, 1590, 146, 0, 1869, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4233, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 742, 744, 743, 0, 0, 0, 0, 1627, + 0, 0, 0, 0, 749, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2215, 0, 753, 0, 0, 4233, + 1058, 0, 0, 768, 0, 0, 1029, 1030, 0, 1024, + 746, 0, 0, 0, 1025, 2137, 0, 0, 0, 0, + 2098, 0, 0, 2145, 0, 0, 0, 748, 752, 758, + 0, 759, 761, 0, 0, 762, 763, 764, 0, 0, + 0, 766, 767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2139, 2107, 0, 0, 0, 4343, 0, + 0, 0, 0, 2140, 2141, 0, 0, 1853, 1854, 1855, + 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1875, 1876, + 1877, 1878, 1879, 1880, 1873, 1874, 0, 0, 0, 2106, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2114, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 748, 752, 758, 0, 759, 761, 0, 0, 762, + 763, 764, 0, 0, 0, 766, 767, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2130, 0, 0, + 0, 0, 0, 0, 745, 751, 750, 757, 747, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 754, 755, + 0, 756, 760, 0, 0, 741, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 765, 0, 0, 0, 2909, + 2910, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 772, 773, 774, 775, 776, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2097, + 2099, 2096, 0, 0, 0, 2093, 146, 0, 0, 0, + 2118, 0, 0, 146, 0, 0, 0, 0, 2988, 0, + 0, 2124, 0, 0, 0, 0, 0, 0, 0, 2109, + 0, 2092, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2112, 2146, 0, 0, 2113, 2115, 2117, 745, 2119, + 2120, 2121, 2125, 2126, 2127, 2129, 2132, 2133, 2134, 0, + 0, 0, 0, 0, 0, 0, 2122, 2131, 2123, 2171, + 0, 2137, 0, 0, 0, 0, 2098, 0, 2101, 2145, + 0, 0, 0, 0, 0, 0, 0, 0, 1182, 0, + 0, 0, 0, 0, 0, 0, 772, 773, 774, 775, + 776, 0, 0, 0, 0, 0, 0, 0, 0, 2139, + 2107, 0, 0, 0, 2138, 0, 0, 0, 0, 2140, + 2141, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2106, 0, 0, 2094, 2095, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2114, 0, 0, 2135, 0, 0, 742, + 744, 743, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 749, 0, 0, 2111, 0, 0, 146, 2110, 0, + 0, 0, 0, 753, 0, 0, 3176, 3177, 0, 0, + 768, 0, 0, 0, 0, 0, 0, 746, 0, 0, + 0, 0, 2128, 0, 0, 0, 0, 0, 0, 0, + 0, 2116, 1200, 1201, 1167, 0, 0, 0, 1157, 1303, + 1304, 1305, 1302, 0, 2143, 2142, 0, 0, 0, 0, + 0, 0, 0, 2130, 0, 1190, 1194, 1196, 1198, 1203, + 0, 1208, 1204, 1205, 1206, 1207, 0, 1185, 1186, 1187, + 1188, 1165, 1166, 1191, 0, 1168, 0, 1170, 1171, 1172, + 1173, 1169, 1174, 1175, 1176, 1177, 1178, 1181, 1183, 1179, + 1180, 1189, 0, 0, 0, 0, 0, 2103, 0, 1193, + 1195, 1197, 1199, 1202, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, + 0, 0, 0, 0, 0, 2097, 3012, 2096, 0, 1872, + 0, 3011, 0, 0, 0, 0, 2118, 0, 0, 0, + 1184, 0, 2144, 0, 0, 0, 0, 2124, 748, 752, + 758, 0, 759, 761, 0, 0, 762, 763, 764, 0, + 0, 0, 766, 767, 0, 0, 0, 2112, 2146, 0, + 0, 2113, 2115, 2117, 0, 2119, 2120, 2121, 2125, 2126, + 2127, 2129, 2132, 2133, 2134, 0, 0, 0, 0, 0, + 0, 0, 2122, 2131, 2123, 0, 0, 0, 0, 0, + 0, 2137, 0, 0, 2101, 1182, 0, 0, 0, 174, + 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3321, 0, 3849, 0, 0, 0, 0, 0, 2139, + 2138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1181, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1871, 0, 0, 2138, 2106, 0, - 0, 0, 0, 2137, 0, 0, 0, 2139, 2140, 0, - 0, 0, 0, 0, 0, 3175, 3176, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2105, 0, 0, 0, 2093, 2094, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2113, 0, 0, 0, 2134, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2110, 0, 0, 0, 2109, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3862, 3863, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2127, 0, 0, 0, 0, 0, 0, 0, 0, - 2115, 0, 0, 0, 0, 0, 1199, 1200, 1166, 0, - 0, 0, 1156, 2142, 2141, 0, 0, 0, 0, 0, - 146, 2129, 0, 0, 0, 0, 0, 0, 1191, 1189, - 1193, 1195, 1197, 1202, 0, 1207, 1203, 1204, 1205, 1206, - 0, 1184, 1185, 1186, 1187, 1164, 1165, 1190, 0, 1167, - 0, 1169, 1170, 1171, 1172, 1168, 1173, 1174, 1175, 1176, - 1177, 1180, 1182, 1178, 1179, 1188, 2102, 0, 0, 0, - 0, 1867, 0, 1192, 1194, 1196, 1198, 1201, 1864, 0, - 0, 0, 1866, 1863, 1865, 1869, 1870, 0, 0, 0, - 1868, 0, 0, 2096, 3011, 2095, 0, 0, 0, 3010, - 0, 0, 0, 0, 2117, 0, 0, 0, 0, 0, - 0, 2143, 0, 0, 1183, 2123, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3320, 0, 0, 0, 0, 2111, 2145, 0, 0, 2112, - 2114, 2116, 0, 2118, 2119, 2120, 2124, 2125, 2126, 2128, - 2131, 2132, 2133, 0, 0, 0, 0, 0, 0, 0, - 2121, 2130, 2122, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2100, 1181, 0, 0, 0, 0, 0, 3375, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3388, 0, 3389, - 0, 0, 0, 0, 0, 0, 0, 2137, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, - 1860, 1861, 1862, 1874, 1875, 1876, 1877, 1878, 1879, 1872, - 1873, 2093, 2094, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2134, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2110, 0, 0, - 0, 2109, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2127, 0, 1199, 1200, 1166, - 0, 0, 0, 0, 2115, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2142, 2141, 2214, - 1189, 1193, 1195, 1197, 1202, 0, 1207, 1203, 1204, 1205, - 1206, 0, 1184, 1185, 1186, 1187, 1164, 1165, 1190, 0, - 1167, 0, 1169, 1170, 1171, 1172, 1168, 1173, 1174, 1175, - 1176, 1177, 1180, 1182, 1178, 1179, 1188, 0, 0, 0, - 0, 0, 0, 0, 1192, 1194, 1196, 1198, 1201, 0, - 2102, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1183, 1191, 0, 0, 0, - 0, 0, 0, 0, 0, 2143, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3548, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2214, 845, 0, 0, 0, 0, 0, - 0, 0, 0, 417, 0, 0, 549, 583, 572, 655, - 537, 0, 0, 0, 0, 0, 0, 797, 0, 0, - 0, 352, 0, 0, 385, 587, 568, 579, 569, 554, - 555, 556, 563, 364, 557, 558, 559, 529, 560, 530, - 561, 562, 836, 586, 536, 450, 401, 0, 603, 0, - 0, 915, 923, 0, 0, 0, 0, 0, 0, 0, - 0, 911, 0, 0, 0, 0, 789, 0, 0, 826, - 891, 890, 813, 823, 0, 0, 321, 235, 531, 651, - 533, 532, 814, 0, 815, 819, 822, 818, 816, 817, - 0, 906, 0, 0, 0, 0, 0, 0, 781, 793, - 0, 798, 0, 0, 0, 0, 0, 2214, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1191, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 790, 791, 0, - 0, 0, 0, 846, 0, 792, 0, 0, 0, 0, - 0, 451, 479, 0, 491, 0, 375, 376, 841, 820, - 824, 0, 0, 0, 0, 309, 457, 476, 322, 445, - 489, 327, 453, 468, 317, 416, 442, 0, 0, 311, - 474, 452, 398, 310, 0, 436, 350, 366, 347, 414, - 821, 844, 848, 346, 929, 842, 484, 313, 0, 483, - 413, 470, 475, 399, 392, 0, 312, 472, 397, 391, - 379, 356, 930, 380, 381, 370, 426, 389, 427, 371, - 403, 402, 404, 3801, 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 644, 839, 0, 648, 0, - 486, 0, 0, 913, 0, 0, 0, 456, 0, 0, - 382, 0, 0, 0, 843, 0, 439, 419, 926, 0, - 0, 437, 387, 471, 428, 477, 458, 485, 433, 429, - 303, 459, 349, 400, 318, 320, 672, 351, 353, 357, - 358, 409, 410, 423, 444, 461, 462, 463, 348, 332, - 438, 333, 368, 334, 304, 340, 338, 341, 446, 342, - 306, 424, 467, 0, 363, 434, 395, 307, 394, 425, - 466, 465, 319, 493, 500, 501, 591, 0, 506, 683, - 684, 685, 515, 0, 430, 315, 314, 0, 0, 3900, - 344, 328, 330, 331, 329, 422, 520, 521, 522, 524, - 525, 526, 527, 592, 608, 576, 545, 508, 600, 542, - 546, 547, 373, 611, 1895, 1894, 1896, 499, 383, 384, + 0, 0, 0, 0, 2094, 2095, 0, 0, 0, 0, + 3376, 0, 0, 208, 0, 0, 0, 0, 0, 2137, + 0, 0, 2135, 2114, 0, 0, 0, 0, 3389, 0, + 3390, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2111, 0, 0, 0, 2110, 745, 0, 1868, 0, 0, + 0, 0, 0, 146, 1865, 0, 0, 2139, 1867, 1864, + 1866, 1870, 1871, 0, 0, 0, 1869, 0, 2128, 1200, + 1201, 1167, 0, 0, 0, 0, 0, 2116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2143, 2142, 1190, 1194, 1196, 1198, 1203, 0, 1208, 1204, + 1205, 1206, 1207, 2130, 1185, 1186, 1187, 1188, 1165, 1166, + 1191, 2114, 1168, 0, 1170, 1171, 1172, 1173, 1169, 1174, + 1175, 1176, 1177, 1178, 1181, 1183, 1179, 1180, 1189, 0, + 0, 0, 0, 0, 0, 0, 1193, 1195, 1197, 1199, + 1202, 0, 0, 2103, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2215, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1192, 0, 0, 0, 1184, 0, 0, + 0, 0, 0, 0, 0, 0, 2118, 4016, 2144, 0, + 0, 2130, 0, 0, 0, 0, 0, 2124, 1853, 1854, + 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1875, + 1876, 1877, 1878, 1879, 1880, 1873, 1874, 2112, 2146, 0, + 0, 2113, 2115, 2117, 0, 2119, 2120, 2121, 2125, 2126, + 2127, 2129, 2132, 2133, 2134, 0, 0, 0, 0, 0, + 0, 0, 2122, 2131, 2123, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2118, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2124, 0, 0, 0, 0, + 2138, 0, 0, 3549, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2112, 2146, 0, 0, 2113, + 2115, 2117, 0, 2119, 2120, 2121, 2125, 2126, 2127, 2129, + 2132, 2133, 2134, 0, 0, 0, 0, 0, 0, 0, + 2122, 2131, 2123, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2135, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2111, 0, 0, 0, 2110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2138, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2128, 0, + 0, 0, 0, 0, 0, 0, 0, 2116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2215, 0, 0, 0, 0, 0, + 2135, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2111, 0, + 0, 0, 2110, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2128, 0, 0, 0, + 1192, 0, 0, 0, 0, 2116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 846, + 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 798, 0, 0, 0, 352, 0, 2215, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 837, 587, 537, + 451, 401, 0, 604, 0, 0, 916, 924, 0, 0, + 0, 0, 0, 0, 0, 0, 912, 0, 0, 0, + 0, 790, 0, 0, 827, 892, 891, 814, 824, 0, + 0, 321, 235, 532, 652, 534, 533, 815, 0, 816, + 820, 823, 819, 817, 818, 0, 907, 0, 0, 0, + 0, 0, 0, 782, 794, 0, 799, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 791, 792, 3803, 0, 0, 0, 847, 0, + 793, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 842, 821, 825, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 822, 845, 849, 346, 930, + 843, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 931, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 840, 0, 649, 0, 487, 0, 0, 914, 0, + 0, 3902, 457, 0, 0, 382, 0, 0, 0, 844, + 0, 440, 419, 927, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 1896, 1895, 1897, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 911, 415, 614, + 647, 648, 539, 0, 926, 906, 908, 909, 913, 917, + 918, 919, 920, 921, 923, 925, 929, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 928, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 848, 590, 591, 405, + 406, 407, 408, 915, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 937, 910, 936, 938, 939, 935, 940, 941, + 922, 803, 0, 855, 856, 933, 932, 934, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 810, 302, 545, 386, 432, 359, 610, 611, 0, 662, + 899, 864, 865, 866, 800, 867, 861, 862, 801, 863, + 900, 853, 896, 897, 829, 858, 868, 895, 869, 898, + 901, 902, 942, 943, 875, 859, 264, 944, 872, 903, + 894, 893, 870, 854, 904, 905, 836, 831, 873, 874, + 860, 879, 880, 881, 884, 802, 885, 886, 887, 888, + 889, 883, 882, 850, 851, 852, 876, 877, 857, 832, + 833, 834, 835, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 890, + 657, 455, 456, 663, 0, 878, 660, 661, 658, 390, + 442, 461, 449, 846, 680, 535, 536, 681, 646, 0, + 795, 0, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 798, 0, 0, 0, + 352, 1961, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 837, 587, 537, 451, 401, 0, 604, 0, 0, + 916, 924, 0, 0, 0, 0, 0, 0, 0, 0, + 912, 0, 2197, 0, 0, 790, 0, 0, 827, 892, + 891, 814, 824, 0, 0, 321, 235, 532, 652, 534, + 533, 815, 0, 816, 820, 823, 819, 817, 818, 0, + 907, 0, 0, 0, 0, 0, 0, 782, 794, 0, + 799, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 791, 792, 0, 0, + 0, 0, 847, 0, 793, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 2198, 821, 825, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 822, + 845, 849, 346, 930, 843, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 931, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 840, 0, 649, 0, 487, + 0, 0, 914, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 844, 0, 440, 419, 927, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, - 678, 910, 415, 613, 646, 647, 538, 0, 925, 905, - 907, 908, 912, 916, 917, 918, 919, 920, 922, 924, - 928, 677, 0, 593, 607, 681, 606, 674, 421, 0, - 443, 604, 551, 0, 597, 570, 571, 0, 598, 566, - 602, 0, 540, 0, 509, 512, 541, 626, 627, 628, - 305, 511, 630, 631, 632, 633, 634, 635, 636, 629, - 927, 574, 550, 577, 490, 553, 552, 0, 0, 588, - 847, 589, 590, 405, 406, 407, 408, 914, 614, 326, - 510, 432, 0, 575, 0, 0, 0, 0, 0, 0, - 0, 0, 580, 581, 578, 686, 0, 637, 638, 0, - 0, 504, 505, 360, 367, 523, 369, 325, 420, 362, - 488, 377, 0, 516, 582, 517, 640, 643, 641, 642, - 412, 372, 374, 447, 378, 388, 435, 487, 418, 440, - 323, 478, 449, 393, 567, 595, 936, 909, 935, 937, - 938, 934, 939, 940, 921, 802, 0, 854, 855, 932, - 931, 933, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 622, 621, 620, 619, 618, 617, 616, - 615, 0, 0, 564, 464, 339, 294, 335, 336, 343, - 675, 671, 469, 676, 809, 302, 544, 386, 431, 359, - 609, 610, 0, 661, 898, 863, 864, 865, 799, 866, - 860, 861, 800, 862, 899, 852, 895, 896, 828, 857, - 867, 894, 868, 897, 900, 901, 941, 942, 874, 858, - 264, 943, 871, 902, 893, 892, 869, 853, 903, 904, - 835, 830, 872, 873, 859, 878, 879, 880, 883, 801, - 884, 885, 886, 887, 888, 882, 881, 849, 850, 851, - 875, 876, 856, 831, 832, 833, 834, 0, 0, 494, - 495, 496, 519, 0, 497, 480, 543, 673, 0, 0, - 0, 0, 0, 0, 0, 594, 605, 639, 0, 649, - 650, 652, 654, 889, 656, 454, 455, 662, 0, 877, - 659, 660, 657, 390, 441, 460, 448, 845, 679, 534, - 535, 680, 645, 0, 794, 0, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 0, - 797, 0, 0, 0, 352, 1960, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 836, 586, 536, 450, 401, - 0, 603, 0, 0, 915, 923, 0, 0, 0, 0, - 0, 0, 0, 0, 911, 0, 2196, 0, 0, 789, - 0, 0, 826, 891, 890, 813, 823, 0, 0, 321, - 235, 531, 651, 533, 532, 814, 0, 815, 819, 822, - 818, 816, 817, 0, 906, 0, 0, 0, 0, 0, - 0, 781, 793, 0, 798, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 790, 791, 0, 0, 0, 0, 846, 0, 792, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 2197, 820, 824, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 821, 844, 848, 346, 929, 842, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 930, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 839, - 0, 648, 0, 486, 0, 0, 913, 0, 0, 0, - 456, 0, 0, 382, 0, 0, 0, 843, 0, 439, - 419, 926, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 910, 415, 613, 646, 647, 538, - 0, 925, 905, 907, 908, 912, 916, 917, 918, 919, - 920, 922, 924, 928, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 927, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 847, 589, 590, 405, 406, 407, 408, - 914, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 936, - 909, 935, 937, 938, 934, 939, 940, 921, 802, 0, - 854, 855, 932, 931, 933, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 809, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 898, 863, 864, - 865, 799, 866, 860, 861, 800, 862, 899, 852, 895, - 896, 828, 857, 867, 894, 868, 897, 900, 901, 941, - 942, 874, 858, 264, 943, 871, 902, 893, 892, 869, - 853, 903, 904, 835, 830, 872, 873, 859, 878, 879, - 880, 883, 801, 884, 885, 886, 887, 888, 882, 881, - 849, 850, 851, 875, 876, 856, 831, 832, 833, 834, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 889, 656, 454, 455, - 662, 0, 877, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 0, 794, 174, 212, - 845, 0, 0, 0, 0, 0, 0, 0, 0, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 797, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 1340, 586, - 536, 450, 401, 0, 603, 0, 0, 915, 923, 0, - 0, 0, 0, 0, 0, 0, 0, 911, 0, 0, - 0, 0, 789, 0, 0, 826, 891, 890, 813, 823, - 0, 0, 321, 235, 531, 651, 533, 532, 814, 0, - 815, 819, 822, 818, 816, 817, 0, 906, 0, 0, - 0, 0, 0, 0, 781, 793, 0, 798, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 790, 791, 0, 0, 0, 0, 846, - 0, 792, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 841, 820, 824, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 821, 844, 848, 346, - 929, 842, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 930, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 839, 0, 648, 0, 486, 0, 0, 913, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 843, 0, 439, 419, 926, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 910, 415, 613, - 646, 647, 538, 0, 925, 905, 907, 908, 912, 916, - 917, 918, 919, 920, 922, 924, 928, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 927, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 847, 589, 590, 405, - 406, 407, 408, 914, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 936, 909, 935, 937, 938, 934, 939, 940, - 921, 802, 0, 854, 855, 932, 931, 933, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 809, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 898, 863, 864, 865, 799, 866, 860, 861, 800, 862, - 899, 852, 895, 896, 828, 857, 867, 894, 868, 897, - 900, 901, 941, 942, 874, 858, 264, 943, 871, 902, - 893, 892, 869, 853, 903, 904, 835, 830, 872, 873, - 859, 878, 879, 880, 883, 801, 884, 885, 886, 887, - 888, 882, 881, 849, 850, 851, 875, 876, 856, 831, - 832, 833, 834, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 889, - 656, 454, 455, 662, 0, 877, 659, 660, 657, 390, - 441, 460, 448, 845, 679, 534, 535, 680, 645, 0, - 794, 0, 417, 0, 0, 549, 583, 572, 655, 537, - 0, 0, 0, 0, 0, 0, 797, 0, 0, 0, - 352, 4340, 0, 385, 587, 568, 579, 569, 554, 555, - 556, 563, 364, 557, 558, 559, 529, 560, 530, 561, - 562, 836, 586, 536, 450, 401, 0, 603, 0, 0, - 915, 923, 0, 0, 0, 0, 0, 0, 0, 0, - 911, 0, 0, 0, 0, 789, 0, 0, 826, 891, - 890, 813, 823, 0, 0, 321, 235, 531, 651, 533, - 532, 814, 0, 815, 819, 822, 818, 816, 817, 0, - 906, 0, 0, 0, 0, 0, 0, 781, 793, 0, - 798, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 790, 791, 0, 0, - 0, 0, 846, 0, 792, 0, 0, 0, 0, 0, - 451, 479, 0, 491, 0, 375, 376, 841, 820, 824, - 0, 0, 0, 0, 309, 457, 476, 322, 445, 489, - 327, 453, 468, 317, 416, 442, 0, 0, 311, 474, - 452, 398, 310, 0, 436, 350, 366, 347, 414, 821, - 844, 848, 346, 929, 842, 484, 313, 0, 483, 413, - 470, 475, 399, 392, 0, 312, 472, 397, 391, 379, - 356, 930, 380, 381, 370, 426, 389, 427, 371, 403, - 402, 404, 0, 0, 0, 0, 0, 513, 514, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 644, 839, 0, 648, 0, 486, - 0, 0, 913, 0, 0, 0, 456, 0, 0, 382, - 0, 0, 0, 843, 0, 439, 419, 926, 0, 0, - 437, 387, 471, 428, 477, 458, 485, 433, 429, 303, - 459, 349, 400, 318, 320, 672, 351, 353, 357, 358, - 409, 410, 423, 444, 461, 462, 463, 348, 332, 438, - 333, 368, 334, 304, 340, 338, 341, 446, 342, 306, - 424, 467, 0, 363, 434, 395, 307, 394, 425, 466, - 465, 319, 493, 500, 501, 591, 0, 506, 683, 684, - 685, 515, 0, 430, 315, 314, 0, 0, 0, 344, - 328, 330, 331, 329, 422, 520, 521, 522, 524, 525, - 526, 527, 592, 608, 576, 545, 508, 600, 542, 546, - 547, 373, 611, 0, 0, 0, 499, 383, 384, 0, - 355, 354, 396, 308, 0, 0, 361, 300, 301, 678, - 910, 415, 613, 646, 647, 538, 0, 925, 905, 907, - 908, 912, 916, 917, 918, 919, 920, 922, 924, 928, - 677, 0, 593, 607, 681, 606, 674, 421, 0, 443, - 604, 551, 0, 597, 570, 571, 0, 598, 566, 602, - 0, 540, 0, 509, 512, 541, 626, 627, 628, 305, - 511, 630, 631, 632, 633, 634, 635, 636, 629, 927, - 574, 550, 577, 490, 553, 552, 0, 0, 588, 847, - 589, 590, 405, 406, 407, 408, 914, 614, 326, 510, - 432, 0, 575, 0, 0, 0, 0, 0, 0, 0, - 0, 580, 581, 578, 686, 0, 637, 638, 0, 0, - 504, 505, 360, 367, 523, 369, 325, 420, 362, 488, - 377, 0, 516, 582, 517, 640, 643, 641, 642, 412, - 372, 374, 447, 378, 388, 435, 487, 418, 440, 323, - 478, 449, 393, 567, 595, 936, 909, 935, 937, 938, - 934, 939, 940, 921, 802, 0, 854, 855, 932, 931, - 933, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 622, 621, 620, 619, 618, 617, 616, 615, - 0, 0, 564, 464, 339, 294, 335, 336, 343, 675, - 671, 469, 676, 809, 302, 544, 386, 431, 359, 609, - 610, 0, 661, 898, 863, 864, 865, 799, 866, 860, - 861, 800, 862, 899, 852, 895, 896, 828, 857, 867, - 894, 868, 897, 900, 901, 941, 942, 874, 858, 264, - 943, 871, 902, 893, 892, 869, 853, 903, 904, 835, - 830, 872, 873, 859, 878, 879, 880, 883, 801, 884, - 885, 886, 887, 888, 882, 881, 849, 850, 851, 875, - 876, 856, 831, 832, 833, 834, 0, 0, 494, 495, - 496, 519, 0, 497, 480, 543, 673, 0, 0, 0, - 0, 0, 0, 0, 594, 605, 639, 0, 649, 650, - 652, 654, 889, 656, 454, 455, 662, 0, 877, 659, - 660, 657, 390, 441, 460, 448, 845, 679, 534, 535, - 680, 645, 0, 794, 0, 417, 0, 0, 549, 583, - 572, 655, 537, 0, 0, 0, 0, 0, 0, 797, - 0, 0, 0, 352, 0, 0, 385, 587, 568, 579, - 569, 554, 555, 556, 563, 364, 557, 558, 559, 529, - 560, 530, 561, 562, 836, 586, 536, 450, 401, 0, - 603, 0, 0, 915, 923, 0, 0, 0, 0, 0, - 0, 0, 0, 911, 0, 0, 0, 0, 789, 0, - 0, 826, 891, 890, 813, 823, 0, 0, 321, 235, - 531, 651, 533, 532, 814, 0, 815, 819, 822, 818, - 816, 817, 0, 906, 0, 0, 0, 0, 0, 0, - 781, 793, 0, 798, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 790, - 791, 0, 0, 0, 0, 846, 0, 792, 0, 0, - 0, 0, 0, 451, 479, 0, 491, 0, 375, 376, - 841, 820, 824, 0, 0, 0, 0, 309, 457, 476, - 322, 445, 489, 327, 453, 468, 317, 416, 442, 0, - 0, 311, 474, 452, 398, 310, 0, 436, 350, 366, - 347, 414, 821, 844, 848, 346, 929, 842, 484, 313, - 0, 483, 413, 470, 475, 399, 392, 0, 312, 472, - 397, 391, 379, 356, 930, 380, 381, 370, 426, 389, - 427, 371, 403, 402, 404, 0, 0, 0, 0, 0, - 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 644, 839, 0, - 648, 0, 486, 0, 0, 913, 0, 0, 0, 456, - 0, 0, 382, 0, 0, 0, 843, 0, 439, 419, - 926, 4232, 0, 437, 387, 471, 428, 477, 458, 485, - 433, 429, 303, 459, 349, 400, 318, 320, 672, 351, - 353, 357, 358, 409, 410, 423, 444, 461, 462, 463, - 348, 332, 438, 333, 368, 334, 304, 340, 338, 341, - 446, 342, 306, 424, 467, 0, 363, 434, 395, 307, - 394, 425, 466, 465, 319, 493, 500, 501, 591, 0, - 506, 683, 684, 685, 515, 0, 430, 315, 314, 0, - 0, 0, 344, 328, 330, 331, 329, 422, 520, 521, - 522, 524, 525, 526, 527, 592, 608, 576, 545, 508, - 600, 542, 546, 547, 373, 611, 0, 0, 0, 499, + 679, 911, 415, 614, 647, 648, 539, 0, 926, 906, + 908, 909, 913, 917, 918, 919, 920, 921, 923, 925, + 929, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 928, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 848, 590, 591, 405, 406, 407, 408, 915, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 937, 910, 936, 938, + 939, 935, 940, 941, 922, 803, 0, 855, 856, 933, + 932, 934, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 810, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 899, 864, 865, 866, 800, 867, + 861, 862, 801, 863, 900, 853, 896, 897, 829, 858, + 868, 895, 869, 898, 901, 902, 942, 943, 875, 859, + 264, 944, 872, 903, 894, 893, 870, 854, 904, 905, + 836, 831, 873, 874, 860, 879, 880, 881, 884, 802, + 885, 886, 887, 888, 889, 883, 882, 850, 851, 852, + 876, 877, 857, 832, 833, 834, 835, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 890, 657, 455, 456, 663, 0, 878, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 0, 795, 174, 212, 846, 0, 0, + 0, 0, 0, 0, 0, 0, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 798, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 1341, 587, 537, 451, 401, + 0, 604, 0, 0, 916, 924, 0, 0, 0, 0, + 0, 0, 0, 0, 912, 0, 0, 0, 0, 790, + 0, 0, 827, 892, 891, 814, 824, 0, 0, 321, + 235, 532, 652, 534, 533, 815, 0, 816, 820, 823, + 819, 817, 818, 0, 907, 0, 0, 0, 0, 0, + 0, 782, 794, 0, 799, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 791, 792, 0, 0, 0, 0, 847, 0, 793, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 842, 821, 825, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 822, 845, 849, 346, 930, 843, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 931, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 840, + 0, 649, 0, 487, 0, 0, 914, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 844, 0, 440, + 419, 927, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 911, 415, 614, 647, 648, + 539, 0, 926, 906, 908, 909, 913, 917, 918, 919, + 920, 921, 923, 925, 929, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 928, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 848, 590, 591, 405, 406, 407, + 408, 915, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, + 937, 910, 936, 938, 939, 935, 940, 941, 922, 803, + 0, 855, 856, 933, 932, 934, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 810, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 899, 864, + 865, 866, 800, 867, 861, 862, 801, 863, 900, 853, + 896, 897, 829, 858, 868, 895, 869, 898, 901, 902, + 942, 943, 875, 859, 264, 944, 872, 903, 894, 893, + 870, 854, 904, 905, 836, 831, 873, 874, 860, 879, + 880, 881, 884, 802, 885, 886, 887, 888, 889, 883, + 882, 850, 851, 852, 876, 877, 857, 832, 833, 834, + 835, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 890, 657, 455, + 456, 663, 0, 878, 660, 661, 658, 390, 442, 461, + 449, 846, 680, 535, 536, 681, 646, 0, 795, 0, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 798, 0, 0, 0, 352, 4342, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 837, + 587, 537, 451, 401, 0, 604, 0, 0, 916, 924, + 0, 0, 0, 0, 0, 0, 0, 0, 912, 0, + 0, 0, 0, 790, 0, 0, 827, 892, 891, 814, + 824, 0, 0, 321, 235, 532, 652, 534, 533, 815, + 0, 816, 820, 823, 819, 817, 818, 0, 907, 0, + 0, 0, 0, 0, 0, 782, 794, 0, 799, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 791, 792, 0, 0, 0, 0, + 847, 0, 793, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 842, 821, 825, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 822, 845, 849, + 346, 930, 843, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 931, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 840, 0, 649, 0, 487, 0, 0, + 914, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 844, 0, 440, 419, 927, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 911, + 415, 614, 647, 648, 539, 0, 926, 906, 908, 909, + 913, 917, 918, 919, 920, 921, 923, 925, 929, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 928, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 848, 590, + 591, 405, 406, 407, 408, 915, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 937, 910, 936, 938, 939, 935, + 940, 941, 922, 803, 0, 855, 856, 933, 932, 934, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 810, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 899, 864, 865, 866, 800, 867, 861, 862, + 801, 863, 900, 853, 896, 897, 829, 858, 868, 895, + 869, 898, 901, 902, 942, 943, 875, 859, 264, 944, + 872, 903, 894, 893, 870, 854, 904, 905, 836, 831, + 873, 874, 860, 879, 880, 881, 884, 802, 885, 886, + 887, 888, 889, 883, 882, 850, 851, 852, 876, 877, + 857, 832, 833, 834, 835, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 890, 657, 455, 456, 663, 0, 878, 660, 661, + 658, 390, 442, 461, 449, 846, 680, 535, 536, 681, + 646, 0, 795, 0, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 0, 798, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 837, 587, 537, 451, 401, 0, 604, + 0, 0, 916, 924, 0, 0, 0, 0, 0, 0, + 0, 0, 912, 0, 0, 0, 0, 790, 0, 0, + 827, 892, 891, 814, 824, 0, 0, 321, 235, 532, + 652, 534, 533, 815, 0, 816, 820, 823, 819, 817, + 818, 0, 907, 0, 0, 0, 0, 0, 0, 782, + 794, 0, 799, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 791, 792, + 0, 0, 0, 0, 847, 0, 793, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 842, + 821, 825, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 822, 845, 849, 346, 930, 843, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 931, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 840, 0, 649, + 0, 487, 0, 0, 914, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 844, 0, 440, 419, 927, + 4234, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, - 300, 301, 678, 910, 415, 613, 646, 647, 538, 0, - 925, 905, 907, 908, 912, 916, 917, 918, 919, 920, - 922, 924, 928, 677, 0, 593, 607, 681, 606, 674, - 421, 0, 443, 604, 551, 0, 597, 570, 571, 0, - 598, 566, 602, 0, 540, 0, 509, 512, 541, 626, - 627, 628, 305, 511, 630, 631, 632, 633, 634, 635, - 636, 629, 927, 574, 550, 577, 490, 553, 552, 0, - 0, 588, 847, 589, 590, 405, 406, 407, 408, 914, - 614, 326, 510, 432, 0, 575, 0, 0, 0, 0, - 0, 0, 0, 0, 580, 581, 578, 686, 0, 637, - 638, 0, 0, 504, 505, 360, 367, 523, 369, 325, - 420, 362, 488, 377, 0, 516, 582, 517, 640, 643, - 641, 642, 412, 372, 374, 447, 378, 388, 435, 487, - 418, 440, 323, 478, 449, 393, 567, 595, 936, 909, - 935, 937, 938, 934, 939, 940, 921, 802, 0, 854, - 855, 932, 931, 933, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 622, 621, 620, 619, 618, - 617, 616, 615, 0, 0, 564, 464, 339, 294, 335, - 336, 343, 675, 671, 469, 676, 809, 302, 544, 386, - 431, 359, 609, 610, 0, 661, 898, 863, 864, 865, - 799, 866, 860, 861, 800, 862, 899, 852, 895, 896, - 828, 857, 867, 894, 868, 897, 900, 901, 941, 942, - 874, 858, 264, 943, 871, 902, 893, 892, 869, 853, - 903, 904, 835, 830, 872, 873, 859, 878, 879, 880, - 883, 801, 884, 885, 886, 887, 888, 882, 881, 849, - 850, 851, 875, 876, 856, 831, 832, 833, 834, 0, - 0, 494, 495, 496, 519, 0, 497, 480, 543, 673, - 0, 0, 0, 0, 0, 0, 0, 594, 605, 639, - 0, 649, 650, 652, 654, 889, 656, 454, 455, 662, - 0, 877, 659, 660, 657, 390, 441, 460, 448, 845, - 679, 534, 535, 680, 645, 0, 794, 0, 417, 0, - 0, 549, 583, 572, 655, 537, 0, 0, 0, 0, - 0, 0, 797, 0, 0, 0, 352, 1960, 0, 385, - 587, 568, 579, 569, 554, 555, 556, 563, 364, 557, - 558, 559, 529, 560, 530, 561, 562, 836, 586, 536, - 450, 401, 0, 603, 0, 0, 915, 923, 0, 0, - 0, 0, 0, 0, 0, 0, 911, 0, 0, 0, - 0, 789, 0, 0, 826, 891, 890, 813, 823, 0, - 0, 321, 235, 531, 651, 533, 532, 814, 0, 815, - 819, 822, 818, 816, 817, 0, 906, 0, 0, 0, - 0, 0, 0, 781, 793, 0, 798, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 790, 791, 0, 0, 0, 0, 846, 0, - 792, 0, 0, 0, 0, 0, 451, 479, 0, 491, - 0, 375, 376, 841, 820, 824, 0, 0, 0, 0, - 309, 457, 476, 322, 445, 489, 327, 453, 468, 317, - 416, 442, 0, 0, 311, 474, 452, 398, 310, 0, - 436, 350, 366, 347, 414, 821, 844, 848, 346, 929, - 842, 484, 313, 0, 483, 413, 470, 475, 399, 392, - 0, 312, 472, 397, 391, 379, 356, 930, 380, 381, - 370, 426, 389, 427, 371, 403, 402, 404, 0, 0, - 0, 0, 0, 513, 514, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 644, 839, 0, 648, 0, 486, 0, 0, 913, 0, - 0, 0, 456, 0, 0, 382, 0, 0, 0, 843, - 0, 439, 419, 926, 0, 0, 437, 387, 471, 428, - 477, 458, 485, 433, 429, 303, 459, 349, 400, 318, - 320, 672, 351, 353, 357, 358, 409, 410, 423, 444, - 461, 462, 463, 348, 332, 438, 333, 368, 334, 304, - 340, 338, 341, 446, 342, 306, 424, 467, 0, 363, - 434, 395, 307, 394, 425, 466, 465, 319, 493, 500, - 501, 591, 0, 506, 683, 684, 685, 515, 0, 430, + 300, 301, 679, 911, 415, 614, 647, 648, 539, 0, + 926, 906, 908, 909, 913, 917, 918, 919, 920, 921, + 923, 925, 929, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 928, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 848, 590, 591, 405, 406, 407, 408, 915, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 937, 910, + 936, 938, 939, 935, 940, 941, 922, 803, 0, 855, + 856, 933, 932, 934, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 810, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 899, 864, 865, 866, + 800, 867, 861, 862, 801, 863, 900, 853, 896, 897, + 829, 858, 868, 895, 869, 898, 901, 902, 942, 943, + 875, 859, 264, 944, 872, 903, 894, 893, 870, 854, + 904, 905, 836, 831, 873, 874, 860, 879, 880, 881, + 884, 802, 885, 886, 887, 888, 889, 883, 882, 850, + 851, 852, 876, 877, 857, 832, 833, 834, 835, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 890, 657, 455, 456, 663, + 0, 878, 660, 661, 658, 390, 442, 461, 449, 846, + 680, 535, 536, 681, 646, 0, 795, 0, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 798, 0, 0, 0, 352, 1961, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 837, 587, 537, + 451, 401, 0, 604, 0, 0, 916, 924, 0, 0, + 0, 0, 0, 0, 0, 0, 912, 0, 0, 0, + 0, 790, 0, 0, 827, 892, 891, 814, 824, 0, + 0, 321, 235, 532, 652, 534, 533, 815, 0, 816, + 820, 823, 819, 817, 818, 0, 907, 0, 0, 0, + 0, 0, 0, 782, 794, 0, 799, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 791, 792, 0, 0, 0, 0, 847, 0, + 793, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 842, 821, 825, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 822, 845, 849, 346, 930, + 843, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 931, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 840, 0, 649, 0, 487, 0, 0, 914, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 844, + 0, 440, 419, 927, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, - 422, 520, 521, 522, 524, 525, 526, 527, 592, 608, - 576, 545, 508, 600, 542, 546, 547, 373, 611, 0, - 0, 0, 499, 383, 384, 0, 355, 354, 396, 308, - 0, 0, 361, 300, 301, 678, 910, 415, 613, 646, - 647, 538, 0, 925, 905, 907, 908, 912, 916, 917, - 918, 919, 920, 922, 924, 928, 677, 0, 593, 607, - 681, 606, 674, 421, 0, 443, 604, 551, 0, 597, - 570, 571, 0, 598, 566, 602, 0, 540, 0, 509, - 512, 541, 626, 627, 628, 305, 511, 630, 631, 632, - 633, 634, 635, 636, 629, 927, 574, 550, 577, 490, - 553, 552, 0, 0, 588, 847, 589, 590, 405, 406, - 407, 408, 914, 614, 326, 510, 432, 0, 575, 0, - 0, 0, 0, 0, 0, 0, 0, 580, 581, 578, - 686, 0, 637, 638, 0, 0, 504, 505, 360, 367, - 523, 369, 325, 420, 362, 488, 377, 0, 516, 582, - 517, 640, 643, 641, 642, 412, 372, 374, 447, 378, - 388, 435, 487, 418, 440, 323, 478, 449, 393, 567, - 595, 936, 909, 935, 937, 938, 934, 939, 940, 921, - 802, 0, 854, 855, 932, 931, 933, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 622, 621, - 620, 619, 618, 617, 616, 615, 0, 0, 564, 464, - 339, 294, 335, 336, 343, 675, 671, 469, 676, 809, - 302, 544, 386, 431, 359, 609, 610, 0, 661, 898, - 863, 864, 865, 799, 866, 860, 861, 800, 862, 899, - 852, 895, 896, 828, 857, 867, 894, 868, 897, 900, - 901, 941, 942, 874, 858, 264, 943, 871, 902, 893, - 892, 869, 853, 903, 904, 835, 830, 872, 873, 859, - 878, 879, 880, 883, 801, 884, 885, 886, 887, 888, - 882, 881, 849, 850, 851, 875, 876, 856, 831, 832, - 833, 834, 0, 0, 494, 495, 496, 519, 0, 497, - 480, 543, 673, 0, 0, 0, 0, 0, 0, 0, - 594, 605, 639, 0, 649, 650, 652, 654, 889, 656, - 454, 455, 662, 0, 877, 659, 660, 657, 390, 441, - 460, 448, 845, 679, 534, 535, 680, 645, 0, 794, - 0, 417, 0, 0, 549, 583, 572, 655, 537, 0, - 0, 0, 0, 0, 0, 797, 0, 0, 0, 352, - 0, 0, 385, 587, 568, 579, 569, 554, 555, 556, - 563, 364, 557, 558, 559, 529, 560, 530, 561, 562, - 836, 586, 536, 450, 401, 0, 603, 0, 0, 915, - 923, 0, 0, 0, 0, 0, 0, 0, 0, 911, - 0, 0, 0, 0, 789, 0, 0, 826, 891, 890, - 813, 823, 0, 0, 321, 235, 531, 651, 533, 532, - 814, 0, 815, 819, 822, 818, 816, 817, 0, 906, - 0, 0, 0, 0, 0, 0, 781, 793, 0, 798, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 790, 791, 1657, 0, 0, - 0, 846, 0, 792, 0, 0, 0, 0, 0, 451, - 479, 0, 491, 0, 375, 376, 841, 820, 824, 0, - 0, 0, 0, 309, 457, 476, 322, 445, 489, 327, - 453, 468, 317, 416, 442, 0, 0, 311, 474, 452, - 398, 310, 0, 436, 350, 366, 347, 414, 821, 844, - 848, 346, 929, 842, 484, 313, 0, 483, 413, 470, - 475, 399, 392, 0, 312, 472, 397, 391, 379, 356, - 930, 380, 381, 370, 426, 389, 427, 371, 403, 402, - 404, 0, 0, 0, 0, 0, 513, 514, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 644, 839, 0, 648, 0, 486, 0, - 0, 913, 0, 0, 0, 456, 0, 0, 382, 0, - 0, 0, 843, 0, 439, 419, 926, 0, 0, 437, - 387, 471, 428, 477, 458, 485, 433, 429, 303, 459, - 349, 400, 318, 320, 672, 351, 353, 357, 358, 409, - 410, 423, 444, 461, 462, 463, 348, 332, 438, 333, - 368, 334, 304, 340, 338, 341, 446, 342, 306, 424, - 467, 0, 363, 434, 395, 307, 394, 425, 466, 465, - 319, 493, 500, 501, 591, 0, 506, 683, 684, 685, - 515, 0, 430, 315, 314, 0, 0, 0, 344, 328, - 330, 331, 329, 422, 520, 521, 522, 524, 525, 526, - 527, 592, 608, 576, 545, 508, 600, 542, 546, 547, - 373, 611, 0, 0, 0, 499, 383, 384, 0, 355, - 354, 396, 308, 0, 0, 361, 300, 301, 678, 910, - 415, 613, 646, 647, 538, 0, 925, 905, 907, 908, - 912, 916, 917, 918, 919, 920, 922, 924, 928, 677, - 0, 593, 607, 681, 606, 674, 421, 0, 443, 604, - 551, 0, 597, 570, 571, 0, 598, 566, 602, 0, - 540, 0, 509, 512, 541, 626, 627, 628, 305, 511, - 630, 631, 632, 633, 634, 635, 636, 629, 927, 574, - 550, 577, 490, 553, 552, 0, 0, 588, 847, 589, - 590, 405, 406, 407, 408, 914, 614, 326, 510, 432, - 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, - 580, 581, 578, 686, 0, 637, 638, 0, 0, 504, - 505, 360, 367, 523, 369, 325, 420, 362, 488, 377, - 0, 516, 582, 517, 640, 643, 641, 642, 412, 372, - 374, 447, 378, 388, 435, 487, 418, 440, 323, 478, - 449, 393, 567, 595, 936, 909, 935, 937, 938, 934, - 939, 940, 921, 802, 0, 854, 855, 932, 931, 933, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 622, 621, 620, 619, 618, 617, 616, 615, 0, - 0, 564, 464, 339, 294, 335, 336, 343, 675, 671, - 469, 676, 809, 302, 544, 386, 431, 359, 609, 610, - 0, 661, 898, 863, 864, 865, 799, 866, 860, 861, - 800, 862, 899, 852, 895, 896, 828, 857, 867, 894, - 868, 897, 900, 901, 941, 942, 874, 858, 264, 943, - 871, 902, 893, 892, 869, 853, 903, 904, 835, 830, - 872, 873, 859, 878, 879, 880, 883, 801, 884, 885, - 886, 887, 888, 882, 881, 849, 850, 851, 875, 876, - 856, 831, 832, 833, 834, 0, 0, 494, 495, 496, - 519, 0, 497, 480, 543, 673, 0, 0, 0, 0, - 0, 0, 0, 594, 605, 639, 0, 649, 650, 652, - 654, 889, 656, 454, 455, 662, 0, 877, 659, 660, - 657, 390, 441, 460, 448, 0, 679, 534, 535, 680, - 645, 845, 794, 0, 2370, 0, 0, 0, 0, 0, - 417, 0, 0, 549, 583, 572, 655, 537, 0, 0, - 0, 0, 0, 0, 797, 0, 0, 0, 352, 0, - 0, 385, 587, 568, 579, 569, 554, 555, 556, 563, - 364, 557, 558, 559, 529, 560, 530, 561, 562, 836, - 586, 536, 450, 401, 0, 603, 0, 0, 915, 923, - 0, 0, 0, 0, 0, 0, 0, 0, 911, 0, - 0, 0, 0, 789, 0, 0, 826, 891, 890, 813, - 823, 0, 0, 321, 235, 531, 651, 533, 532, 814, - 0, 815, 819, 822, 818, 816, 817, 0, 906, 0, - 0, 0, 0, 0, 0, 781, 793, 0, 798, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 790, 791, 0, 0, 0, 0, - 846, 0, 792, 0, 0, 0, 0, 0, 451, 479, - 0, 491, 0, 375, 376, 841, 820, 824, 0, 0, - 0, 0, 309, 457, 476, 322, 445, 489, 327, 453, - 468, 317, 416, 442, 0, 0, 311, 474, 452, 398, - 310, 0, 436, 350, 366, 347, 414, 821, 844, 848, - 346, 929, 842, 484, 313, 0, 483, 413, 470, 475, - 399, 392, 0, 312, 472, 397, 391, 379, 356, 930, - 380, 381, 370, 426, 389, 427, 371, 403, 402, 404, - 0, 0, 0, 0, 0, 513, 514, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 644, 839, 0, 648, 0, 486, 0, 0, - 913, 0, 0, 0, 456, 0, 0, 382, 0, 0, - 0, 843, 0, 439, 419, 926, 0, 0, 437, 387, - 471, 428, 477, 458, 485, 433, 429, 303, 459, 349, - 400, 318, 320, 672, 351, 353, 357, 358, 409, 410, - 423, 444, 461, 462, 463, 348, 332, 438, 333, 368, - 334, 304, 340, 338, 341, 446, 342, 306, 424, 467, - 0, 363, 434, 395, 307, 394, 425, 466, 465, 319, - 493, 500, 501, 591, 0, 506, 683, 684, 685, 515, - 0, 430, 315, 314, 0, 0, 0, 344, 328, 330, - 331, 329, 422, 520, 521, 522, 524, 525, 526, 527, - 592, 608, 576, 545, 508, 600, 542, 546, 547, 373, - 611, 0, 0, 0, 499, 383, 384, 0, 355, 354, - 396, 308, 0, 0, 361, 300, 301, 678, 910, 415, - 613, 646, 647, 538, 0, 925, 905, 907, 908, 912, - 916, 917, 918, 919, 920, 922, 924, 928, 677, 0, - 593, 607, 681, 606, 674, 421, 0, 443, 604, 551, - 0, 597, 570, 571, 0, 598, 566, 602, 0, 540, - 0, 509, 512, 541, 626, 627, 628, 305, 511, 630, - 631, 632, 633, 634, 635, 636, 629, 927, 574, 550, - 577, 490, 553, 552, 0, 0, 588, 847, 589, 590, - 405, 406, 407, 408, 914, 614, 326, 510, 432, 0, - 575, 0, 0, 0, 0, 0, 0, 0, 0, 580, - 581, 578, 686, 0, 637, 638, 0, 0, 504, 505, - 360, 367, 523, 369, 325, 420, 362, 488, 377, 0, - 516, 582, 517, 640, 643, 641, 642, 412, 372, 374, - 447, 378, 388, 435, 487, 418, 440, 323, 478, 449, - 393, 567, 595, 936, 909, 935, 937, 938, 934, 939, - 940, 921, 802, 0, 854, 855, 932, 931, 933, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 622, 621, 620, 619, 618, 617, 616, 615, 0, 0, - 564, 464, 339, 294, 335, 336, 343, 675, 671, 469, - 676, 809, 302, 544, 386, 431, 359, 609, 610, 0, - 661, 898, 863, 864, 865, 799, 866, 860, 861, 800, - 862, 899, 852, 895, 896, 828, 857, 867, 894, 868, - 897, 900, 901, 941, 942, 874, 858, 264, 943, 871, - 902, 893, 892, 869, 853, 903, 904, 835, 830, 872, - 873, 859, 878, 879, 880, 883, 801, 884, 885, 886, - 887, 888, 882, 881, 849, 850, 851, 875, 876, 856, - 831, 832, 833, 834, 0, 0, 494, 495, 496, 519, - 0, 497, 480, 543, 673, 0, 0, 0, 0, 0, - 0, 0, 594, 605, 639, 0, 649, 650, 652, 654, - 889, 656, 454, 455, 662, 0, 877, 659, 660, 657, - 390, 441, 460, 448, 845, 679, 534, 535, 680, 645, - 0, 794, 0, 417, 0, 0, 549, 583, 572, 655, - 537, 0, 0, 0, 0, 0, 0, 797, 0, 0, - 0, 352, 0, 0, 385, 587, 568, 579, 569, 554, - 555, 556, 563, 364, 557, 558, 559, 529, 560, 530, - 561, 562, 836, 586, 536, 450, 401, 0, 603, 0, - 0, 915, 923, 0, 0, 0, 0, 0, 0, 0, - 0, 911, 0, 0, 0, 0, 789, 0, 0, 826, - 891, 890, 813, 823, 0, 0, 321, 235, 531, 651, - 533, 532, 814, 0, 815, 819, 822, 818, 816, 817, - 0, 906, 0, 0, 0, 0, 0, 0, 781, 793, - 0, 798, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 790, 791, 1953, - 0, 0, 0, 846, 0, 792, 0, 0, 0, 0, - 0, 451, 479, 0, 491, 0, 375, 376, 841, 820, - 824, 0, 0, 0, 0, 309, 457, 476, 322, 445, - 489, 327, 453, 468, 317, 416, 442, 0, 0, 311, - 474, 452, 398, 310, 0, 436, 350, 366, 347, 414, - 821, 844, 848, 346, 929, 842, 484, 313, 0, 483, - 413, 470, 475, 399, 392, 0, 312, 472, 397, 391, - 379, 356, 930, 380, 381, 370, 426, 389, 427, 371, - 403, 402, 404, 0, 0, 0, 0, 0, 513, 514, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 644, 839, 0, 648, 0, - 486, 0, 0, 913, 0, 0, 0, 456, 0, 0, - 382, 0, 0, 0, 843, 0, 439, 419, 926, 0, - 0, 437, 387, 471, 428, 477, 458, 485, 433, 429, - 303, 459, 349, 400, 318, 320, 672, 351, 353, 357, - 358, 409, 410, 423, 444, 461, 462, 463, 348, 332, - 438, 333, 368, 334, 304, 340, 338, 341, 446, 342, - 306, 424, 467, 0, 363, 434, 395, 307, 394, 425, - 466, 465, 319, 493, 500, 501, 591, 0, 506, 683, - 684, 685, 515, 0, 430, 315, 314, 0, 0, 0, - 344, 328, 330, 331, 329, 422, 520, 521, 522, 524, - 525, 526, 527, 592, 608, 576, 545, 508, 600, 542, - 546, 547, 373, 611, 0, 0, 0, 499, 383, 384, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 911, 415, 614, + 647, 648, 539, 0, 926, 906, 908, 909, 913, 917, + 918, 919, 920, 921, 923, 925, 929, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 928, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 848, 590, 591, 405, + 406, 407, 408, 915, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 937, 910, 936, 938, 939, 935, 940, 941, + 922, 803, 0, 855, 856, 933, 932, 934, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 810, 302, 545, 386, 432, 359, 610, 611, 0, 662, + 899, 864, 865, 866, 800, 867, 861, 862, 801, 863, + 900, 853, 896, 897, 829, 858, 868, 895, 869, 898, + 901, 902, 942, 943, 875, 859, 264, 944, 872, 903, + 894, 893, 870, 854, 904, 905, 836, 831, 873, 874, + 860, 879, 880, 881, 884, 802, 885, 886, 887, 888, + 889, 883, 882, 850, 851, 852, 876, 877, 857, 832, + 833, 834, 835, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 890, + 657, 455, 456, 663, 0, 878, 660, 661, 658, 390, + 442, 461, 449, 846, 680, 535, 536, 681, 646, 0, + 795, 0, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 798, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 837, 587, 537, 451, 401, 0, 604, 0, 0, + 916, 924, 0, 0, 0, 0, 0, 0, 0, 0, + 912, 0, 0, 0, 0, 790, 0, 0, 827, 892, + 891, 814, 824, 0, 0, 321, 235, 532, 652, 534, + 533, 815, 0, 816, 820, 823, 819, 817, 818, 0, + 907, 0, 0, 0, 0, 0, 0, 782, 794, 0, + 799, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 791, 792, 1658, 0, + 0, 0, 847, 0, 793, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 842, 821, 825, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 822, + 845, 849, 346, 930, 843, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 931, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 840, 0, 649, 0, 487, + 0, 0, 914, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 844, 0, 440, 419, 927, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, - 678, 910, 415, 613, 646, 647, 538, 0, 925, 905, - 907, 908, 912, 916, 917, 918, 919, 920, 922, 924, - 928, 677, 0, 593, 607, 681, 606, 674, 421, 0, - 443, 604, 551, 0, 597, 570, 571, 0, 598, 566, - 602, 0, 540, 0, 509, 512, 541, 626, 627, 628, - 305, 511, 630, 631, 632, 633, 634, 635, 636, 629, - 927, 574, 550, 577, 490, 553, 552, 0, 0, 588, - 847, 589, 590, 405, 406, 407, 408, 914, 614, 326, - 510, 432, 0, 575, 0, 0, 0, 0, 0, 0, - 0, 0, 580, 581, 578, 686, 0, 637, 638, 0, - 0, 504, 505, 360, 367, 523, 369, 325, 420, 362, - 488, 377, 0, 516, 582, 517, 640, 643, 641, 642, - 412, 372, 374, 447, 378, 388, 435, 487, 418, 440, - 323, 478, 449, 393, 567, 595, 936, 909, 935, 937, - 938, 934, 939, 940, 921, 802, 0, 854, 855, 932, - 931, 933, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 622, 621, 620, 619, 618, 617, 616, - 615, 0, 0, 564, 464, 339, 294, 335, 336, 343, - 675, 671, 469, 676, 809, 302, 544, 386, 431, 359, - 609, 610, 0, 661, 898, 863, 864, 865, 799, 866, - 860, 861, 800, 862, 899, 852, 895, 896, 828, 857, - 867, 894, 868, 897, 900, 901, 941, 942, 874, 858, - 264, 943, 871, 902, 893, 892, 869, 853, 903, 904, - 835, 830, 872, 873, 859, 878, 879, 880, 883, 801, - 884, 885, 886, 887, 888, 882, 881, 849, 850, 851, - 875, 876, 856, 831, 832, 833, 834, 0, 0, 494, - 495, 496, 519, 0, 497, 480, 543, 673, 0, 0, - 0, 0, 0, 0, 0, 594, 605, 639, 0, 649, - 650, 652, 654, 889, 656, 454, 455, 662, 0, 877, - 659, 660, 657, 390, 441, 460, 448, 845, 679, 534, - 535, 680, 645, 0, 794, 0, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 0, - 797, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 836, 586, 536, 450, 401, - 0, 603, 0, 0, 915, 923, 0, 0, 0, 0, - 0, 0, 0, 0, 911, 0, 0, 0, 0, 789, - 0, 0, 826, 891, 890, 813, 823, 0, 0, 321, - 235, 531, 651, 533, 532, 814, 0, 815, 819, 822, - 818, 816, 817, 0, 906, 0, 0, 0, 0, 0, - 0, 781, 793, 0, 798, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 790, 791, 0, 0, 0, 0, 846, 0, 792, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 841, 820, 824, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 821, 844, 848, 346, 929, 842, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 930, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 839, - 0, 648, 0, 486, 0, 0, 913, 0, 0, 0, - 456, 0, 0, 382, 0, 0, 0, 843, 0, 439, - 419, 926, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 910, 415, 613, 646, 647, 538, - 0, 925, 905, 907, 908, 912, 916, 917, 918, 919, - 920, 922, 924, 928, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 927, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 847, 589, 590, 405, 406, 407, 408, - 914, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 936, - 909, 935, 937, 938, 934, 939, 940, 921, 802, 0, - 854, 855, 932, 931, 933, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 809, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 898, 863, 864, - 865, 799, 866, 860, 861, 800, 862, 899, 852, 895, - 896, 828, 857, 867, 894, 868, 897, 900, 901, 941, - 942, 874, 858, 264, 943, 871, 902, 893, 892, 869, - 853, 903, 904, 835, 830, 872, 873, 859, 878, 879, - 880, 883, 801, 884, 885, 886, 887, 888, 882, 881, - 849, 850, 851, 875, 876, 856, 831, 832, 833, 834, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 889, 656, 454, 455, - 662, 0, 877, 659, 660, 657, 390, 441, 460, 448, - 845, 679, 534, 535, 680, 645, 0, 794, 0, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 797, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 836, 586, - 536, 450, 401, 0, 603, 0, 0, 915, 923, 0, - 0, 0, 0, 0, 0, 0, 0, 911, 0, 0, - 0, 0, 789, 0, 0, 826, 891, 890, 813, 823, - 0, 0, 321, 235, 531, 651, 533, 532, 814, 0, - 815, 819, 822, 818, 816, 817, 0, 906, 0, 0, - 0, 0, 0, 0, 781, 793, 0, 798, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 790, 791, 0, 0, 0, 0, 846, - 0, 792, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 841, 820, 824, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 821, 844, 848, 346, - 929, 842, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 930, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 839, 0, 648, 0, 486, 0, 0, 913, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 843, 0, 439, 419, 926, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 910, 415, 613, - 646, 647, 538, 0, 925, 905, 907, 908, 912, 916, - 917, 918, 919, 920, 922, 924, 928, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 927, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 847, 589, 590, 405, - 406, 407, 408, 914, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 936, 909, 935, 937, 938, 934, 939, 940, - 921, 802, 0, 854, 855, 932, 931, 933, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 809, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 898, 863, 864, 865, 799, 866, 860, 861, 800, 862, - 899, 852, 895, 896, 828, 857, 867, 894, 868, 897, - 900, 901, 941, 942, 874, 858, 264, 943, 871, 902, - 893, 892, 869, 853, 903, 904, 835, 830, 872, 873, - 859, 878, 879, 880, 883, 801, 884, 885, 886, 887, - 888, 882, 881, 849, 850, 851, 875, 876, 856, 831, - 832, 833, 834, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 889, - 656, 454, 455, 662, 0, 3754, 659, 3755, 3756, 390, - 441, 460, 448, 845, 679, 534, 535, 680, 645, 0, - 794, 0, 417, 0, 0, 549, 583, 572, 655, 537, - 0, 0, 0, 0, 0, 0, 797, 0, 0, 0, - 352, 0, 0, 385, 587, 568, 579, 569, 554, 555, - 556, 563, 364, 557, 558, 559, 529, 560, 530, 561, - 562, 836, 586, 536, 450, 401, 0, 603, 0, 0, - 915, 923, 0, 0, 0, 0, 0, 0, 0, 0, - 911, 0, 0, 0, 0, 789, 0, 0, 826, 891, - 890, 813, 823, 0, 0, 321, 235, 531, 651, 533, - 532, 2881, 0, 2882, 819, 822, 818, 816, 817, 0, - 906, 0, 0, 0, 0, 0, 0, 781, 793, 0, - 798, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 790, 791, 0, 0, - 0, 0, 846, 0, 792, 0, 0, 0, 0, 0, - 451, 479, 0, 491, 0, 375, 376, 841, 820, 824, - 0, 0, 0, 0, 309, 457, 476, 322, 445, 489, - 327, 453, 468, 317, 416, 442, 0, 0, 311, 474, - 452, 398, 310, 0, 436, 350, 366, 347, 414, 821, - 844, 848, 346, 929, 842, 484, 313, 0, 483, 413, - 470, 475, 399, 392, 0, 312, 472, 397, 391, 379, - 356, 930, 380, 381, 370, 426, 389, 427, 371, 403, - 402, 404, 0, 0, 0, 0, 0, 513, 514, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 644, 839, 0, 648, 0, 486, - 0, 0, 913, 0, 0, 0, 456, 0, 0, 382, - 0, 0, 0, 843, 0, 439, 419, 926, 0, 0, - 437, 387, 471, 428, 477, 458, 485, 433, 429, 303, - 459, 349, 400, 318, 320, 672, 351, 353, 357, 358, - 409, 410, 423, 444, 461, 462, 463, 348, 332, 438, - 333, 368, 334, 304, 340, 338, 341, 446, 342, 306, - 424, 467, 0, 363, 434, 395, 307, 394, 425, 466, - 465, 319, 493, 500, 501, 591, 0, 506, 683, 684, - 685, 515, 0, 430, 315, 314, 0, 0, 0, 344, - 328, 330, 331, 329, 422, 520, 521, 522, 524, 525, - 526, 527, 592, 608, 576, 545, 508, 600, 542, 546, - 547, 373, 611, 0, 0, 0, 499, 383, 384, 0, - 355, 354, 396, 308, 0, 0, 361, 300, 301, 678, - 910, 415, 613, 646, 647, 538, 0, 925, 905, 907, - 908, 912, 916, 917, 918, 919, 920, 922, 924, 928, - 677, 0, 593, 607, 681, 606, 674, 421, 0, 443, - 604, 551, 0, 597, 570, 571, 0, 598, 566, 602, - 0, 540, 0, 509, 512, 541, 626, 627, 628, 305, - 511, 630, 631, 632, 633, 634, 635, 636, 629, 927, - 574, 550, 577, 490, 553, 552, 0, 0, 588, 847, - 589, 590, 405, 406, 407, 408, 914, 614, 326, 510, - 432, 0, 575, 0, 0, 0, 0, 0, 0, 0, - 0, 580, 581, 578, 686, 0, 637, 638, 0, 0, - 504, 505, 360, 367, 523, 369, 325, 420, 362, 488, - 377, 0, 516, 582, 517, 640, 643, 641, 642, 412, - 372, 374, 447, 378, 388, 435, 487, 418, 440, 323, - 478, 449, 393, 567, 595, 936, 909, 935, 937, 938, - 934, 939, 940, 921, 802, 0, 854, 855, 932, 931, - 933, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 622, 621, 620, 619, 618, 617, 616, 615, - 0, 0, 564, 464, 339, 294, 335, 336, 343, 675, - 671, 469, 676, 809, 302, 544, 386, 431, 359, 609, - 610, 0, 661, 898, 863, 864, 865, 799, 866, 860, - 861, 800, 862, 899, 852, 895, 896, 828, 857, 867, - 894, 868, 897, 900, 901, 941, 942, 874, 858, 264, - 943, 871, 902, 893, 892, 869, 853, 903, 904, 835, - 830, 872, 873, 859, 878, 879, 880, 883, 801, 884, - 885, 886, 887, 888, 882, 881, 849, 850, 851, 875, - 876, 856, 831, 832, 833, 834, 0, 0, 494, 495, - 496, 519, 0, 497, 480, 543, 673, 0, 0, 0, - 0, 0, 0, 0, 594, 605, 639, 0, 649, 650, - 652, 654, 889, 656, 454, 455, 662, 0, 877, 659, - 660, 657, 390, 441, 460, 448, 845, 679, 534, 535, - 680, 645, 0, 794, 0, 417, 0, 0, 549, 583, - 572, 655, 537, 0, 0, 1798, 0, 0, 0, 797, - 0, 0, 0, 352, 0, 0, 385, 587, 568, 579, - 569, 554, 555, 556, 563, 364, 557, 558, 559, 529, - 560, 530, 561, 562, 836, 586, 536, 450, 401, 0, - 603, 0, 0, 915, 923, 0, 0, 0, 0, 0, - 0, 0, 0, 911, 0, 0, 0, 0, 789, 0, - 0, 826, 891, 890, 813, 823, 0, 0, 321, 235, - 531, 651, 533, 532, 814, 0, 815, 819, 822, 818, - 816, 817, 0, 906, 0, 0, 0, 0, 0, 0, - 0, 793, 0, 798, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 790, - 791, 0, 0, 0, 0, 846, 0, 792, 0, 0, - 0, 0, 0, 451, 479, 0, 491, 0, 375, 376, - 841, 820, 824, 0, 0, 0, 0, 309, 457, 476, - 322, 445, 489, 327, 453, 468, 317, 416, 442, 0, - 0, 311, 474, 452, 398, 310, 0, 436, 350, 366, - 347, 414, 821, 844, 848, 346, 929, 842, 484, 313, - 0, 483, 413, 470, 475, 399, 392, 0, 312, 472, - 397, 391, 379, 356, 930, 380, 381, 370, 426, 389, - 427, 371, 403, 402, 404, 0, 0, 0, 0, 0, - 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 644, 839, 0, - 648, 0, 486, 0, 0, 913, 0, 0, 0, 456, - 0, 0, 382, 0, 0, 0, 843, 0, 439, 419, - 926, 0, 0, 437, 387, 471, 428, 477, 458, 485, - 433, 429, 303, 459, 349, 400, 318, 320, 672, 351, - 353, 357, 358, 409, 410, 423, 444, 461, 462, 463, - 348, 332, 438, 333, 368, 334, 304, 340, 338, 341, - 446, 342, 306, 424, 467, 0, 363, 434, 395, 307, - 394, 425, 466, 465, 319, 493, 1799, 1800, 591, 0, - 506, 683, 684, 685, 515, 0, 430, 315, 314, 0, - 0, 0, 344, 328, 330, 331, 329, 422, 520, 521, - 522, 524, 525, 526, 527, 592, 608, 576, 545, 508, - 600, 542, 546, 547, 373, 611, 0, 0, 0, 499, + 679, 911, 415, 614, 647, 648, 539, 0, 926, 906, + 908, 909, 913, 917, 918, 919, 920, 921, 923, 925, + 929, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 928, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 848, 590, 591, 405, 406, 407, 408, 915, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 937, 910, 936, 938, + 939, 935, 940, 941, 922, 803, 0, 855, 856, 933, + 932, 934, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 810, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 899, 864, 865, 866, 800, 867, + 861, 862, 801, 863, 900, 853, 896, 897, 829, 858, + 868, 895, 869, 898, 901, 902, 942, 943, 875, 859, + 264, 944, 872, 903, 894, 893, 870, 854, 904, 905, + 836, 831, 873, 874, 860, 879, 880, 881, 884, 802, + 885, 886, 887, 888, 889, 883, 882, 850, 851, 852, + 876, 877, 857, 832, 833, 834, 835, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 890, 657, 455, 456, 663, 0, 878, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 846, 795, 0, 2371, 0, 0, 0, + 0, 0, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 798, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 837, 587, 537, 451, 401, 0, 604, 0, 0, + 916, 924, 0, 0, 0, 0, 0, 0, 0, 0, + 912, 0, 0, 0, 0, 790, 0, 0, 827, 892, + 891, 814, 824, 0, 0, 321, 235, 532, 652, 534, + 533, 815, 0, 816, 820, 823, 819, 817, 818, 0, + 907, 0, 0, 0, 0, 0, 0, 782, 794, 0, + 799, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 791, 792, 0, 0, + 0, 0, 847, 0, 793, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 842, 821, 825, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 822, + 845, 849, 346, 930, 843, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 931, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 840, 0, 649, 0, 487, + 0, 0, 914, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 844, 0, 440, 419, 927, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 911, 415, 614, 647, 648, 539, 0, 926, 906, + 908, 909, 913, 917, 918, 919, 920, 921, 923, 925, + 929, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 928, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 848, 590, 591, 405, 406, 407, 408, 915, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 937, 910, 936, 938, + 939, 935, 940, 941, 922, 803, 0, 855, 856, 933, + 932, 934, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 810, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 899, 864, 865, 866, 800, 867, + 861, 862, 801, 863, 900, 853, 896, 897, 829, 858, + 868, 895, 869, 898, 901, 902, 942, 943, 875, 859, + 264, 944, 872, 903, 894, 893, 870, 854, 904, 905, + 836, 831, 873, 874, 860, 879, 880, 881, 884, 802, + 885, 886, 887, 888, 889, 883, 882, 850, 851, 852, + 876, 877, 857, 832, 833, 834, 835, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 890, 657, 455, 456, 663, 0, 878, + 660, 661, 658, 390, 442, 461, 449, 846, 680, 535, + 536, 681, 646, 0, 795, 0, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 798, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 837, 587, 537, 451, 401, + 0, 604, 0, 0, 916, 924, 0, 0, 0, 0, + 0, 0, 0, 0, 912, 0, 0, 0, 0, 790, + 0, 0, 827, 892, 891, 814, 824, 0, 0, 321, + 235, 532, 652, 534, 533, 815, 0, 816, 820, 823, + 819, 817, 818, 0, 907, 0, 0, 0, 0, 0, + 0, 782, 794, 0, 799, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 791, 792, 1954, 0, 0, 0, 847, 0, 793, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 842, 821, 825, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 822, 845, 849, 346, 930, 843, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 931, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 840, + 0, 649, 0, 487, 0, 0, 914, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 844, 0, 440, + 419, 927, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 911, 415, 614, 647, 648, + 539, 0, 926, 906, 908, 909, 913, 917, 918, 919, + 920, 921, 923, 925, 929, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 928, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 848, 590, 591, 405, 406, 407, + 408, 915, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, + 937, 910, 936, 938, 939, 935, 940, 941, 922, 803, + 0, 855, 856, 933, 932, 934, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 810, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 899, 864, + 865, 866, 800, 867, 861, 862, 801, 863, 900, 853, + 896, 897, 829, 858, 868, 895, 869, 898, 901, 902, + 942, 943, 875, 859, 264, 944, 872, 903, 894, 893, + 870, 854, 904, 905, 836, 831, 873, 874, 860, 879, + 880, 881, 884, 802, 885, 886, 887, 888, 889, 883, + 882, 850, 851, 852, 876, 877, 857, 832, 833, 834, + 835, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 890, 657, 455, + 456, 663, 0, 878, 660, 661, 658, 390, 442, 461, + 449, 846, 680, 535, 536, 681, 646, 0, 795, 0, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 798, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 837, + 587, 537, 451, 401, 0, 604, 0, 0, 916, 924, + 0, 0, 0, 0, 0, 0, 0, 0, 912, 0, + 0, 0, 0, 790, 0, 0, 827, 892, 891, 814, + 824, 0, 0, 321, 235, 532, 652, 534, 533, 815, + 0, 816, 820, 823, 819, 817, 818, 0, 907, 0, + 0, 0, 0, 0, 0, 782, 794, 0, 799, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 791, 792, 0, 0, 0, 0, + 847, 0, 793, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 842, 821, 825, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 822, 845, 849, + 346, 930, 843, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 931, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 840, 0, 649, 0, 487, 0, 0, + 914, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 844, 0, 440, 419, 927, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 911, + 415, 614, 647, 648, 539, 0, 926, 906, 908, 909, + 913, 917, 918, 919, 920, 921, 923, 925, 929, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 928, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 848, 590, + 591, 405, 406, 407, 408, 915, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 937, 910, 936, 938, 939, 935, + 940, 941, 922, 803, 0, 855, 856, 933, 932, 934, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 810, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 899, 864, 865, 866, 800, 867, 861, 862, + 801, 863, 900, 853, 896, 897, 829, 858, 868, 895, + 869, 898, 901, 902, 942, 943, 875, 859, 264, 944, + 872, 903, 894, 893, 870, 854, 904, 905, 836, 831, + 873, 874, 860, 879, 880, 881, 884, 802, 885, 886, + 887, 888, 889, 883, 882, 850, 851, 852, 876, 877, + 857, 832, 833, 834, 835, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 890, 657, 455, 456, 663, 0, 878, 660, 661, + 658, 390, 442, 461, 449, 846, 680, 535, 536, 681, + 646, 0, 795, 0, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 0, 798, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 837, 587, 537, 451, 401, 0, 604, + 0, 0, 916, 924, 0, 0, 0, 0, 0, 0, + 0, 0, 912, 0, 0, 0, 0, 790, 0, 0, + 827, 892, 891, 814, 824, 0, 0, 321, 235, 532, + 652, 534, 533, 815, 0, 816, 820, 823, 819, 817, + 818, 0, 907, 0, 0, 0, 0, 0, 0, 782, + 794, 0, 799, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 791, 792, + 0, 0, 0, 0, 847, 0, 793, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 842, + 821, 825, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 822, 845, 849, 346, 930, 843, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 931, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 840, 0, 649, + 0, 487, 0, 0, 914, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 844, 0, 440, 419, 927, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, - 300, 301, 678, 910, 415, 613, 646, 647, 538, 0, - 925, 905, 907, 908, 912, 916, 917, 918, 919, 920, - 922, 924, 928, 677, 0, 593, 607, 681, 606, 674, - 421, 0, 443, 604, 551, 0, 597, 570, 571, 0, - 598, 566, 602, 0, 540, 0, 509, 512, 541, 626, - 627, 628, 305, 511, 630, 631, 632, 633, 634, 635, - 636, 629, 927, 574, 550, 577, 490, 553, 552, 0, - 0, 588, 847, 589, 590, 405, 406, 407, 408, 914, - 614, 326, 510, 432, 0, 575, 0, 0, 0, 0, - 0, 0, 0, 0, 580, 581, 578, 686, 0, 637, - 638, 0, 0, 504, 505, 360, 367, 523, 369, 325, - 420, 362, 488, 377, 0, 516, 582, 517, 640, 643, - 641, 642, 412, 372, 374, 447, 378, 388, 435, 487, - 418, 440, 323, 478, 449, 393, 567, 595, 936, 909, - 935, 937, 938, 934, 939, 940, 921, 802, 0, 854, - 855, 932, 931, 933, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 622, 621, 620, 619, 618, - 617, 616, 615, 0, 0, 564, 464, 339, 294, 335, - 336, 343, 675, 671, 469, 676, 809, 302, 544, 386, - 431, 359, 609, 610, 0, 661, 898, 863, 864, 865, - 799, 866, 860, 861, 800, 862, 899, 852, 895, 896, - 828, 857, 867, 894, 868, 897, 900, 901, 941, 942, - 874, 858, 264, 943, 871, 902, 893, 892, 869, 853, - 903, 904, 835, 830, 872, 873, 859, 878, 879, 880, - 883, 801, 884, 885, 886, 887, 888, 882, 881, 849, - 850, 851, 875, 876, 856, 831, 832, 833, 834, 0, - 0, 494, 495, 496, 519, 0, 497, 480, 543, 673, - 0, 0, 0, 0, 0, 0, 0, 594, 605, 639, - 0, 649, 650, 652, 654, 889, 656, 454, 455, 662, - 0, 877, 659, 660, 657, 390, 441, 460, 448, 845, - 679, 534, 535, 680, 645, 0, 794, 0, 417, 0, - 0, 549, 583, 572, 655, 537, 0, 0, 0, 0, - 0, 0, 797, 0, 0, 0, 352, 0, 0, 385, - 587, 568, 579, 569, 554, 555, 556, 563, 364, 557, - 558, 559, 529, 560, 530, 561, 562, 836, 586, 536, - 450, 401, 0, 603, 0, 0, 915, 923, 0, 0, - 0, 0, 0, 0, 0, 0, 911, 0, 0, 0, - 0, 789, 0, 0, 826, 891, 890, 813, 823, 0, - 0, 321, 235, 531, 651, 533, 532, 814, 0, 815, - 819, 822, 818, 816, 817, 0, 906, 0, 0, 0, - 0, 0, 0, 0, 793, 0, 798, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 790, 791, 0, 0, 0, 0, 846, 0, - 792, 0, 0, 0, 0, 0, 451, 479, 0, 491, - 0, 375, 376, 841, 820, 824, 0, 0, 0, 0, - 309, 457, 476, 322, 445, 489, 327, 453, 468, 317, - 416, 442, 0, 0, 311, 474, 452, 398, 310, 0, - 436, 350, 366, 347, 414, 821, 844, 848, 346, 929, - 842, 484, 313, 0, 483, 413, 470, 475, 399, 392, - 0, 312, 472, 397, 391, 379, 356, 930, 380, 381, - 370, 426, 389, 427, 371, 403, 402, 404, 0, 0, - 0, 0, 0, 513, 514, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 644, 839, 0, 648, 0, 486, 0, 0, 913, 0, - 0, 0, 456, 0, 0, 382, 0, 0, 0, 843, - 0, 439, 419, 926, 0, 0, 437, 387, 471, 428, - 477, 458, 485, 433, 429, 303, 459, 349, 400, 318, - 320, 672, 351, 353, 357, 358, 409, 410, 423, 444, - 461, 462, 463, 348, 332, 438, 333, 368, 334, 304, - 340, 338, 341, 446, 342, 306, 424, 467, 0, 363, - 434, 395, 307, 394, 425, 466, 465, 319, 493, 500, - 501, 591, 0, 506, 683, 684, 685, 515, 0, 430, + 300, 301, 679, 911, 415, 614, 647, 648, 539, 0, + 926, 906, 908, 909, 913, 917, 918, 919, 920, 921, + 923, 925, 929, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 928, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 848, 590, 591, 405, 406, 407, 408, 915, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 937, 910, + 936, 938, 939, 935, 940, 941, 922, 803, 0, 855, + 856, 933, 932, 934, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 810, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 899, 864, 865, 866, + 800, 867, 861, 862, 801, 863, 900, 853, 896, 897, + 829, 858, 868, 895, 869, 898, 901, 902, 942, 943, + 875, 859, 264, 944, 872, 903, 894, 893, 870, 854, + 904, 905, 836, 831, 873, 874, 860, 879, 880, 881, + 884, 802, 885, 886, 887, 888, 889, 883, 882, 850, + 851, 852, 876, 877, 857, 832, 833, 834, 835, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 890, 657, 455, 456, 663, + 0, 3756, 660, 3757, 3758, 390, 442, 461, 449, 846, + 680, 535, 536, 681, 646, 0, 795, 0, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 798, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 837, 587, 537, + 451, 401, 0, 604, 0, 0, 916, 924, 0, 0, + 0, 0, 0, 0, 0, 0, 912, 0, 0, 0, + 0, 790, 0, 0, 827, 892, 891, 814, 824, 0, + 0, 321, 235, 532, 652, 534, 533, 2882, 0, 2883, + 820, 823, 819, 817, 818, 0, 907, 0, 0, 0, + 0, 0, 0, 782, 794, 0, 799, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 791, 792, 0, 0, 0, 0, 847, 0, + 793, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 842, 821, 825, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 822, 845, 849, 346, 930, + 843, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 931, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 840, 0, 649, 0, 487, 0, 0, 914, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 844, + 0, 440, 419, 927, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, - 422, 520, 521, 522, 524, 525, 526, 527, 592, 608, - 576, 545, 508, 600, 542, 546, 547, 373, 611, 0, - 0, 0, 499, 383, 384, 0, 355, 354, 396, 308, - 0, 0, 361, 300, 301, 678, 910, 415, 613, 646, - 647, 538, 0, 925, 905, 907, 908, 912, 916, 917, - 918, 919, 920, 922, 924, 928, 677, 0, 593, 607, - 681, 606, 674, 421, 0, 443, 604, 551, 0, 597, - 570, 571, 0, 598, 566, 602, 0, 540, 0, 509, - 512, 541, 626, 627, 628, 305, 511, 630, 631, 632, - 633, 634, 635, 636, 629, 927, 574, 550, 577, 490, - 553, 552, 0, 0, 588, 847, 589, 590, 405, 406, - 407, 408, 914, 614, 326, 510, 432, 0, 575, 0, - 0, 0, 0, 0, 0, 0, 0, 580, 581, 578, - 686, 0, 637, 638, 0, 0, 504, 505, 360, 367, - 523, 369, 325, 420, 362, 488, 377, 0, 516, 582, - 517, 640, 643, 641, 642, 412, 372, 374, 447, 378, - 388, 435, 487, 418, 440, 323, 478, 449, 393, 567, - 595, 936, 909, 935, 937, 938, 934, 939, 940, 921, - 802, 0, 854, 855, 932, 931, 933, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 622, 621, - 620, 619, 618, 617, 616, 615, 0, 0, 564, 464, - 339, 294, 335, 336, 343, 675, 671, 469, 676, 809, - 302, 544, 386, 431, 359, 609, 610, 0, 661, 898, - 863, 864, 865, 799, 866, 860, 861, 800, 862, 899, - 852, 895, 896, 828, 857, 867, 894, 868, 897, 900, - 901, 941, 942, 874, 858, 264, 943, 871, 902, 893, - 892, 869, 853, 903, 904, 835, 830, 872, 873, 859, - 878, 879, 880, 883, 801, 884, 885, 886, 887, 888, - 882, 881, 849, 850, 851, 875, 876, 856, 831, 832, - 833, 834, 0, 0, 494, 495, 496, 519, 0, 497, - 480, 543, 673, 0, 0, 0, 0, 0, 0, 0, - 594, 605, 639, 0, 649, 650, 652, 654, 889, 656, - 454, 455, 662, 0, 877, 659, 660, 657, 390, 441, - 460, 448, 845, 679, 534, 535, 680, 645, 0, 794, - 0, 417, 0, 0, 549, 583, 572, 655, 537, 0, - 0, 0, 0, 0, 0, 797, 0, 0, 0, 352, - 0, 0, 385, 587, 568, 579, 569, 554, 555, 556, - 563, 364, 557, 558, 559, 529, 560, 530, 561, 562, - 836, 586, 536, 450, 401, 0, 603, 0, 0, 915, - 923, 0, 0, 0, 0, 0, 0, 0, 0, 911, - 0, 0, 0, 0, 0, 0, 0, 826, 891, 890, - 813, 823, 0, 0, 321, 235, 531, 651, 533, 532, - 814, 0, 815, 819, 822, 818, 816, 817, 0, 906, - 0, 0, 0, 0, 0, 0, 781, 793, 0, 798, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 790, 791, 0, 0, 0, - 0, 846, 0, 792, 0, 0, 0, 0, 0, 451, - 479, 0, 491, 0, 375, 376, 841, 820, 824, 0, - 0, 0, 0, 309, 457, 476, 322, 445, 489, 327, - 453, 468, 317, 416, 442, 0, 0, 311, 474, 452, - 398, 310, 0, 436, 350, 366, 347, 414, 821, 844, - 848, 346, 929, 842, 484, 313, 0, 483, 413, 470, - 475, 399, 392, 0, 312, 472, 397, 391, 379, 356, - 930, 380, 381, 370, 426, 389, 427, 371, 403, 402, - 404, 0, 0, 0, 0, 0, 513, 514, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 644, 839, 0, 648, 0, 486, 0, - 0, 913, 0, 0, 0, 456, 0, 0, 382, 0, - 0, 0, 843, 0, 439, 419, 926, 0, 0, 437, - 387, 471, 428, 477, 458, 485, 433, 429, 303, 459, - 349, 400, 318, 320, 672, 351, 353, 357, 358, 409, - 410, 423, 444, 461, 462, 463, 348, 332, 438, 333, - 368, 334, 304, 340, 338, 341, 446, 342, 306, 424, - 467, 0, 363, 434, 395, 307, 394, 425, 466, 465, - 319, 493, 500, 501, 591, 0, 506, 683, 684, 685, - 515, 0, 430, 315, 314, 0, 0, 0, 344, 328, - 330, 331, 329, 422, 520, 521, 522, 524, 525, 526, - 527, 592, 608, 576, 545, 508, 600, 542, 546, 547, - 373, 611, 0, 0, 0, 499, 383, 384, 0, 355, - 354, 396, 308, 0, 0, 361, 300, 301, 678, 910, - 415, 613, 646, 647, 538, 0, 925, 905, 907, 908, - 912, 916, 917, 918, 919, 920, 922, 924, 928, 677, - 0, 593, 607, 681, 606, 674, 421, 0, 443, 604, - 551, 0, 597, 570, 571, 0, 598, 566, 602, 0, - 540, 0, 509, 512, 541, 626, 627, 628, 305, 511, - 630, 631, 632, 633, 634, 635, 636, 629, 927, 574, - 550, 577, 490, 553, 552, 0, 0, 588, 847, 589, - 590, 405, 406, 407, 408, 914, 614, 326, 510, 432, - 0, 575, 0, 0, 0, 0, 0, 0, 0, 0, - 580, 581, 578, 686, 0, 637, 638, 0, 0, 504, - 505, 360, 367, 523, 369, 325, 420, 362, 488, 377, - 0, 516, 582, 517, 640, 643, 641, 642, 412, 372, - 374, 447, 378, 388, 435, 487, 418, 440, 323, 478, - 449, 393, 567, 595, 936, 909, 935, 937, 938, 934, - 939, 940, 921, 802, 0, 854, 855, 932, 931, 933, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 622, 621, 620, 619, 618, 617, 616, 615, 0, - 0, 564, 464, 339, 294, 335, 336, 343, 675, 671, - 469, 676, 809, 302, 544, 386, 431, 359, 609, 610, - 0, 661, 898, 863, 864, 865, 799, 866, 860, 861, - 800, 862, 899, 852, 895, 896, 828, 857, 867, 894, - 868, 897, 900, 901, 941, 942, 874, 858, 264, 943, - 871, 902, 893, 892, 869, 853, 903, 904, 835, 830, - 872, 873, 859, 878, 879, 880, 883, 801, 884, 885, - 886, 887, 888, 882, 881, 849, 850, 851, 875, 876, - 856, 831, 832, 833, 834, 0, 0, 494, 495, 496, - 519, 0, 497, 480, 543, 673, 0, 0, 0, 0, - 0, 0, 0, 594, 605, 639, 0, 649, 650, 652, - 654, 889, 656, 454, 455, 662, 0, 877, 659, 660, - 657, 390, 441, 460, 448, 0, 679, 534, 535, 680, - 645, 0, 794, 174, 212, 173, 203, 175, 0, 0, - 0, 0, 0, 0, 417, 0, 0, 549, 583, 572, - 655, 537, 0, 204, 0, 0, 0, 0, 0, 0, - 195, 0, 352, 0, 205, 385, 587, 568, 579, 569, - 554, 555, 556, 563, 364, 557, 558, 559, 529, 560, - 530, 561, 562, 144, 586, 536, 450, 401, 0, 603, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 911, 415, 614, + 647, 648, 539, 0, 926, 906, 908, 909, 913, 917, + 918, 919, 920, 921, 923, 925, 929, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 928, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 848, 590, 591, 405, + 406, 407, 408, 915, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 937, 910, 936, 938, 939, 935, 940, 941, + 922, 803, 0, 855, 856, 933, 932, 934, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 810, 302, 545, 386, 432, 359, 610, 611, 0, 662, + 899, 864, 865, 866, 800, 867, 861, 862, 801, 863, + 900, 853, 896, 897, 829, 858, 868, 895, 869, 898, + 901, 902, 942, 943, 875, 859, 264, 944, 872, 903, + 894, 893, 870, 854, 904, 905, 836, 831, 873, 874, + 860, 879, 880, 881, 884, 802, 885, 886, 887, 888, + 889, 883, 882, 850, 851, 852, 876, 877, 857, 832, + 833, 834, 835, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 890, + 657, 455, 456, 663, 0, 878, 660, 661, 658, 390, + 442, 461, 449, 846, 680, 535, 536, 681, 646, 0, + 795, 0, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 1799, 0, 0, 0, 798, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 837, 587, 537, 451, 401, 0, 604, 0, 0, + 916, 924, 0, 0, 0, 0, 0, 0, 0, 0, + 912, 0, 0, 0, 0, 790, 0, 0, 827, 892, + 891, 814, 824, 0, 0, 321, 235, 532, 652, 534, + 533, 815, 0, 816, 820, 823, 819, 817, 818, 0, + 907, 0, 0, 0, 0, 0, 0, 0, 794, 0, + 799, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 791, 792, 0, 0, + 0, 0, 847, 0, 793, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 842, 821, 825, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 822, + 845, 849, 346, 930, 843, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 931, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 840, 0, 649, 0, 487, + 0, 0, 914, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 844, 0, 440, 419, 927, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 1800, 1801, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 911, 415, 614, 647, 648, 539, 0, 926, 906, + 908, 909, 913, 917, 918, 919, 920, 921, 923, 925, + 929, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 928, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 848, 590, 591, 405, 406, 407, 408, 915, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 937, 910, 936, 938, + 939, 935, 940, 941, 922, 803, 0, 855, 856, 933, + 932, 934, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 810, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 899, 864, 865, 866, 800, 867, + 861, 862, 801, 863, 900, 853, 896, 897, 829, 858, + 868, 895, 869, 898, 901, 902, 942, 943, 875, 859, + 264, 944, 872, 903, 894, 893, 870, 854, 904, 905, + 836, 831, 873, 874, 860, 879, 880, 881, 884, 802, + 885, 886, 887, 888, 889, 883, 882, 850, 851, 852, + 876, 877, 857, 832, 833, 834, 835, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 890, 657, 455, 456, 663, 0, 878, + 660, 661, 658, 390, 442, 461, 449, 846, 680, 535, + 536, 681, 646, 0, 795, 0, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 798, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 837, 587, 537, 451, 401, + 0, 604, 0, 0, 916, 924, 0, 0, 0, 0, + 0, 0, 0, 0, 912, 0, 0, 0, 0, 790, + 0, 0, 827, 892, 891, 814, 824, 0, 0, 321, + 235, 532, 652, 534, 533, 815, 0, 816, 820, 823, + 819, 817, 818, 0, 907, 0, 0, 0, 0, 0, + 0, 0, 794, 0, 799, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 791, 792, 0, 0, 0, 0, 847, 0, 793, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 842, 821, 825, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 822, 845, 849, 346, 930, 843, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 931, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 840, + 0, 649, 0, 487, 0, 0, 914, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 844, 0, 440, + 419, 927, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 911, 415, 614, 647, 648, + 539, 0, 926, 906, 908, 909, 913, 917, 918, 919, + 920, 921, 923, 925, 929, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 928, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 848, 590, 591, 405, 406, 407, + 408, 915, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, + 937, 910, 936, 938, 939, 935, 940, 941, 922, 803, + 0, 855, 856, 933, 932, 934, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 810, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 899, 864, + 865, 866, 800, 867, 861, 862, 801, 863, 900, 853, + 896, 897, 829, 858, 868, 895, 869, 898, 901, 902, + 942, 943, 875, 859, 264, 944, 872, 903, 894, 893, + 870, 854, 904, 905, 836, 831, 873, 874, 860, 879, + 880, 881, 884, 802, 885, 886, 887, 888, 889, 883, + 882, 850, 851, 852, 876, 877, 857, 832, 833, 834, + 835, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 890, 657, 455, + 456, 663, 0, 878, 660, 661, 658, 390, 442, 461, + 449, 846, 680, 535, 536, 681, 646, 0, 795, 0, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 798, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 837, + 587, 537, 451, 401, 0, 604, 0, 0, 916, 924, + 0, 0, 0, 0, 0, 0, 0, 0, 912, 0, + 0, 0, 0, 0, 0, 0, 827, 892, 891, 814, + 824, 0, 0, 321, 235, 532, 652, 534, 533, 815, + 0, 816, 820, 823, 819, 817, 818, 0, 907, 0, + 0, 0, 0, 0, 0, 782, 794, 0, 799, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 791, 792, 0, 0, 0, 0, + 847, 0, 793, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 842, 821, 825, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 822, 845, 849, + 346, 930, 843, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 931, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 840, 0, 649, 0, 487, 0, 0, + 914, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 844, 0, 440, 419, 927, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 911, + 415, 614, 647, 648, 539, 0, 926, 906, 908, 909, + 913, 917, 918, 919, 920, 921, 923, 925, 929, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 928, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 848, 590, + 591, 405, 406, 407, 408, 915, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 937, 910, 936, 938, 939, 935, + 940, 941, 922, 803, 0, 855, 856, 933, 932, 934, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 810, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 899, 864, 865, 866, 800, 867, 861, 862, + 801, 863, 900, 853, 896, 897, 829, 858, 868, 895, + 869, 898, 901, 902, 942, 943, 875, 859, 264, 944, + 872, 903, 894, 893, 870, 854, 904, 905, 836, 831, + 873, 874, 860, 879, 880, 881, 884, 802, 885, 886, + 887, 888, 889, 883, 882, 850, 851, 852, 876, 877, + 857, 832, 833, 834, 835, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 890, 657, 455, 456, 663, 0, 878, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 0, 795, 174, 212, 173, 203, 175, 0, 0, + 0, 0, 0, 0, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 204, 0, 0, 0, 0, 0, 0, + 195, 0, 352, 0, 205, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 144, 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, - 234, 0, 0, 0, 0, 0, 0, 321, 235, 531, - 651, 533, 532, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 0, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 451, 479, 0, 491, 0, 375, 376, 0, - 0, 0, 0, 0, 0, 0, 309, 457, 476, 322, - 445, 489, 327, 453, 468, 317, 416, 442, 0, 0, - 311, 474, 452, 398, 310, 0, 436, 350, 366, 347, - 414, 0, 473, 502, 346, 492, 0, 484, 313, 0, - 483, 413, 470, 475, 399, 392, 0, 312, 472, 397, - 391, 379, 356, 518, 380, 381, 370, 426, 389, 427, - 371, 403, 402, 404, 0, 0, 0, 0, 0, 513, - 514, 0, 0, 0, 0, 0, 0, 0, 172, 201, - 210, 202, 72, 128, 0, 0, 644, 0, 0, 648, - 0, 486, 0, 0, 227, 0, 0, 0, 456, 0, - 0, 382, 200, 194, 193, 503, 0, 439, 419, 239, - 0, 0, 437, 387, 471, 428, 477, 458, 485, 433, - 429, 303, 459, 349, 400, 318, 320, 247, 351, 353, - 357, 358, 409, 410, 423, 444, 461, 462, 463, 348, - 332, 438, 333, 368, 334, 304, 340, 338, 341, 446, - 342, 306, 424, 467, 0, 363, 434, 395, 307, 394, - 425, 466, 465, 319, 493, 500, 501, 591, 0, 506, - 623, 624, 625, 515, 0, 430, 315, 314, 0, 0, - 0, 344, 328, 330, 331, 329, 422, 520, 521, 522, - 524, 525, 526, 527, 592, 608, 576, 545, 508, 600, - 542, 546, 547, 373, 611, 0, 0, 0, 499, 383, - 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, - 301, 481, 345, 415, 613, 646, 647, 538, 0, 601, - 539, 548, 337, 573, 585, 584, 411, 498, 230, 596, - 599, 528, 240, 0, 593, 607, 565, 606, 241, 421, - 0, 443, 604, 551, 0, 597, 570, 571, 0, 598, - 566, 602, 0, 540, 0, 509, 512, 541, 626, 627, - 628, 305, 511, 630, 631, 632, 633, 634, 635, 636, - 629, 482, 574, 550, 577, 490, 553, 552, 0, 0, - 588, 507, 589, 590, 405, 406, 407, 408, 365, 614, - 326, 510, 432, 142, 575, 0, 0, 0, 0, 0, - 0, 0, 0, 580, 581, 578, 238, 0, 637, 638, - 0, 0, 504, 505, 360, 367, 523, 369, 325, 420, - 362, 488, 377, 0, 516, 582, 517, 640, 643, 641, - 642, 412, 372, 374, 447, 378, 388, 435, 487, 418, - 440, 323, 478, 449, 393, 567, 595, 0, 0, 0, - 0, 0, 0, 0, 0, 68, 0, 0, 287, 288, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 622, 621, 620, 619, 618, 617, - 616, 615, 0, 0, 564, 464, 339, 294, 335, 336, - 343, 245, 316, 469, 246, 0, 302, 544, 386, 431, - 359, 609, 610, 63, 661, 248, 249, 250, 251, 252, - 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, - 262, 265, 266, 267, 268, 269, 270, 271, 272, 612, - 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, - 296, 663, 664, 665, 666, 667, 0, 0, 297, 298, - 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, - 494, 495, 496, 519, 0, 497, 480, 543, 242, 47, - 228, 231, 233, 232, 0, 64, 594, 605, 639, 5, - 649, 650, 652, 654, 653, 656, 454, 455, 662, 0, - 658, 659, 660, 657, 390, 441, 460, 448, 147, 243, - 534, 535, 244, 645, 174, 212, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 417, 0, 0, 549, 583, - 572, 655, 537, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 352, 0, 0, 385, 587, 568, 579, - 569, 554, 555, 556, 563, 364, 557, 558, 559, 529, - 560, 530, 561, 562, 144, 586, 536, 450, 401, 0, - 603, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, - 0, 234, 0, 0, 0, 0, 0, 0, 321, 235, - 531, 651, 533, 532, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 324, 2547, 2550, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 451, 479, 0, 491, 0, 375, 376, - 0, 0, 0, 0, 0, 0, 0, 309, 457, 476, - 322, 445, 489, 327, 453, 468, 317, 416, 442, 0, - 0, 311, 474, 452, 398, 310, 0, 436, 350, 366, - 347, 414, 0, 473, 502, 346, 492, 0, 484, 313, - 0, 483, 413, 470, 475, 399, 392, 0, 312, 472, - 397, 391, 379, 356, 518, 380, 381, 370, 426, 389, - 427, 371, 403, 402, 404, 0, 0, 0, 0, 0, - 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 644, 0, 0, - 648, 2551, 486, 0, 0, 0, 2546, 0, 2545, 456, - 2543, 2548, 382, 0, 0, 0, 503, 0, 439, 419, - 682, 0, 0, 437, 387, 471, 428, 477, 458, 485, - 433, 429, 303, 459, 349, 400, 318, 320, 672, 351, - 353, 357, 358, 409, 410, 423, 444, 461, 462, 463, - 348, 332, 438, 333, 368, 334, 304, 340, 338, 341, - 446, 342, 306, 424, 467, 2549, 363, 434, 395, 307, - 394, 425, 466, 465, 319, 493, 500, 501, 591, 0, - 506, 683, 684, 685, 515, 0, 430, 315, 314, 0, - 0, 0, 344, 328, 330, 331, 329, 422, 520, 521, - 522, 524, 525, 526, 527, 592, 608, 576, 545, 508, - 600, 542, 546, 547, 373, 611, 0, 0, 0, 499, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 0, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 172, 201, + 210, 202, 72, 128, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 227, 0, 0, 0, 457, 0, + 0, 382, 200, 194, 193, 504, 0, 440, 419, 239, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 247, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 624, 625, 626, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, - 300, 301, 678, 345, 415, 613, 646, 647, 538, 0, - 601, 539, 548, 337, 573, 585, 584, 411, 498, 0, - 596, 599, 528, 677, 0, 593, 607, 681, 606, 674, - 421, 0, 443, 604, 551, 0, 597, 570, 571, 0, - 598, 566, 602, 0, 540, 0, 509, 512, 541, 626, - 627, 628, 305, 511, 630, 631, 632, 633, 634, 635, - 636, 629, 482, 574, 550, 577, 490, 553, 552, 0, - 0, 588, 507, 589, 590, 405, 406, 407, 408, 365, - 614, 326, 510, 432, 0, 575, 0, 0, 0, 0, - 0, 0, 0, 0, 580, 581, 578, 686, 0, 637, - 638, 0, 0, 504, 505, 360, 367, 523, 369, 325, - 420, 362, 488, 377, 0, 516, 582, 517, 640, 643, - 641, 642, 412, 372, 374, 447, 378, 388, 435, 487, - 418, 440, 323, 478, 449, 393, 567, 595, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, + 300, 301, 482, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 230, + 597, 600, 529, 240, 0, 594, 608, 566, 607, 241, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 142, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 238, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, + 0, 0, 0, 0, 0, 0, 68, 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 622, 621, 620, 619, 618, - 617, 616, 615, 0, 0, 564, 464, 339, 294, 335, - 336, 343, 675, 671, 469, 676, 0, 302, 544, 386, - 431, 359, 609, 610, 0, 661, 248, 249, 250, 251, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 245, 316, 470, 246, 0, 302, 545, 386, + 432, 359, 610, 611, 63, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, - 612, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, - 0, 296, 663, 664, 665, 666, 667, 0, 0, 297, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, - 0, 494, 495, 496, 519, 0, 497, 480, 543, 673, - 0, 0, 0, 0, 0, 0, 0, 594, 605, 639, - 0, 649, 650, 652, 654, 653, 656, 454, 455, 662, - 0, 658, 659, 660, 657, 390, 441, 460, 448, 0, - 679, 534, 535, 680, 645, 417, 0, 0, 549, 583, - 572, 655, 537, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 352, 0, 0, 385, 587, 568, 579, - 569, 554, 555, 556, 563, 364, 557, 558, 559, 529, - 560, 530, 561, 562, 0, 586, 536, 450, 401, 0, - 603, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1376, 0, - 0, 234, 0, 0, 813, 823, 0, 0, 321, 235, - 531, 651, 533, 532, 814, 0, 815, 819, 822, 818, - 816, 817, 0, 324, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 451, 479, 0, 491, 0, 375, 376, - 0, 820, 0, 0, 0, 0, 0, 309, 457, 476, - 322, 445, 489, 327, 453, 468, 317, 416, 442, 0, - 0, 311, 474, 452, 398, 310, 0, 436, 350, 366, - 347, 414, 821, 473, 502, 346, 492, 0, 484, 313, - 0, 483, 413, 470, 475, 399, 392, 0, 312, 472, - 397, 391, 379, 356, 518, 380, 381, 370, 426, 389, - 427, 371, 403, 402, 404, 0, 0, 0, 0, 0, - 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 644, 0, 0, - 648, 0, 486, 0, 0, 0, 0, 0, 0, 456, - 0, 0, 382, 0, 0, 0, 503, 0, 439, 419, - 682, 0, 0, 437, 387, 471, 428, 477, 458, 485, - 433, 429, 303, 459, 349, 400, 318, 320, 672, 351, - 353, 357, 358, 409, 410, 423, 444, 461, 462, 463, - 348, 332, 438, 333, 368, 334, 304, 340, 338, 341, - 446, 342, 306, 424, 467, 0, 363, 434, 395, 307, - 394, 425, 466, 465, 319, 493, 500, 501, 591, 0, - 506, 683, 684, 685, 515, 0, 430, 315, 314, 0, - 0, 0, 344, 328, 330, 331, 329, 422, 520, 521, - 522, 524, 525, 526, 527, 592, 608, 576, 545, 508, - 600, 542, 546, 547, 373, 611, 0, 0, 0, 499, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 242, + 47, 228, 231, 233, 232, 0, 64, 595, 606, 640, + 5, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 147, + 243, 535, 536, 244, 646, 174, 212, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 144, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, + 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 324, 2548, 2551, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 2552, 487, 0, 0, 0, 2547, 0, 2546, + 457, 2544, 2549, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 2550, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, + 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, + 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, + 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 417, 0, 0, + 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 0, 0, 385, 588, + 569, 580, 570, 555, 556, 557, 564, 364, 558, 559, + 560, 530, 561, 531, 562, 563, 0, 587, 537, 451, + 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1377, 0, 0, 234, 0, 0, 814, 824, 0, 0, + 321, 235, 532, 652, 534, 533, 815, 0, 816, 820, + 823, 819, 817, 818, 0, 324, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 452, 480, 0, 492, 0, + 375, 376, 0, 821, 0, 0, 0, 0, 0, 309, + 458, 477, 322, 446, 490, 327, 454, 469, 317, 416, + 443, 0, 0, 311, 475, 453, 398, 310, 0, 437, + 350, 366, 347, 414, 822, 474, 503, 346, 493, 0, + 485, 313, 0, 484, 413, 471, 476, 399, 392, 0, + 312, 473, 397, 391, 379, 356, 519, 380, 381, 370, + 427, 389, 428, 371, 403, 402, 404, 0, 0, 0, + 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 645, + 0, 0, 649, 0, 487, 0, 0, 0, 0, 0, + 0, 457, 0, 0, 382, 0, 0, 0, 504, 0, + 440, 419, 683, 0, 0, 438, 387, 472, 429, 478, + 459, 486, 434, 430, 303, 460, 349, 400, 318, 320, + 673, 351, 353, 357, 358, 409, 410, 424, 445, 462, + 463, 464, 348, 332, 439, 333, 368, 334, 304, 340, + 338, 341, 447, 342, 306, 425, 468, 0, 363, 435, + 395, 307, 394, 426, 467, 466, 319, 494, 501, 502, + 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, + 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, + 423, 521, 522, 523, 525, 526, 527, 528, 593, 609, + 577, 546, 509, 601, 543, 547, 548, 373, 612, 0, + 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, + 0, 0, 361, 300, 301, 679, 345, 415, 614, 647, + 648, 539, 0, 602, 540, 549, 337, 574, 586, 585, + 411, 499, 0, 597, 600, 529, 678, 0, 594, 608, + 682, 607, 675, 421, 0, 444, 605, 552, 0, 598, + 571, 572, 0, 599, 567, 603, 0, 541, 0, 510, + 513, 542, 627, 628, 629, 305, 512, 631, 632, 633, + 634, 635, 636, 637, 630, 483, 575, 551, 578, 491, + 554, 553, 0, 0, 589, 508, 590, 591, 405, 406, + 407, 408, 365, 615, 326, 511, 433, 0, 576, 0, + 0, 0, 0, 0, 0, 0, 0, 581, 582, 579, + 687, 0, 638, 639, 0, 0, 505, 506, 360, 367, + 524, 369, 325, 420, 362, 489, 377, 0, 517, 583, + 518, 641, 644, 642, 643, 412, 372, 374, 448, 378, + 388, 436, 488, 418, 441, 323, 479, 450, 393, 568, + 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 623, 622, + 621, 620, 619, 618, 617, 616, 0, 0, 565, 465, + 339, 294, 335, 336, 343, 676, 672, 470, 677, 0, + 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, + 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, + 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, + 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 0, 0, 0, 0, 296, 664, 665, 666, 667, 668, + 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, + 292, 293, 0, 0, 495, 496, 497, 520, 0, 498, + 481, 544, 674, 0, 0, 0, 0, 0, 0, 0, + 595, 606, 640, 0, 650, 651, 653, 655, 654, 657, + 455, 456, 663, 0, 659, 660, 661, 658, 390, 442, + 461, 449, 0, 680, 535, 536, 681, 646, 174, 212, + 173, 203, 175, 0, 0, 0, 0, 0, 0, 417, + 706, 0, 550, 584, 573, 656, 538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 713, 0, 0, 0, 0, 0, + 0, 0, 712, 0, 0, 234, 0, 0, 0, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 477, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 0, 485, 313, 0, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 710, 711, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 0, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 434, 430, 303, 460, 349, 400, + 318, 320, 673, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 637, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 508, 590, 591, + 405, 406, 407, 408, 707, 709, 326, 511, 433, 721, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 412, 372, 374, + 448, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 68, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 390, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 1182, + 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 0, + 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, + 0, 0, 0, 321, 235, 532, 652, 534, 533, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 2718, 2719, 1167, 0, 0, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 2712, 2715, 2716, 2717, + 2720, 0, 2725, 2721, 2722, 2723, 2724, 0, 2707, 2708, + 2709, 2710, 1165, 2691, 2713, 0, 2692, 413, 2693, 2694, + 2695, 2696, 1169, 2697, 2698, 2699, 2700, 2701, 2704, 2705, + 2702, 2703, 2711, 427, 389, 428, 371, 403, 402, 404, + 1193, 1195, 1197, 1199, 1202, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 0, 0, 649, 0, 487, 0, 0, + 0, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 2706, 0, 440, 419, 683, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 345, + 415, 614, 647, 648, 539, 0, 602, 540, 549, 337, + 574, 586, 585, 411, 499, 0, 597, 600, 529, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 483, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 508, 590, + 591, 405, 406, 407, 408, 365, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 0, 302, 2714, 386, 432, 359, 610, 611, + 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, + 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, + 267, 268, 269, 270, 271, 272, 613, 263, 264, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 0, 0, 0, 0, 296, 664, 665, + 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, + 289, 290, 291, 292, 293, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 654, 657, 455, 456, 663, 0, 659, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 417, 0, 0, 550, 584, 573, 656, 538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 0, 0, 385, 588, 569, 580, 570, 555, 556, 557, + 564, 364, 558, 559, 560, 530, 561, 531, 562, 563, + 0, 587, 537, 451, 401, 0, 604, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, + 0, 0, 0, 0, 321, 235, 532, 652, 534, 533, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, + 2548, 2551, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, + 480, 0, 492, 0, 375, 376, 0, 0, 0, 0, + 0, 0, 0, 309, 458, 477, 322, 446, 490, 327, + 454, 469, 317, 416, 443, 0, 0, 311, 475, 453, + 398, 310, 0, 437, 350, 366, 347, 414, 0, 474, + 503, 346, 493, 0, 485, 313, 0, 484, 413, 471, + 476, 399, 392, 0, 312, 473, 397, 391, 379, 356, + 519, 380, 381, 370, 427, 389, 428, 371, 403, 402, + 404, 0, 0, 0, 0, 0, 514, 515, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 645, 0, 0, 649, 2552, 487, 0, + 0, 0, 2547, 0, 2546, 457, 2544, 2549, 382, 0, + 0, 0, 504, 0, 440, 419, 683, 0, 0, 438, + 387, 472, 429, 478, 459, 486, 434, 430, 303, 460, + 349, 400, 318, 320, 673, 351, 353, 357, 358, 409, + 410, 424, 445, 462, 463, 464, 348, 332, 439, 333, + 368, 334, 304, 340, 338, 341, 447, 342, 306, 425, + 468, 2550, 363, 435, 395, 307, 394, 426, 467, 466, + 319, 494, 501, 502, 592, 0, 507, 684, 685, 686, + 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, + 330, 331, 329, 422, 423, 521, 522, 523, 525, 526, + 527, 528, 593, 609, 577, 546, 509, 601, 543, 547, + 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, + 355, 354, 396, 308, 0, 0, 361, 300, 301, 679, + 345, 415, 614, 647, 648, 539, 0, 602, 540, 549, + 337, 574, 586, 585, 411, 499, 0, 597, 600, 529, + 678, 0, 594, 608, 682, 607, 675, 421, 0, 444, + 605, 552, 0, 598, 571, 572, 0, 599, 567, 603, + 0, 541, 0, 510, 513, 542, 627, 628, 629, 305, + 512, 631, 632, 633, 634, 635, 636, 637, 630, 483, + 575, 551, 578, 491, 554, 553, 0, 0, 589, 508, + 590, 591, 405, 406, 407, 408, 365, 615, 326, 511, + 433, 0, 576, 0, 0, 0, 0, 0, 0, 0, + 0, 581, 582, 579, 687, 0, 638, 639, 0, 0, + 505, 506, 360, 367, 524, 369, 325, 420, 362, 489, + 377, 0, 517, 583, 518, 641, 644, 642, 643, 412, + 372, 374, 448, 378, 388, 436, 488, 418, 441, 323, + 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 623, 622, 621, 620, 619, 618, 617, 616, + 0, 0, 565, 465, 339, 294, 335, 336, 343, 676, + 672, 470, 677, 0, 302, 545, 386, 432, 359, 610, + 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, + 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, + 266, 267, 268, 269, 270, 271, 272, 613, 263, 264, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 0, 0, 0, 0, 296, 664, + 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, + 0, 289, 290, 291, 292, 293, 0, 0, 495, 496, + 497, 520, 0, 498, 481, 544, 674, 0, 0, 0, + 0, 0, 0, 0, 595, 606, 640, 0, 650, 651, + 653, 655, 654, 657, 455, 456, 663, 0, 659, 660, + 661, 658, 390, 442, 461, 449, 0, 680, 535, 536, + 681, 646, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 0, 587, 537, 451, 401, 0, 604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, + 0, 0, 0, 0, 0, 321, 235, 532, 652, 534, + 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 324, 0, 2569, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 0, 0, 0, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 0, + 474, 503, 346, 493, 0, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 519, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 0, 0, 649, 2568, 487, + 0, 0, 0, 2574, 2571, 2573, 457, 0, 2572, 382, + 0, 0, 0, 504, 0, 440, 419, 683, 0, 2566, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 345, 415, 614, 647, 648, 539, 0, 602, 540, + 549, 337, 574, 586, 585, 411, 499, 0, 597, 600, + 529, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 483, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 508, 590, 591, 405, 406, 407, 408, 365, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 0, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, + 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, + 265, 266, 267, 268, 269, 270, 271, 272, 613, 263, + 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 0, 0, 0, 0, 296, + 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, + 0, 0, 289, 290, 291, 292, 293, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 654, 657, 455, 456, 663, 0, 659, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 417, 0, 0, 550, 584, 573, 656, + 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 352, 0, 0, 385, 588, 569, 580, 570, 555, + 556, 557, 564, 364, 558, 559, 560, 530, 561, 531, + 562, 563, 0, 587, 537, 451, 401, 0, 604, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 321, 235, 532, 652, + 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 2569, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 452, 480, 0, 492, 0, 375, 376, 0, 0, + 0, 0, 0, 0, 0, 309, 458, 477, 322, 446, + 490, 327, 454, 469, 317, 416, 443, 0, 0, 311, + 475, 453, 398, 310, 0, 437, 350, 366, 347, 414, + 0, 474, 503, 346, 493, 0, 485, 313, 0, 484, + 413, 471, 476, 399, 392, 0, 312, 473, 397, 391, + 379, 356, 519, 380, 381, 370, 427, 389, 428, 371, + 403, 402, 404, 0, 0, 0, 0, 0, 514, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 645, 0, 0, 649, 2568, + 487, 0, 0, 0, 2574, 2571, 2573, 457, 0, 2572, + 382, 0, 0, 0, 504, 0, 440, 419, 683, 0, + 0, 438, 387, 472, 429, 478, 459, 486, 434, 430, + 303, 460, 349, 400, 318, 320, 673, 351, 353, 357, + 358, 409, 410, 424, 445, 462, 463, 464, 348, 332, + 439, 333, 368, 334, 304, 340, 338, 341, 447, 342, + 306, 425, 468, 0, 363, 435, 395, 307, 394, 426, + 467, 466, 319, 494, 501, 502, 592, 0, 507, 684, + 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, + 344, 328, 330, 331, 329, 422, 423, 521, 522, 523, + 525, 526, 527, 528, 593, 609, 577, 546, 509, 601, + 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, + 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, + 301, 679, 345, 415, 614, 647, 648, 539, 0, 602, + 540, 549, 337, 574, 586, 585, 411, 499, 0, 597, + 600, 529, 678, 0, 594, 608, 682, 607, 675, 421, + 0, 444, 605, 552, 0, 598, 571, 572, 0, 599, + 567, 603, 0, 541, 0, 510, 513, 542, 627, 628, + 629, 305, 512, 631, 632, 633, 634, 635, 636, 637, + 630, 483, 575, 551, 578, 491, 554, 553, 0, 0, + 589, 508, 590, 591, 405, 406, 407, 408, 365, 615, + 326, 511, 433, 0, 576, 0, 0, 0, 0, 0, + 0, 0, 0, 581, 582, 579, 687, 0, 638, 639, + 0, 0, 505, 506, 360, 367, 524, 369, 325, 420, + 362, 489, 377, 0, 517, 583, 518, 641, 644, 642, + 643, 412, 372, 374, 448, 378, 388, 436, 488, 418, + 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 622, 621, 620, 619, 618, + 617, 616, 0, 0, 565, 465, 339, 294, 335, 336, + 343, 676, 672, 470, 677, 0, 302, 545, 386, 432, + 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, + 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, + 262, 265, 266, 267, 268, 269, 270, 271, 272, 613, + 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, + 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, + 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, + 495, 496, 497, 520, 0, 498, 481, 544, 674, 0, + 0, 0, 0, 0, 0, 0, 595, 606, 640, 0, + 650, 651, 653, 655, 654, 657, 455, 456, 663, 0, + 659, 660, 661, 658, 390, 442, 461, 449, 0, 680, + 535, 536, 681, 646, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 2239, 0, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 0, 587, 537, 451, 401, 0, 604, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 2240, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 0, 1303, 1304, 1305, 1302, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 0, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 0, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 504, 0, 440, 419, 683, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, - 300, 301, 678, 345, 415, 613, 646, 647, 538, 0, - 601, 539, 548, 337, 573, 585, 584, 411, 498, 0, - 596, 599, 528, 677, 0, 593, 607, 681, 606, 674, - 421, 0, 443, 604, 551, 0, 597, 570, 571, 0, - 598, 566, 602, 0, 540, 0, 509, 512, 541, 626, - 627, 628, 305, 511, 630, 631, 632, 633, 634, 635, - 636, 629, 482, 574, 550, 577, 490, 553, 552, 0, - 0, 588, 507, 589, 590, 405, 406, 407, 408, 365, - 614, 326, 510, 432, 0, 575, 0, 0, 0, 0, - 0, 0, 0, 0, 580, 581, 578, 686, 0, 637, - 638, 0, 0, 504, 505, 360, 367, 523, 369, 325, - 420, 362, 488, 377, 0, 516, 582, 517, 640, 643, - 641, 642, 412, 372, 374, 447, 378, 388, 435, 487, - 418, 440, 323, 478, 449, 393, 567, 595, 0, 0, + 300, 301, 679, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 0, + 597, 600, 529, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 622, 621, 620, 619, 618, - 617, 616, 615, 0, 0, 564, 464, 339, 294, 335, - 336, 343, 675, 671, 469, 676, 0, 302, 544, 386, - 431, 359, 609, 610, 0, 661, 248, 249, 250, 251, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 0, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, - 612, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, - 0, 296, 663, 664, 665, 666, 667, 0, 0, 297, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, - 0, 494, 495, 496, 519, 0, 497, 480, 543, 673, - 0, 0, 0, 0, 0, 0, 0, 594, 605, 639, - 0, 649, 650, 652, 654, 653, 656, 454, 455, 662, - 0, 658, 659, 660, 657, 390, 441, 460, 448, 0, - 679, 534, 535, 680, 645, 174, 212, 173, 203, 175, - 0, 0, 0, 0, 0, 0, 417, 705, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 0, 586, 536, 450, 401, - 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 712, 0, 0, 0, 0, 0, 0, 0, 711, - 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, - 235, 531, 651, 533, 532, 0, 0, 0, 0, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 0, + 680, 535, 536, 681, 646, 174, 212, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 144, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, + 2498, 0, 234, 0, 0, 0, 0, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 0, 0, 0, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 0, 473, 502, 346, 492, 0, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 518, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 709, 710, 0, 644, 0, - 0, 648, 0, 486, 0, 0, 0, 0, 0, 0, - 456, 0, 0, 382, 0, 0, 0, 503, 0, 439, - 419, 682, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 345, 415, 613, 646, 647, 538, - 0, 601, 539, 548, 337, 573, 585, 584, 411, 498, - 0, 596, 599, 528, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 482, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 507, 589, 590, 405, 406, 407, 408, - 706, 708, 326, 510, 432, 720, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 0, - 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 0, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 248, 249, 250, - 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, - 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, - 272, 612, 263, 264, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 0, 0, 296, 663, 664, 665, 666, 667, 0, 0, - 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 653, 656, 454, 455, - 662, 0, 658, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 1181, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 0, 586, 536, 450, 401, - 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, - 235, 531, 651, 533, 532, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 0, 487, 0, 0, 0, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, + 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, + 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, + 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 174, 212, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 144, 587, 537, + 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 208, 2279, 0, 234, 0, 0, 0, 0, 0, + 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 2717, - 2718, 1166, 0, 0, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 2711, 2714, 2715, 2716, 2719, 0, 2724, 2720, - 2721, 2722, 2723, 0, 2706, 2707, 2708, 2709, 1164, 2690, - 2712, 0, 2691, 413, 2692, 2693, 2694, 2695, 1168, 2696, - 2697, 2698, 2699, 2700, 2703, 2704, 2701, 2702, 2710, 426, - 389, 427, 371, 403, 402, 404, 1192, 1194, 1196, 1198, - 1201, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 0, - 0, 648, 0, 486, 0, 0, 0, 0, 0, 0, - 456, 0, 0, 382, 0, 0, 0, 2705, 0, 439, - 419, 682, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 345, 415, 613, 646, 647, 538, - 0, 601, 539, 548, 337, 573, 585, 584, 411, 498, - 0, 596, 599, 528, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 482, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 507, 589, 590, 405, 406, 407, 408, - 365, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 0, 302, 2713, - 386, 431, 359, 609, 610, 0, 661, 248, 249, 250, - 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, - 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, - 272, 612, 263, 264, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 0, 0, 296, 663, 664, 665, 666, 667, 0, 0, - 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 653, 656, 454, 455, - 662, 0, 658, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 0, 586, 536, 450, 401, - 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, - 235, 531, 651, 533, 532, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 324, 2547, 2550, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 0, 0, 0, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 0, 473, 502, 346, 492, 0, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 518, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 0, - 0, 648, 2551, 486, 0, 0, 0, 2546, 0, 2545, - 456, 2543, 2548, 382, 0, 0, 0, 503, 0, 439, - 419, 682, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 2549, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 345, 415, 613, 646, 647, 538, - 0, 601, 539, 548, 337, 573, 585, 584, 411, 498, - 0, 596, 599, 528, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 482, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 507, 589, 590, 405, 406, 407, 408, - 365, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 0, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 248, 249, 250, - 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, - 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, - 272, 612, 263, 264, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 0, 0, 296, 663, 664, 665, 666, 667, 0, 0, - 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 653, 656, 454, 455, - 662, 0, 658, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 0, 586, 536, 450, 401, - 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 0, 474, 503, 346, 493, + 0, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 519, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 0, 0, 649, 0, 487, 0, 0, 0, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 504, + 0, 440, 419, 683, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 345, 415, 614, + 647, 648, 539, 0, 602, 540, 549, 337, 574, 586, + 585, 411, 499, 0, 597, 600, 529, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 483, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 508, 590, 591, 405, + 406, 407, 408, 365, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 0, 302, 545, 386, 432, 359, 610, 611, 0, 662, + 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, + 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, + 269, 270, 271, 272, 613, 263, 264, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 0, 0, 0, 0, 296, 664, 665, 666, 667, + 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, + 291, 292, 293, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 654, + 657, 455, 456, 663, 0, 659, 660, 661, 658, 390, + 442, 461, 449, 0, 680, 535, 536, 681, 646, 417, + 0, 0, 550, 584, 573, 656, 538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 352, 1093, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 234, 1100, 1101, 0, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1104, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 1087, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 1073, 485, 313, 1072, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 0, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 1091, 430, 303, 460, 349, 400, + 318, 320, 673, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 1092, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 1095, 590, 591, + 405, 406, 407, 408, 365, 615, 1090, 511, 433, 0, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 1102, 1088, 1098, + 1089, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 1099, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 1086, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 174, 212, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 417, 0, 0, 550, 584, 573, 656, 538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 0, 0, 385, 588, 569, 580, 570, 555, 556, 557, + 564, 364, 558, 559, 560, 530, 561, 531, 562, 563, + 144, 587, 537, 451, 401, 0, 604, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2169, 0, 0, 234, 0, 0, + 0, 0, 0, 0, 321, 235, 532, 652, 534, 533, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, + 480, 0, 492, 0, 375, 376, 0, 0, 0, 0, + 0, 0, 0, 309, 458, 477, 322, 446, 490, 327, + 454, 469, 317, 416, 443, 0, 0, 311, 475, 453, + 398, 310, 0, 437, 350, 366, 347, 414, 0, 474, + 503, 346, 493, 0, 485, 313, 0, 484, 413, 471, + 476, 399, 392, 0, 312, 473, 397, 391, 379, 356, + 519, 380, 381, 370, 427, 389, 428, 371, 403, 402, + 404, 0, 0, 0, 0, 0, 514, 515, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 645, 0, 0, 649, 0, 487, 0, + 0, 0, 0, 0, 0, 457, 0, 0, 382, 0, + 0, 0, 504, 0, 440, 419, 683, 0, 0, 438, + 387, 472, 429, 478, 459, 486, 434, 430, 303, 460, + 349, 400, 318, 320, 673, 351, 353, 357, 358, 409, + 410, 424, 445, 462, 463, 464, 348, 332, 439, 333, + 368, 334, 304, 340, 338, 341, 447, 342, 306, 425, + 468, 0, 363, 435, 395, 307, 394, 426, 467, 466, + 319, 494, 501, 502, 592, 0, 507, 684, 685, 686, + 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, + 330, 331, 329, 422, 423, 521, 522, 523, 525, 526, + 527, 528, 593, 609, 577, 546, 509, 601, 543, 547, + 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, + 355, 354, 396, 308, 0, 0, 361, 300, 301, 679, + 345, 415, 614, 647, 648, 539, 0, 602, 540, 549, + 337, 574, 586, 585, 411, 499, 0, 597, 600, 529, + 678, 0, 594, 608, 682, 607, 675, 421, 0, 444, + 605, 552, 0, 598, 571, 572, 0, 599, 567, 603, + 0, 541, 0, 510, 513, 542, 627, 628, 629, 305, + 512, 631, 632, 633, 634, 635, 636, 637, 630, 483, + 575, 551, 578, 491, 554, 553, 0, 0, 589, 508, + 590, 591, 405, 406, 407, 408, 365, 615, 326, 511, + 433, 0, 576, 0, 0, 0, 0, 0, 0, 0, + 0, 581, 582, 579, 687, 0, 638, 639, 0, 0, + 505, 506, 360, 367, 524, 369, 325, 420, 362, 489, + 377, 0, 517, 583, 518, 641, 644, 642, 643, 412, + 372, 374, 448, 378, 388, 436, 488, 418, 441, 323, + 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 623, 622, 621, 620, 619, 618, 617, 616, + 0, 0, 565, 465, 339, 294, 335, 336, 343, 676, + 672, 470, 677, 0, 302, 545, 386, 432, 359, 610, + 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, + 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, + 266, 267, 268, 269, 270, 271, 272, 613, 263, 264, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 0, 0, 0, 0, 296, 664, + 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, + 0, 289, 290, 291, 292, 293, 0, 0, 495, 496, + 497, 520, 0, 498, 481, 544, 674, 0, 0, 0, + 0, 0, 0, 0, 595, 606, 640, 0, 650, 651, + 653, 655, 654, 657, 455, 456, 663, 0, 659, 660, + 661, 658, 390, 442, 461, 449, 0, 680, 535, 536, + 681, 646, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 0, 587, 537, 451, 401, 0, 604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 1100, + 1101, 0, 0, 0, 0, 321, 235, 532, 652, 534, + 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1104, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 0, 0, 0, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 0, + 474, 503, 346, 493, 1073, 485, 313, 1072, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 519, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 0, 0, 649, 0, 487, + 0, 0, 0, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 504, 0, 440, 419, 683, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 345, 415, 614, 647, 648, 539, 0, 602, 540, + 549, 337, 574, 586, 585, 411, 499, 0, 597, 600, + 529, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 483, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 508, 590, 591, 405, 406, 407, 408, 365, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 1102, 2190, 1098, 2191, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 1099, 568, 596, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 0, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, + 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, + 265, 266, 267, 268, 269, 270, 271, 272, 613, 263, + 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 0, 0, 0, 0, 296, + 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, + 0, 0, 289, 290, 291, 292, 293, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 654, 657, 455, 456, 663, 0, 659, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 417, 0, 0, 550, 584, 573, 656, + 538, 0, 0, 3127, 0, 0, 0, 0, 0, 0, + 0, 352, 0, 0, 385, 588, 569, 580, 570, 555, + 556, 557, 564, 364, 558, 559, 560, 530, 561, 531, + 562, 563, 0, 587, 537, 451, 401, 0, 604, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 321, 235, 532, 652, + 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 452, 480, 0, 492, 0, 375, 376, 0, 0, + 0, 0, 0, 0, 0, 309, 458, 477, 322, 446, + 490, 327, 454, 469, 317, 416, 443, 0, 0, 311, + 475, 453, 398, 310, 0, 437, 350, 366, 347, 414, + 0, 474, 503, 346, 493, 0, 485, 313, 0, 484, + 413, 471, 476, 399, 392, 0, 312, 473, 397, 391, + 379, 356, 519, 380, 381, 370, 427, 389, 428, 371, + 403, 402, 404, 0, 0, 0, 0, 0, 514, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3130, + 0, 0, 0, 0, 3129, 645, 0, 0, 649, 0, + 487, 0, 0, 0, 0, 0, 0, 457, 0, 0, + 382, 0, 0, 0, 504, 0, 440, 419, 683, 0, + 0, 438, 387, 472, 429, 478, 459, 486, 434, 430, + 303, 460, 349, 400, 318, 320, 673, 351, 353, 357, + 358, 409, 410, 424, 445, 462, 463, 464, 348, 332, + 439, 333, 368, 334, 304, 340, 338, 341, 447, 342, + 306, 425, 468, 0, 363, 435, 395, 307, 394, 426, + 467, 466, 319, 494, 501, 502, 592, 0, 507, 684, + 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, + 344, 328, 330, 331, 329, 422, 423, 521, 522, 523, + 525, 526, 527, 528, 593, 609, 577, 546, 509, 601, + 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, + 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, + 301, 679, 345, 415, 614, 647, 648, 539, 0, 602, + 540, 549, 337, 574, 586, 585, 411, 499, 0, 597, + 600, 529, 678, 0, 594, 608, 682, 607, 675, 421, + 0, 444, 605, 552, 0, 598, 571, 572, 0, 599, + 567, 603, 0, 541, 0, 510, 513, 542, 627, 628, + 629, 305, 512, 631, 632, 633, 634, 635, 636, 637, + 630, 483, 575, 551, 578, 491, 554, 553, 0, 0, + 589, 508, 590, 591, 405, 406, 407, 408, 365, 615, + 326, 511, 433, 0, 576, 0, 0, 0, 0, 0, + 0, 0, 0, 581, 582, 579, 687, 0, 638, 639, + 0, 0, 505, 506, 360, 367, 524, 369, 325, 420, + 362, 489, 377, 0, 517, 583, 518, 641, 644, 642, + 643, 412, 372, 374, 448, 378, 388, 436, 488, 418, + 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 622, 621, 620, 619, 618, + 617, 616, 0, 0, 565, 465, 339, 294, 335, 336, + 343, 676, 672, 470, 677, 0, 302, 545, 386, 432, + 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, + 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, + 262, 265, 266, 267, 268, 269, 270, 271, 272, 613, + 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, + 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, + 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, + 495, 496, 497, 520, 0, 498, 481, 544, 674, 0, + 0, 0, 0, 0, 0, 0, 595, 606, 640, 0, + 650, 651, 653, 655, 654, 657, 455, 456, 663, 0, + 659, 660, 661, 658, 390, 442, 461, 449, 0, 680, + 535, 536, 681, 646, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 352, 1624, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 0, 587, 537, 451, 401, 0, 604, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 1622, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, - 235, 531, 651, 533, 532, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 324, 0, 2568, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 0, 0, 0, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 0, 473, 502, 346, 492, 0, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 518, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 0, - 0, 648, 2567, 486, 0, 0, 0, 2573, 2570, 2572, - 456, 0, 2571, 382, 0, 0, 0, 503, 0, 439, - 419, 682, 0, 2565, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 345, 415, 613, 646, 647, 538, - 0, 601, 539, 548, 337, 573, 585, 584, 411, 498, - 0, 596, 599, 528, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 482, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 507, 589, 590, 405, 406, 407, 408, - 365, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 0, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 248, 249, 250, - 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, - 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, - 272, 612, 263, 264, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 0, 0, 296, 663, 664, 665, 666, 667, 0, 0, - 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 653, 656, 454, 455, - 662, 0, 658, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 0, 586, 536, 450, 401, - 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, - 235, 531, 651, 533, 532, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 324, 0, 2568, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 0, 0, 0, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 0, 473, 502, 346, 492, 0, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 518, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 0, - 0, 648, 2567, 486, 0, 0, 0, 2573, 2570, 2572, - 456, 0, 2571, 382, 0, 0, 0, 503, 0, 439, - 419, 682, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 345, 415, 613, 646, 647, 538, - 0, 601, 539, 548, 337, 573, 585, 584, 411, 498, - 0, 596, 599, 528, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 482, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 507, 589, 590, 405, 406, 407, 408, - 365, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 0, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 248, 249, 250, - 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, - 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, - 272, 612, 263, 264, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 0, 0, 296, 663, 664, 665, 666, 667, 0, 0, - 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 653, 656, 454, 455, - 662, 0, 658, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 417, 0, 0, 549, - 583, 572, 655, 537, 0, 0, 0, 0, 0, 2238, - 0, 0, 0, 0, 352, 0, 0, 385, 587, 568, - 579, 569, 554, 555, 556, 563, 364, 557, 558, 559, - 529, 560, 530, 561, 562, 0, 586, 536, 450, 401, - 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 234, 0, 0, 2239, 0, 0, 0, 321, - 235, 531, 651, 533, 532, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 324, 0, 0, 1302, 1303, 1304, - 1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 451, 479, 0, 491, 0, 375, - 376, 0, 0, 0, 0, 0, 0, 0, 309, 457, - 476, 322, 445, 489, 327, 453, 468, 317, 416, 442, - 0, 0, 311, 474, 452, 398, 310, 0, 436, 350, - 366, 347, 414, 0, 473, 502, 346, 492, 0, 484, - 313, 0, 483, 413, 470, 475, 399, 392, 0, 312, - 472, 397, 391, 379, 356, 518, 380, 381, 370, 426, - 389, 427, 371, 403, 402, 404, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 644, 0, - 0, 648, 0, 486, 0, 0, 0, 0, 0, 0, - 456, 0, 0, 382, 0, 0, 0, 503, 0, 439, - 419, 682, 0, 0, 437, 387, 471, 428, 477, 458, - 485, 433, 429, 303, 459, 349, 400, 318, 320, 672, - 351, 353, 357, 358, 409, 410, 423, 444, 461, 462, - 463, 348, 332, 438, 333, 368, 334, 304, 340, 338, - 341, 446, 342, 306, 424, 467, 0, 363, 434, 395, - 307, 394, 425, 466, 465, 319, 493, 500, 501, 591, - 0, 506, 683, 684, 685, 515, 0, 430, 315, 314, - 0, 0, 0, 344, 328, 330, 331, 329, 422, 520, - 521, 522, 524, 525, 526, 527, 592, 608, 576, 545, - 508, 600, 542, 546, 547, 373, 611, 0, 0, 0, - 499, 383, 384, 0, 355, 354, 396, 308, 0, 0, - 361, 300, 301, 678, 345, 415, 613, 646, 647, 538, - 0, 601, 539, 548, 337, 573, 585, 584, 411, 498, - 0, 596, 599, 528, 677, 0, 593, 607, 681, 606, - 674, 421, 0, 443, 604, 551, 0, 597, 570, 571, - 0, 598, 566, 602, 0, 540, 0, 509, 512, 541, - 626, 627, 628, 305, 511, 630, 631, 632, 633, 634, - 635, 636, 629, 482, 574, 550, 577, 490, 553, 552, - 0, 0, 588, 507, 589, 590, 405, 406, 407, 408, - 365, 614, 326, 510, 432, 0, 575, 0, 0, 0, - 0, 0, 0, 0, 0, 580, 581, 578, 686, 0, - 637, 638, 0, 0, 504, 505, 360, 367, 523, 369, - 325, 420, 362, 488, 377, 0, 516, 582, 517, 640, - 643, 641, 642, 412, 372, 374, 447, 378, 388, 435, - 487, 418, 440, 323, 478, 449, 393, 567, 595, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 1620, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 0, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 504, 0, 440, 419, 683, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, + 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, + 300, 301, 679, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 0, + 597, 600, 529, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, + 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 0, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, + 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, + 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, + 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 0, + 680, 535, 536, 681, 646, 417, 0, 0, 550, 584, + 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 352, 1618, 0, 385, 588, 569, 580, + 570, 555, 556, 557, 564, 364, 558, 559, 560, 530, + 561, 531, 562, 563, 0, 587, 537, 451, 401, 0, + 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 234, 0, 0, 1622, 0, 0, 0, 321, 235, + 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 452, 480, 0, 492, 0, 375, 376, + 1620, 0, 0, 0, 0, 0, 0, 309, 458, 477, + 322, 446, 490, 327, 454, 469, 317, 416, 443, 0, + 0, 311, 475, 453, 398, 310, 0, 437, 350, 366, + 347, 414, 0, 474, 503, 346, 493, 0, 485, 313, + 0, 484, 413, 471, 476, 399, 392, 0, 312, 473, + 397, 391, 379, 356, 519, 380, 381, 370, 427, 389, + 428, 371, 403, 402, 404, 0, 0, 0, 0, 0, + 514, 515, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 645, 0, 0, + 649, 0, 487, 0, 0, 0, 0, 0, 0, 457, + 0, 0, 382, 0, 0, 0, 504, 0, 440, 419, + 683, 0, 0, 438, 387, 472, 429, 478, 459, 486, + 434, 430, 303, 460, 349, 400, 318, 320, 673, 351, + 353, 357, 358, 409, 410, 424, 445, 462, 463, 464, + 348, 332, 439, 333, 368, 334, 304, 340, 338, 341, + 447, 342, 306, 425, 468, 0, 363, 435, 395, 307, + 394, 426, 467, 466, 319, 494, 501, 502, 592, 0, + 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, + 0, 0, 344, 328, 330, 331, 329, 422, 423, 521, + 522, 523, 525, 526, 527, 528, 593, 609, 577, 546, + 509, 601, 543, 547, 548, 373, 612, 0, 0, 0, + 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, + 361, 300, 301, 679, 345, 415, 614, 647, 648, 539, + 0, 602, 540, 549, 337, 574, 586, 585, 411, 499, + 0, 597, 600, 529, 678, 0, 594, 608, 682, 607, + 675, 421, 0, 444, 605, 552, 0, 598, 571, 572, + 0, 599, 567, 603, 0, 541, 0, 510, 513, 542, + 627, 628, 629, 305, 512, 631, 632, 633, 634, 635, + 636, 637, 630, 483, 575, 551, 578, 491, 554, 553, + 0, 0, 589, 508, 590, 591, 405, 406, 407, 408, + 365, 615, 326, 511, 433, 0, 576, 0, 0, 0, + 0, 0, 0, 0, 0, 581, 582, 579, 687, 0, + 638, 639, 0, 0, 505, 506, 360, 367, 524, 369, + 325, 420, 362, 489, 377, 0, 517, 583, 518, 641, + 644, 642, 643, 412, 372, 374, 448, 378, 388, 436, + 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 622, 621, 620, 619, - 618, 617, 616, 615, 0, 0, 564, 464, 339, 294, - 335, 336, 343, 675, 671, 469, 676, 0, 302, 544, - 386, 431, 359, 609, 610, 0, 661, 248, 249, 250, + 0, 0, 0, 0, 0, 0, 623, 622, 621, 620, + 619, 618, 617, 616, 0, 0, 565, 465, 339, 294, + 335, 336, 343, 676, 672, 470, 677, 0, 302, 545, + 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, - 272, 612, 263, 264, 273, 274, 275, 276, 277, 278, + 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 0, 0, 296, 663, 664, 665, 666, 667, 0, 0, + 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, - 0, 0, 494, 495, 496, 519, 0, 497, 480, 543, - 673, 0, 0, 0, 0, 0, 0, 0, 594, 605, - 639, 0, 649, 650, 652, 654, 653, 656, 454, 455, - 662, 0, 658, 659, 660, 657, 390, 441, 460, 448, - 0, 679, 534, 535, 680, 645, 174, 212, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 417, 0, 0, - 549, 583, 572, 655, 537, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 352, 0, 0, 385, 587, - 568, 579, 569, 554, 555, 556, 563, 364, 557, 558, - 559, 529, 560, 530, 561, 562, 144, 586, 536, 450, - 401, 0, 603, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 208, 2497, 0, 234, 0, 0, 0, 0, 0, 0, - 321, 235, 531, 651, 533, 532, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, + 0, 0, 495, 496, 497, 520, 0, 498, 481, 544, + 674, 0, 0, 0, 0, 0, 0, 0, 595, 606, + 640, 0, 650, 651, 653, 655, 654, 657, 455, 456, + 663, 0, 659, 660, 661, 658, 390, 442, 461, 449, + 0, 680, 535, 536, 681, 646, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 0, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4296, 0, 234, 892, 0, 0, 0, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 451, 479, 0, 491, 0, - 375, 376, 0, 0, 0, 0, 0, 0, 0, 309, - 457, 476, 322, 445, 489, 327, 453, 468, 317, 416, - 442, 0, 0, 311, 474, 452, 398, 310, 0, 436, - 350, 366, 347, 414, 0, 473, 502, 346, 492, 0, - 484, 313, 0, 483, 413, 470, 475, 399, 392, 0, - 312, 472, 397, 391, 379, 356, 518, 380, 381, 370, - 426, 389, 427, 371, 403, 402, 404, 0, 0, 0, - 0, 0, 513, 514, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 644, - 0, 0, 648, 0, 486, 0, 0, 0, 0, 0, - 0, 456, 0, 0, 382, 0, 0, 0, 503, 0, - 439, 419, 682, 0, 0, 437, 387, 471, 428, 477, - 458, 485, 433, 429, 303, 459, 349, 400, 318, 320, - 672, 351, 353, 357, 358, 409, 410, 423, 444, 461, - 462, 463, 348, 332, 438, 333, 368, 334, 304, 340, - 338, 341, 446, 342, 306, 424, 467, 0, 363, 434, - 395, 307, 394, 425, 466, 465, 319, 493, 500, 501, - 591, 0, 506, 683, 684, 685, 515, 0, 430, 315, - 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, - 520, 521, 522, 524, 525, 526, 527, 592, 608, 576, - 545, 508, 600, 542, 546, 547, 373, 611, 0, 0, - 0, 499, 383, 384, 0, 355, 354, 396, 308, 0, - 0, 361, 300, 301, 678, 345, 415, 613, 646, 647, - 538, 0, 601, 539, 548, 337, 573, 585, 584, 411, - 498, 0, 596, 599, 528, 677, 0, 593, 607, 681, - 606, 674, 421, 0, 443, 604, 551, 0, 597, 570, - 571, 0, 598, 566, 602, 0, 540, 0, 509, 512, - 541, 626, 627, 628, 305, 511, 630, 631, 632, 633, - 634, 635, 636, 629, 482, 574, 550, 577, 490, 553, - 552, 0, 0, 588, 507, 589, 590, 405, 406, 407, - 408, 365, 614, 326, 510, 432, 0, 575, 0, 0, - 0, 0, 0, 0, 0, 0, 580, 581, 578, 686, - 0, 637, 638, 0, 0, 504, 505, 360, 367, 523, - 369, 325, 420, 362, 488, 377, 0, 516, 582, 517, - 640, 643, 641, 642, 412, 372, 374, 447, 378, 388, - 435, 487, 418, 440, 323, 478, 449, 393, 567, 595, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 0, 487, 0, 0, 0, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 622, 621, 620, - 619, 618, 617, 616, 615, 0, 0, 564, 464, 339, - 294, 335, 336, 343, 675, 671, 469, 676, 0, 302, - 544, 386, 431, 359, 609, 610, 0, 661, 248, 249, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, - 271, 272, 612, 263, 264, 273, 274, 275, 276, 277, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, - 0, 0, 0, 296, 663, 664, 665, 666, 667, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, - 293, 0, 0, 494, 495, 496, 519, 0, 497, 480, - 543, 673, 0, 0, 0, 0, 0, 0, 0, 594, - 605, 639, 0, 649, 650, 652, 654, 653, 656, 454, - 455, 662, 0, 658, 659, 660, 657, 390, 441, 460, - 448, 0, 679, 534, 535, 680, 645, 174, 212, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 417, 0, - 0, 549, 583, 572, 655, 537, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, - 587, 568, 579, 569, 554, 555, 556, 563, 364, 557, - 558, 559, 529, 560, 530, 561, 562, 144, 586, 536, - 450, 401, 0, 603, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 208, 2278, 0, 234, 0, 0, 0, 0, 0, - 0, 321, 235, 531, 651, 533, 532, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 451, 479, 0, 491, - 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, - 309, 457, 476, 322, 445, 489, 327, 453, 468, 317, - 416, 442, 0, 0, 311, 474, 452, 398, 310, 0, - 436, 350, 366, 347, 414, 0, 473, 502, 346, 492, - 0, 484, 313, 0, 483, 413, 470, 475, 399, 392, - 0, 312, 472, 397, 391, 379, 356, 518, 380, 381, - 370, 426, 389, 427, 371, 403, 402, 404, 0, 0, - 0, 0, 0, 513, 514, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 644, 0, 0, 648, 0, 486, 0, 0, 0, 0, - 0, 0, 456, 0, 0, 382, 0, 0, 0, 503, - 0, 439, 419, 682, 0, 0, 437, 387, 471, 428, - 477, 458, 485, 433, 429, 303, 459, 349, 400, 318, - 320, 672, 351, 353, 357, 358, 409, 410, 423, 444, - 461, 462, 463, 348, 332, 438, 333, 368, 334, 304, - 340, 338, 341, 446, 342, 306, 424, 467, 0, 363, - 434, 395, 307, 394, 425, 466, 465, 319, 493, 500, - 501, 591, 0, 506, 683, 684, 685, 515, 0, 430, - 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, - 422, 520, 521, 522, 524, 525, 526, 527, 592, 608, - 576, 545, 508, 600, 542, 546, 547, 373, 611, 0, - 0, 0, 499, 383, 384, 0, 355, 354, 396, 308, - 0, 0, 361, 300, 301, 678, 345, 415, 613, 646, - 647, 538, 0, 601, 539, 548, 337, 573, 585, 584, - 411, 498, 0, 596, 599, 528, 677, 0, 593, 607, - 681, 606, 674, 421, 0, 443, 604, 551, 0, 597, - 570, 571, 0, 598, 566, 602, 0, 540, 0, 509, - 512, 541, 626, 627, 628, 305, 511, 630, 631, 632, - 633, 634, 635, 636, 629, 482, 574, 550, 577, 490, - 553, 552, 0, 0, 588, 507, 589, 590, 405, 406, - 407, 408, 365, 614, 326, 510, 432, 0, 575, 0, - 0, 0, 0, 0, 0, 0, 0, 580, 581, 578, - 686, 0, 637, 638, 0, 0, 504, 505, 360, 367, - 523, 369, 325, 420, 362, 488, 377, 0, 516, 582, - 517, 640, 643, 641, 642, 412, 372, 374, 447, 378, - 388, 435, 487, 418, 440, 323, 478, 449, 393, 567, - 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 622, 621, - 620, 619, 618, 617, 616, 615, 0, 0, 564, 464, - 339, 294, 335, 336, 343, 675, 671, 469, 676, 0, - 302, 544, 386, 431, 359, 609, 610, 0, 661, 248, - 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, - 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, - 270, 271, 272, 612, 263, 264, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 0, 0, 0, 0, 296, 663, 664, 665, 666, 667, - 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, - 292, 293, 0, 0, 494, 495, 496, 519, 0, 497, - 480, 543, 673, 0, 0, 0, 0, 0, 0, 0, - 594, 605, 639, 0, 649, 650, 652, 654, 653, 656, - 454, 455, 662, 0, 658, 659, 660, 657, 390, 441, - 460, 448, 0, 679, 534, 535, 680, 645, 417, 0, - 0, 549, 583, 572, 655, 537, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 352, 1092, 0, 385, - 587, 568, 579, 569, 554, 555, 556, 563, 364, 557, - 558, 559, 529, 560, 530, 561, 562, 0, 586, 536, - 450, 401, 0, 603, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 234, 1099, 1100, 0, 0, 0, - 0, 321, 235, 531, 651, 533, 532, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1103, 0, 0, 0, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 417, 0, 0, + 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 0, 0, 385, 588, + 569, 580, 570, 555, 556, 557, 564, 364, 558, 559, + 560, 530, 561, 531, 562, 563, 0, 587, 537, 451, + 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 234, 0, 0, 1622, 0, 0, 0, + 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 451, 479, 0, 491, - 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, - 309, 457, 1086, 322, 445, 489, 327, 453, 468, 317, - 416, 442, 0, 0, 311, 474, 452, 398, 310, 0, - 436, 350, 366, 347, 414, 0, 473, 502, 346, 492, - 1072, 484, 313, 1071, 483, 413, 470, 475, 399, 392, - 0, 312, 472, 397, 391, 379, 356, 518, 380, 381, - 370, 426, 389, 427, 371, 403, 402, 404, 0, 0, - 0, 0, 0, 513, 514, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 644, 0, 0, 648, 0, 486, 0, 0, 0, 0, - 0, 0, 456, 0, 0, 382, 0, 0, 0, 503, - 0, 439, 419, 682, 0, 0, 437, 387, 471, 428, - 477, 458, 485, 1090, 429, 303, 459, 349, 400, 318, - 320, 672, 351, 353, 357, 358, 409, 410, 423, 444, - 461, 462, 463, 348, 332, 438, 333, 368, 334, 304, - 340, 338, 341, 446, 342, 306, 424, 467, 0, 363, - 434, 395, 307, 394, 425, 466, 465, 319, 493, 500, - 501, 591, 0, 506, 683, 684, 685, 515, 0, 430, - 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, - 422, 520, 521, 522, 524, 525, 526, 527, 592, 608, - 576, 545, 508, 600, 542, 546, 547, 373, 611, 0, - 0, 0, 499, 383, 384, 0, 355, 354, 396, 308, - 0, 0, 361, 300, 301, 678, 345, 415, 613, 646, - 647, 538, 0, 601, 539, 548, 337, 573, 585, 584, - 411, 498, 0, 596, 599, 528, 677, 0, 593, 607, - 681, 606, 674, 421, 0, 443, 604, 551, 0, 597, - 570, 571, 0, 598, 566, 602, 0, 540, 0, 509, - 512, 541, 626, 627, 628, 305, 511, 630, 631, 632, - 633, 634, 635, 1091, 629, 482, 574, 550, 577, 490, - 553, 552, 0, 0, 588, 1094, 589, 590, 405, 406, - 407, 408, 365, 614, 1089, 510, 432, 0, 575, 0, - 0, 0, 0, 0, 0, 0, 0, 580, 581, 578, - 686, 0, 637, 638, 0, 0, 504, 505, 360, 367, - 523, 369, 325, 420, 362, 488, 377, 0, 516, 582, - 517, 640, 643, 641, 642, 1101, 1087, 1097, 1088, 378, - 388, 435, 487, 418, 440, 323, 478, 449, 1098, 567, - 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 452, 480, 0, 492, 0, + 375, 376, 1620, 0, 0, 0, 0, 0, 0, 309, + 458, 477, 322, 446, 490, 327, 454, 469, 317, 416, + 443, 0, 0, 311, 475, 453, 398, 310, 0, 437, + 350, 366, 347, 414, 0, 474, 503, 346, 493, 0, + 485, 313, 0, 484, 413, 471, 476, 399, 392, 0, + 312, 473, 397, 391, 379, 356, 519, 380, 381, 370, + 427, 389, 428, 371, 403, 402, 404, 0, 0, 0, + 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 645, + 0, 0, 649, 0, 487, 0, 0, 0, 0, 0, + 0, 457, 0, 0, 382, 0, 0, 0, 504, 0, + 440, 419, 683, 0, 0, 438, 387, 472, 429, 478, + 459, 486, 434, 430, 303, 460, 349, 400, 318, 320, + 673, 351, 353, 357, 358, 409, 410, 424, 445, 462, + 463, 464, 348, 332, 439, 333, 368, 334, 304, 340, + 338, 341, 447, 342, 306, 425, 468, 0, 363, 435, + 395, 307, 394, 426, 467, 466, 319, 494, 501, 502, + 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, + 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, + 423, 521, 522, 523, 525, 526, 527, 528, 593, 609, + 577, 546, 509, 601, 543, 547, 548, 373, 612, 0, + 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, + 0, 0, 361, 300, 301, 679, 345, 415, 614, 647, + 648, 539, 0, 602, 540, 549, 337, 574, 586, 585, + 411, 499, 0, 597, 600, 529, 678, 0, 594, 608, + 682, 607, 675, 421, 0, 444, 605, 552, 0, 598, + 571, 572, 0, 599, 567, 603, 0, 541, 0, 510, + 513, 542, 627, 628, 629, 305, 512, 631, 632, 633, + 634, 635, 636, 637, 630, 483, 575, 551, 578, 491, + 554, 553, 0, 0, 589, 508, 590, 591, 405, 406, + 407, 408, 365, 615, 326, 511, 433, 0, 576, 0, + 0, 0, 0, 0, 0, 0, 0, 581, 582, 579, + 687, 0, 638, 639, 0, 0, 505, 506, 360, 367, + 524, 369, 325, 420, 362, 489, 377, 0, 517, 583, + 518, 641, 644, 642, 643, 412, 372, 374, 448, 378, + 388, 436, 488, 418, 441, 323, 479, 450, 393, 568, + 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 622, 621, - 620, 619, 618, 617, 616, 615, 0, 0, 564, 464, - 339, 294, 335, 336, 343, 675, 671, 469, 676, 0, - 302, 544, 386, 431, 359, 609, 610, 0, 661, 248, + 0, 0, 0, 0, 0, 0, 0, 0, 623, 622, + 621, 620, 619, 618, 617, 616, 0, 0, 565, 465, + 339, 294, 335, 336, 343, 676, 672, 470, 677, 0, + 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, - 270, 271, 272, 612, 263, 264, 273, 274, 275, 276, + 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 0, 0, 0, 0, 296, 663, 664, 665, 666, 667, + 0, 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, - 292, 293, 0, 0, 494, 495, 496, 519, 0, 497, - 480, 543, 673, 0, 0, 0, 0, 0, 0, 0, - 594, 605, 639, 0, 649, 650, 652, 654, 653, 656, - 454, 455, 662, 0, 658, 659, 660, 657, 1085, 441, - 460, 448, 0, 679, 534, 535, 680, 645, 174, 212, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 144, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2168, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 292, 293, 0, 0, 495, 496, 497, 520, 0, 498, + 481, 544, 674, 0, 0, 0, 0, 0, 0, 0, + 595, 606, 640, 0, 650, 651, 653, 655, 654, 657, + 455, 456, 663, 0, 659, 660, 661, 658, 390, 442, + 461, 449, 0, 680, 535, 536, 681, 646, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 0, 587, 537, + 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 1099, 1100, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1103, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 1072, 484, 313, 1071, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 1101, 2189, 1097, 2190, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 1098, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 3126, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 0, 0, 1622, 0, 0, + 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 1835, 0, 0, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 0, 474, 503, 346, 493, + 0, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 519, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3129, 0, 0, 0, 0, - 3128, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 0, 0, 649, 0, 487, 0, 0, 0, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 504, + 0, 440, 419, 683, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 345, 415, 614, + 647, 648, 539, 0, 602, 540, 549, 337, 574, 586, + 585, 411, 499, 0, 597, 600, 529, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 483, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 508, 590, 591, 405, + 406, 407, 408, 365, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 0, 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, + 269, 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 1623, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, + 286, 0, 0, 0, 0, 296, 664, 665, 666, 667, + 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, + 291, 292, 293, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 654, + 657, 455, 456, 663, 0, 659, 660, 661, 658, 390, + 442, 461, 449, 0, 680, 535, 536, 681, 646, 417, + 0, 0, 550, 584, 573, 656, 538, 0, 0, 0, + 0, 0, 2653, 0, 0, 0, 0, 352, 0, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 234, 0, 0, 2655, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 1619, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 1617, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 477, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 0, 485, 313, 0, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 0, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 434, 430, 303, 460, 349, 400, + 318, 320, 673, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 637, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 508, 590, 591, + 405, 406, 407, 408, 365, 615, 326, 511, 433, 0, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 412, 372, 374, + 448, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 390, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 2239, 0, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 0, + 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 0, 0, 2240, + 0, 0, 0, 321, 235, 532, 652, 534, 533, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 0, 474, 503, + 346, 493, 0, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 519, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 0, 0, 649, 0, 487, 0, 0, + 0, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 504, 0, 440, 419, 683, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 345, + 415, 614, 647, 648, 539, 0, 602, 540, 549, 337, + 574, 586, 585, 411, 499, 0, 597, 600, 529, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 483, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 508, 590, + 591, 405, 406, 407, 408, 365, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 0, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, + 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, + 267, 268, 269, 270, 271, 272, 613, 263, 264, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 0, 0, 0, 0, 296, 664, 665, + 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, + 289, 290, 291, 292, 293, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 654, 657, 455, 456, 663, 0, 659, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 417, 0, 0, 550, 584, 573, 656, 538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 0, 0, 385, 588, 569, 580, 570, 555, 556, 557, + 564, 364, 558, 559, 560, 530, 561, 531, 562, 563, + 0, 587, 537, 451, 401, 0, 604, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, + 3353, 3355, 0, 0, 321, 235, 532, 652, 534, 533, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, + 480, 0, 492, 0, 375, 376, 0, 0, 0, 0, + 0, 0, 0, 309, 458, 477, 322, 446, 490, 327, + 454, 469, 317, 416, 443, 0, 0, 311, 475, 453, + 398, 310, 0, 437, 350, 366, 347, 414, 0, 474, + 503, 346, 493, 0, 485, 313, 0, 484, 413, 471, + 476, 399, 392, 0, 312, 473, 397, 391, 379, 356, + 519, 380, 381, 370, 427, 389, 428, 371, 403, 402, + 404, 0, 0, 0, 0, 0, 514, 515, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 645, 0, 0, 649, 0, 487, 0, + 0, 0, 0, 0, 0, 457, 0, 0, 382, 0, + 0, 0, 504, 0, 440, 419, 683, 0, 0, 438, + 387, 472, 429, 478, 459, 486, 434, 430, 303, 460, + 349, 400, 318, 320, 673, 351, 353, 357, 358, 409, + 410, 424, 445, 462, 463, 464, 348, 332, 439, 333, + 368, 334, 304, 340, 338, 341, 447, 342, 306, 425, + 468, 0, 363, 435, 395, 307, 394, 426, 467, 466, + 319, 494, 501, 502, 592, 0, 507, 684, 685, 686, + 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, + 330, 331, 329, 422, 423, 521, 522, 523, 525, 526, + 527, 528, 593, 609, 577, 546, 509, 601, 543, 547, + 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, + 355, 354, 396, 308, 0, 0, 361, 300, 301, 679, + 345, 415, 614, 647, 648, 539, 0, 602, 540, 549, + 337, 574, 586, 585, 411, 499, 0, 597, 600, 529, + 678, 0, 594, 608, 682, 607, 675, 421, 0, 444, + 605, 552, 0, 598, 571, 572, 0, 599, 567, 603, + 0, 541, 0, 510, 513, 542, 627, 628, 629, 305, + 512, 631, 632, 633, 634, 635, 636, 637, 630, 483, + 575, 551, 578, 491, 554, 553, 0, 0, 589, 508, + 590, 591, 405, 406, 407, 408, 365, 615, 326, 511, + 433, 0, 576, 0, 0, 0, 0, 0, 0, 0, + 0, 581, 582, 579, 687, 0, 638, 639, 0, 0, + 505, 506, 360, 367, 524, 369, 325, 420, 362, 489, + 377, 0, 517, 583, 518, 641, 644, 642, 643, 412, + 372, 374, 448, 378, 388, 436, 488, 418, 441, 323, + 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 623, 622, 621, 620, 619, 618, 617, 616, + 0, 0, 565, 465, 339, 294, 335, 336, 343, 676, + 672, 470, 677, 0, 302, 545, 386, 432, 359, 610, + 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, + 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, + 266, 267, 268, 269, 270, 271, 272, 613, 263, 264, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 0, 0, 0, 0, 296, 664, + 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, + 0, 289, 290, 291, 292, 293, 0, 0, 495, 496, + 497, 520, 0, 498, 481, 544, 674, 0, 0, 0, + 0, 0, 0, 0, 595, 606, 640, 0, 650, 651, + 653, 655, 654, 657, 455, 456, 663, 0, 659, 660, + 661, 658, 390, 442, 461, 449, 0, 680, 535, 536, + 681, 646, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 352, 2676, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 0, 587, 537, 451, 401, 0, 604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, + 0, 1622, 0, 0, 0, 321, 235, 532, 652, 534, + 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 0, 0, 0, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 0, + 474, 503, 346, 493, 0, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 519, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 0, 0, 649, 0, 487, + 0, 0, 0, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 504, 0, 440, 419, 683, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 345, 415, 614, 647, 648, 539, 0, 602, 540, + 549, 337, 574, 586, 585, 411, 499, 0, 597, 600, + 529, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 483, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 508, 590, 591, 405, 406, 407, 408, 365, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 0, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, + 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, + 265, 266, 267, 268, 269, 270, 271, 272, 613, 263, + 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 0, 0, 0, 0, 296, + 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, + 0, 0, 289, 290, 291, 292, 293, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 654, 657, 455, 456, 663, 0, 659, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 417, 0, 0, 550, 584, 573, 656, + 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 699, 352, 0, 0, 385, 588, 569, 580, 570, 555, + 556, 557, 564, 364, 558, 559, 560, 530, 561, 531, + 562, 563, 0, 587, 537, 451, 401, 0, 604, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 321, 235, 532, 652, + 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 452, 480, 0, 492, 0, 375, 376, 0, 0, + 0, 0, 0, 0, 0, 309, 458, 477, 322, 446, + 490, 327, 454, 469, 317, 416, 443, 0, 0, 311, + 475, 453, 398, 310, 0, 437, 350, 366, 347, 414, + 0, 474, 503, 346, 493, 0, 485, 313, 0, 484, + 413, 471, 476, 399, 392, 0, 312, 473, 397, 391, + 379, 356, 519, 380, 381, 370, 427, 389, 428, 371, + 403, 402, 404, 0, 0, 0, 0, 0, 514, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 645, 0, 0, 649, 0, + 487, 0, 1014, 0, 0, 0, 0, 457, 0, 0, + 382, 0, 0, 0, 504, 0, 440, 419, 683, 0, + 0, 438, 387, 472, 429, 478, 459, 486, 434, 430, + 303, 460, 349, 400, 318, 320, 673, 351, 353, 357, + 358, 409, 410, 424, 445, 462, 463, 464, 348, 332, + 439, 333, 368, 334, 304, 340, 338, 341, 447, 342, + 306, 425, 468, 0, 363, 435, 395, 307, 394, 426, + 467, 466, 319, 494, 501, 502, 592, 0, 507, 684, + 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, + 344, 328, 330, 331, 329, 422, 423, 521, 522, 523, + 525, 526, 527, 528, 593, 609, 577, 546, 509, 601, + 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, + 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, + 301, 679, 345, 415, 614, 647, 648, 539, 0, 602, + 540, 549, 337, 574, 586, 585, 411, 499, 0, 597, + 600, 529, 678, 0, 594, 608, 682, 607, 675, 421, + 0, 444, 605, 552, 0, 598, 571, 572, 0, 599, + 567, 603, 0, 541, 0, 510, 513, 542, 627, 628, + 629, 305, 512, 631, 632, 633, 634, 635, 636, 637, + 630, 483, 575, 551, 578, 491, 554, 553, 0, 0, + 589, 508, 590, 591, 405, 406, 407, 408, 365, 615, + 326, 511, 433, 0, 576, 0, 0, 0, 0, 0, + 0, 0, 0, 581, 582, 579, 687, 0, 638, 639, + 0, 0, 505, 506, 360, 367, 524, 369, 325, 420, + 362, 489, 377, 0, 517, 583, 518, 641, 644, 642, + 643, 412, 372, 374, 448, 378, 388, 436, 488, 418, + 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 622, 621, 620, 619, 618, + 617, 616, 0, 0, 565, 465, 339, 294, 335, 336, + 343, 676, 672, 470, 677, 0, 302, 545, 386, 432, + 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, + 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, + 262, 265, 266, 267, 268, 269, 270, 271, 272, 613, + 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, + 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, + 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, + 495, 496, 497, 520, 0, 498, 481, 544, 674, 0, + 0, 0, 0, 0, 0, 0, 595, 606, 640, 0, + 650, 651, 653, 655, 654, 657, 455, 456, 663, 0, + 659, 660, 661, 658, 390, 442, 461, 449, 0, 680, + 535, 536, 681, 646, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 0, 587, 537, 451, 401, 0, 604, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 892, 0, 0, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 1619, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4294, 0, 234, 891, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 0, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 0, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 504, 0, 440, 419, 683, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, + 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, + 300, 301, 679, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 0, + 597, 600, 529, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, + 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 0, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, + 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, + 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, + 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 0, + 680, 535, 536, 681, 646, 417, 0, 0, 550, 584, + 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 352, 0, 0, 385, 588, 569, 580, + 570, 555, 556, 557, 564, 364, 558, 559, 560, 530, + 561, 531, 562, 563, 0, 587, 537, 451, 401, 0, + 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4273, 0, + 0, 234, 0, 0, 0, 0, 0, 0, 321, 235, + 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 452, 480, 0, 492, 0, 375, 376, + 0, 0, 0, 0, 0, 0, 0, 309, 458, 477, + 322, 446, 490, 327, 454, 469, 317, 416, 443, 0, + 0, 311, 475, 453, 398, 310, 0, 437, 350, 366, + 347, 414, 0, 474, 503, 346, 493, 0, 485, 313, + 0, 484, 413, 471, 476, 399, 392, 0, 312, 473, + 397, 391, 379, 356, 519, 380, 381, 370, 427, 389, + 428, 371, 403, 402, 404, 0, 0, 0, 0, 0, + 514, 515, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 645, 0, 0, + 649, 0, 487, 0, 0, 0, 0, 0, 0, 457, + 0, 0, 382, 0, 0, 0, 504, 0, 440, 419, + 683, 0, 0, 438, 387, 472, 429, 478, 459, 486, + 434, 430, 303, 460, 349, 400, 318, 320, 673, 351, + 353, 357, 358, 409, 410, 424, 445, 462, 463, 464, + 348, 332, 439, 333, 368, 334, 304, 340, 338, 341, + 447, 342, 306, 425, 468, 0, 363, 435, 395, 307, + 394, 426, 467, 466, 319, 494, 501, 502, 592, 0, + 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, + 0, 0, 344, 328, 330, 331, 329, 422, 423, 521, + 522, 523, 525, 526, 527, 528, 593, 609, 577, 546, + 509, 601, 543, 547, 548, 373, 612, 0, 0, 0, + 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, + 361, 300, 301, 679, 345, 415, 614, 647, 648, 539, + 0, 602, 540, 549, 337, 574, 586, 585, 411, 499, + 0, 597, 600, 529, 678, 0, 594, 608, 682, 607, + 675, 421, 0, 444, 605, 552, 0, 598, 571, 572, + 0, 599, 567, 603, 0, 541, 0, 510, 513, 542, + 627, 628, 629, 305, 512, 631, 632, 633, 634, 635, + 636, 637, 630, 483, 575, 551, 578, 491, 554, 553, + 0, 0, 589, 508, 590, 591, 405, 406, 407, 408, + 365, 615, 326, 511, 433, 0, 576, 0, 0, 0, + 0, 0, 0, 0, 0, 581, 582, 579, 687, 0, + 638, 639, 0, 0, 505, 506, 360, 367, 524, 369, + 325, 420, 362, 489, 377, 0, 517, 583, 518, 641, + 644, 642, 643, 412, 372, 374, 448, 378, 388, 436, + 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 1619, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 1834, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 2652, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 2654, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 2238, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 2239, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 3352, 3354, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 2675, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 698, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 1013, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 891, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4271, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 4022, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 4180, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1848, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4037, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 3944, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 3385, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3409, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2168, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 3624, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3520, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3231, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 2654, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 3044, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 2904, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2303, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 2779, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2734, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 2732, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 2503, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 623, 622, 621, 620, + 619, 618, 617, 616, 0, 0, 565, 465, 339, 294, + 335, 336, 343, 676, 672, 470, 677, 0, 302, 545, + 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, + 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, + 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, + 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, + 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, + 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, + 0, 0, 495, 496, 497, 520, 0, 498, 481, 544, + 674, 0, 0, 0, 0, 0, 0, 0, 595, 606, + 640, 0, 650, 651, 653, 655, 654, 657, 455, 456, + 663, 0, 659, 660, 661, 658, 390, 442, 461, 449, + 0, 680, 535, 536, 681, 646, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 0, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 234, 0, 0, 4024, 0, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 0, 487, 0, 0, 0, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 2012, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, + 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, + 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, + 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 417, 0, 0, + 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 0, 0, 385, 588, + 569, 580, 570, 555, 556, 557, 564, 364, 558, 559, + 560, 530, 561, 531, 562, 563, 0, 587, 537, 451, + 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, + 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 2150, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 452, 480, 0, 492, 0, + 375, 376, 0, 0, 0, 0, 0, 0, 0, 309, + 458, 477, 322, 446, 490, 327, 454, 469, 317, 416, + 443, 0, 0, 311, 475, 453, 398, 310, 0, 437, + 350, 366, 347, 414, 0, 474, 503, 346, 493, 0, + 485, 313, 0, 484, 413, 471, 476, 399, 392, 0, + 312, 473, 397, 391, 379, 356, 519, 380, 381, 370, + 427, 389, 428, 371, 403, 402, 404, 0, 0, 0, + 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 645, + 0, 0, 649, 0, 487, 0, 0, 0, 4182, 0, + 0, 457, 0, 0, 382, 0, 0, 0, 504, 0, + 440, 419, 683, 0, 0, 438, 387, 472, 429, 478, + 459, 486, 434, 430, 303, 460, 349, 400, 318, 320, + 673, 351, 353, 357, 358, 409, 410, 424, 445, 462, + 463, 464, 348, 332, 439, 333, 368, 334, 304, 340, + 338, 341, 447, 342, 306, 425, 468, 0, 363, 435, + 395, 307, 394, 426, 467, 466, 319, 494, 501, 502, + 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, + 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, + 423, 521, 522, 523, 525, 526, 527, 528, 593, 609, + 577, 546, 509, 601, 543, 547, 548, 373, 612, 0, + 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, + 0, 0, 361, 300, 301, 679, 345, 415, 614, 647, + 648, 539, 0, 602, 540, 549, 337, 574, 586, 585, + 411, 499, 0, 597, 600, 529, 678, 0, 594, 608, + 682, 607, 675, 421, 0, 444, 605, 552, 0, 598, + 571, 572, 0, 599, 567, 603, 0, 541, 0, 510, + 513, 542, 627, 628, 629, 305, 512, 631, 632, 633, + 634, 635, 636, 637, 630, 483, 575, 551, 578, 491, + 554, 553, 0, 0, 589, 508, 590, 591, 405, 406, + 407, 408, 365, 615, 326, 511, 433, 0, 576, 0, + 0, 0, 0, 0, 0, 0, 0, 581, 582, 579, + 687, 0, 638, 639, 0, 0, 505, 506, 360, 367, + 524, 369, 325, 420, 362, 489, 377, 0, 517, 583, + 518, 641, 644, 642, 643, 412, 372, 374, 448, 378, + 388, 436, 488, 418, 441, 323, 479, 450, 393, 568, + 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 623, 622, + 621, 620, 619, 618, 617, 616, 0, 0, 565, 465, + 339, 294, 335, 336, 343, 676, 672, 470, 677, 0, + 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, + 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, + 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, + 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 0, 0, 0, 0, 296, 664, 665, 666, 667, 668, + 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, + 292, 293, 0, 0, 495, 496, 497, 520, 0, 498, + 481, 544, 674, 0, 0, 0, 0, 0, 0, 0, + 595, 606, 640, 0, 650, 651, 653, 655, 654, 657, + 455, 456, 663, 0, 659, 660, 661, 658, 390, 442, + 461, 449, 0, 680, 535, 536, 681, 646, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 0, 587, 537, + 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 1849, 0, 0, 234, 0, 0, 0, 0, 0, + 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 0, 474, 503, 346, 493, + 0, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 519, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 0, 0, 649, 0, 487, 0, 0, 0, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 504, + 0, 440, 419, 683, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 345, 415, 614, + 647, 648, 539, 0, 602, 540, 549, 337, 574, 586, + 585, 411, 499, 0, 597, 600, 529, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 483, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 508, 590, 591, 405, + 406, 407, 408, 365, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 0, 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, + 269, 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, + 286, 0, 0, 0, 0, 296, 664, 665, 666, 667, + 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, + 291, 292, 293, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 654, + 657, 455, 456, 663, 0, 659, 660, 661, 658, 390, + 442, 461, 449, 0, 680, 535, 536, 681, 646, 417, + 0, 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 1621, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, + 0, 0, 0, 4039, 0, 234, 0, 0, 0, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 2054, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 477, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 0, 485, 313, 0, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 0, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 434, 430, 303, 460, 349, 400, + 318, 320, 673, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 637, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 508, 590, 591, + 405, 406, 407, 408, 365, 615, 326, 511, 433, 0, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 412, 372, 374, + 448, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 390, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 0, + 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, + 0, 0, 0, 321, 235, 532, 652, 534, 533, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 0, 474, 503, + 346, 493, 0, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 519, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 0, 0, 649, 0, 487, 0, 0, + 0, 3946, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 504, 0, 440, 419, 683, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 345, + 415, 614, 647, 648, 539, 0, 602, 540, 549, 337, + 574, 586, 585, 411, 499, 0, 597, 600, 529, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 483, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 508, 590, + 591, 405, 406, 407, 408, 365, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 0, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, + 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, + 267, 268, 269, 270, 271, 272, 613, 263, 264, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 0, 0, 0, 0, 296, 664, 665, + 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, + 289, 290, 291, 292, 293, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 654, 657, 455, 456, 663, 0, 659, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 417, 0, 0, 550, 584, 573, 656, 538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 0, 0, 385, 588, 569, 580, 570, 555, 556, 557, + 564, 364, 558, 559, 560, 530, 561, 531, 562, 563, + 0, 587, 537, 451, 401, 0, 604, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, + 3386, 0, 0, 0, 321, 235, 532, 652, 534, 533, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, + 480, 0, 492, 0, 375, 376, 0, 0, 0, 0, + 0, 0, 0, 309, 458, 477, 322, 446, 490, 327, + 454, 469, 317, 416, 443, 0, 0, 311, 475, 453, + 398, 310, 0, 437, 350, 366, 347, 414, 0, 474, + 503, 346, 493, 0, 485, 313, 0, 484, 413, 471, + 476, 399, 392, 0, 312, 473, 397, 391, 379, 356, + 519, 380, 381, 370, 427, 389, 428, 371, 403, 402, + 404, 0, 0, 0, 0, 0, 514, 515, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 645, 0, 0, 649, 0, 487, 0, + 0, 0, 0, 0, 0, 457, 0, 0, 382, 0, + 0, 0, 504, 0, 440, 419, 683, 0, 0, 438, + 387, 472, 429, 478, 459, 486, 434, 430, 303, 460, + 349, 400, 318, 320, 673, 351, 353, 357, 358, 409, + 410, 424, 445, 462, 463, 464, 348, 332, 439, 333, + 368, 334, 304, 340, 338, 341, 447, 342, 306, 425, + 468, 0, 363, 435, 395, 307, 394, 426, 467, 466, + 319, 494, 501, 502, 592, 0, 507, 684, 685, 686, + 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, + 330, 331, 329, 422, 423, 521, 522, 523, 525, 526, + 527, 528, 593, 609, 577, 546, 509, 601, 543, 547, + 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, + 355, 354, 396, 308, 0, 0, 361, 300, 301, 679, + 345, 415, 614, 647, 648, 539, 0, 602, 540, 549, + 337, 574, 586, 585, 411, 499, 0, 597, 600, 529, + 678, 0, 594, 608, 682, 607, 675, 421, 0, 444, + 605, 552, 0, 598, 571, 572, 0, 599, 567, 603, + 0, 541, 0, 510, 513, 542, 627, 628, 629, 305, + 512, 631, 632, 633, 634, 635, 636, 637, 630, 483, + 575, 551, 578, 491, 554, 553, 0, 0, 589, 508, + 590, 591, 405, 406, 407, 408, 365, 615, 326, 511, + 433, 0, 576, 0, 0, 0, 0, 0, 0, 0, + 0, 581, 582, 579, 687, 0, 638, 639, 0, 0, + 505, 506, 360, 367, 524, 369, 325, 420, 362, 489, + 377, 0, 517, 583, 518, 641, 644, 642, 643, 412, + 372, 374, 448, 378, 388, 436, 488, 418, 441, 323, + 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 623, 622, 621, 620, 619, 618, 617, 616, + 0, 0, 565, 465, 339, 294, 335, 336, 343, 676, + 672, 470, 677, 0, 302, 545, 386, 432, 359, 610, + 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, + 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, + 266, 267, 268, 269, 270, 271, 272, 613, 263, 264, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 0, 0, 0, 0, 296, 664, + 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, + 0, 289, 290, 291, 292, 293, 0, 0, 495, 496, + 497, 520, 0, 498, 481, 544, 674, 0, 0, 0, + 0, 0, 0, 0, 595, 606, 640, 0, 650, 651, + 653, 655, 654, 657, 455, 456, 663, 0, 659, 660, + 661, 658, 390, 442, 461, 449, 0, 680, 535, 536, + 681, 646, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 0, 587, 537, 451, 401, 0, 604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, + 0, 0, 0, 0, 0, 321, 235, 532, 652, 534, + 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3410, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 0, 0, 0, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 0, + 474, 503, 346, 493, 0, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 519, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 0, 0, 649, 0, 487, + 0, 0, 0, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 504, 0, 440, 419, 683, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 345, 415, 614, 647, 648, 539, 0, 602, 540, + 549, 337, 574, 586, 585, 411, 499, 0, 597, 600, + 529, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 483, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 508, 590, 591, 405, 406, 407, 408, 365, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 0, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, + 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, + 265, 266, 267, 268, 269, 270, 271, 272, 613, 263, + 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 0, 0, 0, 0, 296, + 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, + 0, 0, 289, 290, 291, 292, 293, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 654, 657, 455, 456, 663, 0, 659, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 417, 0, 0, 550, 584, 573, 656, + 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 352, 0, 0, 385, 588, 569, 580, 570, 555, + 556, 557, 564, 364, 558, 559, 560, 530, 561, 531, + 562, 563, 0, 587, 537, 451, 401, 0, 604, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2169, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 321, 235, 532, 652, + 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 452, 480, 0, 492, 0, 375, 376, 0, 0, + 0, 0, 0, 0, 0, 309, 458, 477, 322, 446, + 490, 327, 454, 469, 317, 416, 443, 0, 0, 311, + 475, 453, 398, 310, 0, 437, 350, 366, 347, 414, + 0, 474, 503, 346, 493, 0, 485, 313, 0, 484, + 413, 471, 476, 399, 392, 0, 312, 473, 397, 391, + 379, 356, 519, 380, 381, 370, 427, 389, 428, 371, + 403, 402, 404, 0, 0, 0, 0, 0, 514, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 645, 0, 0, 649, 0, + 487, 0, 0, 0, 0, 0, 0, 457, 0, 0, + 382, 0, 0, 0, 504, 0, 440, 419, 683, 0, + 0, 438, 387, 472, 429, 478, 459, 486, 434, 430, + 303, 460, 349, 400, 318, 320, 673, 351, 353, 357, + 358, 409, 410, 424, 445, 462, 463, 464, 348, 332, + 439, 333, 368, 334, 304, 340, 338, 341, 447, 342, + 306, 425, 468, 0, 363, 435, 395, 307, 394, 426, + 467, 466, 319, 494, 501, 502, 592, 0, 507, 684, + 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, + 344, 328, 330, 331, 329, 422, 423, 521, 522, 523, + 525, 526, 527, 528, 593, 609, 577, 546, 509, 601, + 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, + 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, + 301, 679, 345, 415, 614, 647, 648, 539, 0, 602, + 540, 549, 337, 574, 586, 585, 411, 499, 0, 597, + 600, 529, 678, 0, 594, 608, 682, 607, 675, 421, + 0, 444, 605, 552, 0, 598, 571, 572, 0, 599, + 567, 603, 0, 541, 0, 510, 513, 542, 627, 628, + 629, 305, 512, 631, 632, 633, 634, 635, 636, 637, + 630, 483, 575, 551, 578, 491, 554, 553, 0, 0, + 589, 508, 590, 591, 405, 406, 407, 408, 365, 615, + 326, 511, 433, 0, 576, 0, 0, 0, 0, 0, + 0, 0, 0, 581, 582, 579, 687, 0, 638, 639, + 0, 0, 505, 506, 360, 367, 524, 369, 325, 420, + 362, 489, 377, 0, 517, 583, 518, 641, 644, 642, + 643, 412, 372, 374, 448, 378, 388, 436, 488, 418, + 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 622, 621, 620, 619, 618, + 617, 616, 0, 0, 565, 465, 339, 294, 335, 336, + 343, 676, 672, 470, 677, 0, 302, 545, 386, 432, + 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, + 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, + 262, 265, 266, 267, 268, 269, 270, 271, 272, 613, + 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, + 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, + 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, + 495, 496, 497, 520, 0, 498, 481, 544, 674, 0, + 0, 0, 0, 0, 0, 0, 595, 606, 640, 0, + 650, 651, 653, 655, 654, 657, 455, 456, 663, 0, + 659, 660, 661, 658, 390, 442, 461, 449, 0, 680, + 535, 536, 681, 646, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 3626, 0, 0, 0, 0, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 0, 587, 537, 451, 401, 0, 604, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 0, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 0, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 0, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 504, 0, 440, 419, 683, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, + 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, + 300, 301, 679, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 0, + 597, 600, 529, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, + 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 0, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, + 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, + 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, + 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 0, + 680, 535, 536, 681, 646, 417, 0, 0, 550, 584, + 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 352, 0, 0, 385, 588, 569, 580, + 570, 555, 556, 557, 564, 364, 558, 559, 560, 530, + 561, 531, 562, 563, 0, 587, 537, 451, 401, 0, + 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 1650, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 698, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 234, 0, 0, 0, 0, 0, 0, 321, 235, + 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3521, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 452, 480, 0, 492, 0, 375, 376, + 0, 0, 0, 0, 0, 0, 0, 309, 458, 477, + 322, 446, 490, 327, 454, 469, 317, 416, 443, 0, + 0, 311, 475, 453, 398, 310, 0, 437, 350, 366, + 347, 414, 0, 474, 503, 346, 493, 0, 485, 313, + 0, 484, 413, 471, 476, 399, 392, 0, 312, 473, + 397, 391, 379, 356, 519, 380, 381, 370, 427, 389, + 428, 371, 403, 402, 404, 0, 0, 0, 0, 0, + 514, 515, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 645, 0, 0, + 649, 0, 487, 0, 0, 0, 0, 0, 0, 457, + 0, 0, 382, 0, 0, 0, 504, 0, 440, 419, + 683, 0, 0, 438, 387, 472, 429, 478, 459, 486, + 434, 430, 303, 460, 349, 400, 318, 320, 673, 351, + 353, 357, 358, 409, 410, 424, 445, 462, 463, 464, + 348, 332, 439, 333, 368, 334, 304, 340, 338, 341, + 447, 342, 306, 425, 468, 0, 363, 435, 395, 307, + 394, 426, 467, 466, 319, 494, 501, 502, 592, 0, + 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, + 0, 0, 344, 328, 330, 331, 329, 422, 423, 521, + 522, 523, 525, 526, 527, 528, 593, 609, 577, 546, + 509, 601, 543, 547, 548, 373, 612, 0, 0, 0, + 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, + 361, 300, 301, 679, 345, 415, 614, 647, 648, 539, + 0, 602, 540, 549, 337, 574, 586, 585, 411, 499, + 0, 597, 600, 529, 678, 0, 594, 608, 682, 607, + 675, 421, 0, 444, 605, 552, 0, 598, 571, 572, + 0, 599, 567, 603, 0, 541, 0, 510, 513, 542, + 627, 628, 629, 305, 512, 631, 632, 633, 634, 635, + 636, 637, 630, 483, 575, 551, 578, 491, 554, 553, + 0, 0, 589, 508, 590, 591, 405, 406, 407, 408, + 365, 615, 326, 511, 433, 0, 576, 0, 0, 0, + 0, 0, 0, 0, 0, 581, 582, 579, 687, 0, + 638, 639, 0, 0, 505, 506, 360, 367, 524, 369, + 325, 420, 362, 489, 377, 0, 517, 583, 518, 641, + 644, 642, 643, 412, 372, 374, 448, 378, 388, 436, + 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 623, 622, 621, 620, + 619, 618, 617, 616, 0, 0, 565, 465, 339, 294, + 335, 336, 343, 676, 672, 470, 677, 0, 302, 545, + 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, + 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, + 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, + 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, + 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, + 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, + 0, 0, 495, 496, 497, 520, 0, 498, 481, 544, + 674, 0, 0, 0, 0, 0, 0, 0, 595, 606, + 640, 0, 650, 651, 653, 655, 654, 657, 455, 456, + 663, 0, 659, 660, 661, 658, 390, 442, 461, 449, + 0, 680, 535, 536, 681, 646, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 0, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 3232, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 0, 487, 0, 0, 0, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, + 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, + 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, + 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 417, 0, 0, + 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 0, 0, 385, 588, + 569, 580, 570, 555, 556, 557, 564, 364, 558, 559, + 560, 530, 561, 531, 562, 563, 0, 587, 537, 451, + 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 234, 0, 0, 1622, 0, 0, 0, + 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 703, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 452, 480, 0, 492, 0, + 375, 376, 0, 0, 0, 0, 0, 0, 0, 309, + 458, 477, 322, 446, 490, 327, 454, 469, 317, 416, + 443, 0, 0, 311, 475, 453, 398, 310, 0, 437, + 350, 366, 347, 414, 0, 474, 503, 346, 493, 0, + 485, 313, 0, 484, 413, 471, 476, 399, 392, 0, + 312, 473, 397, 391, 379, 356, 519, 380, 381, 370, + 427, 389, 428, 371, 403, 402, 404, 0, 0, 0, + 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 645, + 0, 0, 649, 0, 487, 0, 0, 0, 0, 0, + 0, 457, 0, 0, 382, 0, 0, 0, 504, 0, + 440, 419, 683, 0, 0, 438, 387, 472, 429, 478, + 459, 486, 434, 430, 303, 460, 349, 400, 318, 320, + 673, 351, 353, 357, 358, 409, 410, 424, 445, 462, + 463, 464, 348, 332, 439, 333, 368, 334, 304, 340, + 338, 341, 447, 342, 306, 425, 468, 0, 363, 435, + 395, 307, 394, 426, 467, 466, 319, 494, 501, 502, + 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, + 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, + 423, 521, 522, 523, 525, 526, 527, 528, 593, 609, + 577, 546, 509, 601, 543, 547, 548, 373, 612, 0, + 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, + 0, 0, 361, 300, 301, 679, 345, 415, 614, 647, + 648, 539, 0, 602, 540, 549, 337, 574, 586, 585, + 411, 499, 0, 597, 600, 529, 678, 0, 594, 608, + 682, 607, 675, 421, 0, 444, 605, 552, 0, 598, + 571, 572, 0, 599, 567, 603, 0, 541, 0, 510, + 513, 542, 627, 628, 629, 305, 512, 631, 632, 633, + 634, 635, 636, 637, 630, 483, 575, 551, 578, 491, + 554, 553, 0, 0, 589, 508, 590, 591, 405, 406, + 407, 408, 365, 615, 326, 511, 433, 0, 576, 0, + 0, 0, 0, 0, 0, 0, 0, 581, 582, 579, + 687, 0, 638, 639, 0, 0, 505, 506, 360, 367, + 524, 369, 325, 420, 362, 489, 377, 0, 517, 583, + 518, 641, 644, 642, 643, 412, 372, 374, 448, 378, + 388, 436, 488, 418, 441, 323, 479, 450, 393, 568, + 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 623, 622, + 621, 620, 619, 618, 617, 616, 0, 0, 565, 465, + 339, 294, 335, 336, 343, 676, 672, 470, 677, 0, + 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, + 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, + 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, + 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 0, 0, 0, 0, 296, 664, 665, 666, 667, 668, + 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, + 292, 293, 0, 0, 495, 496, 497, 520, 0, 498, + 481, 544, 674, 0, 0, 0, 0, 0, 0, 0, + 595, 606, 640, 0, 650, 651, 653, 655, 654, 657, + 455, 456, 663, 0, 659, 660, 661, 658, 390, 442, + 461, 449, 0, 680, 535, 536, 681, 646, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 0, 587, 537, + 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 0, 0, 0, 234, 0, 0, 2655, 0, 0, + 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 0, 474, 503, 346, 493, + 0, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 519, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 0, 0, 649, 0, 487, 0, 0, 0, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 504, + 0, 440, 419, 683, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 345, 415, 614, + 647, 648, 539, 0, 602, 540, 549, 337, 574, 586, + 585, 411, 499, 0, 597, 600, 529, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 483, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 508, 590, 591, 405, + 406, 407, 408, 365, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 1015, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 0, 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, + 269, 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, + 286, 0, 0, 0, 0, 296, 664, 665, 666, 667, + 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, + 291, 292, 293, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 654, + 657, 455, 456, 663, 0, 659, 660, 661, 658, 390, + 442, 461, 449, 0, 680, 535, 536, 681, 646, 417, + 0, 0, 550, 584, 573, 656, 538, 0, 0, 3045, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 477, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 0, 485, 313, 0, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 0, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 434, 430, 303, 460, 349, 400, + 318, 320, 673, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 637, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 508, 590, 591, + 405, 406, 407, 408, 365, 615, 326, 511, 433, 0, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 412, 372, 374, + 448, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 390, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 0, + 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 0, 0, 2905, + 0, 0, 0, 321, 235, 532, 652, 534, 533, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 0, 474, 503, + 346, 493, 0, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 519, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 0, 0, 649, 0, 487, 0, 0, + 0, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 504, 0, 440, 419, 683, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 345, + 415, 614, 647, 648, 539, 0, 602, 540, 549, 337, + 574, 586, 585, 411, 499, 0, 597, 600, 529, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 483, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 508, 590, + 591, 405, 406, 407, 408, 365, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 0, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, + 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, + 267, 268, 269, 270, 271, 272, 613, 263, 264, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 0, 0, 0, 0, 296, 664, 665, + 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, + 289, 290, 291, 292, 293, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 654, 657, 455, 456, 663, 0, 659, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 417, 0, 0, 550, 584, 573, 656, 538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 0, 0, 385, 588, 569, 580, 570, 555, 556, 557, + 564, 364, 558, 559, 560, 530, 561, 531, 562, 563, + 0, 587, 537, 451, 401, 0, 604, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, + 0, 0, 0, 0, 321, 235, 532, 652, 534, 533, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2304, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, + 480, 0, 492, 0, 375, 376, 0, 0, 0, 0, + 0, 0, 0, 309, 458, 477, 322, 446, 490, 327, + 454, 469, 317, 416, 443, 0, 0, 311, 475, 453, + 398, 310, 0, 437, 350, 366, 347, 414, 0, 474, + 503, 346, 493, 0, 485, 313, 0, 484, 413, 471, + 476, 399, 392, 0, 312, 473, 397, 391, 379, 356, + 519, 380, 381, 370, 427, 389, 428, 371, 403, 402, + 404, 0, 0, 0, 0, 0, 514, 515, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 645, 0, 0, 649, 0, 487, 0, + 0, 0, 0, 0, 0, 457, 0, 0, 382, 0, + 0, 0, 504, 0, 440, 419, 683, 0, 0, 438, + 387, 472, 429, 478, 459, 486, 434, 430, 303, 460, + 349, 400, 318, 320, 673, 351, 353, 357, 358, 409, + 410, 424, 445, 462, 463, 464, 348, 332, 439, 333, + 368, 334, 304, 340, 338, 341, 447, 342, 306, 425, + 468, 0, 363, 435, 395, 307, 394, 426, 467, 466, + 319, 494, 501, 502, 592, 0, 507, 684, 685, 686, + 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, + 330, 331, 329, 422, 423, 521, 522, 523, 525, 526, + 527, 528, 593, 609, 577, 546, 509, 601, 543, 547, + 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, + 355, 354, 396, 308, 0, 0, 361, 300, 301, 679, + 345, 415, 614, 647, 648, 539, 0, 602, 540, 549, + 337, 574, 586, 585, 411, 499, 0, 597, 600, 529, + 678, 0, 594, 608, 682, 607, 675, 421, 0, 444, + 605, 552, 0, 598, 571, 572, 0, 599, 567, 603, + 0, 541, 0, 510, 513, 542, 627, 628, 629, 305, + 512, 631, 632, 633, 634, 635, 636, 637, 630, 483, + 575, 551, 578, 491, 554, 553, 0, 0, 589, 508, + 590, 591, 405, 406, 407, 408, 365, 615, 326, 511, + 433, 0, 576, 0, 0, 0, 0, 0, 0, 0, + 0, 581, 582, 579, 687, 0, 638, 639, 0, 0, + 505, 506, 360, 367, 524, 369, 325, 420, 362, 489, + 377, 0, 517, 583, 518, 641, 644, 642, 643, 412, + 372, 374, 448, 378, 388, 436, 488, 418, 441, 323, + 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 623, 622, 621, 620, 619, 618, 617, 616, + 0, 0, 565, 465, 339, 294, 335, 336, 343, 676, + 672, 470, 677, 0, 302, 545, 386, 432, 359, 610, + 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, + 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, + 266, 267, 268, 269, 270, 271, 272, 613, 263, 264, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 0, 0, 0, 0, 296, 664, + 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, + 0, 289, 290, 291, 292, 293, 0, 0, 495, 496, + 497, 520, 0, 498, 481, 544, 674, 0, 0, 0, + 0, 0, 0, 0, 595, 606, 640, 0, 650, 651, + 653, 655, 654, 657, 455, 456, 663, 0, 659, 660, + 661, 658, 390, 442, 461, 449, 0, 680, 535, 536, + 681, 646, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 0, 587, 537, 451, 401, 0, 604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, + 0, 2780, 0, 0, 0, 321, 235, 532, 652, 534, + 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 0, 0, 0, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 0, + 474, 503, 346, 493, 0, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 519, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 0, 0, 649, 0, 487, + 0, 0, 0, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 504, 0, 440, 419, 683, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 345, 415, 614, 647, 648, 539, 0, 602, 540, + 549, 337, 574, 586, 585, 411, 499, 0, 597, 600, + 529, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 483, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 508, 590, 591, 405, 406, 407, 408, 365, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 0, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 0, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, + 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, + 265, 266, 267, 268, 269, 270, 271, 272, 613, 263, + 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 0, 0, 0, 0, 296, + 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, + 0, 0, 289, 290, 291, 292, 293, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 654, 657, 455, 456, 663, 0, 659, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 417, 0, 0, 550, 584, 573, 656, + 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 352, 0, 0, 385, 588, 569, 580, 570, 555, + 556, 557, 564, 364, 558, 559, 560, 530, 561, 531, + 562, 563, 0, 587, 537, 451, 401, 0, 604, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 321, 235, 532, 652, + 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2735, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 452, 480, 0, 492, 0, 375, 376, 0, 0, + 0, 0, 0, 0, 0, 309, 458, 477, 322, 446, + 490, 327, 454, 469, 317, 416, 443, 0, 0, 311, + 475, 453, 398, 310, 0, 437, 350, 366, 347, 414, + 0, 474, 503, 346, 493, 0, 485, 313, 0, 484, + 413, 471, 476, 399, 392, 0, 312, 473, 397, 391, + 379, 356, 519, 380, 381, 370, 427, 389, 428, 371, + 403, 402, 404, 0, 0, 0, 0, 0, 514, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 645, 0, 0, 649, 0, + 487, 0, 0, 0, 0, 0, 0, 457, 0, 0, + 382, 0, 0, 0, 504, 0, 440, 419, 683, 0, + 0, 438, 387, 472, 429, 478, 459, 486, 434, 430, + 303, 460, 349, 400, 318, 320, 673, 351, 353, 357, + 358, 409, 410, 424, 445, 462, 463, 464, 348, 332, + 439, 333, 368, 334, 304, 340, 338, 341, 447, 342, + 306, 425, 468, 0, 363, 435, 395, 307, 394, 426, + 467, 466, 319, 494, 501, 502, 592, 0, 507, 684, + 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, + 344, 328, 330, 331, 329, 422, 423, 521, 522, 523, + 525, 526, 527, 528, 593, 609, 577, 546, 509, 601, + 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, + 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, + 301, 679, 345, 415, 614, 647, 648, 539, 0, 602, + 540, 549, 337, 574, 586, 585, 411, 499, 0, 597, + 600, 529, 678, 0, 594, 608, 682, 607, 675, 421, + 0, 444, 605, 552, 0, 598, 571, 572, 0, 599, + 567, 603, 0, 541, 0, 510, 513, 542, 627, 628, + 629, 305, 512, 631, 632, 633, 634, 635, 636, 637, + 630, 483, 575, 551, 578, 491, 554, 553, 0, 0, + 589, 508, 590, 591, 405, 406, 407, 408, 365, 615, + 326, 511, 433, 0, 576, 0, 0, 0, 0, 0, + 0, 0, 0, 581, 582, 579, 687, 0, 638, 639, + 0, 0, 505, 506, 360, 367, 524, 369, 325, 420, + 362, 489, 377, 0, 517, 583, 518, 641, 644, 642, + 643, 412, 372, 374, 448, 378, 388, 436, 488, 418, + 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 622, 621, 620, 619, 618, + 617, 616, 0, 0, 565, 465, 339, 294, 335, 336, + 343, 676, 672, 470, 677, 0, 302, 545, 386, 432, + 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, + 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, + 262, 265, 266, 267, 268, 269, 270, 271, 272, 613, + 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, + 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, + 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, + 495, 496, 497, 520, 0, 498, 481, 544, 674, 0, + 0, 0, 0, 0, 0, 0, 595, 606, 640, 0, + 650, 651, 653, 655, 654, 657, 455, 456, 663, 0, + 659, 660, 661, 658, 390, 442, 461, 449, 0, 680, + 535, 536, 681, 646, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 0, 587, 537, 451, 401, 0, 604, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 2733, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 0, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 0, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 504, 0, 440, 419, 683, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 435, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, + 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, + 300, 301, 679, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 0, + 597, 600, 529, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, + 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 0, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, + 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, + 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, + 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 2504, + 680, 535, 536, 681, 646, 417, 0, 0, 550, 584, + 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 352, 0, 0, 385, 588, 569, 580, + 570, 555, 556, 557, 564, 364, 558, 559, 560, 530, + 561, 531, 562, 563, 0, 587, 537, 451, 401, 0, + 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 3330, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 234, 0, 0, 0, 0, 0, 0, 321, 235, + 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 452, 480, 0, 492, 0, 375, 376, + 0, 0, 0, 0, 0, 0, 0, 309, 458, 477, + 322, 446, 490, 327, 454, 469, 317, 416, 443, 0, + 0, 311, 475, 453, 398, 310, 0, 437, 350, 366, + 347, 414, 0, 474, 503, 346, 493, 0, 485, 313, + 0, 484, 413, 471, 476, 399, 392, 0, 312, 473, + 397, 391, 379, 356, 519, 380, 381, 370, 427, 389, + 428, 371, 403, 402, 404, 0, 0, 0, 0, 0, + 514, 515, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 645, 0, 0, + 649, 0, 487, 0, 0, 0, 0, 0, 0, 457, + 0, 0, 382, 0, 0, 0, 504, 0, 440, 419, + 683, 0, 0, 438, 387, 472, 429, 478, 459, 486, + 434, 430, 303, 460, 349, 400, 318, 320, 673, 351, + 353, 357, 358, 409, 410, 424, 445, 462, 463, 464, + 348, 332, 439, 333, 368, 334, 304, 340, 338, 341, + 447, 342, 306, 425, 468, 0, 363, 435, 395, 307, + 394, 426, 467, 466, 319, 494, 501, 502, 592, 0, + 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, + 0, 0, 344, 328, 330, 331, 329, 422, 423, 521, + 522, 523, 525, 526, 527, 528, 593, 609, 577, 546, + 509, 601, 543, 547, 548, 373, 612, 0, 0, 0, + 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, + 361, 300, 301, 679, 345, 415, 614, 647, 648, 539, + 0, 602, 540, 549, 337, 574, 586, 585, 411, 499, + 0, 597, 600, 529, 678, 0, 594, 608, 682, 607, + 675, 421, 0, 444, 605, 552, 0, 598, 571, 572, + 0, 599, 567, 603, 0, 541, 0, 510, 513, 542, + 627, 628, 629, 305, 512, 631, 632, 633, 634, 635, + 636, 637, 630, 483, 575, 551, 578, 491, 554, 553, + 0, 0, 589, 508, 590, 591, 405, 406, 407, 408, + 365, 615, 326, 511, 433, 0, 576, 0, 0, 0, + 0, 0, 0, 0, 0, 581, 582, 579, 687, 0, + 638, 639, 0, 0, 505, 506, 360, 367, 524, 369, + 325, 420, 362, 489, 377, 0, 517, 583, 518, 641, + 644, 642, 643, 412, 372, 374, 448, 378, 388, 436, + 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 623, 622, 621, 620, + 619, 618, 617, 616, 0, 0, 565, 465, 339, 294, + 335, 336, 343, 676, 672, 470, 677, 0, 302, 545, + 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, + 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, + 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, + 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, + 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, + 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, + 0, 0, 495, 496, 497, 520, 0, 498, 481, 544, + 674, 0, 0, 0, 0, 0, 0, 0, 595, 606, + 640, 0, 650, 651, 653, 655, 654, 657, 455, 456, + 663, 0, 659, 660, 661, 658, 390, 442, 461, 449, + 0, 680, 535, 536, 681, 646, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 0, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 234, 0, 0, 0, 2013, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 1998, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 477, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 0, 487, 0, 0, 0, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, + 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, + 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, + 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 417, 0, 0, + 550, 584, 573, 656, 538, 0, 2151, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 0, 0, 385, 588, + 569, 580, 570, 555, 556, 557, 564, 364, 558, 559, + 560, 530, 561, 531, 562, 563, 0, 587, 537, 451, + 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, + 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 1600, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 452, 480, 0, 492, 0, + 375, 376, 0, 0, 0, 0, 0, 0, 0, 309, + 458, 477, 322, 446, 490, 327, 454, 469, 317, 416, + 443, 0, 0, 311, 475, 453, 398, 310, 0, 437, + 350, 366, 347, 414, 0, 474, 503, 346, 493, 0, + 485, 313, 0, 484, 413, 471, 476, 399, 392, 0, + 312, 473, 397, 391, 379, 356, 519, 380, 381, 370, + 427, 389, 428, 371, 403, 402, 404, 0, 0, 0, + 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 645, + 0, 0, 649, 0, 487, 0, 0, 0, 0, 0, + 0, 457, 0, 0, 382, 0, 0, 0, 504, 0, + 440, 419, 683, 0, 0, 438, 387, 472, 429, 478, + 459, 486, 434, 430, 303, 460, 349, 400, 318, 320, + 673, 351, 353, 357, 358, 409, 410, 424, 445, 462, + 463, 464, 348, 332, 439, 333, 368, 334, 304, 340, + 338, 341, 447, 342, 306, 425, 468, 0, 363, 435, + 395, 307, 394, 426, 467, 466, 319, 494, 501, 502, + 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, + 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, + 423, 521, 522, 523, 525, 526, 527, 528, 593, 609, + 577, 546, 509, 601, 543, 547, 548, 373, 612, 0, + 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, + 0, 0, 361, 300, 301, 679, 345, 415, 614, 647, + 648, 539, 0, 602, 540, 549, 337, 574, 586, 585, + 411, 499, 0, 597, 600, 529, 678, 0, 594, 608, + 682, 607, 675, 421, 0, 444, 605, 552, 0, 598, + 571, 572, 0, 599, 567, 603, 0, 541, 0, 510, + 513, 542, 627, 628, 629, 305, 512, 631, 632, 633, + 634, 635, 636, 637, 630, 483, 575, 551, 578, 491, + 554, 553, 0, 0, 589, 508, 590, 591, 405, 406, + 407, 408, 365, 615, 326, 511, 433, 0, 576, 0, + 0, 0, 0, 0, 0, 0, 0, 581, 582, 579, + 687, 0, 638, 639, 0, 0, 505, 506, 360, 367, + 524, 369, 325, 420, 362, 489, 377, 0, 517, 583, + 518, 641, 644, 642, 643, 412, 372, 374, 448, 378, + 388, 436, 488, 418, 441, 323, 479, 450, 393, 568, + 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 623, 622, + 621, 620, 619, 618, 617, 616, 0, 0, 565, 465, + 339, 294, 335, 336, 343, 676, 672, 470, 677, 0, + 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, + 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, + 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, + 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 0, 0, 0, 0, 296, 664, 665, 666, 667, 668, + 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, + 292, 293, 0, 0, 495, 496, 497, 520, 0, 498, + 481, 544, 674, 0, 0, 0, 0, 0, 0, 0, + 595, 606, 640, 0, 650, 651, 653, 655, 654, 657, + 455, 456, 663, 0, 659, 660, 661, 658, 390, 442, + 461, 449, 0, 680, 535, 536, 681, 646, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 0, 587, 537, + 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 0, 0, 0, 0, 234, 0, 0, 1622, 0, 0, + 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 1598, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 469, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 0, 474, 503, 346, 493, + 0, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 519, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 0, 0, 649, 0, 487, 0, 0, 0, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 504, + 0, 440, 419, 683, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 2055, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 345, 415, 614, + 647, 648, 539, 0, 602, 540, 549, 337, 574, 586, + 585, 411, 499, 0, 597, 600, 529, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 483, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 508, 590, 591, 405, + 406, 407, 408, 365, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 0, 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, + 269, 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, + 286, 0, 0, 0, 0, 296, 664, 665, 666, 667, + 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, + 291, 292, 293, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 654, + 657, 455, 456, 663, 0, 659, 660, 661, 658, 390, + 442, 461, 449, 0, 680, 535, 536, 681, 646, 417, + 0, 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 1474, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 477, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 0, 485, 313, 0, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 1651, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 434, 430, 303, 460, 349, 400, + 318, 320, 673, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 637, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 508, 590, 591, + 405, 406, 407, 408, 365, 615, 326, 511, 433, 0, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 412, 372, 374, + 448, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 390, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 699, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 0, + 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, + 0, 0, 0, 321, 235, 532, 652, 534, 533, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 0, 474, 503, + 346, 493, 0, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 519, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 0, 0, 649, 0, 487, 0, 0, + 0, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 504, 0, 440, 419, 683, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 434, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 345, + 415, 614, 647, 648, 539, 0, 602, 540, 549, 337, + 574, 586, 585, 411, 499, 0, 597, 600, 529, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 637, 630, 483, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 508, 590, + 591, 405, 406, 407, 408, 365, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 0, 302, 545, 386, 432, 359, 610, 611, + 0, 662, 248, 249, 250, 251, 252, 253, 254, 255, + 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, + 267, 268, 269, 270, 271, 272, 613, 263, 264, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 0, 0, 0, 0, 296, 664, 665, + 666, 667, 668, 0, 0, 297, 298, 299, 0, 0, + 289, 290, 291, 292, 293, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 0, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 654, 657, 455, 456, 663, 0, 659, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 417, 0, 0, 550, 584, 573, 656, 538, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 0, 0, 385, 588, 569, 580, 570, 555, 556, 557, + 564, 364, 558, 559, 560, 530, 561, 531, 562, 563, + 0, 587, 537, 451, 401, 0, 604, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, + 0, 0, 0, 0, 321, 235, 532, 652, 534, 533, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 324, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 452, + 480, 0, 492, 0, 375, 376, 0, 0, 0, 0, + 0, 0, 0, 309, 458, 477, 322, 446, 490, 327, + 454, 469, 317, 416, 443, 0, 0, 311, 475, 453, + 398, 310, 0, 437, 350, 366, 347, 414, 0, 474, + 503, 346, 493, 0, 485, 313, 0, 484, 413, 471, + 476, 399, 392, 0, 312, 473, 397, 391, 379, 356, + 519, 380, 381, 370, 427, 389, 428, 371, 403, 402, + 404, 0, 0, 0, 0, 0, 514, 515, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 645, 0, 704, 649, 0, 487, 0, + 0, 0, 0, 0, 0, 457, 0, 0, 382, 0, + 0, 0, 504, 0, 440, 419, 683, 0, 0, 438, + 387, 472, 429, 478, 459, 486, 434, 430, 303, 460, + 349, 400, 318, 320, 673, 351, 353, 357, 358, 409, + 410, 424, 445, 462, 463, 464, 348, 332, 439, 333, + 368, 334, 304, 340, 338, 341, 447, 342, 306, 425, + 468, 0, 363, 435, 395, 307, 394, 426, 467, 466, + 319, 494, 501, 502, 592, 0, 507, 684, 685, 686, + 516, 0, 431, 315, 314, 0, 0, 0, 344, 328, + 330, 331, 329, 422, 423, 521, 522, 523, 525, 526, + 527, 528, 593, 609, 577, 546, 509, 601, 543, 547, + 548, 373, 612, 0, 0, 0, 500, 383, 384, 0, + 355, 354, 396, 308, 0, 0, 361, 300, 301, 679, + 345, 415, 614, 647, 648, 539, 0, 602, 540, 549, + 337, 574, 586, 585, 411, 499, 0, 597, 600, 529, + 678, 0, 594, 608, 682, 607, 675, 421, 0, 444, + 605, 552, 0, 598, 571, 572, 0, 599, 567, 603, + 0, 541, 0, 510, 513, 542, 627, 628, 629, 305, + 512, 631, 632, 633, 634, 635, 636, 637, 630, 483, + 575, 551, 578, 491, 554, 553, 0, 0, 589, 508, + 590, 591, 405, 406, 407, 408, 365, 615, 326, 511, + 433, 0, 576, 0, 0, 0, 0, 0, 0, 0, + 0, 581, 582, 579, 687, 0, 638, 639, 0, 0, + 505, 506, 360, 367, 524, 369, 325, 420, 362, 489, + 377, 0, 517, 583, 518, 641, 644, 642, 643, 412, + 372, 374, 448, 378, 388, 436, 488, 418, 441, 323, + 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 287, 288, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 623, 622, 621, 620, 619, 618, 617, 616, + 0, 0, 565, 465, 339, 294, 335, 336, 343, 676, + 672, 470, 677, 0, 302, 545, 386, 432, 359, 610, + 611, 0, 662, 248, 249, 250, 251, 252, 253, 254, + 255, 295, 256, 257, 258, 259, 260, 261, 262, 265, + 266, 267, 268, 269, 270, 271, 272, 613, 263, 264, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 0, 0, 0, 0, 296, 664, + 665, 666, 667, 668, 0, 0, 297, 298, 299, 0, + 0, 289, 290, 291, 292, 293, 0, 0, 495, 496, + 497, 520, 0, 498, 481, 544, 674, 0, 0, 0, + 0, 0, 0, 0, 595, 606, 640, 0, 650, 651, + 653, 655, 654, 657, 455, 456, 663, 0, 659, 660, + 661, 658, 390, 442, 461, 449, 0, 680, 535, 536, + 681, 646, 417, 0, 0, 550, 584, 573, 656, 538, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 352, 0, 0, 385, 588, 569, 580, 570, 555, 556, + 557, 564, 364, 558, 559, 560, 530, 561, 531, 562, + 563, 0, 587, 537, 451, 401, 0, 604, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, + 0, 0, 0, 0, 0, 321, 235, 532, 652, 534, + 533, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 452, 480, 0, 492, 0, 375, 376, 0, 0, 0, + 0, 0, 0, 0, 309, 458, 477, 322, 446, 490, + 327, 454, 469, 317, 416, 443, 0, 0, 311, 475, + 453, 398, 310, 0, 437, 350, 366, 347, 414, 0, + 474, 503, 346, 493, 0, 485, 313, 0, 484, 413, + 471, 476, 399, 392, 0, 312, 473, 397, 391, 379, + 356, 519, 380, 381, 370, 427, 389, 428, 371, 403, + 402, 404, 0, 0, 0, 0, 0, 514, 515, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 0, 0, 649, 0, 487, + 0, 0, 0, 0, 0, 0, 457, 0, 0, 382, + 0, 0, 0, 504, 0, 440, 419, 683, 0, 0, + 438, 387, 472, 429, 478, 459, 486, 434, 430, 303, + 460, 349, 400, 318, 320, 673, 351, 353, 357, 358, + 409, 410, 424, 445, 462, 463, 464, 348, 332, 439, + 333, 368, 334, 304, 340, 338, 341, 447, 342, 306, + 425, 468, 0, 363, 435, 395, 307, 394, 426, 467, + 466, 319, 494, 501, 502, 592, 0, 507, 684, 685, + 686, 516, 0, 431, 315, 314, 0, 0, 0, 344, + 328, 330, 331, 329, 422, 423, 521, 522, 523, 525, + 526, 527, 528, 593, 609, 577, 546, 509, 601, 543, + 547, 548, 373, 612, 0, 0, 0, 500, 383, 384, + 0, 355, 354, 396, 308, 0, 0, 361, 300, 301, + 679, 345, 415, 614, 647, 648, 539, 0, 602, 540, + 549, 337, 574, 586, 585, 411, 499, 0, 597, 600, + 529, 678, 0, 594, 608, 682, 607, 675, 421, 0, + 444, 605, 552, 0, 598, 571, 572, 0, 599, 567, + 603, 0, 541, 0, 510, 513, 542, 627, 628, 629, + 305, 512, 631, 632, 633, 634, 635, 636, 637, 630, + 483, 575, 551, 578, 491, 554, 553, 0, 0, 589, + 508, 590, 591, 405, 406, 407, 408, 365, 615, 326, + 511, 433, 0, 576, 0, 0, 0, 0, 0, 0, + 0, 0, 581, 582, 579, 687, 0, 638, 639, 0, + 0, 505, 506, 360, 367, 524, 369, 325, 420, 362, + 489, 377, 0, 517, 583, 518, 641, 644, 642, 643, + 412, 372, 374, 448, 378, 388, 436, 488, 418, 441, + 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 287, 288, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 623, 622, 621, 620, 619, 618, 617, + 616, 1016, 0, 565, 465, 339, 294, 335, 336, 343, + 676, 672, 470, 677, 0, 302, 545, 386, 432, 359, + 610, 611, 0, 662, 248, 249, 250, 251, 252, 253, + 254, 255, 295, 256, 257, 258, 259, 260, 261, 262, + 265, 266, 267, 268, 269, 270, 271, 272, 613, 263, + 264, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 0, 0, 0, 0, 296, + 664, 665, 666, 667, 668, 0, 0, 297, 298, 299, + 0, 0, 289, 290, 291, 292, 293, 0, 0, 495, + 496, 497, 520, 0, 498, 481, 544, 674, 0, 0, + 0, 0, 0, 0, 0, 595, 606, 640, 0, 650, + 651, 653, 655, 654, 657, 455, 456, 663, 0, 659, + 660, 661, 658, 390, 442, 461, 449, 0, 680, 535, + 536, 681, 646, 417, 0, 0, 550, 584, 573, 656, + 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 352, 0, 0, 385, 588, 569, 580, 570, 555, + 556, 557, 564, 364, 558, 559, 560, 530, 561, 531, + 562, 563, 0, 587, 537, 451, 401, 0, 604, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 321, 235, 532, 652, + 534, 533, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 452, 480, 0, 492, 0, 375, 376, 0, 0, + 0, 0, 0, 0, 0, 309, 458, 477, 322, 446, + 490, 327, 454, 469, 317, 416, 443, 0, 0, 311, + 475, 453, 398, 310, 0, 437, 350, 366, 347, 414, + 0, 474, 503, 346, 493, 0, 485, 313, 0, 484, + 413, 471, 476, 399, 392, 0, 312, 473, 397, 391, + 379, 356, 519, 380, 381, 370, 427, 389, 428, 371, + 403, 402, 404, 0, 0, 0, 0, 0, 514, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 645, 0, 0, 649, 0, + 487, 0, 0, 0, 0, 0, 0, 457, 0, 0, + 382, 0, 0, 0, 504, 0, 440, 419, 683, 0, + 0, 438, 387, 472, 429, 478, 459, 486, 434, 430, + 303, 460, 349, 400, 318, 320, 673, 351, 353, 357, + 358, 409, 410, 424, 445, 462, 463, 464, 348, 332, + 439, 333, 368, 334, 304, 340, 338, 341, 447, 342, + 306, 425, 468, 0, 363, 435, 395, 307, 394, 426, + 467, 466, 319, 494, 501, 502, 592, 0, 507, 684, + 685, 686, 516, 0, 431, 315, 314, 0, 0, 0, + 344, 328, 330, 331, 329, 422, 423, 521, 522, 523, + 525, 526, 527, 528, 593, 609, 577, 546, 509, 601, + 543, 547, 548, 373, 612, 0, 0, 0, 500, 383, + 384, 0, 355, 354, 396, 308, 0, 0, 361, 300, + 301, 679, 345, 415, 614, 647, 648, 539, 0, 602, + 540, 549, 337, 574, 586, 585, 411, 499, 0, 597, + 600, 529, 678, 0, 594, 608, 682, 607, 675, 421, + 0, 444, 605, 552, 0, 598, 571, 572, 0, 599, + 567, 603, 0, 541, 0, 510, 513, 542, 627, 628, + 629, 305, 512, 631, 632, 633, 634, 635, 636, 637, + 630, 483, 575, 551, 578, 491, 554, 553, 0, 0, + 589, 508, 590, 591, 405, 406, 407, 408, 365, 615, + 326, 511, 433, 0, 576, 0, 0, 0, 0, 0, + 0, 0, 0, 581, 582, 579, 687, 0, 638, 639, + 0, 0, 505, 506, 360, 367, 524, 369, 325, 420, + 362, 489, 377, 0, 517, 583, 518, 641, 644, 642, + 643, 412, 372, 374, 448, 378, 388, 436, 488, 418, + 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 287, 288, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 623, 622, 621, 620, 619, 618, + 617, 616, 0, 0, 565, 465, 339, 294, 335, 336, + 343, 676, 672, 470, 677, 0, 302, 545, 386, 432, + 359, 610, 611, 0, 662, 248, 249, 250, 251, 252, + 253, 254, 255, 295, 256, 257, 258, 259, 260, 261, + 262, 265, 266, 267, 268, 269, 270, 271, 272, 613, + 263, 264, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 0, 0, 0, 0, + 296, 664, 665, 666, 667, 668, 0, 0, 297, 298, + 299, 0, 0, 289, 290, 291, 292, 293, 0, 0, + 495, 496, 497, 520, 0, 498, 481, 544, 674, 0, + 0, 0, 0, 0, 0, 0, 595, 606, 640, 0, + 650, 651, 653, 655, 654, 657, 455, 456, 663, 0, + 659, 660, 661, 658, 390, 442, 461, 449, 0, 680, + 535, 536, 681, 646, 417, 0, 0, 550, 584, 573, + 656, 538, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 352, 0, 0, 385, 588, 569, 580, 570, + 555, 556, 557, 564, 364, 558, 559, 560, 530, 561, + 531, 562, 563, 0, 587, 537, 451, 401, 0, 604, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 0, 0, 0, 0, 321, 235, 532, + 652, 534, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 452, 480, 0, 492, 0, 375, 376, 0, + 0, 0, 0, 0, 0, 0, 309, 458, 477, 322, + 446, 490, 327, 454, 469, 317, 416, 443, 0, 0, + 311, 475, 453, 398, 310, 0, 437, 350, 366, 347, + 414, 0, 474, 503, 346, 493, 0, 485, 313, 0, + 484, 413, 471, 476, 399, 392, 0, 312, 473, 397, + 391, 379, 356, 519, 380, 381, 370, 427, 389, 428, + 371, 403, 402, 404, 0, 0, 0, 0, 0, 514, + 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 645, 0, 0, 649, + 0, 487, 0, 0, 0, 0, 0, 0, 457, 0, + 0, 382, 0, 0, 0, 504, 0, 440, 419, 683, + 0, 0, 438, 387, 472, 429, 478, 459, 486, 434, + 430, 303, 460, 349, 400, 318, 320, 673, 351, 353, + 357, 358, 409, 410, 424, 445, 462, 463, 464, 348, + 332, 439, 333, 368, 334, 304, 340, 338, 341, 447, + 342, 306, 425, 468, 0, 363, 3331, 395, 307, 394, + 426, 467, 466, 319, 494, 501, 502, 592, 0, 507, + 684, 685, 686, 516, 0, 431, 315, 314, 0, 0, + 0, 344, 328, 330, 331, 329, 422, 423, 521, 522, + 523, 525, 526, 527, 528, 593, 609, 577, 546, 509, + 601, 543, 547, 548, 373, 612, 0, 0, 0, 500, + 383, 384, 0, 355, 354, 396, 308, 0, 0, 361, + 300, 301, 679, 345, 415, 614, 647, 648, 539, 0, + 602, 540, 549, 337, 574, 586, 585, 411, 499, 0, + 597, 600, 529, 678, 0, 594, 608, 682, 607, 675, + 421, 0, 444, 605, 552, 0, 598, 571, 572, 0, + 599, 567, 603, 0, 541, 0, 510, 513, 542, 627, + 628, 629, 305, 512, 631, 632, 633, 634, 635, 636, + 637, 630, 483, 575, 551, 578, 491, 554, 553, 0, + 0, 589, 508, 590, 591, 405, 406, 407, 408, 365, + 615, 326, 511, 433, 0, 576, 0, 0, 0, 0, + 0, 0, 0, 0, 581, 582, 579, 687, 0, 638, + 639, 0, 0, 505, 506, 360, 367, 524, 369, 325, + 420, 362, 489, 377, 0, 517, 583, 518, 641, 644, + 642, 643, 412, 372, 374, 448, 378, 388, 436, 488, + 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, + 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 623, 622, 621, 620, 619, + 618, 617, 616, 0, 0, 565, 465, 339, 294, 335, + 336, 343, 676, 672, 470, 677, 0, 302, 545, 386, + 432, 359, 610, 611, 0, 662, 248, 249, 250, 251, + 252, 253, 254, 255, 295, 256, 257, 258, 259, 260, + 261, 262, 265, 266, 267, 268, 269, 270, 271, 272, + 613, 263, 264, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 0, 0, 0, + 0, 296, 664, 665, 666, 667, 668, 0, 0, 297, + 298, 299, 0, 0, 289, 290, 291, 292, 293, 0, + 0, 495, 496, 497, 520, 0, 498, 481, 544, 674, + 0, 0, 0, 0, 0, 0, 0, 595, 606, 640, + 0, 650, 651, 653, 655, 654, 657, 455, 456, 663, + 0, 659, 660, 661, 658, 390, 442, 461, 449, 0, + 680, 535, 536, 681, 646, 417, 0, 0, 550, 584, + 573, 656, 538, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 352, 0, 0, 385, 588, 569, 580, + 570, 555, 556, 557, 564, 364, 558, 559, 560, 530, + 561, 531, 562, 563, 0, 587, 537, 451, 401, 0, + 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 433, 429, 303, 459, 349, 400, - 318, 320, 776, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 636, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 0, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 0, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 0, 0, 0, 0, 0, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 0, 679, 534, 535, 680, 645, 417, - 0, 0, 549, 583, 572, 655, 537, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, - 385, 587, 568, 579, 569, 554, 555, 556, 563, 364, - 557, 558, 559, 529, 560, 530, 561, 562, 0, 586, - 536, 450, 401, 0, 603, 0, 0, 0, 0, 0, + 0, 234, 0, 0, 0, 0, 0, 0, 321, 235, + 532, 652, 534, 533, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 452, 480, 0, 492, 0, 375, 376, + 0, 0, 0, 0, 0, 0, 0, 309, 458, 477, + 322, 446, 490, 327, 454, 1999, 317, 416, 443, 0, + 0, 311, 475, 453, 398, 310, 0, 437, 350, 366, + 347, 414, 0, 474, 503, 346, 493, 0, 485, 313, + 0, 484, 413, 471, 476, 399, 392, 0, 312, 473, + 397, 391, 379, 356, 519, 380, 381, 370, 427, 389, + 428, 371, 403, 402, 404, 0, 0, 0, 0, 0, + 514, 515, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 645, 0, 0, + 649, 0, 487, 0, 0, 0, 0, 0, 0, 457, + 0, 0, 382, 0, 0, 0, 504, 0, 440, 419, + 683, 0, 0, 438, 387, 472, 429, 478, 459, 486, + 434, 430, 303, 460, 349, 400, 318, 320, 673, 351, + 353, 357, 358, 409, 410, 424, 445, 462, 463, 464, + 348, 332, 439, 333, 368, 334, 304, 340, 338, 341, + 447, 342, 306, 425, 468, 0, 363, 435, 395, 307, + 394, 426, 467, 466, 319, 494, 501, 502, 592, 0, + 507, 684, 685, 686, 516, 0, 431, 315, 314, 0, + 0, 0, 344, 328, 330, 331, 329, 422, 423, 521, + 522, 523, 525, 526, 527, 528, 593, 609, 577, 546, + 509, 601, 543, 547, 548, 373, 612, 0, 0, 0, + 500, 383, 384, 0, 355, 354, 396, 308, 0, 0, + 361, 300, 301, 679, 345, 415, 614, 647, 648, 539, + 0, 602, 540, 549, 337, 574, 586, 585, 411, 499, + 0, 597, 600, 529, 678, 0, 594, 608, 682, 607, + 675, 421, 0, 444, 605, 552, 0, 598, 571, 572, + 0, 599, 567, 603, 0, 541, 0, 510, 513, 542, + 627, 628, 629, 305, 512, 631, 632, 633, 634, 635, + 636, 637, 630, 483, 575, 551, 578, 491, 554, 553, + 0, 0, 589, 508, 590, 591, 405, 406, 407, 408, + 365, 615, 326, 511, 433, 0, 576, 0, 0, 0, + 0, 0, 0, 0, 0, 581, 582, 579, 687, 0, + 638, 639, 0, 0, 505, 506, 360, 367, 524, 369, + 325, 420, 362, 489, 377, 0, 517, 583, 518, 641, + 644, 642, 643, 412, 372, 374, 448, 378, 388, 436, + 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, - 0, 0, 321, 235, 531, 651, 533, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, + 287, 288, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 623, 622, 621, 620, + 619, 618, 617, 616, 0, 0, 565, 465, 339, 294, + 335, 336, 343, 676, 672, 470, 677, 0, 302, 545, + 386, 432, 359, 610, 611, 0, 662, 248, 249, 250, + 251, 252, 253, 254, 255, 295, 256, 257, 258, 259, + 260, 261, 262, 265, 266, 267, 268, 269, 270, 271, + 272, 613, 263, 264, 273, 274, 275, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, + 0, 0, 296, 664, 665, 666, 667, 668, 0, 0, + 297, 298, 299, 0, 0, 289, 290, 291, 292, 293, + 0, 0, 495, 496, 497, 520, 0, 498, 481, 544, + 674, 0, 0, 0, 0, 0, 0, 0, 595, 606, + 640, 0, 650, 651, 653, 655, 654, 657, 455, 456, + 663, 0, 659, 660, 661, 658, 390, 442, 461, 449, + 0, 680, 535, 536, 681, 646, 417, 0, 0, 550, + 584, 573, 656, 538, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 352, 0, 0, 385, 588, 569, + 580, 570, 555, 556, 557, 564, 364, 558, 559, 560, + 530, 561, 531, 562, 563, 0, 587, 537, 451, 401, + 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 234, 0, 0, 0, 0, 0, 0, 321, + 235, 532, 652, 534, 533, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 451, 479, 0, - 491, 0, 375, 376, 0, 0, 0, 0, 0, 0, - 0, 309, 457, 476, 322, 445, 489, 327, 453, 468, - 317, 416, 442, 0, 0, 311, 474, 452, 398, 310, - 0, 436, 350, 366, 347, 414, 0, 473, 502, 346, - 492, 0, 484, 313, 0, 483, 413, 470, 475, 399, - 392, 0, 312, 472, 397, 391, 379, 356, 518, 380, - 381, 370, 426, 389, 427, 371, 403, 402, 404, 0, - 0, 0, 0, 0, 513, 514, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 644, 0, 0, 648, 0, 486, 0, 0, 0, - 0, 0, 0, 456, 0, 0, 382, 0, 0, 0, - 503, 0, 439, 419, 682, 0, 0, 437, 387, 471, - 428, 477, 458, 485, 728, 429, 303, 459, 349, 400, - 318, 320, 672, 351, 353, 357, 358, 409, 410, 423, - 444, 461, 462, 463, 348, 332, 438, 333, 368, 334, - 304, 340, 338, 341, 446, 342, 306, 424, 467, 0, - 363, 434, 395, 307, 394, 425, 466, 465, 319, 493, - 500, 501, 591, 0, 506, 683, 684, 685, 515, 0, - 430, 315, 314, 0, 0, 0, 344, 328, 330, 331, - 329, 422, 520, 521, 522, 524, 525, 526, 527, 592, - 608, 576, 545, 508, 600, 542, 546, 547, 373, 611, - 0, 0, 0, 499, 383, 384, 0, 355, 354, 396, - 308, 0, 0, 361, 300, 301, 678, 345, 415, 613, - 646, 647, 538, 0, 601, 539, 548, 337, 573, 585, - 584, 411, 498, 0, 596, 599, 528, 677, 0, 593, - 607, 681, 606, 674, 421, 0, 443, 604, 551, 0, - 597, 570, 571, 0, 598, 566, 602, 0, 540, 0, - 509, 512, 541, 626, 627, 628, 305, 511, 630, 631, - 632, 633, 634, 635, 729, 629, 482, 574, 550, 577, - 490, 553, 552, 0, 0, 588, 507, 589, 590, 405, - 406, 407, 408, 365, 614, 326, 510, 432, 0, 575, - 0, 0, 0, 0, 0, 0, 0, 0, 580, 581, - 578, 686, 0, 637, 638, 0, 2136, 504, 505, 360, - 367, 523, 369, 325, 420, 362, 488, 377, 0, 516, - 582, 517, 640, 643, 641, 642, 412, 372, 374, 447, - 378, 388, 435, 487, 418, 440, 323, 478, 449, 393, - 567, 595, 0, 0, 2138, 0, 0, 0, 0, 0, - 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, - 621, 620, 619, 618, 617, 616, 615, 0, 0, 564, - 464, 339, 294, 335, 336, 343, 675, 671, 469, 676, - 0, 302, 544, 386, 431, 359, 609, 610, 2113, 661, - 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, - 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, - 269, 270, 271, 272, 612, 263, 264, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 0, 0, 296, 663, 664, 665, 666, - 667, 0, 0, 297, 298, 299, 0, 0, 289, 290, - 291, 292, 293, 0, 0, 494, 495, 496, 519, 0, - 497, 480, 543, 673, 4014, 0, 0, 0, 2129, 0, - 0, 594, 605, 639, 0, 649, 650, 652, 654, 653, - 656, 454, 455, 662, 0, 658, 659, 660, 657, 390, - 441, 460, 448, 2136, 679, 534, 535, 680, 645, 0, - 0, 174, 212, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3847, 0, 0, 0, 0, - 0, 2138, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2136, 0, 0, 0, 0, 0, 0, 0, - 0, 2117, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2123, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 208, 0, 0, 0, 0, - 2138, 0, 2111, 2145, 0, 2113, 2112, 2114, 2116, 0, - 2118, 2119, 2120, 2124, 2125, 2126, 2128, 2131, 2132, 2133, - 0, 0, 0, 0, 0, 0, 0, 2121, 2130, 2122, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4043, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2113, 0, 0, 0, 0, 0, - 0, 0, 2136, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2137, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2129, 0, 0, 0, 0, + 0, 0, 0, 0, 452, 480, 0, 492, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 309, 458, + 1601, 322, 446, 490, 327, 454, 469, 317, 416, 443, + 0, 0, 311, 475, 453, 398, 310, 0, 437, 350, + 366, 347, 414, 0, 474, 503, 346, 493, 0, 485, + 313, 0, 484, 413, 471, 476, 399, 392, 0, 312, + 473, 397, 391, 379, 356, 519, 380, 381, 370, 427, + 389, 428, 371, 403, 402, 404, 0, 0, 0, 0, + 0, 514, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 645, 0, + 0, 649, 0, 487, 0, 0, 0, 0, 0, 0, + 457, 0, 0, 382, 0, 0, 0, 504, 0, 440, + 419, 683, 0, 0, 438, 387, 472, 429, 478, 459, + 486, 434, 430, 303, 460, 349, 400, 318, 320, 673, + 351, 353, 357, 358, 409, 410, 424, 445, 462, 463, + 464, 348, 332, 439, 333, 368, 334, 304, 340, 338, + 341, 447, 342, 306, 425, 468, 0, 363, 435, 395, + 307, 394, 426, 467, 466, 319, 494, 501, 502, 592, + 0, 507, 684, 685, 686, 516, 0, 431, 315, 314, + 0, 0, 0, 344, 328, 330, 331, 329, 422, 423, + 521, 522, 523, 525, 526, 527, 528, 593, 609, 577, + 546, 509, 601, 543, 547, 548, 373, 612, 0, 0, + 0, 500, 383, 384, 0, 355, 354, 396, 308, 0, + 0, 361, 300, 301, 679, 345, 415, 614, 647, 648, + 539, 0, 602, 540, 549, 337, 574, 586, 585, 411, + 499, 0, 597, 600, 529, 678, 0, 594, 608, 682, + 607, 675, 421, 0, 444, 605, 552, 0, 598, 571, + 572, 0, 599, 567, 603, 0, 541, 0, 510, 513, + 542, 627, 628, 629, 305, 512, 631, 632, 633, 634, + 635, 636, 637, 630, 483, 575, 551, 578, 491, 554, + 553, 0, 0, 589, 508, 590, 591, 405, 406, 407, + 408, 365, 615, 326, 511, 433, 0, 576, 0, 0, + 0, 0, 0, 0, 0, 0, 581, 582, 579, 687, + 0, 638, 639, 0, 0, 505, 506, 360, 367, 524, + 369, 325, 420, 362, 489, 377, 0, 517, 583, 518, + 641, 644, 642, 643, 412, 372, 374, 448, 378, 388, + 436, 488, 418, 441, 323, 479, 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2138, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 287, 288, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 623, 622, 621, + 620, 619, 618, 617, 616, 0, 0, 565, 465, 339, + 294, 335, 336, 343, 676, 672, 470, 677, 0, 302, + 545, 386, 432, 359, 610, 611, 0, 662, 248, 249, + 250, 251, 252, 253, 254, 255, 295, 256, 257, 258, + 259, 260, 261, 262, 265, 266, 267, 268, 269, 270, + 271, 272, 613, 263, 264, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, + 0, 0, 0, 296, 664, 665, 666, 667, 668, 0, + 0, 297, 298, 299, 0, 0, 289, 290, 291, 292, + 293, 0, 0, 495, 496, 497, 520, 0, 498, 481, + 544, 674, 0, 0, 0, 0, 0, 0, 0, 595, + 606, 640, 0, 650, 651, 653, 655, 654, 657, 455, + 456, 663, 0, 659, 660, 661, 658, 390, 442, 461, + 449, 0, 680, 535, 536, 681, 646, 417, 0, 0, + 550, 584, 573, 656, 538, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 0, 0, 385, 588, + 569, 580, 570, 555, 556, 557, 564, 364, 558, 559, + 560, 530, 561, 531, 562, 563, 0, 587, 537, 451, + 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, + 321, 235, 532, 652, 534, 533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2134, 0, 0, 0, - 0, 0, 0, 0, 2129, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2110, 0, 0, 0, 2109, 0, - 0, 0, 0, 0, 2113, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2117, 0, - 0, 0, 2127, 0, 0, 0, 0, 0, 0, 2123, - 0, 2115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2111, - 2145, 0, 0, 2112, 2114, 2116, 0, 2118, 2119, 2120, - 2124, 2125, 2126, 2128, 2131, 2132, 2133, 2117, 0, 0, - 0, 0, 0, 0, 2121, 2130, 2122, 0, 2123, 0, - 0, 0, 0, 0, 2129, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2111, 2145, - 0, 0, 2112, 2114, 2116, 0, 2118, 2119, 2120, 2124, - 2125, 2126, 2128, 2131, 2132, 2133, 0, 0, 0, 0, - 0, 2137, 0, 2121, 2130, 2122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2117, 0, 0, - 2137, 0, 0, 2134, 0, 0, 0, 0, 2123, 0, + 0, 0, 0, 0, 0, 452, 480, 0, 492, 0, + 375, 376, 0, 0, 0, 0, 0, 0, 0, 309, + 458, 1599, 322, 446, 490, 327, 454, 469, 317, 416, + 443, 0, 0, 311, 475, 453, 398, 310, 0, 437, + 350, 366, 347, 414, 0, 474, 503, 346, 493, 0, + 485, 313, 0, 484, 413, 471, 476, 399, 392, 0, + 312, 473, 397, 391, 379, 356, 519, 380, 381, 370, + 427, 389, 428, 371, 403, 402, 404, 0, 0, 0, + 0, 0, 514, 515, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 645, + 0, 0, 649, 0, 487, 0, 0, 0, 0, 0, + 0, 457, 0, 0, 382, 0, 0, 0, 504, 0, + 440, 419, 683, 0, 0, 438, 387, 472, 429, 478, + 459, 486, 434, 430, 303, 460, 349, 400, 318, 320, + 673, 351, 353, 357, 358, 409, 410, 424, 445, 462, + 463, 464, 348, 332, 439, 333, 368, 334, 304, 340, + 338, 341, 447, 342, 306, 425, 468, 0, 363, 435, + 395, 307, 394, 426, 467, 466, 319, 494, 501, 502, + 592, 0, 507, 684, 685, 686, 516, 0, 431, 315, + 314, 0, 0, 0, 344, 328, 330, 331, 329, 422, + 423, 521, 522, 523, 525, 526, 527, 528, 593, 609, + 577, 546, 509, 601, 543, 547, 548, 373, 612, 0, + 0, 0, 500, 383, 384, 0, 355, 354, 396, 308, + 0, 0, 361, 300, 301, 679, 345, 415, 614, 647, + 648, 539, 0, 602, 540, 549, 337, 574, 586, 585, + 411, 499, 0, 597, 600, 529, 678, 0, 594, 608, + 682, 607, 675, 421, 0, 444, 605, 552, 0, 598, + 571, 572, 0, 599, 567, 603, 0, 541, 0, 510, + 513, 542, 627, 628, 629, 305, 512, 631, 632, 633, + 634, 635, 636, 637, 630, 483, 575, 551, 578, 491, + 554, 553, 0, 0, 589, 508, 590, 591, 405, 406, + 407, 408, 365, 615, 326, 511, 433, 0, 576, 0, + 0, 0, 0, 0, 0, 0, 0, 581, 582, 579, + 687, 0, 638, 639, 0, 0, 505, 506, 360, 367, + 524, 369, 325, 420, 362, 489, 377, 0, 517, 583, + 518, 641, 644, 642, 643, 412, 372, 374, 448, 378, + 388, 436, 488, 418, 441, 323, 479, 450, 393, 568, + 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 287, 288, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 623, 622, + 621, 620, 619, 618, 617, 616, 0, 0, 565, 465, + 339, 294, 335, 336, 343, 676, 672, 470, 677, 0, + 302, 545, 386, 432, 359, 610, 611, 0, 662, 248, + 249, 250, 251, 252, 253, 254, 255, 295, 256, 257, + 258, 259, 260, 261, 262, 265, 266, 267, 268, 269, + 270, 271, 272, 613, 263, 264, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 0, 0, 0, 0, 296, 664, 665, 666, 667, 668, + 0, 0, 297, 298, 299, 0, 0, 289, 290, 291, + 292, 293, 0, 0, 495, 496, 497, 520, 0, 498, + 481, 544, 674, 0, 0, 0, 0, 0, 0, 0, + 595, 606, 640, 0, 650, 651, 653, 655, 654, 657, + 455, 456, 663, 0, 659, 660, 661, 658, 390, 442, + 461, 449, 0, 680, 535, 536, 681, 646, 417, 0, + 0, 550, 584, 573, 656, 538, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 0, 0, 385, + 588, 569, 580, 570, 555, 556, 557, 564, 364, 558, + 559, 560, 530, 561, 531, 562, 563, 0, 587, 537, + 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, + 0, 321, 235, 532, 652, 534, 533, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2110, 0, 0, 0, 2109, 0, 0, 2111, 2145, - 0, 0, 2112, 2114, 2116, 0, 2118, 2119, 2120, 2124, - 2125, 2126, 2128, 2131, 2132, 2133, 0, 0, 0, 2127, - 0, 0, 2134, 2121, 2130, 2122, 0, 0, 2115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2110, 0, 0, 0, 2109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2127, 0, - 2137, 0, 0, 0, 0, 0, 0, 2115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 452, 480, 0, 492, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 309, 458, 477, 322, 446, 490, 327, 454, 1475, 317, + 416, 443, 0, 0, 311, 475, 453, 398, 310, 0, + 437, 350, 366, 347, 414, 0, 474, 503, 346, 493, + 0, 485, 313, 0, 484, 413, 471, 476, 399, 392, + 0, 312, 473, 397, 391, 379, 356, 519, 380, 381, + 370, 427, 389, 428, 371, 403, 402, 404, 0, 0, + 0, 0, 0, 514, 515, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 645, 0, 0, 649, 0, 487, 0, 0, 0, 0, + 0, 0, 457, 0, 0, 382, 0, 0, 0, 504, + 0, 440, 419, 683, 0, 0, 438, 387, 472, 429, + 478, 459, 486, 434, 430, 303, 460, 349, 400, 318, + 320, 673, 351, 353, 357, 358, 409, 410, 424, 445, + 462, 463, 464, 348, 332, 439, 333, 368, 334, 304, + 340, 338, 341, 447, 342, 306, 425, 468, 0, 363, + 435, 395, 307, 394, 426, 467, 466, 319, 494, 501, + 502, 592, 0, 507, 684, 685, 686, 516, 0, 431, + 315, 314, 0, 0, 0, 344, 328, 330, 331, 329, + 422, 423, 521, 522, 523, 525, 526, 527, 528, 593, + 609, 577, 546, 509, 601, 543, 547, 548, 373, 612, + 0, 0, 0, 500, 383, 384, 0, 355, 354, 396, + 308, 0, 0, 361, 300, 301, 679, 345, 415, 614, + 647, 648, 539, 0, 602, 540, 549, 337, 574, 586, + 585, 411, 499, 0, 597, 600, 529, 678, 0, 594, + 608, 682, 607, 675, 421, 0, 444, 605, 552, 0, + 598, 571, 572, 0, 599, 567, 603, 0, 541, 0, + 510, 513, 542, 627, 628, 629, 305, 512, 631, 632, + 633, 634, 635, 636, 637, 630, 483, 575, 551, 578, + 491, 554, 553, 0, 0, 589, 508, 590, 591, 405, + 406, 407, 408, 365, 615, 326, 511, 433, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 581, 582, + 579, 687, 0, 638, 639, 0, 0, 505, 506, 360, + 367, 524, 369, 325, 420, 362, 489, 377, 0, 517, + 583, 518, 641, 644, 642, 643, 412, 372, 374, 448, + 378, 388, 436, 488, 418, 441, 323, 479, 450, 393, + 568, 596, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 287, 288, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 623, + 622, 621, 620, 619, 618, 617, 616, 0, 0, 565, + 465, 339, 294, 335, 336, 343, 676, 672, 470, 677, + 0, 302, 545, 386, 432, 359, 610, 611, 0, 662, + 248, 249, 250, 251, 252, 253, 254, 255, 295, 256, + 257, 258, 259, 260, 261, 262, 265, 266, 267, 268, + 269, 270, 271, 272, 613, 263, 264, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 0, 0, 0, 0, 296, 664, 665, 666, 667, + 668, 0, 0, 297, 298, 299, 0, 0, 289, 290, + 291, 292, 293, 0, 0, 495, 496, 497, 520, 0, + 498, 481, 544, 674, 0, 0, 0, 0, 0, 0, + 0, 595, 606, 640, 0, 650, 651, 653, 655, 654, + 657, 455, 456, 663, 0, 659, 660, 661, 658, 390, + 442, 461, 449, 0, 680, 535, 536, 681, 646, 417, + 0, 0, 550, 584, 573, 656, 538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, + 385, 588, 569, 580, 570, 555, 556, 557, 564, 364, + 558, 559, 560, 530, 561, 531, 562, 563, 0, 587, + 537, 451, 401, 0, 604, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, + 0, 0, 321, 235, 532, 652, 534, 533, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2110, 0, 0, 0, 2109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2127, 0, - 0, 0, 0, 0, 0, 0, 0, 2115, + 0, 0, 0, 0, 0, 0, 0, 452, 480, 0, + 492, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 309, 458, 477, 322, 446, 490, 327, 454, 469, + 317, 416, 443, 0, 0, 311, 475, 453, 398, 310, + 0, 437, 350, 366, 347, 414, 0, 474, 503, 346, + 493, 0, 485, 313, 0, 484, 413, 471, 476, 399, + 392, 0, 312, 473, 397, 391, 379, 356, 519, 380, + 381, 370, 427, 389, 428, 371, 403, 402, 404, 0, + 0, 0, 0, 0, 514, 515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 645, 0, 0, 649, 0, 487, 0, 0, 0, + 0, 0, 0, 457, 0, 0, 382, 0, 0, 0, + 504, 0, 440, 419, 683, 0, 0, 438, 387, 472, + 429, 478, 459, 486, 434, 430, 303, 460, 349, 400, + 318, 320, 777, 351, 353, 357, 358, 409, 410, 424, + 445, 462, 463, 464, 348, 332, 439, 333, 368, 334, + 304, 340, 338, 341, 447, 342, 306, 425, 468, 0, + 363, 435, 395, 307, 394, 426, 467, 466, 319, 494, + 501, 502, 592, 0, 507, 684, 685, 686, 516, 0, + 431, 315, 314, 0, 0, 0, 344, 328, 330, 331, + 329, 422, 423, 521, 522, 523, 525, 526, 527, 528, + 593, 609, 577, 546, 509, 601, 543, 547, 548, 373, + 612, 0, 0, 0, 500, 383, 384, 0, 355, 354, + 396, 308, 0, 0, 361, 300, 301, 679, 345, 415, + 614, 647, 648, 539, 0, 602, 540, 549, 337, 574, + 586, 585, 411, 499, 0, 597, 600, 529, 678, 0, + 594, 608, 682, 607, 675, 421, 0, 444, 605, 552, + 0, 598, 571, 572, 0, 599, 567, 603, 0, 541, + 0, 510, 513, 542, 627, 628, 629, 305, 512, 631, + 632, 633, 634, 635, 636, 637, 630, 483, 575, 551, + 578, 491, 554, 553, 0, 0, 589, 508, 590, 591, + 405, 406, 407, 408, 365, 615, 326, 511, 433, 0, + 576, 0, 0, 0, 0, 0, 0, 0, 0, 581, + 582, 579, 687, 0, 638, 639, 0, 0, 505, 506, + 360, 367, 524, 369, 325, 420, 362, 489, 377, 0, + 517, 583, 518, 641, 644, 642, 643, 412, 372, 374, + 448, 378, 388, 436, 488, 418, 441, 323, 479, 450, + 393, 568, 596, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 287, 288, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 623, 622, 621, 620, 619, 618, 617, 616, 0, 0, + 565, 465, 339, 294, 335, 336, 343, 676, 672, 470, + 677, 0, 302, 545, 386, 432, 359, 610, 611, 0, + 662, 248, 249, 250, 251, 252, 253, 254, 255, 295, + 256, 257, 258, 259, 260, 261, 262, 265, 266, 267, + 268, 269, 270, 271, 272, 613, 263, 264, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 0, 0, 0, 0, 296, 664, 665, 666, + 667, 668, 0, 0, 297, 298, 299, 0, 0, 289, + 290, 291, 292, 293, 0, 0, 495, 496, 497, 520, + 0, 498, 481, 544, 674, 0, 0, 0, 0, 0, + 0, 0, 595, 606, 640, 0, 650, 651, 653, 655, + 654, 657, 455, 456, 663, 0, 659, 660, 661, 658, + 390, 442, 461, 449, 0, 680, 535, 536, 681, 646, + 417, 0, 0, 550, 584, 573, 656, 538, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, + 0, 385, 588, 569, 580, 570, 555, 556, 557, 564, + 364, 558, 559, 560, 530, 561, 531, 562, 563, 0, + 587, 537, 451, 401, 0, 604, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, + 0, 0, 0, 321, 235, 532, 652, 534, 533, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 324, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 452, 480, + 0, 492, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 309, 458, 477, 322, 446, 490, 327, 454, + 469, 317, 416, 443, 0, 0, 311, 475, 453, 398, + 310, 0, 437, 350, 366, 347, 414, 0, 474, 503, + 346, 493, 0, 485, 313, 0, 484, 413, 471, 476, + 399, 392, 0, 312, 473, 397, 391, 379, 356, 519, + 380, 381, 370, 427, 389, 428, 371, 403, 402, 404, + 0, 0, 0, 0, 0, 514, 515, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 645, 0, 0, 649, 0, 487, 0, 0, + 0, 0, 0, 0, 457, 0, 0, 382, 0, 0, + 0, 504, 0, 440, 419, 683, 0, 0, 438, 387, + 472, 429, 478, 459, 486, 729, 430, 303, 460, 349, + 400, 318, 320, 673, 351, 353, 357, 358, 409, 410, + 424, 445, 462, 463, 464, 348, 332, 439, 333, 368, + 334, 304, 340, 338, 341, 447, 342, 306, 425, 468, + 0, 363, 435, 395, 307, 394, 426, 467, 466, 319, + 494, 501, 502, 592, 0, 507, 684, 685, 686, 516, + 0, 431, 315, 314, 0, 0, 0, 344, 328, 330, + 331, 329, 422, 423, 521, 522, 523, 525, 526, 527, + 528, 593, 609, 577, 546, 509, 601, 543, 547, 548, + 373, 612, 0, 0, 0, 500, 383, 384, 0, 355, + 354, 396, 308, 0, 0, 361, 300, 301, 679, 345, + 415, 614, 647, 648, 539, 0, 602, 540, 549, 337, + 574, 586, 585, 411, 499, 0, 597, 600, 529, 678, + 0, 594, 608, 682, 607, 675, 421, 0, 444, 605, + 552, 0, 598, 571, 572, 0, 599, 567, 603, 0, + 541, 0, 510, 513, 542, 627, 628, 629, 305, 512, + 631, 632, 633, 634, 635, 636, 730, 630, 483, 575, + 551, 578, 491, 554, 553, 0, 0, 589, 508, 590, + 591, 405, 406, 407, 408, 365, 615, 326, 511, 433, + 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, + 581, 582, 579, 687, 0, 638, 639, 0, 0, 505, + 506, 360, 367, 524, 369, 325, 420, 362, 489, 377, + 0, 517, 583, 518, 641, 644, 642, 643, 412, 372, + 374, 448, 378, 388, 436, 488, 418, 441, 323, 479, + 450, 393, 568, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 287, 288, 0, 0, 0, + 0, 0, 2137, 0, 0, 0, 0, 0, 0, 0, + 0, 623, 622, 621, 620, 619, 618, 617, 616, 0, + 0, 565, 465, 339, 294, 335, 336, 343, 676, 672, + 470, 677, 0, 302, 545, 386, 432, 359, 610, 611, + 2139, 662, 248, 249, 250, 251, 252, 253, 254, 255, + 295, 256, 257, 258, 259, 260, 261, 262, 265, 266, + 267, 268, 269, 270, 271, 272, 613, 263, 264, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 2137, 4045, 0, 0, 296, 664, 665, + 666, 667, 668, 0, 2114, 297, 298, 299, 0, 0, + 289, 290, 291, 292, 293, 0, 0, 495, 496, 497, + 520, 0, 498, 481, 544, 674, 0, 0, 0, 0, + 0, 2139, 0, 595, 606, 640, 0, 650, 651, 653, + 655, 654, 657, 455, 456, 663, 0, 659, 660, 661, + 658, 390, 442, 461, 449, 0, 680, 535, 536, 681, + 646, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2130, 2114, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2130, 0, 2118, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2124, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2112, 2146, + 0, 0, 2113, 2115, 2117, 0, 2119, 2120, 2121, 2125, + 2126, 2127, 2129, 2132, 2133, 2134, 0, 0, 0, 0, + 0, 0, 0, 2122, 2131, 2123, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2118, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2124, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2138, 0, 0, 0, 0, 0, 0, 0, 2112, + 2146, 0, 0, 2113, 2115, 2117, 0, 2119, 2120, 2121, + 2125, 2126, 2127, 2129, 2132, 2133, 2134, 0, 0, 0, + 0, 0, 0, 0, 2122, 2131, 2123, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2135, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2111, 0, 0, 0, 2110, 0, 0, 0, 0, + 0, 0, 2138, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2128, + 0, 0, 0, 0, 0, 0, 0, 0, 2116, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2135, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2111, 0, 0, 0, 2110, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2128, 0, 0, 0, 0, 0, 0, 0, 0, 2116, } var yyPact = [...]int{ - 374, -1000, -1000, -1000, -363, 16329, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 506, -1000, -1000, -1000, -357, 16539, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 52564, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 392, 52564, -361, -1000, 3203, 50554, -1000, - -1000, -1000, 254, 51224, 18361, 52564, 500, 494, 52564, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 52828, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 353, 52828, -354, -1000, 3190, 50815, -1000, + -1000, -1000, 225, 51486, 18574, 52828, 488, 486, 52828, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 918, -1000, - 57254, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 822, 4708, 56584, 12281, -246, -1000, 1433, -54, 2792, 506, - -222, -230, 486, 1102, 1109, 1200, 1163, 52564, 1086, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 251, 32464, 51894, 1014, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 945, -1000, + 57525, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 840, 4799, 56854, 12485, -242, -1000, 1418, -53, 2770, 450, + -221, -222, 478, 1107, 1113, 1145, 1052, 52828, 1091, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 220, 32698, 52157, 989, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 4414, 239, 915, 1014, 23743, 53, 51, 1433, 3226, -122, - 217, -1000, 1451, 4377, 204, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 12281, 12281, 16329, -412, - 16329, 12281, 52564, 52564, -1000, -1000, -1000, -1000, -361, 51224, - 822, 4708, 12281, 2792, 506, -222, -230, 486, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 4518, 279, 939, 989, 23964, 72, 69, 1418, 3036, -135, + 205, -1000, 1371, 4376, 208, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 12485, 12485, 16539, -407, + 16539, 12485, 52828, 52828, -1000, -1000, -1000, -1000, -354, 51486, + 840, 4799, 12485, 2770, 450, -221, -222, 478, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -122, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -135, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -7755,8 +7762,8 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 51, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 69, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -7773,445 +7780,446 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 5468, -1000, - 1649, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2497, 3422, 1648, - 2762, -1000, -1000, -1000, -1000, 1433, 3840, 783, 52564, -1000, - 132, 3801, -1000, 52564, 52564, 130, 2052, -1000, 620, 588, - 599, 856, 318, 1645, -1000, -1000, -1000, -1000, -1000, -1000, - 636, 3798, -1000, 52564, 52564, 3455, 52564, -1000, 337, 710, - -1000, 4837, 3625, 1505, 964, 3480, -1000, -1000, 3421, -1000, - 323, 416, 320, 623, 385, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 277, -1000, 3698, -1000, -1000, 301, -1000, -1000, - 295, -1000, -1000, -1000, 50, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -56, -1000, -1000, 1175, - 2612, 12281, 2250, -1000, 3061, 1780, -1000, -1000, -1000, 7564, - 14973, 14973, 14973, 14973, 52564, -1000, -1000, 3245, 12281, 3418, - 3416, 3415, 3414, -1000, -1000, -1000, -1000, -1000, -1000, 3410, - 1643, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 2195, -1000, -1000, -1000, 15646, -1000, 3409, 3408, 3407, 3406, - 3403, 3401, 3399, 3397, 3395, 3394, 3393, 3392, 3390, 3389, - 3058, 17680, 3387, 2760, 2746, 3381, 3374, 3373, 2745, 3372, - 3370, 3368, 3058, 3058, 3361, 3360, 3359, 3358, 3357, 3355, - 3353, 3351, 3350, 3347, 3346, 3345, 3344, 3339, 3338, 3337, - 3334, 3332, 3329, 3324, 3323, 3315, 3314, 3312, 3311, 3300, - 3299, 3293, 3286, 3284, 3281, 3277, 3276, 3275, 3270, 3265, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 5504, + -1000, 1710, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2447, 3339, + 1707, 2762, -1000, -1000, -1000, -1000, 1418, 3816, 722, 52828, + -1000, 139, 3759, -1000, 52828, 52828, 170, 2042, -1000, 572, + 601, 584, 933, 275, 1701, -1000, -1000, -1000, -1000, -1000, + -1000, 634, 3758, -1000, 52828, 52828, 3366, 52828, -1000, 405, + 656, -1000, 4913, 3554, 1310, 956, 3389, -1000, -1000, 3338, + -1000, 283, 423, 243, 569, 349, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 299, -1000, 3637, -1000, -1000, 259, -1000, + -1000, 250, -1000, -1000, -1000, 68, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -58, -1000, -1000, + 1167, 2608, 12485, 2382, -1000, 4221, 1773, -1000, -1000, -1000, + 7761, 15181, 15181, 15181, 15181, 52828, -1000, -1000, 3160, 12485, + 3337, 3336, 3335, 3333, -1000, -1000, -1000, -1000, -1000, -1000, + 3332, 1692, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 2170, -1000, -1000, -1000, 15855, -1000, 3331, 3330, 3326, + 3323, 3322, 3316, 3315, 3313, 3307, 3306, 3301, 3296, 3294, + 3293, 3020, 17892, 3287, 2761, 2758, 3285, 3279, 3276, 2747, + 3273, 3272, 3271, 3020, 3020, 3268, 3266, 3263, 3260, 3259, + 3256, 3255, 3254, 3245, 3241, 3240, 3239, 3238, 3235, 3234, + 3232, 3231, 3230, 3228, 3227, 3224, 3222, 3221, 3219, 3218, + 3217, 3212, 3206, 3205, 3204, 3200, 3199, 3198, 3196, 3195, + 3194, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 1443, -1000, 3264, 3810, 3135, -1000, - 3684, 3679, 3666, 3664, -294, 3263, 2401, -1000, -1000, 97, - 52564, 52564, 288, 52564, -317, 407, -128, -129, -130, 1004, - -1000, 502, -1000, -1000, 1121, -1000, 1061, 55914, 888, -1000, - -1000, 52564, 818, 818, 818, 52564, 194, 853, 818, 818, - 818, 818, 818, 899, 818, 3717, 914, 913, 912, 911, - 818, -81, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2051, - 2050, 3541, 783, 50554, 1538, 52564, -1000, 3174, 1033, -1000, - -1000, -1000, -1000, 407, -340, 1990, 1990, 3784, 3784, 3713, - 3711, 741, 721, 672, 1990, 553, -1000, 1950, 1950, 1950, - 1950, 1990, 490, 754, 3718, 3718, 34, 1950, 41, 1990, - 1990, 41, 1990, 1990, -1000, 2095, 225, -302, -1000, -1000, - -1000, -1000, 1950, 1950, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 3693, 3689, 822, 822, 52564, 822, 822, 186, 52564, - 822, 822, 822, 52564, 833, -352, -16, 55244, 54574, 2530, - 337, 687, 666, 1551, 2105, -1000, 1817, 52564, 52564, 1817, - 1817, 27104, 26434, -1000, 52564, -1000, 3810, 3135, 3052, 2113, - 3049, 3135, -131, 407, 822, 822, 822, 822, 822, 252, - 822, 822, 822, 822, 822, 52564, 52564, 49884, 822, 822, - 822, 822, 10256, 1451, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 16329, 2295, 2285, - 203, -29, -338, 306, -1000, -1000, 52564, 3599, 1774, -1000, - -1000, -1000, 3161, -1000, 3167, 3167, 3167, 3167, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3167, 3167, - 3173, 3262, -1000, -1000, 3163, 3163, 3163, 3161, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1443, -1000, 3191, 3797, 3006, + -1000, 3629, 3626, 3614, 3612, -295, 3183, 2351, -1000, -1000, + 106, 52828, 52828, 296, 52828, -316, 397, -141, -142, -144, + 849, -1000, 493, -1000, -1000, 1076, -1000, 1069, 56183, 902, + -1000, -1000, 52828, 832, 832, 832, 52828, 176, 985, 832, + 832, 832, 832, 832, 907, 832, 3672, 935, 919, 917, + 911, 832, -95, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 2037, 2027, 3456, 722, 50815, 1552, 52828, -1000, 3114, 1054, + -1000, -1000, -1000, -1000, 397, -344, 1835, 1835, 3735, 3735, + 3667, 3666, 671, 667, 663, 1835, 556, -1000, 1938, 1938, + 1938, 1938, 1835, 470, 731, 3675, 3675, 37, 1938, 51, + 1835, 1835, 51, 1835, 1835, -1000, 2020, 217, -301, -1000, + -1000, -1000, -1000, 1938, 1938, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 3632, 3625, 840, 840, 52828, 840, 840, 174, + 52828, 840, 840, 840, 52828, 856, -342, -25, 55512, 54841, + 2323, 405, 655, 643, 1558, 2022, -1000, 1834, 52828, 52828, + 1834, 1834, 27330, 26659, -1000, 52828, -1000, 3797, 3006, 3012, + 1615, 3008, 3006, -145, 397, 840, 840, 840, 840, 840, + 231, 840, 840, 840, 840, 840, 52828, 52828, 50144, 840, + 840, 840, 840, 10457, 1371, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 16539, 2115, + 2310, 206, -32, -335, 274, -1000, -1000, 52828, 3522, 1730, + -1000, -1000, -1000, 3097, -1000, 3106, 3106, 3106, 3106, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 3106, + 3106, 3113, 3182, -1000, -1000, 3098, 3098, 3098, 3097, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 3168, 3168, 3171, 3171, 3168, 52564, 3822, - -1000, -1000, 12281, 52564, 3619, 3810, 3614, 3718, 3775, 3229, - 3259, -1000, -1000, 52564, 326, 2289, -1000, -1000, 1642, 2398, - 2728, -1000, 318, -1000, 604, 318, -1000, 679, 679, 1988, - -1000, 1221, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 52564, - -56, 479, -1000, -1000, 2699, 3255, -1000, 621, 1251, 1579, - -1000, 404, 4587, 41844, 337, 41844, 52564, -1000, -1000, -1000, - -1000, -1000, -1000, 49, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 3110, 3110, 3112, 3112, 3110, 52828, + 3793, -1000, -1000, 12485, 52828, 3535, 3797, 3528, 3675, 3730, + 2934, 3180, -1000, -1000, 52828, 322, 2258, -1000, -1000, 1667, + 2348, 2746, -1000, 275, -1000, 557, 275, -1000, 430, 430, + 1831, -1000, 1210, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 52828, -58, 3197, -1000, -1000, 2721, 3179, -1000, 621, 1257, + 1612, -1000, 212, 5370, 42092, 405, 42092, 52828, -1000, -1000, + -1000, -1000, -1000, -1000, 59, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 247, -1000, - 12281, 12281, 12281, 12281, 12281, -1000, 727, 14300, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 14973, 14973, 14973, 14973, 14973, - 14973, 14973, 14973, 14973, 14973, 14973, 14973, 14973, 14973, 3240, - 2061, 14973, 14973, 14973, 14973, 5080, 29114, 2113, 3509, 1539, - 308, 1780, 1780, 1780, 1780, 12281, -1000, 2091, 2612, 12281, - 12281, 12281, 12281, 35814, 52564, -1000, -1000, 4826, 12281, 12281, - 5308, 12281, 3662, 12281, 12281, 12281, 3046, 6208, 52564, 12281, - -1000, 3039, 3038, -1000, -1000, 2179, 12281, -1000, -1000, 12281, - -1000, -1000, 12281, 14973, 12281, -1000, 12281, 12281, 12281, -1000, - -1000, 253, 253, 1013, 3662, 3662, 3662, 2038, 12281, 12281, - 3662, 3662, 3662, 2001, 3662, 3662, 3662, 3662, 3662, 3662, - 3662, 3662, 3662, 3662, 3662, 3019, 3013, 3012, 3010, 12281, - 3005, 12281, 12281, 12281, 12281, 12281, 11608, 3718, -246, -1000, - 9583, 3614, 3718, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -298, 3254, 52564, 2727, 2725, -370, -375, - 1148, -375, 1641, -1000, -318, 1093, 287, 52564, -1000, -1000, - 52564, 2397, 52564, 2388, 214, 213, 52564, 52564, -7, 1096, - 1078, 1082, -1000, -1000, 52564, 53904, -1000, 52564, 2098, 52564, - 52564, 3653, -1000, 52564, 52564, 818, 818, 818, -1000, 47874, - 41844, 52564, 52564, 337, 52564, 52564, 52564, 818, 818, 818, - 818, 52564, -1000, 3560, 41844, 3545, 3100, 783, 52564, 1538, - 3652, 52564, 833, -1000, -1000, -1000, -1000, -1000, 3784, 14973, - 14973, -1000, -1000, 12281, -1000, 255, 49214, 1950, 1990, 1990, - -1000, -1000, 52564, -1000, -1000, -1000, 1950, 52564, 1950, 1950, - 3784, 1950, -1000, -1000, -1000, 1990, 1990, -1000, -1000, 12281, - -1000, -1000, 1950, 1950, -1000, -1000, 3784, 52564, 45, 3784, - 3784, 25, -1000, -1000, -1000, 1990, 52564, 52564, 818, 52564, - -1000, 52564, 52564, -1000, -1000, 52564, 52564, 5159, 52564, 337, - 47874, 48544, 3688, -1000, 41844, 52564, 52564, 1530, -1000, 886, - 39164, -1000, 52564, 1465, -1000, -2, -1000, -14, -16, 1817, - -16, 1817, 882, -1000, 605, 391, 25094, 549, 41844, 6881, - -1000, -1000, 1817, 1817, 6881, 6881, 1680, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 1515, -1000, 258, 3718, -1000, -1000, - -1000, -1000, -1000, 2387, -329, 52564, 47874, 41844, 337, 52564, - 822, 52564, 52564, 52564, 52564, 52564, -1000, 3251, 1639, -1000, - 3624, 52564, 52564, 52564, 52564, 1518, -1000, -1000, 21711, 1637, - -1000, -1000, 2083, -1000, 12281, 16329, -280, 12281, 16329, 16329, - 12281, 16329, -1000, 12281, 1662, -1000, -1000, -1000, -1000, 2385, - -1000, 2383, -1000, -1000, -1000, -1000, -1000, 2724, 2724, -1000, - 2379, -1000, -1000, -1000, -1000, 2378, -1000, -1000, 2376, -1000, - -1000, -1000, -1000, -179, 3003, 1175, -1000, 2722, 3718, -1000, - -255, 3761, 12281, -1000, -250, -1000, 23073, 52564, 52564, -380, - 2045, 2044, 2041, 3702, 822, 52564, -1000, 3710, -1000, -1000, - 318, -1000, -1000, -1000, 679, 431, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 1628, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -123, -124, 1513, -1000, 52564, - -1000, -1000, 404, 41844, 44524, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1439, -1000, -1000, 178, -1000, 879, 220, 1973, - -1000, -1000, 190, 210, 142, 965, 2612, -1000, 2106, 2106, - 2119, -1000, 755, -1000, -1000, -1000, -1000, 3245, -1000, -1000, - -1000, 3023, 2855, -1000, 1986, 1986, 1710, 1710, 1710, 1710, - 1710, 2214, 2214, 1780, 1780, -1000, -1000, -1000, 7564, 3240, - 14973, 14973, 14973, 14973, 998, 998, 4748, 4558, -1000, -1000, - 1725, 1725, -1000, -1000, -1000, -1000, 12281, 176, 2069, -1000, - 12281, 3273, 1796, 2716, 1660, 1970, -1000, 3161, 12281, 1619, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 300, + -1000, 12485, 12485, 12485, 12485, 12485, -1000, 735, 14507, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 15181, 15181, 15181, 15181, + 15181, 15181, 15181, 15181, 15181, 15181, 15181, 15181, 15181, 15181, + 3158, 1968, 15181, 15181, 15181, 15181, 4279, 29343, 1615, 3510, + 1554, 323, 1773, 1773, 1773, 1773, 12485, -1000, 2059, 2608, + 12485, 12485, 12485, 12485, 36053, 52828, -1000, -1000, 5563, 12485, + 12485, 4712, 12485, 3610, 12485, 12485, 12485, 3004, 6403, 52828, + 12485, -1000, 3001, 2999, -1000, -1000, 2178, 12485, -1000, -1000, + 12485, -1000, -1000, 12485, 15181, 12485, -1000, 12485, 12485, 12485, + -1000, -1000, 1391, 1391, 908, 3610, 3610, 3610, 1931, 12485, + 12485, 3610, 3610, 3610, 1910, 3610, 3610, 3610, 3610, 3610, + 3610, 3610, 3610, 3610, 3610, 3610, 2985, 2981, 2979, 2978, + 12485, 2976, 12485, 12485, 12485, 12485, 12485, 11811, 3675, -242, + -1000, 9783, 3528, 3675, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -297, 3172, 52828, 2741, 2740, -367, + -368, 1180, -368, 1666, -1000, -319, 1095, 292, 52828, -1000, + -1000, 52828, 2347, 52828, 2346, 224, 211, 52828, 52828, -20, + 1098, 1074, 1088, -1000, -1000, 52828, 54170, -1000, 52828, 2073, + 52828, 52828, 3593, -1000, 52828, 52828, 832, 832, 832, -1000, + 48131, 42092, 52828, 52828, 405, 52828, 52828, 52828, 832, 832, + 832, 832, 52828, -1000, 3473, 42092, 3467, 2932, 722, 52828, + 1552, 3587, 52828, 856, -1000, -1000, -1000, -1000, -1000, 3735, + 15181, 15181, -1000, -1000, 12485, -1000, 222, 49473, 1938, 1835, + 1835, -1000, -1000, 52828, -1000, -1000, -1000, 1938, 52828, 1938, + 1938, 3735, 1938, -1000, -1000, -1000, 1835, 1835, -1000, -1000, + 12485, -1000, -1000, 1938, 1938, -1000, -1000, 3735, 52828, 58, + 3735, 3735, 43, -1000, -1000, -1000, 1835, 52828, 52828, 832, + 52828, -1000, 52828, 52828, -1000, -1000, 52828, 52828, 5199, 52828, + 405, 48131, 48802, 3623, -1000, 42092, 52828, 52828, 1550, -1000, + 901, 39408, -1000, 52828, 1468, -1000, -7, -1000, -34, -25, + 1834, -25, 1834, 899, -1000, 616, 394, 25317, 555, 42092, + 7077, -1000, -1000, 1834, 1834, 7077, 7077, 1767, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1548, -1000, 288, 3675, -1000, + -1000, -1000, -1000, -1000, 2334, -328, 52828, 48131, 42092, 405, + 52828, 840, 52828, 52828, 52828, 52828, 52828, -1000, 3171, 1665, + -1000, 3550, 52828, 52828, 52828, 52828, 1560, -1000, -1000, 21929, + 1647, -1000, -1000, 2063, -1000, 12485, 16539, -267, 12485, 16539, + 16539, 12485, 16539, -1000, 12485, 1700, -1000, -1000, -1000, -1000, + 2333, -1000, 2332, -1000, -1000, -1000, -1000, -1000, 2736, 2736, + -1000, 2328, -1000, -1000, -1000, -1000, 2326, -1000, -1000, 2321, + -1000, -1000, -1000, -1000, -173, 2975, 1167, -1000, 2735, 3675, + -1000, -246, 3721, 12485, -1000, -243, -1000, 23293, 52828, 52828, + -376, 2026, 2021, 2017, 3647, 840, 52828, -1000, 3663, -1000, + -1000, 275, -1000, -1000, -1000, 430, 443, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1632, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -136, -137, 1531, -1000, + 52828, -1000, -1000, 212, 42092, 44776, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 1387, -1000, -1000, 182, -1000, 896, 201, + 1830, -1000, -1000, 186, 214, 173, 977, 2608, -1000, 2077, + 2077, 2083, -1000, 653, -1000, -1000, -1000, -1000, 3160, -1000, + -1000, -1000, 2615, 2544, -1000, 1942, 1942, 1779, 1779, 1779, + 1779, 1779, 1987, 1987, 1773, 1773, -1000, -1000, -1000, 7761, + 3158, 15181, 15181, 15181, 15181, 913, 913, 4586, 4554, -1000, + -1000, 1746, 1746, -1000, -1000, -1000, -1000, 12485, 181, 2060, + -1000, 12485, 2639, 1902, 2557, 1509, 1823, -1000, 3097, 12485, + 1630, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 2973, 2970, 2434, 3755, 2969, 12485, -1000, -1000, 1820, + 1813, 1808, -1000, 2327, 11137, -1000, -1000, -1000, 2966, 1610, + 2965, -1000, -1000, -1000, 2954, 1806, 1274, 2952, 3861, 2951, + 2946, 2942, 2935, 1529, 1523, 1522, -1000, -1000, -1000, -1000, + 12485, 12485, 12485, 12485, 2928, 1786, 1784, 12485, 12485, 12485, + 12485, 2918, 12485, 12485, 12485, 12485, 12485, 12485, 12485, 12485, + 12485, 12485, 52828, 115, 115, 115, 115, 3499, 115, 1970, + 1737, 3479, 3468, 1732, 1508, 1498, -1000, -1000, 1781, -1000, + 2608, -1000, -1000, 3721, -1000, 3157, 2320, 1488, -1000, -1000, + -351, 2680, 885, 52828, -320, 52828, 885, 52828, 52828, 2016, + 885, -322, 2728, -1000, -1000, 2726, -1000, 52828, 52828, 52828, + 52828, -153, 3533, -1000, -1000, 1094, 1067, 1061, -1000, 52828, + -1000, 2723, 3543, 3662, 859, 52828, 3156, 3151, 52828, 52828, + 52828, 229, -1000, -1000, 1343, -1000, 201, -73, 495, 1226, + 3364, 813, 3791, 52828, 52828, 52828, 52828, 3584, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 3388, -243, -1000, 22611, + 52828, 2932, -1000, 3145, 1770, -1000, 47460, -1000, 1773, 1773, + 2608, 52828, 52828, 52828, 3358, 52828, 52828, 3735, 3735, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 1938, 3735, 3735, 1594, + 1835, 1938, -1000, -1000, 1938, -376, -1000, 1938, -1000, -376, + 1603, -376, 52828, -1000, -1000, -1000, 3581, 3114, 1478, -1000, + -1000, -1000, 3728, 1276, 803, 803, 1046, 552, 3724, 20587, + -1000, 1884, 1137, 881, 3512, 278, -1000, 1884, -169, 771, + 1884, 1884, 1884, 1884, 1884, 1884, 1884, 623, 620, 1884, + 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, 1884, + 1111, 1884, 1884, 1884, 1884, 1884, -1000, 1884, 3144, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 648, 581, 960, 228, + 3617, 324, -1000, 310, 1343, 633, 3609, 347, 52828, 52828, + 3805, 1284, -1000, -1000, -1000, -1000, -1000, 30014, 30014, 24646, + 30014, -1000, 203, 1834, -25, -10, -1000, -1000, 1468, 7077, + 1468, 7077, 2318, -1000, -1000, 880, -1000, -1000, 1226, -1000, + 52828, 52828, -1000, -1000, 3140, 2015, -1000, -1000, 17892, -1000, + 7077, 7077, -1000, -1000, 32027, 52828, -1000, -65, -1000, -45, + 3721, -1000, -1000, -1000, 1169, -1000, -1000, 1466, 1226, 3378, + 52828, 1169, 1169, 1169, -1000, -1000, 19245, 52828, 52828, -1000, + -1000, -1000, -328, 3735, 10457, -1000, 39408, -1000, -1000, 46789, + -1000, 46118, 2050, -1000, 16539, 2294, 200, -1000, 265, -339, + 199, 2202, 198, 2608, -1000, -1000, 2917, 2910, 1747, -1000, + 1742, 2905, 1726, 1725, 2317, -1000, 33, 3721, 2722, 3528, + -219, 1459, -1000, 2355, 1184, -1000, 3137, -1000, 1713, 3449, + -1000, 1417, -1000, 1990, 1704, -1000, -1000, 12485, 45447, 12485, + 1039, 2717, 1598, 167, -1000, -1000, -1000, 52828, 2721, 1695, + 44776, 1321, -1000, 877, 1596, 1591, -1000, 42092, 268, 42092, + -1000, 42092, -1000, -1000, 3693, -1000, 52828, 3531, -1000, -1000, + -1000, 2680, 1982, -375, 52828, -1000, -1000, -1000, -1000, -1000, + 1684, -1000, 913, 913, 4586, 4439, -1000, 15181, -1000, 15181, + -1000, -1000, -1000, -1000, 3462, -1000, 2049, -1000, 12485, 2169, + 4279, 12485, 4279, 1874, 28672, 36053, -154, 3564, 3436, 52828, + -1000, -1000, 12485, 12485, -1000, 3428, -1000, -1000, -1000, -1000, + 12485, 12485, 2390, -1000, 52828, -1000, -1000, -1000, -1000, 28672, + -1000, 15181, -1000, -1000, -1000, -1000, 12485, 12485, 12485, 1431, + 1431, 3387, 1683, 115, 115, 115, 3365, 3350, 3319, 1673, + 115, 3281, 3274, 3269, 3261, 3185, 3147, 3138, 3134, 3073, + 2968, 1659, -1000, 3136, -1000, -1000, -1000, 115, -1000, 115, + 12485, 115, 12485, 115, 115, 12485, 2149, 13833, 9783, -1000, + 3528, 303, 1426, 2316, 2712, 112, -1000, 1981, -1000, 345, + -1000, 52828, 3753, -1000, 1587, 2711, 44105, -1000, 52828, -1000, + -1000, 3749, 3748, -1000, -1000, 52828, 52828, -1000, -1000, -1000, + 1064, -1000, 2699, -1000, 244, 223, 2222, 234, 1160, 19245, + 3114, 3131, 3114, 108, 1884, 608, 42092, 627, -1000, 52828, + 2142, 1974, 3377, 781, 3521, 52828, 52828, 3130, 1104, 3129, + 3128, 3576, 453, 5811, -1000, 3513, 1184, 1654, 3448, 1417, + -1000, 4376, -1000, 52828, 52828, 1364, -1000, 1585, -1000, -1000, + 52828, -1000, 405, -1000, 1835, -1000, -1000, 3735, -1000, -1000, + 12485, 12485, 3735, 1835, 1835, -1000, 1938, -1000, 52828, -1000, + -376, 453, 5811, 3573, 5515, 543, 2440, -1000, 52828, -1000, + -1000, -1000, 783, -1000, 1030, 832, 52828, 2111, 1030, 2110, + 3122, -1000, -1000, 52828, 52828, 52828, 52828, -1000, -1000, 52828, + -1000, 52828, 52828, 52828, 52828, 52828, 43434, -1000, 52828, 52828, + -1000, 52828, 2108, 52828, 2104, 3586, -1000, 1884, 1884, 1010, + -1000, -1000, 603, -1000, 43434, 2314, 2313, 2303, 2301, 2698, + 2696, 2695, 1884, 1884, 2290, 2693, 42763, 2692, 1197, 2289, + 2288, 2280, 2279, 2690, 959, -1000, 2688, 2272, 2270, 2260, + 52828, 3121, 2575, -1000, -1000, 2222, 870, 108, 1884, 313, + 52828, 1955, 1954, 608, 568, 568, 490, -76, 25988, -1000, + -1000, -1000, 52828, 39408, 39408, 39408, 39408, 39408, 39408, -1000, + 3430, 3404, 3116, -1000, 3418, 3417, 3424, 3421, 3369, 52828, + 39408, 3114, -1000, 42763, -1000, -1000, -1000, 1615, 1649, 3718, + 1037, 12485, 7077, -1000, -1000, -42, -51, -1000, -1000, -1000, + -1000, 42092, 2687, 555, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 3528, 52828, 52828, 775, 2902, 1407, -1000, -1000, -1000, + 5811, 3106, 3106, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 3106, 3106, 3113, -1000, -1000, 3098, 3098, 3098, + 3097, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 3110, 3110, 3112, 3112, 3110, -1000, -1000, -1000, 3733, + -1000, 1396, -1000, -1000, 1569, -1000, 2067, -359, 16539, 2053, + 2045, -1000, 12485, 16539, 12485, -276, 294, -278, -1000, -1000, + -1000, 2686, -1000, -1000, -1000, 2278, -1000, 2273, -1000, 142, + 148, 3528, 168, -1000, 3790, 12485, 3476, -1000, -1000, -243, + 9783, 2950, 52828, -243, 52828, 9783, -1000, 52828, 171, -391, + -392, 166, 2685, -1000, 52828, 2263, -1000, -1000, -1000, 3747, + 42092, 405, 1819, 41421, -1000, 258, -1000, 1366, 596, 2683, + -1000, 910, 104, 2682, 2680, -1000, -1000, -1000, -1000, 15181, + 1773, -1000, -1000, -1000, 2608, 12485, 2896, 2499, 2894, 2887, + -1000, 3106, 3106, -1000, 3097, 3098, 3097, 1746, 1746, 2885, + -1000, 3096, -1000, 3564, -1000, 2254, 2964, -1000, 2960, 2929, + 12485, -1000, 2881, 4514, 1727, 1693, 2893, -99, -203, 115, + 115, -1000, -1000, -1000, -1000, 115, 115, 115, 115, -1000, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, + 115, 768, -1000, -1000, 1547, -1000, 1438, -1000, -1000, 2884, + -119, -309, -120, -312, -1000, -1000, 2880, 1388, -1000, -1000, + -1000, -1000, -1000, 4712, 1377, 504, 504, 2680, 2678, 52828, + 2656, -325, 52828, -1000, -394, -395, 2654, 52828, 52828, 458, + 2056, -1000, 2652, -1000, -1000, 52828, 52828, 52828, 53499, 580, + 52828, 52828, 2651, -1000, 2644, 2878, 1356, -1000, -1000, 52828, + -1000, -1000, -1000, 2873, 3571, 19916, 3568, 2368, -1000, -1000, + -1000, 31356, 568, -1000, -1000, -1000, 680, 267, 2262, 560, + -1000, 52828, 475, 3465, 1940, 2643, 52828, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 3521, -1000, 1001, -376, 425, + 38066, 17221, -1000, 2920, 52828, -1000, 52828, 19916, 19916, 2920, + 400, 1918, -1000, 2102, 2940, -243, 2872, -1000, 722, 1248, + 128, 39408, 52828, -1000, 38737, -1000, 1226, 3735, -1000, 2608, + 2608, -376, 3735, 3735, 1835, -1000, -1000, 400, -1000, 2920, + -1000, 1637, 21258, 530, 441, 429, -1000, 688, -1000, -1000, + 720, 3485, 5811, -1000, 52828, -1000, 52828, -1000, 52828, 52828, + 832, 12485, 3485, 52828, 869, -1000, 1182, 427, 376, 760, + 760, 1351, -1000, 3564, -1000, -1000, 1349, -1000, -1000, -1000, + -1000, 52828, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 28672, + 28672, 3607, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 2640, 2638, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 3000, 2987, 3004, 3796, 2975, 12281, -1000, -1000, 1969, 1961, - 1960, -1000, 2333, 10935, -1000, -1000, -1000, 2974, 1618, 2973, - -1000, -1000, -1000, 2968, 1952, 1209, 2966, 1962, 2964, 2963, - 2961, 2960, 1510, 1502, 1490, -1000, -1000, -1000, -1000, 12281, - 12281, 12281, 12281, 2959, 1918, 1917, 12281, 12281, 12281, 12281, - 2950, 12281, 12281, 12281, 12281, 12281, 12281, 12281, 12281, 12281, - 12281, 52564, 80, 80, 80, 80, 3478, 80, 1902, 1621, - 3470, 3437, 1782, 1487, 1486, -1000, -1000, 1915, -1000, 2612, - -1000, -1000, 3761, -1000, 3239, 2373, 1475, -1000, -1000, -358, - 2650, 869, 52564, -319, 52564, 869, 52564, 52564, 2036, 869, - -321, 2721, -1000, -1000, 2718, -1000, 52564, 52564, 52564, 52564, - -138, 3618, -1000, -1000, 1089, 1037, 1041, -1000, 52564, -1000, - 2710, 3623, 3709, 857, 52564, 3231, 3230, 52564, 52564, 52564, - 235, -1000, -1000, 1379, -1000, 220, -69, 503, 1218, 3448, - 814, 3821, 52564, 52564, 52564, 52564, 3651, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 3479, -250, -1000, 22392, 52564, - 3100, -1000, 3227, 1905, -1000, 47204, -1000, 1780, 1780, 2612, - 52564, 52564, 52564, 3447, 52564, 52564, 3784, 3784, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1950, 3784, 3784, 1504, 1990, - 1950, -1000, -1000, 1950, -380, -1000, 1950, -1000, -380, 1615, - -380, 52564, -1000, -1000, -1000, 3648, 3174, 1467, -1000, -1000, - -1000, 3773, 1636, 807, 807, 1066, 770, 3762, 20371, -1000, - 1819, 1385, 862, 3577, 321, -1000, 1819, -176, 789, 1819, - 1819, 1819, 1819, 1819, 1819, 1819, 630, 628, 1819, 1819, - 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1819, 1107, - 1819, 1819, 1819, 1819, 1819, -1000, 1819, 3225, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 648, 592, 927, 232, 3683, - 349, -1000, 344, 1379, 607, 3676, 384, 52564, 52564, 3803, - 1516, -1000, -1000, -1000, -1000, -1000, 29784, 29784, 24424, 29784, - -1000, 193, 1817, -16, -35, -1000, -1000, 1465, 6881, 1465, - 6881, 2371, -1000, -1000, 859, -1000, -1000, 1218, -1000, 52564, - 52564, -1000, -1000, 3224, 2035, -1000, -1000, 17680, -1000, 6881, - 6881, -1000, -1000, 31794, 52564, -1000, -62, -1000, -45, 3761, - -1000, -1000, -1000, 1178, -1000, -1000, 1460, 1218, 3477, 52564, - 1178, 1178, 1178, -1000, -1000, 19031, 52564, 52564, -1000, -1000, - -1000, -329, 3784, 10256, -1000, 39164, -1000, -1000, 46534, -1000, - 45864, 2067, -1000, 16329, 2275, 200, -1000, 293, -343, 198, - 2177, 196, 2612, -1000, -1000, 2946, 2943, 1895, -1000, 1883, - 2907, 1874, 1873, 2369, -1000, -10, 3761, 2707, 3614, -223, - 1450, -1000, 2380, 1184, -1000, 3216, -1000, 1871, 3536, -1000, - 1432, -1000, 2034, 1870, -1000, -1000, 12281, 45194, 12281, 1018, - 2693, 1612, 122, -1000, -1000, -1000, 52564, 2699, 1861, 44524, - 1290, -1000, 851, 1595, 1593, -1000, 41844, 313, 41844, -1000, - 41844, -1000, -1000, 3734, -1000, 52564, 3615, -1000, -1000, -1000, - 2650, 2033, -376, 52564, -1000, -1000, -1000, -1000, -1000, 1856, - -1000, 998, 998, 4748, 4491, -1000, 14973, -1000, 14973, -1000, - -1000, -1000, -1000, 3428, -1000, 2060, -1000, 12281, 2225, 5080, - 12281, 5080, 1897, 28444, 35814, -140, 3605, 3412, 52564, -1000, - -1000, 12281, 12281, -1000, 3348, -1000, -1000, -1000, -1000, 12281, - 12281, 2645, -1000, 52564, -1000, -1000, -1000, -1000, 28444, -1000, - 14973, -1000, -1000, -1000, -1000, 12281, 12281, 12281, 1383, 1383, - 3335, 1843, 80, 80, 80, 3291, 3279, 3267, 1800, 80, - 3260, 3243, 3205, 3189, 3184, 3169, 3165, 3108, 2926, 2900, - 1779, -1000, 3211, -1000, -1000, -1000, 80, -1000, 80, 12281, - 80, 12281, 80, 80, 12281, 2204, 13627, 9583, -1000, 3614, - 312, 1437, 2368, 2692, 105, -1000, 2031, -1000, 381, -1000, - 52564, 3795, -1000, 1590, 2691, 43854, -1000, 52564, -1000, -1000, - 3794, 3793, -1000, -1000, 52564, 52564, -1000, -1000, -1000, 1020, - -1000, 2682, -1000, 260, 249, 2293, 262, 1246, 19031, 3174, - 3210, 3174, 77, 1819, 638, 41844, 650, -1000, 52564, 2166, - 2027, 3475, 872, 3595, 52564, 52564, 3186, 1537, 3182, 3181, - 3647, 469, 5769, -1000, 3601, 1184, 1778, 3527, 1432, -1000, - 4377, -1000, 52564, 52564, 1488, -1000, 1589, -1000, -1000, 52564, - -1000, 337, -1000, 1990, -1000, -1000, 3784, -1000, -1000, 12281, - 12281, 3784, 1990, 1990, -1000, 1950, -1000, 52564, -1000, -380, - 469, 5769, 3629, 5473, 575, 2584, -1000, 52564, -1000, -1000, - -1000, 825, -1000, 1040, 818, 52564, 2143, 1040, 2138, 3179, - -1000, -1000, 52564, 52564, 52564, 52564, -1000, -1000, 52564, -1000, - 52564, 52564, 52564, 52564, 52564, 43184, -1000, 52564, 52564, -1000, - 52564, 2130, 52564, 2128, 3597, -1000, 1819, 1819, 1002, -1000, - -1000, 586, -1000, 43184, 2367, 2364, 2361, 2356, 2681, 2679, - 2677, 1819, 1819, 2354, 2676, 42514, 2674, 1275, 2353, 2350, - 2349, 2331, 2671, 1028, -1000, 2665, 2313, 2312, 2305, 52564, - 3178, 2558, -1000, -1000, 2293, 845, 77, 1819, 348, 52564, - 2026, 2024, 638, 590, 590, 499, -72, 25764, -1000, -1000, - -1000, 52564, 39164, 39164, 39164, 39164, 39164, 39164, -1000, 3505, - 3499, 3176, -1000, 3502, 3501, 3511, 3492, 2657, 52564, 39164, - 3174, -1000, 42514, -1000, -1000, -1000, 2113, 1772, 3716, 1084, - 12281, 6881, -1000, -1000, -37, -31, -1000, -1000, -1000, -1000, - 41844, 2661, 549, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 3614, 52564, 52564, 867, 2906, 1414, -1000, -1000, -1000, 5769, - 3167, 3167, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 3167, 3167, 3173, -1000, -1000, 3163, 3163, 3163, 3161, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 3168, 3168, 3171, 3171, 3168, -1000, -1000, -1000, 3781, -1000, - 1400, -1000, -1000, 1586, -1000, 2099, -366, 16329, 2070, 1885, - -1000, 12281, 16329, 12281, -282, 330, -286, -1000, -1000, -1000, - 2655, -1000, -1000, -1000, 2343, -1000, 2340, -1000, 94, 185, - 3614, 140, -1000, 3820, 12281, 3567, -1000, -1000, -250, 9583, - 3054, 52564, -250, 52564, 9583, -1000, 52564, 172, -394, -395, - 166, 2654, -1000, 52564, 2339, -1000, -1000, -1000, 3789, 41844, - 337, 1754, 41174, -1000, 300, -1000, 1436, 608, 2653, -1000, - 909, 104, 2651, 2650, -1000, -1000, -1000, -1000, 14973, 1780, - -1000, -1000, -1000, 2612, 12281, 2904, 2390, 2901, 2895, -1000, - 3167, 3167, -1000, 3161, 3163, 3161, 1725, 1725, 2894, -1000, - 3160, -1000, 3605, -1000, 2399, 2869, -1000, 2848, 2689, 12281, - -1000, 2886, 4445, 1757, 1514, 2680, -86, -207, 80, 80, - -1000, -1000, -1000, -1000, 80, 80, 80, 80, -1000, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 786, -1000, -1000, 1584, -1000, 1445, -1000, -1000, 2663, -110, - -311, -114, -313, -1000, -1000, 2880, 1395, -1000, -1000, -1000, - -1000, -1000, 5308, 1392, 516, 516, 2650, 2648, 52564, 2646, - -324, 52564, -1000, -396, -397, 2643, 52564, 52564, 472, 2084, - -1000, 2642, -1000, -1000, 52564, 52564, 52564, 53234, 591, 52564, - 52564, 2632, -1000, 2630, 2879, 1368, -1000, -1000, 52564, -1000, - -1000, -1000, 2872, 3628, 19701, 3627, 2428, -1000, -1000, -1000, - 31124, 590, -1000, -1000, -1000, 715, 290, 2338, 566, -1000, - 52564, 498, 3558, 2023, 2628, 52564, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 3595, -1000, 1193, -380, 420, 37824, - 17010, -1000, 2958, 52564, -1000, 52564, 19701, 19701, 2958, 447, - 2047, -1000, 2127, 2933, -250, 2870, -1000, 783, 1228, 126, - 39164, 52564, -1000, 38494, -1000, 1218, 3784, -1000, 2612, 2612, - -380, 3784, 3784, 1990, -1000, -1000, 447, -1000, 2958, -1000, - 1333, 21041, 541, 468, 452, -1000, 670, -1000, -1000, 773, - 3574, 5769, -1000, 52564, -1000, 52564, -1000, 52564, 52564, 818, - 12281, 3574, 52564, 844, -1000, 1157, 433, 418, 764, 764, - 1357, -1000, 3605, -1000, -1000, 1340, -1000, -1000, -1000, -1000, - 52564, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 28444, 28444, - 3673, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 2625, 2619, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 52828, 1606, -1000, 1939, + 2636, 405, 2368, 31356, 1936, 1834, 2635, 2627, 568, -1000, + 2626, 2621, -1000, 2142, 1921, 863, 52828, -1000, 1190, 52828, + 52828, -1000, 1287, -1000, 1920, 3348, 3376, 3348, -1000, 3348, + -1000, -1000, -1000, -1000, 3419, 2620, -1000, 3408, -1000, 3407, + -1000, -1000, -1000, -1000, 1287, -1000, -1000, -1000, -1000, -1000, + 1037, -1000, 3655, 1030, 1030, 1030, 2869, -1000, -1000, -1000, + -1000, 1321, 2867, -1000, -1000, 3650, -1000, -1000, -1000, -1000, + -1000, -1000, 19245, 3520, 3719, 3720, 40750, -1000, -359, 2048, + -1000, 2091, 196, 2047, 52828, -1000, -1000, -1000, 2864, 2856, + -249, 158, 3716, 3715, 3650, -261, 2617, 256, -1000, -1000, + 3500, -1000, 2855, 1309, -243, -1000, -1000, 1184, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -403, -1000, -1000, 405, -1000, + 1315, -1000, -1000, -1000, -1000, -1000, -1000, 185, -1000, 52828, + -1000, 1261, 103, -1000, 2608, -1000, 4279, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2614, -1000, -1000, + 12485, -1000, -1000, -1000, 2871, -1000, -1000, 12485, 12485, -1000, + 2854, 2612, 2843, 2609, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 3797, -1000, 3712, 115, 12485, 115, 12485, 115, 1604, + 2840, 2839, 1579, 2838, 2836, -1000, 12485, 2823, 4712, 1018, + 2592, 1018, -1000, -1000, -1000, -1000, 52828, -1000, -1000, -1000, + 30685, 861, -376, -1000, 390, -1000, 463, 2586, -1000, -1000, + 52828, 2222, 576, 2222, 659, 52828, -328, -1000, -157, 1160, + 5811, 915, 2920, 2818, 1260, -1000, -1000, -1000, -1000, 2920, + -1000, 2585, 190, -1000, -1000, -1000, -1000, 2259, -1000, -1000, + 2253, 1650, 213, -1000, -1000, -1000, -1000, -1000, -1000, 2360, + 52828, 40079, 2361, 1916, -379, -1000, 3094, -1000, 1884, 1884, + 1884, 861, 52828, 1570, -1000, 1884, 1884, 2817, -1000, -1000, + 861, 2816, 2812, 3789, 779, 1867, 1865, -1000, 2250, 1075, + -243, -1000, 1184, -1000, 30014, 39408, 38737, 1283, -1000, 1568, + -1000, -1000, -1000, -1000, -1000, 3735, 779, -1000, 519, 2248, + 15181, 3093, 15181, 3076, 549, 3069, 1543, -1000, 52828, -1000, + -1000, 52828, 399, 3066, -1000, 3065, 3354, 498, 3063, 3061, + 52828, 2822, -1000, 3485, 52828, 734, 3517, -1000, 356, -1000, + -1000, -1000, -1000, -1000, -1000, 564, -1000, 52828, -1000, 52828, + -1000, 1750, -1000, 28672, -1000, -1000, 1541, -1000, 2575, 2574, + -1000, -1000, -1000, 190, 2569, 7077, -1000, -1000, -1000, -1000, + -1000, 3465, 2568, 2360, 52828, -1000, 52828, 1190, 1190, 3797, + 52828, 9783, -1000, -1000, 12485, 3059, -1000, 12485, -1000, -1000, + -1000, 2809, -1000, -1000, -1000, -1000, -1000, 3058, 3489, -1000, + -1000, -1000, -1000, -1000, -1000, 3768, -1000, 2293, -1000, 12485, + 13159, -1000, 823, 16539, -283, 293, -1000, -1000, -1000, -251, + 2565, -1000, -1000, 3708, 2559, 2394, -1000, 33, 2537, -1000, + 12485, -1000, -1000, -1000, 1184, -1000, 1226, -1000, -1000, 1147, + 632, -1000, 2805, 1969, -1000, 2624, -1000, 2530, 2525, 115, + -1000, 115, -1000, 238, 12485, -1000, 2509, -1000, 2470, -1000, + -1000, 2536, -1000, -1000, -1000, 2528, -1000, -1000, 2405, -1000, + 2794, -1000, 2526, -1000, -1000, 2519, -1000, -1000, 342, 861, + 52828, 2518, 2245, -1000, -1000, 468, -381, -1000, 2516, 2222, + 2515, 2222, 52828, 566, -1000, 2514, 2511, -1000, -1000, 5811, + 3786, 3789, 19916, 3786, -1000, -1000, 3686, 335, -1000, -1000, + 2247, 619, -1000, -1000, 2507, 563, -1000, 1190, -1000, 1915, + 2164, 2437, 36053, 28672, 29343, 2505, -1000, -1000, -1000, 38066, + 2293, 2293, 5835, -1000, 300, 58147, -1000, 3057, 1118, 1857, + -1000, 2243, -1000, 2241, -1000, 52828, -1000, 1184, 3735, 1283, + 120, -1000, -1000, 1805, -1000, 1118, 2440, 3707, -1000, 4490, + 52828, 4422, 52828, 3055, 1909, 15181, -1000, 720, 3447, -1000, + -1000, 399, -1000, -1000, 2127, 15181, -1000, -1000, 2502, 29343, + 879, 1906, 1904, 912, 3051, -1000, 587, 3765, -1000, -1000, + -1000, 1004, 3048, -1000, 2089, 2088, -1000, 52828, -1000, 36053, + 36053, 857, 857, 36053, 36053, 3040, 760, -1000, -1000, 15181, + -1000, -1000, -1000, 1903, 3562, -1000, -1000, -1000, 1884, 1672, + -1000, -1000, -1000, -1000, -1000, -1000, 2361, -1000, -1000, 1169, + -1000, 3675, -1000, -1000, 2608, 52828, 2608, -1000, 37395, -1000, + 3706, 3704, -1000, -1000, 2608, 1314, 261, 3037, 3035, -1000, + -359, 52828, 52828, -253, 2236, -1000, 2498, 152, -1000, -1000, + 142, -1000, 1167, -255, 43, 28672, 1901, -1000, 2788, 348, + -161, -1000, -1000, -1000, -1000, -1000, 2776, -1000, 759, -1000, + -1000, -1000, 1167, 115, 115, 2613, 2535, -1000, -1000, -1000, + -1000, 52828, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2416, + -328, 2497, -328, 2486, 562, 2222, -1000, -1000, -158, -1000, + -1000, 395, -1000, -1000, -1000, 607, 2374, -1000, -1000, 326, + -1000, -1000, -1000, 2360, 2485, -1000, -1000, 101, -1000, 1900, + 1540, -1000, -1000, -1000, -1000, -1000, -1000, 714, -1000, 2920, + 5923, -1000, 1137, -1000, 1147, 714, 34711, 618, 1998, -1000, + 2234, -1000, -1000, 1152, 3797, -1000, 598, -1000, 545, -1000, + 1500, -1000, 1495, 36724, 2233, 4378, -1000, 58066, 826, -1000, + -1000, 4586, -1000, -1000, -1000, -1000, -1000, -1000, 2483, 2482, + -1000, -1000, -1000, -1000, -1000, 2224, 3034, -80, 3598, 2479, + -1000, -1000, 3031, 1487, 1483, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1477, 1476, 36053, -1000, -1000, + 4586, 3562, 2139, -1000, 1884, 1884, 2477, 2474, 417, -1000, + -1000, 1884, 1884, 1884, -1000, -1000, 1899, 1884, 1884, 28672, + 1884, -1000, -1000, 1461, 1433, -1000, -1000, -1000, -1000, -1000, + -337, 3030, 12485, 12485, -1000, -1000, -1000, 3025, -1000, -1000, + 3701, -249, -258, 2467, 127, 143, -1000, 2464, -1000, -159, + 3441, -165, -1000, -1000, 685, -244, 105, 102, 78, -1000, + -1000, -1000, 12485, -1000, -1000, -1000, -1000, -1000, 99, -1000, + 1893, -1000, -328, -1000, -328, 2222, 2439, 52828, 585, -1000, + -1000, -1000, -1000, 183, -1000, -1000, -1000, -1000, -1000, -1000, + 2437, 2436, -1000, 508, 3698, -1000, 58147, -1000, 1884, -1000, + 508, 1432, -1000, 1884, 1884, -1000, 451, -1000, 1836, -1000, + 2209, -1000, 3675, -1000, 428, -1000, 517, -1000, -1000, -1000, + 1422, -1000, -1000, -1000, 58066, 528, -1000, 679, 3024, -1000, + -1000, 2504, 12485, 3020, 1884, 2410, -150, 36053, 3342, 3283, + 3149, 2517, 1419, -1000, -1000, 2207, 2205, -1000, -1000, 52828, + 2196, 2195, 2191, 2136, 2175, 2165, -1000, 28672, -1000, -1000, + 35382, -1000, 3018, 1411, 1401, 52828, 2394, -251, -1000, 2433, + -1000, 843, 130, 143, -1000, 3697, 149, 3696, 3694, 1151, + 3440, -1000, -1000, 2081, -1000, 93, 90, 86, -1000, -1000, + -1000, -1000, -328, 2416, 2409, -1000, -1000, 2408, -328, 567, + -1000, 255, -1000, -1000, -1000, 3562, -1000, 3683, 543, -1000, + 28672, -1000, -1000, 34711, 2293, 2293, -1000, -1000, 2155, -1000, + -1000, -1000, -1000, 2153, -1000, -1000, -1000, 1367, -1000, 52828, + 957, 9109, -1000, 2373, -1000, 52828, -1000, 3374, -1000, 221, + 1357, 3562, 857, 3562, 857, 3562, 857, 3562, 857, 249, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 52564, 1770, -1000, 2020, 2618, - 337, 2428, 31124, 2019, 1817, 2617, 2614, 590, -1000, 2605, - 2604, -1000, 2166, 2016, 907, 52564, -1000, 1188, 52564, 52564, - -1000, 1415, -1000, 2015, 3436, 3466, 3436, -1000, 3436, -1000, - -1000, -1000, -1000, 3365, 2594, -1000, 3352, -1000, 2739, -1000, - -1000, -1000, -1000, 1415, -1000, -1000, -1000, -1000, -1000, 1084, - -1000, 3707, 1040, 1040, 1040, 2865, -1000, -1000, -1000, -1000, - 1290, 2864, -1000, -1000, 3704, -1000, -1000, -1000, -1000, -1000, - -1000, 19031, 3591, 3779, 3760, 40504, -1000, -366, 1783, -1000, - 2201, 191, 2163, 52564, -1000, -1000, -1000, 2863, 2857, -257, - 115, 3759, 3758, 3704, -274, 2592, 294, -1000, -1000, 3581, - -1000, 2854, 1270, -250, -1000, -1000, 1184, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -399, -1000, -1000, 337, -1000, 1410, - -1000, -1000, -1000, -1000, -1000, -1000, 189, -1000, 52564, -1000, - 1258, 101, -1000, 2612, -1000, 5080, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 2583, -1000, -1000, 12281, - -1000, -1000, -1000, 2616, -1000, -1000, 12281, 12281, -1000, 2853, - 2581, 2851, 2568, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 3810, -1000, 3757, 80, 12281, 80, 12281, 80, 1769, 2850, - 2849, 1735, 2847, 2845, -1000, 12281, 2844, 5308, 1016, 2564, - 1016, -1000, -1000, -1000, -1000, 52564, -1000, -1000, -1000, 30454, - 838, -380, -1000, 389, -1000, 477, 2561, -1000, -1000, 52564, - 2293, 584, 2293, 667, 52564, -329, -1000, -146, 1246, 5769, - 921, 2958, 2843, 1231, -1000, -1000, -1000, -1000, 2958, -1000, - 2560, 202, -1000, -1000, -1000, -1000, 2336, -1000, -1000, 2302, - 1598, 222, -1000, -1000, -1000, -1000, -1000, -1000, 2301, 52564, - 39834, 2386, 2003, -383, -1000, 3158, -1000, 1819, 1819, 1819, - 838, 52564, 1722, -1000, 1819, 1819, 2841, -1000, -1000, 838, - 2839, 2822, 3813, 765, 1974, 1878, -1000, 2334, 1099, -250, - -1000, 1184, -1000, 29784, 39164, 38494, 1386, -1000, 1569, -1000, - -1000, -1000, -1000, -1000, 3784, 765, -1000, 527, 2330, 14973, - 3150, 14973, 3149, 547, 3142, 1718, -1000, 52564, -1000, -1000, - 52564, 4065, 3141, -1000, 3140, 3446, 509, 3114, 3105, 52564, - 2585, -1000, 3574, 52564, 777, 3590, -1000, 376, -1000, -1000, - -1000, -1000, -1000, -1000, 589, -1000, 52564, -1000, 52564, -1000, - 1672, -1000, 28444, -1000, -1000, 1667, -1000, 2558, 2554, -1000, - -1000, -1000, 202, 2553, 6881, -1000, -1000, -1000, -1000, -1000, - 3558, 2546, 2301, 52564, -1000, 52564, 1188, 1188, 3810, 52564, - 9583, -1000, -1000, 12281, 3104, -1000, 12281, -1000, -1000, -1000, - 2817, -1000, -1000, -1000, -1000, -1000, 3102, 3588, -1000, -1000, - -1000, -1000, -1000, -1000, 3807, -1000, 1977, -1000, 12281, 12954, - -1000, 812, 16329, -287, 327, -1000, -1000, -1000, -259, 2535, - -1000, -1000, 3756, 2532, 2448, -1000, -10, 2531, -1000, 12281, - -1000, -1000, -1000, 1184, -1000, 1218, -1000, -1000, 1073, 632, - -1000, 2816, 2066, -1000, 2578, -1000, 2574, 2562, 80, -1000, - 80, -1000, 218, 12281, -1000, 2527, -1000, 2469, -1000, -1000, - 2529, -1000, -1000, -1000, 2525, -1000, -1000, 2404, -1000, 2815, - -1000, 2521, -1000, -1000, 2520, -1000, -1000, 368, 838, 52564, - 2519, 2327, -1000, 524, -385, -1000, 2515, 2293, 2514, 2293, - 52564, 581, -1000, 2512, 2511, -1000, -1000, 5769, 3812, 3813, - 19701, 3812, -1000, -1000, 3731, 362, -1000, -1000, 2268, 633, - -1000, -1000, 2510, 573, -1000, 1188, -1000, 1995, 2227, 2478, - 35814, 28444, 29114, 2508, -1000, -1000, -1000, 37824, 1977, 1977, - 57937, -1000, 247, 58086, -1000, 3101, 1114, 1826, -1000, 2326, - -1000, 2325, -1000, 52564, -1000, 1184, 3784, 1386, 123, -1000, - -1000, 1739, -1000, 1114, 2584, 3752, -1000, 4431, 52564, 4216, - 52564, 3097, 1993, 14973, -1000, 773, 3519, -1000, -1000, 4065, - -1000, -1000, 2154, 14973, -1000, -1000, 2507, 29114, 897, 1971, - 1866, 904, 3096, -1000, 600, 3806, -1000, -1000, -1000, 970, - 3092, -1000, 2125, 2117, -1000, 52564, -1000, 35814, 35814, 864, - 864, 35814, 35814, 3078, 764, -1000, -1000, 14973, -1000, -1000, - -1000, 1851, 809, -1000, -1000, -1000, 1819, 1670, -1000, -1000, - -1000, -1000, -1000, -1000, 2386, -1000, -1000, 1178, -1000, 3718, - -1000, -1000, 2612, 52564, 2612, -1000, 37154, -1000, 3749, 3748, - -1000, -1000, 2612, 1299, 256, 3077, 3075, -1000, -366, 52564, - 52564, -267, 2322, -1000, 2505, 109, -1000, -1000, 94, -1000, - 1175, -269, 25, 28444, 1850, -1000, 2814, 354, -160, -1000, - -1000, -1000, -1000, -1000, 2812, -1000, 1079, -1000, -1000, -1000, - 1175, 80, 80, 2811, 2809, -1000, -1000, -1000, -1000, 52564, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2466, -329, 2504, - -329, 2503, 577, 2293, -1000, -1000, -149, -1000, -1000, 398, - -1000, -1000, -1000, 617, 2436, -1000, -1000, 360, -1000, -1000, - -1000, 2301, 2501, -1000, -1000, 100, -1000, 1841, 1659, -1000, - -1000, -1000, -1000, -1000, -1000, 763, -1000, 2958, 57740, -1000, - 1385, -1000, 1073, 763, 34474, 669, 1925, -1000, 2320, -1000, - -1000, 1172, 3810, -1000, 644, -1000, 544, -1000, 1652, -1000, - 1626, 36484, 2314, 3799, -1000, 57986, 916, -1000, -1000, 4748, - -1000, -1000, -1000, -1000, -1000, -1000, 2500, 2499, -1000, -1000, - -1000, -1000, -1000, 2304, 3073, -64, 3671, 2496, -1000, -1000, - 3072, 1622, 1597, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 1578, 1508, 35814, -1000, -1000, 4748, 809, - 2217, -1000, 1819, 1819, 2495, 2488, 438, -1000, -1000, 1819, - 1819, 1819, -1000, -1000, 1838, 1819, 1819, 28444, 1819, -1000, - -1000, 1507, 1494, -1000, -1000, -1000, -1000, -1000, -346, 3071, - 12281, 12281, -1000, -1000, -1000, 3065, -1000, -1000, 3747, -257, - -271, 2487, 90, 119, -1000, 2484, -1000, -150, 3280, -165, - -1000, -1000, 720, -252, 74, 68, 64, -1000, -1000, -1000, - 12281, -1000, -1000, -1000, -1000, -1000, 99, -1000, 1836, -1000, - -329, -1000, -329, 2293, 2482, 52564, 596, -1000, -1000, -1000, - -1000, 182, -1000, -1000, -1000, -1000, -1000, -1000, 2478, 2476, - -1000, 520, 3746, -1000, 58086, -1000, 1819, -1000, 520, 1491, - -1000, 1819, 1819, -1000, 466, -1000, 1804, -1000, 2292, -1000, - 3718, -1000, 458, -1000, 522, -1000, -1000, -1000, 1489, -1000, - -1000, -1000, 57986, 528, -1000, 751, 3064, -1000, -1000, 2808, - 12281, 3058, 1819, 2800, -136, 35814, 3439, 3438, 3432, 2620, - 1482, -1000, -1000, 2291, 2274, -1000, -1000, 52564, 2273, 2269, - 2247, 2211, 2235, 2226, -1000, 28444, -1000, -1000, 35144, -1000, - 3057, 1476, 1381, 52564, 2448, -259, -1000, 2473, -1000, 829, - 93, 119, -1000, 3745, 102, 3743, 3742, 1156, 3185, -1000, - -1000, 2104, -1000, 76, 60, 58, -1000, -1000, -1000, -1000, - -329, 2466, 2458, -1000, -1000, 2457, -329, 537, -1000, 278, - -1000, -1000, -1000, 809, -1000, 3741, 575, -1000, 28444, -1000, - -1000, 34474, 1977, 1977, -1000, -1000, 2221, -1000, -1000, -1000, - -1000, 2219, -1000, -1000, -1000, 1380, -1000, 52564, 971, 8910, - -1000, 2157, -1000, 52564, -1000, 3463, -1000, 211, 1367, 809, - 864, 809, 864, 809, 864, 809, 864, 292, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 1366, 12281, -1000, -1000, 1356, -1000, -1000, -267, -1000, - 3056, 2167, 115, 103, 3732, -1000, 2448, 3729, 2448, 2448, - -1000, 83, 3811, 720, -1000, -1000, -1000, -1000, -1000, -1000, - -329, -1000, 2456, -1000, -1000, -1000, 33804, 541, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 528, 58086, -1000, 8910, 1315, - -1000, 2612, -1000, 764, -1000, -1000, 3458, 3282, 3788, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 2856, - 2694, -1000, 52564, -1000, 3669, 27774, 108, -1000, -1000, -1000, - 2454, -1000, 2448, -1000, -1000, 1818, -162, -1000, -1000, -305, - -1000, 52564, 527, -1000, 58086, 1227, -1000, 8910, -1000, -1000, - 3790, -1000, 3804, 883, 883, 809, 809, 809, 809, 12281, - -1000, -1000, -1000, 52564, -1000, 1216, -1000, -1000, -1000, 1562, - -1000, -1000, -1000, -1000, 2441, -167, -1000, -1000, 2433, 1211, - 2584, -1000, -1000, -1000, -1000, -1000, 2262, 602, -1000, 2579, - 1154, -1000, 1794, -1000, 33134, 52564, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 52564, 8237, -1000, 1149, -1000, - -1000, 2612, 52564, -1000, + -1000, -1000, -1000, 1355, 12485, -1000, -1000, 1352, -1000, -1000, + -253, -1000, 3014, 2134, 158, 111, 3680, -1000, 2394, 3678, + 2394, 2394, -1000, 110, 3783, 685, -1000, -1000, -1000, -1000, + -1000, -1000, -328, -1000, 2407, -1000, -1000, -1000, 34040, 530, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 528, 58147, -1000, + 9109, 1300, -1000, 2608, -1000, 760, -1000, -1000, 3371, 3370, + 3740, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 2645, 2395, -1000, 52828, -1000, 3590, 28001, 123, -1000, + -1000, -1000, 2399, -1000, 2394, -1000, -1000, 1866, -163, -1000, + -1000, -307, -1000, 52828, 519, -1000, 58147, 1286, -1000, 9109, + -1000, -1000, 3764, -1000, 3741, 882, 882, 3562, 3562, 3562, + 3562, 12485, -1000, -1000, -1000, 52828, -1000, 1235, -1000, -1000, + -1000, 1567, -1000, -1000, -1000, -1000, 2391, -166, -1000, -1000, + 2384, 1219, 2440, -1000, -1000, -1000, -1000, -1000, 2197, 593, + -1000, 2387, 1143, -1000, 1842, -1000, 33369, 52828, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 52828, 8435, -1000, + 1566, -1000, -1000, 2608, 52828, -1000, } var yyPgo = [...]int{ - 0, 188, 3838, 251, 186, 4445, 114, 261, 297, 3615, - 287, 259, 258, 4443, 4442, 4433, 3610, 3607, 4427, 4426, - 4425, 4424, 4423, 4421, 4420, 4419, 4417, 4416, 4415, 4414, - 4413, 4412, 4410, 4409, 4408, 4407, 4405, 4404, 4402, 4401, - 4399, 4398, 4397, 4396, 4390, 4389, 4388, 4387, 249, 4386, - 4385, 4378, 4377, 4376, 4375, 4374, 4373, 4357, 4356, 4354, - 4353, 4352, 4351, 4349, 4348, 4347, 4346, 4345, 4344, 4342, - 4341, 4340, 4339, 4336, 4335, 4334, 4332, 4330, 4327, 4324, - 4323, 4322, 4319, 4318, 4317, 4315, 265, 4314, 3579, 4313, - 4312, 4311, 4310, 4309, 4308, 4307, 4306, 4304, 4302, 4301, - 4300, 280, 4299, 4297, 4296, 4294, 4293, 4291, 4288, 4286, - 4284, 4282, 4281, 4280, 4279, 308, 4278, 4271, 4270, 4269, - 224, 4268, 244, 4267, 184, 146, 4266, 4265, 4264, 4263, - 4262, 4261, 4260, 4258, 4257, 4255, 4254, 4249, 4248, 4244, - 248, 170, 68, 4243, 54, 4242, 264, 212, 4240, 225, - 4239, 152, 4237, 148, 4236, 4235, 4234, 4233, 4232, 4231, - 4229, 4228, 4224, 4223, 4222, 4221, 4220, 4216, 4213, 4212, - 4211, 4208, 4205, 4203, 4202, 4201, 4200, 4199, 4198, 55, - 4197, 266, 4195, 82, 4193, 182, 4189, 80, 4187, 4186, - 98, 4183, 4182, 52, 145, 267, 1802, 272, 4181, 198, - 4178, 4175, 250, 180, 4172, 4171, 260, 4170, 191, 232, - 164, 109, 124, 4168, 161, 4164, 262, 47, 46, 247, - 197, 147, 4162, 4160, 59, 169, 149, 4159, 213, 102, - 4157, 4156, 113, 4155, 4153, 106, 4152, 246, 190, 4151, - 107, 4149, 4147, 4146, 19, 4145, 4143, 211, 199, 4142, - 4141, 103, 4140, 4139, 97, 134, 4138, 81, 137, 172, - 136, 4137, 2853, 132, 85, 4135, 123, 111, 4124, 110, - 4123, 4122, 4119, 4118, 194, 4117, 4116, 135, 66, 4115, - 4114, 4113, 77, 4111, 86, 4110, 36, 4108, 62, 4107, - 4105, 4104, 4103, 4102, 4101, 4100, 4099, 4098, 4097, 4096, - 4094, 35, 4093, 4091, 4086, 4085, 7, 13, 15, 4083, - 28, 4082, 173, 4081, 4078, 167, 4075, 203, 4074, 4073, - 99, 92, 4072, 94, 4071, 176, 4070, 14, 29, 78, - 4069, 4067, 4066, 1951, 4065, 4064, 4063, 314, 4062, 4061, - 4059, 163, 4058, 4055, 4054, 441, 4053, 4052, 4051, 4050, - 4049, 4048, 162, 4045, 1, 222, 25, 4044, 133, 141, - 4043, 38, 32, 4042, 53, 139, 209, 138, 104, 4040, - 4039, 4037, 748, 204, 96, 44, 0, 101, 226, 160, - 4035, 4033, 4032, 263, 4031, 237, 207, 238, 243, 268, - 183, 4030, 4028, 61, 4027, 166, 33, 58, 151, 93, - 22, 465, 4025, 909, 9, 201, 4022, 218, 4021, 8, - 17, 72, 156, 4020, 4017, 40, 277, 4016, 4015, 4014, - 142, 4013, 4011, 128, 73, 4007, 4006, 4005, 4004, 4002, - 50, 4001, 181, 30, 4000, 118, 3999, 256, 125, 242, - 165, 193, 189, 159, 227, 235, 84, 71, 3998, 1857, - 144, 115, 16, 3997, 228, 3994, 276, 130, 3993, 91, - 3992, 245, 269, 220, 3991, 195, 11, 49, 41, 31, - 51, 12, 217, 120, 3990, 3989, 23, 57, 3988, 56, - 3987, 20, 3986, 3985, 42, 3984, 64, 5, 3983, 3981, - 18, 21, 3980, 37, 214, 179, 129, 100, 70, 3979, - 3978, 155, 192, 3977, 157, 168, 154, 3976, 43, 3975, - 3973, 3972, 3970, 804, 257, 3969, 3968, 3967, 3965, 3964, - 3963, 3962, 3961, 206, 3960, 140, 45, 3959, 3957, 3956, - 3939, 117, 153, 3936, 3935, 3934, 3933, 39, 83, 3932, - 10, 3931, 26, 24, 34, 3930, 63, 3928, 3927, 3926, - 3, 196, 3925, 3924, 4, 3923, 3922, 2, 3921, 3920, - 126, 3919, 95, 27, 177, 112, 3917, 3915, 90, 210, - 150, 3914, 3911, 105, 255, 3909, 215, 3908, 178, 236, - 253, 3905, 221, 3902, 3901, 3899, 3898, 3897, 1226, 3896, - 3895, 241, 67, 89, 3894, 223, 122, 3893, 3892, 88, - 171, 121, 116, 60, 87, 3891, 119, 219, 3889, 208, - 3885, 252, 3882, 3873, 108, 3871, 3870, 3869, 3868, 200, - 3866, 3865, 202, 230, 3864, 3862, 309, 3861, 3860, 3859, - 3858, 3857, 3854, 3853, 3852, 3850, 3842, 239, 271, 3840, + 0, 183, 3814, 256, 185, 4413, 146, 262, 280, 3542, + 265, 261, 254, 4412, 4411, 4409, 3534, 3532, 4408, 4406, + 4405, 4403, 4402, 4400, 4399, 4398, 4397, 4396, 4395, 4389, + 4388, 4387, 4386, 4384, 4383, 4382, 4380, 4379, 4378, 4362, + 4357, 4356, 4355, 4354, 4353, 4352, 4351, 4349, 249, 4348, + 4347, 4346, 4344, 4342, 4338, 4337, 4336, 4335, 4334, 4333, + 4332, 4329, 4326, 4325, 4324, 4323, 4322, 4321, 4320, 4319, + 4317, 4316, 4315, 4314, 4312, 4311, 4310, 4309, 4308, 4307, + 4306, 4305, 4304, 4303, 4302, 4301, 227, 4299, 3522, 4298, + 4296, 4295, 4293, 4292, 4291, 4288, 4287, 4286, 4277, 4276, + 4275, 324, 4273, 4272, 4271, 4270, 4269, 4268, 4267, 4266, + 4265, 4264, 4263, 4262, 4260, 313, 4259, 4257, 4253, 4252, + 236, 4250, 296, 4249, 180, 161, 4245, 4244, 4243, 4242, + 4239, 4237, 4236, 4235, 4234, 4233, 4232, 4231, 4230, 4229, + 251, 171, 68, 4226, 55, 4225, 248, 217, 4224, 228, + 4223, 151, 4222, 154, 4221, 4213, 4211, 4210, 4209, 4208, + 4206, 4204, 4203, 4202, 4201, 4200, 4199, 4197, 4195, 4191, + 4189, 4188, 4187, 4186, 4185, 4184, 4183, 4182, 4179, 53, + 4176, 270, 4175, 80, 4173, 182, 4172, 78, 4171, 4169, + 89, 4168, 4167, 59, 145, 264, 2113, 263, 4165, 198, + 4164, 4162, 253, 173, 4161, 4160, 267, 4158, 163, 237, + 157, 113, 125, 4157, 144, 4154, 272, 49, 46, 268, + 197, 142, 4152, 4151, 60, 184, 149, 4149, 211, 100, + 4148, 4147, 109, 4146, 4143, 106, 4142, 247, 191, 4141, + 107, 4140, 4139, 4137, 25, 4136, 4135, 216, 202, 4130, + 4124, 102, 4123, 4122, 73, 137, 4119, 82, 136, 169, + 130, 4118, 2963, 128, 86, 4117, 127, 110, 4116, 112, + 4115, 4114, 4112, 4111, 195, 4110, 4109, 152, 66, 4107, + 4106, 4105, 77, 4104, 84, 4103, 35, 4102, 62, 4101, + 4099, 4098, 4097, 4096, 4090, 4089, 4088, 4087, 4085, 4084, + 4082, 32, 4080, 4077, 4076, 4075, 7, 14, 17, 4074, + 28, 4073, 172, 4072, 4071, 166, 4068, 203, 4067, 4066, + 99, 92, 4065, 94, 4064, 167, 4063, 12, 29, 72, + 4062, 4061, 4059, 310, 4056, 4055, 4054, 319, 4053, 4052, + 4050, 160, 4049, 4047, 4045, 719, 4044, 4043, 4042, 4041, + 4039, 4037, 162, 4034, 1, 223, 26, 4033, 138, 132, + 4032, 40, 31, 4031, 51, 114, 208, 129, 104, 4030, + 4027, 4026, 746, 207, 97, 43, 0, 101, 230, 156, + 4023, 4022, 4021, 259, 4019, 238, 212, 239, 294, 266, + 209, 4002, 4001, 63, 4000, 164, 45, 56, 141, 93, + 21, 269, 3999, 909, 10, 201, 3997, 221, 3995, 8, + 16, 71, 150, 3994, 3993, 37, 271, 3992, 3991, 3990, + 133, 3989, 3988, 189, 105, 3987, 3986, 3985, 3984, 3982, + 50, 3981, 190, 33, 3980, 139, 3979, 258, 117, 188, + 135, 192, 187, 155, 225, 232, 83, 81, 3977, 1942, + 147, 115, 15, 3976, 226, 3974, 194, 122, 3973, 91, + 3972, 245, 276, 220, 3971, 196, 11, 52, 39, 30, + 47, 9, 309, 118, 3966, 3965, 22, 54, 3964, 57, + 3963, 20, 3962, 3961, 42, 3960, 64, 5, 3959, 3958, + 19, 18, 3957, 38, 214, 177, 121, 98, 70, 3955, + 3954, 159, 193, 3953, 179, 176, 168, 3952, 41, 3945, + 3939, 3938, 3937, 806, 257, 3936, 3935, 3934, 3932, 3931, + 3928, 3927, 3926, 210, 3925, 140, 44, 3924, 3923, 3922, + 3921, 116, 153, 3920, 3919, 3917, 3915, 34, 85, 3911, + 13, 3907, 23, 24, 36, 3905, 58, 3903, 3902, 3901, + 3, 199, 3900, 3899, 4, 3898, 3897, 2, 3896, 3895, + 126, 3894, 95, 27, 170, 111, 3893, 3892, 90, 213, + 148, 3891, 3889, 103, 255, 3884, 218, 3875, 178, 244, + 260, 3873, 222, 3872, 3870, 3868, 3867, 3866, 1241, 3865, + 3864, 243, 67, 96, 3862, 224, 120, 3861, 3860, 88, + 165, 124, 123, 61, 87, 3859, 119, 219, 3856, 204, + 3855, 250, 3854, 3853, 108, 3852, 3851, 3850, 3848, 200, + 3847, 3846, 206, 235, 3844, 3842, 317, 3841, 3840, 3837, + 3830, 3828, 3826, 3820, 3817, 3816, 3812, 241, 246, 3809, } -//line mysql_sql.y:13577 +//line mysql_sql.y:13584 type yySymType struct { union interface{} id int @@ -9400,79 +9408,79 @@ var yyR1 = [...]int{ 185, 185, 426, 426, 423, 423, 244, 244, 421, 421, 422, 422, 420, 420, 420, 424, 424, 44, 79, 45, 46, 47, 43, 425, 425, 189, 189, 189, 189, 189, - 189, 192, 192, 192, 192, 192, 191, 191, 191, 191, - 190, 190, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 143, 142, 142, 142, 142, 142, 145, - 145, 359, 359, 358, 358, 144, 298, 298, 42, 276, - 276, 500, 500, 495, 495, 495, 495, 495, 515, 515, - 515, 496, 496, 496, 497, 497, 497, 499, 499, 499, - 498, 498, 498, 498, 498, 514, 514, 516, 516, 516, - 467, 467, 468, 468, 468, 471, 471, 487, 487, 488, - 488, 486, 486, 493, 493, 492, 492, 491, 491, 490, - 490, 489, 489, 489, 489, 482, 482, 481, 481, 469, - 469, 469, 469, 469, 470, 470, 470, 480, 480, 485, - 485, 330, 330, 329, 329, 284, 284, 285, 285, 328, - 328, 282, 282, 283, 283, 283, 327, 327, 327, 327, + 189, 192, 192, 192, 192, 192, 192, 191, 191, 191, + 191, 190, 190, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 143, 142, 142, 142, 142, 142, + 145, 145, 359, 359, 358, 358, 144, 298, 298, 42, + 276, 276, 500, 500, 495, 495, 495, 495, 495, 515, + 515, 515, 496, 496, 496, 497, 497, 497, 499, 499, + 499, 498, 498, 498, 498, 498, 514, 514, 516, 516, + 516, 467, 467, 468, 468, 468, 471, 471, 487, 487, + 488, 488, 486, 486, 493, 493, 492, 492, 491, 491, + 490, 490, 489, 489, 489, 489, 482, 482, 481, 481, + 469, 469, 469, 469, 469, 470, 470, 470, 480, 480, + 485, 485, 330, 330, 329, 329, 284, 284, 285, 285, + 328, 328, 282, 282, 283, 283, 283, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, 327, - 327, 567, 567, 568, 287, 287, 299, 299, 299, 299, - 299, 299, 286, 286, 288, 288, 264, 264, 262, 262, - 254, 254, 254, 254, 254, 254, 255, 255, 256, 256, - 257, 257, 257, 261, 261, 260, 260, 260, 260, 258, - 258, 259, 259, 259, 259, 259, 259, 453, 453, 564, - 564, 565, 565, 560, 560, 560, 563, 563, 563, 563, - 563, 563, 563, 563, 566, 566, 566, 562, 562, 266, - 353, 353, 353, 376, 376, 376, 376, 378, 352, 352, - 352, 281, 281, 280, 280, 278, 278, 278, 278, 278, + 327, 327, 567, 567, 568, 287, 287, 299, 299, 299, + 299, 299, 299, 286, 286, 288, 288, 264, 264, 262, + 262, 254, 254, 254, 254, 254, 254, 255, 255, 256, + 256, 257, 257, 257, 261, 261, 260, 260, 260, 260, + 258, 258, 259, 259, 259, 259, 259, 259, 453, 453, + 564, 564, 565, 565, 560, 560, 560, 563, 563, 563, + 563, 563, 563, 563, 563, 566, 566, 566, 562, 562, + 266, 353, 353, 353, 376, 376, 376, 376, 378, 352, + 352, 352, 281, 281, 280, 280, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - 278, 278, 278, 278, 278, 278, 278, 452, 452, 392, - 392, 393, 393, 310, 309, 309, 309, 309, 309, 307, - 308, 306, 306, 306, 306, 306, 303, 303, 302, 302, - 302, 304, 304, 304, 304, 304, 431, 431, 300, 300, - 290, 290, 290, 289, 289, 289, 494, 399, 399, 399, + 278, 278, 278, 278, 278, 278, 278, 278, 452, 452, + 392, 392, 393, 393, 310, 309, 309, 309, 309, 309, + 307, 308, 306, 306, 306, 306, 306, 303, 303, 302, + 302, 302, 304, 304, 304, 304, 304, 431, 431, 300, + 300, 290, 290, 290, 289, 289, 289, 494, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, - 399, 399, 401, 401, 401, 401, 401, 401, 401, 401, + 399, 399, 399, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, - 305, 350, 350, 350, 350, 350, 350, 350, 350, 350, - 350, 350, 350, 350, 350, 350, 351, 351, 351, 351, - 351, 351, 351, 351, 402, 402, 408, 408, 577, 577, - 576, 267, 267, 267, 268, 268, 268, 268, 268, 268, - 268, 268, 268, 277, 277, 277, 476, 476, 476, 476, - 477, 477, 477, 477, 478, 478, 478, 474, 474, 475, - 475, 413, 414, 414, 521, 521, 522, 522, 472, 472, - 473, 349, 349, 349, 349, 349, 349, 349, 349, 349, + 401, 305, 350, 350, 350, 350, 350, 350, 350, 350, + 350, 350, 350, 350, 350, 350, 350, 351, 351, 351, + 351, 351, 351, 351, 351, 402, 402, 408, 408, 577, + 577, 576, 267, 267, 267, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 277, 277, 277, 476, 476, 476, + 476, 477, 477, 477, 477, 478, 478, 478, 474, 474, + 475, 475, 413, 414, 414, 521, 521, 522, 522, 472, + 472, 473, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, 349, - 349, 349, 349, 349, 529, 529, 529, 346, 346, 346, + 349, 349, 349, 349, 349, 529, 529, 529, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 587, 587, 587, 572, 572, 572, 573, + 346, 346, 346, 346, 587, 587, 587, 572, 572, 572, 573, 573, 573, 573, 573, 573, 573, 573, 573, 573, - 573, 574, 574, 574, 574, 574, 574, 574, 574, 574, - 574, 574, 574, 574, 574, 574, 574, 574, 575, 575, - 575, 575, 348, 348, 348, 348, 348, 347, 347, 347, + 573, 573, 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, 574, 575, + 575, 575, 575, 348, 348, 348, 348, 348, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, 347, - 347, 347, 347, 347, 347, 415, 415, 416, 416, 526, - 526, 526, 526, 526, 526, 527, 527, 528, 528, 528, - 528, 520, 520, 520, 520, 520, 520, 520, 520, 520, + 347, 347, 347, 347, 347, 347, 415, 415, 416, 416, + 526, 526, 526, 526, 526, 526, 527, 527, 528, 528, + 528, 528, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, 520, - 520, 400, 345, 345, 345, 417, 409, 409, 410, 410, - 411, 411, 403, 403, 403, 403, 403, 403, 404, 404, - 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, - 406, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 405, 405, 407, 407, 419, 419, 419, 418, - 418, 418, 418, 418, 418, 418, 279, 279, 279, 279, - 397, 397, 397, 396, 396, 396, 396, 396, 396, 396, - 396, 396, 396, 396, 396, 269, 269, 269, 269, 273, - 273, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 274, 274, 274, 274, 274, - 272, 272, 272, 272, 272, 270, 270, 270, 270, 270, + 520, 520, 400, 345, 345, 345, 417, 409, 409, 410, + 410, 411, 411, 403, 403, 403, 403, 403, 403, 404, + 404, 406, 406, 406, 406, 406, 406, 406, 406, 406, + 406, 406, 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 405, 405, 407, 407, 419, 419, 419, + 418, 418, 418, 418, 418, 418, 418, 279, 279, 279, + 279, 397, 397, 397, 396, 396, 396, 396, 396, 396, + 396, 396, 396, 396, 396, 396, 269, 269, 269, 269, + 273, 273, 275, 275, 275, 275, 275, 275, 275, 275, + 275, 275, 275, 275, 275, 275, 274, 274, 274, 274, + 274, 272, 272, 272, 272, 272, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 123, 124, 124, 271, 355, 355, - 501, 501, 504, 504, 502, 502, 503, 505, 505, 505, - 506, 506, 506, 507, 507, 507, 511, 511, 364, 364, - 364, 372, 372, 371, 371, 371, 371, 371, 371, 371, + 270, 270, 270, 270, 270, 123, 124, 124, 271, 355, + 355, 501, 501, 504, 504, 502, 502, 503, 505, 505, + 505, 506, 506, 506, 507, 507, 507, 511, 511, 364, + 364, 364, 372, 372, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, @@ -9510,13 +9518,13 @@ var yyR1 = [...]int{ 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, - 371, 370, 370, 370, 370, 370, 370, 370, 370, 370, - 370, 369, 369, 369, 369, 369, 369, 369, 369, 369, + 371, 371, 371, 370, 370, 370, 370, 370, 370, 370, + 370, 370, 370, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, - 369, 369, 369, + 369, 369, 369, 369, 369, } var yyR2 = [...]int{ @@ -9644,79 +9652,79 @@ var yyR2 = [...]int{ 0, 4, 1, 1, 0, 3, 0, 1, 0, 1, 1, 2, 4, 4, 4, 0, 1, 8, 2, 4, 4, 4, 9, 0, 2, 8, 9, 5, 5, 7, - 7, 0, 3, 3, 3, 2, 0, 3, 3, 3, - 0, 3, 11, 9, 11, 8, 6, 9, 7, 10, - 7, 6, 8, 2, 2, 9, 4, 5, 3, 0, - 4, 1, 3, 0, 3, 6, 0, 2, 10, 0, - 2, 0, 2, 0, 3, 2, 4, 3, 0, 2, - 1, 0, 2, 3, 0, 2, 3, 0, 2, 1, - 0, 3, 2, 4, 3, 0, 1, 0, 1, 1, - 0, 6, 0, 3, 5, 0, 4, 0, 3, 1, - 3, 4, 5, 0, 3, 1, 3, 2, 3, 1, - 2, 0, 4, 6, 5, 0, 2, 0, 2, 4, - 5, 4, 5, 1, 5, 6, 5, 0, 3, 0, - 1, 1, 3, 3, 3, 0, 4, 1, 3, 3, - 3, 0, 1, 1, 3, 2, 3, 3, 3, 4, - 4, 3, 3, 3, 3, 4, 4, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 1, 5, - 4, 1, 3, 3, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 2, 4, - 0, 5, 5, 5, 5, 6, 0, 1, 1, 3, - 1, 1, 1, 1, 1, 7, 9, 7, 9, 2, - 1, 7, 9, 7, 9, 8, 5, 0, 1, 0, - 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 3, - 1, 3, 5, 1, 1, 1, 1, 1, 1, 3, - 5, 0, 1, 1, 2, 1, 2, 2, 1, 1, - 2, 2, 2, 3, 3, 2, 2, 1, 5, 6, - 4, 1, 1, 1, 5, 4, 1, 1, 2, 0, - 1, 1, 2, 5, 0, 1, 1, 2, 2, 3, - 3, 1, 1, 2, 2, 2, 0, 1, 2, 2, - 2, 0, 4, 7, 3, 3, 0, 3, 0, 3, - 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, + 7, 0, 3, 3, 3, 2, 2, 0, 3, 3, + 3, 0, 3, 11, 9, 11, 8, 6, 9, 7, + 10, 7, 6, 8, 2, 2, 9, 4, 5, 3, + 0, 4, 1, 3, 0, 3, 6, 0, 2, 10, + 0, 2, 0, 2, 0, 3, 2, 4, 3, 0, + 2, 1, 0, 2, 3, 0, 2, 3, 0, 2, + 1, 0, 3, 2, 4, 3, 0, 1, 0, 1, + 1, 0, 6, 0, 3, 5, 0, 4, 0, 3, + 1, 3, 4, 5, 0, 3, 1, 3, 2, 3, + 1, 2, 0, 4, 6, 5, 0, 2, 0, 2, + 4, 5, 4, 5, 1, 5, 6, 5, 0, 3, + 0, 1, 1, 3, 3, 3, 0, 4, 1, 3, + 3, 3, 0, 1, 1, 3, 2, 3, 3, 3, + 4, 4, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 3, 5, 2, 2, 2, - 2, 4, 1, 1, 2, 5, 6, 8, 6, 3, - 6, 6, 1, 1, 1, 1, 1, 1, 3, 9, - 1, 4, 4, 4, 4, 5, 4, 5, 7, 9, - 5, 7, 9, 5, 5, 7, 7, 9, 7, 7, - 7, 9, 7, 7, 0, 2, 0, 1, 1, 2, - 4, 1, 2, 2, 1, 2, 2, 1, 2, 2, - 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 1, 1, 1, 2, 5, 0, - 1, 3, 0, 1, 0, 2, 0, 2, 0, 1, - 6, 8, 8, 6, 6, 5, 5, 5, 6, 6, - 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 1, 1, 1, 4, 4, 6, - 8, 6, 4, 5, 4, 4, 4, 3, 4, 6, - 6, 7, 4, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 5, 4, 1, 3, 3, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 4, 0, 5, 5, 5, 5, 6, 0, 1, 1, + 3, 1, 1, 1, 1, 1, 7, 9, 7, 9, + 2, 1, 7, 9, 7, 9, 8, 5, 0, 1, + 0, 1, 1, 1, 1, 3, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, + 3, 1, 3, 5, 1, 1, 1, 1, 1, 1, + 3, 5, 0, 1, 1, 2, 1, 2, 2, 1, + 1, 2, 2, 2, 3, 3, 2, 2, 1, 5, + 6, 4, 1, 1, 1, 5, 4, 1, 1, 2, + 0, 1, 1, 2, 5, 0, 1, 1, 2, 2, + 3, 3, 1, 1, 2, 2, 2, 0, 1, 2, + 2, 2, 0, 4, 7, 3, 3, 0, 3, 0, + 3, 1, 1, 1, 1, 1, 1, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 3, 5, 2, 2, + 2, 2, 4, 1, 1, 2, 5, 6, 8, 6, + 3, 6, 6, 1, 1, 1, 1, 1, 1, 3, + 9, 1, 4, 4, 4, 4, 5, 4, 5, 7, + 9, 5, 7, 9, 5, 5, 7, 7, 9, 7, + 7, 7, 9, 7, 7, 0, 2, 0, 1, 1, + 2, 4, 1, 2, 2, 1, 2, 2, 1, 2, + 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 2, 5, + 0, 1, 3, 0, 1, 0, 2, 0, 2, 0, + 1, 6, 8, 8, 6, 6, 5, 5, 5, 6, + 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 1, 1, 1, 4, 4, + 6, 8, 6, 4, 5, 4, 4, 4, 3, 4, + 6, 6, 7, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 8, 8, 6, 4, 2, 3, - 2, 4, 2, 2, 4, 6, 2, 2, 4, 6, - 4, 2, 4, 4, 4, 0, 1, 2, 3, 1, - 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, + 1, 1, 1, 2, 2, 8, 8, 6, 4, 2, + 3, 2, 4, 2, 2, 4, 6, 2, 2, 4, + 6, 4, 2, 4, 4, 4, 0, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, - 1, 3, 3, 3, 3, 3, 2, 1, 1, 1, - 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, - 1, 3, 4, 4, 5, 4, 5, 3, 4, 5, - 6, 1, 0, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, + 3, 1, 3, 3, 3, 3, 3, 2, 1, 1, + 1, 3, 4, 3, 4, 3, 4, 3, 4, 3, + 4, 1, 3, 4, 4, 5, 4, 5, 3, 4, + 5, 6, 1, 0, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 1, 1, 1, 2, 3, 1, 1, 1, 2, + 1, 2, 1, 1, 1, 2, 3, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 4, 4, 1, 2, 3, 5, 1, 1, 3, - 0, 1, 0, 3, 0, 3, 3, 0, 3, 5, - 0, 3, 5, 0, 1, 1, 0, 1, 1, 2, - 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 4, 4, 1, 2, 3, 5, 1, 1, + 3, 0, 1, 0, 3, 0, 3, 3, 0, 3, + 5, 0, 3, 5, 0, 1, 1, 0, 1, 1, + 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -9760,17 +9768,17 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, + 1, 1, 1, 1, 1, } var yyChk = [...]int{ - -1000, -632, -635, -2, -5, 670, -1, -4, -124, -93, + -1000, -632, -635, -2, -5, 671, -1, -4, -124, -93, -7, -15, -126, -127, -8, -122, -10, -11, -169, -13, -100, -117, -119, -121, -120, -48, -12, -116, -86, -87, -102, -110, -113, -114, -115, -128, -123, -125, -193, -129, - -130, -131, -176, -134, -136, -137, -189, 660, -94, -95, + -130, -131, -176, -134, -136, -137, -189, 661, -94, -95, -96, -97, -98, -99, -34, -33, -32, -31, -161, -166, - -170, -172, -132, 584, 666, 487, -9, -578, 536, -16, + -170, -172, -132, 585, 667, 488, -9, -578, 537, -16, -17, -18, 253, 280, -380, -381, -382, -384, -636, -49, -50, -51, -61, -62, -63, -64, -65, -75, -76, -77, -52, -53, -54, -57, -55, -68, -67, -69, -70, -71, @@ -9778,427 +9786,427 @@ var yyChk = [...]int{ -59, -174, -177, -133, -80, -81, -82, -84, -83, -89, -85, -90, -163, -168, -14, -175, -91, -92, 254, -88, 79, -103, -104, -105, -106, -107, -108, -109, -111, -112, - 413, 419, 474, 659, 64, -194, -196, 689, 690, 693, - 572, 575, 298, 177, 178, 180, 181, 185, 188, -35, + 414, 420, 475, 660, 64, -194, -196, 690, 691, 694, + 573, 576, 298, 177, 178, 180, 181, 185, 188, -35, -36, -37, -38, -39, -40, -42, -41, -43, -44, -45, -46, -47, 249, 16, 14, 18, -19, -22, -20, -23, -21, -29, -30, -28, -25, -27, -162, -26, -167, -24, - -171, -173, -135, 275, 274, 41, 341, 342, 343, 417, - 273, 250, 252, 17, 34, 45, 392, -195, 88, 573, - 251, -197, 15, 695, -6, -3, -2, -148, -152, -156, - -159, -160, -157, -158, -4, -124, 123, 265, 661, -376, - 409, 662, 664, 663, 91, 99, -369, -371, 487, 280, - 413, 419, 659, 690, 693, 572, 575, 298, 586, 587, - 588, 589, 590, 591, 592, 593, 595, 596, 597, 598, - 599, 600, 601, 611, 612, 602, 603, 604, 605, 606, - 607, 608, 609, 613, 614, 615, 616, 617, 618, 619, - 620, 621, 622, 623, 624, 625, 626, 539, 540, 644, - 645, 646, 647, 648, 568, 594, 631, 639, 640, 641, - 390, 391, 577, 292, 316, 442, 322, 329, 386, 177, - 195, 191, 218, 209, 348, 347, 573, 186, 296, 334, - 297, 98, 180, 522, 113, 499, 471, 183, 353, 356, - 354, 355, 311, 313, 315, 569, 570, 403, 318, 567, - 317, 319, 321, 571, 352, 393, 205, 200, 310, 294, - 198, 299, 43, 300, 384, 383, 223, 301, 302, 581, - 495, 389, 501, 326, 55, 469, 199, 496, 314, 498, - 227, 231, 513, 374, 514, 168, 169, 503, 516, 222, - 225, 226, 272, 380, 381, 46, 579, 284, 517, 229, - 685, 221, 216, 525, 330, 328, 385, 220, 194, 215, - 295, 68, 233, 232, 234, 465, 466, 467, 468, 303, - 304, 407, 512, 212, 201, 394, 187, 25, 520, 279, - 500, 420, 357, 305, 323, 331, 228, 230, 286, 291, - 346, 580, 473, 290, 327, 518, 197, 283, 312, 278, - 521, 686, 188, 422, 306, 181, 320, 515, 688, 524, - 67, 163, 193, 184, 677, 678, 269, 178, 288, 293, - 687, 307, 308, 309, 566, 333, 332, 324, 185, 574, - 213, 285, 219, 203, 192, 214, 179, 287, 523, 164, - 657, 392, 452, 211, 208, 289, 262, 519, 502, 182, - 456, 166, 206, 335, 651, 652, 653, 656, 408, 379, - 336, 337, 204, 276, 493, 494, 340, 462, 369, 436, - 472, 443, 437, 240, 241, 344, 505, 507, 224, 654, - 358, 359, 360, 497, 361, 362, 363, 364, 412, 59, - 61, 100, 103, 102, 691, 692, 66, 32, 398, 401, - 434, 438, 371, 658, 578, 368, 372, 373, 402, 28, - 454, 424, 458, 457, 51, 52, 53, 56, 57, 58, - 60, 62, 63, 54, 565, 417, 431, 526, 48, 50, - 427, 428, 30, 404, 453, 475, 367, 455, 486, 49, - 484, 485, 506, 29, 406, 405, 65, 47, 461, 463, - 464, 338, 365, 415, 667, 527, 410, 426, 430, 411, - 370, 400, 432, 70, 423, 668, 418, 416, 366, 582, - 583, 375, 610, 395, 470, 562, 561, 560, 559, 558, - 557, 556, 555, 341, 342, 343, 439, 440, 441, 451, - 444, 445, 446, 447, 448, 449, 450, 489, 490, 669, - 508, 510, 511, 509, 257, 694, 396, 397, 260, 671, - 672, 101, 673, 675, 674, 31, 676, 684, 681, 682, - 683, 585, 679, 632, 633, 634, 635, 636, -458, -456, - -376, 573, 298, 659, 419, 572, 575, 413, 392, 690, - 693, 417, 280, 341, 342, 343, 487, 390, -248, -376, - 694, -88, -17, -16, -9, -195, -196, -206, 42, -262, - -376, 428, -262, 259, -385, 26, 469, -101, 470, 254, - 255, 88, 80, -376, -10, -115, -8, -122, -86, -193, - 474, -383, -376, 341, 341, -383, 259, -378, 290, 450, - -376, -513, 265, -462, -435, 291, -461, -437, -464, -438, - 35, 249, 251, 250, 584, 287, 18, 417, 261, 16, - 15, 418, 273, 28, 29, 31, 17, 419, 421, 32, - 422, 425, 426, 427, 45, 431, 432, 280, 91, 99, - 94, 632, 633, 634, 635, 636, 298, -247, -376, -411, - -403, 120, -406, -398, -399, -401, -354, -551, -396, 88, - 149, 150, 157, 121, 696, -400, -494, 39, 123, 590, - 594, 631, 537, -346, -347, -348, -349, -350, -351, 576, - -376, -552, -550, 94, 104, 106, 110, 111, 109, 107, - 171, 202, 108, 95, 172, -196, 91, -572, 600, -370, - 623, 645, 646, 647, 648, 622, 64, -520, -528, 258, - -526, 170, 207, 276, 203, 16, 155, 462, 204, 639, - 640, 641, 597, 619, 539, 540, 644, 601, 611, 626, - 592, 593, 595, 587, 588, 589, 591, 602, 604, 618, - -529, 614, 624, 625, 610, 642, 643, 681, 627, 628, - 629, 638, 637, 630, 632, 633, 634, 635, 636, 675, - 93, 92, 617, 616, 603, 598, 599, 605, 586, 596, - 606, 607, 615, 620, 621, 401, 113, 402, 403, 529, - 393, 83, 404, 265, 469, 73, 405, 406, 407, 408, - 409, 536, 410, 74, 411, 400, 280, 452, 412, 206, - 224, 542, 541, 543, 533, 530, 528, 531, 532, 534, - 535, 608, 609, 613, -138, -140, 649, -626, -337, -627, - 6, 7, 8, 9, -628, 172, -617, 471, 580, 94, - 529, 259, 334, 390, 19, 680, 571, 680, 571, 348, - 182, 179, -449, 182, 119, 188, 187, 263, 182, -449, - -376, 185, 680, 184, 677, 344, -425, -180, 390, 452, - 361, 100, 290, -429, -426, 569, -514, 338, 334, 310, - 260, 116, -181, 270, 269, 114, 529, 258, 429, 329, - 59, 61, -206, 264, -580, 563, -579, -376, -588, -589, - 246, 247, 248, 680, 685, 403, 102, 103, 677, 678, - 30, 259, 414, 286, 507, 505, 506, 508, 509, 510, - 511, -66, -530, -512, 502, 501, -389, 494, 500, 492, - 504, 495, 391, 363, 584, 362, 249, 671, 570, 564, - -364, 436, 472, 526, 527, 415, 473, 513, 515, 496, - 113, 210, 207, 260, 262, 259, 677, 290, 390, 529, - 452, 100, 361, 259, -588, 685, 179, 513, 515, 471, - 290, 450, 44, -455, 462, -454, -456, 514, 525, 92, - 93, 512, -364, 113, 493, 493, -626, -337, -194, -196, - -125, -578, 571, 680, 260, 390, 452, 290, 261, 259, - 566, 569, 262, 529, 258, 341, 414, 286, 361, 100, - 184, 677, -200, -201, -202, 242, 243, 244, 72, 247, - 245, 69, 35, 36, 37, -1, 127, 695, -403, -403, - -6, 698, -6, -403, -376, -376, 174, -269, -273, -270, - -272, -271, -275, -274, 207, 208, 170, 211, 217, 213, - 214, 215, 216, 218, 219, 220, 221, 222, 225, 226, - 223, 34, 224, 276, 203, 204, 205, 206, 227, 191, - 209, 578, 235, 192, 236, 193, 237, 194, 238, 168, - 169, 239, 195, 198, 199, 200, 201, 197, 173, -236, - 94, 35, 88, 173, 94, -626, -216, -217, 11, -226, - 282, -262, -254, 173, 696, 19, -262, -352, -376, 471, - 130, -101, 80, -101, 470, 80, -101, 470, 254, -581, - -582, -583, -585, 254, 470, 469, 255, 325, -120, 173, - 298, 19, -383, -383, 86, -262, -437, 290, -462, -435, - 39, 85, 174, 263, 174, 85, 88, 415, 390, 452, - 416, 529, 259, 429, 262, 290, 430, 390, 452, 259, - 262, 529, 290, 390, 259, 262, 452, 290, 430, 390, - 492, 493, 262, 30, 420, 423, 424, 493, -534, 525, - 174, 119, 116, 117, 118, -403, 137, -418, 130, 131, - 132, 133, 134, 135, 136, 144, 143, 156, 149, 150, - 151, 152, 153, 154, 155, 145, 146, 147, 148, 140, - 120, 138, 142, 139, 122, 161, 160, -196, -403, -411, - 64, -401, -401, -401, -401, -376, -494, -408, -403, 88, - 88, 88, 88, 88, 173, 107, 94, -403, 88, 88, + -171, -173, -135, 275, 274, 41, 341, 342, 343, 418, + 273, 250, 252, 17, 34, 45, 393, -195, 88, 574, + 251, -197, 15, 696, -6, -3, -2, -148, -152, -156, + -159, -160, -157, -158, -4, -124, 123, 265, 662, -376, + 410, 663, 665, 664, 91, 99, -369, -371, 488, 280, + 414, 420, 660, 691, 694, 573, 576, 298, 587, 588, + 589, 590, 591, 592, 593, 594, 596, 597, 598, 599, + 600, 601, 602, 612, 613, 603, 604, 605, 606, 607, + 608, 609, 610, 614, 615, 616, 617, 618, 619, 620, + 621, 622, 623, 624, 625, 626, 627, 540, 541, 645, + 646, 647, 648, 649, 569, 595, 632, 640, 641, 642, + 391, 392, 578, 292, 316, 443, 322, 329, 387, 177, + 195, 191, 218, 209, 348, 347, 574, 186, 296, 334, + 297, 98, 180, 523, 113, 500, 472, 183, 353, 356, + 354, 355, 311, 313, 315, 570, 571, 404, 318, 568, + 317, 319, 321, 572, 352, 394, 205, 200, 310, 294, + 198, 299, 43, 300, 385, 384, 223, 301, 302, 582, + 496, 390, 502, 326, 55, 470, 199, 497, 314, 499, + 227, 231, 514, 375, 515, 168, 169, 504, 517, 222, + 225, 226, 272, 381, 382, 46, 580, 284, 518, 229, + 686, 221, 216, 526, 330, 328, 386, 220, 194, 215, + 295, 68, 233, 232, 234, 466, 467, 468, 469, 303, + 304, 408, 513, 212, 201, 395, 187, 25, 521, 279, + 501, 421, 357, 358, 305, 323, 331, 228, 230, 286, + 291, 346, 581, 474, 290, 327, 519, 197, 283, 312, + 278, 522, 687, 188, 423, 306, 181, 320, 516, 689, + 525, 67, 163, 193, 184, 678, 679, 269, 178, 288, + 293, 688, 307, 308, 309, 567, 333, 332, 324, 185, + 575, 213, 285, 219, 203, 192, 214, 179, 287, 524, + 164, 658, 393, 453, 211, 208, 289, 262, 520, 503, + 182, 457, 166, 206, 335, 652, 653, 654, 657, 409, + 380, 336, 337, 204, 276, 494, 495, 340, 463, 370, + 437, 473, 444, 438, 240, 241, 344, 506, 508, 224, + 655, 359, 360, 361, 498, 362, 363, 364, 365, 413, + 59, 61, 100, 103, 102, 692, 693, 66, 32, 399, + 402, 435, 439, 372, 659, 579, 369, 373, 374, 403, + 28, 455, 425, 459, 458, 51, 52, 53, 56, 57, + 58, 60, 62, 63, 54, 566, 418, 432, 527, 48, + 50, 428, 429, 30, 405, 454, 476, 368, 456, 487, + 49, 485, 486, 507, 29, 407, 406, 65, 47, 462, + 464, 465, 338, 366, 416, 668, 528, 411, 427, 431, + 412, 371, 401, 433, 70, 424, 669, 419, 417, 367, + 583, 584, 376, 611, 396, 471, 563, 562, 561, 560, + 559, 558, 557, 556, 341, 342, 343, 440, 441, 442, + 452, 445, 446, 447, 448, 449, 450, 451, 490, 491, + 670, 509, 511, 512, 510, 257, 695, 397, 398, 260, + 672, 673, 101, 674, 676, 675, 31, 677, 685, 682, + 683, 684, 586, 680, 633, 634, 635, 636, 637, -458, + -456, -376, 574, 298, 660, 420, 573, 576, 414, 393, + 691, 694, 418, 280, 341, 342, 343, 488, 391, -248, + -376, 695, -88, -17, -16, -9, -195, -196, -206, 42, + -262, -376, 429, -262, 259, -385, 26, 470, -101, 471, + 254, 255, 88, 80, -376, -10, -115, -8, -122, -86, + -193, 475, -383, -376, 341, 341, -383, 259, -378, 290, + 451, -376, -513, 265, -462, -435, 291, -461, -437, -464, + -438, 35, 249, 251, 250, 585, 287, 18, 418, 261, + 16, 15, 419, 273, 28, 29, 31, 17, 420, 422, + 32, 423, 426, 427, 428, 45, 432, 433, 280, 91, + 99, 94, 633, 634, 635, 636, 637, 298, -247, -376, + -411, -403, 120, -406, -398, -399, -401, -354, -551, -396, + 88, 149, 150, 157, 121, 697, -400, -494, 39, 123, + 591, 595, 632, 538, -346, -347, -348, -349, -350, -351, + 577, -376, -552, -550, 94, 104, 106, 110, 111, 109, + 107, 171, 202, 108, 95, 172, -196, 91, -572, 601, + -370, 624, 646, 647, 648, 649, 623, 64, -520, -528, + 258, -526, 170, 207, 276, 203, 16, 155, 463, 204, + 640, 641, 642, 598, 620, 540, 541, 645, 602, 612, + 627, 593, 594, 596, 588, 589, 590, 592, 603, 605, + 619, -529, 615, 625, 626, 611, 643, 644, 682, 628, + 629, 630, 639, 638, 631, 633, 634, 635, 636, 637, + 676, 93, 92, 618, 617, 604, 599, 600, 606, 587, + 597, 607, 608, 616, 621, 622, 402, 113, 403, 404, + 530, 394, 83, 405, 265, 470, 73, 406, 407, 408, + 409, 410, 537, 411, 74, 412, 401, 280, 453, 413, + 206, 224, 543, 542, 544, 534, 531, 529, 532, 533, + 535, 536, 609, 610, 614, -138, -140, 650, -626, -337, + -627, 6, 7, 8, 9, -628, 172, -617, 472, 581, + 94, 530, 259, 334, 391, 19, 681, 572, 681, 572, + 348, 182, 179, -449, 182, 119, 188, 187, 263, 182, + -449, -376, 185, 681, 184, 678, 344, -425, -180, 391, + 453, 362, 100, 290, -429, -426, 570, -514, 338, 334, + 310, 260, 116, -181, 270, 269, 114, 530, 258, 430, + 329, 59, 61, -206, 264, -580, 564, -579, -376, -588, + -589, 246, 247, 248, 681, 686, 404, 102, 103, 678, + 679, 30, 259, 415, 286, 508, 506, 507, 509, 510, + 511, 512, -66, -530, -512, 503, 502, -389, 495, 501, + 493, 505, 496, 392, 364, 585, 363, 249, 672, 571, + 565, -364, 437, 473, 527, 528, 416, 474, 514, 516, + 497, 113, 210, 207, 260, 262, 259, 678, 290, 391, + 530, 453, 100, 362, 259, -588, 686, 179, 514, 516, + 472, 290, 451, 44, -455, 463, -454, -456, 515, 526, + 92, 93, 513, -364, 113, 494, 494, -626, -337, -194, + -196, -125, -578, 572, 681, 260, 391, 453, 290, 261, + 259, 567, 570, 262, 530, 258, 341, 415, 286, 362, + 100, 184, 678, -200, -201, -202, 242, 243, 244, 72, + 247, 245, 69, 35, 36, 37, -1, 127, 696, -403, + -403, -6, 699, -6, -403, -376, -376, 174, -269, -273, + -270, -272, -271, -275, -274, 207, 208, 170, 211, 217, + 213, 214, 215, 216, 218, 219, 220, 221, 222, 225, + 226, 223, 34, 224, 276, 203, 204, 205, 206, 227, + 191, 209, 579, 235, 192, 236, 193, 237, 194, 238, + 168, 169, 239, 195, 198, 199, 200, 201, 197, 173, + -236, 94, 35, 88, 173, 94, -626, -216, -217, 11, + -226, 282, -262, -254, 173, 697, 19, -262, -352, -376, + 472, 130, -101, 80, -101, 471, 80, -101, 471, 254, + -581, -582, -583, -585, 254, 471, 470, 255, 325, -120, + 173, 298, 19, -383, -383, 86, -262, -437, 290, -462, + -435, 39, 85, 174, 263, 174, 85, 88, 416, 391, + 453, 417, 530, 259, 430, 262, 290, 431, 391, 453, + 259, 262, 530, 290, 391, 259, 262, 453, 290, 431, + 391, 493, 494, 262, 30, 421, 424, 425, 494, -534, + 526, 174, 119, 116, 117, 118, -403, 137, -418, 130, + 131, 132, 133, 134, 135, 136, 144, 143, 156, 149, + 150, 151, 152, 153, 154, 155, 145, 146, 147, 148, + 140, 120, 138, 142, 139, 122, 161, 160, -196, -403, + -411, 64, -401, -401, -401, -401, -376, -494, -408, -403, + 88, 88, 88, 88, 88, 173, 107, 94, -403, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - -527, 88, 88, -415, -416, 88, 88, -396, -352, 88, - 94, 94, 88, 88, 88, 94, 88, 88, 88, -416, - -416, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, -527, 88, 88, -415, -416, 88, 88, -396, -352, + 88, 94, 94, 88, 88, 88, 94, 88, 88, 88, + -416, -416, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, - 88, 88, 88, 88, 88, 88, 88, -217, 174, -216, - 88, -216, -217, -197, -196, 35, 36, 35, 36, 35, - 36, 35, 36, -629, 668, 88, 104, 691, 240, -230, - -376, -231, -376, -146, 19, 696, -376, 677, -611, 35, - 574, 574, 574, 574, 249, 18, 352, 57, 518, 14, - 186, 187, 188, -376, 185, 263, -376, -423, 265, -423, - -423, -246, -376, 286, 414, 262, 566, 262, -181, -423, - -423, -423, -423, -423, 261, -423, 26, 259, 259, 259, - 259, -423, 536, 130, 130, 62, -226, -206, 174, -580, - -225, 88, -590, 190, -611, 686, 687, 688, -388, 138, - 142, -388, -333, 20, -333, 26, 26, 288, 288, 288, - -388, 328, -637, -638, 19, 140, -386, -638, -386, -386, - -388, -639, 261, 503, 46, 289, 288, -218, -219, 24, - -218, 497, 493, -479, 498, 499, -390, -638, -389, -388, - -388, -389, -388, -388, -388, 35, 259, 262, 529, 361, - 672, -637, -637, 34, 34, -513, -513, -262, -513, -513, - -513, 564, -365, -376, -513, -513, -513, -316, -317, -262, - -591, 264, 688, -623, -622, 516, -625, 518, 179, -456, - 179, -456, 91, -437, 290, 290, 174, 130, 26, -457, - 130, 141, -456, -456, -457, -457, -286, 44, -375, 170, - -376, 94, -286, 44, -620, -619, -262, -217, -197, -196, - 89, 89, 89, 574, -611, -513, -513, -513, -513, -513, - -514, -513, -513, -513, -513, -513, -383, -237, -376, -248, - 265, -513, -513, -513, -513, -198, -199, 151, -403, -376, - -202, -3, -150, -149, 124, 125, 127, 662, 409, 661, - 665, 659, -456, 44, -507, 164, 163, -501, -503, 88, - -502, 88, -502, -502, -502, -502, -502, 88, 88, -504, - 88, -504, -504, -501, -505, 88, -505, -506, 88, -506, - -505, -376, -483, 14, -409, -411, -376, 42, -217, -141, - 42, -219, 23, -524, 64, -193, 88, 34, 88, -376, - 204, 184, 676, 38, 100, 173, 104, 94, -120, -101, - 80, -120, -101, -101, 89, 174, -584, 110, 111, -586, - 94, 222, 213, -376, -118, 94, -550, -7, -12, -8, - -10, -11, -48, -86, -193, 572, 575, -553, -551, 88, - 35, 461, 85, 19, -463, 259, 529, 414, 286, 262, - 390, -461, -444, -441, -439, -375, -437, -440, -439, -466, - -352, 493, -142, 476, 475, 340, -403, -403, -403, -403, - -403, 109, 120, 379, 110, 111, -398, -419, 35, 336, - 337, -399, -399, -399, -399, -399, -399, -399, -399, -399, - -399, -399, -399, -401, -401, -407, -417, -494, 88, 140, - 138, 142, 139, 122, -401, -401, -399, -399, -267, -269, - 163, 164, -288, -375, 170, 89, 174, -403, -577, -576, - 124, -403, -403, -403, -403, -430, -432, -352, 88, -376, - -573, -574, 544, 545, 546, 547, 548, 549, 550, 551, - 552, 553, 554, 405, 400, 406, 404, 393, 412, 407, - 408, 206, 561, 562, 555, 556, 557, 558, 559, 560, - -409, -409, -403, -573, -409, -345, 36, 35, -411, -411, - -411, 89, -403, -587, 377, 376, 378, -221, -376, -409, - 89, 89, 89, 104, -411, -411, -409, -399, -409, -409, - -409, -409, -574, -574, -575, 276, 203, 205, 204, -345, - -345, -345, -345, 151, -411, -411, -345, -345, -345, -345, - 151, -345, -345, -345, -345, -345, -345, -345, -345, -345, - -345, -345, 89, 89, 89, 89, -403, 89, -403, -403, - -403, -403, -403, 151, -411, -218, -140, -532, -531, -403, - 44, -141, -219, -630, 669, 88, -352, -618, 94, 94, - 696, -146, 173, 19, 259, -146, 173, 677, 184, -146, - 19, -376, -376, 104, -376, 104, 259, 529, 259, 529, - -262, -262, 519, 520, 183, 187, 186, -376, 185, -376, - -376, 120, -376, -376, 38, -248, -237, -423, -423, -423, - -595, -376, 95, -445, -442, -439, -376, -376, -435, -376, - -365, -262, -423, -423, -423, -423, -262, -297, 56, 57, - 58, -439, -182, 59, 60, -523, 64, -193, 88, 34, - -226, -579, 38, -224, -376, -591, -333, -401, -401, -403, - 390, 529, 259, -439, 290, -637, -388, -388, -366, -365, - -390, -385, -390, -390, -333, -386, -388, -388, -403, -390, - -386, -333, -376, 493, -333, -333, -479, -388, -387, -376, - -387, -423, -365, -366, -366, -262, -262, -311, -318, -312, - -319, 282, 256, 398, 399, 252, 250, 11, 251, -327, - 329, -424, 537, -292, -293, 80, 45, -295, 280, 438, - 434, 292, 296, 98, 297, 471, 298, 261, 300, 301, - 302, 317, 319, 272, 303, 304, 305, 462, 306, 178, - 318, 307, 308, 309, 416, -287, 6, 364, 44, 54, - 55, 485, 484, 582, 14, 293, -376, -438, -595, -593, - 34, -376, 34, -445, -439, -376, -376, 174, 263, -209, - -211, -208, -204, -205, -210, -336, -338, -207, 88, -262, - -196, -376, -456, 174, 517, 519, 520, -623, -457, -623, - -457, 263, 35, 461, -460, 461, 35, -435, -454, 513, - 515, -450, 94, 462, -440, -459, 85, 170, -531, -457, - -457, -459, -459, 160, 174, -621, 518, 519, 246, -218, - 104, -244, 679, -264, -262, -595, -444, -435, -376, -513, - -264, -264, -264, -378, -378, 88, 173, 39, -376, -376, - -376, -376, -332, 174, -331, 19, -377, -376, 38, 94, - 173, -151, -149, 126, -403, -6, 661, -403, -6, -6, - -403, -6, -403, -511, 166, 104, 104, -355, 94, -355, - 104, 104, 104, 585, 89, 94, -218, 650, -220, 23, - -215, -214, -403, -525, -412, -571, 649, -228, 89, -221, - -569, -570, -221, -227, -376, -254, 130, 130, 130, 27, - -513, -376, 26, -120, -101, -582, 173, 174, -224, -463, - -443, -440, -465, 151, -376, -451, 174, 14, 699, 92, - 263, -608, -607, 453, 89, 174, -535, 264, 536, 94, - 696, 469, 240, 241, 109, 379, 110, 111, -494, -411, - -407, -401, -401, -399, -399, -405, 277, -405, 119, -277, - 169, 168, -277, -403, 697, -402, -576, 126, -403, 38, - 174, 38, 174, 86, 174, 89, -501, -403, 173, 89, - 89, 19, 19, 89, -403, 89, 89, 89, 89, 19, - 19, -403, 89, 173, 89, 89, 89, 89, 86, 89, - 174, 89, 89, 89, 89, 174, 174, 174, -411, -411, - -403, -411, 89, 89, 89, -403, -403, -403, -411, 89, - -403, -403, -403, -403, -403, -403, -403, -403, -403, -403, - -224, -473, 488, -473, -473, -473, 89, -473, 89, 174, - 89, 174, 89, 89, 174, 174, 174, 174, 89, -220, - 88, 104, 174, 692, -359, -358, 94, -147, 263, -376, - 677, -376, -147, -376, -376, 130, -147, 677, 94, 94, - -262, -365, -262, -365, 577, 42, 184, 188, 188, 187, - -376, 94, 39, 26, 26, 327, -247, 88, 88, -262, - -262, -262, -597, 439, -609, 174, 44, -607, 529, -178, - 340, -427, 86, -185, 347, 19, 14, -262, -262, -262, - -262, -276, 38, -448, 85, -525, -228, 89, -569, -523, - 88, 89, 174, 19, -203, -263, -376, -376, -376, -376, - -436, 86, -376, -366, -333, -333, -390, -333, -333, 174, - 25, -388, -390, -390, -254, -386, -254, 173, -254, -365, - -500, 38, -225, 174, 23, 282, -261, -373, -258, -260, - 267, -393, -259, 270, -565, 268, 266, 114, 271, 325, - 115, 261, -373, -373, 267, -296, 263, 38, -373, -314, - 261, 382, 325, 268, 23, 282, -313, 261, 115, -376, - 267, 271, 268, 266, -372, 130, -364, 160, 263, 46, - 416, -372, 583, 282, -372, -372, -372, -372, -372, -372, - -372, 299, 299, -372, -372, -372, -372, -372, -372, -372, - -372, -372, -372, -372, 179, -372, -372, -372, -372, -372, - -372, 88, 294, 295, 327, 252, -598, 439, 34, 396, - 396, 397, -609, 392, 45, 34, -186, 390, -317, -315, - -387, 34, -339, -340, -341, -342, -344, -343, 71, 75, - 77, 81, 72, 73, 74, 78, 83, 76, 34, 174, - -374, -379, 38, -376, 94, -374, -196, -211, -209, -374, - 88, -457, -622, -624, 521, 518, 524, -459, -459, 104, - 263, 88, 130, -459, -459, 44, -375, -619, 525, 519, - -220, 174, 85, -264, -238, -239, -240, -241, -269, -352, - 208, 211, 213, 214, 215, 216, 218, 219, 220, 221, - 222, 225, 226, 223, 224, 276, 203, 204, 205, 206, - 227, 191, 209, 578, 192, 193, 194, 168, 169, 195, - 198, 199, 200, 201, 197, -376, -248, -244, -333, -199, - -211, -376, 94, -376, 151, 127, -6, 125, -155, -154, - -153, 128, 659, 665, 127, 127, 127, 89, 89, 89, - 174, 89, 89, 89, 174, 89, 174, 104, -538, 498, - -220, 94, -141, 627, 174, -212, 40, 41, 174, 88, - 89, 174, 64, 174, 130, 89, 174, -403, -376, 94, - -403, 204, 94, 173, 471, -376, -551, 89, -465, 174, - 263, 173, 173, -441, 419, -375, -443, 23, 14, -352, - 42, -359, 130, 696, -376, 89, -405, -405, 119, -401, - -398, 89, 127, -403, 125, -267, -403, -267, -268, -274, - 170, 207, 276, 206, 205, 203, 163, 164, -286, -432, - 577, -212, 89, -376, -403, -403, 89, -403, -403, 19, - -376, -286, -399, -403, -403, -403, -217, -217, 89, 89, - -472, -473, -472, -472, 89, 89, 89, 89, -472, 89, + 88, 88, 88, 88, 88, 88, 88, 88, -217, 174, + -216, 88, -216, -217, -197, -196, 35, 36, 35, 36, + 35, 36, 35, 36, -629, 669, 88, 104, 692, 240, + -230, -376, -231, -376, -146, 19, 697, -376, 678, -611, + 35, 575, 575, 575, 575, 249, 18, 352, 57, 519, + 14, 186, 187, 188, -376, 185, 263, -376, -423, 265, + -423, -423, -246, -376, 286, 415, 262, 567, 262, -181, + -423, -423, -423, -423, -423, 261, -423, 26, 259, 259, + 259, 259, -423, 537, 130, 130, 62, -226, -206, 174, + -580, -225, 88, -590, 190, -611, 687, 688, 689, -388, + 138, 142, -388, -333, 20, -333, 26, 26, 288, 288, + 288, -388, 328, -637, -638, 19, 140, -386, -638, -386, + -386, -388, -639, 261, 504, 46, 289, 288, -218, -219, + 24, -218, 498, 494, -479, 499, 500, -390, -638, -389, + -388, -388, -389, -388, -388, -388, 35, 259, 262, 530, + 362, 673, -637, -637, 34, 34, -513, -513, -262, -513, + -513, -513, 565, -365, -376, -513, -513, -513, -316, -317, + -262, -591, 264, 689, -623, -622, 517, -625, 519, 179, + -456, 179, -456, 91, -437, 290, 290, 174, 130, 26, + -457, 130, 141, -456, -456, -457, -457, -286, 44, -375, + 170, -376, 94, -286, 44, -620, -619, -262, -217, -197, + -196, 89, 89, 89, 575, -611, -513, -513, -513, -513, + -513, -514, -513, -513, -513, -513, -513, -383, -237, -376, + -248, 265, -513, -513, -513, -513, -198, -199, 151, -403, + -376, -202, -3, -150, -149, 124, 125, 127, 663, 410, + 662, 666, 660, -456, 44, -507, 164, 163, -501, -503, + 88, -502, 88, -502, -502, -502, -502, -502, 88, 88, + -504, 88, -504, -504, -501, -505, 88, -505, -506, 88, + -506, -505, -376, -483, 14, -409, -411, -376, 42, -217, + -141, 42, -219, 23, -524, 64, -193, 88, 34, 88, + -376, 204, 184, 677, 38, 100, 173, 104, 94, -120, + -101, 80, -120, -101, -101, 89, 174, -584, 110, 111, + -586, 94, 222, 213, -376, -118, 94, -550, -7, -12, + -8, -10, -11, -48, -86, -193, 573, 576, -553, -551, + 88, 35, 462, 85, 19, -463, 259, 530, 415, 286, + 262, 391, -461, -444, -441, -439, -375, -437, -440, -439, + -466, -352, 494, -142, 477, 476, 340, -403, -403, -403, + -403, -403, 109, 120, 380, 110, 111, -398, -419, 35, + 336, 337, -399, -399, -399, -399, -399, -399, -399, -399, + -399, -399, -399, -399, -401, -401, -407, -417, -494, 88, + 140, 138, 142, 139, 122, -401, -401, -399, -399, -267, + -269, 163, 164, -288, -375, 170, 89, 174, -403, -577, + -576, 124, -403, -403, -403, -403, -430, -432, -352, 88, + -376, -573, -574, 545, 546, 547, 548, 549, 550, 551, + 552, 553, 554, 555, 406, 401, 407, 405, 394, 413, + 408, 409, 206, 562, 563, 556, 557, 558, 559, 560, + 561, -409, -409, -403, -573, -409, -345, 36, 35, -411, + -411, -411, 89, -403, -587, 378, 377, 379, -221, -376, + -409, 89, 89, 89, 104, -411, -411, -409, -399, -409, + -409, -409, -409, -574, -574, -575, 276, 203, 205, 204, + -345, -345, -345, -345, 151, -411, -411, -345, -345, -345, + -345, 151, -345, -345, -345, -345, -345, -345, -345, -345, + -345, -345, -345, 89, 89, 89, 89, -403, 89, -403, + -403, -403, -403, -403, 151, -411, -218, -140, -532, -531, + -403, 44, -141, -219, -630, 670, 88, -352, -618, 94, + 94, 697, -146, 173, 19, 259, -146, 173, 678, 184, + -146, 19, -376, -376, 104, -376, 104, 259, 530, 259, + 530, -262, -262, 520, 521, 183, 187, 186, -376, 185, + -376, -376, 120, -376, -376, 38, -248, -237, -423, -423, + -423, -595, -376, 95, -445, -442, -439, -376, -376, -435, + -376, -365, -262, -423, -423, -423, -423, -262, -297, 56, + 57, 58, -439, -182, 59, 60, -523, 64, -193, 88, + 34, -226, -579, 38, -224, -376, -591, -333, -401, -401, + -403, 391, 530, 259, -439, 290, -637, -388, -388, -366, + -365, -390, -385, -390, -390, -333, -386, -388, -388, -403, + -390, -386, -333, -376, 494, -333, -333, -479, -388, -387, + -376, -387, -423, -365, -366, -366, -262, -262, -311, -318, + -312, -319, 282, 256, 399, 400, 252, 250, 11, 251, + -327, 329, -424, 538, -292, -293, 80, 45, -295, 280, + 439, 435, 292, 296, 98, 297, 472, 298, 261, 300, + 301, 302, 317, 319, 272, 303, 304, 305, 463, 306, + 178, 318, 307, 308, 309, 417, -287, 6, 365, 44, + 54, 55, 486, 485, 583, 14, 293, -376, -438, -595, + -593, 34, -376, 34, -445, -439, -376, -376, 174, 263, + -209, -211, -208, -204, -205, -210, -336, -338, -207, 88, + -262, -196, -376, -456, 174, 518, 520, 521, -623, -457, + -623, -457, 263, 35, 462, -460, 462, 35, -435, -454, + 514, 516, -450, 94, 463, -440, -459, 85, 170, -531, + -457, -457, -459, -459, 160, 174, -621, 519, 520, 246, + -218, 104, -244, 680, -264, -262, -595, -444, -435, -376, + -513, -264, -264, -264, -378, -378, 88, 173, 39, -376, + -376, -376, -376, -332, 174, -331, 19, -377, -376, 38, + 94, 173, -151, -149, 126, -403, -6, 662, -403, -6, + -6, -403, -6, -403, -511, 166, 104, 104, -355, 94, + -355, 104, 104, 104, 586, 89, 94, -218, 651, -220, + 23, -215, -214, -403, -525, -412, -571, 650, -228, 89, + -221, -569, -570, -221, -227, -376, -254, 130, 130, 130, + 27, -513, -376, 26, -120, -101, -582, 173, 174, -224, + -463, -443, -440, -465, 151, -376, -451, 174, 14, 700, + 92, 263, -608, -607, 454, 89, 174, -535, 264, 537, + 94, 697, 470, 240, 241, 109, 380, 110, 111, -494, + -411, -407, -401, -401, -399, -399, -405, 277, -405, 119, + -277, 169, 168, -277, -403, 698, -402, -576, 126, -403, + 38, 174, 38, 174, 86, 174, 89, -501, -403, 173, + 89, 89, 19, 19, 89, -403, 89, 89, 89, 89, + 19, 19, -403, 89, 173, 89, 89, 89, 89, 86, + 89, 174, 89, 89, 89, 89, 174, 174, 174, -411, + -411, -403, -411, 89, 89, 89, -403, -403, -403, -411, + 89, -403, -403, -403, -403, -403, -403, -403, -403, -403, + -403, -224, -473, 489, -473, -473, -473, 89, -473, 89, + 174, 89, 174, 89, 89, 174, 174, 174, 174, 89, + -220, 88, 104, 174, 693, -359, -358, 94, -147, 263, + -376, 678, -376, -147, -376, -376, 130, -147, 678, 94, + 94, -262, -365, -262, -365, 578, 42, 184, 188, 188, + 187, -376, 94, 39, 26, 26, 327, -247, 88, 88, + -262, -262, -262, -597, 440, -609, 174, 44, -607, 530, + -178, 340, -427, 86, -185, 347, 19, 14, -262, -262, + -262, -262, -276, 38, -448, 85, -525, -228, 89, -569, + -523, 88, 89, 174, 19, -203, -263, -376, -376, -376, + -376, -436, 86, -376, -366, -333, -333, -390, -333, -333, + 174, 25, -388, -390, -390, -254, -386, -254, 173, -254, + -365, -500, 38, -225, 174, 23, 282, -261, -373, -258, + -260, 267, -393, -259, 270, -565, 268, 266, 114, 271, + 325, 115, 261, -373, -373, 267, -296, 263, 38, -373, + -314, 261, 383, 325, 268, 23, 282, -313, 261, 115, + -376, 267, 271, 268, 266, -372, 130, -364, 160, 263, + 46, 417, -372, 584, 282, -372, -372, -372, -372, -372, + -372, -372, 299, 299, -372, -372, -372, -372, -372, -372, + -372, -372, -372, -372, -372, 179, -372, -372, -372, -372, + -372, -372, 88, 294, 295, 327, 252, -598, 440, 34, + 397, 397, 398, -609, 393, 45, 34, -186, 391, -317, + -315, -387, 34, -339, -340, -341, -342, -344, -343, 71, + 75, 77, 81, 72, 73, 74, 78, 83, 76, 34, + 174, -374, -379, 38, -376, 94, -374, -196, -211, -209, + -374, 88, -457, -622, -624, 522, 519, 525, -459, -459, + 104, 263, 88, 130, -459, -459, 44, -375, -619, 526, + 520, -220, 174, 85, -264, -238, -239, -240, -241, -269, + -352, 208, 211, 213, 214, 215, 216, 218, 219, 220, + 221, 222, 225, 226, 223, 224, 276, 203, 204, 205, + 206, 227, 191, 209, 579, 192, 193, 194, 168, 169, + 195, 198, 199, 200, 201, 197, -376, -248, -244, -333, + -199, -211, -376, 94, -376, 151, 127, -6, 125, -155, + -154, -153, 128, 660, 666, 127, 127, 127, 89, 89, + 89, 174, 89, 89, 89, 174, 89, 174, 104, -538, + 499, -220, 94, -141, 628, 174, -212, 40, 41, 174, + 88, 89, 174, 64, 174, 130, 89, 174, -403, -376, + 94, -403, 204, 94, 173, 472, -376, -551, 89, -465, + 174, 263, 173, 173, -441, 420, -375, -443, 23, 14, + -352, 42, -359, 130, 697, -376, 89, -405, -405, 119, + -401, -398, 89, 127, -403, 125, -267, -403, -267, -268, + -274, 170, 207, 276, 206, 205, 203, 163, 164, -286, + -432, 578, -212, 89, -376, -403, -403, 89, -403, -403, + 19, -376, -286, -399, -403, -403, -403, -217, -217, 89, + 89, -472, -473, -472, -472, 89, 89, 89, 89, -472, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 88, -473, -473, -403, -473, -403, -473, -473, -403, 104, - 106, 104, 106, -531, -141, -631, 66, 667, 65, 461, - 109, 330, 174, 104, 94, 697, 174, 130, 390, -376, - 19, 173, 94, -376, 94, -376, 19, 19, -262, -262, - 188, 94, -610, 334, 390, 529, 259, 390, 334, 529, - 259, -484, 104, 427, -249, -250, -251, -252, -253, 140, - 175, 176, -238, -225, 88, -225, -600, 500, 441, 451, - -372, -395, -394, 392, 45, -518, 462, 447, 448, -442, - 290, -365, -606, 101, 130, 85, 368, 372, 374, 373, - 369, 370, 371, -421, -422, -420, -424, -365, -593, 88, - 88, -193, 38, 138, -185, 347, 88, 88, 38, -495, - 358, -269, 43, 89, 64, -1, -376, -262, -203, -376, - 19, 174, -592, 173, -376, -435, -388, -333, -403, -403, - -333, -388, -388, -390, -376, -254, -495, -269, 38, -312, - 256, 251, -469, 327, 328, -470, -485, 330, -487, 88, - -266, -352, -259, -564, -565, -423, -376, 115, -564, 115, - 88, -266, -352, -352, -315, -352, -376, -376, -376, -376, - -322, -321, -352, -325, 35, -326, -376, -376, -376, -376, - 115, -376, 115, -291, 44, 51, 52, 53, -372, -372, - 210, -294, 44, 461, 463, 464, -325, 104, 104, 104, - 104, 94, 94, 94, -372, -372, 104, 94, -379, 94, - -566, 187, 48, 49, 104, 104, 104, 104, 44, 94, - -299, 44, 310, 314, 311, 312, 313, 94, 104, 44, - 104, 44, 104, 44, -376, 88, -567, -568, 94, -484, - 263, -600, -372, 396, -456, 130, 130, -395, -602, 98, - 442, -602, -605, 340, -188, 529, 35, -229, 256, 251, - -593, -447, -446, -352, -208, -208, -208, -208, -208, -208, - 71, 82, 71, -222, 88, 71, 76, 71, 76, 71, - -341, 71, 82, -447, -210, -225, -379, 89, -616, -615, - -614, -612, 79, 264, 80, -409, -459, 518, 522, 523, - -443, -391, 94, -450, -141, -262, -262, -516, 320, 321, - 89, 174, -269, -335, 21, 173, 123, -6, -151, -153, - -403, -6, -403, 661, 409, 662, 94, 104, 104, -546, - 482, 477, 479, -141, -547, 469, 14, -214, -213, 47, - -412, -533, -532, 64, -193, -221, -525, -570, -531, -376, - 697, 697, 697, 697, 94, -376, 104, 19, -440, -435, - 151, 151, -376, 420, -451, 94, 440, 94, 259, 697, - 94, -359, -398, -403, 89, 38, 89, 89, -502, -502, - -501, -504, -501, -277, -277, 89, 88, -212, 89, 26, - 89, 89, 89, -403, 89, 89, 174, 174, 89, -521, - 538, -522, 612, -472, -472, -472, -472, -472, -472, -472, + 89, 88, -473, -473, -403, -473, -403, -473, -473, -403, + 104, 106, 104, 106, -531, -141, -631, 66, 668, 65, + 462, 109, 330, 174, 104, 94, 698, 174, 130, 391, + -376, 19, 173, 94, -376, 94, -376, 19, 19, -262, + -262, 188, 94, -610, 334, 391, 530, 259, 391, 334, + 530, 259, -484, 104, 428, -249, -250, -251, -252, -253, + 140, 175, 176, -238, -225, 88, -225, -600, 501, 442, + 452, -372, -395, -394, 393, 45, -518, 463, 448, 449, + -442, 290, -365, -606, 101, 130, 85, 369, 373, 375, + 374, 370, 371, 372, -421, -422, -420, -424, -365, -593, + 88, 88, -193, 38, 138, -185, 347, 88, 88, 38, + -495, 359, -269, 43, 89, 64, -1, -376, -262, -203, + -376, 19, 174, -592, 173, -376, -435, -388, -333, -403, + -403, -333, -388, -388, -390, -376, -254, -495, -269, 38, + -312, 256, 251, -469, 327, 328, -470, -485, 330, -487, + 88, -266, -352, -259, -564, -565, -423, -376, 115, -564, + 115, 88, -266, -352, -352, -315, -352, -376, -376, -376, + -376, -322, -321, -352, -325, 35, -326, -376, -376, -376, + -376, 115, -376, 115, -291, 44, 51, 52, 53, -372, + -372, 210, -294, 44, 462, 464, 465, -325, 104, 104, + 104, 104, 94, 94, 94, -372, -372, 104, 94, -379, + 94, -566, 187, 48, 49, 104, 104, 104, 104, 44, + 94, -299, 44, 310, 314, 311, 312, 313, 94, 104, + 44, 104, 44, 104, 44, -376, 88, -567, -568, 94, + -484, 263, -600, -372, 397, -456, 130, 130, -395, -602, + 98, 443, -602, -605, 340, -188, 530, 35, -229, 256, + 251, -593, -447, -446, -352, -208, -208, -208, -208, -208, + -208, 71, 82, 71, -222, 88, 71, 76, 71, 76, + 71, -341, 71, 82, -447, -210, -225, -379, 89, -616, + -615, -614, -612, 79, 264, 80, -409, -459, 519, 523, + 524, -443, -391, 94, -450, -141, -262, -262, -516, 320, + 321, 89, 174, -269, -335, 21, 173, 123, -6, -151, + -153, -403, -6, -403, 662, 410, 663, 94, 104, 104, + -546, 483, 478, 480, -141, -547, 470, 14, -214, -213, + 47, -412, -533, -532, 64, -193, -221, -525, -570, -531, + -376, 698, 698, 698, 698, 94, -376, 104, 19, -440, + -435, 151, 151, -376, 421, -451, 94, 441, 94, 259, + 698, 94, -359, -398, -403, 89, 38, 89, 89, -502, + -502, -501, -504, -501, -277, -277, 89, 88, -212, 89, + 26, 89, 89, 89, -403, 89, 89, 174, 174, 89, + -521, 539, -522, 613, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, -472, - -414, -413, 282, 89, 174, 89, 174, 89, 483, 674, - 674, 483, 674, 674, 89, 174, -573, 174, -367, 335, - -367, -358, 94, -376, 94, 677, -376, 697, 697, 94, - -262, -365, -192, 357, -191, 124, 94, -376, -376, -376, - 327, -376, 327, -376, -376, 94, 94, 89, 174, -352, - 89, 38, -255, -256, -257, -266, -258, -260, 38, -601, - 98, -596, 94, -376, 95, -602, 172, 394, 44, 443, - 444, 459, 389, 104, 104, 449, -594, -376, -187, 259, - 390, -604, 55, 130, 94, -262, -420, -364, 160, 301, - -254, 361, -330, -329, -376, 94, -255, -193, -262, -262, - -255, -255, -193, -496, 360, 23, 104, 150, 115, 64, - -193, -525, 89, -226, 86, 173, -211, -263, -376, 151, - -333, -254, -333, -333, -388, -496, -193, -481, 331, 88, - -479, 88, -479, 115, 369, -488, -486, 282, -320, 48, - 50, -269, -562, -376, -560, -562, -376, -560, -560, -423, - -403, -320, -266, 263, 34, 251, -323, 372, 366, 367, - 372, 374, -452, 326, 120, -452, 174, -212, 174, -376, - -286, -286, 34, 94, 94, -264, 89, 174, 130, 94, - -438, -601, -596, 130, -457, 94, 94, -602, 94, 94, - -606, 130, -265, 259, -365, 174, -229, -229, -333, 174, - 130, -233, -232, 85, 86, -234, 85, -232, -232, 71, - -223, 94, 71, 71, -333, -614, -613, 26, -565, -565, - -565, 89, 89, -235, 26, -240, 44, -334, 22, 23, - 151, 127, 125, 127, 127, -376, 89, 89, -508, 651, - -542, -544, 477, 23, 23, -235, -548, 656, 94, 420, - 48, 49, 89, -525, 697, -435, -451, 462, -262, 174, - 697, -267, -305, 94, -403, 89, -403, -403, 89, 94, - 89, 94, -217, 23, -473, -403, -473, -403, -473, 89, - 174, 89, 89, 89, 174, 89, 89, -403, 89, -573, - -368, 204, 94, -368, -376, -377, -190, 263, -254, 38, - 427, 24, 591, 353, 94, -376, -484, 327, -484, 327, - 259, -376, -244, -428, 579, -251, -269, 257, -193, 89, - 174, -193, 94, -599, 453, 104, 44, 104, 172, 445, - -519, -179, 98, -264, 35, -229, -603, 98, 130, 696, - 88, -372, -372, -372, -190, -376, 89, 174, -372, -372, - 89, -190, 89, 89, -284, 14, -497, 281, 104, 150, - 104, 150, 104, 17, 264, -525, -374, -211, -376, -333, - -592, 173, -333, -497, -471, 332, 104, -399, 88, -399, - 88, -480, 329, 88, 89, 174, -376, -352, -281, -280, - -278, 109, 120, 44, 434, -279, 98, 160, 315, 318, - 317, 293, 316, -310, -392, 85, 437, 366, 367, -424, - 651, 568, 266, 114, 115, 421, -393, 88, 88, 86, - 335, 88, 88, -562, 89, -320, -352, 44, -323, 44, - -324, 388, -433, 326, -321, -376, 160, -286, 89, -568, - 94, -599, 94, -459, -604, 94, -179, -264, -593, -217, - -446, -531, -403, 88, -403, 89, 88, 71, 11, 21, - 17, -396, -403, -411, 681, 683, 684, 265, -6, 662, - 409, -301, 652, 94, 23, 94, -540, 94, -538, 94, - -411, -144, -298, -364, 298, 89, -304, 140, 14, 89, - 89, 89, -472, -472, -475, -474, -478, 483, 327, 491, - -411, 89, 89, 94, 94, 89, 89, 94, 94, 390, - -190, -262, 94, 104, 354, 355, 356, 696, 94, -484, - 94, -484, -376, 327, 94, 94, -242, -269, -183, 14, - -284, -257, -183, 23, 14, 393, 44, 104, 44, 446, - 94, -187, 130, 110, 111, -360, -361, 94, -430, -286, - -288, 94, -329, -396, -396, -282, -193, 38, -283, -327, - -424, -143, -142, -282, 88, -498, 178, 104, 150, 104, - 104, -447, -333, -333, -498, -487, 23, 89, -466, 89, - -466, 88, 130, -399, -486, -489, 64, -278, 109, -399, - 94, -288, -289, 44, 314, 310, 130, 130, -290, 44, - 294, 295, -300, 88, 325, 17, 210, 88, 115, 115, - -262, -430, -430, -563, 368, 369, 370, 375, 372, 373, - 371, 374, -563, -430, -430, 88, -453, -452, -399, -433, - 130, -434, 272, 380, 381, 98, 14, 366, 367, 385, - 384, 383, 386, 387, 388, 393, 404, -372, 160, -603, - -218, -224, -561, -376, 266, 23, 23, -517, 14, 682, - 88, 88, -376, -376, -356, 653, 104, 94, 479, -546, - -509, 654, -536, -479, -286, 130, 89, 78, 578, 580, - 89, -477, 122, 445, 449, -397, -400, 104, 106, 202, - 172, -473, -473, 89, 89, -376, -363, -362, 94, -244, - 94, -244, 94, 327, -484, 579, -184, 63, 525, 94, - 95, 440, 94, 95, 393, -179, 94, 697, 174, 130, - 89, -467, 282, -193, 174, -327, -364, -144, -467, -285, - -328, -376, 94, -515, 187, 359, 14, 104, 150, 104, - -217, -499, 187, 359, -470, 89, 89, 89, -466, 104, - 89, -493, -490, 88, -327, 284, 140, 94, 94, 104, - 88, -526, 34, 94, -431, 88, 89, 89, 89, 89, - -430, 110, 111, -372, -372, 94, 94, 365, -372, -372, - -372, 130, -372, -372, -286, -372, 89, 89, 174, 684, - 88, -411, -411, 88, 23, -508, -510, 655, 94, -545, - 482, -539, -537, 477, 478, 479, 480, 94, 579, 68, - 581, -476, -477, 449, -397, -400, 649, 489, 489, 489, - 697, 174, 130, -244, -244, -484, 94, -245, -376, 325, - 462, -361, 94, -433, -468, 334, 23, -327, -372, -468, - 89, 174, -372, -372, 359, 104, 150, 104, -218, 359, - -482, 333, 89, -493, -327, -492, -491, 332, 285, 88, - 89, -403, -415, -372, 89, -303, -302, 576, -430, -433, - 86, -433, 86, -433, 86, -433, 86, 89, 104, 104, - -376, 104, 104, 104, 110, 111, 104, 104, -286, -376, - 266, -139, 88, 89, 89, -357, -376, -540, -301, 94, - -549, 264, -543, -544, 481, -537, 23, 479, 23, 23, - -145, 174, 68, 119, 490, 490, 490, -244, -362, 94, - 94, -244, -243, 38, 484, 420, 23, -469, -286, -328, - -396, -396, 104, 104, 89, 174, -376, 281, 88, -410, - -404, -403, 281, 89, -376, -309, -307, -308, 85, 496, - 323, 324, 89, -563, -563, -563, -563, -310, 89, 174, - -409, 89, 174, -356, -556, 88, 104, -542, -541, -543, - 23, -540, 23, -540, -540, 486, 14, -476, -244, 94, - -352, 88, -481, -491, -490, -410, 89, 174, -452, -308, - 85, -307, 85, 18, 17, -433, -433, -433, -433, 88, - 89, -376, -559, 34, 89, -555, -554, -353, -550, -376, - 482, 483, 94, -540, 130, 580, -634, -633, 673, -466, - -471, 89, -404, -306, 320, 321, 34, 187, -306, -409, - -558, -557, -354, 89, 174, 173, 94, 581, 94, 89, - -487, 109, 44, 322, 89, 174, 130, -554, -376, -557, - 44, -403, 173, -376, + -472, -414, -413, 282, 89, 174, 89, 174, 89, 484, + 675, 675, 484, 675, 675, 89, 174, -573, 174, -367, + 335, -367, -358, 94, -376, 94, 678, -376, 698, 698, + 94, -262, -365, -192, 357, -191, 124, 94, -376, -376, + -376, 327, -376, 327, -376, -376, 94, 94, 89, 174, + -352, 89, 38, -255, -256, -257, -266, -258, -260, 38, + -601, 98, -596, 94, -376, 95, -602, 172, 395, 44, + 444, 445, 460, 390, 104, 104, 450, -594, -376, -187, + 259, 391, -604, 55, 130, 94, -262, -420, -364, 160, + 301, -254, 362, -330, -329, -376, 94, -255, -193, -262, + -262, -255, -255, -193, -496, 361, 23, 104, 150, 115, + 64, -193, -525, 89, -226, 86, 173, -211, -263, -376, + 151, -333, -254, -333, -333, -388, -496, -193, -481, 331, + 88, -479, 88, -479, 115, 370, -488, -486, 282, -320, + 48, 50, -269, -562, -376, -560, -562, -376, -560, -560, + -423, -403, -320, -266, 263, 34, 251, -323, 373, 367, + 368, 373, 375, -452, 326, 120, -452, 174, -212, 174, + -376, -286, -286, 34, 94, 94, -264, 89, 174, 130, + 94, -438, -601, -596, 130, -457, 94, 94, -602, 94, + 94, -606, 130, -265, 259, -365, 174, -229, -229, -333, + 174, 130, -233, -232, 85, 86, -234, 85, -232, -232, + 71, -223, 94, 71, 71, -333, -614, -613, 26, -565, + -565, -565, 89, 89, -235, 26, -240, 44, -334, 22, + 23, 151, 127, 125, 127, 127, -376, 89, 89, -508, + 652, -542, -544, 478, 23, 23, -235, -548, 657, 94, + 421, 48, 49, 89, -525, 698, -435, -451, 463, -262, + 174, 698, -267, -305, 94, -403, 89, -403, -403, 89, + 94, 89, 94, -217, 23, -473, -403, -473, -403, -473, + 89, 174, 89, 89, 89, 174, 89, 89, -403, 89, + -573, -368, 204, 94, -368, -376, -377, -190, 263, -254, + 38, 428, 24, 592, 358, 353, 94, -376, -484, 327, + -484, 327, 259, -376, -244, -428, 580, -251, -269, 257, + -193, 89, 174, -193, 94, -599, 454, 104, 44, 104, + 172, 446, -519, -179, 98, -264, 35, -229, -603, 98, + 130, 697, 88, -372, -372, -372, -190, -376, 89, 174, + -372, -372, 89, -190, 89, 89, -284, 14, -497, 281, + 104, 150, 104, 150, 104, 17, 264, -525, -374, -211, + -376, -333, -592, 173, -333, -497, -471, 332, 104, -399, + 88, -399, 88, -480, 329, 88, 89, 174, -376, -352, + -281, -280, -278, 109, 120, 44, 435, -279, 98, 160, + 315, 318, 317, 293, 316, -310, -392, 85, 438, 367, + 368, -424, 652, 569, 266, 114, 115, 422, -393, 88, + 88, 86, 335, 88, 88, -562, 89, -320, -352, 44, + -323, 44, -324, 389, -433, 326, -321, -376, 160, -286, + 89, -568, 94, -599, 94, -459, -604, 94, -179, -264, + -593, -217, -446, -531, -403, 88, -403, 89, 88, 71, + 11, 21, 17, -396, -403, -411, 682, 684, 685, 265, + -6, 663, 410, -301, 653, 94, 23, 94, -540, 94, + -538, 94, -411, -144, -298, -364, 298, 89, -304, 140, + 14, 89, 89, 89, -472, -472, -475, -474, -478, 484, + 327, 492, -411, 89, 89, 94, 94, 89, 89, 94, + 94, 391, -190, -262, 94, 104, 354, 355, 356, 697, + 94, -484, 94, -484, -376, 327, 94, 94, -242, -269, + -183, 14, -284, -257, -183, 23, 14, 394, 44, 104, + 44, 447, 94, -187, 130, 110, 111, -360, -361, 94, + -430, -286, -288, 94, -329, -396, -396, -282, -193, 38, + -283, -327, -424, -143, -142, -282, 88, -498, 178, 104, + 150, 104, 104, -447, -333, -333, -498, -487, 23, 89, + -466, 89, -466, 88, 130, -399, -486, -489, 64, -278, + 109, -399, 94, -288, -289, 44, 314, 310, 130, 130, + -290, 44, 294, 295, -300, 88, 325, 17, 210, 88, + 115, 115, -262, -430, -430, -563, 369, 370, 371, 376, + 373, 374, 372, 375, -563, -430, -430, 88, -453, -452, + -399, -433, 130, -434, 272, 381, 382, 98, 14, 367, + 368, 386, 385, 384, 387, 388, 389, 394, 405, -372, + 160, -603, -218, -224, -561, -376, 266, 23, 23, -517, + 14, 683, 88, 88, -376, -376, -356, 654, 104, 94, + 480, -546, -509, 655, -536, -479, -286, 130, 89, 78, + 579, 581, 89, -477, 122, 446, 450, -397, -400, 104, + 106, 202, 172, -473, -473, 89, 89, -376, -363, -362, + 94, -244, 94, -244, 94, 327, -484, 580, -184, 63, + 526, 94, 95, 441, 94, 95, 394, -179, 94, 698, + 174, 130, 89, -467, 282, -193, 174, -327, -364, -144, + -467, -285, -328, -376, 94, -515, 187, 360, 14, 104, + 150, 104, -217, -499, 187, 360, -470, 89, 89, 89, + -466, 104, 89, -493, -490, 88, -327, 284, 140, 94, + 94, 104, 88, -526, 34, 94, -431, 88, 89, 89, + 89, 89, -430, 110, 111, -372, -372, 94, 94, 366, + -372, -372, -372, 130, -372, -372, -286, -372, 89, 89, + 174, 685, 88, -411, -411, 88, 23, -508, -510, 656, + 94, -545, 483, -539, -537, 478, 479, 480, 481, 94, + 580, 68, 582, -476, -477, 450, -397, -400, 650, 490, + 490, 490, 698, 174, 130, -244, -244, -484, 94, -245, + -376, 325, 463, -361, 94, -433, -468, 334, 23, -327, + -372, -468, 89, 174, -372, -372, 360, 104, 150, 104, + -218, 360, -482, 333, 89, -493, -327, -492, -491, 332, + 285, 88, 89, -403, -415, -372, 89, -303, -302, 577, + -430, -433, 86, -433, 86, -433, 86, -433, 86, 89, + 104, 104, -376, 104, 104, 104, 110, 111, 104, 104, + -286, -376, 266, -139, 88, 89, 89, -357, -376, -540, + -301, 94, -549, 264, -543, -544, 482, -537, 23, 480, + 23, 23, -145, 174, 68, 119, 491, 491, 491, -244, + -362, 94, 94, -244, -243, 38, 485, 421, 23, -469, + -286, -328, -396, -396, 104, 104, 89, 174, -376, 281, + 88, -410, -404, -403, 281, 89, -376, -309, -307, -308, + 85, 497, 323, 324, 89, -563, -563, -563, -563, -310, + 89, 174, -409, 89, 174, -356, -556, 88, 104, -542, + -541, -543, 23, -540, 23, -540, -540, 487, 14, -476, + -244, 94, -352, 88, -481, -491, -490, -410, 89, 174, + -452, -308, 85, -307, 85, 18, 17, -433, -433, -433, + -433, 88, 89, -376, -559, 34, 89, -555, -554, -353, + -550, -376, 483, 484, 94, -540, 130, 581, -634, -633, + 674, -466, -471, 89, -404, -306, 320, 321, 34, 187, + -306, -409, -558, -557, -354, 89, 174, 173, 94, 582, + 94, 89, -487, 109, 44, 322, 89, 174, 130, -554, + -376, -557, 44, -403, 173, -376, } var yyDef = [...]int{ @@ -10225,418 +10233,418 @@ var yyDef = [...]int{ -2, 0, 0, 751, 0, 0, 0, 835, 0, 0, 0, 880, 898, 23, 0, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 19, 0, - 19, 0, 0, 0, 1473, 1474, 1475, 1476, 2309, 2279, - -2, 2040, 2014, 2203, 2204, 2098, 2110, 2007, 2351, 2352, - 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, - 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, - 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, - 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, - 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, - 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, - 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, - 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, - 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013, - 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, - 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, - 2035, 2036, 2037, 2038, 2039, 2041, 2042, 2043, 2044, 2045, - 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, - 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, - 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, - 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, - 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, - 2096, 2097, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, - 2107, 2108, 2109, 2112, 2113, 2114, 2115, 2116, 2117, 2118, - 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, - 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, - 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, - 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, - 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, - 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, - 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, - 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, - 2199, 2200, 2201, 2202, 2205, 2206, 2207, 2208, 2209, 2210, - 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, - 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, - 2231, 2232, 2233, 2234, 2235, -2, 2237, 2238, 2239, 2240, - 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, - 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, - 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, - 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2280, 2281, - 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, - 2292, 2293, 2294, -2, -2, -2, 2298, 2299, 2300, 2301, - 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2310, 2311, 2312, - 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, - 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, - 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 0, 323, - 321, 1979, 2007, 2014, 2040, 2098, 2110, 2111, 2150, 2203, - 2204, 2236, 2279, 2295, 2296, 2297, 2309, 0, 0, 1035, - 0, 360, 740, 741, 768, 835, 863, 801, 0, 806, - 1420, 0, 700, 0, 398, 0, 2030, 402, 2286, 0, - 0, 0, 0, 697, 392, 393, 394, 395, 396, 397, - 0, 0, 1008, 0, 0, 388, 0, 354, 2100, 2308, - 1477, 0, 0, 0, 0, 0, 210, 1162, 212, 1164, - 216, 224, 0, 0, 0, 229, 230, 233, 234, 235, - 236, 237, 0, 241, 0, 243, 246, 0, 248, 249, - 0, 252, 253, 254, 0, 264, 265, 266, 1165, 1166, - 1167, 1168, 1169, 1170, 1171, 1172, -2, 139, 1033, 1934, - 1820, 0, 1827, 1840, 1851, 1561, 1562, 1563, 1564, 0, - 0, 0, 0, 0, 0, 1572, 1573, 0, 1616, 2355, - 2398, 2399, 0, 1582, 1583, 1584, 1585, 1586, 1587, 0, - 150, 162, 163, 1873, 1874, 1875, 1876, 1877, 1878, 1879, - 0, 1881, 1882, 1883, 1791, 1546, 1473, 0, 2364, 0, - 2386, 2393, 2394, 2395, 2396, 2385, 0, 0, 1775, 0, - 1765, 0, 0, -2, -2, 0, 0, 2176, -2, 2400, - 2401, 2402, 2361, 2382, 2390, 2391, 2392, 2365, 2366, 2389, - 2357, 2358, 2359, 2352, 2353, 2354, 2356, 2368, 2370, 2381, - 0, 2377, 2387, 2388, 2284, 0, 0, 2331, 0, 0, - 0, 0, 0, 0, 2336, 2337, 2338, 2339, 2340, 2326, - 164, 165, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, -2, 1786, - -2, 1788, -2, 1790, -2, 1793, -2, -2, -2, -2, - 1798, 1799, -2, 1801, -2, -2, -2, -2, -2, -2, - -2, 1777, 1778, 1779, 1780, 1769, 1770, 1771, 1772, 1773, - 1774, -2, -2, -2, 863, 956, 0, 863, 0, 836, - 885, 888, 891, 894, 839, 0, 0, 112, 113, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 349, 350, 338, 340, 0, 344, 0, 0, 340, 337, - 331, 0, 1214, 1214, 1214, 0, 0, 0, 1214, 1214, - 1214, 1214, 1214, 0, 1214, 0, 0, 0, 0, 0, - 1214, 0, 1070, 1174, 1175, 1176, 1212, 1213, 1306, 0, - 0, 0, 801, 0, 849, 0, 851, 854, 756, 752, - 753, 754, 755, 0, 0, 677, 677, 923, 923, 0, - 623, 0, 0, 0, 677, 0, 637, 629, 0, 0, - 0, 677, 0, 0, 856, 856, 0, 680, 687, 677, - 677, -2, 677, 677, 674, 677, 0, 0, 1228, 643, - 644, 645, 629, 629, 648, 649, 650, 660, 661, 688, - 1958, 0, 0, 551, 551, 0, 551, 551, 551, 0, - 551, 551, 551, 0, 758, 2056, 2145, 2037, 2116, 1989, - 2100, 2308, 0, 296, 2176, 301, 0, 2039, 2059, 0, - 0, 2078, 0, -2, 0, 376, 863, 0, 0, 835, - 0, 0, 0, 0, 551, 551, 551, 551, 551, 1305, - 551, 551, 551, 551, 551, 0, 0, 0, 551, 551, - 551, 551, 0, 899, 900, 902, 903, 904, 905, 906, - 907, 908, 909, 910, 911, 5, 6, 19, 0, 0, - 0, 0, 0, 0, 118, 117, 0, 1935, 1953, 1886, - 1887, 1888, 1940, 1890, 1944, 1944, 1944, 1944, 1919, 1920, - 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1944, 1944, - 0, 0, 1933, 1910, 1942, 1942, 1942, 1940, 1937, 1891, + 19, 0, 0, 0, 1474, 1475, 1476, 1477, 2311, 2281, + -2, 2041, 2015, 2205, 2206, 2100, 2112, 2008, 2353, 2354, + 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, + 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, + 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, + 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, + 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, + 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, + 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, + 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, + 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + 2004, 2005, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014, + 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, + 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, + 2036, 2037, 2038, 2039, 2040, 2042, 2043, 2044, 2045, 2046, + 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, + 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, + 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, + 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, + 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, + 2097, 2098, 2099, 2101, 2102, 2103, 2104, 2105, 2106, 2107, + 2108, 2109, 2110, 2111, 2114, 2115, 2116, 2117, 2118, 2119, + 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, + 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, + 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, + 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, + 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, + 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, + 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, + 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, + 2200, 2201, 2202, 2203, 2204, 2207, 2208, 2209, 2210, 2211, + 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, + 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, + 2232, 2233, 2234, 2235, 2236, 2237, -2, 2239, 2240, 2241, + 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, + 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, + 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, + 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2282, + 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, + 2293, 2294, 2295, 2296, -2, -2, -2, 2300, 2301, 2302, + 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2312, 2313, + 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, + 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, + 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 0, + 323, 321, 1980, 2008, 2015, 2041, 2100, 2112, 2113, 2152, + 2205, 2206, 2238, 2281, 2297, 2298, 2299, 2311, 0, 0, + 1035, 0, 360, 740, 741, 768, 835, 863, 801, 0, + 806, 1421, 0, 700, 0, 398, 0, 2031, 402, 2288, + 0, 0, 0, 0, 697, 392, 393, 394, 395, 396, + 397, 0, 0, 1008, 0, 0, 388, 0, 354, 2102, + 2310, 1478, 0, 0, 0, 0, 0, 210, 1162, 212, + 1164, 216, 224, 0, 0, 0, 229, 230, 233, 234, + 235, 236, 237, 0, 241, 0, 243, 246, 0, 248, + 249, 0, 252, 253, 254, 0, 264, 265, 266, 1165, + 1166, 1167, 1168, 1169, 1170, 1171, 1172, -2, 139, 1033, + 1935, 1821, 0, 1828, 1841, 1852, 1562, 1563, 1564, 1565, + 0, 0, 0, 0, 0, 0, 1573, 1574, 0, 1617, + 2357, 2400, 2401, 0, 1583, 1584, 1585, 1586, 1587, 1588, + 0, 150, 162, 163, 1874, 1875, 1876, 1877, 1878, 1879, + 1880, 0, 1882, 1883, 1884, 1792, 1547, 1474, 0, 2366, + 0, 2388, 2395, 2396, 2397, 2398, 2387, 0, 0, 1776, + 0, 1766, 0, 0, -2, -2, 0, 0, 2178, -2, + 2402, 2403, 2404, 2363, 2384, 2392, 2393, 2394, 2367, 2368, + 2391, 2359, 2360, 2361, 2354, 2355, 2356, 2358, 2370, 2372, + 2383, 0, 2379, 2389, 2390, 2286, 0, 0, 2333, 0, + 0, 0, 0, 0, 0, 2338, 2339, 2340, 2341, 2342, + 2328, 164, 165, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + 1787, -2, 1789, -2, 1791, -2, 1794, -2, -2, -2, + -2, 1799, 1800, -2, 1802, -2, -2, -2, -2, -2, + -2, -2, 1778, 1779, 1780, 1781, 1770, 1771, 1772, 1773, + 1774, 1775, -2, -2, -2, 863, 956, 0, 863, 0, + 836, 885, 888, 891, 894, 839, 0, 0, 112, 113, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 349, 350, 338, 340, 0, 344, 0, 0, 340, + 337, 331, 0, 1214, 1214, 1214, 0, 0, 0, 1214, + 1214, 1214, 1214, 1214, 0, 1214, 0, 0, 0, 0, + 0, 1214, 0, 1070, 1174, 1175, 1176, 1212, 1213, 1307, + 0, 0, 0, 801, 0, 849, 0, 851, 854, 756, + 752, 753, 754, 755, 0, 0, 677, 677, 923, 923, + 0, 623, 0, 0, 0, 677, 0, 637, 629, 0, + 0, 0, 677, 0, 0, 856, 856, 0, 680, 687, + 677, 677, -2, 677, 677, 674, 677, 0, 0, 1228, + 643, 644, 645, 629, 629, 648, 649, 650, 660, 661, + 688, 1959, 0, 0, 551, 551, 0, 551, 551, 551, + 0, 551, 551, 551, 0, 758, 2057, 2147, 2038, 2118, + 1990, 2102, 2310, 0, 296, 2178, 301, 0, 2040, 2060, + 0, 0, 2079, 0, -2, 0, 376, 863, 0, 0, + 835, 0, 0, 0, 0, 551, 551, 551, 551, 551, + 1306, 551, 551, 551, 551, 551, 0, 0, 0, 551, + 551, 551, 551, 0, 899, 900, 902, 903, 904, 905, + 906, 907, 908, 909, 910, 911, 5, 6, 19, 0, + 0, 0, 0, 0, 0, 118, 117, 0, 1936, 1954, + 1887, 1888, 1889, 1941, 1891, 1945, 1945, 1945, 1945, 1920, + 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1945, + 1945, 0, 0, 1934, 1911, 1943, 1943, 1943, 1941, 1938, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, - 1902, 1903, 1904, 1947, 1947, 1950, 1950, 1947, 0, 440, - 438, 439, 1816, 0, 0, 863, -2, 0, 0, 0, - 0, 805, 1418, 0, 0, 0, 701, 399, 1478, 0, - 0, 403, 0, 404, 0, 0, 406, 0, 0, 0, - 428, 0, 431, 414, 415, 416, 417, 418, 410, 0, - 190, 0, 390, 391, 0, 0, 356, 0, 0, 0, - 552, 0, 0, 0, 0, 0, 0, 221, 217, 225, - 228, 238, 245, 0, 257, 259, 262, 218, 226, 231, - 232, 239, 260, 219, 222, 223, 227, 261, 263, 220, - 240, 244, 258, 242, 247, 250, 251, 256, 0, 191, - 0, 0, 0, 0, 0, 1826, 0, 0, 1859, 1860, - 1861, 1862, 1863, 1864, 1865, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -2, 1820, 0, - 0, 1567, 1568, 1569, 1570, 0, 1574, 0, 1617, 0, - 0, 0, 0, 0, 0, 1880, 1884, 0, 1816, 1816, - 0, 1816, 1812, 0, 0, 0, 0, 0, 0, 1816, - 1748, 0, 0, 1750, 1766, 0, 0, 1752, 1753, 0, - 1756, 1757, 1816, 0, 1816, 1761, 1816, 1816, 1816, 1742, - 1743, 0, 0, 0, 1812, 1812, 1812, 1812, 0, 0, - 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, 1812, - 1812, 1812, 1812, 1812, 1812, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 856, 0, 864, - 0, -2, 0, 882, 884, 886, 887, 889, 890, 892, - 893, 895, 896, 841, 0, 0, 114, 0, 0, 0, - 97, 0, 0, 95, 0, 0, 0, 0, 73, 75, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 342, 0, 347, 333, 2137, 0, 332, 0, 0, 0, - 0, 0, 1032, 0, 0, 1214, 1214, 1214, 1071, 0, - 0, 0, 0, 0, 0, 0, 0, 1214, 1214, 1214, - 1214, 0, 1234, 0, 0, 0, 0, 801, 0, 850, - 0, 0, 758, 757, 72, 612, 613, 614, 923, 0, - 0, 616, 617, 0, 618, 0, 0, 629, 677, 677, - 635, 636, 631, 630, 683, 684, 680, 0, 680, 680, - 923, 0, 654, 655, 656, 677, 677, 662, 857, 0, - 663, 664, 680, 0, 685, 686, 923, 0, 0, 923, - 923, 0, 672, 673, 675, 677, 0, 0, 1214, 0, - 693, 631, 631, 1959, 1960, 0, 0, 1225, 0, 0, - 0, 0, 0, 696, 0, 0, 0, 457, 458, 0, - 0, 759, 0, 275, 279, 0, 282, 0, 2145, 0, - 2145, 0, 0, 289, 0, 0, 0, 0, 0, 0, - 319, 320, 0, 0, 0, 0, 310, 313, 1412, 1413, - 1159, 1160, 314, 315, 368, 369, 0, 856, 881, 883, - 877, 878, 879, 0, 1216, 0, 0, 0, 0, 0, - 551, 0, 0, 0, 0, 0, 734, 0, 1050, 736, - 0, 0, 0, 0, 0, 931, 925, 927, 1003, 150, - 901, 8, 135, 132, 0, 19, 0, 0, 19, 19, - 0, 19, 324, 0, 1956, 1954, 1955, 1889, 1941, 0, - 1915, 0, 1916, 1917, 1918, 1929, 1930, 0, 0, 1911, - 0, 1912, 1913, 1914, 1905, 0, 1906, 1907, 0, 1908, - 1909, 322, 437, 0, 0, 1817, 1036, 0, 856, 833, - 0, 861, 0, 760, 793, 762, 0, 782, 0, 1420, - 0, 0, 0, 0, 551, 0, 400, 0, 411, 405, - 0, 412, 407, 408, 0, 0, 430, 432, 433, 434, - 435, 419, 420, 698, 385, 386, 387, 377, 378, 379, - 380, 381, 382, 383, 384, 0, 0, 389, 160, 0, - 357, 358, 0, 0, 0, 204, 205, 206, 207, 208, - 209, 211, 195, 723, 725, 1151, 1163, 0, 1154, 0, - 214, 255, 187, 0, 0, 0, 1821, 1822, 1823, 1824, - 1825, 1830, 0, 1832, 1834, 1836, 1838, 0, 1856, -2, - -2, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, - 1556, 1557, 1558, 1559, 1560, 1841, 1854, 1855, 0, 0, - 0, 0, 0, 0, 1852, 1852, 1847, 0, 1579, 1621, - 1633, 1633, 1588, 1414, 1415, 1565, 0, 0, 1614, 1618, - 0, 0, 0, 0, 0, 0, 1196, 1940, 0, 151, - 1811, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, + 1902, 1903, 1904, 1905, 1948, 1948, 1951, 1951, 1948, 0, + 440, 438, 439, 1817, 0, 0, 863, -2, 0, 0, + 0, 0, 805, 1419, 0, 0, 0, 701, 399, 1479, + 0, 0, 403, 0, 404, 0, 0, 406, 0, 0, + 0, 428, 0, 431, 414, 415, 416, 417, 418, 410, + 0, 190, 0, 390, 391, 0, 0, 356, 0, 0, + 0, 552, 0, 0, 0, 0, 0, 0, 221, 217, + 225, 228, 238, 245, 0, 257, 259, 262, 218, 226, + 231, 232, 239, 260, 219, 222, 223, 227, 261, 263, + 220, 240, 244, 258, 242, 247, 250, 251, 256, 0, + 191, 0, 0, 0, 0, 0, 1827, 0, 0, 1860, + 1861, 1862, 1863, 1864, 1865, 1866, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -2, 1821, + 0, 0, 1568, 1569, 1570, 1571, 0, 1575, 0, 1618, + 0, 0, 0, 0, 0, 0, 1881, 1885, 0, 1817, + 1817, 0, 1817, 1813, 0, 0, 0, 0, 0, 0, + 1817, 1749, 0, 0, 1751, 1767, 0, 0, 1753, 1754, + 0, 1757, 1758, 1817, 0, 1817, 1762, 1817, 1817, 1817, + 1743, 1744, 0, 0, 0, 1813, 1813, 1813, 1813, 0, + 0, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, 1813, + 1813, 1813, 1813, 1813, 1813, 1813, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 856, 0, + 864, 0, -2, 0, 882, 884, 886, 887, 889, 890, + 892, 893, 895, 896, 841, 0, 0, 114, 0, 0, + 0, 97, 0, 0, 95, 0, 0, 0, 0, 73, + 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 342, 0, 347, 333, 2139, 0, 332, 0, 0, + 0, 0, 0, 1032, 0, 0, 1214, 1214, 1214, 1071, + 0, 0, 0, 0, 0, 0, 0, 0, 1214, 1214, + 1214, 1214, 0, 1234, 0, 0, 0, 0, 801, 0, + 850, 0, 0, 758, 757, 72, 612, 613, 614, 923, + 0, 0, 616, 617, 0, 618, 0, 0, 629, 677, + 677, 635, 636, 631, 630, 683, 684, 680, 0, 680, + 680, 923, 0, 654, 655, 656, 677, 677, 662, 857, + 0, 663, 664, 680, 0, 685, 686, 923, 0, 0, + 923, 923, 0, 672, 673, 675, 677, 0, 0, 1214, + 0, 693, 631, 631, 1960, 1961, 0, 0, 1225, 0, + 0, 0, 0, 0, 696, 0, 0, 0, 457, 458, + 0, 0, 759, 0, 275, 279, 0, 282, 0, 2147, + 0, 2147, 0, 0, 289, 0, 0, 0, 0, 0, + 0, 319, 320, 0, 0, 0, 0, 310, 313, 1413, + 1414, 1159, 1160, 314, 315, 368, 369, 0, 856, 881, + 883, 877, 878, 879, 0, 1216, 0, 0, 0, 0, + 0, 551, 0, 0, 0, 0, 0, 734, 0, 1050, + 736, 0, 0, 0, 0, 0, 931, 925, 927, 1003, + 150, 901, 8, 135, 132, 0, 19, 0, 0, 19, + 19, 0, 19, 324, 0, 1957, 1955, 1956, 1890, 1942, + 0, 1916, 0, 1917, 1918, 1919, 1930, 1931, 0, 0, + 1912, 0, 1913, 1914, 1915, 1906, 0, 1907, 1908, 0, + 1909, 1910, 322, 437, 0, 0, 1818, 1036, 0, 856, + 833, 0, 861, 0, 760, 793, 762, 0, 782, 0, + 1421, 0, 0, 0, 0, 551, 0, 400, 0, 411, + 405, 0, 412, 407, 408, 0, 0, 430, 432, 433, + 434, 435, 419, 420, 698, 385, 386, 387, 377, 378, + 379, 380, 381, 382, 383, 384, 0, 0, 389, 160, + 0, 357, 358, 0, 0, 0, 204, 205, 206, 207, + 208, 209, 211, 195, 723, 725, 1151, 1163, 0, 1154, + 0, 214, 255, 187, 0, 0, 0, 1822, 1823, 1824, + 1825, 1826, 1831, 0, 1833, 1835, 1837, 1839, 0, 1857, + -2, -2, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, + 1556, 1557, 1558, 1559, 1560, 1561, 1842, 1855, 1856, 0, + 0, 0, 0, 0, 0, 1853, 1853, 1848, 0, 1580, + 1622, 1634, 1634, 1589, 1415, 1416, 1566, 0, 0, 1615, + 1619, 0, 0, 0, 0, 0, 0, 1196, 1941, 0, + 151, 1812, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, - 0, 0, 1820, 0, 0, 0, 1813, 1814, 0, 0, - 0, 1697, 0, 0, 1703, 1704, 1705, 0, 788, 0, - 1776, 1749, 1767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1738, 1739, 1740, 1741, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 955, 957, 0, 797, 799, - 800, 830, 861, 837, 0, 0, 0, 110, 115, 0, - 1273, 103, 0, 0, 0, 103, 0, 0, 0, 103, - 0, 0, 76, 1229, 77, 1231, 0, 0, 0, 0, - 0, 0, 351, 352, 0, 0, 346, 334, 2137, 336, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1086, 1087, 549, 1145, 0, 0, 0, 1161, 1200, - 1210, 0, 0, 0, 0, 0, 1279, 1072, 1077, 1078, - 1079, 1073, 1074, 1080, 1081, 779, 793, 774, 0, 782, - 0, 852, 0, 0, 972, 0, 615, 678, 679, 924, - 619, 0, 0, 626, 2100, 631, 923, 923, 638, 632, - 639, 682, 640, 641, 642, 680, 923, 923, 858, 677, - 680, 665, 681, 680, 1420, 669, 0, 676, 1420, 694, - 1420, 0, 692, 646, 647, 1281, 854, 455, 456, 461, - 463, 0, 513, 513, 513, 496, 513, 0, 0, 484, - 1961, 0, 0, 0, 0, 493, 1961, 0, 0, 1961, - 1961, 1961, 1961, 1961, 1961, 1961, 0, 0, 1961, 1961, - 1961, 1961, 1961, 1961, 1961, 1961, 1961, 1961, 1961, 0, - 1961, 1961, 1961, 1961, 1961, 1398, 1961, 0, 1226, 503, - 504, 505, 506, 511, 512, 0, 0, 0, 544, 0, - 0, 1085, 0, 549, 0, 0, 1127, 0, 0, 936, - 0, 937, 938, 939, 934, 974, 998, 998, 0, 998, - 978, 1420, 0, 0, 0, 287, 288, 276, 0, 277, - 0, 0, 290, 291, 0, 293, 294, 295, 302, 2037, - 2116, 297, 299, 0, 0, 303, 316, 317, 318, 0, - 0, 308, 309, 0, 0, 371, 372, 374, 0, 861, - 1230, 74, 1217, 720, 1416, 721, 722, 726, 0, 0, - 729, 730, 731, 732, 733, 1052, 0, 0, 1136, 1137, - 1139, 1216, 923, 0, 932, 0, 928, 1004, 0, 1006, - 0, 0, 133, 19, 0, 126, 123, 0, 0, 0, - 0, 0, 1936, 1885, 1957, 0, 0, 0, 1938, 0, - 0, 0, 0, 0, 116, 813, 861, 0, 807, 0, - 865, 866, 869, 761, 790, 0, 794, 0, 0, 786, - 766, 783, 0, 0, 803, 1419, 0, 0, 0, 0, - 0, 1479, 0, 413, 409, 429, 0, 0, 0, 0, - 198, 1148, 0, 199, 203, 193, 0, 0, 0, 1153, - 0, 1150, 1155, 0, 213, 0, 0, 188, 189, 1264, - 1273, 0, 0, 0, 1831, 1833, 1835, 1837, 1839, 0, - 1842, 1852, 1852, 1848, 0, 1843, 0, 1845, 0, 1622, - 1634, 1635, 1623, 1821, 1571, 0, 1619, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 869, 0, 0, 1687, - 1688, 0, 0, 1692, 0, 1694, 1695, 1696, 1698, 0, - 0, 0, 1702, 0, 1747, 1768, 1751, 1754, 0, 1758, - 0, 1760, 1762, 1763, 1764, 0, 0, 0, 863, 863, - 0, 0, 1658, 1658, 1658, 0, 0, 0, 0, 1658, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1591, 0, 1592, 1593, 1594, 0, 1596, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 958, 807, - 0, 0, 0, 0, 0, 1271, 0, 93, 0, 98, - 0, 0, 94, 99, 0, 0, 96, 0, 105, 78, - 0, 0, 1237, 1238, 0, 0, 353, 341, 343, 0, - 335, 0, 1215, 0, 0, 0, 0, -2, 1052, 854, - 0, 854, 1097, 1961, 553, 0, 0, 1147, 0, 1116, - 0, 0, 0, -2, 0, 0, 0, 1210, 0, 0, - 0, 1283, 0, 769, 0, 773, 0, 0, 778, 770, - 23, 855, 0, 0, 0, 745, 749, 622, 620, 0, - 624, 0, 625, 677, 633, 634, 923, 657, 658, 0, - 0, 923, 677, 677, 668, 680, 689, 0, 690, 1420, - 1283, 0, 0, 1225, 1349, 1317, 474, 0, 1433, 1434, - 514, 0, 1440, 1449, 1214, 1511, 0, 1449, 0, 0, - 1451, 1452, 0, 0, 0, 0, 497, 498, 0, 483, - 0, 0, 0, 0, 0, 0, 482, 0, 0, 524, - 0, 0, 0, 0, 0, 1962, 1961, 1961, 0, 491, - 492, 0, 495, 0, 0, 0, 0, 0, 0, 0, - 0, 1961, 1961, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1389, 0, 0, 0, 0, 0, - 0, 0, 1404, 1405, 0, 0, 1097, 1961, 0, 0, - 0, 0, 553, 1142, 1142, 1114, 1132, 0, 459, 460, - 521, 0, 0, 0, 0, 0, 0, 0, 964, 0, - 0, 0, 963, 0, 0, 0, 0, 0, 0, 0, - 854, 999, 0, 1001, 1002, 976, -2, 0, 936, 981, - 1816, 0, 280, 281, 0, 0, 286, 304, 306, 278, - 0, 0, 0, 305, 307, 311, 312, 370, 373, 375, - 807, 0, 0, 1307, 0, 1053, 1054, 1056, 1057, 0, + 1738, 0, 0, 1821, 0, 0, 0, 1814, 1815, 0, + 0, 0, 1698, 0, 0, 1704, 1705, 1706, 0, 788, + 0, 1777, 1750, 1768, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1739, 1740, 1741, 1742, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 955, 957, 0, 797, + 799, 800, 830, 861, 837, 0, 0, 0, 110, 115, + 0, 1274, 103, 0, 0, 0, 103, 0, 0, 0, + 103, 0, 0, 76, 1229, 77, 1231, 0, 0, 0, + 0, 0, 0, 351, 352, 0, 0, 346, 334, 2139, + 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1086, 1087, 549, 1145, 0, 0, 0, 1161, + 1200, 1210, 0, 0, 0, 0, 0, 1280, 1072, 1077, + 1078, 1079, 1073, 1074, 1080, 1081, 779, 793, 774, 0, + 782, 0, 852, 0, 0, 972, 0, 615, 678, 679, + 924, 619, 0, 0, 626, 2102, 631, 923, 923, 638, + 632, 639, 682, 640, 641, 642, 680, 923, 923, 858, + 677, 680, 665, 681, 680, 1421, 669, 0, 676, 1421, + 694, 1421, 0, 692, 646, 647, 1282, 854, 455, 456, + 461, 463, 0, 513, 513, 513, 496, 513, 0, 0, + 484, 1962, 0, 0, 0, 0, 493, 1962, 0, 0, + 1962, 1962, 1962, 1962, 1962, 1962, 1962, 0, 0, 1962, + 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, + 0, 1962, 1962, 1962, 1962, 1962, 1399, 1962, 0, 1226, + 503, 504, 505, 506, 511, 512, 0, 0, 0, 544, + 0, 0, 1085, 0, 549, 0, 0, 1127, 0, 0, + 936, 0, 937, 938, 939, 934, 974, 998, 998, 0, + 998, 978, 1421, 0, 0, 0, 287, 288, 276, 0, + 277, 0, 0, 290, 291, 0, 293, 294, 295, 302, + 2038, 2118, 297, 299, 0, 0, 303, 316, 317, 318, + 0, 0, 308, 309, 0, 0, 371, 372, 374, 0, + 861, 1230, 74, 1217, 720, 1417, 721, 722, 726, 0, + 0, 729, 730, 731, 732, 733, 1052, 0, 0, 1136, + 1137, 1139, 1216, 923, 0, 932, 0, 928, 1004, 0, + 1006, 0, 0, 133, 19, 0, 126, 123, 0, 0, + 0, 0, 0, 1937, 1886, 1958, 0, 0, 0, 1939, + 0, 0, 0, 0, 0, 116, 813, 861, 0, 807, + 0, 865, 866, 869, 761, 790, 0, 794, 0, 0, + 786, 766, 783, 0, 0, 803, 1420, 0, 0, 0, + 0, 0, 1480, 0, 413, 409, 429, 0, 0, 0, + 0, 198, 1148, 0, 199, 203, 193, 0, 0, 0, + 1153, 0, 1150, 1155, 0, 213, 0, 0, 188, 189, + 1265, 1274, 0, 0, 0, 1832, 1834, 1836, 1838, 1840, + 0, 1843, 1853, 1853, 1849, 0, 1844, 0, 1846, 0, + 1623, 1635, 1636, 1624, 1822, 1572, 0, 1620, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 869, 0, 0, + 1688, 1689, 0, 0, 1693, 0, 1695, 1696, 1697, 1699, + 0, 0, 0, 1703, 0, 1748, 1769, 1752, 1755, 0, + 1759, 0, 1761, 1763, 1764, 1765, 0, 0, 0, 863, + 863, 0, 0, 1659, 1659, 1659, 0, 0, 0, 0, + 1659, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1592, 0, 1593, 1594, 1595, 0, 1597, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 958, + 807, 0, 0, 0, 0, 0, 1272, 0, 93, 0, + 98, 0, 0, 94, 99, 0, 0, 96, 0, 105, + 78, 0, 0, 1237, 1238, 0, 0, 353, 341, 343, + 0, 335, 0, 1215, 0, 0, 0, 0, -2, 1052, + 854, 0, 854, 1097, 1962, 553, 0, 0, 1147, 0, + 1116, 0, 0, 0, -2, 0, 0, 0, 1210, 0, + 0, 0, 1284, 0, 769, 0, 773, 0, 0, 778, + 770, 23, 855, 0, 0, 0, 745, 749, 622, 620, + 0, 624, 0, 625, 677, 633, 634, 923, 657, 658, + 0, 0, 923, 677, 677, 668, 680, 689, 0, 690, + 1421, 1284, 0, 0, 1225, 1350, 1318, 474, 0, 1434, + 1435, 514, 0, 1441, 1450, 1214, 1512, 0, 1450, 0, + 0, 1452, 1453, 0, 0, 0, 0, 497, 498, 0, + 483, 0, 0, 0, 0, 0, 0, 482, 0, 0, + 524, 0, 0, 0, 0, 0, 1963, 1962, 1962, 0, + 491, 492, 0, 495, 0, 0, 0, 0, 0, 0, + 0, 0, 1962, 1962, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1390, 0, 0, 0, 0, + 0, 0, 0, 1405, 1406, 0, 0, 1097, 1962, 0, + 0, 0, 0, 553, 1142, 1142, 1114, 1132, 0, 459, + 460, 521, 0, 0, 0, 0, 0, 0, 0, 964, + 0, 0, 0, 963, 0, 0, 0, 0, 0, 0, + 0, 854, 999, 0, 1001, 1002, 976, -2, 0, 936, + 981, 1817, 0, 280, 281, 0, 0, 286, 304, 306, + 278, 0, 0, 0, 305, 307, 311, 312, 370, 373, + 375, 807, 0, 0, 1308, 0, 1053, 1054, 1056, 1057, + 0, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, 2022, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, 2021, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, 1051, 737, 1140, 914, 926, - 933, 1005, 1007, 151, 929, 0, 136, 19, 135, 127, - 128, 0, 19, 0, 0, 0, 0, 1946, 1945, 1931, - 0, 1932, 1943, 1948, 0, 1951, 0, 441, 817, 0, - 807, 809, 834, 0, 0, 872, 870, 871, 793, 795, - 0, 0, 793, 0, 0, 802, 0, 0, 0, 0, - 0, 0, 1138, 0, 0, 699, 161, 436, 0, 0, - 0, 0, 0, 724, 0, 1152, 195, 0, 0, 215, - 0, 0, 0, 1273, 1268, 1815, 1844, 1846, 0, 1853, - 1849, 1566, 1575, 1615, 0, 0, 0, 0, 0, 1624, - 1944, 1944, 1627, 1940, 1942, 1940, 1633, 1633, 0, 1197, - 0, 1198, 869, 152, 0, 0, 1693, 0, 0, 0, - 789, 0, 0, 0, 0, 0, 1654, 1656, 1658, 1658, - 1665, 1659, 1666, 1667, 1658, 1658, 1658, 1658, 1672, 1658, - 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, 1658, - 1652, 1595, 1597, 0, 1600, 0, 1603, 1604, 0, 0, - 0, 1874, 1875, 798, 831, 0, 0, 844, 845, 846, - 847, 848, 0, 0, 63, 63, 1273, 0, 0, 0, - 0, 0, 109, 0, 0, 0, 0, 0, 1241, 1246, - 345, 0, 79, 80, 82, 0, 0, 0, 0, 0, - 0, 0, 92, 0, 0, 1038, 1039, 1041, 0, 1044, - 1045, 1046, 0, 0, 1426, 0, 1101, 1098, 1099, 1100, - 0, 1142, 554, 555, 556, 557, 0, 0, 0, 1146, - 0, 0, 1109, 0, 0, 0, 1201, 1202, 1203, 1204, - 1205, 1206, 1207, 1208, -2, 1220, 0, 1420, 0, 0, - 1426, 1256, 0, 0, 1261, 0, 1426, 1426, 0, 1291, - 0, 1280, 0, 0, 793, 0, 973, 801, 0, -2, - 0, 0, 747, 0, 621, 627, 923, 651, 859, 860, - 1420, 923, 923, 677, 695, 691, 1291, 1282, 0, 462, - 513, 0, 1337, 0, 0, 1343, 0, 1350, 467, 0, - 515, 0, 1439, 1467, 1450, 1467, 1512, 1467, 1467, 1214, - 0, 515, 0, 0, 485, 0, 0, 0, 0, 0, - 481, 518, 869, 468, 470, 471, 472, 522, 523, 525, - 0, 527, 528, 487, 499, 500, 501, 502, 0, 0, - 0, 494, 507, 508, 509, 510, 469, 1366, 1367, 1368, - 1371, 1372, 1373, 1374, 0, 0, 1377, 1378, 1379, 1380, - 1381, 1464, 1465, 1466, 1382, 1383, 1384, 1385, 1386, 1387, - 1388, 1406, 1407, 1408, 1409, 1410, 1411, 1390, 1391, 1392, - 1393, 1394, 1395, 1396, 1397, 0, 0, 1401, 0, 0, - 0, 1101, 0, 0, 0, 0, 0, 1142, 547, 0, - 0, 548, 1116, 0, 1134, 0, 1128, 1129, 0, 0, - 771, 923, 363, 0, 968, 959, 0, 943, 0, 945, - 965, 946, 966, 0, 0, 950, 0, 952, 0, 948, - 949, 954, 947, 923, 935, 975, 1000, 977, 980, 982, - 983, 989, 0, 0, 0, 0, 274, 283, 284, 285, - 292, 0, 573, 298, 875, 1417, 727, 728, 1308, 1309, - 735, 0, 1058, 912, 0, 0, 131, 134, 0, 129, - 0, 0, 0, 0, 121, 119, 1939, 0, 0, 819, - 175, 0, 0, 875, 811, 0, 0, 867, 868, 0, - 791, 0, 796, 793, 765, 787, 764, 784, 785, 804, - 1421, 1422, 1423, 1424, 0, 1480, 401, 0, 1149, 195, - 200, 201, 202, 196, 194, 1156, 0, 1158, 0, 1266, - 0, 0, 1850, 1620, 1576, 0, 1578, 1580, 1625, 1626, - 1628, 1629, 1630, 1631, 1632, 1581, 0, 1199, 1689, 0, - 1691, 1699, 1700, 0, 1755, 1759, 0, 0, 1746, 0, - 0, 0, 0, 1663, 1664, 1668, 1669, 1670, 1671, 1673, + -2, -2, -2, -2, -2, -2, 1051, 737, 1140, 914, + 926, 933, 1005, 1007, 151, 929, 0, 136, 19, 135, + 127, 128, 0, 19, 0, 0, 0, 0, 1947, 1946, + 1932, 0, 1933, 1944, 1949, 0, 1952, 0, 441, 817, + 0, 807, 809, 834, 0, 0, 872, 870, 871, 793, + 795, 0, 0, 793, 0, 0, 802, 0, 0, 0, + 0, 0, 0, 1138, 0, 0, 699, 161, 436, 0, + 0, 0, 0, 0, 724, 0, 1152, 195, 0, 0, + 215, 0, 0, 0, 1274, 1269, 1816, 1845, 1847, 0, + 1854, 1850, 1567, 1576, 1616, 0, 0, 0, 0, 0, + 1625, 1945, 1945, 1628, 1941, 1943, 1941, 1634, 1634, 0, + 1197, 0, 1198, 869, 152, 0, 0, 1694, 0, 0, + 0, 789, 0, 0, 0, 0, 0, 1655, 1657, 1659, + 1659, 1666, 1660, 1667, 1668, 1659, 1659, 1659, 1659, 1673, + 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, + 1659, 1653, 1596, 1598, 0, 1601, 0, 1604, 1605, 0, + 0, 0, 1875, 1876, 798, 831, 0, 0, 844, 845, + 846, 847, 848, 0, 0, 63, 63, 1274, 0, 0, + 0, 0, 0, 109, 0, 0, 0, 0, 0, 1241, + 1247, 345, 0, 79, 80, 82, 0, 0, 0, 0, + 0, 0, 0, 92, 0, 0, 1038, 1039, 1041, 0, + 1044, 1045, 1046, 0, 0, 1427, 0, 1101, 1098, 1099, + 1100, 0, 1142, 554, 555, 556, 557, 0, 0, 0, + 1146, 0, 0, 1109, 0, 0, 0, 1201, 1202, 1203, + 1204, 1205, 1206, 1207, 1208, -2, 1220, 0, 1421, 0, + 0, 1427, 1257, 0, 0, 1262, 0, 1427, 1427, 0, + 1292, 0, 1281, 0, 0, 793, 0, 973, 801, 0, + -2, 0, 0, 747, 0, 621, 627, 923, 651, 859, + 860, 1421, 923, 923, 677, 695, 691, 1292, 1283, 0, + 462, 513, 0, 1338, 0, 0, 1344, 0, 1351, 467, + 0, 515, 0, 1440, 1468, 1451, 1468, 1513, 1468, 1468, + 1214, 0, 515, 0, 0, 485, 0, 0, 0, 0, + 0, 481, 518, 869, 468, 470, 471, 472, 522, 523, + 525, 0, 527, 528, 487, 499, 500, 501, 502, 0, + 0, 0, 494, 507, 508, 509, 510, 469, 1367, 1368, + 1369, 1372, 1373, 1374, 1375, 0, 0, 1378, 1379, 1380, + 1381, 1382, 1465, 1466, 1467, 1383, 1384, 1385, 1386, 1387, + 1388, 1389, 1407, 1408, 1409, 1410, 1411, 1412, 1391, 1392, + 1393, 1394, 1395, 1396, 1397, 1398, 0, 0, 1402, 0, + 0, 0, 1101, 0, 0, 0, 0, 0, 1142, 547, + 0, 0, 548, 1116, 0, 1134, 0, 1128, 1129, 0, + 0, 771, 923, 363, 0, 968, 959, 0, 943, 0, + 945, 965, 946, 966, 0, 0, 950, 0, 952, 0, + 948, 949, 954, 947, 923, 935, 975, 1000, 977, 980, + 982, 983, 989, 0, 0, 0, 0, 274, 283, 284, + 285, 292, 0, 573, 298, 875, 1418, 727, 728, 1309, + 1310, 735, 0, 1058, 912, 0, 0, 131, 134, 0, + 129, 0, 0, 0, 0, 121, 119, 1940, 0, 0, + 819, 175, 0, 0, 875, 811, 0, 0, 867, 868, + 0, 791, 0, 796, 793, 765, 787, 764, 784, 785, + 804, 1422, 1423, 1424, 1425, 0, 1481, 401, 0, 1149, + 195, 200, 201, 202, 196, 194, 1156, 0, 1158, 0, + 1267, 0, 0, 1851, 1621, 1577, 0, 1579, 1581, 1626, + 1627, 1629, 1630, 1631, 1632, 1633, 1582, 0, 1199, 1690, + 0, 1692, 1700, 1701, 0, 1756, 1760, 0, 0, 1747, + 0, 0, 0, 0, 1664, 1665, 1669, 1670, 1671, 1672, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, - 863, 1653, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 842, 0, 0, 0, 65, 0, - 65, 1272, 1274, 104, 106, 0, 100, 101, 102, 1003, - 1250, 1420, 1239, 0, 1240, 0, 0, 81, 83, 0, - 2101, 0, 0, 0, 0, 1216, 1031, 1047, 1043, 0, - 0, 0, 0, 1427, 1428, 1430, 1431, 1432, 0, 1069, - 0, 0, 1089, 1090, 1091, 1103, 0, 559, 560, 0, - 0, 0, 572, 568, 569, 570, 550, 1141, 1123, 0, - 0, 1112, 0, 0, 1122, 0, 1221, 1961, 1961, 1961, - 1250, 0, 0, 1351, 1961, 1961, 0, 1258, 1260, 1250, - 0, 0, 1355, 1294, 0, 0, 1285, 0, 0, 793, - 777, 776, 853, 998, 0, 0, 923, 746, 749, 750, - 628, 666, 670, 667, 923, 1294, 454, 1315, 0, 0, - 0, 0, 0, 1347, 0, 0, 1319, 0, 486, 516, - 0, -2, 0, 1468, 0, 1453, 1468, 0, 0, 1467, - 0, 475, 515, 0, 0, 0, 529, 0, 535, 536, - 1178, 532, 533, 1507, 0, 534, 0, 520, 0, 526, - 1369, 1370, 0, 1375, 1376, 0, 1400, 0, 0, 465, - 466, 539, 0, 0, 0, 540, 541, 546, 1143, 1144, - 1109, 0, 1123, 0, 1133, 0, 1130, 1131, 863, 0, - 0, 940, 969, 0, 0, 941, 0, 942, 944, 967, - 0, 961, 951, 953, 362, 984, 0, 0, 986, 987, - 988, 979, 300, 829, 0, 1055, 0, 897, 0, 0, - 930, 0, 19, 0, 0, 124, 1949, 1952, 821, 0, - 818, 176, 0, 0, 0, 832, 813, 0, 810, 0, - 873, 874, 792, 763, 1425, 197, 192, 1157, 1276, 0, - 1267, 0, 1531, 1590, 0, 1701, 0, 0, 1658, 1655, - 1658, 1657, 1649, 0, 1598, 0, 1601, 0, 1605, 1606, - 0, 1608, 1609, 1610, 0, 1612, 1613, 0, 840, 0, - 61, 0, 64, 62, 0, 108, 1235, 0, 1250, 0, - 0, 0, 1245, 0, 0, 84, 0, 0, 0, 0, - 0, 0, 90, 0, 0, 1040, 1042, 0, 1075, 1355, - 0, 1075, 1102, 1088, 0, 0, 561, 562, 0, 565, - 571, 1104, 0, 0, 1106, 1107, 1108, 0, 0, 1120, - 0, 0, 0, 0, 1209, 1211, 1227, 0, 0, 0, - -2, 1262, 0, -2, 1255, 0, 1300, 0, 1292, 0, - 1284, 0, 1287, 0, 781, 775, 923, 923, -2, 743, - 748, 0, 671, 1300, 1317, 0, 1338, 0, 0, 0, - 0, 0, 0, 0, 1318, 0, 1331, 517, 1469, -2, - 1483, 1485, 0, 1226, 1488, 1489, 0, 0, 0, 0, - 0, 0, 1538, 1497, 0, 0, 1501, 1502, 1503, 0, - 0, 1506, 0, 1868, 1869, 0, 1510, 0, 0, 0, - 0, 0, 0, 0, 1447, 476, 477, 0, 479, 480, - 1178, 0, 531, 1508, 519, 473, 1961, 489, 1399, 1402, - 1403, 545, 542, 543, 1112, 1115, 1126, 1135, 772, 856, - 364, 365, 970, 0, 960, 962, 993, 990, 0, 0, - 876, 1059, 913, 921, 2331, 2333, 2330, 125, 130, 0, - 0, 823, 0, 820, 0, 814, 816, 186, 817, 812, - 862, 146, 178, 0, 0, 1577, 0, 0, 0, 1690, - 1744, 1745, 1661, 1662, 0, 1650, 0, 1644, 1645, 1646, - 1651, 0, 0, 0, 0, 843, 838, 66, 107, 0, - 1236, 1242, 1243, 1244, 1247, 1248, 1249, 70, 1216, 0, - 1216, 0, 0, 0, 1034, 1048, 0, 1061, 1068, 1082, - 1232, 1429, 1067, 0, 0, 558, 563, 0, 566, 567, - 1124, 1123, 0, 1110, 1111, 0, 1118, 0, 0, 1222, - 1223, 1224, 1352, 1353, 1354, 1310, 1257, 0, -2, 1363, - 0, 1253, 1276, 1310, 0, 1288, 0, 1295, 0, 1293, - 1286, 780, 863, 744, 1297, 464, 1349, 1339, 0, 1341, - 0, 0, 0, 0, 1320, -2, 0, 1484, 1486, 1487, - 1490, 1491, 1492, 1543, 1544, 1545, 0, 0, 1495, 1540, - 1541, 1542, 1496, 0, 0, 0, 0, 0, 1866, 1867, - 1536, 0, 0, 1454, 1456, 1457, 1458, 1459, 1460, 1461, - 1462, 1463, 1455, 0, 0, 0, 1446, 1448, 478, 530, - 0, 1179, 1961, 1961, 0, 0, 0, 1185, 1186, 1961, - 1961, 1961, 1190, 1191, 0, 1961, 1961, 0, 1961, 1125, - 361, 0, 0, 994, 996, 991, 992, 915, 0, 0, - 0, 0, 120, 122, 137, 0, 822, 177, 0, 819, - 148, 0, 169, 0, 1277, 0, 1589, 0, 0, 0, - 1660, 1647, 0, 0, 0, 0, 0, 1870, 1871, 1872, - 0, 1599, 1602, 1607, 1611, 1251, 0, 68, 0, 85, - 1216, 86, 1216, 0, 0, 0, 0, 1083, 1084, 1092, - 1093, 0, 1095, 1096, 564, 1105, 1113, 1117, 1120, 0, - 1178, 1312, 0, 1259, 1225, 1365, 1961, 1263, 1312, 0, - 1357, 1961, 1961, 1278, 0, 1290, 0, 1302, 0, 1296, - 856, 453, 0, 1299, 1335, 1340, 1342, 1344, 0, 1348, - 1346, 1321, -2, 0, 1329, 0, 0, 1493, 1494, 0, - 0, 1765, 1961, 0, 1526, 0, 1178, 1178, 1178, 1178, - 0, 537, 538, 0, 0, 1182, 1183, 0, 0, 0, - 0, 0, 0, 0, 488, 0, 971, 985, 0, 922, - 0, 0, 0, 0, 0, 821, 138, 0, 147, 166, - 0, 179, 180, 0, 0, 0, 0, 1269, 0, 1534, - 1535, 0, 1636, 0, 0, 0, 1640, 1641, 1642, 1643, - 1216, 70, 0, 87, 88, 0, 1216, 0, 1060, 0, - 1094, 1119, 1121, 1177, 1252, 0, 1349, 1364, 0, 1254, - 1356, 0, 0, 0, 1289, 1301, 0, 1304, 742, 1298, - 1316, 0, 1345, 1322, 1330, 0, 1325, 0, 0, 0, - 1539, 0, 1500, 0, 1505, 1514, 1527, 0, 0, 1435, - 0, 1437, 0, 1441, 0, 1443, 0, 0, 1180, 1181, - 1184, 1187, 1188, 1189, 1192, 1193, 1194, 1195, 490, 995, - 997, 0, 1816, 917, 918, 0, 825, 815, 823, 149, - 153, 0, 175, 172, 0, 181, 0, 0, 0, 0, - 1265, 0, 1532, 0, 1637, 1638, 1639, 67, 69, 71, - 1216, 89, 0, 1062, 1063, 1076, 0, 1337, 1369, 1358, - 1359, 1360, 1303, 1336, 1324, 0, -2, 1332, 0, 0, - 1818, 1828, 1829, 1498, 1504, 1513, 1515, 1516, 0, 1528, - 1529, 1530, 1537, 1178, 1178, 1178, 1178, 1445, 916, 0, - 0, 824, 0, 808, 140, 0, 0, 170, 171, 173, - 0, 182, 0, 184, 185, 0, 0, 1648, 91, 1064, - 1313, 0, 1315, 1326, -2, 0, 1334, 0, 1499, 1517, - 0, 1518, 0, 0, 0, 1436, 1438, 1442, 1444, 1816, - 919, 826, 1275, 0, 154, 0, 156, 158, 159, 1470, - 167, 168, 174, 183, 0, 0, 1049, 1065, 0, 0, - 1317, 1333, 1819, 1519, 1521, 1522, 0, 0, 1520, 0, - 141, 142, 0, 155, 0, 0, 1270, 1533, 1066, 1314, - 1311, 1523, 1525, 1524, 920, 0, 0, 157, 1471, 143, - 144, 145, 0, 1472, + 1684, 863, 1654, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 842, 0, 0, 0, 65, + 0, 65, 1273, 1275, 104, 106, 0, 100, 101, 102, + 1003, 1251, 1421, 1239, 0, 1240, 0, 0, 81, 83, + 0, 2103, 0, 0, 0, 0, 1216, 1031, 1047, 1043, + 0, 0, 0, 0, 1428, 1429, 1431, 1432, 1433, 0, + 1069, 0, 0, 1089, 1090, 1091, 1103, 0, 559, 560, + 0, 0, 0, 572, 568, 569, 570, 550, 1141, 1123, + 0, 0, 1112, 0, 0, 1122, 0, 1221, 1962, 1962, + 1962, 1251, 0, 0, 1352, 1962, 1962, 0, 1259, 1261, + 1251, 0, 0, 1356, 1295, 0, 0, 1286, 0, 0, + 793, 777, 776, 853, 998, 0, 0, 923, 746, 749, + 750, 628, 666, 670, 667, 923, 1295, 454, 1316, 0, + 0, 0, 0, 0, 1348, 0, 0, 1320, 0, 486, + 516, 0, -2, 0, 1469, 0, 1454, 1469, 0, 0, + 1468, 0, 475, 515, 0, 0, 0, 529, 0, 535, + 536, 1178, 532, 533, 1508, 0, 534, 0, 520, 0, + 526, 1370, 1371, 0, 1376, 1377, 0, 1401, 0, 0, + 465, 466, 539, 0, 0, 0, 540, 541, 546, 1143, + 1144, 1109, 0, 1123, 0, 1133, 0, 1130, 1131, 863, + 0, 0, 940, 969, 0, 0, 941, 0, 942, 944, + 967, 0, 961, 951, 953, 362, 984, 0, 0, 986, + 987, 988, 979, 300, 829, 0, 1055, 0, 897, 0, + 0, 930, 0, 19, 0, 0, 124, 1950, 1953, 821, + 0, 818, 176, 0, 0, 0, 832, 813, 0, 810, + 0, 873, 874, 792, 763, 1426, 197, 192, 1157, 1277, + 0, 1268, 0, 1532, 1591, 0, 1702, 0, 0, 1659, + 1656, 1659, 1658, 1650, 0, 1599, 0, 1602, 0, 1606, + 1607, 0, 1609, 1610, 1611, 0, 1613, 1614, 0, 840, + 0, 61, 0, 64, 62, 0, 108, 1235, 0, 1251, + 0, 0, 0, 1245, 1246, 0, 0, 84, 0, 0, + 0, 0, 0, 0, 90, 0, 0, 1040, 1042, 0, + 1075, 1356, 0, 1075, 1102, 1088, 0, 0, 561, 562, + 0, 565, 571, 1104, 0, 0, 1106, 1107, 1108, 0, + 0, 1120, 0, 0, 0, 0, 1209, 1211, 1227, 0, + 0, 0, -2, 1263, 0, -2, 1256, 0, 1301, 0, + 1293, 0, 1285, 0, 1288, 0, 781, 775, 923, 923, + -2, 743, 748, 0, 671, 1301, 1318, 0, 1339, 0, + 0, 0, 0, 0, 0, 0, 1319, 0, 1332, 517, + 1470, -2, 1484, 1486, 0, 1226, 1489, 1490, 0, 0, + 0, 0, 0, 0, 1539, 1498, 0, 0, 1502, 1503, + 1504, 0, 0, 1507, 0, 1869, 1870, 0, 1511, 0, + 0, 0, 0, 0, 0, 0, 1448, 476, 477, 0, + 479, 480, 1178, 0, 531, 1509, 519, 473, 1962, 489, + 1400, 1403, 1404, 545, 542, 543, 1112, 1115, 1126, 1135, + 772, 856, 364, 365, 970, 0, 960, 962, 993, 990, + 0, 0, 876, 1059, 913, 921, 2333, 2335, 2332, 125, + 130, 0, 0, 823, 0, 820, 0, 814, 816, 186, + 817, 812, 862, 146, 178, 0, 0, 1578, 0, 0, + 0, 1691, 1745, 1746, 1662, 1663, 0, 1651, 0, 1645, + 1646, 1647, 1652, 0, 0, 0, 0, 843, 838, 66, + 107, 0, 1236, 1242, 1243, 1244, 1248, 1249, 1250, 70, + 1216, 0, 1216, 0, 0, 0, 1034, 1048, 0, 1061, + 1068, 1082, 1232, 1430, 1067, 0, 0, 558, 563, 0, + 566, 567, 1124, 1123, 0, 1110, 1111, 0, 1118, 0, + 0, 1222, 1223, 1224, 1353, 1354, 1355, 1311, 1258, 0, + -2, 1364, 0, 1254, 1277, 1311, 0, 1289, 0, 1296, + 0, 1294, 1287, 780, 863, 744, 1298, 464, 1350, 1340, + 0, 1342, 0, 0, 0, 0, 1321, -2, 0, 1485, + 1487, 1488, 1491, 1492, 1493, 1544, 1545, 1546, 0, 0, + 1496, 1541, 1542, 1543, 1497, 0, 0, 0, 0, 0, + 1867, 1868, 1537, 0, 0, 1455, 1457, 1458, 1459, 1460, + 1461, 1462, 1463, 1464, 1456, 0, 0, 0, 1447, 1449, + 478, 530, 0, 1179, 1962, 1962, 0, 0, 0, 1185, + 1186, 1962, 1962, 1962, 1190, 1191, 0, 1962, 1962, 0, + 1962, 1125, 361, 0, 0, 994, 996, 991, 992, 915, + 0, 0, 0, 0, 120, 122, 137, 0, 822, 177, + 0, 819, 148, 0, 169, 0, 1278, 0, 1590, 0, + 0, 0, 1661, 1648, 0, 0, 0, 0, 0, 1871, + 1872, 1873, 0, 1600, 1603, 1608, 1612, 1252, 0, 68, + 0, 85, 1216, 86, 1216, 0, 0, 0, 0, 1083, + 1084, 1092, 1093, 0, 1095, 1096, 564, 1105, 1113, 1117, + 1120, 0, 1178, 1313, 0, 1260, 1225, 1366, 1962, 1264, + 1313, 0, 1358, 1962, 1962, 1279, 0, 1291, 0, 1303, + 0, 1297, 856, 453, 0, 1300, 1336, 1341, 1343, 1345, + 0, 1349, 1347, 1322, -2, 0, 1330, 0, 0, 1494, + 1495, 0, 0, 1766, 1962, 0, 1527, 0, 1178, 1178, + 1178, 1178, 0, 537, 538, 0, 0, 1182, 1183, 0, + 0, 0, 0, 0, 0, 0, 488, 0, 971, 985, + 0, 922, 0, 0, 0, 0, 0, 821, 138, 0, + 147, 166, 0, 179, 180, 0, 0, 0, 0, 1270, + 0, 1535, 1536, 0, 1637, 0, 0, 0, 1641, 1642, + 1643, 1644, 1216, 70, 0, 87, 88, 0, 1216, 0, + 1060, 0, 1094, 1119, 1121, 1177, 1253, 0, 1350, 1365, + 0, 1255, 1357, 0, 0, 0, 1290, 1302, 0, 1305, + 742, 1299, 1317, 0, 1346, 1323, 1331, 0, 1326, 0, + 0, 0, 1540, 0, 1501, 0, 1506, 1515, 1528, 0, + 0, 1436, 0, 1438, 0, 1442, 0, 1444, 0, 0, + 1180, 1181, 1184, 1187, 1188, 1189, 1192, 1193, 1194, 1195, + 490, 995, 997, 0, 1817, 917, 918, 0, 825, 815, + 823, 149, 153, 0, 175, 172, 0, 181, 0, 0, + 0, 0, 1266, 0, 1533, 0, 1638, 1639, 1640, 67, + 69, 71, 1216, 89, 0, 1062, 1063, 1076, 0, 1338, + 1370, 1359, 1360, 1361, 1304, 1337, 1325, 0, -2, 1333, + 0, 0, 1819, 1829, 1830, 1499, 1505, 1514, 1516, 1517, + 0, 1529, 1530, 1531, 1538, 1178, 1178, 1178, 1178, 1446, + 916, 0, 0, 824, 0, 808, 140, 0, 0, 170, + 171, 173, 0, 182, 0, 184, 185, 0, 0, 1649, + 91, 1064, 1314, 0, 1316, 1327, -2, 0, 1335, 0, + 1500, 1518, 0, 1519, 0, 0, 0, 1437, 1439, 1443, + 1445, 1817, 919, 826, 1276, 0, 154, 0, 156, 158, + 159, 1471, 167, 168, 174, 183, 0, 0, 1049, 1065, + 0, 0, 1318, 1334, 1820, 1520, 1522, 1523, 0, 0, + 1521, 0, 141, 142, 0, 155, 0, 0, 1271, 1534, + 1066, 1315, 1312, 1524, 1526, 1525, 920, 0, 0, 157, + 1472, 143, 144, 145, 0, 1473, } var yyTok1 = [...]int{ @@ -10645,14 +10653,14 @@ var yyTok1 = [...]int{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 121, 3, 3, 3, 154, 144, 3, 88, 89, 151, 149, 174, 150, 173, 152, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 698, 695, - 131, 130, 132, 3, 699, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 699, 696, + 131, 130, 132, 3, 700, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 156, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 696, 143, 697, 157, + 3, 3, 3, 697, 143, 698, 157, } var yyTok2 = [...]int{ @@ -10769,7 +10777,7 @@ var yyTok3 = [...]int{ 58005, 680, 58006, 681, 58007, 682, 58008, 683, 58009, 684, 58010, 685, 58011, 686, 58012, 687, 58013, 688, 58014, 689, 58015, 690, 58016, 691, 58017, 692, 58018, 693, 58019, 694, - 0, + 58020, 695, 0, } var yyErrorMessages = [...]struct { @@ -21163,65 +21171,75 @@ yydefault: } yyVAL.union = yyLOCAL case 1246: + yyDollar = yyS[yypt-2 : yypt+1] + var yyLOCAL *tree.DiffOutputOpt +//line mysql_sql.y:8280 + { + yyLOCAL = &tree.DiffOutputOpt{ + Summary: true, + } + } + yyVAL.union = yyLOCAL + case 1247: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8282 +//line mysql_sql.y:8288 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1247: + case 1248: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8286 +//line mysql_sql.y:8292 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_FAIL, } } yyVAL.union = yyLOCAL - case 1248: + case 1249: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8292 +//line mysql_sql.y:8298 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_SKIP, } } yyVAL.union = yyLOCAL - case 1249: + case 1250: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConflictOpt -//line mysql_sql.y:8298 +//line mysql_sql.y:8304 { yyLOCAL = &tree.ConflictOpt{ Opt: tree.CONFLICT_ACCEPT, } } yyVAL.union = yyLOCAL - case 1250: + case 1251: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ToAccountOpt -//line mysql_sql.y:8306 +//line mysql_sql.y:8312 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1251: + case 1252: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ToAccountOpt -//line mysql_sql.y:8310 +//line mysql_sql.y:8316 { yyLOCAL = &tree.ToAccountOpt{ AccountName: tree.Identifier(yyDollar[3].cstrUnion().Compare()), } } yyVAL.union = yyLOCAL - case 1252: + case 1253: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8318 +//line mysql_sql.y:8324 { t := tree.NewCreateTable() t.Temporary = yyDollar[2].boolValUnion() @@ -21234,10 +21252,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1253: + case 1254: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8330 +//line mysql_sql.y:8336 { t := tree.NewCreateTable() t.IfNotExists = yyDollar[4].ifNotExistsUnion() @@ -21247,10 +21265,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1254: + case 1255: yyDollar = yyS[yypt-11 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8339 +//line mysql_sql.y:8345 { t := tree.NewCreateTable() t.IsClusterTable = true @@ -21263,10 +21281,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1255: + case 1256: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8351 +//line mysql_sql.y:8357 { t := tree.NewCreateTable() t.IsDynamicTable = true @@ -21277,10 +21295,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1256: + case 1257: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8361 +//line mysql_sql.y:8367 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -21291,10 +21309,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1257: + case 1258: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8371 +//line mysql_sql.y:8377 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -21306,10 +21324,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1258: + case 1259: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8382 +//line mysql_sql.y:8388 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -21320,10 +21338,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1259: + case 1260: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8392 +//line mysql_sql.y:8398 { t := tree.NewCreateTable() t.IsAsSelect = true @@ -21335,10 +21353,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1260: + case 1261: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8403 +//line mysql_sql.y:8409 { t := tree.NewCreateTable() t.IsAsLike = true @@ -21347,10 +21365,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1261: + case 1262: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8411 +//line mysql_sql.y:8417 { t := tree.NewCreateTable() t.Temporary = yyDollar[2].boolValUnion() @@ -21360,10 +21378,10 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1262: + case 1263: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8420 +//line mysql_sql.y:8426 { t := tree.NewCloneTable() t.CreateTable.Table = *yyDollar[5].tableNameUnion() @@ -21374,19 +21392,19 @@ yydefault: yyLOCAL = t } yyVAL.union = yyLOCAL - case 1263: + case 1264: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8432 +//line mysql_sql.y:8438 { yyLOCAL = yyDollar[1].loadParamUnion() yyLOCAL.Tail = yyDollar[2].tailParamUnion() } yyVAL.union = yyLOCAL - case 1264: + case 1265: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8439 +//line mysql_sql.y:8445 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -21397,10 +21415,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1265: + case 1266: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8449 +//line mysql_sql.y:8455 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -21414,10 +21432,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1266: + case 1267: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8462 +//line mysql_sql.y:8468 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -21426,10 +21444,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1267: + case 1268: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8470 +//line mysql_sql.y:8476 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -21439,10 +21457,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1268: + case 1269: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ExternParam -//line mysql_sql.y:8479 +//line mysql_sql.y:8485 { yyLOCAL = &tree.ExternParam{ ExParamConst: tree.ExParamConst{ @@ -21451,55 +21469,55 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1269: + case 1270: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8488 +//line mysql_sql.y:8494 { yyVAL.str = "" } - case 1270: + case 1271: yyDollar = yyS[yypt-4 : yypt+1] -//line mysql_sql.y:8492 +//line mysql_sql.y:8498 { yyVAL.str = yyDollar[4].str } - case 1271: + case 1272: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8498 +//line mysql_sql.y:8504 { yyLOCAL = yyDollar[1].strsUnion() } yyVAL.union = yyLOCAL - case 1272: + case 1273: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8502 +//line mysql_sql.y:8508 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].strsUnion()...) } yyVAL.union = yyLOCAL - case 1273: + case 1274: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8507 +//line mysql_sql.y:8513 { yyLOCAL = []string{} } yyVAL.union = yyLOCAL - case 1274: + case 1275: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:8511 +//line mysql_sql.y:8517 { yyLOCAL = append(yyLOCAL, yyDollar[1].str) yyLOCAL = append(yyLOCAL, yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1275: + case 1276: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.TailParameter -//line mysql_sql.y:8518 +//line mysql_sql.y:8524 { yyLOCAL = &tree.TailParameter{ Charset: yyDollar[1].str, @@ -21511,22 +21529,22 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1276: + case 1277: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:8530 +//line mysql_sql.y:8536 { yyVAL.str = "" } - case 1277: + case 1278: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:8534 +//line mysql_sql.y:8540 { yyVAL.str = yyDollar[2].str } - case 1278: + case 1279: yyDollar = yyS[yypt-10 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:8540 +//line mysql_sql.y:8546 { var Name = yyDollar[4].tableNameUnion() var Type = yyDollar[5].columnTypeUnion() @@ -21548,10 +21566,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1279: + case 1280: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:8561 +//line mysql_sql.y:8567 { locale := "" fstr := "bigint" @@ -21566,44 +21584,44 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1280: + case 1281: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:8575 +//line mysql_sql.y:8581 { yyLOCAL = yyDollar[2].columnTypeUnion() } yyVAL.union = yyLOCAL - case 1281: + case 1282: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.TypeOption -//line mysql_sql.y:8579 +//line mysql_sql.y:8585 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1282: + case 1283: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TypeOption -//line mysql_sql.y:8583 +//line mysql_sql.y:8589 { yyLOCAL = &tree.TypeOption{ Type: yyDollar[2].columnTypeUnion(), } } yyVAL.union = yyLOCAL - case 1283: + case 1284: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8589 +//line mysql_sql.y:8595 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1284: + case 1285: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8593 +//line mysql_sql.y:8599 { yyLOCAL = &tree.IncrementByOption{ Minus: false, @@ -21611,10 +21629,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1285: + case 1286: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8600 +//line mysql_sql.y:8606 { yyLOCAL = &tree.IncrementByOption{ Minus: false, @@ -21622,10 +21640,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1286: + case 1287: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8607 +//line mysql_sql.y:8613 { yyLOCAL = &tree.IncrementByOption{ Minus: true, @@ -21633,10 +21651,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1287: + case 1288: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.IncrementByOption -//line mysql_sql.y:8614 +//line mysql_sql.y:8620 { yyLOCAL = &tree.IncrementByOption{ Minus: true, @@ -21644,42 +21662,42 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1288: + case 1289: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8621 +//line mysql_sql.y:8627 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1289: + case 1290: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8625 +//line mysql_sql.y:8631 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1290: + case 1291: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8629 +//line mysql_sql.y:8635 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1291: + case 1292: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:8633 +//line mysql_sql.y:8639 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1292: + case 1293: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:8637 +//line mysql_sql.y:8643 { yyLOCAL = &tree.MinValueOption{ Minus: false, @@ -21687,10 +21705,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1293: + case 1294: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MinValueOption -//line mysql_sql.y:8644 +//line mysql_sql.y:8650 { yyLOCAL = &tree.MinValueOption{ Minus: true, @@ -21698,18 +21716,18 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1294: + case 1295: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:8651 +//line mysql_sql.y:8657 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1295: + case 1296: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:8655 +//line mysql_sql.y:8661 { yyLOCAL = &tree.MaxValueOption{ Minus: false, @@ -21717,10 +21735,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1296: + case 1297: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.MaxValueOption -//line mysql_sql.y:8662 +//line mysql_sql.y:8668 { yyLOCAL = &tree.MaxValueOption{ Minus: true, @@ -21728,46 +21746,46 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1297: + case 1298: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:8669 +//line mysql_sql.y:8675 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1298: + case 1299: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:8673 +//line mysql_sql.y:8679 { yyLOCAL = &tree.CycleOption{ Cycle: false, } } yyVAL.union = yyLOCAL - case 1299: + case 1300: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CycleOption -//line mysql_sql.y:8679 +//line mysql_sql.y:8685 { yyLOCAL = &tree.CycleOption{ Cycle: true, } } yyVAL.union = yyLOCAL - case 1300: + case 1301: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8685 +//line mysql_sql.y:8691 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1301: + case 1302: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8689 +//line mysql_sql.y:8695 { yyLOCAL = &tree.StartWithOption{ Minus: false, @@ -21775,10 +21793,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1302: + case 1303: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8696 +//line mysql_sql.y:8702 { yyLOCAL = &tree.StartWithOption{ Minus: false, @@ -21786,10 +21804,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1303: + case 1304: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8703 +//line mysql_sql.y:8709 { yyLOCAL = &tree.StartWithOption{ Minus: true, @@ -21797,10 +21815,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1304: + case 1305: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.StartWithOption -//line mysql_sql.y:8710 +//line mysql_sql.y:8716 { yyLOCAL = &tree.StartWithOption{ Minus: true, @@ -21808,58 +21826,58 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1305: + case 1306: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8717 +//line mysql_sql.y:8723 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1306: + case 1307: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8721 +//line mysql_sql.y:8727 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1307: + case 1308: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8726 +//line mysql_sql.y:8732 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1308: + case 1309: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8730 +//line mysql_sql.y:8736 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1309: + case 1310: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:8734 +//line mysql_sql.y:8740 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1310: + case 1311: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.PartitionOption -//line mysql_sql.y:8739 +//line mysql_sql.y:8745 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1311: + case 1312: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.PartitionOption -//line mysql_sql.y:8743 +//line mysql_sql.y:8749 { yyDollar[3].partitionByUnion().Num = uint64(yyDollar[4].int64ValUnion()) var PartBy = yyDollar[3].partitionByUnion() @@ -21872,18 +21890,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1312: + case 1313: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:8756 +//line mysql_sql.y:8762 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1313: + case 1314: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:8760 +//line mysql_sql.y:8766 { var ColumnList = []*tree.UnresolvedName{yyDollar[3].unresolvedNameUnion()} yyLOCAL = tree.NewClusterByOption( @@ -21892,10 +21910,10 @@ yydefault: } yyVAL.union = yyLOCAL - case 1314: + case 1315: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.ClusterByOption -//line mysql_sql.y:8768 +//line mysql_sql.y:8774 { var ColumnList = yyDollar[4].unresolveNamesUnion() yyLOCAL = tree.NewClusterByOption( @@ -21903,18 +21921,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1315: + case 1316: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8776 +//line mysql_sql.y:8782 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1316: + case 1317: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8780 +//line mysql_sql.y:8786 { var IsSubPartition = true var PType = yyDollar[3].partitionByUnion().PType @@ -21928,42 +21946,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1317: + case 1318: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8794 +//line mysql_sql.y:8800 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1318: + case 1319: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8798 +//line mysql_sql.y:8804 { yyLOCAL = yyDollar[2].partitionsUnion() } yyVAL.union = yyLOCAL - case 1319: + case 1320: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8804 +//line mysql_sql.y:8810 { yyLOCAL = []*tree.Partition{yyDollar[1].partitionUnion()} } yyVAL.union = yyLOCAL - case 1320: + case 1321: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.Partition -//line mysql_sql.y:8808 +//line mysql_sql.y:8814 { yyLOCAL = append(yyDollar[1].partitionsUnion(), yyDollar[3].partitionUnion()) } yyVAL.union = yyLOCAL - case 1321: + case 1322: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.Partition -//line mysql_sql.y:8814 +//line mysql_sql.y:8820 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Values = yyDollar[3].valuesUnion() @@ -21977,10 +21995,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1322: + case 1323: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.Partition -//line mysql_sql.y:8827 +//line mysql_sql.y:8833 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Values = yyDollar[3].valuesUnion() @@ -21994,42 +22012,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1323: + case 1324: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8841 +//line mysql_sql.y:8847 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1324: + case 1325: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8845 +//line mysql_sql.y:8851 { yyLOCAL = yyDollar[2].subPartitionsUnion() } yyVAL.union = yyLOCAL - case 1325: + case 1326: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8851 +//line mysql_sql.y:8857 { yyLOCAL = []*tree.SubPartition{yyDollar[1].subPartitionUnion()} } yyVAL.union = yyLOCAL - case 1326: + case 1327: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.SubPartition -//line mysql_sql.y:8855 +//line mysql_sql.y:8861 { yyLOCAL = append(yyDollar[1].subPartitionsUnion(), yyDollar[3].subPartitionUnion()) } yyVAL.union = yyLOCAL - case 1327: + case 1328: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.SubPartition -//line mysql_sql.y:8861 +//line mysql_sql.y:8867 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Options []tree.TableOption @@ -22039,10 +22057,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1328: + case 1329: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.SubPartition -//line mysql_sql.y:8870 +//line mysql_sql.y:8876 { var Name = tree.Identifier(yyDollar[2].cstrUnion().Compare()) var Options = yyDollar[3].tableOptionsUnion() @@ -22052,53 +22070,53 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1329: + case 1330: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8881 +//line mysql_sql.y:8887 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1330: + case 1331: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:8885 +//line mysql_sql.y:8891 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[2].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1331: + case 1332: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8890 +//line mysql_sql.y:8896 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1332: + case 1333: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8894 +//line mysql_sql.y:8900 { expr := tree.NewMaxValue() var valueList = tree.Exprs{expr} yyLOCAL = tree.NewValuesLessThan(valueList) } yyVAL.union = yyLOCAL - case 1333: + case 1334: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8900 +//line mysql_sql.y:8906 { var valueList = yyDollar[5].exprsUnion() yyLOCAL = tree.NewValuesLessThan(valueList) } yyVAL.union = yyLOCAL - case 1334: + case 1335: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Values -//line mysql_sql.y:8905 +//line mysql_sql.y:8911 { var valueList = yyDollar[4].exprsUnion() yyLOCAL = tree.NewValuesIn( @@ -22106,18 +22124,18 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1335: + case 1336: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8913 +//line mysql_sql.y:8919 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1336: + case 1337: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8917 +//line mysql_sql.y:8923 { res := yyDollar[2].item.(int64) if res == 0 { @@ -22127,18 +22145,18 @@ yydefault: yyLOCAL = res } yyVAL.union = yyLOCAL - case 1337: + case 1338: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8927 +//line mysql_sql.y:8933 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1338: + case 1339: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:8931 +//line mysql_sql.y:8937 { res := yyDollar[2].item.(int64) if res == 0 { @@ -22148,10 +22166,10 @@ yydefault: yyLOCAL = res } yyVAL.union = yyLOCAL - case 1339: + case 1340: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8942 +//line mysql_sql.y:8948 { rangeTyp := tree.NewRangeType() rangeTyp.Expr = yyDollar[3].exprUnion() @@ -22160,10 +22178,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1340: + case 1341: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8950 +//line mysql_sql.y:8956 { rangeTyp := tree.NewRangeType() rangeTyp.ColumnList = yyDollar[4].unresolveNamesUnion() @@ -22172,10 +22190,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1341: + case 1342: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8958 +//line mysql_sql.y:8964 { listTyp := tree.NewListType() listTyp.Expr = yyDollar[3].exprUnion() @@ -22184,10 +22202,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1342: + case 1343: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8966 +//line mysql_sql.y:8972 { listTyp := tree.NewListType() listTyp.ColumnList = yyDollar[4].unresolveNamesUnion() @@ -22196,10 +22214,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1344: + case 1345: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8977 +//line mysql_sql.y:8983 { keyTyp := tree.NewKeyType() keyTyp.Linear = yyDollar[1].boolValUnion() @@ -22209,10 +22227,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1345: + case 1346: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8986 +//line mysql_sql.y:8992 { keyTyp := tree.NewKeyType() keyTyp.Linear = yyDollar[1].boolValUnion() @@ -22223,10 +22241,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1346: + case 1347: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.PartitionBy -//line mysql_sql.y:8996 +//line mysql_sql.y:9002 { Linear := yyDollar[1].boolValUnion() Expr := yyDollar[4].exprUnion() @@ -22236,58 +22254,58 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1347: + case 1348: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:9006 +//line mysql_sql.y:9012 { yyLOCAL = 2 } yyVAL.union = yyLOCAL - case 1348: + case 1349: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:9010 +//line mysql_sql.y:9016 { yyLOCAL = yyDollar[3].item.(int64) } yyVAL.union = yyLOCAL - case 1349: + case 1350: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9015 +//line mysql_sql.y:9021 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1350: + case 1351: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9019 +//line mysql_sql.y:9025 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1351: + case 1352: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.ConnectorOption -//line mysql_sql.y:9025 +//line mysql_sql.y:9031 { yyLOCAL = []*tree.ConnectorOption{yyDollar[1].connectorOptionUnion()} } yyVAL.union = yyLOCAL - case 1352: + case 1353: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.ConnectorOption -//line mysql_sql.y:9029 +//line mysql_sql.y:9035 { yyLOCAL = append(yyDollar[1].connectorOptionsUnion(), yyDollar[3].connectorOptionUnion()) } yyVAL.union = yyLOCAL - case 1353: + case 1354: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConnectorOption -//line mysql_sql.y:9035 +//line mysql_sql.y:9041 { var Key = tree.Identifier(yyDollar[1].cstrUnion().Compare()) var Val = yyDollar[3].exprUnion() @@ -22297,10 +22315,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1354: + case 1355: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ConnectorOption -//line mysql_sql.y:9044 +//line mysql_sql.y:9050 { var Key = tree.Identifier(yyDollar[1].str) var Val = yyDollar[3].exprUnion() @@ -22310,42 +22328,42 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1355: + case 1356: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9054 +//line mysql_sql.y:9060 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1356: + case 1357: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9058 +//line mysql_sql.y:9064 { yyLOCAL = yyDollar[3].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 1357: + case 1358: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9064 +//line mysql_sql.y:9070 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1358: + case 1359: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9068 +//line mysql_sql.y:9074 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[3].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1359: + case 1360: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9074 +//line mysql_sql.y:9080 { var Key = tree.Identifier(yyDollar[1].cstrUnion().Compare()) var Val = yyDollar[3].exprUnion() @@ -22355,10 +22373,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1360: + case 1361: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9083 +//line mysql_sql.y:9089 { var Key = tree.Identifier(yyDollar[1].str) var Val = yyDollar[3].exprUnion() @@ -22368,364 +22386,364 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1361: + case 1362: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9093 +//line mysql_sql.y:9099 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1362: + case 1363: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9097 +//line mysql_sql.y:9103 { yyLOCAL = yyDollar[1].tableOptionsUnion() } yyVAL.union = yyLOCAL - case 1363: + case 1364: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9103 +//line mysql_sql.y:9109 { yyLOCAL = []tree.TableOption{yyDollar[1].tableOptionUnion()} } yyVAL.union = yyLOCAL - case 1364: + case 1365: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9107 +//line mysql_sql.y:9113 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[3].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1365: + case 1366: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.TableOption -//line mysql_sql.y:9111 +//line mysql_sql.y:9117 { yyLOCAL = append(yyDollar[1].tableOptionsUnion(), yyDollar[2].tableOptionUnion()) } yyVAL.union = yyLOCAL - case 1366: + case 1367: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9117 +//line mysql_sql.y:9123 { yyLOCAL = tree.NewTableOptionAUTOEXTEND_SIZE(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1367: + case 1368: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9121 +//line mysql_sql.y:9127 { yyLOCAL = tree.NewTableOptionAutoIncrement(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1368: + case 1369: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9125 +//line mysql_sql.y:9131 { yyLOCAL = tree.NewTableOptionAvgRowLength(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1369: + case 1370: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9129 +//line mysql_sql.y:9135 { yyLOCAL = tree.NewTableOptionCharset(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1370: + case 1371: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9133 +//line mysql_sql.y:9139 { yyLOCAL = tree.NewTableOptionCollate(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1371: + case 1372: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9137 +//line mysql_sql.y:9143 { yyLOCAL = tree.NewTableOptionChecksum(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1372: + case 1373: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9141 +//line mysql_sql.y:9147 { str := util.DealCommentString(yyDollar[3].str) yyLOCAL = tree.NewTableOptionComment(str) } yyVAL.union = yyLOCAL - case 1373: + case 1374: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9146 +//line mysql_sql.y:9152 { yyLOCAL = tree.NewTableOptionCompression(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1374: + case 1375: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9150 +//line mysql_sql.y:9156 { yyLOCAL = tree.NewTableOptionConnection(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1375: + case 1376: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9154 +//line mysql_sql.y:9160 { yyLOCAL = tree.NewTableOptionDataDirectory(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1376: + case 1377: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9158 +//line mysql_sql.y:9164 { yyLOCAL = tree.NewTableOptionIndexDirectory(yyDollar[4].str) } yyVAL.union = yyLOCAL - case 1377: + case 1378: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9162 +//line mysql_sql.y:9168 { yyLOCAL = tree.NewTableOptionDelayKeyWrite(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1378: + case 1379: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9166 +//line mysql_sql.y:9172 { yyLOCAL = tree.NewTableOptionEncryption(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1379: + case 1380: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9170 +//line mysql_sql.y:9176 { yyLOCAL = tree.NewTableOptionEngine(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1380: + case 1381: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9174 +//line mysql_sql.y:9180 { yyLOCAL = tree.NewTableOptionEngineAttr(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1381: + case 1382: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9178 +//line mysql_sql.y:9184 { yyLOCAL = tree.NewTableOptionInsertMethod(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1382: + case 1383: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9182 +//line mysql_sql.y:9188 { yyLOCAL = tree.NewTableOptionKeyBlockSize(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1383: + case 1384: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9186 +//line mysql_sql.y:9192 { yyLOCAL = tree.NewTableOptionMaxRows(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1384: + case 1385: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9190 +//line mysql_sql.y:9196 { yyLOCAL = tree.NewTableOptionMinRows(uint64(yyDollar[3].item.(int64))) } yyVAL.union = yyLOCAL - case 1385: + case 1386: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9194 +//line mysql_sql.y:9200 { t := tree.NewTableOptionPackKeys() t.Value = yyDollar[3].item.(int64) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1386: + case 1387: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9200 +//line mysql_sql.y:9206 { t := tree.NewTableOptionPackKeys() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1387: + case 1388: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9206 +//line mysql_sql.y:9212 { yyLOCAL = tree.NewTableOptionPassword(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1388: + case 1389: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9210 +//line mysql_sql.y:9216 { yyLOCAL = tree.NewTableOptionRowFormat(yyDollar[3].rowFormatTypeUnion()) } yyVAL.union = yyLOCAL - case 1389: + case 1390: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9214 +//line mysql_sql.y:9220 { yyLOCAL = tree.NewTTableOptionStartTrans(true) } yyVAL.union = yyLOCAL - case 1390: + case 1391: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9218 +//line mysql_sql.y:9224 { yyLOCAL = tree.NewTTableOptionSecondaryEngineAttr(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1391: + case 1392: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9222 +//line mysql_sql.y:9228 { t := tree.NewTableOptionStatsAutoRecalc() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1392: + case 1393: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9228 +//line mysql_sql.y:9234 { t := tree.NewTableOptionStatsAutoRecalc() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1393: + case 1394: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9234 +//line mysql_sql.y:9240 { t := tree.NewTableOptionStatsPersistent() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1394: + case 1395: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9240 +//line mysql_sql.y:9246 { t := tree.NewTableOptionStatsPersistent() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1395: + case 1396: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9246 +//line mysql_sql.y:9252 { t := tree.NewTableOptionStatsSamplePages() t.Value = uint64(yyDollar[3].item.(int64)) yyLOCAL = t } yyVAL.union = yyLOCAL - case 1396: + case 1397: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9252 +//line mysql_sql.y:9258 { t := tree.NewTableOptionStatsSamplePages() t.Default = true yyLOCAL = t } yyVAL.union = yyLOCAL - case 1397: + case 1398: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9258 +//line mysql_sql.y:9264 { yyLOCAL = tree.NewTableOptionTablespace(yyDollar[3].cstrUnion().Compare(), "") } yyVAL.union = yyLOCAL - case 1398: + case 1399: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9262 +//line mysql_sql.y:9268 { yyLOCAL = tree.NewTableOptionTablespace("", yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1399: + case 1400: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9266 +//line mysql_sql.y:9272 { yyLOCAL = tree.NewTableOptionUnion(yyDollar[4].tableNamesUnion()) } yyVAL.union = yyLOCAL - case 1400: + case 1401: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.TableOption -//line mysql_sql.y:9270 +//line mysql_sql.y:9276 { var Preperties = yyDollar[3].propertiesUnion() yyLOCAL = tree.NewTableOptionProperties(Preperties) } yyVAL.union = yyLOCAL - case 1401: + case 1402: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.Property -//line mysql_sql.y:9277 +//line mysql_sql.y:9283 { yyLOCAL = []tree.Property{yyDollar[1].propertyUnion()} } yyVAL.union = yyLOCAL - case 1402: + case 1403: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []tree.Property -//line mysql_sql.y:9281 +//line mysql_sql.y:9287 { yyLOCAL = append(yyDollar[1].propertiesUnion(), yyDollar[3].propertyUnion()) } yyVAL.union = yyLOCAL - case 1403: + case 1404: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Property -//line mysql_sql.y:9287 +//line mysql_sql.y:9293 { var Key = yyDollar[1].str var Value = yyDollar[3].str @@ -22735,96 +22753,96 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1404: + case 1405: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9298 +//line mysql_sql.y:9304 { yyVAL.str = " " + yyDollar[1].str + " " + yyDollar[2].str } - case 1405: + case 1406: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9302 +//line mysql_sql.y:9308 { yyVAL.str = " " + yyDollar[1].str + " " + yyDollar[2].str } - case 1406: + case 1407: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9308 +//line mysql_sql.y:9314 { yyLOCAL = tree.ROW_FORMAT_DEFAULT } yyVAL.union = yyLOCAL - case 1407: + case 1408: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9312 +//line mysql_sql.y:9318 { yyLOCAL = tree.ROW_FORMAT_DYNAMIC } yyVAL.union = yyLOCAL - case 1408: + case 1409: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9316 +//line mysql_sql.y:9322 { yyLOCAL = tree.ROW_FORMAT_FIXED } yyVAL.union = yyLOCAL - case 1409: + case 1410: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9320 +//line mysql_sql.y:9326 { yyLOCAL = tree.ROW_FORMAT_COMPRESSED } yyVAL.union = yyLOCAL - case 1410: + case 1411: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9324 +//line mysql_sql.y:9330 { yyLOCAL = tree.ROW_FORMAT_REDUNDANT } yyVAL.union = yyLOCAL - case 1411: + case 1412: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.RowFormatType -//line mysql_sql.y:9328 +//line mysql_sql.y:9334 { yyLOCAL = tree.ROW_FORMAT_COMPACT } yyVAL.union = yyLOCAL - case 1416: + case 1417: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:9342 +//line mysql_sql.y:9348 { yyLOCAL = tree.TableNames{yyDollar[1].tableNameUnion()} } yyVAL.union = yyLOCAL - case 1417: + case 1418: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableNames -//line mysql_sql.y:9346 +//line mysql_sql.y:9352 { yyLOCAL = append(yyDollar[1].tableNamesUnion(), yyDollar[3].tableNameUnion()) } yyVAL.union = yyLOCAL - case 1418: + case 1419: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:9355 +//line mysql_sql.y:9361 { tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) prefix := tree.ObjectNamePrefix{ExplicitSchema: false} yyLOCAL = tree.NewTableName(tree.Identifier(tblName), prefix, yyDollar[2].atTimeStampUnion()) } yyVAL.union = yyLOCAL - case 1419: + case 1420: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.TableName -//line mysql_sql.y:9361 +//line mysql_sql.y:9367 { dbName := yylex.(*Lexer).GetDbOrTblName(yyDollar[1].cstrUnion().Origin()) tblName := yylex.(*Lexer).GetDbOrTblName(yyDollar[3].cstrUnion().Origin()) @@ -22832,18 +22850,18 @@ yydefault: yyLOCAL = tree.NewTableName(tree.Identifier(tblName), prefix, yyDollar[4].atTimeStampUnion()) } yyVAL.union = yyLOCAL - case 1420: + case 1421: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9369 +//line mysql_sql.y:9375 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1421: + case 1422: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9373 +//line mysql_sql.y:9379 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATTIMESTAMPTIME, @@ -22851,10 +22869,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1422: + case 1423: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9380 +//line mysql_sql.y:9386 { var str = yyDollar[4].cstrUnion().Compare() yyLOCAL = &tree.AtTimeStamp{ @@ -22864,10 +22882,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1423: + case 1424: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9389 +//line mysql_sql.y:9395 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATTIMESTAMPSNAPSHOT, @@ -22876,10 +22894,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1424: + case 1425: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9397 +//line mysql_sql.y:9403 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ATMOTIMESTAMP, @@ -22887,10 +22905,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1425: + case 1426: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.AtTimeStamp -//line mysql_sql.y:9404 +//line mysql_sql.y:9410 { yyLOCAL = &tree.AtTimeStamp{ Type: tree.ASOFTIMESTAMP, @@ -22898,74 +22916,74 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1426: + case 1427: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:9412 +//line mysql_sql.y:9418 { yyLOCAL = tree.TableDefs(nil) } yyVAL.union = yyLOCAL - case 1428: + case 1429: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:9419 +//line mysql_sql.y:9425 { yyLOCAL = tree.TableDefs{yyDollar[1].tableDefUnion()} } yyVAL.union = yyLOCAL - case 1429: + case 1430: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.TableDefs -//line mysql_sql.y:9423 +//line mysql_sql.y:9429 { yyLOCAL = append(yyDollar[1].tableDefsUnion(), yyDollar[3].tableDefUnion()) } yyVAL.union = yyLOCAL - case 1430: + case 1431: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9429 +//line mysql_sql.y:9435 { yyLOCAL = tree.TableDef(yyDollar[1].columnTableDefUnion()) } yyVAL.union = yyLOCAL - case 1431: + case 1432: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9433 +//line mysql_sql.y:9439 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1432: + case 1433: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9437 +//line mysql_sql.y:9443 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1433: + case 1434: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9443 +//line mysql_sql.y:9449 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1434: + case 1435: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9447 +//line mysql_sql.y:9453 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1435: + case 1436: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9453 +//line mysql_sql.y:9459 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -22979,10 +22997,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1436: + case 1437: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9466 +//line mysql_sql.y:9472 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].str @@ -22996,10 +23014,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1437: + case 1438: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9479 +//line mysql_sql.y:9485 { keyTyp := tree.INDEX_TYPE_INVALID if yyDollar[3].strsUnion()[1] != "" { @@ -23041,10 +23059,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1438: + case 1439: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9520 +//line mysql_sql.y:9526 { keyTyp := tree.INDEX_TYPE_INVALID if yyDollar[3].strsUnion()[1] != "" { @@ -23085,10 +23103,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1439: + case 1440: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9562 +//line mysql_sql.y:9568 { if yyDollar[1].str != "" { switch v := yyDollar[2].tableDefUnion().(type) { @@ -23103,18 +23121,18 @@ yydefault: yyLOCAL = yyDollar[2].tableDefUnion() } yyVAL.union = yyLOCAL - case 1440: + case 1441: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9576 +//line mysql_sql.y:9582 { yyLOCAL = yyDollar[1].tableDefUnion() } yyVAL.union = yyLOCAL - case 1441: + case 1442: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9582 +//line mysql_sql.y:9588 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -23128,10 +23146,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1442: + case 1443: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9595 +//line mysql_sql.y:9601 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -23145,10 +23163,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1443: + case 1444: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9608 +//line mysql_sql.y:9614 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -23162,10 +23180,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1444: + case 1445: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9621 +//line mysql_sql.y:9627 { var KeyParts = yyDollar[5].keyPartsUnion() var Name = yyDollar[3].strsUnion()[0] @@ -23179,10 +23197,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1445: + case 1446: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9634 +//line mysql_sql.y:9640 { var IfNotExists = yyDollar[3].ifNotExistsUnion() var KeyParts = yyDollar[6].keyPartsUnion() @@ -23198,10 +23216,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1446: + case 1447: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.TableDef -//line mysql_sql.y:9649 +//line mysql_sql.y:9655 { var Expr = yyDollar[3].exprUnion() var Enforced = yyDollar[5].boolValUnion() @@ -23211,327 +23229,327 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1447: + case 1448: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9659 +//line mysql_sql.y:9665 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1449: + case 1450: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9665 +//line mysql_sql.y:9671 { yyVAL.str = "" } - case 1450: + case 1451: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9669 +//line mysql_sql.y:9675 { yyVAL.str = yyDollar[1].str } - case 1453: + case 1454: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9679 +//line mysql_sql.y:9685 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].str yyLOCAL[1] = "" } yyVAL.union = yyLOCAL - case 1454: + case 1455: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9685 +//line mysql_sql.y:9691 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].str yyLOCAL[1] = yyDollar[3].str } yyVAL.union = yyLOCAL - case 1455: + case 1456: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:9691 +//line mysql_sql.y:9697 { yyLOCAL = make([]string, 2) yyLOCAL[0] = yyDollar[1].cstrUnion().Compare() yyLOCAL[1] = yyDollar[3].str } yyVAL.union = yyLOCAL - case 1467: + case 1468: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9713 +//line mysql_sql.y:9719 { yyVAL.str = "" } - case 1468: + case 1469: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9717 +//line mysql_sql.y:9723 { yyVAL.str = yyDollar[1].cstrUnion().Compare() } - case 1469: + case 1470: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.ColumnTableDef -//line mysql_sql.y:9723 +//line mysql_sql.y:9729 { yyLOCAL = tree.NewColumnTableDef(yyDollar[1].unresolvedNameUnion(), yyDollar[2].columnTypeUnion(), yyDollar[3].columnAttributesUnion()) } yyVAL.union = yyLOCAL - case 1470: + case 1471: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9729 +//line mysql_sql.y:9735 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1471: + case 1472: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9733 +//line mysql_sql.y:9739 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) } yyVAL.union = yyLOCAL - case 1472: + case 1473: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9738 +//line mysql_sql.y:9744 { dbNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(dbNameCStr, tblNameCStr, yyDollar[5].cstrUnion()) } yyVAL.union = yyLOCAL - case 1473: + case 1474: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9746 +//line mysql_sql.y:9752 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1474: + case 1475: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9750 +//line mysql_sql.y:9756 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1475: + case 1476: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9754 +//line mysql_sql.y:9760 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1476: + case 1477: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9758 +//line mysql_sql.y:9764 { yyLOCAL = tree.NewCStr(yyDollar[1].str, 1) } yyVAL.union = yyLOCAL - case 1477: + case 1478: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.CStr -//line mysql_sql.y:9764 +//line mysql_sql.y:9770 { yyLOCAL = yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) } yyVAL.union = yyLOCAL - case 1478: + case 1479: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9770 +//line mysql_sql.y:9776 { yyLOCAL = tree.NewUnresolvedName(yyDollar[1].cstrUnion()) } yyVAL.union = yyLOCAL - case 1479: + case 1480: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9774 +//line mysql_sql.y:9780 { tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(tblNameCStr, yyDollar[3].cstrUnion()) } yyVAL.union = yyLOCAL - case 1480: + case 1481: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.UnresolvedName -//line mysql_sql.y:9779 +//line mysql_sql.y:9785 { dbNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[1].cstrUnion().Origin()) tblNameCStr := yylex.(*Lexer).GetDbOrTblNameCStr(yyDollar[3].cstrUnion().Origin()) yyLOCAL = tree.NewUnresolvedName(dbNameCStr, tblNameCStr, yyDollar[5].cstrUnion()) } yyVAL.union = yyLOCAL - case 1481: + case 1482: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9786 +//line mysql_sql.y:9792 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1482: + case 1483: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9790 +//line mysql_sql.y:9796 { yyLOCAL = yyDollar[1].columnAttributesUnion() } yyVAL.union = yyLOCAL - case 1483: + case 1484: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9796 +//line mysql_sql.y:9802 { yyLOCAL = []tree.ColumnAttribute{yyDollar[1].columnAttributeUnion()} } yyVAL.union = yyLOCAL - case 1484: + case 1485: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []tree.ColumnAttribute -//line mysql_sql.y:9800 +//line mysql_sql.y:9806 { yyLOCAL = append(yyDollar[1].columnAttributesUnion(), yyDollar[2].columnAttributeUnion()) } yyVAL.union = yyLOCAL - case 1485: + case 1486: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9806 +//line mysql_sql.y:9812 { yyLOCAL = tree.NewAttributeNull(true) } yyVAL.union = yyLOCAL - case 1486: + case 1487: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9810 +//line mysql_sql.y:9816 { yyLOCAL = tree.NewAttributeNull(false) } yyVAL.union = yyLOCAL - case 1487: + case 1488: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9814 +//line mysql_sql.y:9820 { yyLOCAL = tree.NewAttributeDefault(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1488: + case 1489: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9818 +//line mysql_sql.y:9824 { yyLOCAL = tree.NewAttributeAutoIncrement() } yyVAL.union = yyLOCAL - case 1489: + case 1490: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9822 +//line mysql_sql.y:9828 { yyLOCAL = yyDollar[1].columnAttributeUnion() } yyVAL.union = yyLOCAL - case 1490: + case 1491: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9826 +//line mysql_sql.y:9832 { str := util.DealCommentString(yyDollar[2].str) yyLOCAL = tree.NewAttributeComment(tree.NewNumVal(str, str, false, tree.P_char)) } yyVAL.union = yyLOCAL - case 1491: + case 1492: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9831 +//line mysql_sql.y:9837 { yyLOCAL = tree.NewAttributeCollate(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1492: + case 1493: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9835 +//line mysql_sql.y:9841 { yyLOCAL = tree.NewAttributeColumnFormat(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1493: + case 1494: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9839 +//line mysql_sql.y:9845 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1494: + case 1495: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9843 +//line mysql_sql.y:9849 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1495: + case 1496: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9847 +//line mysql_sql.y:9853 { yyLOCAL = tree.NewAttributeStorage(yyDollar[2].str) } yyVAL.union = yyLOCAL - case 1496: + case 1497: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9851 +//line mysql_sql.y:9857 { yyLOCAL = tree.NewAttributeAutoRandom(int(yyDollar[2].int64ValUnion())) } yyVAL.union = yyLOCAL - case 1497: + case 1498: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9855 +//line mysql_sql.y:9861 { yyLOCAL = yyDollar[1].attributeReferenceUnion() } yyVAL.union = yyLOCAL - case 1498: + case 1499: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9859 +//line mysql_sql.y:9865 { yyLOCAL = tree.NewAttributeCheckConstraint(yyDollar[4].exprUnion(), false, yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1499: + case 1500: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9863 +//line mysql_sql.y:9869 { yyLOCAL = tree.NewAttributeCheckConstraint(yyDollar[4].exprUnion(), yyDollar[6].boolValUnion(), yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1500: + case 1501: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9867 +//line mysql_sql.y:9873 { name := tree.NewUnresolvedColName(yyDollar[3].str) var es tree.Exprs = nil @@ -23546,98 +23564,98 @@ yydefault: yyLOCAL = tree.NewAttributeOnUpdate(expr) } yyVAL.union = yyLOCAL - case 1501: + case 1502: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9881 +//line mysql_sql.y:9887 { yyLOCAL = tree.NewAttributeLowCardinality() } yyVAL.union = yyLOCAL - case 1502: + case 1503: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9885 +//line mysql_sql.y:9891 { yyLOCAL = tree.NewAttributeVisable(true) } yyVAL.union = yyLOCAL - case 1503: + case 1504: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9889 +//line mysql_sql.y:9895 { yyLOCAL = tree.NewAttributeVisable(false) } yyVAL.union = yyLOCAL - case 1504: + case 1505: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9893 +//line mysql_sql.y:9899 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1505: + case 1506: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9897 +//line mysql_sql.y:9903 { yyLOCAL = tree.NewAttributeHeader(yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1506: + case 1507: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:9901 +//line mysql_sql.y:9907 { yyLOCAL = tree.NewAttributeHeaders() } yyVAL.union = yyLOCAL - case 1507: + case 1508: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9907 +//line mysql_sql.y:9913 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1508: + case 1509: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:9911 +//line mysql_sql.y:9917 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1509: + case 1510: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:9916 +//line mysql_sql.y:9922 { yyVAL.str = "" } - case 1510: + case 1511: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9920 +//line mysql_sql.y:9926 { yyVAL.str = yyDollar[1].str } - case 1511: + case 1512: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:9926 +//line mysql_sql.y:9932 { yyVAL.str = "" } - case 1512: + case 1513: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:9930 +//line mysql_sql.y:9936 { yyVAL.str = yyDollar[2].cstrUnion().Compare() } - case 1513: + case 1514: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.AttributeReference -//line mysql_sql.y:9936 +//line mysql_sql.y:9942 { var TableName = yyDollar[2].tableNameUnion() var KeyParts = yyDollar[3].keyPartsUnion() @@ -23653,10 +23671,10 @@ yydefault: ) } yyVAL.union = yyLOCAL - case 1514: + case 1515: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9953 +//line mysql_sql.y:9959 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: tree.REFERENCE_OPTION_INVALID, @@ -23664,10 +23682,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1515: + case 1516: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9960 +//line mysql_sql.y:9966 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[1].referenceOptionTypeUnion(), @@ -23675,10 +23693,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1516: + case 1517: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9967 +//line mysql_sql.y:9973 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: tree.REFERENCE_OPTION_INVALID, @@ -23686,10 +23704,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1517: + case 1518: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9974 +//line mysql_sql.y:9980 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[1].referenceOptionTypeUnion(), @@ -23697,10 +23715,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1518: + case 1519: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.ReferenceOnRecord -//line mysql_sql.y:9981 +//line mysql_sql.y:9987 { yyLOCAL = &tree.ReferenceOnRecord{ OnDelete: yyDollar[2].referenceOptionTypeUnion(), @@ -23708,274 +23726,274 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1519: + case 1520: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9990 +//line mysql_sql.y:9996 { yyLOCAL = yyDollar[3].referenceOptionTypeUnion() } yyVAL.union = yyLOCAL - case 1520: + case 1521: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:9996 +//line mysql_sql.y:10002 { yyLOCAL = yyDollar[3].referenceOptionTypeUnion() } yyVAL.union = yyLOCAL - case 1521: + case 1522: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:10002 +//line mysql_sql.y:10008 { yyLOCAL = tree.REFERENCE_OPTION_RESTRICT } yyVAL.union = yyLOCAL - case 1522: + case 1523: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:10006 +//line mysql_sql.y:10012 { yyLOCAL = tree.REFERENCE_OPTION_CASCADE } yyVAL.union = yyLOCAL - case 1523: + case 1524: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:10010 +//line mysql_sql.y:10016 { yyLOCAL = tree.REFERENCE_OPTION_SET_NULL } yyVAL.union = yyLOCAL - case 1524: + case 1525: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:10014 +//line mysql_sql.y:10020 { yyLOCAL = tree.REFERENCE_OPTION_NO_ACTION } yyVAL.union = yyLOCAL - case 1525: + case 1526: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ReferenceOptionType -//line mysql_sql.y:10018 +//line mysql_sql.y:10024 { yyLOCAL = tree.REFERENCE_OPTION_SET_DEFAULT } yyVAL.union = yyLOCAL - case 1526: + case 1527: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:10023 +//line mysql_sql.y:10029 { yyLOCAL = tree.MATCH_INVALID } yyVAL.union = yyLOCAL - case 1528: + case 1529: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:10030 +//line mysql_sql.y:10036 { yyLOCAL = tree.MATCH_FULL } yyVAL.union = yyLOCAL - case 1529: + case 1530: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:10034 +//line mysql_sql.y:10040 { yyLOCAL = tree.MATCH_PARTIAL } yyVAL.union = yyLOCAL - case 1530: + case 1531: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.MatchType -//line mysql_sql.y:10038 +//line mysql_sql.y:10044 { yyLOCAL = tree.MATCH_SIMPLE } yyVAL.union = yyLOCAL - case 1531: + case 1532: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:10043 +//line mysql_sql.y:10049 { yyLOCAL = tree.FULLTEXT_DEFAULT } yyVAL.union = yyLOCAL - case 1532: + case 1533: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:10047 +//line mysql_sql.y:10053 { yyLOCAL = tree.FULLTEXT_NL } yyVAL.union = yyLOCAL - case 1533: + case 1534: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:10051 +//line mysql_sql.y:10057 { yyLOCAL = tree.FULLTEXT_NL_QUERY_EXPANSION } yyVAL.union = yyLOCAL - case 1534: + case 1535: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:10055 +//line mysql_sql.y:10061 { yyLOCAL = tree.FULLTEXT_BOOLEAN } yyVAL.union = yyLOCAL - case 1535: + case 1536: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.FullTextSearchType -//line mysql_sql.y:10059 +//line mysql_sql.y:10065 { yyLOCAL = tree.FULLTEXT_QUERY_EXPANSION } yyVAL.union = yyLOCAL - case 1536: + case 1537: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:10064 +//line mysql_sql.y:10070 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1537: + case 1538: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []*tree.KeyPart -//line mysql_sql.y:10068 +//line mysql_sql.y:10074 { yyLOCAL = yyDollar[2].keyPartsUnion() } yyVAL.union = yyLOCAL - case 1538: + case 1539: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:10073 +//line mysql_sql.y:10079 { yyLOCAL = -1 } yyVAL.union = yyLOCAL - case 1539: + case 1540: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int64 -//line mysql_sql.y:10077 +//line mysql_sql.y:10083 { yyLOCAL = yyDollar[2].item.(int64) } yyVAL.union = yyLOCAL - case 1546: + case 1547: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.Subquery -//line mysql_sql.y:10093 +//line mysql_sql.y:10099 { yyLOCAL = &tree.Subquery{Select: yyDollar[1].selectStatementUnion(), Exists: false} } yyVAL.union = yyLOCAL - case 1547: + case 1548: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10099 +//line mysql_sql.y:10105 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_AND, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1548: + case 1549: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10103 +//line mysql_sql.y:10109 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_OR, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1549: + case 1550: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10107 +//line mysql_sql.y:10113 { yyLOCAL = tree.NewBinaryExpr(tree.BIT_XOR, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1550: + case 1551: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10111 +//line mysql_sql.y:10117 { yyLOCAL = tree.NewBinaryExpr(tree.PLUS, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1551: + case 1552: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10115 +//line mysql_sql.y:10121 { yyLOCAL = tree.NewBinaryExpr(tree.MINUS, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1552: + case 1553: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10119 +//line mysql_sql.y:10125 { yyLOCAL = tree.NewBinaryExpr(tree.MULTI, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1553: + case 1554: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10123 +//line mysql_sql.y:10129 { yyLOCAL = tree.NewBinaryExpr(tree.DIV, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1554: + case 1555: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10127 +//line mysql_sql.y:10133 { yyLOCAL = tree.NewBinaryExpr(tree.INTEGER_DIV, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1555: + case 1556: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10131 +//line mysql_sql.y:10137 { yyLOCAL = tree.NewBinaryExpr(tree.MOD, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1556: + case 1557: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10135 +//line mysql_sql.y:10141 { yyLOCAL = tree.NewBinaryExpr(tree.MOD, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1557: + case 1558: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10139 +//line mysql_sql.y:10145 { yyLOCAL = tree.NewBinaryExpr(tree.LEFT_SHIFT, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1558: + case 1559: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10143 +//line mysql_sql.y:10149 { yyLOCAL = tree.NewBinaryExpr(tree.RIGHT_SHIFT, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1559: + case 1560: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10147 +//line mysql_sql.y:10153 { name := tree.NewUnresolvedColName("json_extract") yyLOCAL = &tree.FuncExpr{ @@ -23985,10 +24003,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1560: + case 1561: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10156 +//line mysql_sql.y:10162 { extractName := tree.NewUnresolvedColName("json_extract") inner := &tree.FuncExpr{ @@ -24004,90 +24022,90 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1561: + case 1562: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10171 +//line mysql_sql.y:10177 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1562: + case 1563: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10177 +//line mysql_sql.y:10183 { yyLOCAL = yyDollar[1].unresolvedNameUnion() } yyVAL.union = yyLOCAL - case 1563: + case 1564: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10181 +//line mysql_sql.y:10187 { yyLOCAL = yyDollar[1].varExprUnion() } yyVAL.union = yyLOCAL - case 1564: + case 1565: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10185 +//line mysql_sql.y:10191 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1565: + case 1566: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10189 +//line mysql_sql.y:10195 { yyLOCAL = tree.NewParentExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1566: + case 1567: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10193 +//line mysql_sql.y:10199 { yyLOCAL = tree.NewTuple(append(yyDollar[2].exprsUnion(), yyDollar[4].exprUnion())) } yyVAL.union = yyLOCAL - case 1567: + case 1568: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10197 +//line mysql_sql.y:10203 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_PLUS, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1568: + case 1569: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10201 +//line mysql_sql.y:10207 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_MINUS, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1569: + case 1570: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10205 +//line mysql_sql.y:10211 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_TILDE, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1570: + case 1571: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10209 +//line mysql_sql.y:10215 { yyLOCAL = tree.NewUnaryExpr(tree.UNARY_MARK, yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1571: + case 1572: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10213 +//line mysql_sql.y:10219 { hint := strings.ToLower(yyDollar[2].cstrUnion().Compare()) switch hint { @@ -24130,35 +24148,35 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1572: + case 1573: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10255 +//line mysql_sql.y:10261 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1573: + case 1574: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10259 +//line mysql_sql.y:10265 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1574: + case 1575: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10263 +//line mysql_sql.y:10269 { yyDollar[2].subqueryUnion().Exists = true yyLOCAL = yyDollar[2].subqueryUnion() } yyVAL.union = yyLOCAL - case 1575: + case 1576: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10268 +//line mysql_sql.y:10274 { yyLOCAL = &tree.CaseExpr{ Expr: yyDollar[2].exprUnion(), @@ -24167,50 +24185,50 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1576: + case 1577: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10276 +//line mysql_sql.y:10282 { yyLOCAL = tree.NewCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1577: + case 1578: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10280 +//line mysql_sql.y:10286 { yyLOCAL = tree.NewSerialExtractExpr(yyDollar[3].exprUnion(), yyDollar[5].exprUnion(), yyDollar[7].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1578: + case 1579: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10284 +//line mysql_sql.y:10290 { yyLOCAL = tree.NewBitCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1579: + case 1580: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10288 +//line mysql_sql.y:10294 { yyLOCAL = tree.NewCastExpr(yyDollar[1].exprUnion(), yyDollar[3].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1580: + case 1581: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10292 +//line mysql_sql.y:10298 { yyLOCAL = tree.NewCastExpr(yyDollar[3].exprUnion(), yyDollar[5].columnTypeUnion()) } yyVAL.union = yyLOCAL - case 1581: + case 1582: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10296 +//line mysql_sql.y:10302 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal(yyDollar[5].str, yyDollar[5].str, false, tree.P_char) @@ -24221,66 +24239,66 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1582: + case 1583: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10306 +//line mysql_sql.y:10312 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1583: + case 1584: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10310 +//line mysql_sql.y:10316 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1584: + case 1585: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10314 +//line mysql_sql.y:10320 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1585: + case 1586: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10318 +//line mysql_sql.y:10324 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1586: + case 1587: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10322 +//line mysql_sql.y:10328 { yyLOCAL = yyDollar[1].funcExprUnion() } yyVAL.union = yyLOCAL - case 1587: + case 1588: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10326 +//line mysql_sql.y:10332 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1588: + case 1589: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10330 +//line mysql_sql.y:10336 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1589: + case 1590: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10334 +//line mysql_sql.y:10340 { val, err := tree.NewFullTextMatchFuncExpression(yyDollar[3].keyPartsUnion(), yyDollar[7].str, yyDollar[8].fullTextSearchTypeUnion()) if err != nil { @@ -24290,16 +24308,16 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1590: + case 1591: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10345 +//line mysql_sql.y:10351 { yyVAL.str = yyDollar[1].str } - case 1591: + case 1592: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10351 +//line mysql_sql.y:10357 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24309,10 +24327,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1592: + case 1593: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10360 +//line mysql_sql.y:10366 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24322,10 +24340,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1593: + case 1594: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10369 +//line mysql_sql.y:10375 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24335,10 +24353,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1594: + case 1595: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10378 +//line mysql_sql.y:10384 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24348,10 +24366,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1595: + case 1596: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10387 +//line mysql_sql.y:10393 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24362,10 +24380,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1596: + case 1597: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10397 +//line mysql_sql.y:10403 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24375,10 +24393,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1597: + case 1598: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10406 +//line mysql_sql.y:10412 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24389,10 +24407,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1598: + case 1599: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10416 +//line mysql_sql.y:10422 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24403,10 +24421,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1599: + case 1600: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10426 +//line mysql_sql.y:10432 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24417,10 +24435,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1600: + case 1601: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10436 +//line mysql_sql.y:10442 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24431,10 +24449,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1601: + case 1602: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10446 +//line mysql_sql.y:10452 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24445,10 +24463,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1602: + case 1603: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10456 +//line mysql_sql.y:10462 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24459,10 +24477,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1603: + case 1604: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10466 +//line mysql_sql.y:10472 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24473,10 +24491,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1604: + case 1605: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10476 +//line mysql_sql.y:10482 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24487,10 +24505,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1605: + case 1606: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10486 +//line mysql_sql.y:10492 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -24501,10 +24519,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1606: + case 1607: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10498 +//line mysql_sql.y:10504 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, true, nil, "block") @@ -24515,10 +24533,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1607: + case 1608: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10508 +//line mysql_sql.y:10514 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, true, nil, yyDollar[8].str) @@ -24529,10 +24547,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1608: + case 1609: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10518 +//line mysql_sql.y:10524 { val, err := tree.NewSamplePercentFuncExpression1(yyDollar[5].item.(int64), true, nil) if err != nil { @@ -24542,10 +24560,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1609: + case 1610: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10527 +//line mysql_sql.y:10533 { val, err := tree.NewSamplePercentFuncExpression2(yyDollar[5].item.(float64), true, nil) if err != nil { @@ -24555,10 +24573,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1610: + case 1611: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10537 +//line mysql_sql.y:10543 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, false, yyDollar[3].exprsUnion(), "block") @@ -24569,10 +24587,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1611: + case 1612: yyDollar = yyS[yypt-9 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10547 +//line mysql_sql.y:10553 { v := int(yyDollar[5].item.(int64)) val, err := tree.NewSampleRowsFuncExpression(v, false, yyDollar[3].exprsUnion(), yyDollar[8].str) @@ -24583,10 +24601,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1612: + case 1613: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10557 +//line mysql_sql.y:10563 { val, err := tree.NewSamplePercentFuncExpression1(yyDollar[5].item.(int64), false, yyDollar[3].exprsUnion()) if err != nil { @@ -24596,10 +24614,10 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1613: + case 1614: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10566 +//line mysql_sql.y:10572 { val, err := tree.NewSamplePercentFuncExpression2(yyDollar[5].item.(float64), false, yyDollar[3].exprsUnion()) if err != nil { @@ -24609,58 +24627,58 @@ yydefault: yyLOCAL = val } yyVAL.union = yyLOCAL - case 1614: + case 1615: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10576 +//line mysql_sql.y:10582 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1615: + case 1616: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10580 +//line mysql_sql.y:10586 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1616: + case 1617: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10585 +//line mysql_sql.y:10591 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1617: + case 1618: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:10589 +//line mysql_sql.y:10595 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1618: + case 1619: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []*tree.When -//line mysql_sql.y:10595 +//line mysql_sql.y:10601 { yyLOCAL = []*tree.When{yyDollar[1].whenClauseUnion()} } yyVAL.union = yyLOCAL - case 1619: + case 1620: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL []*tree.When -//line mysql_sql.y:10599 +//line mysql_sql.y:10605 { yyLOCAL = append(yyDollar[1].whenClauseListUnion(), yyDollar[2].whenClauseUnion()) } yyVAL.union = yyLOCAL - case 1620: + case 1621: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.When -//line mysql_sql.y:10605 +//line mysql_sql.y:10611 { yyLOCAL = &tree.When{ Cond: yyDollar[2].exprUnion(), @@ -24668,9 +24686,9 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1621: + case 1622: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:10614 +//line mysql_sql.y:10620 { t := yyVAL.columnTypeUnion() str := strings.ToLower(t.InternalType.FamilyString) @@ -24683,10 +24701,10 @@ yydefault: } } } - case 1622: + case 1623: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10626 +//line mysql_sql.y:10632 { name := yyDollar[1].str if yyDollar[2].str != "" { @@ -24704,10 +24722,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1623: + case 1624: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10643 +//line mysql_sql.y:10649 { locale := "" yyLOCAL = &tree.T{ @@ -24722,10 +24740,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1625: + case 1626: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10660 +//line mysql_sql.y:10666 { locale := "" yyLOCAL = &tree.T{ @@ -24739,10 +24757,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1626: + case 1627: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10673 +//line mysql_sql.y:10679 { locale := "" yyLOCAL = &tree.T{ @@ -24756,10 +24774,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1627: + case 1628: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10686 +//line mysql_sql.y:10692 { locale := "" yyLOCAL = &tree.T{ @@ -24772,10 +24790,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1628: + case 1629: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10698 +//line mysql_sql.y:10704 { locale := "" yyLOCAL = &tree.T{ @@ -24790,10 +24808,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1629: + case 1630: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10712 +//line mysql_sql.y:10718 { locale := "" yyLOCAL = &tree.T{ @@ -24809,10 +24827,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1630: + case 1631: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10727 +//line mysql_sql.y:10733 { locale := "" yyLOCAL = &tree.T{ @@ -24828,10 +24846,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1631: + case 1632: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10742 +//line mysql_sql.y:10748 { name := yyDollar[1].str if yyDollar[2].str != "" { @@ -24849,10 +24867,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1632: + case 1633: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:10759 +//line mysql_sql.y:10765 { locale := "" yyLOCAL = &tree.T{ @@ -24867,95 +24885,95 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1633: + case 1634: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10775 +//line mysql_sql.y:10781 { } - case 1637: + case 1638: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10782 +//line mysql_sql.y:10788 { yyLOCAL = &tree.FrameBound{Type: tree.Following, UnBounded: true} } yyVAL.union = yyLOCAL - case 1638: + case 1639: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10786 +//line mysql_sql.y:10792 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1639: + case 1640: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10790 +//line mysql_sql.y:10796 { yyLOCAL = &tree.FrameBound{Type: tree.Following, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1640: + case 1641: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10796 +//line mysql_sql.y:10802 { yyLOCAL = &tree.FrameBound{Type: tree.CurrentRow} } yyVAL.union = yyLOCAL - case 1641: + case 1642: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10800 +//line mysql_sql.y:10806 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, UnBounded: true} } yyVAL.union = yyLOCAL - case 1642: + case 1643: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10804 +//line mysql_sql.y:10810 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1643: + case 1644: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameBound -//line mysql_sql.y:10808 +//line mysql_sql.y:10814 { yyLOCAL = &tree.FrameBound{Type: tree.Preceding, Expr: yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1644: + case 1645: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:10814 +//line mysql_sql.y:10820 { yyLOCAL = tree.Rows } yyVAL.union = yyLOCAL - case 1645: + case 1646: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:10818 +//line mysql_sql.y:10824 { yyLOCAL = tree.Range } yyVAL.union = yyLOCAL - case 1646: + case 1647: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FrameType -//line mysql_sql.y:10822 +//line mysql_sql.y:10828 { yyLOCAL = tree.Groups } yyVAL.union = yyLOCAL - case 1647: + case 1648: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10828 +//line mysql_sql.y:10834 { yyLOCAL = &tree.FrameClause{ Type: yyDollar[1].frameTypeUnion(), @@ -24964,10 +24982,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1648: + case 1649: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10836 +//line mysql_sql.y:10842 { yyLOCAL = &tree.FrameClause{ Type: yyDollar[1].frameTypeUnion(), @@ -24977,82 +24995,82 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1649: + case 1650: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10846 +//line mysql_sql.y:10852 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1650: + case 1651: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.FrameClause -//line mysql_sql.y:10850 +//line mysql_sql.y:10856 { yyLOCAL = yyDollar[1].frameClauseUnion() } yyVAL.union = yyLOCAL - case 1651: + case 1652: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:10856 +//line mysql_sql.y:10862 { yyLOCAL = yyDollar[3].exprsUnion() } yyVAL.union = yyLOCAL - case 1652: + case 1653: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:10861 +//line mysql_sql.y:10867 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1653: + case 1654: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:10865 +//line mysql_sql.y:10871 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1654: + case 1655: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10870 +//line mysql_sql.y:10876 { yyVAL.str = "," } - case 1655: + case 1656: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:10874 +//line mysql_sql.y:10880 { yyVAL.str = yyDollar[2].str } - case 1656: + case 1657: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:10879 +//line mysql_sql.y:10885 { yyVAL.str = "1,vector_l2_ops,random,false" } - case 1657: + case 1658: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:10883 +//line mysql_sql.y:10889 { yyVAL.str = yyDollar[2].str } - case 1658: + case 1659: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:10888 +//line mysql_sql.y:10894 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1660: + case 1661: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.WindowSpec -//line mysql_sql.y:10895 +//line mysql_sql.y:10901 { hasFrame := true var f *tree.FrameClause @@ -25077,10 +25095,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1661: + case 1662: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10921 +//line mysql_sql.y:10927 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25093,10 +25111,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1662: + case 1663: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10933 +//line mysql_sql.y:10939 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25109,10 +25127,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1663: + case 1664: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10945 +//line mysql_sql.y:10951 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25124,10 +25142,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1664: + case 1665: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10956 +//line mysql_sql.y:10962 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25139,10 +25157,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1665: + case 1666: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10967 +//line mysql_sql.y:10973 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal("*", "*", false, tree.P_char) @@ -25154,10 +25172,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1666: + case 1667: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10978 +//line mysql_sql.y:10984 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25168,10 +25186,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1667: + case 1668: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10988 +//line mysql_sql.y:10994 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25182,10 +25200,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1668: + case 1669: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:10998 +//line mysql_sql.y:11004 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25197,10 +25215,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1669: + case 1670: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11009 +//line mysql_sql.y:11015 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25212,10 +25230,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1670: + case 1671: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11020 +//line mysql_sql.y:11026 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25227,10 +25245,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1671: + case 1672: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11031 +//line mysql_sql.y:11037 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25242,10 +25260,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1672: + case 1673: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11042 +//line mysql_sql.y:11048 { name := tree.NewUnresolvedColName(yyDollar[1].str) es := tree.NewNumVal("*", "*", false, tree.P_char) @@ -25257,10 +25275,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1673: + case 1674: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11053 +//line mysql_sql.y:11059 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25272,10 +25290,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1674: + case 1675: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11064 +//line mysql_sql.y:11070 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25287,10 +25305,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1675: + case 1676: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11075 +//line mysql_sql.y:11081 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25302,10 +25320,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1676: + case 1677: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11086 +//line mysql_sql.y:11092 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25317,10 +25335,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1677: + case 1678: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11097 +//line mysql_sql.y:11103 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25332,10 +25350,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1678: + case 1679: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11108 +//line mysql_sql.y:11114 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25347,10 +25365,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1679: + case 1680: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11119 +//line mysql_sql.y:11125 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25362,10 +25380,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1680: + case 1681: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11130 +//line mysql_sql.y:11136 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25377,10 +25395,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1681: + case 1682: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11141 +//line mysql_sql.y:11147 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25392,10 +25410,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1682: + case 1683: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11152 +//line mysql_sql.y:11158 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25407,10 +25425,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1683: + case 1684: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11163 +//line mysql_sql.y:11169 { name := tree.NewUnresolvedColName(yyDollar[1].str) var columnList tree.Exprs @@ -25428,10 +25446,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1687: + case 1688: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11187 +//line mysql_sql.y:11193 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25441,10 +25459,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1688: + case 1689: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11196 +//line mysql_sql.y:11202 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25454,10 +25472,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1689: + case 1690: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11205 +//line mysql_sql.y:11211 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25467,10 +25485,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1690: + case 1691: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11214 +//line mysql_sql.y:11220 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25480,10 +25498,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1691: + case 1692: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11223 +//line mysql_sql.y:11229 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -25495,10 +25513,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1692: + case 1693: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11234 +//line mysql_sql.y:11240 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25508,10 +25526,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1693: + case 1694: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11243 +//line mysql_sql.y:11249 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25522,10 +25540,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1694: + case 1695: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11253 +//line mysql_sql.y:11259 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25535,10 +25553,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1695: + case 1696: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11262 +//line mysql_sql.y:11268 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25548,10 +25566,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1696: + case 1697: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11271 +//line mysql_sql.y:11277 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25561,10 +25579,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1697: + case 1698: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11280 +//line mysql_sql.y:11286 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25574,10 +25592,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1698: + case 1699: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11289 +//line mysql_sql.y:11295 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(0), "0", false, tree.P_int64) @@ -25590,10 +25608,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1699: + case 1700: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11301 +//line mysql_sql.y:11307 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(1), "1", false, tree.P_int64) @@ -25605,10 +25623,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1700: + case 1701: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11312 +//line mysql_sql.y:11318 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(2), "2", false, tree.P_int64) @@ -25622,10 +25640,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1701: + case 1702: yyDollar = yyS[yypt-7 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11325 +//line mysql_sql.y:11331 { name := tree.NewUnresolvedColName(yyDollar[1].str) arg0 := tree.NewNumVal(int64(3), "3", false, tree.P_int64) @@ -25638,10 +25656,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1702: + case 1703: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11337 +//line mysql_sql.y:11343 { column := tree.NewUnresolvedColName(yyDollar[3].str) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25652,16 +25670,16 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1709: + case 1710: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:11359 +//line mysql_sql.y:11365 { yyVAL.str = yyDollar[1].str } - case 1742: + case 1743: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11401 +//line mysql_sql.y:11407 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -25675,10 +25693,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1743: + case 1744: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11414 +//line mysql_sql.y:11420 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -25692,10 +25710,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1744: + case 1745: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11427 +//line mysql_sql.y:11433 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -25707,10 +25725,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1745: + case 1746: yyDollar = yyS[yypt-8 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11438 +//line mysql_sql.y:11444 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -25722,10 +25740,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1746: + case 1747: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11449 +//line mysql_sql.y:11455 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToUpper(yyDollar[3].str) @@ -25737,10 +25755,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1747: + case 1748: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11461 +//line mysql_sql.y:11467 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25750,10 +25768,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1748: + case 1749: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11470 +//line mysql_sql.y:11476 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25762,10 +25780,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1749: + case 1750: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11478 +//line mysql_sql.y:11484 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25774,10 +25792,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1750: + case 1751: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11486 +//line mysql_sql.y:11492 { name := tree.NewUnresolvedColName(yyDollar[1].str) var es tree.Exprs = nil @@ -25791,10 +25809,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1751: + case 1752: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11499 +//line mysql_sql.y:11505 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25804,10 +25822,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1752: + case 1753: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11508 +//line mysql_sql.y:11514 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := make([]tree.Expr, 1) @@ -25819,10 +25837,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1753: + case 1754: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11519 +//line mysql_sql.y:11525 { name := tree.NewUnresolvedColName(yyDollar[1].str) exprs := make([]tree.Expr, 1) @@ -25834,10 +25852,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1754: + case 1755: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11530 +//line mysql_sql.y:11536 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25847,10 +25865,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1755: + case 1756: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11539 +//line mysql_sql.y:11545 { cn := tree.NewNumVal(yyDollar[5].str, yyDollar[5].str, false, tree.P_char) es := yyDollar[3].exprsUnion() @@ -25863,10 +25881,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1756: + case 1757: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11551 +//line mysql_sql.y:11557 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25877,10 +25895,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1757: + case 1758: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11561 +//line mysql_sql.y:11567 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25891,10 +25909,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1758: + case 1759: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11571 +//line mysql_sql.y:11577 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25904,10 +25922,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1759: + case 1760: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11580 +//line mysql_sql.y:11586 { es := tree.Exprs{yyDollar[3].exprUnion()} es = append(es, yyDollar[5].exprUnion()) @@ -25919,10 +25937,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1760: + case 1761: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11591 +//line mysql_sql.y:11597 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25932,10 +25950,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1761: + case 1762: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11600 +//line mysql_sql.y:11606 { val := tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_char) name := tree.NewUnresolvedColName(yyDollar[1].str) @@ -25946,10 +25964,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1762: + case 1763: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11610 +//line mysql_sql.y:11616 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25959,10 +25977,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1763: + case 1764: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11619 +//line mysql_sql.y:11625 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25972,10 +25990,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1764: + case 1765: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.FuncExpr -//line mysql_sql.y:11628 +//line mysql_sql.y:11634 { name := tree.NewUnresolvedColName(yyDollar[1].str) yyLOCAL = &tree.FuncExpr{ @@ -25985,34 +26003,34 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1765: + case 1766: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11638 +//line mysql_sql.y:11644 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1766: + case 1767: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11642 +//line mysql_sql.y:11648 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1767: + case 1768: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11648 +//line mysql_sql.y:11654 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1768: + case 1769: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11652 +//line mysql_sql.y:11658 { ival, errStr := util.GetInt64(yyDollar[2].item) if errStr != "" { @@ -26023,20 +26041,20 @@ yydefault: yyLOCAL = tree.NewNumVal(ival, str, false, tree.P_int64) } yyVAL.union = yyLOCAL - case 1775: + case 1776: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:11671 +//line mysql_sql.y:11677 { } - case 1776: + case 1777: yyDollar = yyS[yypt-2 : yypt+1] -//line mysql_sql.y:11673 +//line mysql_sql.y:11679 { } - case 1811: + case 1812: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11715 +//line mysql_sql.y:11721 { name := tree.NewUnresolvedColName(yyDollar[1].str) str := strings.ToLower(yyDollar[3].str) @@ -26048,106 +26066,106 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1812: + case 1813: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:11727 +//line mysql_sql.y:11733 { yyLOCAL = tree.FUNC_TYPE_DEFAULT } yyVAL.union = yyLOCAL - case 1813: + case 1814: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:11731 +//line mysql_sql.y:11737 { yyLOCAL = tree.FUNC_TYPE_DISTINCT } yyVAL.union = yyLOCAL - case 1814: + case 1815: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.FuncType -//line mysql_sql.y:11735 +//line mysql_sql.y:11741 { yyLOCAL = tree.FUNC_TYPE_ALL } yyVAL.union = yyLOCAL - case 1815: + case 1816: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.Tuple -//line mysql_sql.y:11741 +//line mysql_sql.y:11747 { yyLOCAL = tree.NewTuple(yyDollar[2].exprsUnion()) } yyVAL.union = yyLOCAL - case 1816: + case 1817: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11746 +//line mysql_sql.y:11752 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1817: + case 1818: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11750 +//line mysql_sql.y:11756 { yyLOCAL = yyDollar[1].exprsUnion() } yyVAL.union = yyLOCAL - case 1818: + case 1819: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11756 +//line mysql_sql.y:11762 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1819: + case 1820: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11760 +//line mysql_sql.y:11766 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1820: + case 1821: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11766 +//line mysql_sql.y:11772 { yyLOCAL = tree.Exprs{yyDollar[1].exprUnion()} } yyVAL.union = yyLOCAL - case 1821: + case 1822: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Exprs -//line mysql_sql.y:11770 +//line mysql_sql.y:11776 { yyLOCAL = append(yyDollar[1].exprsUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1822: + case 1823: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11777 +//line mysql_sql.y:11783 { yyLOCAL = tree.NewAndExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1823: + case 1824: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11781 +//line mysql_sql.y:11787 { yyLOCAL = tree.NewOrExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1824: + case 1825: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11785 +//line mysql_sql.y:11791 { name := tree.NewUnresolvedColName("concat") yyLOCAL = &tree.FuncExpr{ @@ -26157,355 +26175,355 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1825: + case 1826: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11794 +//line mysql_sql.y:11800 { yyLOCAL = tree.NewXorExpr(yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1826: + case 1827: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11798 +//line mysql_sql.y:11804 { yyLOCAL = tree.NewNotExpr(yyDollar[2].exprUnion()) } yyVAL.union = yyLOCAL - case 1827: + case 1828: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11802 +//line mysql_sql.y:11808 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1828: + case 1829: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11807 +//line mysql_sql.y:11813 { yyLOCAL = yyDollar[1].exprUnion() } yyVAL.union = yyLOCAL - case 1829: + case 1830: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11811 +//line mysql_sql.y:11817 { yyLOCAL = tree.NewMaxValue() } yyVAL.union = yyLOCAL - case 1830: + case 1831: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11817 +//line mysql_sql.y:11823 { yyLOCAL = tree.NewIsNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1831: + case 1832: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11821 +//line mysql_sql.y:11827 { yyLOCAL = tree.NewIsNotNullExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1832: + case 1833: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11825 +//line mysql_sql.y:11831 { yyLOCAL = tree.NewIsUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1833: + case 1834: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11829 +//line mysql_sql.y:11835 { yyLOCAL = tree.NewIsNotUnknownExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1834: + case 1835: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11833 +//line mysql_sql.y:11839 { yyLOCAL = tree.NewIsTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1835: + case 1836: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11837 +//line mysql_sql.y:11843 { yyLOCAL = tree.NewIsNotTrueExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1836: + case 1837: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11841 +//line mysql_sql.y:11847 { yyLOCAL = tree.NewIsFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1837: + case 1838: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11845 +//line mysql_sql.y:11851 { yyLOCAL = tree.NewIsNotFalseExpr(yyDollar[1].exprUnion()) } yyVAL.union = yyLOCAL - case 1838: + case 1839: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11849 +//line mysql_sql.y:11855 { yyLOCAL = tree.NewComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1839: + case 1840: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11853 +//line mysql_sql.y:11859 { yyLOCAL = tree.NewSubqueryComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[3].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[4].subqueryUnion()) yyLOCAL = tree.NewSubqueryComparisonExpr(yyDollar[2].comparisonOpUnion(), yyDollar[3].comparisonOpUnion(), yyDollar[1].exprUnion(), yyDollar[4].subqueryUnion()) } yyVAL.union = yyLOCAL - case 1841: + case 1842: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11861 +//line mysql_sql.y:11867 { yyLOCAL = tree.NewComparisonExpr(tree.IN, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1842: + case 1843: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11865 +//line mysql_sql.y:11871 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_IN, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1843: + case 1844: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11869 +//line mysql_sql.y:11875 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.LIKE, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1844: + case 1845: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11873 +//line mysql_sql.y:11879 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_LIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 1845: + case 1846: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11877 +//line mysql_sql.y:11883 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.ILIKE, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1846: + case 1847: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11881 +//line mysql_sql.y:11887 { yyLOCAL = tree.NewComparisonExprWithEscape(tree.NOT_ILIKE, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 1847: + case 1848: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11885 +//line mysql_sql.y:11891 { yyLOCAL = tree.NewComparisonExpr(tree.REG_MATCH, yyDollar[1].exprUnion(), yyDollar[3].exprUnion()) } yyVAL.union = yyLOCAL - case 1848: + case 1849: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11889 +//line mysql_sql.y:11895 { yyLOCAL = tree.NewComparisonExpr(tree.NOT_REG_MATCH, yyDollar[1].exprUnion(), yyDollar[4].exprUnion()) } yyVAL.union = yyLOCAL - case 1849: + case 1850: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11893 +//line mysql_sql.y:11899 { yyLOCAL = tree.NewRangeCond(false, yyDollar[1].exprUnion(), yyDollar[3].exprUnion(), yyDollar[5].exprUnion()) } yyVAL.union = yyLOCAL - case 1850: + case 1851: yyDollar = yyS[yypt-6 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11897 +//line mysql_sql.y:11903 { yyLOCAL = tree.NewRangeCond(true, yyDollar[1].exprUnion(), yyDollar[4].exprUnion(), yyDollar[6].exprUnion()) } yyVAL.union = yyLOCAL - case 1852: + case 1853: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11903 +//line mysql_sql.y:11909 { yyLOCAL = nil } yyVAL.union = yyLOCAL - case 1853: + case 1854: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11907 +//line mysql_sql.y:11913 { yyLOCAL = yyDollar[2].exprUnion() } yyVAL.union = yyLOCAL - case 1854: + case 1855: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11913 +//line mysql_sql.y:11919 { yyLOCAL = yyDollar[1].tupleUnion() } yyVAL.union = yyLOCAL - case 1855: + case 1856: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11917 +//line mysql_sql.y:11923 { yyLOCAL = yyDollar[1].subqueryUnion() } yyVAL.union = yyLOCAL - case 1856: + case 1857: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11924 +//line mysql_sql.y:11930 { yyLOCAL = tree.ALL } yyVAL.union = yyLOCAL - case 1857: + case 1858: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11928 +//line mysql_sql.y:11934 { yyLOCAL = tree.ANY } yyVAL.union = yyLOCAL - case 1858: + case 1859: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11932 +//line mysql_sql.y:11938 { yyLOCAL = tree.SOME } yyVAL.union = yyLOCAL - case 1859: + case 1860: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11938 +//line mysql_sql.y:11944 { yyLOCAL = tree.EQUAL } yyVAL.union = yyLOCAL - case 1860: + case 1861: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11942 +//line mysql_sql.y:11948 { yyLOCAL = tree.LESS_THAN } yyVAL.union = yyLOCAL - case 1861: + case 1862: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11946 +//line mysql_sql.y:11952 { yyLOCAL = tree.GREAT_THAN } yyVAL.union = yyLOCAL - case 1862: + case 1863: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11950 +//line mysql_sql.y:11956 { yyLOCAL = tree.LESS_THAN_EQUAL } yyVAL.union = yyLOCAL - case 1863: + case 1864: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11954 +//line mysql_sql.y:11960 { yyLOCAL = tree.GREAT_THAN_EQUAL } yyVAL.union = yyLOCAL - case 1864: + case 1865: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11958 +//line mysql_sql.y:11964 { yyLOCAL = tree.NOT_EQUAL } yyVAL.union = yyLOCAL - case 1865: + case 1866: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ComparisonOp -//line mysql_sql.y:11962 +//line mysql_sql.y:11968 { yyLOCAL = tree.NULL_SAFE_EQUAL } yyVAL.union = yyLOCAL - case 1866: + case 1867: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11968 +//line mysql_sql.y:11974 { yyLOCAL = tree.NewAttributePrimaryKey() } yyVAL.union = yyLOCAL - case 1867: + case 1868: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11972 +//line mysql_sql.y:11978 { yyLOCAL = tree.NewAttributeUniqueKey() } yyVAL.union = yyLOCAL - case 1868: + case 1869: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11976 +//line mysql_sql.y:11982 { yyLOCAL = tree.NewAttributeUnique() } yyVAL.union = yyLOCAL - case 1869: + case 1870: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.ColumnAttribute -//line mysql_sql.y:11980 +//line mysql_sql.y:11986 { yyLOCAL = tree.NewAttributeKey() } yyVAL.union = yyLOCAL - case 1870: + case 1871: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11986 +//line mysql_sql.y:11992 { str := fmt.Sprintf("%v", yyDollar[1].item) switch v := yyDollar[1].item.(type) { @@ -26519,35 +26537,35 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1871: + case 1872: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:11999 +//line mysql_sql.y:12005 { fval := yyDollar[1].item.(float64) yyLOCAL = tree.NewNumVal(fval, yylex.(*Lexer).scanner.LastToken, false, tree.P_float64) } yyVAL.union = yyLOCAL - case 1872: + case 1873: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12004 +//line mysql_sql.y:12010 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_decimal) } yyVAL.union = yyLOCAL - case 1873: + case 1874: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12010 +//line mysql_sql.y:12016 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_char) } yyVAL.union = yyLOCAL - case 1874: + case 1875: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12014 +//line mysql_sql.y:12020 { str := fmt.Sprintf("%v", yyDollar[1].item) switch v := yyDollar[1].item.(type) { @@ -26561,51 +26579,51 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1875: + case 1876: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12027 +//line mysql_sql.y:12033 { fval := yyDollar[1].item.(float64) yyLOCAL = tree.NewNumVal(fval, yylex.(*Lexer).scanner.LastToken, false, tree.P_float64) } yyVAL.union = yyLOCAL - case 1876: + case 1877: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12032 +//line mysql_sql.y:12038 { yyLOCAL = tree.NewNumVal(true, "true", false, tree.P_bool) } yyVAL.union = yyLOCAL - case 1877: + case 1878: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12036 +//line mysql_sql.y:12042 { yyLOCAL = tree.NewNumVal(false, "false", false, tree.P_bool) } yyVAL.union = yyLOCAL - case 1878: + case 1879: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12040 +//line mysql_sql.y:12046 { yyLOCAL = tree.NewNumVal("null", "null", false, tree.P_null) } yyVAL.union = yyLOCAL - case 1879: + case 1880: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12044 +//line mysql_sql.y:12050 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_hexnum) } yyVAL.union = yyLOCAL - case 1880: + case 1881: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12048 +//line mysql_sql.y:12054 { if strings.HasPrefix(yyDollar[2].str, "0x") { yyDollar[2].str = yyDollar[2].str[2:] @@ -26613,69 +26631,69 @@ yydefault: yyLOCAL = tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_bit) } yyVAL.union = yyLOCAL - case 1881: + case 1882: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12055 +//line mysql_sql.y:12061 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_decimal) } yyVAL.union = yyLOCAL - case 1882: + case 1883: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12059 +//line mysql_sql.y:12065 { yyLOCAL = tree.NewNumVal(yyDollar[1].str, yyDollar[1].str, false, tree.P_bit) } yyVAL.union = yyLOCAL - case 1883: + case 1884: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12063 +//line mysql_sql.y:12069 { yyLOCAL = tree.NewParamExpr(yylex.(*Lexer).GetParamIndex()) } yyVAL.union = yyLOCAL - case 1884: + case 1885: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Expr -//line mysql_sql.y:12067 +//line mysql_sql.y:12073 { yyLOCAL = tree.NewNumVal(yyDollar[2].str, yyDollar[2].str, false, tree.P_ScoreBinary) } yyVAL.union = yyLOCAL - case 1885: + case 1886: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12073 +//line mysql_sql.y:12079 { yyLOCAL = yyDollar[1].columnTypeUnion() yyLOCAL.InternalType.Unsigned = yyDollar[2].unsignedOptUnion() yyLOCAL.InternalType.Zerofill = yyDollar[3].zeroFillOptUnion() } yyVAL.union = yyLOCAL - case 1889: + case 1890: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12084 +//line mysql_sql.y:12090 { yyLOCAL = yyDollar[1].columnTypeUnion() yyLOCAL.InternalType.DisplayWith = yyDollar[2].lengthOptUnion() } yyVAL.union = yyLOCAL - case 1890: + case 1891: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12089 +//line mysql_sql.y:12095 { yyLOCAL = yyDollar[1].columnTypeUnion() } yyVAL.union = yyLOCAL - case 1891: + case 1892: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12095 +//line mysql_sql.y:12101 { locale := "" yyLOCAL = &tree.T{ @@ -26688,10 +26706,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1892: + case 1893: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12107 +//line mysql_sql.y:12113 { locale := "" yyLOCAL = &tree.T{ @@ -26704,10 +26722,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1893: + case 1894: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12119 +//line mysql_sql.y:12125 { locale := "" yyLOCAL = &tree.T{ @@ -26720,10 +26738,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1894: + case 1895: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12131 +//line mysql_sql.y:12137 { locale := "" yyLOCAL = &tree.T{ @@ -26737,10 +26755,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1895: + case 1896: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12144 +//line mysql_sql.y:12150 { locale := "" yyLOCAL = &tree.T{ @@ -26754,10 +26772,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1896: + case 1897: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12157 +//line mysql_sql.y:12163 { locale := "" yyLOCAL = &tree.T{ @@ -26771,10 +26789,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1897: + case 1898: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12170 +//line mysql_sql.y:12176 { locale := "" yyLOCAL = &tree.T{ @@ -26788,10 +26806,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1898: + case 1899: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12183 +//line mysql_sql.y:12189 { locale := "" yyLOCAL = &tree.T{ @@ -26805,10 +26823,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1899: + case 1900: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12196 +//line mysql_sql.y:12202 { locale := "" yyLOCAL = &tree.T{ @@ -26822,10 +26840,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1900: + case 1901: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12209 +//line mysql_sql.y:12215 { locale := "" yyLOCAL = &tree.T{ @@ -26839,10 +26857,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1901: + case 1902: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12222 +//line mysql_sql.y:12228 { locale := "" yyLOCAL = &tree.T{ @@ -26856,10 +26874,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1902: + case 1903: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12235 +//line mysql_sql.y:12241 { locale := "" yyLOCAL = &tree.T{ @@ -26873,10 +26891,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1903: + case 1904: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12248 +//line mysql_sql.y:12254 { locale := "" yyLOCAL = &tree.T{ @@ -26890,10 +26908,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1904: + case 1905: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12261 +//line mysql_sql.y:12267 { locale := "" yyLOCAL = &tree.T{ @@ -26907,10 +26925,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1905: + case 1906: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12276 +//line mysql_sql.y:12282 { locale := "" if yyDollar[2].lengthScaleOptUnion().DisplayWith > 255 { @@ -26938,10 +26956,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1906: + case 1907: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12303 +//line mysql_sql.y:12309 { locale := "" if yyDollar[2].lengthScaleOptUnion().DisplayWith > 255 { @@ -26983,10 +27001,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1907: + case 1908: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12345 +//line mysql_sql.y:12351 { locale := "" if yyDollar[2].lengthScaleOptUnion().Scale != tree.NotDefineDec && yyDollar[2].lengthScaleOptUnion().Scale > yyDollar[2].lengthScaleOptUnion().DisplayWith { @@ -27023,10 +27041,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1908: + case 1909: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12381 +//line mysql_sql.y:12387 { locale := "" if yyDollar[2].lengthScaleOptUnion().Scale != tree.NotDefineDec && yyDollar[2].lengthScaleOptUnion().Scale > yyDollar[2].lengthScaleOptUnion().DisplayWith { @@ -27063,10 +27081,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1909: + case 1910: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12417 +//line mysql_sql.y:12423 { locale := "" yyLOCAL = &tree.T{ @@ -27082,10 +27100,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1910: + case 1911: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12434 +//line mysql_sql.y:12440 { locale := "" yyLOCAL = &tree.T{ @@ -27098,10 +27116,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1911: + case 1912: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12446 +//line mysql_sql.y:12452 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -27122,10 +27140,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1912: + case 1913: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12466 +//line mysql_sql.y:12472 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -27146,10 +27164,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1913: + case 1914: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12486 +//line mysql_sql.y:12492 { locale := "" if yyDollar[2].lengthOptUnion() < 0 || yyDollar[2].lengthOptUnion() > 6 { @@ -27170,10 +27188,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1914: + case 1915: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12506 +//line mysql_sql.y:12512 { locale := "" yyLOCAL = &tree.T{ @@ -27188,10 +27206,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1915: + case 1916: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12522 +//line mysql_sql.y:12528 { locale := "" yyLOCAL = &tree.T{ @@ -27205,10 +27223,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1916: + case 1917: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12535 +//line mysql_sql.y:12541 { locale := "" yyLOCAL = &tree.T{ @@ -27222,10 +27240,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1917: + case 1918: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12548 +//line mysql_sql.y:12554 { locale := "" yyLOCAL = &tree.T{ @@ -27239,10 +27257,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1918: + case 1919: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12561 +//line mysql_sql.y:12567 { locale := "" yyLOCAL = &tree.T{ @@ -27256,10 +27274,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1919: + case 1920: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12574 +//line mysql_sql.y:12580 { locale := "" yyLOCAL = &tree.T{ @@ -27272,10 +27290,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1920: + case 1921: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12586 +//line mysql_sql.y:12592 { locale := "" yyLOCAL = &tree.T{ @@ -27288,10 +27306,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1921: + case 1922: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12598 +//line mysql_sql.y:12604 { locale := "" yyLOCAL = &tree.T{ @@ -27304,10 +27322,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1922: + case 1923: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12610 +//line mysql_sql.y:12616 { locale := "" yyLOCAL = &tree.T{ @@ -27320,10 +27338,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1923: + case 1924: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12622 +//line mysql_sql.y:12628 { locale := "" yyLOCAL = &tree.T{ @@ -27336,10 +27354,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1924: + case 1925: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12634 +//line mysql_sql.y:12640 { locale := "" yyLOCAL = &tree.T{ @@ -27352,10 +27370,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1925: + case 1926: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12646 +//line mysql_sql.y:12652 { locale := "" yyLOCAL = &tree.T{ @@ -27368,10 +27386,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1926: + case 1927: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12658 +//line mysql_sql.y:12664 { locale := "" yyLOCAL = &tree.T{ @@ -27384,10 +27402,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1927: + case 1928: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12670 +//line mysql_sql.y:12676 { locale := "" yyLOCAL = &tree.T{ @@ -27400,10 +27418,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1928: + case 1929: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12682 +//line mysql_sql.y:12688 { locale := "" yyLOCAL = &tree.T{ @@ -27416,10 +27434,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1929: + case 1930: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12694 +//line mysql_sql.y:12700 { locale := "" yyLOCAL = &tree.T{ @@ -27433,10 +27451,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1930: + case 1931: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12707 +//line mysql_sql.y:12713 { locale := "" yyLOCAL = &tree.T{ @@ -27450,10 +27468,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1931: + case 1932: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12720 +//line mysql_sql.y:12726 { locale := "" yyLOCAL = &tree.T{ @@ -27467,10 +27485,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1932: + case 1933: yyDollar = yyS[yypt-4 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12733 +//line mysql_sql.y:12739 { locale := "" yyLOCAL = &tree.T{ @@ -27484,10 +27502,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1933: + case 1934: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12746 +//line mysql_sql.y:12752 { locale := "" yyLOCAL = &tree.T{ @@ -27501,20 +27519,20 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1934: + case 1935: yyDollar = yyS[yypt-2 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:12761 +//line mysql_sql.y:12767 { yyLOCAL = &tree.Do{ Exprs: yyDollar[2].exprsUnion(), } } yyVAL.union = yyLOCAL - case 1935: + case 1936: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:12769 +//line mysql_sql.y:12775 { yyLOCAL = &tree.Declare{ Variables: yyDollar[2].strsUnion(), @@ -27523,10 +27541,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1936: + case 1937: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.Statement -//line mysql_sql.y:12778 +//line mysql_sql.y:12784 { yyLOCAL = &tree.Declare{ Variables: yyDollar[2].strsUnion(), @@ -27535,10 +27553,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1937: + case 1938: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL *tree.T -//line mysql_sql.y:12788 +//line mysql_sql.y:12794 { locale := "" yyLOCAL = &tree.T{ @@ -27551,75 +27569,75 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1938: + case 1939: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12811 +//line mysql_sql.y:12817 { yyLOCAL = make([]string, 0, 4) yyLOCAL = append(yyLOCAL, yyDollar[1].str) } yyVAL.union = yyLOCAL - case 1939: + case 1940: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL []string -//line mysql_sql.y:12816 +//line mysql_sql.y:12822 { yyLOCAL = append(yyDollar[1].strsUnion(), yyDollar[3].str) } yyVAL.union = yyLOCAL - case 1940: + case 1941: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12822 +//line mysql_sql.y:12828 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1942: + case 1943: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12829 +//line mysql_sql.y:12835 { yyLOCAL = 0 } yyVAL.union = yyLOCAL - case 1943: + case 1944: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12833 +//line mysql_sql.y:12839 { yyLOCAL = int32(yyDollar[2].item.(int64)) } yyVAL.union = yyLOCAL - case 1944: + case 1945: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12838 +//line mysql_sql.y:12844 { yyLOCAL = int32(-1) } yyVAL.union = yyLOCAL - case 1945: + case 1946: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12842 +//line mysql_sql.y:12848 { yyLOCAL = int32(yyDollar[2].item.(int64)) } yyVAL.union = yyLOCAL - case 1946: + case 1947: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL int32 -//line mysql_sql.y:12848 +//line mysql_sql.y:12854 { yyLOCAL = tree.GetDisplayWith(int32(yyDollar[2].item.(int64))) } yyVAL.union = yyLOCAL - case 1947: + case 1948: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12854 +//line mysql_sql.y:12860 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.NotDefineDisplayWidth, @@ -27627,10 +27645,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1948: + case 1949: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12861 +//line mysql_sql.y:12867 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -27638,10 +27656,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1949: + case 1950: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12868 +//line mysql_sql.y:12874 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -27649,10 +27667,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1950: + case 1951: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12877 +//line mysql_sql.y:12883 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: 38, // this is the default precision for decimal @@ -27660,10 +27678,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1951: + case 1952: yyDollar = yyS[yypt-3 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12884 +//line mysql_sql.y:12890 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -27671,10 +27689,10 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1952: + case 1953: yyDollar = yyS[yypt-5 : yypt+1] var yyLOCAL tree.LengthScaleOpt -//line mysql_sql.y:12891 +//line mysql_sql.y:12897 { yyLOCAL = tree.LengthScaleOpt{ DisplayWith: tree.GetDisplayWith(int32(yyDollar[2].item.(int64))), @@ -27682,52 +27700,52 @@ yydefault: } } yyVAL.union = yyLOCAL - case 1953: + case 1954: yyDollar = yyS[yypt-0 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12900 +//line mysql_sql.y:12906 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1954: + case 1955: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12904 +//line mysql_sql.y:12910 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1955: + case 1956: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12908 +//line mysql_sql.y:12914 { yyLOCAL = false } yyVAL.union = yyLOCAL - case 1956: + case 1957: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12914 +//line mysql_sql.y:12920 { } - case 1957: + case 1958: yyDollar = yyS[yypt-1 : yypt+1] var yyLOCAL bool -//line mysql_sql.y:12916 +//line mysql_sql.y:12922 { yyLOCAL = true } yyVAL.union = yyLOCAL - case 1961: + case 1962: yyDollar = yyS[yypt-0 : yypt+1] -//line mysql_sql.y:12926 +//line mysql_sql.y:12932 { yyVAL.str = "" } - case 1962: + case 1963: yyDollar = yyS[yypt-1 : yypt+1] -//line mysql_sql.y:12930 +//line mysql_sql.y:12936 { yyVAL.str = string(yyDollar[1].str) } From 42e7c2734cbee8d6d9b372d90769c0008939eba9 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 2 Mar 2026 12:57:10 +0800 Subject: [PATCH 14/23] chore(data-branch): clean up docs and revert unused disttae changes --- bench_delete_perf_20260122_190508.md | 15 - bench_insert_perf_20260122_191042.md | 14 - bench_insert_perf_20260123_103322.md | 14 - .../databranchutils/BRANCH_HASHMAP_DESIGN.md | 295 +++++++++++++--- .../BRANCH_HASHMAP_REDESIGN.md | 316 ------------------ .../disttae/local_disttae_datasource.go | 9 - .../disttae/logtailreplay/partition_state.go | 13 - 7 files changed, 244 insertions(+), 432 deletions(-) delete mode 100644 bench_delete_perf_20260122_190508.md delete mode 100644 bench_insert_perf_20260122_191042.md delete mode 100644 bench_insert_perf_20260123_103322.md delete mode 100644 pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md diff --git a/bench_delete_perf_20260122_190508.md b/bench_delete_perf_20260122_190508.md deleted file mode 100644 index aa7972623355f..0000000000000 --- a/bench_delete_perf_20260122_190508.md +++ /dev/null @@ -1,15 +0,0 @@ -# Delete Benchmark Report - -- db: bench_delete_perf -- total_rows: 10000000 -- delete_rows: 81920 -- batch_size: 8192 -- batches: 10 -- started_at: 20260122_190508 - -|strategy|total_sec|avg_ms_per_batch|rows_per_sec| -|---|---|---|---| -in_list|25.240|2524.032|3246 -subquery_in|0.332|33.198|246763 -join_keys|0.350|34.965|234295 -range|0.394|39.372|208067 diff --git a/bench_insert_perf_20260122_191042.md b/bench_insert_perf_20260122_191042.md deleted file mode 100644 index 995f6f01a7e2b..0000000000000 --- a/bench_insert_perf_20260122_191042.md +++ /dev/null @@ -1,14 +0,0 @@ -# Insert Benchmark Report - -- db: bench_insert_perf -- total_rows: 10000000 -- insert_rows: 81920 -- batch_size: 8192 -- batches: 10 -- started_at: 20260122_191042 - -|strategy|total_sec|avg_ms_per_batch|rows_per_sec| -|---|---|---|---| -values_list|16.861|1686.127|4858 -values_select|19.714|1971.412|4155 -subquery_select|0.434|43.361|188923 diff --git a/bench_insert_perf_20260123_103322.md b/bench_insert_perf_20260123_103322.md deleted file mode 100644 index 25d6e240056eb..0000000000000 --- a/bench_insert_perf_20260123_103322.md +++ /dev/null @@ -1,14 +0,0 @@ -# Insert Benchmark Report - -- db: bench_insert_perf -- total_rows: 10000000 -- insert_rows: 81920 -- batch_size: 8192 -- batches: 10 -- started_at: 20260123_103322 - -|strategy|total_sec|avg_ms_per_batch|rows_per_sec| -|---|---|---|---| -values_list|15.160|1516.049|5404 -values_select|16.953|1695.303|4832 -subquery_select|0.562|56.167|145851 diff --git a/pkg/frontend/databranchutils/BRANCH_HASHMAP_DESIGN.md b/pkg/frontend/databranchutils/BRANCH_HASHMAP_DESIGN.md index 339e4ee18b74a..538ad6721f8b1 100644 --- a/pkg/frontend/databranchutils/BRANCH_HASHMAP_DESIGN.md +++ b/pkg/frontend/databranchutils/BRANCH_HASHMAP_DESIGN.md @@ -1,51 +1,244 @@ -# Branch Hashmap Optimization Plan - -This document captures the design decisions for the sharded `branchHashmap`. All code changes must honor the behavior described here. - -## Goals -- Provide predictable high concurrency for `Put`, `Get`, `Pop`, and iteration while keeping the API surface concurrency-safe. -- Keep work per lock bounded to reduce tail latency even with tens of millions of rows. -- Minimize memory copies so `PutByVectors` can ingest 8,192-row batches efficiently. -- Preserve spill-to-disk semantics and leave TODO hooks for later monitoring instrumentation. - -## Architecture Overview -1. **Shard-per-lock structure**: The hashmap is split into `N` shards, configured via `NewBranchHashmap` options. `N` must satisfy `4 <= N <= 64`. Defaults use `runtime.NumCPU() * 4` clamped into that range. Each shard owns its buckets, spill state, and accounting. -2. **Strictly serial shard operations**: Each shard exposes `putBatch`, `probe`, `pop`, and `iterate` routines guarded by its mutex. No goroutines run inside shards; serialization happens at the shard boundary while callers gain concurrency by hashing onto different shards. -3. **ForEachShardParallel API**: Callers iterate shard-by-shard by invoking `ForEachShardParallel(fn, parallelism)`. The callback receives a `ShardCursor` that offers read-only iteration and helper mutations (`PopByEncodedKey`). Internally the hashmap fans work out to a goroutine pool so different shards progress concurrently while each shard still executes serially. -4. **Read-only return data**: Data slices returned from public APIs alias internal buffers and must be treated as read-only. Callers copy if they need to retain data after the next hashmap call. - -## Key APIs & Semantics -- `PutByVectors` encodes up to 8,192 rows per call, allocates once per chunk, and dispatches entries to shards based on hash. -- `GetByVectors` / `PopByVectors` encode keys sequentially inside the calling goroutine and rely on shard-level parallelism plus caller-driven concurrency rather than spawning worker pools. -- `PopByEncodedKey` remains O(1) when provided a pre-encoded key. Calls targeting the same shard serialize; different shards operate concurrently. -- `PopByEncodedFullValues` reconstructs keys from full row payloads before delegating to key-based pop, allowing callers that only have value encoding to remove entries. -- `ForEachShardParallel` replaces the old `ForEach`. `PopByEncodedKey` must be invoked via `ShardCursor` while holding the shard lock to avoid blocking other shards. `parallelism <= 0` uses `min(runtime.NumCPU(), shardCount)`; positive values are clamped to `[1, shardCount]`. -- `ItemCount` returns the current row count using shard-local counters that are updated during insertions and removals. No iteration is required to compute the total. -- Returned rows still decode via `DecodeRow` without changing tuple order. -- `Project(keyCols, parallelism)` builds a new hashmap by re-encoding keys with the provided column indexes while keeping the original value payloads. Work is fanned out by shard using `ForEachShardParallel`; large shards are processed in batches to cap memory pressure. The returned hashmap is independent of the source (separate storage and locks). `parallelism` follows the same clamping rules as `ForEachShardParallel`. -- `Migrate(keyCols, parallelism)` migrates rows into a new hashmap and removes them from the source during traversal to avoid holding double memory. Key re-encoding and batching semantics match `Project`; removal uses shard-local pop to stay non-blocking for other shards. - -## Memory Management -- Each shard pools `entryBlock` arenas so large slabs are reused. Temporary packers, key buffers, and batches sit in global `sync.Pool`s to avoid GC churn. -- Encoding for `PutByVectors` allocates per batch rather than per row to keep allocator pressure low. - -## Spill Strategy -- Spills are triggered globally but executed per shard. Each shard tracks its spill manifest and exposes both in-memory and spilled rows when iterating. - -## Concurrency & Correctness -- All public APIs are concurrency-safe. Shard locks serialize same-key work while allowing cross-shard parallelism. -- Adding or removing keys within a shard during iteration is only legal via the provided cursor helpers. This keeps iteration deterministic. - -## Testing & Benchmarking -- Unit tests cover sharding defaults, concurrent `Put/Get/Pop`, `ForEachShardParallel` semantics, spill handling, and read-only guarantees. -- Benchmarks focus on multi-shard `Put` throughput and `Get` latency to verify batching efficiency. - -## Observability -- TODO hooks exist in insertion and spill paths so future monitoring can expose shard-level metrics once instrumentation is ready. - -## Implementation Order -1. Introduce configuration, shard structs, and options. -2. Route Put/Get/Pop through shards. -3. Implement `ForEachShardParallel` and update iteration call sites. -4. Add tests/benchmarks for concurrency, spill, and iteration paths. -5. Wire monitoring once metrics infrastructure is available. +# Branch Hashmap Design (Current Implementation) + +This document describes the current, implemented behavior of `pkg/frontend/databranchutils/branch_hashmap.go`. +It replaces older split docs and avoids forward-looking proposals that are not in code yet. + +## 1. Scope + +`BranchHashmap` is a shard-based, spill-capable hashmap used by data-branch diff/merge logic. It supports: + +- vector batch insert (`PutByVectors`) +- key probing and removal (`Get*`, `Pop*`) +- shard-parallel iteration with in-iteration mutation helpers (`ForEachShardParallel`) +- key re-projection (`Project`) and consuming migration (`Migrate`) + +Non-goals in current implementation: + +- point-lookups optimized for very large spilled datasets (spill path is scan-based) +- crash recovery for spill files (spill files are temporary process-local artifacts) +- automatic compaction of tombstoned spill data + +## 2. High-Level Architecture + +``` +branchHashmap + ├─ meta: valueTypes, keyTypes, keyCols, allocator, options + ├─ shard[0..N-1] + │ ├─ memStore (open-addressing hash index + flat entries + LRU) + │ ├─ spillStore (optional; bucketed segmented files + tombstone bitmap) + │ └─ mutex + iteration gate + item counter + ├─ packer pool + └─ prepared-entry batch pool +``` + +### 2.1 Sharding + +- Default shard count: `runtime.NumCPU() * 4` +- Clamped range: `[4, 128]` +- Shard index: `hash(key) % shardCount` +- Each shard serializes operations via shard mutex. + +### 2.2 Hashing + +- Hash function: `hashtable.BytesBatchGenHashStatesWithSeed` +- Seed: `branchHashSeed = 0x9e3779b97f4a7c15` +- Hash key input is the encoded key bytes. + +## 3. Data Model and Encoding + +### 3.1 Row Encoding + +- Keys and rows are encoded with `types.Packer`. +- Supported types are implemented in `encodeValue` / `encodeDecodedValue`. +- Null values are encoded explicitly. +- On first `PutByVectors`, hashmap captures: + - `valueTypes` (all columns), + - `keyCols` and `keyTypes`. +- Later puts must match vector schema and key definition exactly. + +### 3.2 Duplicate Keys + +- Duplicate keys are supported. +- A key can map to multiple encoded row payloads (`[][]byte`). + +## 4. In-Memory Store + +Each shard owns a `memStore`: + +- hash index: open addressing (`memSlotEmpty = -1`, tombstone slot = `-2`) +- flat `entries []memEntry` +- free list for entry index reuse +- LRU chain (`lruHead`, `lruTail`) for spill eviction candidate selection + +`memEntry` stores: + +- `hash` +- key/value offsets + lengths into an `entryBlock` buffer +- index slot and LRU links +- `inUse` flag + +`entryBlock` keeps one allocator-backed buffer for a batch and an atomic refcount. Entry removal decrements refcount and frees allocator memory when zero. + +## 5. Spill Store + +Spill is shard-local and optional (created lazily when needed). + +### 5.1 Bucket and Segment Layout + +- Buckets per shard: default `1024`, normalized to power-of-two +- Bucket id: `hash & (bucketCount-1)` +- Segment max bytes: default `128MB` +- Segment filename: `spill-b%05d-%06d.bin` + +### 5.2 On-Disk Record Format + +Per record: + +- `hash` (uint64, little-endian) +- `keyLen` (uint32, little-endian) +- `valLen` (uint32, little-endian) +- `key bytes` +- `value bytes` + +### 5.3 Deletion in Spill + +- No in-place rewrite. +- Deletions set tombstones in per-bucket bitmap (`rid -> deleted`). +- Reads/iteration skip tombstoned records. + +## 6. Core Operation Semantics + +### 6.1 PutByVectors + +- Batch size target: `8192` rows (`putBatchSize`). +- Encodes key/value per row, groups by shard, inserts under shard lock. +- Allocation path: + - try allocator + - if allocator returns `nil` buffer: trigger global spill and retry + - if still cannot fit, split chunk recursively + - for single-entry chunk, fallback to Go heap allocation + +### 6.2 Get / Pop by vectors + +- Key vectors are encoded in caller goroutine. +- Probes are grouped by shard and processed under each shard lock. +- `GetByVectors`: + - in-memory hits return read-only slices aliased to internal buffers + - spill hits return copied payloads +- `PopByVectors(removeAll=true)` removes all rows for each key. +- `PopByVectors(removeAll=false)` removes one row per probed key entry. + +### 6.3 Encoded-key operations + +- `GetByEncodedKey` +- `PopByEncodedKey` +- `PopByEncodedKeyValue` +- `PopByEncodedFullValue` +- `PopByEncodedFullValueExact` + +`PopByEncodedFullValue*` reconstruct key bytes from the full encoded row payload and then delegates to key/key+value removal. + +### 6.4 Streaming pop + +`PopByVectorsStream` removes like `PopByVectors`, but invokes callback per removed row: + +- callback receives `(probeIndex, encodedKey, encodedRow)` +- removed row payload is copied and safe to keep +- key bytes may come from ephemeral scan buffers for spilled rows; copy if retained + +## 7. Iteration and Concurrency Model + +### 7.1 ForEachShardParallel + +- Runs one task per shard via `ants` worker pool. +- `parallelism <= 0` => defaults to `runtime.NumCPU()`, then clamped to `[1, shardCount]`. +- Per shard: + - `beginIteration` sets `iterating=true` + - normal lock-based operations wait until iteration ends + - callback receives `ShardCursor` + +### 7.2 ShardCursor guarantees + +- `cursor.ForEach` iterates per entry, not grouped by key. +- order: + - all in-memory entries first (`memStore.forEach`) + - then spill buckets in bucket order and segment scan order +- mutation helpers (`PopByEncodedKey`, `PopByEncodedKeyValue`) are allowed during cursor lifecycle and operate in shard iteration context. + +Data lifetime rule: + +- data returned to callback must be treated as transient read-only views unless caller copies it. + +## 8. Project and Migrate + +Both APIs rebuild a new hashmap with new key columns: + +- target keeps source allocator and spill settings +- target shard count equals source shard count +- target value rows keep original encoded row payload + +`Project`: + +- source remains unchanged + +`Migrate`: + +- consumes source by popping keys during iteration +- reduces peak memory compared with duplicating full dataset + +Edge behavior: + +- if source `ItemCount()==0`, current code returns `NewBranchHashmap()` with default options. + +## 9. Lifecycle, Errors, and Cleanup + +- `Close()` is idempotent. +- Close path: + - releases in-memory entry blocks + - closes spill store + - removes spill files and spill directory +- If spill stats exist, close logs aggregate spill summary. +- On spill write/scan errors, operation returns error; no crash-recovery protocol is implemented. + +## 10. Configuration Defaults + +| Parameter | Current Default | Notes | +|---|---:|---| +| shard count | `clamp(runtime.NumCPU()*4, 4, 128)` | configurable by option | +| spill bucket count | `1024` | normalized to power-of-two | +| spill segment max bytes | `128MB` | configurable by option | +| put batch size | `8192` | internal constant | +| mem index initial size | `1024` | internal constant | + +## 11. Observability + +Current implementation records spill statistics and prints aggregate summary on `Close()`, including: + +- spill bytes/entries +- bucket scans and scan amplification indicators +- get/pop probe-to-scan ratios +- repeated bucket scan hints + +Fine-grained runtime metrics are marked as TODO in code. + +## 12. Tested Behavior (Unit/Benchmark Coverage) + +`branch_hashmap_test.go` verifies: + +- basic put/get/pop +- duplicate-key semantics and partial removal +- composite-key behavior +- spill and retrieval/removal correctness +- `ItemCount` in memory and spilled cases +- shard parallelism bound +- safe pop during `ForEachShardParallel` +- encoded-key and full-value deletion APIs +- schema/key consistency checks across multiple puts +- shard count clamp behavior +- project/migrate correctness and performance benchmarks + +## 13. Known Limitations + +- Spill lookup/removal uses bucket scan, so lookup latency may rise with large spill volume. +- Spill tombstones are not compacted automatically. +- `DecodeRow` currently returns tuple and error; the `[]types.Type` return value is not populated. diff --git a/pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md b/pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md deleted file mode 100644 index 1dbe662f9c780..0000000000000 --- a/pkg/frontend/databranchutils/BRANCH_HASHMAP_REDESIGN.md +++ /dev/null @@ -1,316 +0,0 @@ -# Branch Hashmap Redesign (Bucketized Spill, Streamed Iteration) - -## Layered Structure (At a Glance) - -``` -BranchHashmap - ├─ Shards[] (N shards) - │ ├─ InMemoryStore - │ │ ├─ HashIndex (open addressing) - │ │ ├─ EntryMeta[] (flat array) - │ │ └─ EntryArena (allocator-managed byte blocks) - │ ├─ SpillStore (bucketized on disk) - │ │ ├─ BucketFiles[B] - │ │ ├─ BucketRowCount[B] - │ │ └─ TombstoneBitmap[B] (lazy) - │ └─ BucketCache (optional, per-shard LRU) - ├─ Global config (spill, cache, shard count) - └─ Pools (packers, temp buffers) -``` - ---- - -## 1. Goals and Constraints - -### 1.1 Goals -- **I/O friendly spill**: sequential disk I/O instead of random `ReadAt` during traversal or batch operations. -- **Memory/GC friendly**: reduce per-entry pointer structures and demonstrating predictable heap usage. -- **Batch/diff optimized**: primary use is bulk comparison/diff; design should favor streaming and bucket locality. -- **Stable mapping**: once spilled, data is never re-hashed or rewritten, ensuring deterministic bucket mapping. -- **Interface compatibility**: keep `BranchHashmap` public interface unchanged; `ForEach` semantics may be revised. - -### 1.2 Constraints / Assumptions -- BranchHashmap is **write-once-ish**: after build, no full rebuild or rehash is required. -- Primary keys are often unique, but duplicates must still be supported. -- ForEach is mainly used by `data_branch` diff logic and can tolerate changes in grouping semantics. -- Spill is **append-only**; no in-place updates. -- Spill reads can be sequential; occasional random point lookups are acceptable but not the dominant path. - -### 1.3 Non-goals -- Full general-purpose OLTP index performance. -- Perfect efficiency for single-key random access when spill is large. -- Immediate compaction or tombstone reclamation (can be added later). - ---- - -## 2. Core Concepts and Terminology - -- **Shard**: independent unit with its own lock, memory store, spill store, cache, and counters. -- **Bucket**: fixed partition of spill files within a shard (`bucket = hash & (B-1)`), **not** the same as in-memory hash buckets. -- **Entry**: a single row (key + full value payload). -- **Rid**: record id in a bucket file (0-based, append order). -- **Tombstone**: deletion marker for spilled rows, stored as bitmap indexed by rid. - ---- - -## 3. Data Structures - -### 3.1 InMemoryStore - -**Goal**: compact and GC-friendly storage while preserving O(1) lookup. - -``` -EntryMeta { - hash uint64 - keyOff uint32/uint64 - keyLen uint32 - valOff uint32/uint64 - valLen uint32 -} - -HashIndex: open addressing array of int32 indexes -EntryArena: large allocator blocks holding concatenated key/value bytes -``` - -**Design choices** -- Open addressing avoids `map` overhead. -- EntryMeta is a flat array to minimize pointer chasing. -- Allocator blocks reduce GC pressure. - -### 3.2 SpillStore - -**Goal**: sequential I/O, predictable file count, minimal in-memory index. - -``` -BucketFiles[B] -BucketRowCount[B] -TombstoneBitmap[B] (optional, created on first delete) -``` - -**File format** (append-only): -``` -[hash(uint64)][keyLen(uint32)][valLen(uint32)][key bytes][value bytes] -``` - -### 3.3 BucketCache (optional) - -**Goal**: reduce repeated sequential scans for hot buckets. - -- Per-shard LRU cache. -- Stores `key -> rid` and optionally `rid -> value`. -- Bounded by configurable memory budget. - ---- - -## 4. State Model and Transitions - -### 4.1 High-level States -- **EMPTY**: shard has no entries. -- **IN_MEMORY**: entries stored in InMemoryStore only. -- **SPILLING**: InMemoryStore evicts entries into SpillStore. -- **SPILLED**: bucket files exist; tombstones may exist. - -### 4.2 State Transitions -1) `EMPTY -> IN_MEMORY`: PutByVectors inserts first entry. -2) `IN_MEMORY -> SPILLING`: allocator pressure triggers spill. -3) `SPILLING -> SPILLED`: spill completes; entries removed from memory. -4) `SPILLED -> SPILLING`: additional spill from memory to disk. -5) `* -> CLOSED`: Close releases memory, closes files, deletes spill dirs. - ---- - -## 5. Algorithms (Detailed) - -### 5.1 PutByVectors -**Input**: vectors + keyCols - -**Steps**: -1) Encode key/value for each row into batch. -2) Allocate one block for batch payloads. -3) Create EntryMeta and insert into shard InMemoryStore. -4) If allocator fails, invoke `spill(required)`. - -**Notes**: -- No spill rehashing; entries are moved to bucket files by hash. - -### 5.2 spill(required) -**Goal**: free `required` bytes from InMemoryStore. - -**Steps**: -1) For each shard, evict entries in LRU order. -2) For each entry: - - compute bucket: `hash & (B-1)` - - append to bucket file (sequential) - - increment BucketRowCount[bucket] -3) Remove entry from InMemoryStore. - -**Logging**: -- log required, freed, pointers/entries, avg entry size. - -### 5.3 ForEach (new semantics) -**Goal**: streaming iteration, low memory, bucket-local I/O. - -**Semantic change**: -- Previously: `fn(key, rows)` grouped by key. -- Now: `fn(key, rows)` is called **per entry** with `len(rows)==1`. - -**Order**: -1) **In-memory first**: iterate EntryMeta array; call fn with in-memory slices. -2) **Spill next**: for each bucket file in order: - - sequentially scan file - - maintain rid counter - - skip if tombstone bit is set - - call fn per entry - -**Copy policy**: -- In-memory: zero-copy slices into arena. -- Spill: one copy into scratch buffer; valid only during callback. - -### 5.4 GetByVectors / PopByVectors -**Goal**: batch-friendly, bucket-local access. - -**Steps**: -1) Encode keys. -2) Group keys by bucket (hash & (B-1)). -3) For each bucket: - - if bucket cached, use cache for lookups - - else sequentially scan bucket file, building temporary map - - for Pop: set tombstone bit for matching rid -4) Return results in input order. - -### 5.5 PopByEncodedKey / PopByEncodedKeyValue -**Goal**: correctness with acceptable cost. - -**Steps**: -1) Compute bucket by hash. -2) If bucket cached, lookup rid, set tombstone. -3) Otherwise, sequentially scan bucket file to find key/value. - -**Note**: This is slower than current index-based random access but fits diff/batch use. - ---- - -## 6. Tombstone Strategy - -**Why tombstone**: no file rewrite; stable rid. - -- **Structure**: per-bucket bitmap (`rid -> deleted?`). -- **Lazy allocation**: only allocate when first delete happens. -- **Memory**: 1 bit per record; 1e8 deletions ≈ 12.5MB total (plus metadata). - -**Optional**: Trigger compaction when tombstone ratio exceeds threshold. - ---- - -## 7. Concurrency Model - -- Shard lock serializes shard operations. -- ForEach requires shard lock; Pop during iteration must be called via ShardCursor. -- Parallelism comes from `ForEachShardParallel`. -- Cache is per-shard to avoid cross-shard contention and pollution. - ---- - -## 8. Failure and Recovery Behavior - -- Spill files are created under shard-specific spillDir. -- On error during spill, shard stays consistent; entries remain in memory if spill fails. -- On Close: close files, delete spillDir. -- No crash recovery required (spill files are temp). - ---- - -## 9. Configuration - -| Parameter | Description | Default | -|---|---|---| -| `shardCount` | number of shards | `clamp(runtime.NumCPU()*4,4,128)` | -| `bucketCount` | spill buckets per shard (power of 2) | 128 or 256 | -| `spillPartitionMaxBytes` | max bucket file size (optional) | 128MB | -| `cacheBytesPerShard` | bucket cache budget | 64MB | -| `spillMinReleaseBytes` | minimum spill size | 1MB | - ---- - -## 10. Large-Scale Considerations (10TB+) - -To support tens of TB scale, the baseline design must add **segmented bucket files** and use **64-bit offsets** end-to-end. Without these, bucket files become too large, offsets overflow, and tombstone bitmaps balloon uncontrollably. - -### 10.1 Bucket Segmentation -- Each bucket is split into **fixed-size segments** (e.g. 1–4GB). -- Spill appends to the current segment; when full, rotates to the next. -- Maintain `BucketSegments[bucket] -> []SegmentMeta` including: - - `path` - - `rowCount` - - `byteSize` - - `minRid` / `maxRid` - -### 10.2 64-bit Offsets and RIDs -- Use `uint64` for all offsets and record counters. -- Record id becomes `rid = segmentBaseRid + localRid`. -- Hash index remains 32-bit if entry count < 2^31; otherwise, upgrade to 64-bit indexes. - -### 10.3 Tombstone Scaling -- Tombstones are **per-segment bitmaps**, not per-bucket monolithic bitmaps. -- This enables: - - small, cache-friendly bitmaps - - partial cleanup or compaction per segment -- With 10B rows fully deleted, bitmap memory remains in the low GB range and can be partitioned per segment. - -### 10.4 Cache Boundaries -- Strict per-shard cache limits (e.g. 64–128MB/shard). -- Eviction should drop segment caches cleanly to avoid page cache thrash. - -### 10.5 File Descriptor Strategy -- Never keep all bucket/segment files open. -- Maintain a per-shard FD LRU (1–4 active segment files). - -### 10.6 Suggested Defaults for 10TB -- `shardCount`: 64–128 -- `bucketCount`: 512–1024 -- `segmentSize`: 1GB -- `cacheBytesPerShard`: 64–128MB -- `spillMinReleaseBytes`: 8–64MB - ---- - -## 11. Behavioral Differences vs Current Implementation - -- ForEach is **streaming per entry** (no grouped rows). -- Spill uses **bucket files** rather than per-entry index. -- Random Get/Pop on spilled data is slower; batch operations are faster. -- Tombstones replace delete-in-file. - ---- - -## 12. Testing Strategy - -- **Correctness**: Put/Get/Pop with unique and duplicate keys. -- **Streaming**: ForEach returns all rows; order not guaranteed but count is. -- **Spill**: data survives spill; tombstone hides deleted rows. -- **Batch**: GetByVectors with mixed buckets. -- **Cache**: repeated gets hit cache; cache evictions do not corrupt data. -- **Concurrency**: ForEachShardParallel with mixed Pop calls. - ---- - -## 13. Implementation Checklist - -1) Add bucket spill store structures. -2) Update spill path to write bucket files sequentially. -3) Implement tombstone bitmap per bucket. -4) Update ForEach to stream entries (in-memory then spill buckets). -5) Update Get/Pop to bucket-grouped access. -6) Update tests for new ForEach semantics. -7) Update design docs and comments. - ---- - -## 14. Rationale Summary - -- **Bucketized spill** enables sequential I/O and avoids giant per-entry indexes. -- **Streaming ForEach** avoids full-map grouping and reduces memory spikes. -- **Tombstone bitmap** provides low-memory deletion marking for spilled rows. -- **Per-shard cache** prevents cross-shard cache pollution under concurrency. - -This design optimizes for the dominant workload (bulk diff) while maintaining correctness and concurrency safety. Even with changed ForEach semantics, the interface surface remains compatible and existing callers can be updated with minimal logic changes. diff --git a/pkg/vm/engine/disttae/local_disttae_datasource.go b/pkg/vm/engine/disttae/local_disttae_datasource.go index f16f06e815450..35fb3f6403a08 100644 --- a/pkg/vm/engine/disttae/local_disttae_datasource.go +++ b/pkg/vm/engine/disttae/local_disttae_datasource.go @@ -155,15 +155,6 @@ func (ls *LocalDisttaeDataSource) String() string { blks) } -func (ls *LocalDisttaeDataSource) GetObjectCreateTS( - bid *objectio.Blockid, -) (types.TS, bool) { - if ls == nil || ls.pState == nil || bid == nil { - return types.TS{}, false - } - return ls.pState.GetDataObjectCreateTS(bid.Object()) -} - func (ls *LocalDisttaeDataSource) SetOrderBy(orderby []*plan.OrderBySpec) { ls.OrderBy = orderby } diff --git a/pkg/vm/engine/disttae/logtailreplay/partition_state.go b/pkg/vm/engine/disttae/logtailreplay/partition_state.go index 65b786cdbf2d8..e5a41490e109d 100644 --- a/pkg/vm/engine/disttae/logtailreplay/partition_state.go +++ b/pkg/vm/engine/disttae/logtailreplay/partition_state.go @@ -1588,19 +1588,6 @@ func (p *PartitionState) IsDataObjectVisible(objId *types.Objectid, snapshot typ return false } -// GetDataObjectCreateTS returns the create timestamp of a persisted data object. -func (p *PartitionState) GetDataObjectCreateTS(objID *types.Objectid) (types.TS, bool) { - var stats objectio.ObjectStats - objectio.SetObjectStatsObjectName(&stats, objectio.BuildObjectNameWithObjectID(objID)) - - entry := objectio.ObjectEntry{ObjectStats: stats} - if obj, exists := p.dataObjectsNameIndex.Get(entry); exists { - return obj.CreateTime, true - } - - return types.TS{}, false -} - // countTombstoneStatsLinear uses linear deduplication for single object // Single object is already sorted, no cross-object duplicates possible func (p *PartitionState) countTombstoneStatsLinear( From b27b41af8d5d7ce5db21c7b7f3f6fd28511882fe Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 2 Mar 2026 13:07:13 +0800 Subject: [PATCH 15/23] chore: remove temporary AAAA debug logs --- pkg/frontend/data_branch.go | 9 --------- pkg/objectio/funcs.go | 13 ------------- pkg/vm/engine/disttae/local_disttae_datasource.go | 11 ----------- 3 files changed, 33 deletions(-) diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 3f7eb57db40db..1b3480c122c24 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -42,7 +42,6 @@ import ( plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" "github.com/matrixorigin/matrixone/pkg/util/executor" "github.com/matrixorigin/matrixone/pkg/vm/engine" - "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" "github.com/panjf2000/ants/v2" ) @@ -1479,9 +1478,6 @@ func getTablesCreationCommitTS( continue } - fmt.Printf("AAAA tableId=%d, bat=%s\n", - tableID, common.MoBatchToString(readBatch, readBatch.RowCount())) - relIDs := vector.MustFixedColWithTypeCheck[uint64](readBatch.Vecs[0]) commitCol := vector.MustFixedColWithTypeCheck[types.TS](readBatch.Vecs[1]) for i := range relIDs { @@ -1494,11 +1490,6 @@ func getTablesCreationCommitTS( commitTS = commitCol[i] } commitFound = true - fmt.Printf("AAAA tableId=%d row=%d commit=%s\n", - tableID, i, commitCol[i].ToString()) - } else { - fmt.Printf("AAAA tableId=%d row=%d commit=NULL\n", - tableID, i) } } } diff --git a/pkg/objectio/funcs.go b/pkg/objectio/funcs.go index 2eb0aa0b8bd98..f100c33a2ec03 100644 --- a/pkg/objectio/funcs.go +++ b/pkg/objectio/funcs.go @@ -160,7 +160,6 @@ func ReadOneBlockWithMeta( blkmeta := meta.GetBlockMeta(uint32(blk)) maxSeqnum := blkmeta.GetMaxSeqnum() for i, seqnum := range seqnums { - reqSeqnum := seqnum // special columns if seqnum >= SEQNUM_UPPER { metaColCnt := blkmeta.GetMetaColumnCount() @@ -177,18 +176,6 @@ func ReadOneBlockWithMeta( // 2. old version tn nonappendable block col := blkmeta.ColumnMeta(seqnum) if col.DataType() != uint8(types.T_TS) { - if reqSeqnum == SEQNUM_COMMITTS { - logutil.Infof( - "AAAA objectio commit placeholder: file=%s blk=%d reqSeq=%d mappedSeq=%d metaColCnt=%d dtype=%d rows=%d", - name, - blk, - reqSeqnum, - seqnum, - metaColCnt, - col.DataType(), - blkmeta.GetRows(), - ) - } putFillHolder(i, seqnum) } else { ext := col.Location() diff --git a/pkg/vm/engine/disttae/local_disttae_datasource.go b/pkg/vm/engine/disttae/local_disttae_datasource.go index 35fb3f6403a08..941b477de2da0 100644 --- a/pkg/vm/engine/disttae/local_disttae_datasource.go +++ b/pkg/vm/engine/disttae/local_disttae_datasource.go @@ -862,17 +862,6 @@ func (ls *LocalDisttaeDataSource) filterInMemCommittedInserts( if int(idx) >= len(entry.Batch.Vecs) /*add column*/ || entry.Batch.Attrs[idx] == "" /*drop column*/ { - if seqNums[i] == objectio.SEQNUM_COMMITTS { - logutil.Infof( - "AAAA inmem commit missing: tableId=%d idx=%d vecs=%d attrs=%d rowOffset=%d rowTime=%s", - ls.table.tableId, - idx, - len(entry.Batch.Vecs), - len(entry.Batch.Attrs), - entry.Offset, - entry.Time.ToString(), - ) - } err = vector.AppendAny( outBatch.Vecs[i], nil, From e6260e7adc74e918ced1efbec2c7e42b07cf6f4f Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 2 Mar 2026 15:56:00 +0800 Subject: [PATCH 16/23] test: raise coverage for data branch and hashmap paths --- .../rscthrottler/resource_throttler_test.go | 39 ++ pkg/frontend/data_branch_output_test.go | 363 ++++++++++++++++++ .../databranchutils/branch_hashmap.go | 9 +- .../databranchutils/branch_hashmap_test.go | 216 +++++++++++ .../engine/disttae/txn_table_sharding_test.go | 38 ++ 5 files changed, 657 insertions(+), 8 deletions(-) create mode 100644 pkg/frontend/data_branch_output_test.go diff --git a/pkg/common/rscthrottler/resource_throttler_test.go b/pkg/common/rscthrottler/resource_throttler_test.go index 9c9e1881537c5..f019f429f74b0 100644 --- a/pkg/common/rscthrottler/resource_throttler_test.go +++ b/pkg/common/rscthrottler/resource_throttler_test.go @@ -130,3 +130,42 @@ func BenchmarkThrottler(b *testing.B) { throttler.Available() } } + +func TestAcquirePolicyForDataBranch(t *testing.T) { + t.Run("deny when projected usage exceeds rate limit", func(t *testing.T) { + throttler := &memThrottler{limitRate: 0.80} + throttler.actualTotalMemory.Store(100) + throttler.limit.Store(80) + throttler.rss.Store(70) + throttler.reserved.Store(5) + + left, ok := AcquirePolicyForDataBranch(throttler, 11) + require.False(t, ok) + require.Equal(t, int64(0), left) + require.Equal(t, int64(5), throttler.reserved.Load()) + }) + + t.Run("allow at boundary and reserve memory", func(t *testing.T) { + throttler := &memThrottler{limitRate: 0.80} + throttler.actualTotalMemory.Store(100) + throttler.limit.Store(80) + throttler.rss.Store(70) + + left, ok := AcquirePolicyForDataBranch(throttler, 10) + require.True(t, ok) + require.Equal(t, int64(20), left) + require.Equal(t, int64(10), throttler.reserved.Load()) + }) + + t.Run("fallback to default policy when rate check is disabled", func(t *testing.T) { + throttler := &memThrottler{limitRate: 0} + throttler.actualTotalMemory.Store(100) + throttler.limit.Store(80) + throttler.rss.Store(20) + + left, ok := AcquirePolicyForDataBranch(throttler, 10) + require.True(t, ok) + require.Equal(t, int64(70), left) + require.Equal(t, int64(10), throttler.reserved.Load()) + }) +} diff --git a/pkg/frontend/data_branch_output_test.go b/pkg/frontend/data_branch_output_test.go new file mode 100644 index 0000000000000..c7477bfd23119 --- /dev/null +++ b/pkg/frontend/data_branch_output_test.go @@ -0,0 +1,363 @@ +// Copyright 2025 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "bytes" + "context" + "regexp" + "strings" + "testing" + + "github.com/golang/mock/gomock" + "github.com/matrixorigin/matrixone/pkg/container/types" + mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" + "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/stretchr/testify/require" +) + +func TestDataBranchOutputConfigAndQualifiedTableName(t *testing.T) { + cfg := newDiffCSVUserConfig() + require.NotNil(t, cfg) + require.True(t, cfg.Outfile) + require.NotNil(t, cfg.Fields) + require.NotNil(t, cfg.Lines) + require.Equal(t, tree.DefaultFieldsTerminated, cfg.Fields.Terminated.Value) + require.Equal(t, tree.DefaultFieldsEnclosedBy[0], cfg.Fields.EnclosedBy.Value) + require.Equal(t, tree.DefaultFieldsEscapedBy[0], cfg.Fields.EscapedBy.Value) + require.Equal(t, "\n", cfg.Lines.TerminatedBy.Value) + require.False(t, cfg.Header) + + require.Equal(t, "db.t", qualifiedTableName("db", "t")) +} + +func TestDataBranchOutputMakeFileName(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + baseRel := mock_frontend.NewMockRelation(ctrl) + tarRel := mock_frontend.NewMockRelation(ctrl) + baseRel.EXPECT().GetTableName().Return("t1").AnyTimes() + tarRel.EXPECT().GetTableName().Return("t2").AnyTimes() + + tblStuff := tableStuff{ + baseRel: baseRel, + tarRel: tarRel, + } + + got := makeFileName(nil, nil, tblStuff) + require.Regexp(t, regexp.MustCompile(`^diff_t2_t1_\d{8}_\d{6}$`), got) + + got = makeFileName( + &tree.AtTimeStamp{SnapshotName: "sp1"}, + &tree.AtTimeStamp{SnapshotName: "sp2"}, + tblStuff, + ) + require.Regexp(t, regexp.MustCompile(`^diff_t2_sp2_t1_sp1_\d{8}_\d{6}$`), got) +} + +func TestDataBranchOutputWriteRowValues(t *testing.T) { + tblStuff := tableStuff{} + tblStuff.def.colNames = []string{"id", "name"} + tblStuff.def.colTypes = []types.Type{types.T_int64.ToType(), types.T_varchar.ToType()} + tblStuff.def.visibleIdxes = []int{0, 1} + tblStuff.def.pkColIdxes = []int{0} + tblStuff.def.pkColIdx = 0 + + row := []any{int64(7), "alice"} + + insertBuf := &bytes.Buffer{} + require.NoError(t, writeInsertRowValues(nil, tblStuff, row, insertBuf)) + require.Equal(t, "(7,'alice')", insertBuf.String()) + + deleteBuf := &bytes.Buffer{} + require.NoError(t, writeDeleteRowValues(nil, tblStuff, row, deleteBuf)) + require.Equal(t, "7", deleteBuf.String()) + + tblStuff.def.pkColIdxes = []int{0, 1} + deleteTupleBuf := &bytes.Buffer{} + require.NoError(t, writeDeleteRowValues(nil, tblStuff, row, deleteTupleBuf)) + require.Equal(t, "(7,'alice')", deleteTupleBuf.String()) + + alwaysTupleBuf := &bytes.Buffer{} + require.NoError(t, writeDeleteRowValuesAsTuple(nil, tblStuff, row, alwaysTupleBuf)) + require.Equal(t, "(7,'alice')", alwaysTupleBuf.String()) +} + +func TestDataBranchOutputWriteDeleteRowSQLFull(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + baseRel := mock_frontend.NewMockRelation(ctrl) + baseRel.EXPECT().GetTableDef(gomock.Any()).Return(&plan.TableDef{ + DbName: "db1", + Name: "t1", + }).AnyTimes() + + tblStuff := tableStuff{ + baseRel: baseRel, + } + tblStuff.def.colNames = []string{"id", "name"} + tblStuff.def.colTypes = []types.Type{types.T_int64.ToType(), types.T_varchar.ToType()} + tblStuff.def.visibleIdxes = []int{0, 1} + + row := []any{int64(9), nil} + buf := &bytes.Buffer{} + require.NoError(t, writeDeleteRowSQLFull(context.Background(), nil, tblStuff, row, buf)) + require.Equal(t, "delete from db1.t1 where id = 9 and name is null limit 1;\n", buf.String()) +} + +func TestDataBranchOutputExecSQLStatementsWithWriteFile(t *testing.T) { + var out bytes.Buffer + writeFile := func(b []byte) error { + _, err := out.Write(b) + return err + } + + err := execSQLStatements( + context.Background(), + nil, + nil, + writeFile, + []string{"select 1", "", "insert into t values (1)"}, + ) + require.NoError(t, err) + require.Equal(t, "select 1;\ninsert into t values (1);\n", out.String()) +} + +func TestDataBranchOutputInitAndDropPKTablesWithWriteFile(t *testing.T) { + pkInfo := &pkBatchInfo{ + dbName: "db1", + baseTable: "base_t", + deleteTable: "__mo_diff_del_x", + insertTable: "__mo_diff_ins_x", + pkNames: []string{"id"}, + visibleNames: []string{"id", "name"}, + } + + var out bytes.Buffer + writeFile := func(b []byte) error { + _, err := out.Write(b) + return err + } + + require.NoError(t, initPKTables(context.Background(), nil, nil, pkInfo, writeFile)) + require.NoError(t, dropPKTables(context.Background(), nil, nil, pkInfo, writeFile)) + + got := out.String() + require.Contains(t, got, "drop table if exists db1.__mo_diff_del_x;\n") + require.Contains(t, got, "drop table if exists db1.__mo_diff_ins_x;\n") + require.Contains(t, got, "create table db1.__mo_diff_del_x as select id from db1.base_t where 1=0;\n") + require.Contains(t, got, "create table db1.__mo_diff_ins_x as select id,name from db1.base_t where 1=0;\n") +} + +func TestDataBranchOutputFlushSqlValuesWithWriteFile(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + baseRel := mock_frontend.NewMockRelation(ctrl) + baseRel.EXPECT().GetTableDef(gomock.Any()).Return(&plan.TableDef{ + DbName: "db1", + Name: "t1", + }).AnyTimes() + + tblStuff := tableStuff{ + baseRel: baseRel, + } + tblStuff.def.colNames = []string{"id", "name"} + tblStuff.def.pkColIdx = 0 + tblStuff.def.pkColIdxes = []int{0, 1} + + pkInfo := &pkBatchInfo{ + dbName: "db1", + baseTable: "t1", + deleteTable: "__mo_diff_del_x", + insertTable: "__mo_diff_ins_x", + pkNames: []string{"id", "name"}, + visibleNames: []string{"id", "name"}, + } + + var out bytes.Buffer + writeFile := func(b []byte) error { + _, err := out.Write(b) + return err + } + + require.NoError(t, flushSqlValues( + context.Background(), + nil, + nil, + tblStuff, + bytes.NewBufferString("delete from db1.t1 where id = 1 limit 1;\n"), + true, + true, + nil, + writeFile, + )) + + require.NoError(t, flushSqlValues( + context.Background(), + nil, + nil, + tblStuff, + bytes.NewBufferString("(1,'a')"), + true, + false, + pkInfo, + writeFile, + )) + + require.NoError(t, flushSqlValues( + context.Background(), + nil, + nil, + tblStuff, + bytes.NewBufferString("(2,'b')"), + false, + false, + nil, + writeFile, + )) + + got := out.String() + require.Contains(t, got, "delete from db1.t1 where id = 1 limit 1;\n") + require.Contains(t, got, "insert into db1.__mo_diff_del_x values (1,'a');\n") + require.Contains(t, got, "delete from db1.t1 where (id,name) in (select id,name from db1.__mo_diff_del_x);\n") + require.Contains(t, got, "insert into db1.t1 values (2,'b');\n") +} + +func TestDataBranchOutputTryFlushDeletesOrInserts(t *testing.T) { + pkInfo := &pkBatchInfo{ + dbName: "db1", + baseTable: "t1", + deleteTable: "__mo_diff_del_x", + insertTable: "__mo_diff_ins_x", + pkNames: []string{"id"}, + visibleNames: []string{"id", "name"}, + } + + t.Run("force flush both buffers", func(t *testing.T) { + var out bytes.Buffer + writeFile := func(b []byte) error { + _, err := out.Write(b) + return err + } + + deleteCnt := 1 + insertCnt := 1 + deleteBuf := bytes.NewBufferString("(1)") + insertBuf := bytes.NewBufferString("(1,'a')") + + err := tryFlushDeletesOrInserts( + context.Background(), + nil, + nil, + tableStuff{}, + "", + 0, + 0, + false, + pkInfo, + &deleteCnt, + deleteBuf, + &insertCnt, + insertBuf, + writeFile, + ) + require.NoError(t, err) + require.Equal(t, 0, deleteCnt) + require.Equal(t, 0, insertCnt) + require.Equal(t, 0, deleteBuf.Len()) + require.Equal(t, 0, insertBuf.Len()) + require.Contains(t, out.String(), "delete from db1.t1 where id in (select id from db1.__mo_diff_del_x);\n") + require.Contains(t, out.String(), "insert into db1.t1 (id,name) select id,name from db1.__mo_diff_ins_x;\n") + }) + + t.Run("do nothing when thresholds are not reached", func(t *testing.T) { + var called int + writeFile := func([]byte) error { + called++ + return nil + } + + deleteCnt := 0 + insertCnt := 0 + deleteBuf := &bytes.Buffer{} + insertBuf := &bytes.Buffer{} + + err := tryFlushDeletesOrInserts( + context.Background(), + nil, + nil, + tableStuff{}, + diffDelete, + 1, + 1, + false, + pkInfo, + &deleteCnt, + deleteBuf, + &insertCnt, + insertBuf, + writeFile, + ) + require.NoError(t, err) + require.Equal(t, 0, called) + }) + + t.Run("flush delete before insert on insert threshold", func(t *testing.T) { + var out bytes.Buffer + writeFile := func(b []byte) error { + _, err := out.Write(b) + return err + } + + deleteCnt := 1 + insertCnt := maxSqlBatchCnt - 1 + deleteBuf := bytes.NewBufferString("(7)") + insertBuf := bytes.NewBufferString("(8,'x')") + + err := tryFlushDeletesOrInserts( + context.Background(), + nil, + nil, + tableStuff{}, + diffInsert, + 1, + 1, + false, + pkInfo, + &deleteCnt, + deleteBuf, + &insertCnt, + insertBuf, + writeFile, + ) + require.NoError(t, err) + + got := out.String() + deletePos := strings.Index(got, "insert into db1.__mo_diff_del_x") + insertPos := strings.Index(got, "insert into db1.__mo_diff_ins_x") + require.NotEqual(t, -1, deletePos) + require.NotEqual(t, -1, insertPos) + require.Less(t, deletePos, insertPos) + }) +} + +func TestDataBranchOutputNewSingleWriteAppenderNilWorker(t *testing.T) { + _, _, err := newSingleWriteAppender(context.Background(), nil, nil, "unused", nil) + require.Error(t, err) +} diff --git a/pkg/frontend/databranchutils/branch_hashmap.go b/pkg/frontend/databranchutils/branch_hashmap.go index 1f27a22cc3ff3..aaeefc53ed97c 100644 --- a/pkg/frontend/databranchutils/branch_hashmap.go +++ b/pkg/frontend/databranchutils/branch_hashmap.go @@ -1437,7 +1437,7 @@ func (hs *hashShard) close() error { hs.memInUse = 0 if hs.spill != nil { - if err := hs.spill.close(); err != nil && firstErr == nil { + if err := hs.spill.close(); err != nil { firstErr = err } hs.spill = nil @@ -2001,13 +2001,6 @@ func newMemStore() *memStore { } } -func (ms *memStore) len() int { - if ms == nil { - return 0 - } - return ms.count -} - func (ms *memStore) ensureCapacity(additional int) { if ms.index == nil { ms.init(defaultMemIndexSize) diff --git a/pkg/frontend/databranchutils/branch_hashmap_test.go b/pkg/frontend/databranchutils/branch_hashmap_test.go index c6e132d54d1e0..7e0e550dc290d 100644 --- a/pkg/frontend/databranchutils/branch_hashmap_test.go +++ b/pkg/frontend/databranchutils/branch_hashmap_test.go @@ -1047,6 +1047,156 @@ func TestBranchHashmapPopByEncodedKeyValue(t *testing.T) { } } +func TestBranchHashmapPopByVectorsStreamInMemory(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + keyVec := buildInt64Vector(t, mp, []int64{1, 1, 2}) + valVec := buildStringVector(t, mp, []string{"one", "uno", "two"}) + defer keyVec.Free(mp) + defer valVec.Free(mp) + + bh, err := NewBranchHashmap() + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + + require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) + + probe := buildInt64Vector(t, mp, []int64{1, 2}) + defer probe.Free(mp) + + var ( + callbackCount int + removedByIdx = map[int]int{} + ) + removed, err := bh.PopByVectorsStream([]*vector.Vector{probe}, true, func(idx int, key []byte, row []byte) error { + callbackCount++ + removedByIdx[idx]++ + require.NotEmpty(t, key) + require.NotEmpty(t, row) + return nil + }) + require.NoError(t, err) + require.Equal(t, 3, removed) + require.Equal(t, 3, callbackCount) + require.Equal(t, 2, removedByIdx[0]) + require.Equal(t, 1, removedByIdx[1]) + + after, err := bh.GetByVectors([]*vector.Vector{probe}) + require.NoError(t, err) + require.False(t, after[0].Exists) + require.False(t, after[1].Exists) +} + +func TestBranchHashmapPopByVectorsStreamSpilled(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + allocator := newLimitedAllocator(80) + bh, err := NewBranchHashmap( + WithBranchHashmapAllocator(allocator), + WithBranchHashmapSpillRoot(t.TempDir()), + ) + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + + key := buildInt64Vector(t, mp, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + value := buildStringVector(t, mp, []string{"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}) + defer key.Free(mp) + defer value.Free(mp) + + require.NoError(t, bh.PutByVectors([]*vector.Vector{key, value}, []int{0})) + + probe := buildInt64Vector(t, mp, []int64{9, 10}) + defer probe.Free(mp) + + var callbackCount int + removed, err := bh.PopByVectorsStream([]*vector.Vector{probe}, true, func(_ int, key []byte, row []byte) error { + callbackCount++ + require.NotEmpty(t, key) + require.NotEmpty(t, row) + return nil + }) + require.NoError(t, err) + require.Equal(t, 2, removed) + require.Equal(t, 2, callbackCount) + + after, err := bh.GetByVectors([]*vector.Vector{probe}) + require.NoError(t, err) + require.False(t, after[0].Exists) + require.False(t, after[1].Exists) +} + +func TestBranchHashmapCursorGetAndPopByEncodedValueDuringIteration(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + keyVec := buildInt64Vector(t, mp, []int64{1, 1}) + valVec := buildStringVector(t, mp, []string{"one", "uno"}) + defer keyVec.Free(mp) + defer valVec.Free(mp) + + bh, err := NewBranchHashmap() + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) + + var popped bool + err = bh.ForEachShardParallel(func(cursor ShardCursor) error { + require.GreaterOrEqual(t, cursor.ShardID(), 0) + if popped { + return nil + } + return cursor.ForEach(func(key []byte, row []byte) error { + if popped { + return nil + } + keyCopy := append([]byte(nil), key...) + rowCopy := append([]byte(nil), row...) + + got, err := cursor.GetByEncodedKey(keyCopy) + require.NoError(t, err) + require.True(t, got.Exists) + require.Len(t, got.Rows, 2) + + removed, err := cursor.PopByEncodedKeyValue(keyCopy, rowCopy, false) + require.NoError(t, err) + require.Equal(t, 1, removed) + popped = true + return nil + }) + }, 1) + require.NoError(t, err) + require.True(t, popped) + + probe := buildInt64Vector(t, mp, []int64{1}) + defer probe.Free(mp) + results, err := bh.GetByVectors([]*vector.Vector{probe}) + require.NoError(t, err) + require.True(t, results[0].Exists) + require.Len(t, results[0].Rows, 1) +} + +func TestBranchHashmapCursorNilMethods(t *testing.T) { + var cursor *shardCursor + require.Equal(t, -1, cursor.ShardID()) + + got, err := cursor.GetByEncodedKey([]byte("k")) + require.NoError(t, err) + require.False(t, got.Exists) + require.Empty(t, got.Rows) + + removed, err := cursor.PopByEncodedKeyValue([]byte("k"), []byte("v"), true) + require.NoError(t, err) + require.Equal(t, 0, removed) +} + func TestBranchHashmapPopByEncodedFullValueExact(t *testing.T) { mp := mpool.MustNewZero() defer mpool.DeleteMPool(mp) @@ -1228,6 +1378,72 @@ func TestBranchHashmapShardCountClamp(t *testing.T) { require.Equal(t, maxShardCount, bhHigh.(*branchHashmap).shardCount) } +func TestBranchHashmapShardCountMethod(t *testing.T) { + bh, err := NewBranchHashmap(WithBranchHashmapShardCount(4)) + require.NoError(t, err) + + require.Equal(t, 4, bh.ShardCount()) + require.NoError(t, bh.Close()) + require.Equal(t, 0, bh.ShardCount()) +} + +func TestBranchHashmapRehashSingleShard(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + const rowCnt = 900 + keys := make([]int64, rowCnt) + values := make([]string, rowCnt) + for i := 0; i < rowCnt; i++ { + keys[i] = int64(i) + values[i] = fmt.Sprintf("v%d", i) + } + + keyVec := buildInt64Vector(t, mp, keys) + valVec := buildStringVector(t, mp, values) + defer keyVec.Free(mp) + defer valVec.Free(mp) + + bh, err := NewBranchHashmap(WithBranchHashmapShardCount(1)) + require.NoError(t, err) + defer func() { + require.NoError(t, bh.Close()) + }() + + require.NoError(t, bh.PutByVectors([]*vector.Vector{keyVec, valVec}, []int{0})) + require.Equal(t, int64(rowCnt), bh.ItemCount()) + + probe := buildInt64Vector(t, mp, []int64{0, 450, 899}) + defer probe.Free(mp) + + got, err := bh.GetByVectors([]*vector.Vector{probe}) + require.NoError(t, err) + require.Len(t, got, 3) + for _, res := range got { + require.True(t, res.Exists) + require.Len(t, res.Rows, 1) + } +} + +func TestMemStoreRehash(t *testing.T) { + ms := newMemStore() + ms.init(8) + + for i := 0; i < 8; i++ { + ms.insert(memEntry{ + hash: uint64(i + 1), + keyLen: 1, + valLen: 1, + }) + } + + oldCap := len(ms.index) + ms.rehash(oldCap * 2) + require.Greater(t, len(ms.index), oldCap) + require.Equal(t, 8, ms.count) + require.Equal(t, 0, ms.tombstones) +} + func TestEncodeRowCoversManyTypes(t *testing.T) { mp := mpool.MustNewZero() defer mpool.DeleteMPool(mp) diff --git a/pkg/vm/engine/disttae/txn_table_sharding_test.go b/pkg/vm/engine/disttae/txn_table_sharding_test.go index a049c5a4d7d13..687d7b0c7a493 100644 --- a/pkg/vm/engine/disttae/txn_table_sharding_test.go +++ b/pkg/vm/engine/disttae/txn_table_sharding_test.go @@ -16,9 +16,13 @@ package disttae import ( "context" + "strings" "testing" "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/objectio" + "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/vm/engine" "github.com/stretchr/testify/require" ) @@ -108,3 +112,37 @@ func runIsLocalErrTests( fn(tbl) } + +func TestShardingRemoteReaderUpdateCols(t *testing.T) { + reader := &shardingRemoteReader{} + tblDef := &plan.TableDef{ + Name2ColIndex: map[string]int32{ + "a": 0, + }, + Cols: []*plan.ColDef{ + { + Name: "a", + Typ: plan.Type{ + Id: int32(types.T_int64), + Width: 20, + Scale: 0, + }, + }, + }, + } + + cols := []string{ + "a", + strings.ToUpper(objectio.DefaultCommitTS_Attr), + objectio.PhysicalAddr_Attr, + } + reader.updateCols(cols, tblDef) + require.Len(t, reader.colTypes, len(cols)) + require.Equal(t, types.T_int64, reader.colTypes[0].Oid) + require.Equal(t, types.T_TS, reader.colTypes[1].Oid) + require.Equal(t, objectio.RowidType, reader.colTypes[2]) + + original := append([]types.Type(nil), reader.colTypes...) + reader.updateCols([]string{"unknown_col"}, &plan.TableDef{}) + require.Equal(t, original, reader.colTypes) +} From 2488c2360a654321bb74f9ea182cced481dd5f2a Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Tue, 3 Mar 2026 10:07:44 +0800 Subject: [PATCH 17/23] test: improve data_branch_output coverage --- pkg/frontend/data_branch_output_test.go | 118 ++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/pkg/frontend/data_branch_output_test.go b/pkg/frontend/data_branch_output_test.go index c7477bfd23119..d5d66a41325d7 100644 --- a/pkg/frontend/data_branch_output_test.go +++ b/pkg/frontend/data_branch_output_test.go @@ -357,6 +357,124 @@ func TestDataBranchOutputTryFlushDeletesOrInserts(t *testing.T) { }) } +func TestDataBranchOutputNewPKBatchInfo(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + baseRel := mock_frontend.NewMockRelation(ctrl) + baseRel.EXPECT().GetTableDef(gomock.Any()).Return(&plan.TableDef{ + DbName: "db1", + Name: "t1", + }).AnyTimes() + baseRel.EXPECT().GetTableName().Return("t1").AnyTimes() + + tblStuff := tableStuff{ + baseRel: baseRel, + } + tblStuff.def.colNames = []string{"id", "name", "age"} + tblStuff.def.pkColIdxes = []int{0, 2} + tblStuff.def.visibleIdxes = []int{0, 1, 2} + tblStuff.def.pkKind = normalKind + + info := newPKBatchInfo(context.Background(), &Session{}, tblStuff) + require.NotNil(t, info) + require.Equal(t, "db1", info.dbName) + require.Equal(t, "t1", info.baseTable) + require.Equal(t, []string{"id", "age"}, info.pkNames) + require.Equal(t, []string{"id", "name", "age"}, info.visibleNames) + require.True(t, strings.HasPrefix(info.deleteTable, "__mo_diff_del_")) + require.True(t, strings.HasPrefix(info.insertTable, "__mo_diff_ins_")) + + tblStuff.def.pkKind = fakeKind + require.Nil(t, newPKBatchInfo(context.Background(), &Session{}, tblStuff)) +} + +func TestDataBranchOutputAppenderAppendRowAndFlushAll(t *testing.T) { + pkInfo := &pkBatchInfo{ + dbName: "db1", + baseTable: "t1", + deleteTable: "__mo_diff_del_x", + insertTable: "__mo_diff_ins_x", + pkNames: []string{"id"}, + visibleNames: []string{"id", "name"}, + } + + t.Run("append delete in full-row mode", func(t *testing.T) { + deleteCnt := 0 + insertCnt := 0 + deleteBuf := &bytes.Buffer{} + insertBuf := &bytes.Buffer{} + + appender := sqlValuesAppender{ + ctx: context.Background(), + deleteByFullRow: true, + pkInfo: pkInfo, + deleteCnt: &deleteCnt, + deleteBuf: deleteBuf, + insertCnt: &insertCnt, + insertBuf: insertBuf, + } + + err := appender.appendRow(diffDelete, []byte("delete from db1.t1 where id = 1 limit 1;\n")) + require.NoError(t, err) + require.Equal(t, 1, deleteCnt) + require.Equal(t, "delete from db1.t1 where id = 1 limit 1;\n", deleteBuf.String()) + }) + + t.Run("append insert with comma", func(t *testing.T) { + deleteCnt := 0 + insertCnt := 1 + deleteBuf := &bytes.Buffer{} + insertBuf := bytes.NewBufferString("(1,'a')") + + appender := sqlValuesAppender{ + ctx: context.Background(), + deleteByFullRow: false, + pkInfo: pkInfo, + deleteCnt: &deleteCnt, + deleteBuf: deleteBuf, + insertCnt: &insertCnt, + insertBuf: insertBuf, + } + + err := appender.appendRow(diffInsert, []byte("(2,'b')")) + require.NoError(t, err) + require.Equal(t, 2, insertCnt) + require.Equal(t, "(1,'a'),(2,'b')", insertBuf.String()) + }) + + t.Run("flush all buffers", func(t *testing.T) { + var out bytes.Buffer + writeFile := func(b []byte) error { + _, err := out.Write(b) + return err + } + + deleteCnt := 1 + insertCnt := 1 + deleteBuf := bytes.NewBufferString("(1)") + insertBuf := bytes.NewBufferString("(1,'a')") + appender := sqlValuesAppender{ + ctx: context.Background(), + deleteByFullRow: false, + pkInfo: pkInfo, + deleteCnt: &deleteCnt, + deleteBuf: deleteBuf, + insertCnt: &insertCnt, + insertBuf: insertBuf, + writeFile: writeFile, + } + + require.NoError(t, appender.flushAll()) + require.Equal(t, 0, deleteCnt) + require.Equal(t, 0, insertCnt) + require.Equal(t, 0, deleteBuf.Len()) + require.Equal(t, 0, insertBuf.Len()) + require.Contains(t, out.String(), "insert into db1.__mo_diff_del_x values (1);") + require.Contains(t, out.String(), "insert into db1.__mo_diff_ins_x values (1,'a');") + }) +} + func TestDataBranchOutputNewSingleWriteAppenderNilWorker(t *testing.T) { _, _, err := newSingleWriteAppender(context.Background(), nil, nil, "unused", nil) require.Error(t, err) From e52c2a435408ac1b867dab61e484287f3a189fd3 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 5 Mar 2026 10:56:28 +0800 Subject: [PATCH 18/23] test: cover buildOutputSchema branches --- pkg/frontend/data_branch_output_test.go | 112 ++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/pkg/frontend/data_branch_output_test.go b/pkg/frontend/data_branch_output_test.go index d5d66a41325d7..a9d3fb80385a2 100644 --- a/pkg/frontend/data_branch_output_test.go +++ b/pkg/frontend/data_branch_output_test.go @@ -69,6 +69,118 @@ func TestDataBranchOutputMakeFileName(t *testing.T) { require.Regexp(t, regexp.MustCompile(`^diff_t2_sp2_t1_sp1_\d{8}_\d{6}$`), got) } +func TestDataBranchOutputBuildOutputSchema(t *testing.T) { + ctx := context.Background() + ses := newValidateSession(t) + ses.SetMysqlResultSet(&MysqlResultSet{}) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + baseRel := mock_frontend.NewMockRelation(ctrl) + tarRel := mock_frontend.NewMockRelation(ctrl) + baseRel.EXPECT().GetTableName().Return("t1").AnyTimes() + tarRel.EXPECT().GetTableName().Return("t2").AnyTimes() + + tblStuff := tableStuff{ + baseRel: baseRel, + tarRel: tarRel, + } + tblStuff.def.colNames = []string{"id", "name"} + tblStuff.def.colTypes = []types.Type{types.T_int64.ToType(), types.T_varchar.ToType()} + tblStuff.def.visibleIdxes = []int{0, 1} + + target := tree.NewTableName(tree.Identifier("t2"), tree.ObjectNamePrefix{}, nil) + base := tree.NewTableName(tree.Identifier("t1"), tree.ObjectNamePrefix{}, nil) + + t.Run("default output", func(t *testing.T) { + ses.SetMysqlResultSet(&MysqlResultSet{}) + stmt := &tree.DataBranchDiff{ + TargetTable: *target, + BaseTable: *base, + OutputOpt: nil, + } + require.NoError(t, buildOutputSchema(ctx, ses, stmt, tblStuff)) + + mrs := ses.GetMysqlResultSet() + require.Equal(t, uint64(4), mrs.GetColumnCount()) + col0, err := mrs.GetColumn(ctx, 0) + require.NoError(t, err) + require.Equal(t, "diff t2 against t1", col0.Name()) + col1, err := mrs.GetColumn(ctx, 1) + require.NoError(t, err) + require.Equal(t, "flag", col1.Name()) + }) + + t.Run("summary output", func(t *testing.T) { + ses.SetMysqlResultSet(&MysqlResultSet{}) + stmt := &tree.DataBranchDiff{ + TargetTable: *target, + BaseTable: *base, + OutputOpt: &tree.DiffOutputOpt{Summary: true}, + } + require.NoError(t, buildOutputSchema(ctx, ses, stmt, tblStuff)) + + mrs := ses.GetMysqlResultSet() + require.Equal(t, uint64(3), mrs.GetColumnCount()) + col0, err := mrs.GetColumn(ctx, 0) + require.NoError(t, err) + require.Equal(t, "metric", col0.Name()) + col1, err := mrs.GetColumn(ctx, 1) + require.NoError(t, err) + require.Contains(t, col1.Name(), "t2") + col2, err := mrs.GetColumn(ctx, 2) + require.NoError(t, err) + require.Contains(t, col2.Name(), "t1") + }) + + t.Run("count output", func(t *testing.T) { + ses.SetMysqlResultSet(&MysqlResultSet{}) + stmt := &tree.DataBranchDiff{ + TargetTable: *target, + BaseTable: *base, + OutputOpt: &tree.DiffOutputOpt{Count: true}, + } + require.NoError(t, buildOutputSchema(ctx, ses, stmt, tblStuff)) + + mrs := ses.GetMysqlResultSet() + require.Equal(t, uint64(1), mrs.GetColumnCount()) + col0, err := mrs.GetColumn(ctx, 0) + require.NoError(t, err) + require.Equal(t, "COUNT(*)", col0.Name()) + }) + + t.Run("file output", func(t *testing.T) { + ses.SetMysqlResultSet(&MysqlResultSet{}) + stmt := &tree.DataBranchDiff{ + TargetTable: *target, + BaseTable: *base, + OutputOpt: &tree.DiffOutputOpt{DirPath: "/tmp"}, + } + require.NoError(t, buildOutputSchema(ctx, ses, stmt, tblStuff)) + + mrs := ses.GetMysqlResultSet() + require.Equal(t, uint64(2), mrs.GetColumnCount()) + col0, err := mrs.GetColumn(ctx, 0) + require.NoError(t, err) + require.Equal(t, "FILE SAVED TO", col0.Name()) + col1, err := mrs.GetColumn(ctx, 1) + require.NoError(t, err) + require.Equal(t, "HINT", col1.Name()) + }) + + t.Run("unsupported output", func(t *testing.T) { + ses.SetMysqlResultSet(&MysqlResultSet{}) + stmt := &tree.DataBranchDiff{ + TargetTable: *target, + BaseTable: *base, + OutputOpt: &tree.DiffOutputOpt{}, + } + err := buildOutputSchema(ctx, ses, stmt, tblStuff) + require.Error(t, err) + }) +} + func TestDataBranchOutputWriteRowValues(t *testing.T) { tblStuff := tableStuff{} tblStuff.def.colNames = []string{"id", "name"} From ccb42d26f1a3d5b4bff6e034fe7be8715b9f4476 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Thu, 5 Mar 2026 14:26:32 +0800 Subject: [PATCH 19/23] test: cover appender and cleanup file helpers --- pkg/frontend/data_branch_output_test.go | 96 +++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/pkg/frontend/data_branch_output_test.go b/pkg/frontend/data_branch_output_test.go index a9d3fb80385a2..89bf84cb7ae6f 100644 --- a/pkg/frontend/data_branch_output_test.go +++ b/pkg/frontend/data_branch_output_test.go @@ -17,15 +17,20 @@ package frontend import ( "bytes" "context" + "os" + "path/filepath" "regexp" "strings" "testing" "github.com/golang/mock/gomock" + "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/fileservice" mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) @@ -591,3 +596,94 @@ func TestDataBranchOutputNewSingleWriteAppenderNilWorker(t *testing.T) { _, _, err := newSingleWriteAppender(context.Background(), nil, nil, "unused", nil) require.Error(t, err) } + +func TestDataBranchOutputNewSingleWriteAppenderSuccess(t *testing.T) { + ctx := context.Background() + dir := t.TempDir() + filePath := filepath.Join(dir, "diff.sql") + + etlFS, targetPath, err := fileservice.GetForETL(ctx, nil, filePath) + require.NoError(t, err) + + pool, err := ants.NewPool(1) + require.NoError(t, err) + defer pool.Release() + + called := false + writeFile, release, err := newSingleWriteAppender(ctx, pool, etlFS, targetPath, func() { + called = true + }) + require.NoError(t, err) + + require.NoError(t, writeFile([]byte("BEGIN;\n"))) + require.NoError(t, writeFile([]byte("COMMIT;\n"))) + release() + require.False(t, called) + + content, err := os.ReadFile(filePath) + require.NoError(t, err) + require.Equal(t, "BEGIN;\nCOMMIT;\n", string(content)) +} + +type failingWriteFS struct { + fileservice.FileService +} + +func (fs *failingWriteFS) Write(ctx context.Context, vector fileservice.IOVector) error { + return moerr.NewInternalErrorNoCtx("mock write failure") +} + +func TestDataBranchOutputNewSingleWriteAppenderWriteFail(t *testing.T) { + ctx := context.Background() + dir := t.TempDir() + filePath := filepath.Join(dir, "diff.sql") + + etlFS, _, err := fileservice.GetForETL(ctx, nil, filePath) + require.NoError(t, err) + + pool, err := ants.NewPool(1) + require.NoError(t, err) + defer pool.Release() + + called := false + writeFile, release, err := newSingleWriteAppender( + ctx, + pool, + &failingWriteFS{FileService: etlFS}, + "diff.sql", + func() { called = true }, + ) + require.NoError(t, err) + + _ = writeFile([]byte("SOME SQL;\n")) + release() + require.True(t, called) +} + +func TestDataBranchOutputNewSingleWriteAppenderSubmitFail(t *testing.T) { + ctx := context.Background() + dir := t.TempDir() + filePath := filepath.Join(dir, "diff.sql") + + etlFS, _, err := fileservice.GetForETL(ctx, nil, filePath) + require.NoError(t, err) + + pool, err := ants.NewPool(1) + require.NoError(t, err) + pool.Release() + + _, _, err = newSingleWriteAppender(ctx, pool, etlFS, "diff.sql", nil) + require.Error(t, err) +} + +func TestDataBranchOutputRemoveFileIgnoreError(t *testing.T) { + ctx := context.Background() + filePath := filepath.Join(t.TempDir(), "diff.sql") + require.NoError(t, os.WriteFile(filePath, []byte("x"), 0o644)) + + removeFileIgnoreError(ctx, "", filePath) + + _, err := os.Stat(filePath) + require.Error(t, err) + require.True(t, os.IsNotExist(err)) +} From 3f3602b91725ecbe4bd8cba84653c2a39ca3a3a9 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 9 Mar 2026 17:05:06 +0800 Subject: [PATCH 20/23] fix data branch diff branch timestamp semantics --- pkg/frontend/clone.go | 13 +- pkg/frontend/data_branch.go | 280 ++++++++++-------- pkg/frontend/data_branch_hashdiff.go | 1 - pkg/frontend/databranchutils/branch_dag.go | 30 +- .../databranchutils/branch_dag_test.go | 55 ++-- 5 files changed, 206 insertions(+), 173 deletions(-) diff --git a/pkg/frontend/clone.go b/pkg/frontend/clone.go index 02a3b46a51666..02721e7aa1422 100644 --- a/pkg/frontend/clone.go +++ b/pkg/frontend/clone.go @@ -599,11 +599,18 @@ func updateBranchMetaTable( return nil } - if _, srcTblDef, err = ses.GetTxnCompileCtx().Resolve( - receipt.srcDb, receipt.srcTbl, receipt.snapshot, - ); err != nil { + srcCtx := defines.AttachAccountId(ctx, receipt.srcAccount) + tcc := ses.GetTxnCompileCtx() + origCtx := tcc.GetContext() + tcc.SetContext(srcCtx) + defer tcc.SetContext(origCtx) + + if _, srcTblDef, err = tcc.Resolve(receipt.srcDb, receipt.srcTbl, nil); err != nil { return err } + if srcTblDef == nil { + return moerr.NewNoSuchTable(srcCtx, receipt.srcDb, receipt.srcTbl) + } dstCtx := defines.AttachAccountId(ctx, receipt.toAccount) diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 1b3480c122c24..231cdd584714c 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -675,7 +675,6 @@ func diffMergeAgency( ); err != nil { return } - var ( done bool wg = new(sync.WaitGroup) @@ -960,7 +959,6 @@ func diffOnBase( } } } - // has no lca if tarHandle, baseHandle, err = constructChangeHandle( ctx, ses, bh, tblStuff, &dagInfo, @@ -1133,7 +1131,6 @@ func constructChangeHandle( ); err != nil { return } - for i := range tarRange.rel { if handle, err = databranchutils.CollectChanges( ctx, @@ -1223,9 +1220,13 @@ func decideCollectRange( tarCTS = tblCommitTS[0] baseCTS = tblCommitTS[1] - // Note That: - // 1. the branchTS+1 cannot skip the cloned data, we need get the clone commitTS (the table creation commitTS) - // + // Boundary semantics: + // 1. childCreateCommitTS marks when the child table itself becomes visible. + // The cloned rows are materialized by that DDL, so child-owned change collection + // must start from childCreateCommitTS.Next() to avoid re-reading inherited rows. + // 2. branchTS marks the source snapshot on the parent/LCA side used by the clone. + // Parent-side incremental comparison must start from branchTS.Next() because the + // snapshot at branchTS is already included in the cloned contents. // now we got the t1.snapshot, t1.branchTS, t2.snapshot, t2.branchTS and txnSnapshot, // and then we need to decide the range that t1 and t2 should collect. @@ -1409,7 +1410,6 @@ func getTablesCreationCommitTS( base engine.Relation, snapshot []types.TS, ) (commitTS []types.TS, err error) { - resolveSnapshot := func(idx int) types.TS { if idx >= 0 && idx < len(snapshot) && !snapshot[idx].IsEmpty() { return snapshot[idx] @@ -1417,121 +1417,117 @@ func getTablesCreationCommitTS( return types.TimestampToTS(ses.GetTxnHandler().GetTxn().SnapshotTS()) } - resolveOne := func(tableID uint64, sp types.TS) (types.TS, error) { - resolveAt := func(snapshotTS types.TS) (commit types.TS, ok bool, err error) { - txnOp := ses.GetTxnHandler().GetTxn().CloneSnapshotOp(snapshotTS.ToTimestamp()) - _, _, moTablesRel, rerr := ses.GetTxnHandler().GetStorage().GetRelationById(ctx, txnOp, catalog.MO_TABLES_ID) - if rerr != nil { - return types.TS{}, false, rerr - } + tarCommitTS, err := getTableCreationCommitTSByID(ctx, ses, tar.GetTableID(ctx), resolveSnapshot(0)) + if err != nil { + return nil, err + } + baseCommitTS, err := getTableCreationCommitTSByID(ctx, ses, base.GetTableID(ctx), resolveSnapshot(1)) + if err != nil { + return nil, err + } + return []types.TS{tarCommitTS, baseCommitTS}, nil +} - relData, rerr := moTablesRel.Ranges(ctx, engine.DefaultRangesParam) - if rerr != nil { - return types.TS{}, false, rerr - } - readers, rerr := moTablesRel.BuildReaders( - ctx, - ses.proc, - nil, - relData, - 1, - 0, - false, - engine.Policy_CheckCommittedOnly, - engine.FilterHint{}, - ) - if rerr != nil { - return types.TS{}, false, rerr +func getTableCreationCommitTSByID( + ctx context.Context, + ses *Session, + tableID uint64, + snapshotTS types.TS, +) (types.TS, error) { + resolveAt := func(at types.TS) (commit types.TS, ok bool, err error) { + txnOp := ses.GetTxnHandler().GetTxn().CloneSnapshotOp(at.ToTimestamp()) + _, _, moTablesRel, rerr := ses.GetTxnHandler().GetStorage().GetRelationById(ctx, txnOp, catalog.MO_TABLES_ID) + if rerr != nil { + return types.TS{}, false, rerr + } + + relData, rerr := moTablesRel.Ranges(ctx, engine.DefaultRangesParam) + if rerr != nil { + return types.TS{}, false, rerr + } + readers, rerr := moTablesRel.BuildReaders( + ctx, + ses.proc, + nil, + relData, + 1, + 0, + false, + engine.Policy_CheckCommittedOnly, + engine.FilterHint{}, + ) + if rerr != nil { + return types.TS{}, false, rerr + } + defer func() { + for _, rd := range readers { + if rd != nil { + _ = rd.Close() + } } - defer func() { - for _, rd := range readers { - if rd != nil { - _ = rd.Close() - } + }() + + attrs := []string{ + catalog.SystemRelAttr_ID, + objectio.DefaultCommitTS_Attr, + } + readBatch := batch.NewWithSize(len(attrs)) + readBatch.SetAttributes(attrs) + readBatch.Vecs[0] = vector.NewVec(types.T_uint64.ToType()) + readBatch.Vecs[1] = vector.NewVec(types.T_TS.ToType()) + defer readBatch.Clean(ses.proc.Mp()) + + rowFound := false + commitFound := false + commitTS := types.TS{} + for _, rd := range readers { + for { + var isEnd bool + isEnd, rerr = rd.Read(ctx, attrs, nil, ses.proc.Mp(), readBatch) + if rerr != nil { + return types.TS{}, false, rerr + } + if isEnd { + break + } + if readBatch.RowCount() == 0 { + continue } - }() - attrs := []string{ - catalog.SystemRelAttr_ID, - objectio.DefaultCommitTS_Attr, - } - readBatch := batch.NewWithSize(len(attrs)) - readBatch.SetAttributes(attrs) - readBatch.Vecs[0] = vector.NewVec(types.T_uint64.ToType()) - readBatch.Vecs[1] = vector.NewVec(types.T_TS.ToType()) - defer readBatch.Clean(ses.proc.Mp()) - - rowFound := false - commitFound := false - commitTS := types.TS{} - for _, rd := range readers { - for { - var isEnd bool - isEnd, rerr = rd.Read(ctx, attrs, nil, ses.proc.Mp(), readBatch) - if rerr != nil { - return types.TS{}, false, rerr - } - if isEnd { - break - } - if readBatch.RowCount() == 0 { + relIDs := vector.MustFixedColWithTypeCheck[uint64](readBatch.Vecs[0]) + commitCol := vector.MustFixedColWithTypeCheck[types.TS](readBatch.Vecs[1]) + for i := range relIDs { + if relIDs[i] != tableID { continue } - - relIDs := vector.MustFixedColWithTypeCheck[uint64](readBatch.Vecs[0]) - commitCol := vector.MustFixedColWithTypeCheck[types.TS](readBatch.Vecs[1]) - for i := range relIDs { - if relIDs[i] != tableID { - continue - } - rowFound = true - if !readBatch.Vecs[1].IsNull(uint64(i)) { - if !commitFound || commitCol[i].LT(&commitTS) { - commitTS = commitCol[i] - } - commitFound = true + rowFound = true + if !readBatch.Vecs[1].IsNull(uint64(i)) { + if !commitFound || commitCol[i].LT(&commitTS) { + commitTS = commitCol[i] } + commitFound = true } } } - - if commitFound { - return commitTS, true, nil - } - return types.TS{}, rowFound, nil } - if commit, ok, rerr := resolveAt(sp); rerr != nil { - return types.TS{}, rerr - } else if ok { - return commit, nil + if commitFound { + return commitTS, true, nil } - - curSnapshot := types.TimestampToTS(ses.GetTxnHandler().GetTxn().SnapshotTS()) - if !curSnapshot.EQ(&sp) { - if commit, ok, rerr := resolveAt(curSnapshot); rerr != nil { - return types.TS{}, rerr - } else if ok { - return commit, nil - } - } - - return types.TS{}, moerr.NewInternalErrorNoCtxf( - "cannot find table %d commit ts at snapshot %s", - tableID, - sp.ToString(), - ) + return types.TS{}, rowFound, nil } - tarCommitTS, err := resolveOne(tar.GetTableID(ctx), resolveSnapshot(0)) - if err != nil { - return nil, err + if commit, ok, err := resolveAt(snapshotTS); err != nil { + return types.TS{}, err + } else if ok { + return commit, nil } - baseCommitTS, err := resolveOne(base.GetTableID(ctx), resolveSnapshot(1)) - if err != nil { - return nil, err - } - return []types.TS{tarCommitTS, baseCommitTS}, nil + + return types.TS{}, moerr.NewInternalErrorNoCtxf( + "cannot find table %d commit ts at snapshot %s", + tableID, + snapshotTS.ToString(), + ) } func decideLCABranchTSFromBranchDAG( @@ -1547,22 +1543,22 @@ func decideLCABranchTSFromBranchDAG( var ( dag *databranchutils.DataBranchDAG - tarTS int64 - baseTS int64 - hasLca bool - lcaType int + tarBranchTableID uint64 + baseBranchTableID uint64 + hasLca bool + lcaType int lcaTableID uint64 - tarBranchTS timestamp.Timestamp - baseBranchTS timestamp.Timestamp + tarBranchTS types.TS + baseBranchTS types.TS ) defer func() { branchInfo = branchMetaInfo{ lcaType: lcaType, lcaTableId: lcaTableID, - tarBranchTS: types.TimestampToTS(tarBranchTS), - baseBranchTS: types.TimestampToTS(baseBranchTS), + tarBranchTS: tarBranchTS, + baseBranchTS: baseBranchTS, } }() @@ -1580,25 +1576,45 @@ func decideLCABranchTSFromBranchDAG( // 3. t2 is the lca // t1's [branch_t1_ts + 1, now] join t2's [branch_t1_ts + 1, now] // - // if a table is cloned table, the commit ts of the cloned data - // should be the creation time of the table. - if lcaTableID, tarTS, baseTS, hasLca = dag.FindLCA( + // The DAG only answers lineage questions. The branch timestamp attached to an + // outgoing edge is the source snapshot used by the clone operation, not the + // creation commit timestamp of the child table. + if lcaTableID, tarBranchTableID, baseBranchTableID, hasLca = dag.FindLCA( tblStuff.tarRel.GetTableID(ctx), tblStuff.baseRel.GetTableID(ctx), ); hasLca { if lcaTableID == tblStuff.baseRel.GetTableID(ctx) { - ts := timestamp.Timestamp{PhysicalTime: tarTS} - tarBranchTS = ts - baseBranchTS = ts lcaType = lcaRight + baseBranchTableID = tarBranchTableID + var ts int64 + if ts, hasLca = dag.GetCloneTS(tarBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", tarBranchTableID) + return + } + tarBranchTS = types.BuildTS(ts, 0) + baseBranchTS = tarBranchTS } else if lcaTableID == tblStuff.tarRel.GetTableID(ctx) { - ts := timestamp.Timestamp{PhysicalTime: baseTS} - tarBranchTS = ts - baseBranchTS = ts lcaType = lcaLeft + tarBranchTableID = baseBranchTableID + var ts int64 + if ts, hasLca = dag.GetCloneTS(baseBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", baseBranchTableID) + return + } + baseBranchTS = types.BuildTS(ts, 0) + tarBranchTS = baseBranchTS } else { lcaType = lcaOther - tarBranchTS = timestamp.Timestamp{PhysicalTime: tarTS} - baseBranchTS = timestamp.Timestamp{PhysicalTime: baseTS} + var ts int64 + if ts, hasLca = dag.GetCloneTS(tarBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", tarBranchTableID) + return + } + tarBranchTS = types.BuildTS(ts, 0) + if ts, hasLca = dag.GetCloneTS(baseBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", baseBranchTableID) + return + } + baseBranchTS = types.BuildTS(ts, 0) } } else if tblStuff.tarRel.GetTableID(ctx) == tblStuff.baseRel.GetTableID(ctx) { lcaTableID = tblStuff.tarRel.GetTableID(ctx) @@ -1616,7 +1632,6 @@ func decideLCABranchTSFromBranchDAG( lcaType = lcaRight } } - return } @@ -1644,7 +1659,10 @@ func constructBranchDAG( if sqlRet, err = runSql( sysCtx, ses, bh, - fmt.Sprintf(scanBranchMetadataSql, catalog.MO_CATALOG, catalog.MO_BRANCH_METADATA), + fmt.Sprintf( + "select table_id, clone_ts, p_table_id, table_deleted from %s.%s", + catalog.MO_CATALOG, catalog.MO_BRANCH_METADATA, + ), nil, nil, ); err != nil { return @@ -1655,11 +1673,13 @@ func constructBranchDAG( tblIds := vector.MustFixedColNoTypeCheck[uint64](cols[0]) cloneTS := vector.MustFixedColNoTypeCheck[int64](cols[1]) pTblIds := vector.MustFixedColNoTypeCheck[uint64](cols[2]) + tableDeleted := vector.MustFixedColNoTypeCheck[bool](cols[3]) for i := range tblIds { rowData = append(rowData, databranchutils.DataBranchMetadata{ - TableID: tblIds[i], - CloneTS: cloneTS[i], - PTableID: pTblIds[i], + TableID: tblIds[i], + CloneTS: cloneTS[i], + PTableID: pTblIds[i], + TableDeleted: tableDeleted[i], }) } return true diff --git a/pkg/frontend/data_branch_hashdiff.go b/pkg/frontend/data_branch_hashdiff.go index bdd47974ef29d..25fff0be9a428 100644 --- a/pkg/frontend/data_branch_hashdiff.go +++ b/pkg/frontend/data_branch_hashdiff.go @@ -1253,7 +1253,6 @@ func buildHashmapForTable( tombstoneHashmap databranchutils.BranchHashmap, err error, ) { - var ( atomicErr atomic.Value dataBat *batch.Batch diff --git a/pkg/frontend/databranchutils/branch_dag.go b/pkg/frontend/databranchutils/branch_dag.go index b9a765f331ecf..fd03ae0141a49 100644 --- a/pkg/frontend/databranchutils/branch_dag.go +++ b/pkg/frontend/databranchutils/branch_dag.go @@ -126,10 +126,10 @@ func (d *DataBranchDAG) HasParent(tableID uint64) bool { // FindLCA finds the Lowest Common Ancestor (LCA) for two given table IDs. // It returns: // 1. lcaTableID: The table_id of the common ancestor. -// 2. branchTS1: The clone_ts of the direct child of the LCA that is on the path to tableID1. -// 3. branchTS2: The clone_ts of the direct child of the LCA that is on the path to tableID2. +// 2. childTableID1: The direct child table of the LCA that is on the path to tableID1. +// 3. childTableID2: The direct child table of the LCA that is on the path to tableID2. // 4. ok: A boolean indicating if a common ancestor was found. -func (d *DataBranchDAG) FindLCA(tableID1, tableID2 uint64) (lcaTableID uint64, branchTS1 int64, branchTS2 int64, ok bool) { +func (d *DataBranchDAG) FindLCA(tableID1, tableID2 uint64) (lcaTableID uint64, childTableID1 uint64, childTableID2 uint64, ok bool) { node1, exists1 := d.nodes[tableID1] node2, exists2 := d.nodes[tableID2] @@ -139,9 +139,9 @@ func (d *DataBranchDAG) FindLCA(tableID1, tableID2 uint64) (lcaTableID uint64, b } // If it's the same node, it is its own LCA. - // Both branch timestamps can be defined as the node's own creation timestamp. + // Both child table IDs collapse to the node itself. if tableID1 == tableID2 { - return tableID1, node1.CloneTS, node1.CloneTS, true + return tableID1, node1.TableID, node1.TableID, true } // Keep references to the original nodes for the final step of finding branch timestamps. @@ -182,28 +182,36 @@ func (d *DataBranchDAG) FindLCA(tableID1, tableID2 uint64) (lcaTableID uint64, b // --- Step 3: Find the specific children of the LCA that lead to the original nodes --- - // Find the branch timestamp for the path to tableID1 + // Find the direct child table on the path to tableID1. child1 := originalNode1 if child1 != lcaNode { // If the original node is not the LCA itself for child1 != nil && child1.Parent != lcaNode { child1 = child1.Parent } - branchTS1 = child1.CloneTS + childTableID1 = child1.TableID } else { // If the original node IS the LCA (ancestor case) - branchTS1 = lcaNode.CloneTS + childTableID1 = lcaNode.TableID } - // Find the branch timestamp for the path to tableID2 + // Find the direct child table on the path to tableID2. child2 := originalNode2 if child2 != lcaNode { // If the original node is not the LCA itself for child2 != nil && child2.Parent != lcaNode { child2 = child2.Parent } - branchTS2 = child2.CloneTS + childTableID2 = child2.TableID } else { // If the original node IS the LCA (ancestor case) - branchTS2 = lcaNode.CloneTS + childTableID2 = lcaNode.TableID } ok = true return } + +func (d *DataBranchDAG) GetCloneTS(tableID uint64) (int64, bool) { + node, ok := d.nodes[tableID] + if !ok { + return 0, false + } + return node.CloneTS, true +} diff --git a/pkg/frontend/databranchutils/branch_dag_test.go b/pkg/frontend/databranchutils/branch_dag_test.go index 28520fa84a2e5..992f9019cfb91 100644 --- a/pkg/frontend/databranchutils/branch_dag_test.go +++ b/pkg/frontend/databranchutils/branch_dag_test.go @@ -19,44 +19,43 @@ import "testing" func TestDAGFunctionality(t *testing.T) { // --- Test Setup: Define a complex graph with multiple trees (a forest) --- - // NEW: Since fields cannot be null, we now use value types directly. // A PTableID of 0 is used to signify a root node. // // The graph structure being tested remains the same: // Tree 1 (Root 100) Tree 2 (Root 200) Tree 3 (Root 300) Tree 4 (Root 400) // - // 100(ts:100) 200(ts:200) 300(ts:300) 400(ts:400) + // 100 200 300 400 // / | \ / \ | - // 110(110) 120(120) 130(130) 210(210) 220(220) 301(301) + // 110 120 130 210 220 301 // / \ | | | - // 111(111) 112(112) 121(121) 211(211) 302(302) + // 111 112 121 211 302 // | - // 1121(1121) + // 1121 // rows := []DataBranchMetadata{ // Tree 1 - {TableID: 100, CloneTS: 100, PTableID: 0}, // PTableID: 0 indicates a root node - {TableID: 110, CloneTS: 110, PTableID: 100}, - {TableID: 120, CloneTS: 120, PTableID: 100}, - {TableID: 130, CloneTS: 130, PTableID: 100}, - {TableID: 111, CloneTS: 111, PTableID: 110}, - {TableID: 112, CloneTS: 112, PTableID: 110}, - {TableID: 121, CloneTS: 121, PTableID: 120}, - {TableID: 1121, CloneTS: 1121, PTableID: 112}, + {TableID: 100, PTableID: 0}, // PTableID: 0 indicates a root node + {TableID: 110, PTableID: 100}, + {TableID: 120, PTableID: 100}, + {TableID: 130, PTableID: 100}, + {TableID: 111, PTableID: 110}, + {TableID: 112, PTableID: 110}, + {TableID: 121, PTableID: 120}, + {TableID: 1121, PTableID: 112}, // Tree 2 - {TableID: 200, CloneTS: 200, PTableID: 0}, // PTableID: 0 indicates a root node - {TableID: 210, CloneTS: 210, PTableID: 200}, - {TableID: 220, CloneTS: 220, PTableID: 200}, - {TableID: 211, CloneTS: 211, PTableID: 210}, + {TableID: 200, PTableID: 0}, // PTableID: 0 indicates a root node + {TableID: 210, PTableID: 200}, + {TableID: 220, PTableID: 200}, + {TableID: 211, PTableID: 210}, // Tree 3 (A simple chain) - {TableID: 300, CloneTS: 300, PTableID: 0}, // PTableID: 0 indicates a root node - {TableID: 301, CloneTS: 301, PTableID: 300}, - {TableID: 302, CloneTS: 302, PTableID: 301}, + {TableID: 300, PTableID: 0}, // PTableID: 0 indicates a root node + {TableID: 301, PTableID: 300}, + {TableID: 302, PTableID: 301}, // Tree 4 (Isolated node) - {TableID: 400, CloneTS: 400, PTableID: 0}, // PTableID: 0 indicates a root node + {TableID: 400, PTableID: 0}, // PTableID: 0 indicates a root node } // Assuming your newDAG function has been updated to handle PTableID=0 as a root. @@ -96,8 +95,8 @@ func TestDAGFunctionality(t *testing.T) { name string id1, id2 uint64 wantLCA uint64 - wantTS1 int64 - wantTS2 int64 + wantTS1 uint64 + wantTS2 uint64 wantOK bool }{ // --- Scenarios within a single complex tree (Tree 1) --- @@ -174,7 +173,7 @@ func TestDAGFunctionality(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - lcaID, ts1, ts2, ok := dag.FindLCA(tc.id1, tc.id2) + lcaID, childID1, childID2, ok := dag.FindLCA(tc.id1, tc.id2) if ok != tc.wantOK { t.Fatalf("FindLCA(%d, %d): expected ok=%v, got ok=%v", tc.id1, tc.id2, tc.wantOK, ok) @@ -185,11 +184,11 @@ func TestDAGFunctionality(t *testing.T) { if lcaID != tc.wantLCA { t.Errorf("FindLCA(%d, %d): wrong LCA ID. got=%d, want=%d", tc.id1, tc.id2, lcaID, tc.wantLCA) } - if ts1 != tc.wantTS1 { - t.Errorf("FindLCA(%d, %d): wrong branch TS1. got=%d, want=%d", tc.id1, tc.id2, ts1, tc.wantTS1) + if childID1 != tc.wantTS1 { + t.Errorf("FindLCA(%d, %d): wrong child table ID1. got=%d, want=%d", tc.id1, tc.id2, childID1, tc.wantTS1) } - if ts2 != tc.wantTS2 { - t.Errorf("FindLCA(%d, %d): wrong branch TS2. got=%d, want=%d", tc.id1, tc.id2, ts2, tc.wantTS2) + if childID2 != tc.wantTS2 { + t.Errorf("FindLCA(%d, %d): wrong child table ID2. got=%d, want=%d", tc.id1, tc.id2, childID2, tc.wantTS2) } } }) From b67e011ade1a9691ae14d49b960891593c2b2686 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Mon, 9 Mar 2026 18:47:37 +0800 Subject: [PATCH 21/23] fix ineffectual lca branch assignments --- pkg/frontend/data_branch.go | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index 231cdd584714c..b221b3c251754 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -1581,23 +1581,21 @@ func decideLCABranchTSFromBranchDAG( // creation commit timestamp of the child table. if lcaTableID, tarBranchTableID, baseBranchTableID, hasLca = dag.FindLCA( tblStuff.tarRel.GetTableID(ctx), tblStuff.baseRel.GetTableID(ctx), - ); hasLca { - if lcaTableID == tblStuff.baseRel.GetTableID(ctx) { - lcaType = lcaRight - baseBranchTableID = tarBranchTableID - var ts int64 - if ts, hasLca = dag.GetCloneTS(tarBranchTableID); !hasLca { - err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", tarBranchTableID) + ); hasLca { + if lcaTableID == tblStuff.baseRel.GetTableID(ctx) { + lcaType = lcaRight + var ts int64 + if ts, hasLca = dag.GetCloneTS(tarBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", tarBranchTableID) return } - tarBranchTS = types.BuildTS(ts, 0) - baseBranchTS = tarBranchTS - } else if lcaTableID == tblStuff.tarRel.GetTableID(ctx) { - lcaType = lcaLeft - tarBranchTableID = baseBranchTableID - var ts int64 - if ts, hasLca = dag.GetCloneTS(baseBranchTableID); !hasLca { - err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", baseBranchTableID) + tarBranchTS = types.BuildTS(ts, 0) + baseBranchTS = tarBranchTS + } else if lcaTableID == tblStuff.tarRel.GetTableID(ctx) { + lcaType = lcaLeft + var ts int64 + if ts, hasLca = dag.GetCloneTS(baseBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", baseBranchTableID) return } baseBranchTS = types.BuildTS(ts, 0) From 89ab62c6ba24d425fc32b0359b0212d8326621ac Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Tue, 10 Mar 2026 10:40:09 +0800 Subject: [PATCH 22/23] format data branch dag lookup --- pkg/frontend/data_branch.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/frontend/data_branch.go b/pkg/frontend/data_branch.go index b221b3c251754..2b68acf3016df 100644 --- a/pkg/frontend/data_branch.go +++ b/pkg/frontend/data_branch.go @@ -1581,21 +1581,21 @@ func decideLCABranchTSFromBranchDAG( // creation commit timestamp of the child table. if lcaTableID, tarBranchTableID, baseBranchTableID, hasLca = dag.FindLCA( tblStuff.tarRel.GetTableID(ctx), tblStuff.baseRel.GetTableID(ctx), - ); hasLca { - if lcaTableID == tblStuff.baseRel.GetTableID(ctx) { - lcaType = lcaRight - var ts int64 - if ts, hasLca = dag.GetCloneTS(tarBranchTableID); !hasLca { - err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", tarBranchTableID) + ); hasLca { + if lcaTableID == tblStuff.baseRel.GetTableID(ctx) { + lcaType = lcaRight + var ts int64 + if ts, hasLca = dag.GetCloneTS(tarBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", tarBranchTableID) return } - tarBranchTS = types.BuildTS(ts, 0) - baseBranchTS = tarBranchTS - } else if lcaTableID == tblStuff.tarRel.GetTableID(ctx) { - lcaType = lcaLeft - var ts int64 - if ts, hasLca = dag.GetCloneTS(baseBranchTableID); !hasLca { - err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", baseBranchTableID) + tarBranchTS = types.BuildTS(ts, 0) + baseBranchTS = tarBranchTS + } else if lcaTableID == tblStuff.tarRel.GetTableID(ctx) { + lcaType = lcaLeft + var ts int64 + if ts, hasLca = dag.GetCloneTS(baseBranchTableID); !hasLca { + err = moerr.NewInternalErrorNoCtxf("cannot find clone ts for table %d", baseBranchTableID) return } baseBranchTS = types.BuildTS(ts, 0) From 87701cf4d8f35efcbb94d39970be623d59579ab3 Mon Sep 17 00:00:00 2001 From: gouhongshen Date: Tue, 10 Mar 2026 11:50:02 +0800 Subject: [PATCH 23/23] fix data branch csv diff result handling --- pkg/frontend/data_branch_output.go | 26 +++++++++----- pkg/frontend/data_branch_output_test.go | 46 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/pkg/frontend/data_branch_output.go b/pkg/frontend/data_branch_output.go index 0749bd81d32ed..ffff7d5c6a0e2 100644 --- a/pkg/frontend/data_branch_output.go +++ b/pkg/frontend/data_branch_output.go @@ -568,22 +568,32 @@ func tryDiffAsCSV( if sqlRet, err = runSql(ctx, ses, bh, sql, nil, nil); err != nil { return false, err } + defer sqlRet.Close() - if len(sqlRet.Batches) != 1 && - sqlRet.Batches[0].RowCount() != 1 && - sqlRet.Batches[0].VectorCount() != 1 { - return false, moerr.NewInternalErrorNoCtxf("cannot get count(*) of base table") + ok, err := shouldDiffAsCSV(sqlRet) + if err != nil { + return false, err } - - if vector.GetFixedAtWithTypeCheck[uint64](sqlRet.Batches[0].Vecs[0], 0) != 0 { + if !ok { return false, nil } - sqlRet.Close() - return true, writeCSV(ctx, ses, tblStuff, bh, stmt) } +func shouldDiffAsCSV(sqlRet executor.Result) (bool, error) { + if len(sqlRet.Batches) != 1 || + sqlRet.Batches[0] == nil || + sqlRet.Batches[0].RowCount() != 1 || + sqlRet.Batches[0].VectorCount() != 1 || + len(sqlRet.Batches[0].Vecs) != 1 || + sqlRet.Batches[0].Vecs[0] == nil { + return false, moerr.NewInternalErrorNoCtxf("cannot get count(*) of base table") + } + + return vector.GetFixedAtWithTypeCheck[uint64](sqlRet.Batches[0].Vecs[0], 0) == 0, nil +} + func writeCSV( inputCtx context.Context, ses *Session, diff --git a/pkg/frontend/data_branch_output_test.go b/pkg/frontend/data_branch_output_test.go index 89bf84cb7ae6f..fc799c873783e 100644 --- a/pkg/frontend/data_branch_output_test.go +++ b/pkg/frontend/data_branch_output_test.go @@ -25,11 +25,15 @@ import ( "github.com/golang/mock/gomock" "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/container/types" + "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/fileservice" mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test" "github.com/matrixorigin/matrixone/pkg/pb/plan" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/matrixorigin/matrixone/pkg/util/executor" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) @@ -186,6 +190,48 @@ func TestDataBranchOutputBuildOutputSchema(t *testing.T) { }) } +func TestDataBranchOutputShouldDiffAsCSV(t *testing.T) { + t.Run("reject malformed result without panic", func(t *testing.T) { + ok, err := shouldDiffAsCSV(executor.Result{}) + require.Error(t, err) + require.False(t, ok) + }) + + t.Run("reject non-zero base row count", func(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + bat := batch.NewWithSize(1) + bat.Vecs[0] = vector.NewVec(types.T_uint64.ToType()) + require.NoError(t, vector.AppendFixed[uint64](bat.Vecs[0], 3, false, mp)) + bat.SetRowCount(1) + + ok, err := shouldDiffAsCSV(executor.Result{ + Batches: []*batch.Batch{bat}, + Mp: mp, + }) + require.NoError(t, err) + require.False(t, ok) + }) + + t.Run("allow zero base row count", func(t *testing.T) { + mp := mpool.MustNewZero() + defer mpool.DeleteMPool(mp) + + bat := batch.NewWithSize(1) + bat.Vecs[0] = vector.NewVec(types.T_uint64.ToType()) + require.NoError(t, vector.AppendFixed[uint64](bat.Vecs[0], 0, false, mp)) + bat.SetRowCount(1) + + ok, err := shouldDiffAsCSV(executor.Result{ + Batches: []*batch.Batch{bat}, + Mp: mp, + }) + require.NoError(t, err) + require.True(t, ok) + }) +} + func TestDataBranchOutputWriteRowValues(t *testing.T) { tblStuff := tableStuff{} tblStuff.def.colNames = []string{"id", "name"}