github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/dtables/merge_status_table.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package dtables 16 17 import ( 18 "context" 19 "io" 20 "strings" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/types" 24 25 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 26 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess" 27 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/index" 28 "github.com/dolthub/dolt/go/libraries/utils/set" 29 ) 30 31 // MergeStatusTable is a sql.Table implementation that implements a system table 32 // which shows information about an active merge. 33 type MergeStatusTable struct { 34 dbName string 35 } 36 37 func (s MergeStatusTable) Name() string { 38 return doltdb.MergeStatusTableName 39 } 40 41 func (s MergeStatusTable) String() string { 42 return doltdb.MergeStatusTableName 43 } 44 45 func (s MergeStatusTable) Schema() sql.Schema { 46 return []*sql.Column{ 47 {Name: "is_merging", Type: types.Boolean, Source: doltdb.MergeStatusTableName, PrimaryKey: false, Nullable: false, DatabaseSource: s.dbName}, 48 {Name: "source", Type: types.Text, Source: doltdb.MergeStatusTableName, PrimaryKey: false, Nullable: true, DatabaseSource: s.dbName}, 49 {Name: "source_commit", Type: types.Text, Source: doltdb.MergeStatusTableName, PrimaryKey: false, Nullable: true, DatabaseSource: s.dbName}, 50 {Name: "target", Type: types.Text, Source: doltdb.MergeStatusTableName, PrimaryKey: false, Nullable: true, DatabaseSource: s.dbName}, 51 {Name: "unmerged_tables", Type: types.Text, Source: doltdb.MergeStatusTableName, PrimaryKey: false, Nullable: true, DatabaseSource: s.dbName}, 52 } 53 } 54 55 func (s MergeStatusTable) Collation() sql.CollationID { 56 return sql.Collation_Default 57 } 58 59 func (s MergeStatusTable) Partitions(*sql.Context) (sql.PartitionIter, error) { 60 return index.SinglePartitionIterFromNomsMap(nil), nil 61 } 62 63 func (s MergeStatusTable) PartitionRows(ctx *sql.Context, _ sql.Partition) (sql.RowIter, error) { 64 sesh := dsess.DSessFromSess(ctx.Session) 65 ws, err := sesh.WorkingSet(ctx, s.dbName) 66 if err != nil { 67 return nil, err 68 } 69 70 return newMergeStatusItr(ctx, ws) 71 } 72 73 // NewMergeStatusTable creates a StatusTable 74 func NewMergeStatusTable(dbName string) sql.Table { 75 return &MergeStatusTable{dbName} 76 } 77 78 // MergeStatusIter is a sql.RowItr implementation which iterates over each commit as if it's a row in the table. 79 type MergeStatusIter struct { 80 idx int 81 isMerging bool 82 sourceCommit *string 83 source *string 84 target *string 85 unmergedTables *string 86 } 87 88 func newMergeStatusItr(ctx context.Context, ws *doltdb.WorkingSet) (*MergeStatusIter, error) { 89 wr := ws.WorkingRoot() 90 91 inConflict, err := doltdb.TablesWithDataConflicts(ctx, wr) 92 if err != nil { 93 return nil, err 94 } 95 96 tblsWithViolations, err := doltdb.TablesWithConstraintViolations(ctx, wr) 97 if err != nil { 98 return nil, err 99 } 100 101 var schConflicts []string 102 if ws.MergeActive() { 103 schConflicts = ws.MergeState().TablesWithSchemaConflicts() 104 } 105 106 unmergedTblNames := set.NewStrSet(inConflict) 107 unmergedTblNames.Add(tblsWithViolations...) 108 unmergedTblNames.Add(schConflicts...) 109 110 var sourceCommitSpecStr *string 111 var sourceCommitHash *string 112 var target *string 113 var unmergedTables *string 114 if ws.MergeActive() { 115 state := ws.MergeState() 116 117 s := state.CommitSpecStr() 118 sourceCommitSpecStr = &s 119 120 cmHash, err := state.Commit().HashOf() 121 if err != nil { 122 return nil, err 123 } 124 s2 := cmHash.String() 125 sourceCommitHash = &s2 126 127 curr, err := ws.Ref().ToHeadRef() 128 if err != nil { 129 return nil, err 130 } 131 s3 := curr.String() 132 target = &s3 133 134 s4 := strings.Join(unmergedTblNames.AsSlice(), ", ") 135 unmergedTables = &s4 136 } 137 138 return &MergeStatusIter{ 139 idx: 0, 140 isMerging: ws.MergeActive(), 141 source: sourceCommitSpecStr, 142 sourceCommit: sourceCommitHash, 143 target: target, 144 unmergedTables: unmergedTables, 145 }, nil 146 } 147 148 // Next retrieves the next row. 149 func (itr *MergeStatusIter) Next(*sql.Context) (sql.Row, error) { 150 if itr.idx >= 1 { 151 return nil, io.EOF 152 } 153 154 defer func() { 155 itr.idx++ 156 }() 157 158 return sql.NewRow(itr.isMerging, unwrapString(itr.source), unwrapString(itr.sourceCommit), unwrapString(itr.target), unwrapString(itr.unmergedTables)), nil 159 } 160 161 func unwrapString(s *string) interface{} { 162 if s == nil { 163 return nil 164 } 165 return *s 166 } 167 168 // Close closes the iterator. 169 func (itr *MergeStatusIter) Close(*sql.Context) error { 170 return nil 171 }