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

     1  package sqlbuilder
     2  
     3  import (
     4  	"bytes"
     5  	"container/list"
     6  	"context"
     7  	"fmt"
     8  	"sort"
     9  	"text/scanner"
    10  )
    11  
    12  func ColumnsAndValuesByFieldValues(t Table, fieldValues FieldValues) (cols ColumnCollection, args []interface{}) {
    13  	fieldNames := make([]string, 0)
    14  	for fieldName := range fieldValues {
    15  		fieldNames = append(fieldNames, fieldName)
    16  	}
    17  
    18  	sort.Strings(fieldNames)
    19  
    20  	cols = Cols()
    21  
    22  	for _, fieldName := range fieldNames {
    23  		if col := t.F(fieldName); col != nil {
    24  			cols.(ColumnCollectionManger).AddCol(col)
    25  			args = append(args, fieldValues[fieldName])
    26  		}
    27  	}
    28  	return
    29  }
    30  
    31  func AssignmentsByFieldValues(t Table, fieldValues FieldValues) (assignments Assignments) {
    32  	for fieldName, value := range fieldValues {
    33  		col := t.F(fieldName)
    34  		if col != nil {
    35  			assignments = append(assignments, CastCol[any](col).By(Value(value)))
    36  		}
    37  	}
    38  	return
    39  }
    40  
    41  type TableDefinition interface {
    42  	T() Table
    43  }
    44  
    45  type TableExprParse interface {
    46  	Expr(query string, args ...any) *Ex
    47  }
    48  
    49  type TableWithTableName interface {
    50  	WithTableName(name string) Table
    51  }
    52  
    53  type Table interface {
    54  	SqlExpr
    55  
    56  	// TableName of table
    57  	TableName() string
    58  
    59  	// K
    60  	// get index by key name
    61  	// primaryKey could be use `pk`
    62  	K(k string) Key
    63  	// F
    64  	// get col by col name or struct field names
    65  	F(name string) Column
    66  
    67  	// Cols
    68  	// get cols by col names or struct field name
    69  	Cols(names ...string) ColumnCollection
    70  
    71  	// Keys
    72  	// get indexes by index names
    73  	Keys(names ...string) KeyCollection
    74  }
    75  
    76  func T(tableName string, tableDefinitions ...TableDefinition) Table {
    77  	t := &table{
    78  		name:             tableName,
    79  		ColumnCollection: &columns{},
    80  		KeyCollection:    &keys{},
    81  	}
    82  
    83  	// col added first
    84  	for _, tableDef := range tableDefinitions {
    85  		switch d := tableDef.(type) {
    86  		case Column:
    87  			t.AddCol(d.Of(t))
    88  		}
    89  	}
    90  
    91  	for _, tableDef := range tableDefinitions {
    92  		switch d := tableDef.(type) {
    93  		case Key:
    94  			t.AddKey(d.Of(t))
    95  		}
    96  	}
    97  
    98  	return t
    99  }
   100  
   101  type table struct {
   102  	database    string
   103  	name        string
   104  	description []string
   105  	ColumnCollection
   106  	KeyCollection
   107  }
   108  
   109  func (t *table) AddCol(cols ...Column) {
   110  	for i := range cols {
   111  		t.ColumnCollection.(ColumnCollectionManger).AddCol(cols[i].Of(t))
   112  	}
   113  }
   114  
   115  func (t *table) AddKey(keys ...Key) {
   116  	for i := range keys {
   117  		t.KeyCollection.(KeyCollectionManager).AddKey(keys[i].Of(t))
   118  	}
   119  }
   120  
   121  func (t table) WithTableName(name string) Table {
   122  	newTable := &table{
   123  		database:    t.database,
   124  		name:        name,
   125  		description: t.description,
   126  	}
   127  
   128  	newTable.ColumnCollection = t.ColumnCollection.Of(newTable)
   129  	newTable.KeyCollection = t.KeyCollection.Of(newTable)
   130  
   131  	return newTable
   132  }
   133  
   134  func (t *table) TableName() string {
   135  	return t.name
   136  }
   137  
   138  func (t *table) IsNil() bool {
   139  	return t == nil || len(t.name) == 0
   140  }
   141  
   142  func (t *table) Ex(ctx context.Context) *Ex {
   143  	return Expr(t.name).Ex(ctx)
   144  }
   145  
   146  func (t *table) Expr(query string, args ...interface{}) *Ex {
   147  	if query == "" {
   148  		return nil
   149  	}
   150  
   151  	n := len(args)
   152  	e := Expr("")
   153  	e.Grow(n)
   154  
   155  	s := &scanner.Scanner{}
   156  	s.Init(bytes.NewBuffer([]byte(query)))
   157  
   158  	queryCount := 0
   159  
   160  	for tok := s.Next(); tok != scanner.EOF; tok = s.Next() {
   161  		switch tok {
   162  		case '#':
   163  			fieldNameBuf := bytes.NewBuffer(nil)
   164  
   165  			e.WriteHolder(0)
   166  
   167  			for {
   168  				tok = s.Next()
   169  
   170  				if tok == scanner.EOF {
   171  					break
   172  				}
   173  
   174  				if (tok >= 'A' && tok <= 'Z') ||
   175  					(tok >= 'a' && tok <= 'z') ||
   176  					(tok >= '0' && tok <= '9') ||
   177  					tok == '_' {
   178  
   179  					fieldNameBuf.WriteRune(tok)
   180  					continue
   181  				}
   182  
   183  				e.WriteQueryByte(byte(tok))
   184  
   185  				break
   186  			}
   187  
   188  			if fieldNameBuf.Len() == 0 {
   189  				e.AppendArgs(t)
   190  			} else {
   191  				fieldName := fieldNameBuf.String()
   192  				col := t.F(fieldNameBuf.String())
   193  				if col == nil {
   194  					panic(fmt.Errorf("missing field fieldName %s of table %s", fieldName, t.TableName()))
   195  				}
   196  				e.AppendArgs(col)
   197  			}
   198  		case '?':
   199  			e.WriteQueryByte(byte(tok))
   200  			if queryCount < n {
   201  				e.AppendArgs(args[queryCount])
   202  				queryCount++
   203  			}
   204  		default:
   205  			e.WriteQueryByte(byte(tok))
   206  		}
   207  	}
   208  
   209  	return e
   210  }
   211  
   212  type Tables struct {
   213  	l      *list.List
   214  	tables map[string]*list.Element
   215  }
   216  
   217  func (tables *Tables) TableNames() (names []string) {
   218  	tables.Range(func(tab Table, idx int) bool {
   219  		names = append(names, tab.TableName())
   220  		return true
   221  	})
   222  	sort.Strings(names)
   223  	return
   224  }
   225  
   226  func (tables *Tables) Add(tabs ...Table) {
   227  	if tables.tables == nil {
   228  		tables.tables = map[string]*list.Element{}
   229  		tables.l = list.New()
   230  	}
   231  
   232  	for _, tab := range tabs {
   233  		if tab != nil {
   234  			if _, ok := tables.tables[tab.TableName()]; ok {
   235  				tables.Remove(tab.TableName())
   236  			}
   237  			e := tables.l.PushBack(tab)
   238  			tables.tables[tab.TableName()] = e
   239  		}
   240  	}
   241  }
   242  
   243  func (tables *Tables) Table(tableName string) Table {
   244  	if tables.tables != nil {
   245  		if c, ok := tables.tables[tableName]; ok {
   246  			return c.Value.(Table)
   247  		}
   248  	}
   249  	return nil
   250  }
   251  
   252  func (tables *Tables) Remove(name string) {
   253  	if tables.tables != nil {
   254  		if e, exists := tables.tables[name]; exists {
   255  			tables.l.Remove(e)
   256  			delete(tables.tables, name)
   257  		}
   258  	}
   259  }
   260  
   261  func (tables Tables) Range(cb func(tab Table, idx int) bool) {
   262  	if tables.l != nil {
   263  		i := 0
   264  		for e := tables.l.Front(); e != nil; e = e.Next() {
   265  			if !cb(e.Value.(Table), i) {
   266  				break
   267  			}
   268  			i++
   269  		}
   270  	}
   271  }