github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/dtables/constraint_violations.go (about) 1 // Copyright 2021 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 "github.com/dolthub/go-mysql-server/sql" 19 20 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/index" 21 22 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 23 "github.com/dolthub/dolt/go/libraries/doltcore/row" 24 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 25 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil" 26 "github.com/dolthub/dolt/go/store/types" 27 ) 28 29 // NewConstraintViolationsTable returns a sql.Table that lists constraint violations. 30 func NewConstraintViolationsTable(ctx *sql.Context, tblName string, root doltdb.RootValue, rs RootSetter) (sql.Table, error) { 31 if root.VRW().Format() == types.Format_DOLT { 32 return newProllyCVTable(ctx, tblName, root, rs) 33 } 34 35 return newNomsCVTable(ctx, tblName, root, rs) 36 } 37 38 func newNomsCVTable(ctx *sql.Context, tblName string, root doltdb.RootValue, rs RootSetter) (sql.Table, error) { 39 tbl, tblName, ok, err := doltdb.GetTableInsensitive(ctx, root, tblName) 40 if err != nil { 41 return nil, err 42 } else if !ok { 43 return nil, sql.ErrTableNotFound.New(tblName) 44 } 45 cvSch, err := tbl.GetConstraintViolationsSchema(ctx) 46 if err != nil { 47 return nil, err 48 } 49 sqlSch, err := sqlutil.FromDoltSchema("", doltdb.DoltConstViolTablePrefix+tblName, cvSch) 50 if err != nil { 51 return nil, err 52 } 53 54 return &constraintViolationsTable{ 55 tblName: tblName, 56 root: root, 57 cvSch: cvSch, 58 sqlSch: sqlSch, 59 tbl: tbl, 60 rs: rs, 61 }, nil 62 } 63 64 // constraintViolationsTable is a sql.Table implementation that provides access to the constraint violations that exist 65 // for a user table for the old format. 66 type constraintViolationsTable struct { 67 tblName string 68 root doltdb.RootValue 69 cvSch schema.Schema 70 sqlSch sql.PrimaryKeySchema 71 tbl *doltdb.Table 72 rs RootSetter 73 } 74 75 var _ sql.Table = (*constraintViolationsTable)(nil) 76 var _ sql.DeletableTable = (*constraintViolationsTable)(nil) 77 78 // Name implements the interface sql.Table. 79 func (cvt *constraintViolationsTable) Name() string { 80 return doltdb.DoltConstViolTablePrefix + cvt.tblName 81 } 82 83 // String implements the interface sql.Table. 84 func (cvt *constraintViolationsTable) String() string { 85 return doltdb.DoltConstViolTablePrefix + cvt.tblName 86 } 87 88 // Schema implements the interface sql.Table. 89 func (cvt *constraintViolationsTable) Schema() sql.Schema { 90 return cvt.sqlSch.Schema 91 } 92 93 // Collation implements the interface sql.Table. 94 func (cvt *constraintViolationsTable) Collation() sql.CollationID { 95 return sql.Collation_Default 96 } 97 98 // Partitions implements the interface sql.Table. 99 func (cvt *constraintViolationsTable) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { 100 return index.SinglePartitionIterFromNomsMap(nil), nil 101 } 102 103 // PartitionRows implements the interface sql.Table. 104 func (cvt *constraintViolationsTable) PartitionRows(ctx *sql.Context, part sql.Partition) (sql.RowIter, error) { 105 cvMap, err := cvt.tbl.GetConstraintViolations(ctx) 106 if err != nil { 107 return nil, err 108 } 109 iter, err := cvMap.Iterator(ctx) 110 if err != nil { 111 return nil, err 112 } 113 return &constraintViolationsIter{cvt.cvSch, iter}, nil 114 } 115 116 // Deleter implements the interface sql.DeletableTable. 117 func (cvt *constraintViolationsTable) Deleter(ctx *sql.Context) sql.RowDeleter { 118 cvMap, err := cvt.tbl.GetConstraintViolations(ctx) 119 if err != nil { 120 panic(err) 121 } 122 return &constraintViolationsDeleter{cvt, cvMap.Edit()} 123 } 124 125 // constraintViolationsIter is the iterator for constraintViolationsTable. 126 type constraintViolationsIter struct { 127 dSch schema.Schema 128 iter types.MapIterator 129 } 130 131 var _ sql.RowIter = (*constraintViolationsIter)(nil) 132 133 // Next implements the interface sql.RowIter. 134 func (cvi *constraintViolationsIter) Next(ctx *sql.Context) (sql.Row, error) { 135 k, v, err := cvi.iter.NextTuple(ctx) 136 if err != nil { 137 return nil, err 138 } 139 dRow, err := row.FromNoms(cvi.dSch, k, v) 140 if err != nil { 141 return nil, err 142 } 143 return sqlutil.DoltRowToSqlRow(dRow, cvi.dSch) 144 } 145 146 // Close implements the interface sql.RowIter. 147 func (cvi *constraintViolationsIter) Close(*sql.Context) error { 148 return nil 149 } 150 151 // constraintViolationsDeleter handles deletions on the generated constraintViolationsTable. 152 type constraintViolationsDeleter struct { 153 cvt *constraintViolationsTable 154 editor *types.MapEditor 155 } 156 157 var _ sql.RowDeleter = (*constraintViolationsDeleter)(nil) 158 159 // Delete implements the interface sql.RowDeleter. 160 func (cvd *constraintViolationsDeleter) Delete(ctx *sql.Context, r sql.Row) error { 161 dRow, err := sqlutil.SqlRowToDoltRow(ctx, cvd.cvt.tbl.ValueReadWriter(), r, cvd.cvt.cvSch) 162 if err != nil { 163 return err 164 } 165 key, err := dRow.NomsMapKey(cvd.cvt.cvSch).Value(ctx) 166 if err != nil { 167 return err 168 } 169 cvd.editor.Remove(key) 170 return nil 171 } 172 173 // StatementBegin implements the interface sql.TableEditor. Currently a no-op. 174 func (cvd *constraintViolationsDeleter) StatementBegin(ctx *sql.Context) {} 175 176 // DiscardChanges implements the interface sql.TableEditor. Currently a no-op. 177 func (cvd *constraintViolationsDeleter) DiscardChanges(ctx *sql.Context, errorEncountered error) error { 178 return nil 179 } 180 181 // StatementComplete implements the interface sql.TableEditor. Currently a no-op. 182 func (cvd *constraintViolationsDeleter) StatementComplete(ctx *sql.Context) error { 183 return nil 184 } 185 186 // Close implements the interface sql.RowDeleter. 187 func (cvd *constraintViolationsDeleter) Close(ctx *sql.Context) error { 188 updatedMap, err := cvd.editor.Map(ctx) 189 if err != nil { 190 return err 191 } 192 updatedTbl, err := cvd.cvt.tbl.SetConstraintViolations(ctx, updatedMap) 193 if err != nil { 194 return err 195 } 196 updatedRoot, err := cvd.cvt.root.PutTable(ctx, doltdb.TableName{Name: cvd.cvt.tblName}, updatedTbl) 197 if err != nil { 198 return err 199 } 200 return cvd.cvt.rs.SetRoot(ctx, updatedRoot) 201 }