func schema(sn string) *pqt.Schema { title := pqt.NewColumn("title", pqt.TypeText(), pqt.WithNotNull(), pqt.WithUnique()) lead := pqt.NewColumn("lead", pqt.TypeText()) news := pqt.NewTable("news", pqt.WithTableIfNotExists()). AddColumn(pqt.NewColumn("id", pqt.TypeSerialBig(), pqt.WithPrimaryKey())). AddColumn(title). AddColumn(lead). AddColumn(pqt.NewColumn("continue", pqt.TypeBool(), pqt.WithNotNull(), pqt.WithDefault("false"))). AddColumn(pqt.NewColumn("content", pqt.TypeText(), pqt.WithNotNull())). AddUnique(title, lead) comment := pqt.NewTable("comment", pqt.WithTableIfNotExists()). AddColumn(pqt.NewColumn("id", pqt.TypeSerialBig())). AddColumn(pqt.NewColumn("content", pqt.TypeText(), pqt.WithNotNull())). AddColumn(pqt.NewColumn( "news_title", pqt.TypeText(), pqt.WithNotNull(), pqt.WithReference(title, pqt.WithBidirectional(), pqt.WithOwnerName("comments_by_news_title"), pqt.WithInversedName("news_by_title")), )) category := pqt.NewTable("category", pqt.WithTableIfNotExists()). AddColumn(pqt.NewColumn("id", pqt.TypeSerialBig(), pqt.WithPrimaryKey())). AddColumn(pqt.NewColumn("name", pqt.TypeText(), pqt.WithNotNull())). AddColumn(pqt.NewColumn("content", pqt.TypeText(), pqt.WithNotNull())). AddRelationship( pqt.OneToMany( pqt.SelfReference(), pqt.WithBidirectional(), pqt.WithInversedName("child_category"), pqt.WithOwnerName("parent_category"), pqt.WithColumnName("parent_id"), ), ) pkg := pqt.NewTable("package", pqt.WithTableIfNotExists()). AddColumn(pqt.NewColumn("id", pqt.TypeSerialBig(), pqt.WithPrimaryKey())). AddColumn(pqt.NewColumn("break", pqt.TypeText())). AddRelationship(pqt.ManyToOne( category, pqt.WithBidirectional(), )) timestampable(news) timestampable(comment) timestampable(category) timestampable(pkg) comment.AddRelationship(pqt.ManyToOne(news, pqt.WithBidirectional(), pqt.WithInversedName("news_by_id")), pqt.WithNotNull()) pqt.ManyToMany(category, news, pqt.WithBidirectional()) return pqt.NewSchema(sn, pqt.WithSchemaIfNotExists()). AddTable(category). AddTable(pkg). AddTable(news). AddTable(comment) }
func TestWithColumnName(t *testing.T) { icn := "author" t1 := pqt.NewTable("user").AddColumn(pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey())) t2 := pqt.NewTable("comment") t2.AddRelationship(pqt.OneToOne(t1, pqt.WithColumnName(icn))) if len(t1.InversedRelationships) != 0 { t.Fatalf("user table should have exactly 0 relationship, got %d", len(t1.InversedRelationships)) } if len(t2.OwnedRelationships) != 1 { t.Fatalf("comment table should have exactly 1 relationship, got %d", len(t2.OwnedRelationships)) } var exists bool for _, c := range t2.Columns { if c.Name == icn { exists = true break } } if !exists { t.Errorf("comment table should have column with name %s", icn) } }
func TestTable_AddColumn(t *testing.T) { c0 := pqt.NewColumn("c0", pqt.TypeSerialBig(), pqt.WithPrimaryKey()) c1 := &pqt.Column{Name: "c1"} c2 := &pqt.Column{Name: "c2"} c3 := &pqt.Column{Name: "c3"} tbl := pqt.NewTable("test"). AddColumn(c0). AddColumn(c1). AddColumn(c2). AddColumn(c3). AddColumn(pqt.NewColumn("c4", pqt.TypeIntegerBig(), pqt.WithReference(c0))). AddRelationship(pqt.ManyToOne(pqt.SelfReference())) if len(tbl.Columns) != 6 { t.Errorf("wrong number of colums, expected %d but got %d", 6, len(tbl.Columns)) } if len(tbl.OwnedRelationships) != 2 { // Reference is not a relationship t.Errorf("wrong number of owned relationships, expected %d but got %d", 2, len(tbl.OwnedRelationships)) } for i, c := range tbl.Columns { if c.Name == "" { t.Errorf("column #%d table name is empty", i) } if c.Table == nil { t.Errorf("column #%d table nil pointer", i) } } }
func TestTable_AddRelationship_oneToOneSelfReferencing(t *testing.T) { user := pqt.NewTable("user").AddColumn(pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey())) user.AddRelationship(pqt.OneToOne( pqt.SelfReference(), pqt.WithInversedName("child"), pqt.WithOwnerName("parent"), )) if len(user.OwnedRelationships) != 1 { t.Fatalf("user should have 1 owned relationship, but has %d", len(user.OwnedRelationships)) } if user.OwnedRelationships[0].OwnerName != "parent" { t.Errorf("user relationship to user should be mapped by parent") } if user.OwnedRelationships[0].OwnerTable != user { t.Errorf("user relationship to user should be mapped by user table") } if user.OwnedRelationships[0].Type != pqt.RelationshipTypeOneToOne { t.Errorf("user relationship to user should be %d, but is %d", pqt.RelationshipTypeOneToOne, user.OwnedRelationships[0].Type) } if len(user.InversedRelationships) != 0 { t.Fatalf("user should have 0 inversed relationship, but has %d", len(user.InversedRelationships)) } }
func TestTable_AddRelationship_oneToOneUnidirectional(t *testing.T) { user := pqt.NewTable("user").AddColumn(pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey())) userDetail := pqt.NewTable("user_detail").AddColumn(pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey())). AddRelationship(pqt.OneToOne( user, pqt.WithInversedName("user"), pqt.WithOwnerName("details"), )) if len(user.InversedRelationships) != 0 { t.Fatalf("user should have 0 relationship, but has %d", len(user.InversedRelationships)) } if len(userDetail.OwnedRelationships) != 1 { t.Fatalf("user_detail should have 1 relationship, but has %d", len(userDetail.OwnedRelationships)) } if userDetail.OwnedRelationships[0].InversedName != "user" { t.Errorf("user_detail relationship to user should be mapped by user") } if userDetail.OwnedRelationships[0].InversedTable != user { t.Errorf("user_detail relationship to user should be mapped by user table") } if userDetail.OwnedRelationships[0].Type != pqt.RelationshipTypeOneToOne { t.Errorf("user_detail relationship to user should be %d, but is %d", pqt.RelationshipTypeOneToOne, userDetail.OwnedRelationships[0].Type) } }
func TestTable_AddRelationship_oneToMany(t *testing.T) { user := pqt.NewTable("user").AddColumn(pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey())) comment := pqt.NewTable("comment").AddColumn(pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey())) user.AddRelationship(pqt.OneToMany( comment, pqt.WithBidirectional(), pqt.WithInversedName("author"), pqt.WithOwnerName("comments"), )) if len(user.InversedRelationships) != 1 { t.Fatalf("user should have 1 inversed relationship, but has %d", len(user.InversedRelationships)) } if user.InversedRelationships[0].OwnerName != "comments" { t.Errorf("user inversed relationship to comment should be mapped by comments") } if user.InversedRelationships[0].OwnerTable != comment { t.Errorf("user inversed relationship to comment should be mapped by comment table") } if user.InversedRelationships[0].Type != pqt.RelationshipTypeOneToMany { t.Errorf("user inversed relationship to comment should be one to many") } if len(comment.OwnedRelationships) != 1 { t.Fatalf("comment should have 1 owned relationship, but has %d", len(comment.OwnedRelationships)) } if comment.OwnedRelationships[0].InversedName != "author" { t.Errorf("comment relationship to user should be mapped by author") } if comment.OwnedRelationships[0].InversedTable != user { t.Errorf("comment relationship to user should be mapped by user table") } if comment.OwnedRelationships[0].Type != pqt.RelationshipTypeOneToMany { t.Errorf("comment relationship to user should be %d, but is %d", pqt.RelationshipTypeOneToMany, comment.OwnedRelationships[0].Type) } }
func TestConstraint_Name(t *testing.T) { id := pqt.NewColumn("id", pqt.TypeSerial(), pqt.WithPrimaryKey()) success := map[string]*pqt.Constraint{ "public.user_id_pkey": pqt.PrimaryKey(pqt.NewTable("user"), id), "custom_schema.user_id_pkey": pqt.PrimaryKey(func() *pqt.Table { t := pqt.NewTable("user") s := pqt.NewSchema("custom_schema") s.AddTable(t) return t }(), id), "<missing table>": pqt.Check(nil, "a > b", id), "public.news_key": pqt.Unique(pqt.NewTable("news")), } for expected, given := range success { got := given.Name() if got != expected { t.Errorf("wrong name, expected %s got %s", expected, got) } } }
func TestNewColumn(t *testing.T) { collate := "UTF-7" check := "username = '******'" r := pqt.NewColumn("username", pqt.TypeText()) c := pqt.NewColumn( "user_username", pqt.TypeText(), pqt.WithCollate(collate), pqt.WithCheck(check), pqt.WithDefault("janusz"), pqt.WithUnique(), pqt.WithTypeMapping(pqtgo.BuiltinType(types.Byte)), pqt.WithNotNull(), pqt.WithPrimaryKey(), pqt.WithReference(r), ) if c.Type.String() != pqt.TypeText().String() { t.Errorf("wrong column type, expected %s but got %s", pqt.TypeText().String(), c.Type.String()) } if c.Collate != collate { t.Errorf("wrong column collate, expected %s but got %s", collate, c.Collate) } if c.Check != check { t.Errorf("wrong column check, expected %s but got %s", check, c.Check) } if d, ok := c.Default[pqt.EventInsert]; ok && d != "janusz" { t.Errorf("wrong column default, expected %s but got %s", "janusz", d) } if !c.Unique { t.Error("wrong column unique, expected true but got false") } if !c.NotNull { t.Error("wrong column not null, expected true but got false") } if !c.PrimaryKey { t.Error("wrong column primary key, expected true but got false") } if c.Reference != r { t.Errorf("wrong column reference, expected %p but got %p", r, c.Reference) } constraints := c.Constraints() if len(constraints) != 3 { t.Errorf("wrong number of constraints, expected 3 but got %d", len(constraints)) } var hasPK, hasFK, hasCH bool for _, constraint := range constraints { switch constraint.Type { case pqt.ConstraintTypePrimaryKey: hasPK = true case pqt.ConstraintTypeForeignKey: hasFK = true case pqt.ConstraintTypeCheck: hasCH = true } } if !hasPK { t.Errorf("mising primary key constraint") } if !hasFK { t.Errorf("mising foreign key constraint") } if !hasCH { t.Errorf("mising check constraint") } }