github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/dtables/commits_table.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  	"fmt"
    19  	"io"
    20  
    21  	"github.com/dolthub/go-mysql-server/sql"
    22  	"github.com/dolthub/go-mysql-server/sql/types"
    23  
    24  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    25  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    26  	"github.com/dolthub/dolt/go/libraries/doltcore/sqle/index"
    27  	"github.com/dolthub/dolt/go/store/datas"
    28  	"github.com/dolthub/dolt/go/store/hash"
    29  )
    30  
    31  const commitsDefaultRowCount = 10
    32  
    33  // CommitsTable is a sql.Table that implements a system table which
    34  // shows the combined commit log for all branches in the repo.
    35  type CommitsTable struct {
    36  	dbName string
    37  	ddb    *doltdb.DoltDB
    38  }
    39  
    40  var _ sql.Table = (*CommitsTable)(nil)
    41  var _ sql.IndexAddressable = (*CommitsTable)(nil)
    42  var _ sql.StatisticsTable = (*CommitsTable)(nil)
    43  
    44  // NewCommitsTable creates a CommitsTable
    45  func NewCommitsTable(_ *sql.Context, dbName string, ddb *doltdb.DoltDB) sql.Table {
    46  	return &CommitsTable{dbName: dbName, ddb: ddb}
    47  }
    48  
    49  func (dt *CommitsTable) DataLength(ctx *sql.Context) (uint64, error) {
    50  	numBytesPerRow := schema.SchemaAvgLength(dt.Schema())
    51  	numRows, _, err := dt.RowCount(ctx)
    52  	if err != nil {
    53  		return 0, err
    54  	}
    55  	return numBytesPerRow * numRows, nil
    56  }
    57  
    58  func (dt *CommitsTable) RowCount(_ *sql.Context) (uint64, bool, error) {
    59  	return commitsDefaultRowCount, false, nil
    60  }
    61  
    62  // Name is a sql.Table interface function which returns the name of the table.
    63  func (dt *CommitsTable) Name() string {
    64  	return doltdb.CommitsTableName
    65  }
    66  
    67  // String is a sql.Table interface function which returns the name of the table.
    68  func (dt *CommitsTable) String() string {
    69  	return doltdb.CommitsTableName
    70  }
    71  
    72  // Schema is a sql.Table interface function that gets the sql.Schema of the commits system table.
    73  func (dt *CommitsTable) Schema() sql.Schema {
    74  	return []*sql.Column{
    75  		{Name: "commit_hash", Type: types.Text, Source: doltdb.CommitsTableName, PrimaryKey: true, DatabaseSource: dt.dbName},
    76  		{Name: "committer", Type: types.Text, Source: doltdb.CommitsTableName, PrimaryKey: false, DatabaseSource: dt.dbName},
    77  		{Name: "email", Type: types.Text, Source: doltdb.CommitsTableName, PrimaryKey: false, DatabaseSource: dt.dbName},
    78  		{Name: "date", Type: types.Datetime, Source: doltdb.CommitsTableName, PrimaryKey: false, DatabaseSource: dt.dbName},
    79  		{Name: "message", Type: types.Text, Source: doltdb.CommitsTableName, PrimaryKey: false, DatabaseSource: dt.dbName},
    80  	}
    81  }
    82  
    83  // Collation implements the sql.Table interface.
    84  func (dt *CommitsTable) Collation() sql.CollationID {
    85  	return sql.Collation_Default
    86  }
    87  
    88  // Partitions is a sql.Table interface function that returns a partition
    89  // of the data. Currently the data is unpartitioned.
    90  func (dt *CommitsTable) Partitions(*sql.Context) (sql.PartitionIter, error) {
    91  	return index.SinglePartitionIterFromNomsMap(nil), nil
    92  }
    93  
    94  // PartitionRows is a sql.Table interface function that gets a row iterator for a partition.
    95  func (dt *CommitsTable) PartitionRows(ctx *sql.Context, p sql.Partition) (sql.RowIter, error) {
    96  	switch p := p.(type) {
    97  	case *doltdb.CommitPart:
    98  		return sql.RowsToRowIter(formatCommitTableRow(p.Hash(), p.Meta())), nil
    99  	default:
   100  		return NewCommitsRowItr(ctx, dt.ddb)
   101  	}
   102  }
   103  
   104  // GetIndexes implements sql.IndexAddressable
   105  func (dt *CommitsTable) GetIndexes(ctx *sql.Context) ([]sql.Index, error) {
   106  	return index.DoltCommitIndexes(dt.dbName, dt.Name(), dt.ddb, true)
   107  }
   108  
   109  // IndexedAccess implements sql.IndexAddressable
   110  func (dt *CommitsTable) IndexedAccess(lookup sql.IndexLookup) sql.IndexedTable {
   111  	nt := *dt
   112  	return &nt
   113  }
   114  
   115  func (dt *CommitsTable) PreciseMatch() bool {
   116  	return true
   117  }
   118  
   119  func (dt *CommitsTable) LookupPartitions(ctx *sql.Context, lookup sql.IndexLookup) (sql.PartitionIter, error) {
   120  	if lookup.Index.ID() == index.CommitHashIndexId {
   121  		hashStrs, ok := index.LookupToPointSelectStr(lookup)
   122  		if !ok {
   123  			return nil, fmt.Errorf("failed to parse commit lookup ranges: %s", sql.DebugString(lookup.Ranges))
   124  		}
   125  		hashes, commits, metas := index.HashesToCommits(ctx, dt.ddb, hashStrs, nil, false)
   126  		if len(hashes) == 0 {
   127  			return sql.PartitionsToPartitionIter(), nil
   128  		}
   129  
   130  		return doltdb.NewCommitSlicePartitionIter(hashes, commits, metas), nil
   131  	}
   132  
   133  	return dt.Partitions(ctx)
   134  }
   135  
   136  // CommitsRowItr is a sql.RowItr which iterates over each commit as if it's a row in the table.
   137  type CommitsRowItr struct {
   138  	itr doltdb.CommitItr
   139  }
   140  
   141  // NewCommitsRowItr creates a CommitsRowItr from the current environment.
   142  func NewCommitsRowItr(ctx *sql.Context, ddb *doltdb.DoltDB) (CommitsRowItr, error) {
   143  	itr, err := doltdb.CommitItrForAllBranches(ctx, ddb)
   144  	if err != nil {
   145  		return CommitsRowItr{}, err
   146  	}
   147  
   148  	return CommitsRowItr{itr: itr}, nil
   149  }
   150  
   151  // Next retrieves the next row. It will return io.EOF if it's the last row.
   152  // After retrieving the last row, Close will be automatically closed.
   153  func (itr CommitsRowItr) Next(ctx *sql.Context) (sql.Row, error) {
   154  	h, optCmt, err := itr.itr.Next(ctx)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	cm, ok := optCmt.ToCommit()
   159  	if !ok {
   160  		return nil, io.EOF
   161  	}
   162  
   163  	meta, err := cm.GetCommitMeta(ctx)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  
   168  	return formatCommitTableRow(h, meta), nil
   169  }
   170  
   171  // Close closes the iterator.
   172  func (itr CommitsRowItr) Close(*sql.Context) error {
   173  	return nil
   174  }
   175  
   176  func formatCommitTableRow(h hash.Hash, meta *datas.CommitMeta) sql.Row {
   177  	return sql.NewRow(h.String(), meta.Name, meta.Email, meta.Time(), meta.Description)
   178  }