github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/sqlx/builder/builder_def_tab.go (about)

     1  package builder
     2  
     3  import (
     4  	"bytes"
     5  	"container/list"
     6  	"context"
     7  	"fmt"
     8  	"sort"
     9  	"strings"
    10  	"text/scanner"
    11  )
    12  
    13  type TableDefinition interface{ T() *Table }
    14  
    15  func T(tblName string, defs ...TableDefinition) *Table {
    16  	t := &Table{Name: tblName}
    17  
    18  	for _, def := range defs {
    19  		if d, ok := def.(*Column); ok {
    20  			t.AddCol(d)
    21  		}
    22  		if k, ok := def.(*Key); ok {
    23  			t.AddKey(k)
    24  		}
    25  	}
    26  	return t
    27  }
    28  
    29  type Table struct {
    30  	Name      string
    31  	Desc      []string
    32  	Schema    string
    33  	ModelName string
    34  	Model     Model
    35  
    36  	Columns
    37  	Keys
    38  }
    39  
    40  func (t *Table) TableName() string { return t.Name }
    41  
    42  func (t *Table) IsNil() bool { return t == nil || t.Name == "" }
    43  
    44  func (t *Table) Ex(ctx context.Context) *Ex {
    45  	if t.Schema != "" {
    46  		return Expr(t.Schema + "." + t.Name).Ex(ctx)
    47  	}
    48  	return Expr(t.Name).Ex(ctx)
    49  }
    50  
    51  func (t Table) WithSchema(schema string) *Table {
    52  	t.Schema = schema
    53  
    54  	cols := Columns{}
    55  	t.Columns.Range(func(c *Column, idx int) {
    56  		cols.Add(c.On(&t))
    57  	})
    58  	t.Columns = cols
    59  
    60  	keys := Keys{}
    61  	t.Keys.Range(func(k *Key, idx int) {
    62  		keys.Add(k.On(&t))
    63  	})
    64  	t.Keys = keys
    65  	return &t
    66  }
    67  
    68  func (t *Table) AddCol(c *Column) {
    69  	if c != nil {
    70  		t.Columns.Add(c.On(t))
    71  	}
    72  }
    73  
    74  func (t *Table) AddKey(k *Key) {
    75  	if k != nil {
    76  		t.Keys.Add(k.On(t))
    77  	}
    78  }
    79  
    80  func (t *Table) Expr(query string, args ...interface{}) *Ex {
    81  	if query == "" {
    82  		return nil
    83  	}
    84  
    85  	argc := len(args)
    86  	e := Expr("")
    87  	e.Grow(argc)
    88  
    89  	s := scanner.Scanner{}
    90  	s.Init(bytes.NewBuffer([]byte(query)))
    91  
    92  	qc := 0
    93  
    94  	for tok := s.Next(); tok != scanner.EOF; tok = s.Next() {
    95  		switch tok {
    96  		default:
    97  			e.WriteQueryRune(tok)
    98  		case '?':
    99  			e.WriteQueryRune(tok)
   100  			if qc < argc {
   101  				e.AppendArgs(args[qc])
   102  				qc++
   103  			}
   104  		case '#':
   105  			b := bytes.NewBuffer(nil) //field name buffer
   106  
   107  			e.WriteHolder(0)
   108  			for {
   109  				tok = s.Next()
   110  				if tok == scanner.EOF {
   111  					break
   112  				}
   113  				if tok >= 'A' && tok <= 'Z' || tok >= 'a' && tok <= 'z' ||
   114  					tok >= '0' && tok <= '9' || tok == '_' {
   115  					b.WriteRune(tok)
   116  					continue
   117  				}
   118  				e.WriteQueryRune(tok)
   119  				break
   120  			}
   121  			if b.Len() == 0 {
   122  				e.AppendArgs(t)
   123  				continue
   124  			}
   125  			name := b.String()
   126  			col := t.ColByFieldName(name)
   127  			if col == nil {
   128  				panic(fmt.Errorf("missing field %s of %s", name, t.Name))
   129  			}
   130  			e.AppendArgs(col)
   131  		}
   132  	}
   133  	return e
   134  }
   135  
   136  func (t *Table) Diff(prevT *Table, d Dialect) (exprList []SqlExpr) {
   137  	// diff columns
   138  	t.Columns.Range(func(currC *Column, idx int) {
   139  		if prevC := prevT.Col(currC.Name); prevC != nil {
   140  			if currC != nil {
   141  				if currC.DeprecatedActs != nil {
   142  					renameTo := currC.DeprecatedActs.RenameTo
   143  					if renameTo != "" {
   144  						prevCol := prevT.Col(renameTo)
   145  						if prevCol != nil {
   146  							exprList = append(exprList, d.DropColumn(prevCol))
   147  						}
   148  						targetCol := t.Col(renameTo)
   149  						if targetCol == nil {
   150  							panic(fmt.Errorf("col `%s` is not declared", renameTo))
   151  						}
   152  						exprList = append(exprList, d.RenameColumn(currC, targetCol))
   153  						prevT.AddCol(targetCol)
   154  						return
   155  					}
   156  					exprList = append(exprList, d.DropColumn(currC))
   157  					return
   158  				}
   159  
   160  				prevCT := d.DataType(prevC.ColumnType).Ex(context.Background()).Query()
   161  				currCT := d.DataType(currC.ColumnType).Ex(context.Background()).Query()
   162  
   163  				if currCT != prevCT {
   164  					exprList = append(exprList, d.ModifyColumn(currC, prevC))
   165  				}
   166  				return
   167  			}
   168  			exprList = append(exprList, d.DropColumn(currC))
   169  			return
   170  		}
   171  
   172  		if currC.DeprecatedActs == nil {
   173  			exprList = append(exprList, d.AddColumn(currC))
   174  		}
   175  	})
   176  
   177  	// indexes
   178  	indexes := map[string]bool{}
   179  
   180  	t.Keys.Range(func(key *Key, idx int) {
   181  		name := key.Name
   182  		if key.IsPrimary() {
   183  			name = d.PrimaryKeyName()
   184  		}
   185  		indexes[name] = true
   186  
   187  		prevKey := prevT.Key(name)
   188  		if prevKey == nil {
   189  			exprList = append(exprList, d.AddIndex(key))
   190  		} else {
   191  			if !key.IsPrimary() {
   192  				indexDef := key.Def.TableExpr(key.Table).Ex(context.Background()).Query()
   193  				prevIndexDef := prevKey.Def.TableExpr(prevKey.Table).Ex(context.Background()).Query()
   194  
   195  				if !strings.EqualFold(indexDef, prevIndexDef) {
   196  					exprList = append(exprList, d.DropIndex(key))
   197  					exprList = append(exprList, d.AddIndex(key))
   198  				}
   199  			}
   200  		}
   201  	})
   202  
   203  	prevT.Keys.Range(func(key *Key, idx int) {
   204  		if _, ok := indexes[strings.ToLower(key.Name)]; !ok {
   205  			exprList = append(exprList, d.DropIndex(key))
   206  		}
   207  	})
   208  
   209  	return
   210  }
   211  
   212  func (t *Table) ColumnsAndValuesByFieldValues(fvs FieldValues) (*Columns, []interface{}) {
   213  	fields := make([]string, 0)
   214  	for name, _ := range fvs {
   215  		fields = append(fields, name)
   216  	}
   217  
   218  	sort.Strings(fields)
   219  
   220  	cols := &Columns{}
   221  	args := make([]interface{}, 0, len(fvs))
   222  
   223  	for _, fieldName := range fields {
   224  		if col := t.ColByFieldName(fieldName); col != nil {
   225  			cols.Add(col)
   226  			args = append(args, fvs[fieldName])
   227  		}
   228  	}
   229  	return cols, args
   230  }
   231  
   232  func (t *Table) AssignmentsByFieldValues(fvs FieldValues) Assignments {
   233  	var assignments Assignments
   234  	for name, value := range fvs {
   235  		col := t.ColByFieldName(name)
   236  		if col != nil {
   237  			assignments = append(assignments, col.ValueBy(value))
   238  		}
   239  	}
   240  	return assignments
   241  }
   242  
   243  type Tables struct {
   244  	lst    *list.List
   245  	tables map[string]*list.Element
   246  	models map[string]*list.Element
   247  }
   248  
   249  func (t *Tables) TableNames() []string {
   250  	if t.lst == nil {
   251  		return nil
   252  	}
   253  	names := make([]string, 0, t.lst.Len())
   254  	t.Range(func(tbl *Table, _ int) {
   255  		names = append(names, tbl.Name)
   256  	})
   257  	return names
   258  }
   259  
   260  func (t *Tables) Add(tables ...*Table) {
   261  	if t.lst == nil {
   262  		t.lst = list.New()
   263  		t.tables = make(map[string]*list.Element)
   264  		t.models = make(map[string]*list.Element)
   265  	}
   266  	for _, tbl := range tables {
   267  		if tbl == nil {
   268  			continue
   269  		}
   270  		if _, ok := t.tables[tbl.Name]; ok {
   271  			t.Remove(tbl.Name)
   272  		}
   273  		e := t.lst.PushBack(tbl)
   274  		t.tables[tbl.Name] = e
   275  		if tbl.ModelName != "" {
   276  			t.models[tbl.ModelName] = e
   277  		}
   278  	}
   279  }
   280  
   281  func (t *Tables) Table(name string) *Table {
   282  	if t.tables != nil {
   283  		if c, ok := t.tables[name]; ok {
   284  			return c.Value.(*Table)
   285  		}
   286  	}
   287  	return nil
   288  }
   289  
   290  func (t *Tables) Model(typename string) *Table {
   291  	if t.models != nil {
   292  		if c, ok := t.models[typename]; ok {
   293  			return c.Value.(*Table)
   294  		}
   295  	}
   296  	return nil
   297  }
   298  
   299  func (t *Tables) Remove(name string) {
   300  	if t.tables != nil {
   301  		if e, exists := t.tables[name]; exists {
   302  			t.lst.Remove(e)
   303  			delete(t.tables, name)
   304  		}
   305  	}
   306  }
   307  
   308  func (t *Tables) Range(f func(*Table, int)) {
   309  	if t.lst != nil {
   310  		i := 0
   311  		for e := t.lst.Front(); e != nil; e = e.Next() {
   312  			f(e.Value.(*Table), i)
   313  			i++
   314  		}
   315  	}
   316  }