github.com/blend/go-sdk@v1.20220411.3/db/column_collection_test.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package db
     9  
    10  import (
    11  	"reflect"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/blend/go-sdk/assert"
    16  )
    17  
    18  func Test_Columns(t *testing.T) {
    19  	its := assert.New(t)
    20  
    21  	var emptyColumnCollection ColumnCollection
    22  	firstOrDefaultNil := emptyColumnCollection.FirstOrDefault()
    23  	its.Nil(firstOrDefaultNil)
    24  
    25  	obj := myStruct{}
    26  	meta := Columns(obj)
    27  
    28  	its.NotNil(meta.Columns())
    29  	its.NotEmpty(meta.Columns())
    30  
    31  	its.Equal(9, meta.Len())
    32  
    33  	readOnlyColumns := meta.ReadOnly()
    34  	its.Len(readOnlyColumns.Columns(), 1)
    35  
    36  	firstOrDefault := meta.FirstOrDefault()
    37  	its.NotNil(firstOrDefault)
    38  
    39  	firstCol := meta.FirstOrDefault()
    40  	its.Equal("my_struct", firstCol.TableName)
    41  	its.Equal("PrimaryKeyCol", firstCol.FieldName)
    42  	its.Equal("primary_key_column", firstCol.ColumnName)
    43  	its.True(firstCol.IsPrimaryKey)
    44  	its.True(firstCol.IsAuto)
    45  	its.False(firstCol.IsReadOnly)
    46  
    47  	secondCol := meta.Columns()[1]
    48  	its.Equal("auto_column", secondCol.ColumnName)
    49  	its.False(secondCol.IsPrimaryKey)
    50  	its.True(secondCol.IsAuto)
    51  	its.False(secondCol.IsReadOnly)
    52  
    53  	thirdCol := meta.Columns()[2]
    54  	its.Equal("InferredName", thirdCol.ColumnName)
    55  	its.False(thirdCol.IsPrimaryKey)
    56  	its.False(thirdCol.IsAuto)
    57  	its.False(thirdCol.IsReadOnly)
    58  
    59  	fourthCol := meta.Columns()[3]
    60  	its.Equal("Unique", fourthCol.ColumnName)
    61  	its.False(fourthCol.IsPrimaryKey)
    62  	its.True(fourthCol.IsUniqueKey)
    63  	its.False(fourthCol.IsAuto)
    64  	its.False(fourthCol.IsReadOnly)
    65  
    66  	fifthCol := meta.Columns()[4]
    67  	its.Equal("nullable", fifthCol.ColumnName)
    68  	its.False(fifthCol.IsPrimaryKey)
    69  	its.False(fifthCol.IsAuto)
    70  	its.False(fifthCol.IsReadOnly)
    71  
    72  	sixthCol := meta.Columns()[5]
    73  	its.Equal("InferredWithFlags", sixthCol.ColumnName)
    74  	its.False(sixthCol.IsPrimaryKey)
    75  	its.False(sixthCol.IsAuto)
    76  	its.True(sixthCol.IsReadOnly)
    77  
    78  	uks := meta.UniqueKeys()
    79  	its.Equal(1, uks.Len())
    80  }
    81  
    82  func Test_ColumnNameCSV(t *testing.T) {
    83  	its := assert.New(t)
    84  
    85  	expected := "primary_key_column,auto_column,InferredName,Unique,nullable,InferredWithFlags,big_int,pointer_col,json_col"
    86  	actual := ColumnNamesCSV(myStruct{})
    87  	its.Equal(expected, actual)
    88  }
    89  
    90  func Test_ColumnCollection_Copy(t *testing.T) {
    91  	its := assert.New(t)
    92  
    93  	obj := myStruct{}
    94  	meta := Columns(obj)
    95  	newMeta := meta.Copy()
    96  	its.False(meta == newMeta, "These pointers should not be the same.")
    97  	newMeta.columnPrefix = "foo_"
    98  	its.NotEqual(meta.columnPrefix, newMeta.columnPrefix)
    99  }
   100  
   101  func Test_ColumnCollection_CopyWithColumnPrefix(t *testing.T) {
   102  	its := assert.New(t)
   103  
   104  	obj := myStruct{}
   105  	meta := Columns(obj)
   106  	newMeta := meta.CopyWithColumnPrefix("foo_")
   107  	its.Equal("foo_", newMeta.columnPrefix)
   108  	its.False(meta == newMeta, "These pointers should not be the same.")
   109  	its.NotEqual(meta.columnPrefix, newMeta.columnPrefix)
   110  }
   111  
   112  func Test_ColumnCollection_Add(t *testing.T) {
   113  	its := assert.New(t)
   114  
   115  	obj := myStruct{}
   116  	meta := Columns(obj)
   117  	newMeta := meta.Copy()
   118  	its.Len(newMeta.columns, 9)
   119  	its.False(newMeta.HasColumn("testo"))
   120  	newMeta.Add(Column{
   121  		FieldName:  "Testo",
   122  		ColumnName: "testo",
   123  	})
   124  	its.Len(newMeta.columns, 10)
   125  	its.True(newMeta.HasColumn("testo"))
   126  }
   127  
   128  func Test_ColumnCollection_Remove(t *testing.T) {
   129  	its := assert.New(t)
   130  
   131  	obj := myStruct{}
   132  	meta := Columns(obj)
   133  	newMeta := meta.Copy()
   134  
   135  	its.True(newMeta.HasColumn("primary_key_column"))
   136  	newMeta.Remove("primary_key_column")
   137  	its.False(newMeta.HasColumn("primary_key_column"))
   138  }
   139  
   140  func Test_ColumnCollection_InsertColumns(t *testing.T) {
   141  	its := assert.New(t)
   142  
   143  	obj := myStruct{}
   144  	meta := Columns(obj)
   145  	writeCols := meta.InsertColumns()
   146  	its.NotZero(writeCols.Len())
   147  }
   148  
   149  func Test_ColumnCollection_Zero(t *testing.T) {
   150  	its := assert.New(t)
   151  	cols := Columns(columnsZeroTest{})
   152  
   153  	emptyCols := cols.Zero(columnsZeroTest{})
   154  	its.Equal(len(cols.columns), len(emptyCols.columns))
   155  
   156  	stringValue := "test"
   157  	bytesValue := []byte(stringValue)
   158  	ts := time.Now().UTC()
   159  	setCols := cols.Zero(columnsZeroTest{
   160  		Int:       1,
   161  		Float64:   1,
   162  		TimePtr:   &ts,
   163  		StringPtr: &stringValue,
   164  		Bytes:     bytesValue,
   165  	})
   166  	its.Equal(2, len(setCols.columns))
   167  
   168  	its.False(setCols.HasColumn("Int"))
   169  	its.False(setCols.HasColumn("Float64"))
   170  	its.False(setCols.HasColumn("TimePtr"))
   171  	its.False(setCols.HasColumn("StringPtr"))
   172  	its.False(setCols.HasColumn("Bytes"))
   173  
   174  	its.True(setCols.HasColumn("Time"), setCols.String())
   175  	its.True(setCols.HasColumn("String"), setCols.String())
   176  
   177  	allCols := cols.Zero(columnsZeroTest{
   178  		Int:       1,
   179  		Float64:   1,
   180  		Time:      ts,
   181  		TimePtr:   &ts,
   182  		String:    stringValue,
   183  		StringPtr: &stringValue,
   184  		Bytes:     bytesValue,
   185  	})
   186  	its.Empty(allCols.columns)
   187  }
   188  
   189  func Test_ColumnCollection_NotZero(t *testing.T) {
   190  	its := assert.New(t)
   191  	cols := Columns(columnsZeroTest{})
   192  
   193  	emptyCols := cols.NotZero(columnsZeroTest{})
   194  	its.Empty(emptyCols.columns)
   195  
   196  	stringValue := "test"
   197  	bytesValue := []byte(stringValue)
   198  	ts := time.Now().UTC()
   199  	setCols := cols.NotZero(columnsZeroTest{
   200  		Int:       1,
   201  		Float64:   1,
   202  		TimePtr:   &ts,
   203  		StringPtr: &stringValue,
   204  		Bytes:     bytesValue,
   205  	})
   206  	its.Equal(5, len(setCols.columns))
   207  
   208  	its.True(setCols.HasColumn("Int"))
   209  	its.True(setCols.HasColumn("Float64"))
   210  	its.True(setCols.HasColumn("TimePtr"))
   211  	its.True(setCols.HasColumn("StringPtr"))
   212  	its.True(setCols.HasColumn("Bytes"))
   213  
   214  	its.False(setCols.HasColumn("Time"), setCols.String())
   215  	its.False(setCols.HasColumn("String"), setCols.String())
   216  
   217  	allCols := cols.NotZero(columnsZeroTest{
   218  		Int:       1,
   219  		Float64:   1,
   220  		Time:      ts,
   221  		TimePtr:   &ts,
   222  		String:    stringValue,
   223  		StringPtr: &stringValue,
   224  		Bytes:     bytesValue,
   225  	})
   226  	its.Len(allCols.columns, 7)
   227  }
   228  
   229  func Test_ColumnCollection_ColumnNamesCSVFromAlias(t *testing.T) {
   230  	its := assert.New(t)
   231  
   232  	columns := []Column{
   233  		{ColumnName: "foo0"},
   234  		{ColumnName: "foo1"},
   235  		{ColumnName: "foo2"},
   236  	}
   237  
   238  	withoutPrefix := &ColumnCollection{
   239  		columns: columns,
   240  	}
   241  
   242  	its.Equal("buzz.foo0,buzz.foo1,buzz.foo2", withoutPrefix.ColumnNamesCSVFromAlias("buzz"))
   243  
   244  	withPrefix := &ColumnCollection{
   245  		columns:      columns,
   246  		columnPrefix: "bar_",
   247  	}
   248  
   249  	its.Equal("buzz.foo0 as bar_foo0,buzz.foo1 as bar_foo1,buzz.foo2 as bar_foo2", withPrefix.ColumnNamesCSVFromAlias("buzz"))
   250  }
   251  
   252  func Test_newColumnCacheKey(t *testing.T) {
   253  	its := assert.New(t)
   254  
   255  	its.Equal("db.cacheKeyEmpty", newColumnCacheKey(reflect.TypeOf(cacheKeyEmpty{})))
   256  	its.Equal("db.cacheKeyWithTableName_with_table_name", newColumnCacheKey(reflect.TypeOf(cacheKeyWithTableName{})))
   257  	its.Equal("db.cacheKeyWithColumMetaCacheKeyProvider_with_column_meta_cache_key", newColumnCacheKey(reflect.TypeOf(cacheKeyWithColumMetaCacheKeyProvider{})))
   258  }
   259  
   260  //
   261  // helper types
   262  //
   263  
   264  type cacheKeyEmpty struct{}
   265  
   266  type cacheKeyWithTableName struct{}
   267  
   268  func (j cacheKeyWithTableName) TableName() string { return "with_table_name" }
   269  
   270  type cacheKeyWithColumMetaCacheKeyProvider struct{}
   271  
   272  func (j cacheKeyWithColumMetaCacheKeyProvider) ColumnMetaCacheKey() string {
   273  	return "with_column_meta_cache_key"
   274  }
   275  
   276  type columnsZeroTest struct {
   277  	Int       int
   278  	Float64   float64
   279  	String    string
   280  	StringPtr *string
   281  	Time      time.Time
   282  	TimePtr   *time.Time
   283  	Bytes     []byte
   284  }
   285  
   286  type EmbeddedMeta struct {
   287  	PrimaryKeyCol int    `json:"pk" db:"primary_key_column,pk,serial"`
   288  	AutoCol       string `json:"auto" db:"auto_column,auto"`
   289  }
   290  
   291  type subStruct struct {
   292  	Foo string `json:"foo"`
   293  }
   294  
   295  type myStruct struct {
   296  	EmbeddedMeta      `db:",inline"`
   297  	InferredName      string    `json:"normal"`
   298  	Unique            string    `db:",uk"`
   299  	Excluded          string    `json:"-" db:"-"`
   300  	NullableCol       string    `json:"not_nullable" db:"nullable,nullable"`
   301  	InferredWithFlags string    `db:",readonly"`
   302  	BigIntColumn      int64     `db:"big_int"`
   303  	PointerColumn     *int      `db:"pointer_col"`
   304  	JSONColumn        subStruct `db:"json_col,json"`
   305  }
   306  
   307  func (m myStruct) TableName() string {
   308  	return "my_struct"
   309  }