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  }