Skip to content

Commit

Permalink
Add text input feature
Browse files Browse the repository at this point in the history
  • Loading branch information
noborus committed Nov 28, 2024
1 parent 99a9513 commit bc0e97a
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 0 deletions.
65 changes: 65 additions & 0 deletions input_text.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package trdsql

import (
"bufio"
"io"
"strings"
)

// TextReader provides a reader for text format.
type TextReader struct {
reader *bufio.Reader
num int
maxNum int
}

// NewTextReader returns a new TextReader.
func NewTextReader(reader io.Reader, opts *ReadOpts) (*TextReader, error) {
r := &TextReader{
reader: bufio.NewReader(reader),
}

if opts.InSkip > 0 {
skipRead(r, opts.InSkip)
}

if opts.InLimitRead {
r.maxNum = opts.InPreRead
}
return r, nil
}

// Names returns column names.
func (r *TextReader) Names() ([]string, error) {
return []string{"text"}, nil
}

// Types returns column types.
func (r *TextReader) Types() ([]string, error) {
return []string{"text"}, nil
}

// PreReadRow returns pre-read rows.
func (r *TextReader) PreReadRow() [][]any {
return nil
}

// ReadRow reads a row.
func (r *TextReader) ReadRow([]any) ([]any, error) {
var builder strings.Builder
for {
if r.maxNum > 0 && r.num >= r.maxNum {
return []any{""}, io.EOF
}
line, isPrefix, err := r.reader.ReadLine()
if err != nil {
return []any{""}, err
}
builder.Write(line)
if isPrefix {
continue
}
r.num++
return []any{builder.String()}, nil
}
}
101 changes: 101 additions & 0 deletions input_text_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package trdsql

import (
"io"
"path/filepath"
"reflect"
"strings"
"testing"
)

func TestNewTextReader(t *testing.T) {
type args struct {
reader io.Reader
opts *ReadOpts
}
tests := []struct {
name string
args args
}{
{
name: "test1",
args: args{
reader: strings.NewReader("a\nb\nc\n"),
opts: NewReadOpts(),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewTextReader(tt.args.reader, tt.args.opts)
if err != nil {
t.Fatal(err)
}
names, err := got.Names()
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(names, []string{"text"}) {
t.Errorf("TextReader.Names() != text %v", names)
}
types, err := got.Types()
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(types, []string{"text"}) {
t.Errorf("TextReader.Types() != text %v", types)
}
})
}
}

func TestTextReaderFile(t *testing.T) {
tests := []struct {
name string
fileName string
opts *ReadOpts
want []any
wantErr bool
}{
{
name: "test.csv",
fileName: "test.csv",
opts: NewReadOpts(),
want: []any{"1,Orange"},
wantErr: false,
},
{
name: "test.csv2",
fileName: "test.csv",
opts: &ReadOpts{InSkip: 1},
want: []any{"2,Melon"},
wantErr: false,
},
{
name: "test.csv3",
fileName: "test.csv",
opts: &ReadOpts{InLimitRead: true, InPreRead: 1},
want: []any{"1,Orange"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
file, err := singleFileOpen(filepath.Join(dataDir, tt.fileName))
if err != nil {
t.Error(err)
}
r, err := NewTextReader(file, tt.opts)
if err != nil {
t.Fatal(err)
}
got, err := r.ReadRow(nil)
if (err != nil) != tt.wantErr {
t.Errorf("TextReader.ReadRow() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("TextReader.ReadRow() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit bc0e97a

Please sign in to comment.