github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/table/composite_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 "io" 20 21 "github.com/dolthub/dolt/go/libraries/doltcore/row" 22 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 23 ) 24 25 // CompositeTableReader is a TableReader implementation which will concatenate the results 26 // of multiple TableReader instances into a single set of results. 27 type CompositeTableReader struct { 28 sch schema.Schema 29 readers []TableReadCloser 30 idx int 31 } 32 33 // NewCompositeTableReader creates a new CompositeTableReader instance from a slice of TableReadClosers. 34 func NewCompositeTableReader(readers []TableReadCloser) (*CompositeTableReader, error) { 35 if len(readers) == 0 { 36 panic("nothing to iterate") 37 } 38 39 sch := readers[0].GetSchema() 40 for i := 1; i < len(readers); i++ { 41 otherSch := readers[i].GetSchema() 42 if !schema.SchemasAreEqual(sch, otherSch) { 43 panic("readers must have the same schema") 44 } 45 } 46 47 return &CompositeTableReader{sch: sch, readers: readers, idx: 0}, nil 48 } 49 50 // GetSchema gets the schema of the rows that this reader will return 51 func (rd *CompositeTableReader) GetSchema() schema.Schema { 52 return rd.sch 53 } 54 55 // ReadRow reads a row from a table. If there is a bad row the returned error will be non nil, and calling 56 // IsBadRow(err) will be return true. This is a potentially non-fatal error and callers can decide if they want to 57 // continue on a bad row, or fail. 58 func (rd *CompositeTableReader) ReadRow(ctx context.Context) (row.Row, error) { 59 for rd.idx < len(rd.readers) { 60 r, err := rd.readers[rd.idx].ReadRow(ctx) 61 62 if err == io.EOF { 63 rd.idx++ 64 continue 65 } else if err != nil { 66 return nil, err 67 } 68 69 return r, nil 70 } 71 72 return nil, io.EOF 73 } 74 75 // VerifySchema checks that the incoming schema matches the schema from the existing table 76 func (rd *CompositeTableReader) VerifySchema(outSch schema.Schema) (bool, error) { 77 return schema.VerifyInSchema(rd.sch, outSch) 78 } 79 80 // Close should release resources being held 81 func (rd *CompositeTableReader) Close(ctx context.Context) error { 82 var firstErr error 83 for _, rdr := range rd.readers { 84 err := rdr.Close(ctx) 85 86 if firstErr == nil { 87 firstErr = err 88 } 89 } 90 91 return firstErr 92 }