github.com/tobgu/qframe@v0.4.0/internal/template/column.go (about)

     1  package template
     2  
     3  // Code generated from template/column.go DO NOT EDIT
     4  
     5  import (
     6  	"fmt"
     7  	"github.com/tobgu/qframe/config/rolling"
     8  
     9  	"github.com/mauricelam/genny/generic"
    10  	"github.com/tobgu/qframe/internal/column"
    11  	"github.com/tobgu/qframe/internal/index"
    12  	"github.com/tobgu/qframe/qerrors"
    13  )
    14  
    15  type genericDataType generic.Number
    16  
    17  //go:generate genny -in=$GOFILE -out=../icolumn/column_gen.go -pkg=icolumn gen "genericDataType=int"
    18  //go:generate genny -in=$GOFILE -out=../fcolumn/column_gen.go -pkg=fcolumn gen "genericDataType=float64"
    19  //go:generate genny -in=$GOFILE -out=../bcolumn/column_gen.go -pkg=bcolumn gen "genericDataType=bool"
    20  
    21  type Column struct {
    22  	data []genericDataType
    23  }
    24  
    25  func New(d []genericDataType) Column {
    26  	return Column{data: d}
    27  }
    28  
    29  func NewConst(val genericDataType, count int) Column {
    30  	var nullVal genericDataType
    31  	data := make([]genericDataType, count)
    32  	if val != nullVal {
    33  		for i := range data {
    34  			data[i] = val
    35  		}
    36  	}
    37  
    38  	return Column{data: data}
    39  }
    40  
    41  func (c Column) fnName(name string) string {
    42  	return fmt.Sprintf("%s.%s", c.DataType(), name)
    43  }
    44  
    45  // Apply single argument function. The result may be a column
    46  // of a different type than the current column.
    47  func (c Column) Apply1(fn interface{}, ix index.Int) (interface{}, error) {
    48  	switch t := fn.(type) {
    49  	case func(genericDataType) int:
    50  		result := make([]int, len(c.data))
    51  		for _, i := range ix {
    52  			result[i] = t(c.data[i])
    53  		}
    54  		return result, nil
    55  	case func(genericDataType) float64:
    56  		result := make([]float64, len(c.data))
    57  		for _, i := range ix {
    58  			result[i] = t(c.data[i])
    59  		}
    60  		return result, nil
    61  	case func(genericDataType) bool:
    62  		result := make([]bool, len(c.data))
    63  		for _, i := range ix {
    64  			result[i] = t(c.data[i])
    65  		}
    66  		return result, nil
    67  	case func(genericDataType) *string:
    68  		result := make([]*string, len(c.data))
    69  		for _, i := range ix {
    70  			result[i] = t(c.data[i])
    71  		}
    72  		return result, nil
    73  	default:
    74  		return nil, qerrors.New(c.fnName("Apply1"), "cannot apply type %#v to column", fn)
    75  	}
    76  }
    77  
    78  // Apply double argument function to two columns. Both columns must have the
    79  // same type. The resulting column will have the same type as this column.
    80  func (c Column) Apply2(fn interface{}, s2 column.Column, ix index.Int) (column.Column, error) {
    81  	ss2, ok := s2.(Column)
    82  	if !ok {
    83  		return Column{}, qerrors.New(c.fnName("Apply2"), "invalid column type: %s", s2.DataType())
    84  	}
    85  
    86  	t, ok := fn.(func(genericDataType, genericDataType) genericDataType)
    87  	if !ok {
    88  		return Column{}, qerrors.New("Apply2", "invalid function type: %#v", fn)
    89  	}
    90  
    91  	result := make([]genericDataType, len(c.data))
    92  	for _, i := range ix {
    93  		result[i] = t(c.data[i], ss2.data[i])
    94  	}
    95  
    96  	return New(result), nil
    97  }
    98  
    99  func (c Column) subset(index index.Int) Column {
   100  	data := make([]genericDataType, len(index))
   101  	for i, ix := range index {
   102  		data[i] = c.data[ix]
   103  	}
   104  
   105  	return Column{data: data}
   106  }
   107  
   108  func (c Column) Subset(index index.Int) column.Column {
   109  	return c.subset(index)
   110  }
   111  
   112  func (c Column) Comparable(reverse, equalNull, nullLast bool) column.Comparable {
   113  	result := Comparable{data: c.data, ltValue: column.LessThan, gtValue: column.GreaterThan, nullLtValue: column.LessThan, nullGtValue: column.GreaterThan, equalNullValue: column.NotEqual}
   114  	if reverse {
   115  		result.ltValue, result.nullLtValue, result.gtValue, result.nullGtValue =
   116  			result.gtValue, result.nullGtValue, result.ltValue, result.nullLtValue
   117  	}
   118  
   119  	if nullLast {
   120  		result.nullLtValue, result.nullGtValue = result.nullGtValue, result.nullLtValue
   121  	}
   122  
   123  	if equalNull {
   124  		result.equalNullValue = column.Equal
   125  	}
   126  
   127  	return result
   128  }
   129  
   130  func (c Column) String() string {
   131  	return fmt.Sprintf("%v", c.data)
   132  }
   133  
   134  func (c Column) Len() int {
   135  	return len(c.data)
   136  }
   137  
   138  func (c Column) Aggregate(indices []index.Int, fn interface{}) (column.Column, error) {
   139  	var actualFn func([]genericDataType) genericDataType
   140  	var ok bool
   141  
   142  	switch t := fn.(type) {
   143  	case string:
   144  		actualFn, ok = aggregations[t]
   145  		if !ok {
   146  			return nil, qerrors.New(c.fnName("Aggregate"), "aggregation function %c is not defined for column", fn)
   147  		}
   148  	case func([]genericDataType) genericDataType:
   149  		actualFn = t
   150  	default:
   151  		return nil, qerrors.New(c.fnName("Aggregate"), "invalid aggregation function type: %v", t)
   152  	}
   153  
   154  	data := make([]genericDataType, 0, len(indices))
   155  	var buf []genericDataType
   156  	for _, ix := range indices {
   157  		subS := c.subsetWithBuf(ix, &buf)
   158  		data = append(data, actualFn(subS.data))
   159  	}
   160  
   161  	return Column{data: data}, nil
   162  }
   163  
   164  func (c Column) subsetWithBuf(index index.Int, buf *[]genericDataType) Column {
   165  	if cap(*buf) < len(index) {
   166  		*buf = make([]genericDataType, 0, len(index))
   167  	}
   168  
   169  	data := (*buf)[:0]
   170  	for _, ix := range index {
   171  		data = append(data, c.data[ix])
   172  	}
   173  
   174  	return Column{data: data}
   175  }
   176  
   177  func (c Column) View(ix index.Int) View {
   178  	return View{data: c.data, index: ix}
   179  }
   180  
   181  func (c Column) Rolling(fn interface{}, ix index.Int, config rolling.Config) (column.Column, error) {
   182  	return c, nil
   183  }
   184  
   185  type Comparable struct {
   186  	data           []genericDataType
   187  	ltValue        column.CompareResult
   188  	nullLtValue    column.CompareResult
   189  	gtValue        column.CompareResult
   190  	nullGtValue    column.CompareResult
   191  	equalNullValue column.CompareResult
   192  }
   193  
   194  // View is a view into a column that allows access to individual elements by index.
   195  type View struct {
   196  	data  []genericDataType
   197  	index index.Int
   198  }
   199  
   200  // ItemAt returns the value at position i.
   201  func (v View) ItemAt(i int) genericDataType {
   202  	return v.data[v.index[i]]
   203  }
   204  
   205  // Len returns the column length.
   206  func (v View) Len() int {
   207  	return len(v.index)
   208  }
   209  
   210  // Slice returns a slice containing a copy of the column data.
   211  func (v View) Slice() []genericDataType {
   212  	// TODO: This forces an alloc, as an alternative a slice could be taken
   213  	//       as input that can be (re)used by the client. Are there use cases
   214  	//       where this would actually make sense?
   215  	result := make([]genericDataType, v.Len())
   216  	for i, j := range v.index {
   217  		result[i] = v.data[j]
   218  	}
   219  	return result
   220  }