eskuel

package module
v0.0.0-...-32af369 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2021 License: BSD-3-Clause Imports: 8 Imported by: 0

README

eskuel : manipulate data SQL-like

Overview GoDoc

Package eskuel provides a simple way to store and manipulate data in tables of rows. Those tables allow slicing and dicing the data using SQL-like methods in a straight forward way.

Supported constructs:

  • Select - pick a subset of the table fields
  • Filter - extract a subset of rows from a table
  • Update - update rows in place
  • Transform - construct a new table by transforming data from an existing table
  • Join* - join 2 tables with a given criteria
  • Group - group rows
  • Sort - sort rows

All operations except Update are copy on write.

Install

go get github.com/pierrec/eskuel

Example

See more examples in the examples directory.

// Populate the tables from csv data.
t1, _ := NewFromString(`
id,customer
123,customer1
456,customer2
789,customer3
`)
t2, _ := NewFromString(`
cust_id,order
456,orderxx67
123,orderzz78
456,order789
456,order900
123,orderaa34
`)
// Join the tables.
res := t1.
	JoinInner(t2, func(r, on Row) bool {
		// Match on the same id.
		return r[0].Value == on[0].Value
	}).
	Select(func(c Column) bool {
		// Remove the id columns.
		return !strings.Contains(c.Name, "id")
	})
// res now contains:
// customer,order
// customer1,orderzz78
// customer1,orderaa34
// customer2,orderxx67
// customer2,order789
// customer2,order900
bts, _ := res.MarshalText()
fmt.Println(string(bts))

Documentation

Overview

Package eskuel provides a way to easily manipulate rows of data à la SQL.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Null = Value{^0, "NULL"}

Null defines the NULL value.

Functions

This section is empty.

Types

type CSVReader

type CSVReader interface {
	Read() ([]string, error)
}

CSVReader is the interface used to parse CSV data (also supported by encoding/csv.Reader).

type Column

type Column struct {
	// Name uniquely identifies a Column.
	Name string
	// Key defines if the column is part of the table key.
	// Rows are uniquely identified by the combination of
	// all column keys.
	Key bool
	// Column position in the schema. Automatically set.
	Position int
	// StringValue defines the methods to marshal and unmarshal a string
	// from and to a Value. They are typically used when processing CSV
	// data but there is no restriction on their usage.
	// The interface carries across a modified Table such as Table.Select.
	StringValue interface {
		MarshalString(Value) (string, error)
		UnmarshalString(string) (Value, error)
	}
}

Column defines a table column.

type Row

type Row []Value

Row is a set of Value representing a row. Use Table.Row to create one.

func (Row) Close

func (r Row) Close()

Close returns the row to the pool.

type SubTable

type SubTable struct {
	// contains filtered or unexported fields
}

SubTable is a subset of a table columns. Its data is backed by the table's. A nil SubTable behaves as a Table. It is used to only supply the relevant columns when manipulating the table data, yielding better performance.

func NewSubTable

func NewSubTable(t *Table, f func(Column) bool) *SubTable

func (*SubTable) Columns

func (s *SubTable) Columns() []Column

Columns returns the columns making up s.

type Table

type Table struct {
	// contains filtered or unexported fields
}

Table holds a set of Rows.

func New

func New(schema ...Column) *Table

New instantiates a new table with the supplied schema. An empty schema panics.

Example
package main

import (
	"fmt"

	"git.sr.ht/~pierrec/eskuel"
	"git.sr.ht/~pierrec/eskuel/values"
)

func main() {
	intCol := eskuel.Column{Name: "id", StringValue: values.Int64{}}
	strCol := eskuel.Column{Name: "name", StringValue: values.String{}}
	tab := eskuel.New(intCol, strCol)
	tab.Insert(
		eskuel.Row{{Int: 1}, {String: "a"}},
		eskuel.Row{{Int: 2}, {String: "b"}},
	)
	for _, r := range tab.Rows() {
		fmt.Println(r[0].Int, r[1].String)
	}
}
Output:

1 a
2 b

func NewFromCSV

func NewFromCSV(from CSVReader, init func([]Column) error) (*Table, error)

NewFromCSV creates a table populated with the data from the csv source. The first line of the csv data must contain the table schema. The init function is used to setup the Column's StringValue interface. It can be left nil if the StringValue interface does not need to be instantiated.

See Table.FromCSV for usage.

func (*Table) ColumnAppend

func (t *Table) ColumnAppend(f func(Row), columns ...Column)

ColumnAppend appends a set of new columns to the table's schema. Use ColumnMove to place them at the desired locations. Values for the new column are set by f or to Null if f is nil.

Rows having duplicate keys are deleted, only one of them being kept.

func (*Table) ColumnMove

func (t *Table) ColumnMove(col Column, pos int)

ColumnMove moves col to a new position. If pos < 0, then the column is moved at the front. If pos > len(Columns), then the column is moved at the end.

func (*Table) ColumnRemove

func (t *Table) ColumnRemove(columns ...Column)

ColumnRemove removes the provided columns from t. If all columns get removed, the table schema is left unchanged.

func (*Table) Columns

func (t *Table) Columns() []Column

Columns returns the table's schema.

func (*Table) Count

func (t *Table) Count() int

Count returns the number of rows in the table.

func (*Table) Delete

func (t *Table) Delete(sub *SubTable, f func(r Row) (delete bool)) int

Delete removes rows in t matched by f and returns the number of deleted rows. Note that row order is not preserved.

func (*Table) FindRow

func (t *Table) FindRow(f func(Row) bool) Row

FindRow returns the first row matching f or nil.

func (*Table) FromCSV

func (t *Table) FromCSV(from CSVReader) error

FromCSV adds rows to t provided by the csv reader. Strings "NULL", "null" and "Null" are only converted to Null if the StringValue for the column being read is not set.

func (*Table) FromView

func (t *Table) FromView(v *View)

FromView fills t with the rows in v.

func (*Table) Group

func (t *Table) Group(sub *SubTable, gt *Table, trans func(in, out Row))

Group populates into with rows grouped by keys and built with trans.

func (*Table) Insert

func (t *Table) Insert(rows ...Row)

Insert adds new rows to the table.

func (*Table) JoinFull

func (t *Table) JoinFull(on *Table, subon *SubTable, f func(r, on Row) bool) *Table

JoinFull returns the full joined table of t and on.

func (*Table) JoinInner

func (t *Table) JoinInner(on *Table, subon *SubTable, f func(r, on Row) bool) *Table

JoinInner returns the inner joined table of t and on.

func (*Table) JoinLeft

func (t *Table) JoinLeft(on *Table, subon *SubTable, f func(r, on Row) bool) *Table

JoinLeft returns the left joined table of t and on.

func (*Table) JoinOuterLeft

func (t *Table) JoinOuterLeft(on *Table, subon *SubTable, f func(r, on Row) bool) *Table

JoinOuterLeft returns the outer left joined table of t and on.

func (*Table) MarshalText

func (t *Table) MarshalText() (text []byte, err error)

func (*Table) Row

func (t *Table) Row() Row

Row creates a new Row.

func (*Table) Rows

func (t *Table) Rows() []Row

func (*Table) Select

func (t *Table) Select(f func(Row) bool, schema ...ViewColumn) *View

Select returns a view on the table. An empty schema selects all columns from the table. Use f to filter rows. If unset, all rows are selected. If schema is empty, all columns from t are selected, unchanged.

func (*Table) Slice

func (t *Table) Slice(i int, j int) *Table

Slice returns a table containing the rows in [i, j[.

func (*Table) Sort

func (t *Table) Sort(less func(a, b Row) bool)

Sort orders the table rows based on the given ordering function less.

func (*Table) ToCSV

func (t *Table) ToCSV(w io.Writer) error

func (*Table) UnionWith

func (t *Table) UnionWith(tt *Table)

UnionWith merges the data from tt into t.

t and tt must have the same schema (same column length and names) leaving t unchanged if that is not the case.

Example
package main

import (
	"fmt"

	"git.sr.ht/~pierrec/eskuel"
)

func main() {
	// UnionWith can be used to make a full copy of tab.
	columns := []eskuel.Column{{Name: "c1"}, {Name: "c2"}}
	tab := eskuel.New(columns...)
	tab.Insert(
		eskuel.Row{{Int: 1}, {String: "a"}},
		eskuel.Row{{Int: 2}, {String: "b"}},
	)
	dup := eskuel.New(columns...)
	dup.UnionWith(tab)

	for _, r := range dup.Rows() {
		fmt.Println(r[0].Int, r[1].String)
	}
}
Output:

1 a
2 b

func (*Table) UnmarshalText

func (t *Table) UnmarshalText(text []byte) error

func (*Table) Update

func (t *Table) Update(sub *SubTable, f func(r Row) (stop bool)) int

Update updates t's rows with the values in r after f is called. Update returns the number of updated rows.

Any update to key columns is ignored.

type Value

type Value struct {
	Int    int64  // Int is used to store 8 bytes, typically a number.
	String string // String is used to store everything else.
}

Value stores a row column value in one of the required type.

NB. no type checking is performed on columns.

type View

type View struct {
	// contains filtered or unexported fields
}

func (*View) Columns

func (v *View) Columns() []Column

func (*View) Next

func (v *View) Next() bool

Next prepares the view to return the next row, returning whether or not there is one.

func (*View) Reset

func (v *View) Reset()

func (*View) Row

func (v *View) Row() Row

Row returns the row prepared by Next.

type ViewColumn

type ViewColumn struct {
	Name      string // mapped to a table schema if Transform is nil
	Transform func(Row) Value
	// contains filtered or unexported fields
}

Directories

Path Synopsis
cmd
examples
csv
Parse an unconventional CSV data file into a table.
Parse an unconventional CSV data file into a table.
join
Joining data from 2 tables.
Joining data from 2 tables.
Package values provides typical implementations of eskuel.Value marshaller interface.
Package values provides typical implementations of eskuel.Value marshaller interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL