github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/drivers/interface_test.go (about)

     1  package drivers
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/volatiletech/strmangle"
     7  )
     8  
     9  type testMockDriver struct{}
    10  
    11  func (m testMockDriver) TranslateColumnType(c Column) Column { return c }
    12  func (m testMockDriver) UseLastInsertID() bool               { return false }
    13  func (m testMockDriver) UseTopClause() bool                  { return false }
    14  func (m testMockDriver) Open() error                         { return nil }
    15  func (m testMockDriver) Close()                              {}
    16  
    17  func (m testMockDriver) TableNames(schema string, whitelist, blacklist []string) ([]string, error) {
    18  	if len(whitelist) > 0 {
    19  		return whitelist, nil
    20  	}
    21  	tables := []string{"pilots", "jets", "airports", "licenses", "hangars", "languages", "pilot_languages"}
    22  	return strmangle.SetComplement(tables, blacklist), nil
    23  }
    24  
    25  // Columns returns a list of mock columns
    26  func (m testMockDriver) Columns(schema, tableName string, whitelist, blacklist []string) ([]Column, error) {
    27  	return map[string][]Column{
    28  		"pilots": {
    29  			{Name: "id", Type: "int", DBType: "integer"},
    30  			{Name: "name", Type: "string", DBType: "character"},
    31  		},
    32  		"airports": {
    33  			{Name: "id", Type: "int", DBType: "integer"},
    34  			{Name: "size", Type: "null.Int", DBType: "integer", Nullable: true},
    35  		},
    36  		"jets": {
    37  			{Name: "id", Type: "int", DBType: "integer"},
    38  			{Name: "pilot_id", Type: "int", DBType: "integer", Nullable: true, Unique: true},
    39  			{Name: "airport_id", Type: "int", DBType: "integer"},
    40  			{Name: "name", Type: "string", DBType: "character", Nullable: false},
    41  			{Name: "color", Type: "null.String", DBType: "character", Nullable: true},
    42  			{Name: "uuid", Type: "string", DBType: "uuid", Nullable: true},
    43  			{Name: "identifier", Type: "string", DBType: "uuid", Nullable: false},
    44  			{Name: "cargo", Type: "[]byte", DBType: "bytea", Nullable: false},
    45  			{Name: "manifest", Type: "[]byte", DBType: "bytea", Nullable: true, Unique: true},
    46  		},
    47  		"licenses": {
    48  			{Name: "id", Type: "int", DBType: "integer"},
    49  			{Name: "pilot_id", Type: "int", DBType: "integer"},
    50  		},
    51  		"hangars": {
    52  			{Name: "id", Type: "int", DBType: "integer"},
    53  			{Name: "name", Type: "string", DBType: "character", Nullable: true, Unique: true},
    54  			{Name: "hangar_id", Type: "int", DBType: "integer", Nullable: true},
    55  		},
    56  		"languages": {
    57  			{Name: "id", Type: "int", DBType: "integer"},
    58  			{Name: "language", Type: "string", DBType: "character", Nullable: false, Unique: true},
    59  		},
    60  		"pilot_languages": {
    61  			{Name: "pilot_id", Type: "int", DBType: "integer"},
    62  			{Name: "language_id", Type: "int", DBType: "integer"},
    63  		},
    64  	}[tableName], nil
    65  }
    66  
    67  // ForeignKeyInfo returns a list of mock foreignkeys
    68  func (m testMockDriver) ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error) {
    69  	return map[string][]ForeignKey{
    70  		"jets": {
    71  			{Table: "jets", Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", ForeignColumnUnique: true},
    72  			{Table: "jets", Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id"},
    73  		},
    74  		"licenses": {
    75  			{Table: "licenses", Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"},
    76  		},
    77  		"pilot_languages": {
    78  			{Table: "pilot_languages", Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"},
    79  			{Table: "pilot_languages", Name: "jet_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id"},
    80  		},
    81  		"hangars": {
    82  			{Table: "hangars", Name: "hangar_fk_id", Column: "hangar_id", ForeignTable: "hangars", ForeignColumn: "id"},
    83  		},
    84  	}[tableName], nil
    85  }
    86  
    87  // PrimaryKeyInfo returns mock primary key info for the passed in table name
    88  func (m testMockDriver) PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, error) {
    89  	return map[string]*PrimaryKey{
    90  		"pilots":          {Name: "pilot_id_pkey", Columns: []string{"id"}},
    91  		"airports":        {Name: "airport_id_pkey", Columns: []string{"id"}},
    92  		"jets":            {Name: "jet_id_pkey", Columns: []string{"id"}},
    93  		"licenses":        {Name: "license_id_pkey", Columns: []string{"id"}},
    94  		"hangars":         {Name: "hangar_id_pkey", Columns: []string{"id"}},
    95  		"languages":       {Name: "language_id_pkey", Columns: []string{"id"}},
    96  		"pilot_languages": {Name: "pilot_languages_pkey", Columns: []string{"pilot_id", "language_id"}},
    97  	}[tableName], nil
    98  }
    99  
   100  // RightQuote is the quoting character for the right side of the identifier
   101  func (m testMockDriver) RightQuote() byte {
   102  	return '"'
   103  }
   104  
   105  // LeftQuote is the quoting character for the left side of the identifier
   106  func (m testMockDriver) LeftQuote() byte {
   107  	return '"'
   108  }
   109  
   110  // UseIndexPlaceholders returns true to indicate fake support of indexed placeholders
   111  func (m testMockDriver) UseIndexPlaceholders() bool {
   112  	return false
   113  }
   114  
   115  func TestTables(t *testing.T) {
   116  	t.Parallel()
   117  
   118  	tables, err := TablesConcurrently(testMockDriver{}, "public", nil, nil, 1)
   119  	if err != nil {
   120  		t.Error(err)
   121  	}
   122  
   123  	if len(tables) != 7 {
   124  		t.Errorf("Expected len 7, got: %d\n", len(tables))
   125  	}
   126  
   127  	prev := ""
   128  	for i := range tables {
   129  		if prev >= tables[i].Name {
   130  			t.Error("tables are not sorted")
   131  		}
   132  		prev = tables[i].Name
   133  	}
   134  
   135  	pilots := GetTable(tables, "pilots")
   136  	if len(pilots.Columns) != 2 {
   137  		t.Error()
   138  	}
   139  	if pilots.ToOneRelationships[0].ForeignTable != "jets" {
   140  		t.Error("want a to many to jets")
   141  	}
   142  	if pilots.ToManyRelationships[0].ForeignTable != "licenses" {
   143  		t.Error("want a to many to languages")
   144  	}
   145  	if pilots.ToManyRelationships[1].ForeignTable != "languages" {
   146  		t.Error("want a to many to languages")
   147  	}
   148  
   149  	jets := GetTable(tables, "jets")
   150  	if len(jets.ToManyRelationships) != 0 {
   151  		t.Error("want no to many relationships")
   152  	}
   153  
   154  	languages := GetTable(tables, "pilot_languages")
   155  	if !languages.IsJoinTable {
   156  		t.Error("languages is a join table")
   157  	}
   158  
   159  	hangars := GetTable(tables, "hangars")
   160  	if len(hangars.ToManyRelationships) != 1 || hangars.ToManyRelationships[0].ForeignTable != "hangars" {
   161  		t.Error("want 1 to many relationships")
   162  	}
   163  	if len(hangars.FKeys) != 1 || hangars.FKeys[0].ForeignTable != "hangars" {
   164  		t.Error("want one hangar foreign key to itself")
   165  	}
   166  }
   167  
   168  func TestFilterForeignKeys(t *testing.T) {
   169  	t.Parallel()
   170  
   171  	tables := []Table{
   172  		{
   173  			Name: "one",
   174  			Columns: []Column{
   175  				{Name: "id"},
   176  				{Name: "two_id"},
   177  				{Name: "three_id"},
   178  				{Name: "four_id"},
   179  			},
   180  			FKeys: []ForeignKey{
   181  				{Table: "one", Column: "two_id", ForeignTable: "two", ForeignColumn: "id"},
   182  				{Table: "one", Column: "three_id", ForeignTable: "three", ForeignColumn: "id"},
   183  				{Table: "one", Column: "four_id", ForeignTable: "four", ForeignColumn: "id"},
   184  			},
   185  		},
   186  		{
   187  			Name: "two",
   188  			Columns: []Column{
   189  				{Name: "id"},
   190  			},
   191  		},
   192  		{
   193  			Name: "three",
   194  			Columns: []Column{
   195  				{Name: "id"},
   196  			},
   197  		},
   198  		{
   199  			Name: "four",
   200  			Columns: []Column{
   201  				{Name: "id"},
   202  			},
   203  		},
   204  	}
   205  
   206  	tests := []struct {
   207  		Whitelist   []string
   208  		Blacklist   []string
   209  		ExpectFkNum int
   210  	}{
   211  		{[]string{}, []string{}, 3},
   212  		{[]string{"one", "two", "three"}, []string{}, 2},
   213  		{[]string{"one.two_id", "two"}, []string{}, 1},
   214  		{[]string{"*.two_id", "two"}, []string{}, 1},
   215  		{[]string{}, []string{"three", "four"}, 1},
   216  		{[]string{}, []string{"three.id"}, 2},
   217  		{[]string{}, []string{"one.two_id"}, 2},
   218  		{[]string{}, []string{"*.two_id"}, 2},
   219  		{[]string{"one", "two"}, []string{"two"}, 0},
   220  	}
   221  
   222  	for i, test := range tests {
   223  		table := tables[0]
   224  		filterForeignKeys(&table, test.Whitelist, test.Blacklist)
   225  		if fkNum := len(table.FKeys); fkNum != test.ExpectFkNum {
   226  			t.Errorf("%d) want: %d, got: %d\nTest: %#v", i, test.ExpectFkNum, fkNum, test)
   227  		}
   228  	}
   229  }
   230  
   231  func TestKnownColumn(t *testing.T) {
   232  	tests := []struct {
   233  		table     string
   234  		column    string
   235  		whitelist []string
   236  		blacklist []string
   237  		expected  bool
   238  	}{
   239  		{"one", "id", []string{"one"}, []string{}, true},
   240  		{"one", "id", []string{}, []string{"one"}, false},
   241  		{"one", "id", []string{"one.id"}, []string{}, true},
   242  		{"one", "id", []string{"one.id"}, []string{"one"}, false},
   243  		{"one", "id", []string{"two"}, []string{}, false},
   244  		{"one", "id", []string{"two"}, []string{"one"}, false},
   245  		{"one", "id", []string{"two.id"}, []string{}, false},
   246  		{"one", "id", []string{"*.id"}, []string{}, true},
   247  		{"one", "id", []string{"*.id"}, []string{"*.id"}, false},
   248  	}
   249  
   250  	for i, test := range tests {
   251  		known := knownColumn(test.table, test.column, test.whitelist, test.blacklist)
   252  		if known != test.expected {
   253  			t.Errorf("%d) want: %t, got: %t\nTest: %#v", i, test.expected, known, test)
   254  		}
   255  	}
   256  
   257  }
   258  
   259  func TestSetIsJoinTable(t *testing.T) {
   260  	t.Parallel()
   261  
   262  	tests := []struct {
   263  		Pkey   []string
   264  		Fkey   []string
   265  		Should bool
   266  	}{
   267  		{Pkey: []string{"one", "two"}, Fkey: []string{"one", "two"}, Should: true},
   268  		{Pkey: []string{"two", "one"}, Fkey: []string{"one", "two"}, Should: true},
   269  
   270  		{Pkey: []string{"one"}, Fkey: []string{"one"}, Should: false},
   271  		{Pkey: []string{"one", "two", "three"}, Fkey: []string{"one", "two"}, Should: false},
   272  		{Pkey: []string{"one", "two", "three"}, Fkey: []string{"one", "two", "three"}, Should: false},
   273  		{Pkey: []string{"one"}, Fkey: []string{"one", "two"}, Should: false},
   274  		{Pkey: []string{"one", "two"}, Fkey: []string{"one"}, Should: false},
   275  	}
   276  
   277  	for i, test := range tests {
   278  		var table Table
   279  
   280  		table.PKey = &PrimaryKey{Columns: test.Pkey}
   281  		for _, k := range test.Fkey {
   282  			table.FKeys = append(table.FKeys, ForeignKey{Column: k})
   283  		}
   284  
   285  		setIsJoinTable(&table)
   286  		if is := table.IsJoinTable; is != test.Should {
   287  			t.Errorf("%d) want: %t, got: %t\nTest: %#v", i, test.Should, is, test)
   288  		}
   289  	}
   290  }
   291  
   292  func TestSetForeignKeyConstraints(t *testing.T) {
   293  	t.Parallel()
   294  
   295  	tables := []Table{
   296  		{
   297  			Name: "one",
   298  			Columns: []Column{
   299  				{Name: "id1", Type: "string", Nullable: false, Unique: false},
   300  				{Name: "id2", Type: "string", Nullable: true, Unique: true},
   301  			},
   302  		},
   303  		{
   304  			Name: "other",
   305  			Columns: []Column{
   306  				{Name: "one_id_1", Type: "string", Nullable: false, Unique: false},
   307  				{Name: "one_id_2", Type: "string", Nullable: true, Unique: true},
   308  			},
   309  			FKeys: []ForeignKey{
   310  				{Column: "one_id_1", ForeignTable: "one", ForeignColumn: "id1"},
   311  				{Column: "one_id_2", ForeignTable: "one", ForeignColumn: "id2"},
   312  			},
   313  		},
   314  	}
   315  
   316  	setForeignKeyConstraints(&tables[0], tables)
   317  	setForeignKeyConstraints(&tables[1], tables)
   318  
   319  	first := tables[1].FKeys[0]
   320  	second := tables[1].FKeys[1]
   321  	if first.Nullable {
   322  		t.Error("should not be nullable")
   323  	}
   324  	if first.Unique {
   325  		t.Error("should not be unique")
   326  	}
   327  	if first.ForeignColumnNullable {
   328  		t.Error("should be nullable")
   329  	}
   330  	if first.ForeignColumnUnique {
   331  		t.Error("should be unique")
   332  	}
   333  	if !second.Nullable {
   334  		t.Error("should be nullable")
   335  	}
   336  	if !second.Unique {
   337  		t.Error("should be unique")
   338  	}
   339  	if !second.ForeignColumnNullable {
   340  		t.Error("should be nullable")
   341  	}
   342  	if !second.ForeignColumnUnique {
   343  		t.Error("should be unique")
   344  	}
   345  }
   346  
   347  func TestSetRelationships(t *testing.T) {
   348  	t.Parallel()
   349  
   350  	tables := []Table{
   351  		{
   352  			Name: "one",
   353  			Columns: []Column{
   354  				{Name: "id", Type: "string"},
   355  			},
   356  		},
   357  		{
   358  			Name: "other",
   359  			Columns: []Column{
   360  				{Name: "other_id", Type: "string"},
   361  			},
   362  			FKeys: []ForeignKey{{Column: "other_id", ForeignTable: "one", ForeignColumn: "id", Nullable: true}},
   363  		},
   364  	}
   365  
   366  	setRelationships(&tables[0], tables)
   367  	setRelationships(&tables[1], tables)
   368  
   369  	if got := len(tables[0].ToManyRelationships); got != 1 {
   370  		t.Error("should have a relationship:", got)
   371  	}
   372  	if got := len(tables[1].ToManyRelationships); got != 0 {
   373  		t.Error("should have no to many relationships:", got)
   374  	}
   375  
   376  	rel := tables[0].ToManyRelationships[0]
   377  	if rel.Column != "id" {
   378  		t.Error("wrong column:", rel.Column)
   379  	}
   380  	if rel.ForeignTable != "other" {
   381  		t.Error("wrong table:", rel.ForeignTable)
   382  	}
   383  	if rel.ForeignColumn != "other_id" {
   384  		t.Error("wrong column:", rel.ForeignColumn)
   385  	}
   386  	if rel.ToJoinTable {
   387  		t.Error("should not be a join table")
   388  	}
   389  }