github.com/octohelm/storage@v0.0.0-20240516030302-1ac2cc1ea347/pkg/sqlbuilder/def_column.go (about)

     1  package sqlbuilder
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  
     9  	"github.com/octohelm/x/types"
    10  )
    11  
    12  type Column interface {
    13  	SqlExpr
    14  	TableDefinition
    15  	Def() ColumnDef
    16  	Expr(query string, args ...any) *Ex
    17  	Of(table Table) Column
    18  	With(optionFns ...ColOptionFunc) Column
    19  	MatchName(name string) bool
    20  	Name() string
    21  	FieldName() string
    22  }
    23  
    24  type ColumnSetter interface {
    25  	SetFieldName(name string)
    26  	SetColumnDef(def ColumnDef)
    27  }
    28  
    29  type ColOptionFunc func(c ColumnSetter)
    30  
    31  func ColField(fieldName string) ColOptionFunc {
    32  	return func(c ColumnSetter) {
    33  		c.SetFieldName(fieldName)
    34  	}
    35  }
    36  
    37  func ColDef(def ColumnDef) ColOptionFunc {
    38  	return func(c ColumnSetter) {
    39  		c.SetColumnDef(def)
    40  	}
    41  }
    42  
    43  func ColTypeOf(v any, tagValue string) ColOptionFunc {
    44  	return func(c ColumnSetter) {
    45  		c.SetColumnDef(*ColumnDefFromTypeAndTag(types.FromRType(reflect.TypeOf(v)), tagValue))
    46  	}
    47  }
    48  
    49  func Col(name string, fns ...ColOptionFunc) Column {
    50  	c := &column[any]{
    51  		name: strings.ToLower(name),
    52  		def:  ColumnDef{},
    53  	}
    54  
    55  	for i := range fns {
    56  		fns[i](c)
    57  	}
    58  
    59  	return c
    60  }
    61  
    62  var _ TableDefinition = (*column[any])(nil)
    63  
    64  type column[T any] struct {
    65  	name      string
    66  	fieldName string
    67  	table     Table
    68  	def       ColumnDef
    69  }
    70  
    71  func (c *column[T]) SetFieldName(name string) {
    72  	c.fieldName = name
    73  }
    74  
    75  func (c *column[T]) SetColumnDef(def ColumnDef) {
    76  	c.def = def
    77  }
    78  
    79  func (c *column[T]) FieldName() string {
    80  	return c.fieldName
    81  }
    82  
    83  func (c *column[T]) Def() ColumnDef {
    84  	return c.def
    85  }
    86  
    87  func (c *column[T]) With(optionFns ...ColOptionFunc) Column {
    88  	cc := &column[T]{
    89  		name:      c.name,
    90  		fieldName: c.fieldName,
    91  		table:     c.table,
    92  		def:       c.def,
    93  	}
    94  
    95  	for i := range optionFns {
    96  		optionFns[i](c)
    97  	}
    98  
    99  	return cc
   100  }
   101  
   102  func (c *column[T]) MatchName(name string) bool {
   103  	if name == "" {
   104  		return false
   105  	}
   106  
   107  	// first child upper should be fieldName
   108  	if name[0] >= 'A' && name[0] <= 'Z' {
   109  		return c.fieldName == name
   110  	}
   111  
   112  	return c.name == name
   113  }
   114  
   115  func (c *column[T]) T() Table {
   116  	return c.table
   117  }
   118  
   119  func (c *column[T]) Name() string {
   120  	return c.name
   121  }
   122  
   123  func (c column[T]) Of(table Table) Column {
   124  	return &column[T]{
   125  		table:     table,
   126  		name:      c.name,
   127  		fieldName: c.fieldName,
   128  		def:       c.def,
   129  	}
   130  }
   131  
   132  func (c *column[T]) IsNil() bool {
   133  	return c == nil
   134  }
   135  
   136  func (c *column[T]) Ex(ctx context.Context) *Ex {
   137  	toggles := TogglesFromContext(ctx)
   138  	if toggles.Is(ToggleMultiTable) {
   139  		if c.table == nil {
   140  			panic(fmt.Errorf("table of %s is not defined", c.name))
   141  		}
   142  		if toggles.Is(ToggleNeedAutoAlias) {
   143  			return Expr("?.? AS ?", c.table, Expr(c.name), Expr(fmt.Sprintf("%s__%s", c.table.TableName(), c.name))).Ex(ctx)
   144  		}
   145  		return Expr("?.?", c.table, Expr(c.name)).Ex(ctx)
   146  	}
   147  	return ExactlyExpr(c.name).Ex(ctx)
   148  }
   149  
   150  func (c *column[T]) Expr(query string, args ...any) *Ex {
   151  	n := len(args)
   152  	e := Expr("")
   153  	e.Grow(n)
   154  
   155  	qc := 0
   156  
   157  	for _, key := range []byte(query) {
   158  		switch key {
   159  		case '#':
   160  			e.WriteExpr(c)
   161  		case '?':
   162  			e.WriteQueryByte(key)
   163  			if n > qc {
   164  				e.AppendArgs(args[qc])
   165  				qc++
   166  			}
   167  		default:
   168  			e.WriteQueryByte(key)
   169  		}
   170  	}
   171  
   172  	return e
   173  }
   174  
   175  func (c *column[T]) By(ops ...ColumnValueExpr[T]) Assignment {
   176  	if len(ops) == 0 {
   177  		return nil
   178  	}
   179  	values := make([]any, len(ops))
   180  	for i := range ops {
   181  		values[i] = ops[i](c)
   182  	}
   183  	return ColumnsAndValues(c, values...)
   184  }
   185  
   186  func (c *column[T]) V(operator ColumnValueExpr[T]) SqlExpr {
   187  	return operator(c)
   188  }