github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/table/table_reader.go (about)

     1  // Copyright 2020 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 table
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"io"
    21  
    22  	"github.com/dolthub/go-mysql-server/sql"
    23  
    24  	"github.com/dolthub/dolt/go/libraries/doltcore/row"
    25  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    26  )
    27  
    28  // Reader is an interface for reading rows from a table
    29  type Reader interface {
    30  	// GetSchema gets the schema of the rows that this reader will return
    31  	GetSchema() schema.Schema
    32  
    33  	// ReadRow reads a row from a table.  If there is a bad row the returned error will be non nil, and calling
    34  	// IsBadRow(err) will be return true. This is a potentially non-fatal error and callers can decide if they want to
    35  	// continue on a bad row, or fail.
    36  	ReadRow(ctx context.Context) (row.Row, error)
    37  }
    38  
    39  // Closer is an interface for a writer that can be closed to release resources
    40  type Closer interface {
    41  	// Close should release resources being held
    42  	Close(ctx context.Context) error
    43  }
    44  
    45  // ReadCloser is an interface for reading rows from a table, that can be closed.
    46  type ReadCloser interface {
    47  	Reader
    48  	Closer
    49  }
    50  
    51  type SqlRowReader interface {
    52  	ReadCloser
    53  
    54  	ReadSqlRow(ctx context.Context) (sql.Row, error)
    55  }
    56  
    57  // SqlTableReader is a Reader that can read rows as sql.Row.
    58  type SqlTableReader interface {
    59  	// GetSchema gets the schema of the rows that this reader will return
    60  	GetSchema() schema.Schema
    61  
    62  	// ReadSqlRow reads a row from a table as go-mysql-server sql.Row.
    63  	ReadSqlRow(ctx context.Context) (sql.Row, error)
    64  }
    65  
    66  // PipeRows will read a row from given TableReader and write it to the provided RowWriter.  It will do this
    67  // for every row until the TableReader's ReadRow method returns io.EOF or encounters an error in either reading
    68  // or writing.  The caller will need to handle closing the tables as necessary. If contOnBadRow is true, errors reading
    69  // or writing will be ignored and the pipe operation will continue.
    70  //
    71  // Returns a tuple: (number of rows written, number of errors ignored, error). In the case that err is non-nil, the
    72  // row counter fields in the tuple will be set to -1.
    73  func PipeRows(ctx context.Context, rd SqlRowReader, wr SqlRowWriter, contOnBadRow bool) (int, int, error) {
    74  	var numBad, numGood int
    75  	for {
    76  		r, err := rd.ReadSqlRow(ctx)
    77  
    78  		if err != nil && err != io.EOF {
    79  			if IsBadRow(err) && contOnBadRow {
    80  				numBad++
    81  				continue
    82  			}
    83  
    84  			return -1, -1, err
    85  		} else if err == io.EOF && r == nil {
    86  			break
    87  		} else if r == nil {
    88  			// row equal to nil should
    89  			return -1, -1, errors.New("reader returned nil row with err==nil")
    90  		}
    91  
    92  		err = wr.WriteSqlRow(ctx, r)
    93  
    94  		if err != nil {
    95  			return -1, -1, err
    96  		} else {
    97  			numGood++
    98  		}
    99  	}
   100  
   101  	return numGood, numBad, nil
   102  }