diff options
| -rw-r--r-- | migrations/003_create_posts_table.sql | 6 | ||||
| -rw-r--r-- | migrations/005_create_comments_tables.sql | 5 | ||||
| -rw-r--r-- | migrations/006_create_votes_table.sql | 2 | ||||
| -rw-r--r-- | src/models/boil_relationship_test.go | 32 | ||||
| -rw-r--r-- | src/models/boil_suites_test.go | 36 | ||||
| -rw-r--r-- | src/models/boil_table_names.go | 4 | ||||
| -rw-r--r-- | src/models/boil_types.go | 13 | ||||
| -rw-r--r-- | src/models/comments.go | 2284 | ||||
| -rw-r--r-- | src/models/comments_test.go | 1795 | ||||
| -rw-r--r-- | src/models/posts.go | 598 | ||||
| -rw-r--r-- | src/models/posts_test.go | 483 | ||||
| -rw-r--r-- | src/models/psql_suites_test.go | 4 | ||||
| -rw-r--r-- | src/models/tags.go | 4 | ||||
| -rw-r--r-- | src/models/users.go | 202 | ||||
| -rw-r--r-- | src/models/users_test.go | 153 | ||||
| -rw-r--r-- | src/models/votes.go | 1439 | ||||
| -rw-r--r-- | src/models/votes_test.go | 1072 | ||||
| -rw-r--r-- | src/post/hooks.go | 39 | ||||
| -rw-r--r-- | src/post/routes.go | 4 | ||||
| -rw-r--r-- | src/user/hooks.go | 10 | ||||
| -rw-r--r-- | src/user/routes.go | 2 |
21 files changed, 8036 insertions, 151 deletions
diff --git a/migrations/003_create_posts_table.sql b/migrations/003_create_posts_table.sql index 584b7b4..b8324d3 100644 --- a/migrations/003_create_posts_table.sql +++ b/migrations/003_create_posts_table.sql @@ -1,9 +1,12 @@ +CREATE TYPE postable_state AS ENUM ('hidden', 'visible'); + CREATE TABLE posts( id SERIAL NOT NULL PRIMARY KEY, - title VARCHAR(100) NOT NULL, + title VARCHAR(80) NOT NULL, description TEXT, url VARCHAR(255) UNIQUE, user_id INT NOT NULL REFERENCES users(id), + state postable_state DEFAULT 'visible', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); @@ -16,3 +19,4 @@ EXECUTE PROCEDURE trigger_set_timestamp(); ---- create above / drop below ---- DROP TABLE posts; +DROP TYPE postable_state; diff --git a/migrations/005_create_comments_tables.sql b/migrations/005_create_comments_tables.sql index 3717c0c..8abf274 100644 --- a/migrations/005_create_comments_tables.sql +++ b/migrations/005_create_comments_tables.sql @@ -1,12 +1,10 @@ -CREATE TYPE comment_state AS ENUM ('hidden', 'visible'); - CREATE TABLE comments( id SERIAL NOT NULL PRIMARY KEY, comment TEXT NOT NULL, user_id INT NOT NULL REFERENCES users(id), post_id INT NOT NULL REFERENCES posts(id) ON DELETE CASCADE, reply_id INT REFERENCES comments(id) ON DELETE CASCADE, - state comment_state DEFAULT 'visible', + state postable_state DEFAULT 'visible', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); @@ -19,4 +17,3 @@ EXECUTE PROCEDURE trigger_set_timestamp(); ---- create above / drop below ---- DROP TABLE comments; -DROP TYPE comment_state; diff --git a/migrations/006_create_votes_table.sql b/migrations/006_create_votes_table.sql index 8ed4c5f..ac73918 100644 --- a/migrations/006_create_votes_table.sql +++ b/migrations/006_create_votes_table.sql @@ -6,7 +6,7 @@ CREATE TABLE votes ( inc INT NOT NULL CHECK (inc in (-1, 1)), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - CONSTRAINT vote_pkey UNIQUE NULLS NOT DISTINCT (post_id, comment_id, user_id), + CONSTRAINT post_comment_user_pkey UNIQUE NULLS NOT DISTINCT (post_id, comment_id, user_id), CHECK ((post_id IS NOT NULL AND comment_id IS NULL) OR (comment_id IS NOT NULL AND post_id IS NULL)) ); diff --git a/src/models/boil_relationship_test.go b/src/models/boil_relationship_test.go index 191d17c..dad70c3 100644 --- a/src/models/boil_relationship_test.go +++ b/src/models/boil_relationship_test.go @@ -8,8 +8,13 @@ import "testing" // TestToOne tests cannot be run in parallel // or deadlocks can occur. func TestToOne(t *testing.T) { + t.Run("CommentToPostUsingPost", testCommentToOnePostUsingPost) + t.Run("CommentToCommentUsingReply", testCommentToOneCommentUsingReply) + t.Run("CommentToUserUsingUser", testCommentToOneUserUsingUser) t.Run("PostToUserUsingUser", testPostToOneUserUsingUser) t.Run("TagToUserUsingUser", testTagToOneUserUsingUser) + t.Run("VoteToCommentUsingComment", testVoteToOneCommentUsingComment) + t.Run("VoteToPostUsingPost", testVoteToOnePostUsingPost) } // TestOneToOne tests cannot be run in parallel @@ -19,8 +24,13 @@ func TestOneToOne(t *testing.T) {} // TestToMany tests cannot be run in parallel // or deadlocks can occur. func TestToMany(t *testing.T) { + t.Run("CommentToReplyComments", testCommentToManyReplyComments) + t.Run("CommentToVotes", testCommentToManyVotes) + t.Run("PostToComments", testPostToManyComments) t.Run("PostToTags", testPostToManyTags) + t.Run("PostToVotes", testPostToManyVotes) t.Run("TagToPosts", testTagToManyPosts) + t.Run("UserToComments", testUserToManyComments) t.Run("UserToPosts", testUserToManyPosts) t.Run("UserToTags", testUserToManyTags) } @@ -28,13 +38,22 @@ func TestToMany(t *testing.T) { // TestToOneSet tests cannot be run in parallel // or deadlocks can occur. func TestToOneSet(t *testing.T) { + t.Run("CommentToPostUsingComments", testCommentToOneSetOpPostUsingPost) + t.Run("CommentToCommentUsingReplyComments", testCommentToOneSetOpCommentUsingReply) + t.Run("CommentToUserUsingComments", testCommentToOneSetOpUserUsingUser) t.Run("PostToUserUsingPosts", testPostToOneSetOpUserUsingUser) t.Run("TagToUserUsingTags", testTagToOneSetOpUserUsingUser) + t.Run("VoteToCommentUsingVotes", testVoteToOneSetOpCommentUsingComment) + t.Run("VoteToPostUsingVotes", testVoteToOneSetOpPostUsingPost) } // TestToOneRemove tests cannot be run in parallel // or deadlocks can occur. -func TestToOneRemove(t *testing.T) {} +func TestToOneRemove(t *testing.T) { + t.Run("CommentToCommentUsingReplyComments", testCommentToOneRemoveOpCommentUsingReply) + t.Run("VoteToCommentUsingVotes", testVoteToOneRemoveOpCommentUsingComment) + t.Run("VoteToPostUsingVotes", testVoteToOneRemoveOpPostUsingPost) +} // TestOneToOneSet tests cannot be run in parallel // or deadlocks can occur. @@ -47,8 +66,13 @@ func TestOneToOneRemove(t *testing.T) {} // TestToManyAdd tests cannot be run in parallel // or deadlocks can occur. func TestToManyAdd(t *testing.T) { + t.Run("CommentToReplyComments", testCommentToManyAddOpReplyComments) + t.Run("CommentToVotes", testCommentToManyAddOpVotes) + t.Run("PostToComments", testPostToManyAddOpComments) t.Run("PostToTags", testPostToManyAddOpTags) + t.Run("PostToVotes", testPostToManyAddOpVotes) t.Run("TagToPosts", testTagToManyAddOpPosts) + t.Run("UserToComments", testUserToManyAddOpComments) t.Run("UserToPosts", testUserToManyAddOpPosts) t.Run("UserToTags", testUserToManyAddOpTags) } @@ -56,13 +80,19 @@ func TestToManyAdd(t *testing.T) { // TestToManySet tests cannot be run in parallel // or deadlocks can occur. func TestToManySet(t *testing.T) { + t.Run("CommentToReplyComments", testCommentToManySetOpReplyComments) + t.Run("CommentToVotes", testCommentToManySetOpVotes) t.Run("PostToTags", testPostToManySetOpTags) + t.Run("PostToVotes", testPostToManySetOpVotes) t.Run("TagToPosts", testTagToManySetOpPosts) } // TestToManyRemove tests cannot be run in parallel // or deadlocks can occur. func TestToManyRemove(t *testing.T) { + t.Run("CommentToReplyComments", testCommentToManyRemoveOpReplyComments) + t.Run("CommentToVotes", testCommentToManyRemoveOpVotes) t.Run("PostToTags", testPostToManyRemoveOpTags) + t.Run("PostToVotes", testPostToManyRemoveOpVotes) t.Run("TagToPosts", testTagToManyRemoveOpPosts) } diff --git a/src/models/boil_suites_test.go b/src/models/boil_suites_test.go index 33d14ea..0e93567 100644 --- a/src/models/boil_suites_test.go +++ b/src/models/boil_suites_test.go @@ -12,106 +12,142 @@ import "testing" // It does NOT run each operation group in parallel. // Separating the tests thusly grants avoidance of Postgres deadlocks. func TestParent(t *testing.T) { + t.Run("Comments", testComments) t.Run("Posts", testPosts) t.Run("Tags", testTags) t.Run("Users", testUsers) + t.Run("Votes", testVotes) } func TestDelete(t *testing.T) { + t.Run("Comments", testCommentsDelete) t.Run("Posts", testPostsDelete) t.Run("Tags", testTagsDelete) t.Run("Users", testUsersDelete) + t.Run("Votes", testVotesDelete) } func TestQueryDeleteAll(t *testing.T) { + t.Run("Comments", testCommentsQueryDeleteAll) t.Run("Posts", testPostsQueryDeleteAll) t.Run("Tags", testTagsQueryDeleteAll) t.Run("Users", testUsersQueryDeleteAll) + t.Run("Votes", testVotesQueryDeleteAll) } func TestSliceDeleteAll(t *testing.T) { + t.Run("Comments", testCommentsSliceDeleteAll) t.Run("Posts", testPostsSliceDeleteAll) t.Run("Tags", testTagsSliceDeleteAll) t.Run("Users", testUsersSliceDeleteAll) + t.Run("Votes", testVotesSliceDeleteAll) } func TestExists(t *testing.T) { + t.Run("Comments", testCommentsExists) t.Run("Posts", testPostsExists) t.Run("Tags", testTagsExists) t.Run("Users", testUsersExists) + t.Run("Votes", testVotesExists) } func TestFind(t *testing.T) { + t.Run("Comments", testCommentsFind) t.Run("Posts", testPostsFind) t.Run("Tags", testTagsFind) t.Run("Users", testUsersFind) + t.Run("Votes", testVotesFind) } func TestBind(t *testing.T) { + t.Run("Comments", testCommentsBind) t.Run("Posts", testPostsBind) t.Run("Tags", testTagsBind) t.Run("Users", testUsersBind) + t.Run("Votes", testVotesBind) } func TestOne(t *testing.T) { + t.Run("Comments", testCommentsOne) t.Run("Posts", testPostsOne) t.Run("Tags", testTagsOne) t.Run("Users", testUsersOne) + t.Run("Votes", testVotesOne) } func TestAll(t *testing.T) { + t.Run("Comments", testCommentsAll) t.Run("Posts", testPostsAll) t.Run("Tags", testTagsAll) t.Run("Users", testUsersAll) + t.Run("Votes", testVotesAll) } func TestCount(t *testing.T) { + t.Run("Comments", testCommentsCount) t.Run("Posts", testPostsCount) t.Run("Tags", testTagsCount) t.Run("Users", testUsersCount) + t.Run("Votes", testVotesCount) } func TestHooks(t *testing.T) { + t.Run("Comments", testCommentsHooks) t.Run("Posts", testPostsHooks) t.Run("Tags", testTagsHooks) t.Run("Users", testUsersHooks) + t.Run("Votes", testVotesHooks) } func TestInsert(t *testing.T) { + t.Run("Comments", testCommentsInsert) + t.Run("Comments", testCommentsInsertWhitelist) t.Run("Posts", testPostsInsert) t.Run("Posts", testPostsInsertWhitelist) t.Run("Tags", testTagsInsert) t.Run("Tags", testTagsInsertWhitelist) t.Run("Users", testUsersInsert) t.Run("Users", testUsersInsertWhitelist) + t.Run("Votes", testVotesInsert) + t.Run("Votes", testVotesInsertWhitelist) } func TestReload(t *testing.T) { + t.Run("Comments", testCommentsReload) t.Run("Posts", testPostsReload) t.Run("Tags", testTagsReload) t.Run("Users", testUsersReload) + t.Run("Votes", testVotesReload) } func TestReloadAll(t *testing.T) { + t.Run("Comments", testCommentsReloadAll) t.Run("Posts", testPostsReloadAll) t.Run("Tags", testTagsReloadAll) t.Run("Users", testUsersReloadAll) + t.Run("Votes", testVotesReloadAll) } func TestSelect(t *testing.T) { + t.Run("Comments", testCommentsSelect) t.Run("Posts", testPostsSelect) t.Run("Tags", testTagsSelect) t.Run("Users", testUsersSelect) + t.Run("Votes", testVotesSelect) } func TestUpdate(t *testing.T) { + t.Run("Comments", testCommentsUpdate) t.Run("Posts", testPostsUpdate) t.Run("Tags", testTagsUpdate) t.Run("Users", testUsersUpdate) + t.Run("Votes", testVotesUpdate) } func TestSliceUpdateAll(t *testing.T) { + t.Run("Comments", testCommentsSliceUpdateAll) t.Run("Posts", testPostsSliceUpdateAll) t.Run("Tags", testTagsSliceUpdateAll) t.Run("Users", testUsersSliceUpdateAll) + t.Run("Votes", testVotesSliceUpdateAll) } diff --git a/src/models/boil_table_names.go b/src/models/boil_table_names.go index 29a98ba..88dcf55 100644 --- a/src/models/boil_table_names.go +++ b/src/models/boil_table_names.go @@ -4,13 +4,17 @@ package models var TableNames = struct { + Comments string PostTags string Posts string Tags string Users string + Votes string }{ + Comments: "comments", PostTags: "post_tags", Posts: "posts", Tags: "tags", Users: "users", + Votes: "votes", } diff --git a/src/models/boil_types.go b/src/models/boil_types.go index f1157ed..dcf3eb2 100644 --- a/src/models/boil_types.go +++ b/src/models/boil_types.go @@ -50,3 +50,16 @@ func makeCacheKey(cols boil.Columns, nzDefaults []string) string { strmangle.PutBuffer(buf) return str } + +// Enum values for PostableState +const ( + PostableStateHidden string = "hidden" + PostableStateVisible string = "visible" +) + +func AllPostableState() []string { + return []string{ + PostableStateHidden, + PostableStateVisible, + } +} diff --git a/src/models/comments.go b/src/models/comments.go new file mode 100644 index 0000000..f3c0f94 --- /dev/null +++ b/src/models/comments.go @@ -0,0 +1,2284 @@ +// Code generated by SQLBoiler 4.16.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "database/sql" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/friendsofgo/errors" + "github.com/volatiletech/null/v8" + "github.com/volatiletech/sqlboiler/v4/boil" + "github.com/volatiletech/sqlboiler/v4/queries" + "github.com/volatiletech/sqlboiler/v4/queries/qm" + "github.com/volatiletech/sqlboiler/v4/queries/qmhelper" + "github.com/volatiletech/strmangle" +) + +// Comment is an object representing the database table. +type Comment struct { + ID int `boil:"id" json:"id" toml:"id" yaml:"id"` + Comment string `boil:"comment" json:"comment" toml:"comment" yaml:"comment"` + UserID int `boil:"user_id" json:"user_id" toml:"user_id" yaml:"user_id"` + PostID int `boil:"post_id" json:"post_id" toml:"post_id" yaml:"post_id"` + ReplyID null.Int `boil:"reply_id" json:"reply_id,omitempty" toml:"reply_id" yaml:"reply_id,omitempty"` + State null.String `boil:"state" json:"state,omitempty" toml:"state" yaml:"state,omitempty"` + CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"` + + R *commentR `boil:"-" json:"-" toml:"-" yaml:"-"` + L commentL `boil:"-" json:"-" toml:"-" yaml:"-"` +} + +var CommentColumns = struct { + ID string + Comment string + UserID string + PostID string + ReplyID string + State string + CreatedAt string + UpdatedAt string +}{ + ID: "id", + Comment: "comment", + UserID: "user_id", + PostID: "post_id", + ReplyID: "reply_id", + State: "state", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +var CommentTableColumns = struct { + ID string + Comment string + UserID string + PostID string + ReplyID string + State string + CreatedAt string + UpdatedAt string +}{ + ID: "comments.id", + Comment: "comments.comment", + UserID: "comments.user_id", + PostID: "comments.post_id", + ReplyID: "comments.reply_id", + State: "comments.state", + CreatedAt: "comments.created_at", + UpdatedAt: "comments.updated_at", +} + +// Generated where + +type whereHelperint struct{ field string } + +func (w whereHelperint) EQ(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } +func (w whereHelperint) NEQ(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } +func (w whereHelperint) LT(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } +func (w whereHelperint) LTE(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } +func (w whereHelperint) GT(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } +func (w whereHelperint) GTE(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } +func (w whereHelperint) IN(slice []int) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) +} +func (w whereHelperint) NIN(slice []int) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) +} + +type whereHelperstring struct{ field string } + +func (w whereHelperstring) EQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } +func (w whereHelperstring) NEQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } +func (w whereHelperstring) LT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } +func (w whereHelperstring) LTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } +func (w whereHelperstring) GT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } +func (w whereHelperstring) GTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } +func (w whereHelperstring) LIKE(x string) qm.QueryMod { return qm.Where(w.field+" LIKE ?", x) } +func (w whereHelperstring) NLIKE(x string) qm.QueryMod { return qm.Where(w.field+" NOT LIKE ?", x) } +func (w whereHelperstring) ILIKE(x string) qm.QueryMod { return qm.Where(w.field+" ILIKE ?", x) } +func (w whereHelperstring) NILIKE(x string) qm.QueryMod { return qm.Where(w.field+" NOT ILIKE ?", x) } +func (w whereHelperstring) IN(slice []string) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) +} +func (w whereHelperstring) NIN(slice []string) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) +} + +type whereHelpernull_Int struct{ field string } + +func (w whereHelpernull_Int) EQ(x null.Int) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, false, x) +} +func (w whereHelpernull_Int) NEQ(x null.Int) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, true, x) +} +func (w whereHelpernull_Int) LT(x null.Int) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LT, x) +} +func (w whereHelpernull_Int) LTE(x null.Int) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LTE, x) +} +func (w whereHelpernull_Int) GT(x null.Int) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GT, x) +} +func (w whereHelpernull_Int) GTE(x null.Int) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GTE, x) +} +func (w whereHelpernull_Int) IN(slice []int) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) +} +func (w whereHelpernull_Int) NIN(slice []int) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) +} + +func (w whereHelpernull_Int) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) } +func (w whereHelpernull_Int) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) } + +type whereHelpernull_String struct{ field string } + +func (w whereHelpernull_String) EQ(x null.String) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, false, x) +} +func (w whereHelpernull_String) NEQ(x null.String) qm.QueryMod { + return qmhelper.WhereNullEQ(w.field, true, x) +} +func (w whereHelpernull_String) LT(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LT, x) +} +func (w whereHelpernull_String) LTE(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LTE, x) +} +func (w whereHelpernull_String) GT(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GT, x) +} +func (w whereHelpernull_String) GTE(x null.String) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GTE, x) +} +func (w whereHelpernull_String) LIKE(x null.String) qm.QueryMod { + return qm.Where(w.field+" LIKE ?", x) +} +func (w whereHelpernull_String) NLIKE(x null.String) qm.QueryMod { + return qm.Where(w.field+" NOT LIKE ?", x) +} +func (w whereHelpernull_String) ILIKE(x null.String) qm.QueryMod { + return qm.Where(w.field+" ILIKE ?", x) +} +func (w whereHelpernull_String) NILIKE(x null.String) qm.QueryMod { + return qm.Where(w.field+" NOT ILIKE ?", x) +} +func (w whereHelpernull_String) IN(slice []string) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) +} +func (w whereHelpernull_String) NIN(slice []string) qm.QueryMod { + values := make([]interface{}, 0, len(slice)) + for _, value := range slice { + values = append(values, value) + } + return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) +} + +func (w whereHelpernull_String) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) } +func (w whereHelpernull_String) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) } + +type whereHelpertime_Time struct{ field string } + +func (w whereHelpertime_Time) EQ(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.EQ, x) +} +func (w whereHelpertime_Time) NEQ(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.NEQ, x) +} +func (w whereHelpertime_Time) LT(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LT, x) +} +func (w whereHelpertime_Time) LTE(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.LTE, x) +} +func (w whereHelpertime_Time) GT(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GT, x) +} +func (w whereHelpertime_Time) GTE(x time.Time) qm.QueryMod { + return qmhelper.Where(w.field, qmhelper.GTE, x) +} + +var CommentWhere = struct { + ID whereHelperint + Comment whereHelperstring + UserID whereHelperint + PostID whereHelperint + ReplyID whereHelpernull_Int + State whereHelpernull_String + CreatedAt whereHelpertime_Time + UpdatedAt whereHelpertime_Time +}{ + ID: whereHelperint{field: "\"comments\".\"id\""}, + Comment: whereHelperstring{field: "\"comments\".\"comment\""}, + UserID: whereHelperint{field: "\"comments\".\"user_id\""}, + PostID: whereHelperint{field: "\"comments\".\"post_id\""}, + ReplyID: whereHelpernull_Int{field: "\"comments\".\"reply_id\""}, + State: whereHelpernull_String{field: "\"comments\".\"state\""}, + CreatedAt: whereHelpertime_Time{field: "\"comments\".\"created_at\""}, + UpdatedAt: whereHelpertime_Time{field: "\"comments\".\"updated_at\""}, +} + +// CommentRels is where relationship names are stored. +var CommentRels = struct { + Post string + Reply string + User string + ReplyComments string + Votes string +}{ + Post: "Post", + Reply: "Reply", + User: "User", + ReplyComments: "ReplyComments", + Votes: "Votes", +} + +// commentR is where relationships are stored. +type commentR struct { + Post *Post `boil:"Post" json:"Post" toml:"Post" yaml:"Post"` + Reply *Comment `boil:"Reply" json:"Reply" toml:"Reply" yaml:"Reply"` + User *User `boil:"User" json:"User" toml:"User" yaml:"User"` + ReplyComments CommentSlice `boil:"ReplyComments" json:"ReplyComments" toml:"ReplyComments" yaml:"ReplyComments"` + Votes VoteSlice `boil:"Votes" json:"Votes" toml:"Votes" yaml:"Votes"` +} + +// NewStruct creates a new relationship struct +func (*commentR) NewStruct() *commentR { + return &commentR{} +} + +func (r *commentR) GetPost() *Post { + if r == nil { + return nil + } + return r.Post +} + +func (r *commentR) GetReply() *Comment { + if r == nil { + return nil + } + return r.Reply +} + +func (r *commentR) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +func (r *commentR) GetReplyComments() CommentSlice { + if r == nil { + return nil + } + return r.ReplyComments +} + +func (r *commentR) GetVotes() VoteSlice { + if r == nil { + return nil + } + return r.Votes +} + +// commentL is where Load methods for each relationship are stored. +type commentL struct{} + +var ( + commentAllColumns = []string{"id", "comment", "user_id", "post_id", "reply_id", "state", "created_at", "updated_at"} + commentColumnsWithoutDefault = []string{"comment", "user_id", "post_id"} + commentColumnsWithDefault = []string{"id", "reply_id", "state", "created_at", "updated_at"} + commentPrimaryKeyColumns = []string{"id"} + commentGeneratedColumns = []string{} +) + +type ( + // CommentSlice is an alias for a slice of pointers to Comment. + // This should almost always be used instead of []Comment. + CommentSlice []*Comment + // CommentHook is the signature for custom Comment hook methods + CommentHook func(context.Context, boil.ContextExecutor, *Comment) error + + commentQuery struct { + *queries.Query + } +) + +// Cache for insert, update and upsert +var ( + commentType = reflect.TypeOf(&Comment{}) + commentMapping = queries.MakeStructMapping(commentType) + commentPrimaryKeyMapping, _ = queries.BindMapping(commentType, commentMapping, commentPrimaryKeyColumns) + commentInsertCacheMut sync.RWMutex + commentInsertCache = make(map[string]insertCache) + commentUpdateCacheMut sync.RWMutex + commentUpdateCache = make(map[string]updateCache) + commentUpsertCacheMut sync.RWMutex + commentUpsertCache = make(map[string]insertCache) +) + +var ( + // Force time package dependency for automated UpdatedAt/CreatedAt. + _ = time.Second + // Force qmhelper dependency for where clause generation (which doesn't + // always happen) + _ = qmhelper.Where +) + +var commentAfterSelectMu sync.Mutex +var commentAfterSelectHooks []CommentHook + +var commentBeforeInsertMu sync.Mutex +var commentBeforeInsertHooks []CommentHook +var commentAfterInsertMu sync.Mutex +var commentAfterInsertHooks []CommentHook + +var commentBeforeUpdateMu sync.Mutex +var commentBeforeUpdateHooks []CommentHook +var commentAfterUpdateMu sync.Mutex +var commentAfterUpdateHooks []CommentHook + +var commentBeforeDeleteMu sync.Mutex +var commentBeforeDeleteHooks []CommentHook +var commentAfterDeleteMu sync.Mutex +var commentAfterDeleteHooks []CommentHook + +var commentBeforeUpsertMu sync.Mutex +var commentBeforeUpsertHooks []CommentHook +var commentAfterUpsertMu sync.Mutex +var commentAfterUpsertHooks []CommentHook + +// doAfterSelectHooks executes all "after Select" hooks. +func (o *Comment) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentAfterSelectHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeInsertHooks executes all "before insert" hooks. +func (o *Comment) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentBeforeInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterInsertHooks executes all "after Insert" hooks. +func (o *Comment) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentAfterInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpdateHooks executes all "before Update" hooks. +func (o *Comment) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentBeforeUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpdateHooks executes all "after Update" hooks. +func (o *Comment) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentAfterUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeDeleteHooks executes all "before Delete" hooks. +func (o *Comment) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentBeforeDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterDeleteHooks executes all "after Delete" hooks. +func (o *Comment) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentAfterDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpsertHooks executes all "before Upsert" hooks. +func (o *Comment) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentBeforeUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpsertHooks executes all "after Upsert" hooks. +func (o *Comment) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range commentAfterUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// AddCommentHook registers your hook function for all future operations. +func AddCommentHook(hookPoint boil.HookPoint, commentHook CommentHook) { + switch hookPoint { + case boil.AfterSelectHook: + commentAfterSelectMu.Lock() + commentAfterSelectHooks = append(commentAfterSelectHooks, commentHook) + commentAfterSelectMu.Unlock() + case boil.BeforeInsertHook: + commentBeforeInsertMu.Lock() + commentBeforeInsertHooks = append(commentBeforeInsertHooks, commentHook) + commentBeforeInsertMu.Unlock() + case boil.AfterInsertHook: + commentAfterInsertMu.Lock() + commentAfterInsertHooks = append(commentAfterInsertHooks, commentHook) + commentAfterInsertMu.Unlock() + case boil.BeforeUpdateHook: + commentBeforeUpdateMu.Lock() + commentBeforeUpdateHooks = append(commentBeforeUpdateHooks, commentHook) + commentBeforeUpdateMu.Unlock() + case boil.AfterUpdateHook: + commentAfterUpdateMu.Lock() + commentAfterUpdateHooks = append(commentAfterUpdateHooks, commentHook) + commentAfterUpdateMu.Unlock() + case boil.BeforeDeleteHook: + commentBeforeDeleteMu.Lock() + commentBeforeDeleteHooks = append(commentBeforeDeleteHooks, commentHook) + commentBeforeDeleteMu.Unlock() + case boil.AfterDeleteHook: + commentAfterDeleteMu.Lock() + commentAfterDeleteHooks = append(commentAfterDeleteHooks, commentHook) + commentAfterDeleteMu.Unlock() + case boil.BeforeUpsertHook: + commentBeforeUpsertMu.Lock() + commentBeforeUpsertHooks = append(commentBeforeUpsertHooks, commentHook) + commentBeforeUpsertMu.Unlock() + case boil.AfterUpsertHook: + commentAfterUpsertMu.Lock() + commentAfterUpsertHooks = append(commentAfterUpsertHooks, commentHook) + commentAfterUpsertMu.Unlock() + } +} + +// One returns a single comment record from the query. +func (q commentQuery) One(ctx context.Context, exec boil.ContextExecutor) (*Comment, error) { + o := &Comment{} + + queries.SetLimit(q.Query, 1) + + err := q.Bind(ctx, exec, o) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "models: failed to execute a one query for comments") + } + + if err := o.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + + return o, nil +} + +// All returns all Comment records from the query. +func (q commentQuery) All(ctx context.Context, exec boil.ContextExecutor) (CommentSlice, error) { + var o []*Comment + + err := q.Bind(ctx, exec, &o) + if err != nil { + return nil, errors.Wrap(err, "models: failed to assign all query results to Comment slice") + } + + if len(commentAfterSelectHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + } + } + + return o, nil +} + +// Count returns the count of all Comment records in the query. +func (q commentQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return 0, errors.Wrap(err, "models: failed to count comments rows") + } + + return count, nil +} + +// Exists checks if the row exists in the table. +func (q commentQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + queries.SetLimit(q.Query, 1) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return false, errors.Wrap(err, "models: failed to check if comments exists") + } + + return count > 0, nil +} + +// Post pointed to by the foreign key. +func (o *Comment) Post(mods ...qm.QueryMod) postQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.PostID), + } + + queryMods = append(queryMods, mods...) + + return Posts(queryMods...) +} + +// Reply pointed to by the foreign key. +func (o *Comment) Reply(mods ...qm.QueryMod) commentQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.ReplyID), + } + + queryMods = append(queryMods, mods...) + + return Comments(queryMods...) +} + +// User pointed to by the foreign key. +func (o *Comment) User(mods ...qm.QueryMod) userQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.UserID), + } + + queryMods = append(queryMods, mods...) + + return Users(queryMods...) +} + +// ReplyComments retrieves all the comment's Comments with an executor via reply_id column. +func (o *Comment) ReplyComments(mods ...qm.QueryMod) commentQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"comments\".\"reply_id\"=?", o.ID), + ) + + return Comments(queryMods...) +} + +// Votes retrieves all the vote's Votes with an executor. +func (o *Comment) Votes(mods ...qm.QueryMod) voteQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"votes\".\"comment_id\"=?", o.ID), + ) + + return Votes(queryMods...) +} + +// LoadPost allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (commentL) LoadPost(ctx context.Context, e boil.ContextExecutor, singular bool, maybeComment interface{}, mods queries.Applicator) error { + var slice []*Comment + var object *Comment + + if singular { + var ok bool + object, ok = maybeComment.(*Comment) + if !ok { + object = new(Comment) + ok = queries.SetFromEmbeddedStruct(&object, &maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeComment)) + } + } + } else { + s, ok := maybeComment.(*[]*Comment) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeComment)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &commentR{} + } + args[object.PostID] = struct{}{} + + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &commentR{} + } + + args[obj.PostID] = struct{}{} + + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`posts`), + qm.WhereIn(`posts.id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Post") + } + + var resultSlice []*Post + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Post") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for posts") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for posts") + } + + if len(postAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.Post = foreign + if foreign.R == nil { + foreign.R = &postR{} + } + foreign.R.Comments = append(foreign.R.Comments, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if local.PostID == foreign.ID { + local.R.Post = foreign + if foreign.R == nil { + foreign.R = &postR{} + } + foreign.R.Comments = append(foreign.R.Comments, local) + break + } + } + } + + return nil +} + +// LoadReply allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (commentL) LoadReply(ctx context.Context, e boil.ContextExecutor, singular bool, maybeComment interface{}, mods queries.Applicator) error { + var slice []*Comment + var object *Comment + + if singular { + var ok bool + object, ok = maybeComment.(*Comment) + if !ok { + object = new(Comment) + ok = queries.SetFromEmbeddedStruct(&object, &maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeComment)) + } + } + } else { + s, ok := maybeComment.(*[]*Comment) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeComment)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &commentR{} + } + if !queries.IsNil(object.ReplyID) { + args[object.ReplyID] = struct{}{} + } + + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &commentR{} + } + + if !queries.IsNil(obj.ReplyID) { + args[obj.ReplyID] = struct{}{} + } + + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`comments`), + qm.WhereIn(`comments.id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Comment") + } + + var resultSlice []*Comment + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Comment") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for comments") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for comments") + } + + if len(commentAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.Reply = foreign + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.ReplyComments = append(foreign.R.ReplyComments, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if queries.Equal(local.ReplyID, foreign.ID) { + local.R.Reply = foreign + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.ReplyComments = append(foreign.R.ReplyComments, local) + break + } + } + } + + return nil +} + +// LoadUser allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (commentL) LoadUser(ctx context.Context, e boil.ContextExecutor, singular bool, maybeComment interface{}, mods queries.Applicator) error { + var slice []*Comment + var object *Comment + + if singular { + var ok bool + object, ok = maybeComment.(*Comment) + if !ok { + object = new(Comment) + ok = queries.SetFromEmbeddedStruct(&object, &maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeComment)) + } + } + } else { + s, ok := maybeComment.(*[]*Comment) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeComment)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &commentR{} + } + args[object.UserID] = struct{}{} + + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &commentR{} + } + + args[obj.UserID] = struct{}{} + + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`users`), + qm.WhereIn(`users.id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load User") + } + + var resultSlice []*User + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice User") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for users") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for users") + } + + if len(userAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.User = foreign + if foreign.R == nil { + foreign.R = &userR{} + } + foreign.R.Comments = append(foreign.R.Comments, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if local.UserID == foreign.ID { + local.R.User = foreign + if foreign.R == nil { + foreign.R = &userR{} + } + foreign.R.Comments = append(foreign.R.Comments, local) + break + } + } + } + + return nil +} + +// LoadReplyComments allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (commentL) LoadReplyComments(ctx context.Context, e boil.ContextExecutor, singular bool, maybeComment interface{}, mods queries.Applicator) error { + var slice []*Comment + var object *Comment + + if singular { + var ok bool + object, ok = maybeComment.(*Comment) + if !ok { + object = new(Comment) + ok = queries.SetFromEmbeddedStruct(&object, &maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeComment)) + } + } + } else { + s, ok := maybeComment.(*[]*Comment) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeComment)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &commentR{} + } + args[object.ID] = struct{}{} + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &commentR{} + } + args[obj.ID] = struct{}{} + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`comments`), + qm.WhereIn(`comments.reply_id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load comments") + } + + var resultSlice []*Comment + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice comments") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on comments") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for comments") + } + + if len(commentAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.ReplyComments = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.Reply = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if queries.Equal(local.ID, foreign.ReplyID) { + local.R.ReplyComments = append(local.R.ReplyComments, foreign) + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.Reply = local + break + } + } + } + + return nil +} + +// LoadVotes allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (commentL) LoadVotes(ctx context.Context, e boil.ContextExecutor, singular bool, maybeComment interface{}, mods queries.Applicator) error { + var slice []*Comment + var object *Comment + + if singular { + var ok bool + object, ok = maybeComment.(*Comment) + if !ok { + object = new(Comment) + ok = queries.SetFromEmbeddedStruct(&object, &maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeComment)) + } + } + } else { + s, ok := maybeComment.(*[]*Comment) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeComment) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeComment)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &commentR{} + } + args[object.ID] = struct{}{} + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &commentR{} + } + args[obj.ID] = struct{}{} + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`votes`), + qm.WhereIn(`votes.comment_id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load votes") + } + + var resultSlice []*Vote + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice votes") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on votes") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for votes") + } + + if len(voteAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.Votes = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &voteR{} + } + foreign.R.Comment = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if queries.Equal(local.ID, foreign.CommentID) { + local.R.Votes = append(local.R.Votes, foreign) + if foreign.R == nil { + foreign.R = &voteR{} + } + foreign.R.Comment = local + break + } + } + } + + return nil +} + +// SetPost of the comment to the related item. +// Sets o.R.Post to related. +// Adds o to related.R.Comments. +func (o *Comment) SetPost(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Post) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"post_id"}), + strmangle.WhereClause("\"", "\"", 2, commentPrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + o.PostID = related.ID + if o.R == nil { + o.R = &commentR{ + Post: related, + } + } else { + o.R.Post = related + } + + if related.R == nil { + related.R = &postR{ + Comments: CommentSlice{o}, + } + } else { + related.R.Comments = append(related.R.Comments, o) + } + + return nil +} + +// SetReply of the comment to the related item. +// Sets o.R.Reply to related. +// Adds o to related.R.ReplyComments. +func (o *Comment) SetReply(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Comment) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"reply_id"}), + strmangle.WhereClause("\"", "\"", 2, commentPrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + queries.Assign(&o.ReplyID, related.ID) + if o.R == nil { + o.R = &commentR{ + Reply: related, + } + } else { + o.R.Reply = related + } + + if related.R == nil { + related.R = &commentR{ + ReplyComments: CommentSlice{o}, + } + } else { + related.R.ReplyComments = append(related.R.ReplyComments, o) + } + + return nil +} + +// RemoveReply relationship. +// Sets o.R.Reply to nil. +// Removes o from all passed in related items' relationships struct. +func (o *Comment) RemoveReply(ctx context.Context, exec boil.ContextExecutor, related *Comment) error { + var err error + + queries.SetScanner(&o.ReplyID, nil) + if _, err = o.Update(ctx, exec, boil.Whitelist("reply_id")); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + if o.R != nil { + o.R.Reply = nil + } + if related == nil || related.R == nil { + return nil + } + + for i, ri := range related.R.ReplyComments { + if queries.Equal(o.ReplyID, ri.ReplyID) { + continue + } + + ln := len(related.R.ReplyComments) + if ln > 1 && i < ln-1 { + related.R.ReplyComments[i] = related.R.ReplyComments[ln-1] + } + related.R.ReplyComments = related.R.ReplyComments[:ln-1] + break + } + return nil +} + +// SetUser of the comment to the related item. +// Sets o.R.User to related. +// Adds o to related.R.Comments. +func (o *Comment) SetUser(ctx context.Context, exec boil.ContextExecutor, insert bool, related *User) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"user_id"}), + strmangle.WhereClause("\"", "\"", 2, commentPrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + o.UserID = related.ID + if o.R == nil { + o.R = &commentR{ + User: related, + } + } else { + o.R.User = related + } + + if related.R == nil { + related.R = &userR{ + Comments: CommentSlice{o}, + } + } else { + related.R.Comments = append(related.R.Comments, o) + } + + return nil +} + +// AddReplyComments adds the given related objects to the existing relationships +// of the comment, optionally inserting them as new records. +// Appends related to o.R.ReplyComments. +// Sets related.R.Reply appropriately. +func (o *Comment) AddReplyComments(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Comment) error { + var err error + for _, rel := range related { + if insert { + queries.Assign(&rel.ReplyID, o.ID) + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"reply_id"}), + strmangle.WhereClause("\"", "\"", 2, commentPrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + queries.Assign(&rel.ReplyID, o.ID) + } + } + + if o.R == nil { + o.R = &commentR{ + ReplyComments: related, + } + } else { + o.R.ReplyComments = append(o.R.ReplyComments, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &commentR{ + Reply: o, + } + } else { + rel.R.Reply = o + } + } + return nil +} + +// SetReplyComments removes all previously related items of the +// comment replacing them completely with the passed +// in related items, optionally inserting them as new records. +// Sets o.R.Reply's ReplyComments accordingly. +// Replaces o.R.ReplyComments with related. +// Sets related.R.Reply's ReplyComments accordingly. +func (o *Comment) SetReplyComments(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Comment) error { + query := "update \"comments\" set \"reply_id\" = null where \"reply_id\" = $1" + values := []interface{}{o.ID} + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, query) + fmt.Fprintln(writer, values) + } + _, err := exec.ExecContext(ctx, query, values...) + if err != nil { + return errors.Wrap(err, "failed to remove relationships before set") + } + + if o.R != nil { + for _, rel := range o.R.ReplyComments { + queries.SetScanner(&rel.ReplyID, nil) + if rel.R == nil { + continue + } + + rel.R.Reply = nil + } + o.R.ReplyComments = nil + } + + return o.AddReplyComments(ctx, exec, insert, related...) +} + +// RemoveReplyComments relationships from objects passed in. +// Removes related items from R.ReplyComments (uses pointer comparison, removal does not keep order) +// Sets related.R.Reply. +func (o *Comment) RemoveReplyComments(ctx context.Context, exec boil.ContextExecutor, related ...*Comment) error { + if len(related) == 0 { + return nil + } + + var err error + for _, rel := range related { + queries.SetScanner(&rel.ReplyID, nil) + if rel.R != nil { + rel.R.Reply = nil + } + if _, err = rel.Update(ctx, exec, boil.Whitelist("reply_id")); err != nil { + return err + } + } + if o.R == nil { + return nil + } + + for _, rel := range related { + for i, ri := range o.R.ReplyComments { + if rel != ri { + continue + } + + ln := len(o.R.ReplyComments) + if ln > 1 && i < ln-1 { + o.R.ReplyComments[i] = o.R.ReplyComments[ln-1] + } + o.R.ReplyComments = o.R.ReplyComments[:ln-1] + break + } + } + + return nil +} + +// AddVotes adds the given related objects to the existing relationships +// of the comment, optionally inserting them as new records. +// Appends related to o.R.Votes. +// Sets related.R.Comment appropriately. +func (o *Comment) AddVotes(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Vote) error { + var err error + for _, rel := range related { + if insert { + queries.Assign(&rel.CommentID, o.ID) + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"votes\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"comment_id"}), + strmangle.WhereClause("\"", "\"", 2, votePrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + queries.Assign(&rel.CommentID, o.ID) + } + } + + if o.R == nil { + o.R = &commentR{ + Votes: related, + } + } else { + o.R.Votes = append(o.R.Votes, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &voteR{ + Comment: o, + } + } else { + rel.R.Comment = o + } + } + return nil +} + +// SetVotes removes all previously related items of the +// comment replacing them completely with the passed +// in related items, optionally inserting them as new records. +// Sets o.R.Comment's Votes accordingly. +// Replaces o.R.Votes with related. +// Sets related.R.Comment's Votes accordingly. +func (o *Comment) SetVotes(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Vote) error { + query := "update \"votes\" set \"comment_id\" = null where \"comment_id\" = $1" + values := []interface{}{o.ID} + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, query) + fmt.Fprintln(writer, values) + } + _, err := exec.ExecContext(ctx, query, values...) + if err != nil { + return errors.Wrap(err, "failed to remove relationships before set") + } + + if o.R != nil { + for _, rel := range o.R.Votes { + queries.SetScanner(&rel.CommentID, nil) + if rel.R == nil { + continue + } + + rel.R.Comment = nil + } + o.R.Votes = nil + } + + return o.AddVotes(ctx, exec, insert, related...) +} + +// RemoveVotes relationships from objects passed in. +// Removes related items from R.Votes (uses pointer comparison, removal does not keep order) +// Sets related.R.Comment. +func (o *Comment) RemoveVotes(ctx context.Context, exec boil.ContextExecutor, related ...*Vote) error { + if len(related) == 0 { + return nil + } + + var err error + for _, rel := range related { + queries.SetScanner(&rel.CommentID, nil) + if rel.R != nil { + rel.R.Comment = nil + } + if _, err = rel.Update(ctx, exec, boil.Whitelist("comment_id")); err != nil { + return err + } + } + if o.R == nil { + return nil + } + + for _, rel := range related { + for i, ri := range o.R.Votes { + if rel != ri { + continue + } + + ln := len(o.R.Votes) + if ln > 1 && i < ln-1 { + o.R.Votes[i] = o.R.Votes[ln-1] + } + o.R.Votes = o.R.Votes[:ln-1] + break + } + } + + return nil +} + +// Comments retrieves all the records using an executor. +func Comments(mods ...qm.QueryMod) commentQuery { + mods = append(mods, qm.From("\"comments\"")) + q := NewQuery(mods...) + if len(queries.GetSelect(q)) == 0 { + queries.SetSelect(q, []string{"\"comments\".*"}) + } + + return commentQuery{q} +} + +// FindComment retrieves a single record by ID with an executor. +// If selectCols is empty Find will return all columns. +func FindComment(ctx context.Context, exec boil.ContextExecutor, iD int, selectCols ...string) (*Comment, error) { + commentObj := &Comment{} + + sel := "*" + if len(selectCols) > 0 { + sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",") + } + query := fmt.Sprintf( + "select %s from \"comments\" where \"id\"=$1", sel, + ) + + q := queries.Raw(query, iD) + + err := q.Bind(ctx, exec, commentObj) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "models: unable to select from comments") + } + + if err = commentObj.doAfterSelectHooks(ctx, exec); err != nil { + return commentObj, err + } + + return commentObj, nil +} + +// Insert a single record using an executor. +// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts. +func (o *Comment) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error { + if o == nil { + return errors.New("models: no comments provided for insertion") + } + + var err error + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + if o.CreatedAt.IsZero() { + o.CreatedAt = currTime + } + if o.UpdatedAt.IsZero() { + o.UpdatedAt = currTime + } + } + + if err := o.doBeforeInsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(commentColumnsWithDefault, o) + + key := makeCacheKey(columns, nzDefaults) + commentInsertCacheMut.RLock() + cache, cached := commentInsertCache[key] + commentInsertCacheMut.RUnlock() + + if !cached { + wl, returnColumns := columns.InsertColumnSet( + commentAllColumns, + commentColumnsWithDefault, + commentColumnsWithoutDefault, + nzDefaults, + ) + + cache.valueMapping, err = queries.BindMapping(commentType, commentMapping, wl) + if err != nil { + return err + } + cache.retMapping, err = queries.BindMapping(commentType, commentMapping, returnColumns) + if err != nil { + return err + } + if len(wl) != 0 { + cache.query = fmt.Sprintf("INSERT INTO \"comments\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1)) + } else { + cache.query = "INSERT INTO \"comments\" %sDEFAULT VALUES%s" + } + + var queryOutput, queryReturning string + + if len(cache.retMapping) != 0 { + queryReturning = fmt.Sprintf(" RETURNING \"%s\"", strings.Join(returnColumns, "\",\"")) + } + + cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, vals) + } + + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + + if err != nil { + return errors.Wrap(err, "models: unable to insert into comments") + } + + if !cached { + commentInsertCacheMut.Lock() + commentInsertCache[key] = cache + commentInsertCacheMut.Unlock() + } + + return o.doAfterInsertHooks(ctx, exec) +} + +// Update uses an executor to update the Comment. +// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates. +// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records. +func (o *Comment) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) { + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + o.UpdatedAt = currTime + } + + var err error + if err = o.doBeforeUpdateHooks(ctx, exec); err != nil { + return 0, err + } + key := makeCacheKey(columns, nil) + commentUpdateCacheMut.RLock() + cache, cached := commentUpdateCache[key] + commentUpdateCacheMut.RUnlock() + + if !cached { + wl := columns.UpdateColumnSet( + commentAllColumns, + commentPrimaryKeyColumns, + ) + + if !columns.IsWhitelist() { + wl = strmangle.SetComplement(wl, []string{"created_at"}) + } + if len(wl) == 0 { + return 0, errors.New("models: unable to update comments, could not build whitelist") + } + + cache.query = fmt.Sprintf("UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, wl), + strmangle.WhereClause("\"", "\"", len(wl)+1, commentPrimaryKeyColumns), + ) + cache.valueMapping, err = queries.BindMapping(commentType, commentMapping, append(wl, commentPrimaryKeyColumns...)) + if err != nil { + return 0, err + } + } + + values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, values) + } + var result sql.Result + result, err = exec.ExecContext(ctx, cache.query, values...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update comments row") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by update for comments") + } + + if !cached { + commentUpdateCacheMut.Lock() + commentUpdateCache[key] = cache + commentUpdateCacheMut.Unlock() + } + + return rowsAff, o.doAfterUpdateHooks(ctx, exec) +} + +// UpdateAll updates all rows with the specified column values. +func (q commentQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + queries.SetUpdate(q.Query, cols) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update all for comments") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: unable to retrieve rows affected for comments") + } + + return rowsAff, nil +} + +// UpdateAll updates all rows with the specified column values, using an executor. +func (o CommentSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + ln := int64(len(o)) + if ln == 0 { + return 0, nil + } + + if len(cols) == 0 { + return 0, errors.New("models: update all requires at least one column argument") + } + + colNames := make([]string, len(cols)) + args := make([]interface{}, len(cols)) + + i := 0 + for name, value := range cols { + colNames[i] = name + args[i] = value + i++ + } + + // Append all of the primary key values for each column + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), commentPrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := fmt.Sprintf("UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, colNames), + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), len(colNames)+1, commentPrimaryKeyColumns, len(o))) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args...) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update all in comment slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: unable to retrieve rows affected all in update all comment") + } + return rowsAff, nil +} + +// Upsert attempts an insert using an executor, and does an update or ignore on conflict. +// See boil.Columns documentation for how to properly use updateColumns and insertColumns. +func (o *Comment) Upsert(ctx context.Context, exec boil.ContextExecutor, updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns, opts ...UpsertOptionFunc) error { + if o == nil { + return errors.New("models: no comments provided for upsert") + } + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + if o.CreatedAt.IsZero() { + o.CreatedAt = currTime + } + o.UpdatedAt = currTime + } + + if err := o.doBeforeUpsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(commentColumnsWithDefault, o) + + // Build cache key in-line uglily - mysql vs psql problems + buf := strmangle.GetBuffer() + if updateOnConflict { + buf.WriteByte('t') + } else { + buf.WriteByte('f') + } + buf.WriteByte('.') + for _, c := range conflictColumns { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(updateColumns.Kind)) + for _, c := range updateColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(insertColumns.Kind)) + for _, c := range insertColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + for _, c := range nzDefaults { + buf.WriteString(c) + } + key := buf.String() + strmangle.PutBuffer(buf) + + commentUpsertCacheMut.RLock() + cache, cached := commentUpsertCache[key] + commentUpsertCacheMut.RUnlock() + + var err error + + if !cached { + insert, _ := insertColumns.InsertColumnSet( + commentAllColumns, + commentColumnsWithDefault, + commentColumnsWithoutDefault, + nzDefaults, + ) + + update := updateColumns.UpdateColumnSet( + commentAllColumns, + commentPrimaryKeyColumns, + ) + + if updateOnConflict && len(update) == 0 { + return errors.New("models: unable to upsert comments, could not build update column list") + } + + ret := strmangle.SetComplement(commentAllColumns, strmangle.SetIntersect(insert, update)) + + conflict := conflictColumns + if len(conflict) == 0 && updateOnConflict && len(update) != 0 { + if len(commentPrimaryKeyColumns) == 0 { + return errors.New("models: unable to upsert comments, could not build conflict column list") + } + + conflict = make([]string, len(commentPrimaryKeyColumns)) + copy(conflict, commentPrimaryKeyColumns) + } + cache.query = buildUpsertQueryPostgres(dialect, "\"comments\"", updateOnConflict, ret, update, conflict, insert, opts...) + + cache.valueMapping, err = queries.BindMapping(commentType, commentMapping, insert) + if err != nil { + return err + } + if len(ret) != 0 { + cache.retMapping, err = queries.BindMapping(commentType, commentMapping, ret) + if err != nil { + return err + } + } + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + var returns []interface{} + if len(cache.retMapping) != 0 { + returns = queries.PtrsFromMapping(value, cache.retMapping) + } + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, vals) + } + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(returns...) + if errors.Is(err, sql.ErrNoRows) { + err = nil // Postgres doesn't return anything when there's no update + } + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + if err != nil { + return errors.Wrap(err, "models: unable to upsert comments") + } + + if !cached { + commentUpsertCacheMut.Lock() + commentUpsertCache[key] = cache + commentUpsertCacheMut.Unlock() + } + + return o.doAfterUpsertHooks(ctx, exec) +} + +// Delete deletes a single Comment record with an executor. +// Delete will match against the primary key column to find the record to delete. +func (o *Comment) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if o == nil { + return 0, errors.New("models: no Comment provided for delete") + } + + if err := o.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), commentPrimaryKeyMapping) + sql := "DELETE FROM \"comments\" WHERE \"id\"=$1" + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args...) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete from comments") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by delete for comments") + } + + if err := o.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + return rowsAff, nil +} + +// DeleteAll deletes all matching rows. +func (q commentQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if q.Query == nil { + return 0, errors.New("models: no commentQuery provided for delete all") + } + + queries.SetDelete(q.Query) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete all from comments") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by deleteall for comments") + } + + return rowsAff, nil +} + +// DeleteAll deletes all rows in the slice, using an executor. +func (o CommentSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if len(o) == 0 { + return 0, nil + } + + if len(commentBeforeDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + var args []interface{} + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), commentPrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "DELETE FROM \"comments\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, commentPrimaryKeyColumns, len(o)) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete all from comment slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by deleteall for comments") + } + + if len(commentAfterDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + return rowsAff, nil +} + +// Reload refetches the object from the database +// using the primary keys with an executor. +func (o *Comment) Reload(ctx context.Context, exec boil.ContextExecutor) error { + ret, err := FindComment(ctx, exec, o.ID) + if err != nil { + return err + } + + *o = *ret + return nil +} + +// ReloadAll refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *CommentSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error { + if o == nil || len(*o) == 0 { + return nil + } + + slice := CommentSlice{} + var args []interface{} + for _, obj := range *o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), commentPrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "SELECT \"comments\".* FROM \"comments\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, commentPrimaryKeyColumns, len(*o)) + + q := queries.Raw(sql, args...) + + err := q.Bind(ctx, exec, &slice) + if err != nil { + return errors.Wrap(err, "models: unable to reload all in CommentSlice") + } + + *o = slice + + return nil +} + +// CommentExists checks if the Comment row exists. +func CommentExists(ctx context.Context, exec boil.ContextExecutor, iD int) (bool, error) { + var exists bool + sql := "select exists(select 1 from \"comments\" where \"id\"=$1 limit 1)" + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, iD) + } + row := exec.QueryRowContext(ctx, sql, iD) + + err := row.Scan(&exists) + if err != nil { + return false, errors.Wrap(err, "models: unable to check if comments exists") + } + + return exists, nil +} + +// Exists checks if the Comment row exists. +func (o *Comment) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + return CommentExists(ctx, exec, o.ID) +} diff --git a/src/models/comments_test.go b/src/models/comments_test.go new file mode 100644 index 0000000..5d92a60 --- /dev/null +++ b/src/models/comments_test.go @@ -0,0 +1,1795 @@ +// Code generated by SQLBoiler 4.16.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "bytes" + "context" + "reflect" + "testing" + + "github.com/volatiletech/randomize" + "github.com/volatiletech/sqlboiler/v4/boil" + "github.com/volatiletech/sqlboiler/v4/queries" + "github.com/volatiletech/strmangle" +) + +var ( + // Relationships sometimes use the reflection helper queries.Equal/queries.Assign + // so force a package dependency in case they don't. + _ = queries.Equal +) + +func testComments(t *testing.T) { + t.Parallel() + + query := Comments() + + if query.Query == nil { + t.Error("expected a query, got nothing") + } +} + +func testCommentsDelete(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := o.Delete(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testCommentsQueryDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := Comments().DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testCommentsSliceDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := CommentSlice{o} + + if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testCommentsExists(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + e, err := CommentExists(ctx, tx, o.ID) + if err != nil { + t.Errorf("Unable to check if Comment exists: %s", err) + } + if !e { + t.Errorf("Expected CommentExists to return true, but got false.") + } +} + +func testCommentsFind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + commentFound, err := FindComment(ctx, tx, o.ID) + if err != nil { + t.Error(err) + } + + if commentFound == nil { + t.Error("want a record, got nil") + } +} + +func testCommentsBind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = Comments().Bind(ctx, tx, o); err != nil { + t.Error(err) + } +} + +func testCommentsOne(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if x, err := Comments().One(ctx, tx); err != nil { + t.Error(err) + } else if x == nil { + t.Error("expected to get a non nil record") + } +} + +func testCommentsAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + commentOne := &Comment{} + commentTwo := &Comment{} + if err = randomize.Struct(seed, commentOne, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + if err = randomize.Struct(seed, commentTwo, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = commentOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = commentTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Comments().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 2 { + t.Error("want 2 records, got:", len(slice)) + } +} + +func testCommentsCount(t *testing.T) { + t.Parallel() + + var err error + seed := randomize.NewSeed() + commentOne := &Comment{} + commentTwo := &Comment{} + if err = randomize.Struct(seed, commentOne, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + if err = randomize.Struct(seed, commentTwo, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = commentOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = commentTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 2 { + t.Error("want 2 records, got:", count) + } +} + +func commentBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func commentAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + *o = Comment{} + return nil +} + +func testCommentsHooks(t *testing.T) { + t.Parallel() + + var err error + + ctx := context.Background() + empty := &Comment{} + o := &Comment{} + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, o, commentDBTypes, false); err != nil { + t.Errorf("Unable to randomize Comment object: %s", err) + } + + AddCommentHook(boil.BeforeInsertHook, commentBeforeInsertHook) + if err = o.doBeforeInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o) + } + commentBeforeInsertHooks = []CommentHook{} + + AddCommentHook(boil.AfterInsertHook, commentAfterInsertHook) + if err = o.doAfterInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o) + } + commentAfterInsertHooks = []CommentHook{} + + AddCommentHook(boil.AfterSelectHook, commentAfterSelectHook) + if err = o.doAfterSelectHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterSelectHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o) + } + commentAfterSelectHooks = []CommentHook{} + + AddCommentHook(boil.BeforeUpdateHook, commentBeforeUpdateHook) + if err = o.doBeforeUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o) + } + commentBeforeUpdateHooks = []CommentHook{} + + AddCommentHook(boil.AfterUpdateHook, commentAfterUpdateHook) + if err = o.doAfterUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o) + } + commentAfterUpdateHooks = []CommentHook{} + + AddCommentHook(boil.BeforeDeleteHook, commentBeforeDeleteHook) + if err = o.doBeforeDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o) + } + commentBeforeDeleteHooks = []CommentHook{} + + AddCommentHook(boil.AfterDeleteHook, commentAfterDeleteHook) + if err = o.doAfterDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o) + } + commentAfterDeleteHooks = []CommentHook{} + + AddCommentHook(boil.BeforeUpsertHook, commentBeforeUpsertHook) + if err = o.doBeforeUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o) + } + commentBeforeUpsertHooks = []CommentHook{} + + AddCommentHook(boil.AfterUpsertHook, commentAfterUpsertHook) + if err = o.doAfterUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o) + } + commentAfterUpsertHooks = []CommentHook{} +} + +func testCommentsInsert(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testCommentsInsertWhitelist(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Whitelist(commentColumnsWithoutDefault...)); err != nil { + t.Error(err) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testCommentToManyReplyComments(t *testing.T) { + var err error + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = randomize.Struct(seed, &b, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Fatal(err) + } + + queries.Assign(&b.ReplyID, a.ID) + queries.Assign(&c.ReplyID, a.ID) + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := a.ReplyComments().All(ctx, tx) + if err != nil { + t.Fatal(err) + } + + bFound, cFound := false, false + for _, v := range check { + if queries.Equal(v.ReplyID, b.ReplyID) { + bFound = true + } + if queries.Equal(v.ReplyID, c.ReplyID) { + cFound = true + } + } + + if !bFound { + t.Error("expected to find b") + } + if !cFound { + t.Error("expected to find c") + } + + slice := CommentSlice{&a} + if err = a.L.LoadReplyComments(ctx, tx, false, (*[]*Comment)(&slice), nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.ReplyComments); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + a.R.ReplyComments = nil + if err = a.L.LoadReplyComments(ctx, tx, true, &a, nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.ReplyComments); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + if t.Failed() { + t.Logf("%#v", check) + } +} + +func testCommentToManyVotes(t *testing.T) { + var err error + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = randomize.Struct(seed, &b, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Fatal(err) + } + + queries.Assign(&b.CommentID, a.ID) + queries.Assign(&c.CommentID, a.ID) + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := a.Votes().All(ctx, tx) + if err != nil { + t.Fatal(err) + } + + bFound, cFound := false, false + for _, v := range check { + if queries.Equal(v.CommentID, b.CommentID) { + bFound = true + } + if queries.Equal(v.CommentID, c.CommentID) { + cFound = true + } + } + + if !bFound { + t.Error("expected to find b") + } + if !cFound { + t.Error("expected to find c") + } + + slice := CommentSlice{&a} + if err = a.L.LoadVotes(ctx, tx, false, (*[]*Comment)(&slice), nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Votes); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + a.R.Votes = nil + if err = a.L.LoadVotes(ctx, tx, true, &a, nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Votes); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + if t.Failed() { + t.Logf("%#v", check) + } +} + +func testCommentToManyAddOpReplyComments(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c, d, e Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Comment{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreignersSplitByInsertion := [][]*Comment{ + {&b, &c}, + {&d, &e}, + } + + for i, x := range foreignersSplitByInsertion { + err = a.AddReplyComments(ctx, tx, i != 0, x...) + if err != nil { + t.Fatal(err) + } + + first := x[0] + second := x[1] + + if !queries.Equal(a.ID, first.ReplyID) { + t.Error("foreign key was wrong value", a.ID, first.ReplyID) + } + if !queries.Equal(a.ID, second.ReplyID) { + t.Error("foreign key was wrong value", a.ID, second.ReplyID) + } + + if first.R.Reply != &a { + t.Error("relationship was not added properly to the foreign slice") + } + if second.R.Reply != &a { + t.Error("relationship was not added properly to the foreign slice") + } + + if a.R.ReplyComments[i*2] != first { + t.Error("relationship struct slice not set to correct value") + } + if a.R.ReplyComments[i*2+1] != second { + t.Error("relationship struct slice not set to correct value") + } + + count, err := a.ReplyComments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if want := int64((i + 1) * 2); count != want { + t.Error("want", want, "got", count) + } + } +} + +func testCommentToManySetOpReplyComments(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c, d, e Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Comment{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err = a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + err = a.SetReplyComments(ctx, tx, false, &b, &c) + if err != nil { + t.Fatal(err) + } + + count, err := a.ReplyComments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + err = a.SetReplyComments(ctx, tx, true, &d, &e) + if err != nil { + t.Fatal(err) + } + + count, err = a.ReplyComments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + if !queries.IsValuerNil(b.ReplyID) { + t.Error("want b's foreign key value to be nil") + } + if !queries.IsValuerNil(c.ReplyID) { + t.Error("want c's foreign key value to be nil") + } + if !queries.Equal(a.ID, d.ReplyID) { + t.Error("foreign key was wrong value", a.ID, d.ReplyID) + } + if !queries.Equal(a.ID, e.ReplyID) { + t.Error("foreign key was wrong value", a.ID, e.ReplyID) + } + + if b.R.Reply != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if c.R.Reply != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if d.R.Reply != &a { + t.Error("relationship was not added properly to the foreign struct") + } + if e.R.Reply != &a { + t.Error("relationship was not added properly to the foreign struct") + } + + if a.R.ReplyComments[0] != &d { + t.Error("relationship struct slice not set to correct value") + } + if a.R.ReplyComments[1] != &e { + t.Error("relationship struct slice not set to correct value") + } +} + +func testCommentToManyRemoveOpReplyComments(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c, d, e Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Comment{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + err = a.AddReplyComments(ctx, tx, true, foreigners...) + if err != nil { + t.Fatal(err) + } + + count, err := a.ReplyComments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 4 { + t.Error("count was wrong:", count) + } + + err = a.RemoveReplyComments(ctx, tx, foreigners[:2]...) + if err != nil { + t.Fatal(err) + } + + count, err = a.ReplyComments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + if !queries.IsValuerNil(b.ReplyID) { + t.Error("want b's foreign key value to be nil") + } + if !queries.IsValuerNil(c.ReplyID) { + t.Error("want c's foreign key value to be nil") + } + + if b.R.Reply != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if c.R.Reply != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if d.R.Reply != &a { + t.Error("relationship to a should have been preserved") + } + if e.R.Reply != &a { + t.Error("relationship to a should have been preserved") + } + + if len(a.R.ReplyComments) != 2 { + t.Error("should have preserved two relationships") + } + + // Removal doesn't do a stable deletion for performance so we have to flip the order + if a.R.ReplyComments[1] != &d { + t.Error("relationship to d should have been preserved") + } + if a.R.ReplyComments[0] != &e { + t.Error("relationship to e should have been preserved") + } +} + +func testCommentToManyAddOpVotes(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c, d, e Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Vote{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreignersSplitByInsertion := [][]*Vote{ + {&b, &c}, + {&d, &e}, + } + + for i, x := range foreignersSplitByInsertion { + err = a.AddVotes(ctx, tx, i != 0, x...) + if err != nil { + t.Fatal(err) + } + + first := x[0] + second := x[1] + + if !queries.Equal(a.ID, first.CommentID) { + t.Error("foreign key was wrong value", a.ID, first.CommentID) + } + if !queries.Equal(a.ID, second.CommentID) { + t.Error("foreign key was wrong value", a.ID, second.CommentID) + } + + if first.R.Comment != &a { + t.Error("relationship was not added properly to the foreign slice") + } + if second.R.Comment != &a { + t.Error("relationship was not added properly to the foreign slice") + } + + if a.R.Votes[i*2] != first { + t.Error("relationship struct slice not set to correct value") + } + if a.R.Votes[i*2+1] != second { + t.Error("relationship struct slice not set to correct value") + } + + count, err := a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if want := int64((i + 1) * 2); count != want { + t.Error("want", want, "got", count) + } + } +} + +func testCommentToManySetOpVotes(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c, d, e Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Vote{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err = a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + err = a.SetVotes(ctx, tx, false, &b, &c) + if err != nil { + t.Fatal(err) + } + + count, err := a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + err = a.SetVotes(ctx, tx, true, &d, &e) + if err != nil { + t.Fatal(err) + } + + count, err = a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + if !queries.IsValuerNil(b.CommentID) { + t.Error("want b's foreign key value to be nil") + } + if !queries.IsValuerNil(c.CommentID) { + t.Error("want c's foreign key value to be nil") + } + if !queries.Equal(a.ID, d.CommentID) { + t.Error("foreign key was wrong value", a.ID, d.CommentID) + } + if !queries.Equal(a.ID, e.CommentID) { + t.Error("foreign key was wrong value", a.ID, e.CommentID) + } + + if b.R.Comment != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if c.R.Comment != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if d.R.Comment != &a { + t.Error("relationship was not added properly to the foreign struct") + } + if e.R.Comment != &a { + t.Error("relationship was not added properly to the foreign struct") + } + + if a.R.Votes[0] != &d { + t.Error("relationship struct slice not set to correct value") + } + if a.R.Votes[1] != &e { + t.Error("relationship struct slice not set to correct value") + } +} + +func testCommentToManyRemoveOpVotes(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c, d, e Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Vote{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + err = a.AddVotes(ctx, tx, true, foreigners...) + if err != nil { + t.Fatal(err) + } + + count, err := a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 4 { + t.Error("count was wrong:", count) + } + + err = a.RemoveVotes(ctx, tx, foreigners[:2]...) + if err != nil { + t.Fatal(err) + } + + count, err = a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + if !queries.IsValuerNil(b.CommentID) { + t.Error("want b's foreign key value to be nil") + } + if !queries.IsValuerNil(c.CommentID) { + t.Error("want c's foreign key value to be nil") + } + + if b.R.Comment != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if c.R.Comment != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if d.R.Comment != &a { + t.Error("relationship to a should have been preserved") + } + if e.R.Comment != &a { + t.Error("relationship to a should have been preserved") + } + + if len(a.R.Votes) != 2 { + t.Error("should have preserved two relationships") + } + + // Removal doesn't do a stable deletion for performance so we have to flip the order + if a.R.Votes[1] != &d { + t.Error("relationship to d should have been preserved") + } + if a.R.Votes[0] != &e { + t.Error("relationship to e should have been preserved") + } +} + +func testCommentToOnePostUsingPost(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Comment + var foreign Post + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, postDBTypes, false, postColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Post struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + local.PostID = foreign.ID + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.Post().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if check.ID != foreign.ID { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + ranAfterSelectHook := false + AddPostHook(boil.AfterSelectHook, func(ctx context.Context, e boil.ContextExecutor, o *Post) error { + ranAfterSelectHook = true + return nil + }) + + slice := CommentSlice{&local} + if err = local.L.LoadPost(ctx, tx, false, (*[]*Comment)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.Post == nil { + t.Error("struct should have been eager loaded") + } + + local.R.Post = nil + if err = local.L.LoadPost(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.Post == nil { + t.Error("struct should have been eager loaded") + } + + if !ranAfterSelectHook { + t.Error("failed to run AfterSelect hook for relationship") + } +} + +func testCommentToOneCommentUsingReply(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Comment + var foreign Comment + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + queries.Assign(&local.ReplyID, foreign.ID) + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.Reply().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if !queries.Equal(check.ID, foreign.ID) { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + ranAfterSelectHook := false + AddCommentHook(boil.AfterSelectHook, func(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + ranAfterSelectHook = true + return nil + }) + + slice := CommentSlice{&local} + if err = local.L.LoadReply(ctx, tx, false, (*[]*Comment)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.Reply == nil { + t.Error("struct should have been eager loaded") + } + + local.R.Reply = nil + if err = local.L.LoadReply(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.Reply == nil { + t.Error("struct should have been eager loaded") + } + + if !ranAfterSelectHook { + t.Error("failed to run AfterSelect hook for relationship") + } +} + +func testCommentToOneUserUsingUser(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Comment + var foreign User + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, userDBTypes, false, userColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize User struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + local.UserID = foreign.ID + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.User().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if check.ID != foreign.ID { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + ranAfterSelectHook := false + AddUserHook(boil.AfterSelectHook, func(ctx context.Context, e boil.ContextExecutor, o *User) error { + ranAfterSelectHook = true + return nil + }) + + slice := CommentSlice{&local} + if err = local.L.LoadUser(ctx, tx, false, (*[]*Comment)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.User == nil { + t.Error("struct should have been eager loaded") + } + + local.R.User = nil + if err = local.L.LoadUser(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.User == nil { + t.Error("struct should have been eager loaded") + } + + if !ranAfterSelectHook { + t.Error("failed to run AfterSelect hook for relationship") + } +} + +func testCommentToOneSetOpPostUsingPost(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c Post + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Post{&b, &c} { + err = a.SetPost(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.Post != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.Comments[0] != &a { + t.Error("failed to append to foreign relationship struct") + } + if a.PostID != x.ID { + t.Error("foreign key was wrong value", a.PostID) + } + + zero := reflect.Zero(reflect.TypeOf(a.PostID)) + reflect.Indirect(reflect.ValueOf(&a.PostID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if a.PostID != x.ID { + t.Error("foreign key was wrong value", a.PostID, x.ID) + } + } +} +func testCommentToOneSetOpCommentUsingReply(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Comment{&b, &c} { + err = a.SetReply(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.Reply != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.ReplyComments[0] != &a { + t.Error("failed to append to foreign relationship struct") + } + if !queries.Equal(a.ReplyID, x.ID) { + t.Error("foreign key was wrong value", a.ReplyID) + } + + zero := reflect.Zero(reflect.TypeOf(a.ReplyID)) + reflect.Indirect(reflect.ValueOf(&a.ReplyID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if !queries.Equal(a.ReplyID, x.ID) { + t.Error("foreign key was wrong value", a.ReplyID, x.ID) + } + } +} + +func testCommentToOneRemoveOpCommentUsingReply(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err = a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = a.SetReply(ctx, tx, true, &b); err != nil { + t.Fatal(err) + } + + if err = a.RemoveReply(ctx, tx, &b); err != nil { + t.Error("failed to remove relationship") + } + + count, err := a.Reply().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 0 { + t.Error("want no relationships remaining") + } + + if a.R.Reply != nil { + t.Error("R struct entry should be nil") + } + + if !queries.IsValuerNil(a.ReplyID) { + t.Error("foreign key value should be nil") + } + + if len(b.R.ReplyComments) != 0 { + t.Error("failed to remove a from b's relationships") + } +} + +func testCommentToOneSetOpUserUsingUser(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Comment + var b, c User + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, userDBTypes, false, strmangle.SetComplement(userPrimaryKeyColumns, userColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, userDBTypes, false, strmangle.SetComplement(userPrimaryKeyColumns, userColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*User{&b, &c} { + err = a.SetUser(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.User != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.Comments[0] != &a { + t.Error("failed to append to foreign relationship struct") + } + if a.UserID != x.ID { + t.Error("foreign key was wrong value", a.UserID) + } + + zero := reflect.Zero(reflect.TypeOf(a.UserID)) + reflect.Indirect(reflect.ValueOf(&a.UserID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if a.UserID != x.ID { + t.Error("foreign key was wrong value", a.UserID, x.ID) + } + } +} + +func testCommentsReload(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = o.Reload(ctx, tx); err != nil { + t.Error(err) + } +} + +func testCommentsReloadAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := CommentSlice{o} + + if err = slice.ReloadAll(ctx, tx); err != nil { + t.Error(err) + } +} + +func testCommentsSelect(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Comments().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 1 { + t.Error("want one record, got:", len(slice)) + } +} + +var ( + commentDBTypes = map[string]string{`ID`: `integer`, `Comment`: `text`, `UserID`: `integer`, `PostID`: `integer`, `ReplyID`: `integer`, `State`: `enum.postable_state('hidden','visible')`, `CreatedAt`: `timestamp with time zone`, `UpdatedAt`: `timestamp with time zone`} + _ = bytes.MinRead +) + +func testCommentsUpdate(t *testing.T) { + t.Parallel() + + if 0 == len(commentPrimaryKeyColumns) { + t.Skip("Skipping table with no primary key columns") + } + if len(commentAllColumns) == len(commentPrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, commentDBTypes, true, commentPrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only affect one row but affected", rowsAff) + } +} + +func testCommentsSliceUpdateAll(t *testing.T) { + t.Parallel() + + if len(commentAllColumns) == len(commentPrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Comment{} + if err = randomize.Struct(seed, o, commentDBTypes, true, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, commentDBTypes, true, commentPrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + // Remove Primary keys and unique columns from what we plan to update + var fields []string + if strmangle.StringSliceMatch(commentAllColumns, commentPrimaryKeyColumns) { + fields = commentAllColumns + } else { + fields = strmangle.SetComplement( + commentAllColumns, + commentPrimaryKeyColumns, + ) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + typ := reflect.TypeOf(o).Elem() + n := typ.NumField() + + updateMap := M{} + for _, col := range fields { + for i := 0; i < n; i++ { + f := typ.Field(i) + if f.Tag.Get("boil") == col { + updateMap[col] = value.Field(i).Interface() + } + } + } + + slice := CommentSlice{o} + if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("wanted one record updated but got", rowsAff) + } +} + +func testCommentsUpsert(t *testing.T) { + t.Parallel() + + if len(commentAllColumns) == len(commentPrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + // Attempt the INSERT side of an UPSERT + o := Comment{} + if err = randomize.Struct(seed, &o, commentDBTypes, true); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Upsert(ctx, tx, false, nil, boil.Infer(), boil.Infer()); err != nil { + t.Errorf("Unable to upsert Comment: %s", err) + } + + count, err := Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 1 { + t.Error("want one record, got:", count) + } + + // Attempt the UPDATE side of an UPSERT + if err = randomize.Struct(seed, &o, commentDBTypes, false, commentPrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + if err = o.Upsert(ctx, tx, true, nil, boil.Infer(), boil.Infer()); err != nil { + t.Errorf("Unable to upsert Comment: %s", err) + } + + count, err = Comments().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 1 { + t.Error("want one record, got:", count) + } +} diff --git a/src/models/posts.go b/src/models/posts.go index 7fb455c..ed337d9 100644 --- a/src/models/posts.go +++ b/src/models/posts.go @@ -29,6 +29,7 @@ type Post struct { Description null.String `boil:"description" json:"description,omitempty" toml:"description" yaml:"description,omitempty"` URL null.String `boil:"url" json:"url,omitempty" toml:"url" yaml:"url,omitempty"` UserID int `boil:"user_id" json:"user_id" toml:"user_id" yaml:"user_id"` + State null.String `boil:"state" json:"state,omitempty" toml:"state" yaml:"state,omitempty"` CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"` @@ -42,6 +43,7 @@ var PostColumns = struct { Description string URL string UserID string + State string CreatedAt string UpdatedAt string }{ @@ -50,6 +52,7 @@ var PostColumns = struct { Description: "description", URL: "url", UserID: "user_id", + State: "state", CreatedAt: "created_at", UpdatedAt: "updated_at", } @@ -60,6 +63,7 @@ var PostTableColumns = struct { Description string URL string UserID string + State string CreatedAt string UpdatedAt string }{ @@ -68,139 +72,20 @@ var PostTableColumns = struct { Description: "posts.description", URL: "posts.url", UserID: "posts.user_id", + State: "posts.state", CreatedAt: "posts.created_at", UpdatedAt: "posts.updated_at", } // Generated where -type whereHelperint struct{ field string } - -func (w whereHelperint) EQ(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } -func (w whereHelperint) NEQ(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } -func (w whereHelperint) LT(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } -func (w whereHelperint) LTE(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } -func (w whereHelperint) GT(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } -func (w whereHelperint) GTE(x int) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } -func (w whereHelperint) IN(slice []int) qm.QueryMod { - values := make([]interface{}, 0, len(slice)) - for _, value := range slice { - values = append(values, value) - } - return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) -} -func (w whereHelperint) NIN(slice []int) qm.QueryMod { - values := make([]interface{}, 0, len(slice)) - for _, value := range slice { - values = append(values, value) - } - return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) -} - -type whereHelperstring struct{ field string } - -func (w whereHelperstring) EQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.EQ, x) } -func (w whereHelperstring) NEQ(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.NEQ, x) } -func (w whereHelperstring) LT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LT, x) } -func (w whereHelperstring) LTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.LTE, x) } -func (w whereHelperstring) GT(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GT, x) } -func (w whereHelperstring) GTE(x string) qm.QueryMod { return qmhelper.Where(w.field, qmhelper.GTE, x) } -func (w whereHelperstring) LIKE(x string) qm.QueryMod { return qm.Where(w.field+" LIKE ?", x) } -func (w whereHelperstring) NLIKE(x string) qm.QueryMod { return qm.Where(w.field+" NOT LIKE ?", x) } -func (w whereHelperstring) ILIKE(x string) qm.QueryMod { return qm.Where(w.field+" ILIKE ?", x) } -func (w whereHelperstring) NILIKE(x string) qm.QueryMod { return qm.Where(w.field+" NOT ILIKE ?", x) } -func (w whereHelperstring) IN(slice []string) qm.QueryMod { - values := make([]interface{}, 0, len(slice)) - for _, value := range slice { - values = append(values, value) - } - return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) -} -func (w whereHelperstring) NIN(slice []string) qm.QueryMod { - values := make([]interface{}, 0, len(slice)) - for _, value := range slice { - values = append(values, value) - } - return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) -} - -type whereHelpernull_String struct{ field string } - -func (w whereHelpernull_String) EQ(x null.String) qm.QueryMod { - return qmhelper.WhereNullEQ(w.field, false, x) -} -func (w whereHelpernull_String) NEQ(x null.String) qm.QueryMod { - return qmhelper.WhereNullEQ(w.field, true, x) -} -func (w whereHelpernull_String) LT(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.LT, x) -} -func (w whereHelpernull_String) LTE(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.LTE, x) -} -func (w whereHelpernull_String) GT(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.GT, x) -} -func (w whereHelpernull_String) GTE(x null.String) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.GTE, x) -} -func (w whereHelpernull_String) LIKE(x null.String) qm.QueryMod { - return qm.Where(w.field+" LIKE ?", x) -} -func (w whereHelpernull_String) NLIKE(x null.String) qm.QueryMod { - return qm.Where(w.field+" NOT LIKE ?", x) -} -func (w whereHelpernull_String) ILIKE(x null.String) qm.QueryMod { - return qm.Where(w.field+" ILIKE ?", x) -} -func (w whereHelpernull_String) NILIKE(x null.String) qm.QueryMod { - return qm.Where(w.field+" NOT ILIKE ?", x) -} -func (w whereHelpernull_String) IN(slice []string) qm.QueryMod { - values := make([]interface{}, 0, len(slice)) - for _, value := range slice { - values = append(values, value) - } - return qm.WhereIn(fmt.Sprintf("%s IN ?", w.field), values...) -} -func (w whereHelpernull_String) NIN(slice []string) qm.QueryMod { - values := make([]interface{}, 0, len(slice)) - for _, value := range slice { - values = append(values, value) - } - return qm.WhereNotIn(fmt.Sprintf("%s NOT IN ?", w.field), values...) -} - -func (w whereHelpernull_String) IsNull() qm.QueryMod { return qmhelper.WhereIsNull(w.field) } -func (w whereHelpernull_String) IsNotNull() qm.QueryMod { return qmhelper.WhereIsNotNull(w.field) } - -type whereHelpertime_Time struct{ field string } - -func (w whereHelpertime_Time) EQ(x time.Time) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.EQ, x) -} -func (w whereHelpertime_Time) NEQ(x time.Time) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.NEQ, x) -} -func (w whereHelpertime_Time) LT(x time.Time) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.LT, x) -} -func (w whereHelpertime_Time) LTE(x time.Time) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.LTE, x) -} -func (w whereHelpertime_Time) GT(x time.Time) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.GT, x) -} -func (w whereHelpertime_Time) GTE(x time.Time) qm.QueryMod { - return qmhelper.Where(w.field, qmhelper.GTE, x) -} - var PostWhere = struct { ID whereHelperint Title whereHelperstring Description whereHelpernull_String URL whereHelpernull_String UserID whereHelperint + State whereHelpernull_String CreatedAt whereHelpertime_Time UpdatedAt whereHelpertime_Time }{ @@ -209,23 +94,30 @@ var PostWhere = struct { Description: whereHelpernull_String{field: "\"posts\".\"description\""}, URL: whereHelpernull_String{field: "\"posts\".\"url\""}, UserID: whereHelperint{field: "\"posts\".\"user_id\""}, + State: whereHelpernull_String{field: "\"posts\".\"state\""}, CreatedAt: whereHelpertime_Time{field: "\"posts\".\"created_at\""}, UpdatedAt: whereHelpertime_Time{field: "\"posts\".\"updated_at\""}, } // PostRels is where relationship names are stored. var PostRels = struct { - User string - Tags string + User string + Comments string + Tags string + Votes string }{ - User: "User", - Tags: "Tags", + User: "User", + Comments: "Comments", + Tags: "Tags", + Votes: "Votes", } // postR is where relationships are stored. type postR struct { - User *User `boil:"User" json:"User" toml:"User" yaml:"User"` - Tags TagSlice `boil:"Tags" json:"Tags" toml:"Tags" yaml:"Tags"` + User *User `boil:"User" json:"User" toml:"User" yaml:"User"` + Comments CommentSlice `boil:"Comments" json:"Comments" toml:"Comments" yaml:"Comments"` + Tags TagSlice `boil:"Tags" json:"Tags" toml:"Tags" yaml:"Tags"` + Votes VoteSlice `boil:"Votes" json:"Votes" toml:"Votes" yaml:"Votes"` } // NewStruct creates a new relationship struct @@ -240,6 +132,13 @@ func (r *postR) GetUser() *User { return r.User } +func (r *postR) GetComments() CommentSlice { + if r == nil { + return nil + } + return r.Comments +} + func (r *postR) GetTags() TagSlice { if r == nil { return nil @@ -247,13 +146,20 @@ func (r *postR) GetTags() TagSlice { return r.Tags } +func (r *postR) GetVotes() VoteSlice { + if r == nil { + return nil + } + return r.Votes +} + // postL is where Load methods for each relationship are stored. type postL struct{} var ( - postAllColumns = []string{"id", "title", "description", "url", "user_id", "created_at", "updated_at"} + postAllColumns = []string{"id", "title", "description", "url", "user_id", "state", "created_at", "updated_at"} postColumnsWithoutDefault = []string{"title", "user_id"} - postColumnsWithDefault = []string{"id", "description", "url", "created_at", "updated_at"} + postColumnsWithDefault = []string{"id", "description", "url", "state", "created_at", "updated_at"} postPrimaryKeyColumns = []string{"id"} postGeneratedColumns = []string{} ) @@ -574,6 +480,20 @@ func (o *Post) User(mods ...qm.QueryMod) userQuery { return Users(queryMods...) } +// Comments retrieves all the comment's Comments with an executor. +func (o *Post) Comments(mods ...qm.QueryMod) commentQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"comments\".\"post_id\"=?", o.ID), + ) + + return Comments(queryMods...) +} + // Tags retrieves all the tag's Tags with an executor. func (o *Post) Tags(mods ...qm.QueryMod) tagQuery { var queryMods []qm.QueryMod @@ -589,6 +509,20 @@ func (o *Post) Tags(mods ...qm.QueryMod) tagQuery { return Tags(queryMods...) } +// Votes retrieves all the vote's Votes with an executor. +func (o *Post) Votes(mods ...qm.QueryMod) voteQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"votes\".\"post_id\"=?", o.ID), + ) + + return Votes(queryMods...) +} + // LoadUser allows an eager lookup of values, cached into the // loaded structs of the objects. This is for an N-1 relationship. func (postL) LoadUser(ctx context.Context, e boil.ContextExecutor, singular bool, maybePost interface{}, mods queries.Applicator) error { @@ -709,6 +643,119 @@ func (postL) LoadUser(ctx context.Context, e boil.ContextExecutor, singular bool return nil } +// LoadComments allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (postL) LoadComments(ctx context.Context, e boil.ContextExecutor, singular bool, maybePost interface{}, mods queries.Applicator) error { + var slice []*Post + var object *Post + + if singular { + var ok bool + object, ok = maybePost.(*Post) + if !ok { + object = new(Post) + ok = queries.SetFromEmbeddedStruct(&object, &maybePost) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybePost)) + } + } + } else { + s, ok := maybePost.(*[]*Post) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybePost) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybePost)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &postR{} + } + args[object.ID] = struct{}{} + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &postR{} + } + args[obj.ID] = struct{}{} + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`comments`), + qm.WhereIn(`comments.post_id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load comments") + } + + var resultSlice []*Comment + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice comments") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on comments") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for comments") + } + + if len(commentAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.Comments = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.Post = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if local.ID == foreign.PostID { + local.R.Comments = append(local.R.Comments, foreign) + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.Post = local + break + } + } + } + + return nil +} + // LoadTags allows an eager lookup of values, cached into the // loaded structs of the objects. This is for a 1-M or N-M relationship. func (postL) LoadTags(ctx context.Context, e boil.ContextExecutor, singular bool, maybePost interface{}, mods queries.Applicator) error { @@ -839,6 +886,119 @@ func (postL) LoadTags(ctx context.Context, e boil.ContextExecutor, singular bool return nil } +// LoadVotes allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (postL) LoadVotes(ctx context.Context, e boil.ContextExecutor, singular bool, maybePost interface{}, mods queries.Applicator) error { + var slice []*Post + var object *Post + + if singular { + var ok bool + object, ok = maybePost.(*Post) + if !ok { + object = new(Post) + ok = queries.SetFromEmbeddedStruct(&object, &maybePost) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybePost)) + } + } + } else { + s, ok := maybePost.(*[]*Post) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybePost) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybePost)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &postR{} + } + args[object.ID] = struct{}{} + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &postR{} + } + args[obj.ID] = struct{}{} + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`votes`), + qm.WhereIn(`votes.post_id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load votes") + } + + var resultSlice []*Vote + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice votes") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on votes") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for votes") + } + + if len(voteAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.Votes = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &voteR{} + } + foreign.R.Post = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if queries.Equal(local.ID, foreign.PostID) { + local.R.Votes = append(local.R.Votes, foreign) + if foreign.R == nil { + foreign.R = &voteR{} + } + foreign.R.Post = local + break + } + } + } + + return nil +} + // SetUser of the post to the related item. // Sets o.R.User to related. // Adds o to related.R.Posts. @@ -886,6 +1046,59 @@ func (o *Post) SetUser(ctx context.Context, exec boil.ContextExecutor, insert bo return nil } +// AddComments adds the given related objects to the existing relationships +// of the post, optionally inserting them as new records. +// Appends related to o.R.Comments. +// Sets related.R.Post appropriately. +func (o *Post) AddComments(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Comment) error { + var err error + for _, rel := range related { + if insert { + rel.PostID = o.ID + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"post_id"}), + strmangle.WhereClause("\"", "\"", 2, commentPrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + rel.PostID = o.ID + } + } + + if o.R == nil { + o.R = &postR{ + Comments: related, + } + } else { + o.R.Comments = append(o.R.Comments, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &commentR{ + Post: o, + } + } else { + rel.R.Post = o + } + } + return nil +} + // AddTags adds the given related objects to the existing relationships // of the post, optionally inserting them as new records. // Appends related to o.R.Tags. @@ -1031,6 +1244,133 @@ func removeTagsFromPostsSlice(o *Post, related []*Tag) { } } +// AddVotes adds the given related objects to the existing relationships +// of the post, optionally inserting them as new records. +// Appends related to o.R.Votes. +// Sets related.R.Post appropriately. +func (o *Post) AddVotes(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Vote) error { + var err error + for _, rel := range related { + if insert { + queries.Assign(&rel.PostID, o.ID) + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"votes\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"post_id"}), + strmangle.WhereClause("\"", "\"", 2, votePrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + queries.Assign(&rel.PostID, o.ID) + } + } + + if o.R == nil { + o.R = &postR{ + Votes: related, + } + } else { + o.R.Votes = append(o.R.Votes, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &voteR{ + Post: o, + } + } else { + rel.R.Post = o + } + } + return nil +} + +// SetVotes removes all previously related items of the +// post replacing them completely with the passed +// in related items, optionally inserting them as new records. +// Sets o.R.Post's Votes accordingly. +// Replaces o.R.Votes with related. +// Sets related.R.Post's Votes accordingly. +func (o *Post) SetVotes(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Vote) error { + query := "update \"votes\" set \"post_id\" = null where \"post_id\" = $1" + values := []interface{}{o.ID} + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, query) + fmt.Fprintln(writer, values) + } + _, err := exec.ExecContext(ctx, query, values...) + if err != nil { + return errors.Wrap(err, "failed to remove relationships before set") + } + + if o.R != nil { + for _, rel := range o.R.Votes { + queries.SetScanner(&rel.PostID, nil) + if rel.R == nil { + continue + } + + rel.R.Post = nil + } + o.R.Votes = nil + } + + return o.AddVotes(ctx, exec, insert, related...) +} + +// RemoveVotes relationships from objects passed in. +// Removes related items from R.Votes (uses pointer comparison, removal does not keep order) +// Sets related.R.Post. +func (o *Post) RemoveVotes(ctx context.Context, exec boil.ContextExecutor, related ...*Vote) error { + if len(related) == 0 { + return nil + } + + var err error + for _, rel := range related { + queries.SetScanner(&rel.PostID, nil) + if rel.R != nil { + rel.R.Post = nil + } + if _, err = rel.Update(ctx, exec, boil.Whitelist("post_id")); err != nil { + return err + } + } + if o.R == nil { + return nil + } + + for _, rel := range related { + for i, ri := range o.R.Votes { + if rel != ri { + continue + } + + ln := len(o.R.Votes) + if ln > 1 && i < ln-1 { + o.R.Votes[i] = o.R.Votes[ln-1] + } + o.R.Votes = o.R.Votes[:ln-1] + break + } + } + + return nil +} + // Posts retrieves all the records using an executor. func Posts(mods ...qm.QueryMod) postQuery { mods = append(mods, qm.From("\"posts\"")) diff --git a/src/models/posts_test.go b/src/models/posts_test.go index 578d483..3317ece 100644 --- a/src/models/posts_test.go +++ b/src/models/posts_test.go @@ -494,6 +494,84 @@ func testPostsInsertWhitelist(t *testing.T) { } } +func testPostToManyComments(t *testing.T) { + var err error + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Post + var b, c Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, postDBTypes, true, postColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Post struct: %s", err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = randomize.Struct(seed, &b, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Fatal(err) + } + + b.PostID = a.ID + c.PostID = a.ID + + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := a.Comments().All(ctx, tx) + if err != nil { + t.Fatal(err) + } + + bFound, cFound := false, false + for _, v := range check { + if v.PostID == b.PostID { + bFound = true + } + if v.PostID == c.PostID { + cFound = true + } + } + + if !bFound { + t.Error("expected to find b") + } + if !cFound { + t.Error("expected to find c") + } + + slice := PostSlice{&a} + if err = a.L.LoadComments(ctx, tx, false, (*[]*Post)(&slice), nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Comments); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + a.R.Comments = nil + if err = a.L.LoadComments(ctx, tx, true, &a, nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Comments); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + if t.Failed() { + t.Logf("%#v", check) + } +} + func testPostToManyTags(t *testing.T) { var err error ctx := context.Background() @@ -578,6 +656,158 @@ func testPostToManyTags(t *testing.T) { } } +func testPostToManyVotes(t *testing.T) { + var err error + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Post + var b, c Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, postDBTypes, true, postColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Post struct: %s", err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = randomize.Struct(seed, &b, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Fatal(err) + } + + queries.Assign(&b.PostID, a.ID) + queries.Assign(&c.PostID, a.ID) + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := a.Votes().All(ctx, tx) + if err != nil { + t.Fatal(err) + } + + bFound, cFound := false, false + for _, v := range check { + if queries.Equal(v.PostID, b.PostID) { + bFound = true + } + if queries.Equal(v.PostID, c.PostID) { + cFound = true + } + } + + if !bFound { + t.Error("expected to find b") + } + if !cFound { + t.Error("expected to find c") + } + + slice := PostSlice{&a} + if err = a.L.LoadVotes(ctx, tx, false, (*[]*Post)(&slice), nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Votes); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + a.R.Votes = nil + if err = a.L.LoadVotes(ctx, tx, true, &a, nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Votes); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + if t.Failed() { + t.Logf("%#v", check) + } +} + +func testPostToManyAddOpComments(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Post + var b, c, d, e Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Comment{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreignersSplitByInsertion := [][]*Comment{ + {&b, &c}, + {&d, &e}, + } + + for i, x := range foreignersSplitByInsertion { + err = a.AddComments(ctx, tx, i != 0, x...) + if err != nil { + t.Fatal(err) + } + + first := x[0] + second := x[1] + + if a.ID != first.PostID { + t.Error("foreign key was wrong value", a.ID, first.PostID) + } + if a.ID != second.PostID { + t.Error("foreign key was wrong value", a.ID, second.PostID) + } + + if first.R.Post != &a { + t.Error("relationship was not added properly to the foreign slice") + } + if second.R.Post != &a { + t.Error("relationship was not added properly to the foreign slice") + } + + if a.R.Comments[i*2] != first { + t.Error("relationship struct slice not set to correct value") + } + if a.R.Comments[i*2+1] != second { + t.Error("relationship struct slice not set to correct value") + } + + count, err := a.Comments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if want := int64((i + 1) * 2); count != want { + t.Error("want", want, "got", count) + } + } +} func testPostToManyAddOpTags(t *testing.T) { var err error @@ -806,6 +1036,257 @@ func testPostToManyRemoveOpTags(t *testing.T) { } } +func testPostToManyAddOpVotes(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Post + var b, c, d, e Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Vote{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreignersSplitByInsertion := [][]*Vote{ + {&b, &c}, + {&d, &e}, + } + + for i, x := range foreignersSplitByInsertion { + err = a.AddVotes(ctx, tx, i != 0, x...) + if err != nil { + t.Fatal(err) + } + + first := x[0] + second := x[1] + + if !queries.Equal(a.ID, first.PostID) { + t.Error("foreign key was wrong value", a.ID, first.PostID) + } + if !queries.Equal(a.ID, second.PostID) { + t.Error("foreign key was wrong value", a.ID, second.PostID) + } + + if first.R.Post != &a { + t.Error("relationship was not added properly to the foreign slice") + } + if second.R.Post != &a { + t.Error("relationship was not added properly to the foreign slice") + } + + if a.R.Votes[i*2] != first { + t.Error("relationship struct slice not set to correct value") + } + if a.R.Votes[i*2+1] != second { + t.Error("relationship struct slice not set to correct value") + } + + count, err := a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if want := int64((i + 1) * 2); count != want { + t.Error("want", want, "got", count) + } + } +} + +func testPostToManySetOpVotes(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Post + var b, c, d, e Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Vote{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err = a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + err = a.SetVotes(ctx, tx, false, &b, &c) + if err != nil { + t.Fatal(err) + } + + count, err := a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + err = a.SetVotes(ctx, tx, true, &d, &e) + if err != nil { + t.Fatal(err) + } + + count, err = a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + if !queries.IsValuerNil(b.PostID) { + t.Error("want b's foreign key value to be nil") + } + if !queries.IsValuerNil(c.PostID) { + t.Error("want c's foreign key value to be nil") + } + if !queries.Equal(a.ID, d.PostID) { + t.Error("foreign key was wrong value", a.ID, d.PostID) + } + if !queries.Equal(a.ID, e.PostID) { + t.Error("foreign key was wrong value", a.ID, e.PostID) + } + + if b.R.Post != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if c.R.Post != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if d.R.Post != &a { + t.Error("relationship was not added properly to the foreign struct") + } + if e.R.Post != &a { + t.Error("relationship was not added properly to the foreign struct") + } + + if a.R.Votes[0] != &d { + t.Error("relationship struct slice not set to correct value") + } + if a.R.Votes[1] != &e { + t.Error("relationship struct slice not set to correct value") + } +} + +func testPostToManyRemoveOpVotes(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Post + var b, c, d, e Vote + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Vote{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + err = a.AddVotes(ctx, tx, true, foreigners...) + if err != nil { + t.Fatal(err) + } + + count, err := a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 4 { + t.Error("count was wrong:", count) + } + + err = a.RemoveVotes(ctx, tx, foreigners[:2]...) + if err != nil { + t.Fatal(err) + } + + count, err = a.Votes().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if count != 2 { + t.Error("count was wrong:", count) + } + + if !queries.IsValuerNil(b.PostID) { + t.Error("want b's foreign key value to be nil") + } + if !queries.IsValuerNil(c.PostID) { + t.Error("want c's foreign key value to be nil") + } + + if b.R.Post != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if c.R.Post != nil { + t.Error("relationship was not removed properly from the foreign struct") + } + if d.R.Post != &a { + t.Error("relationship to a should have been preserved") + } + if e.R.Post != &a { + t.Error("relationship to a should have been preserved") + } + + if len(a.R.Votes) != 2 { + t.Error("should have preserved two relationships") + } + + // Removal doesn't do a stable deletion for performance so we have to flip the order + if a.R.Votes[1] != &d { + t.Error("relationship to d should have been preserved") + } + if a.R.Votes[0] != &e { + t.Error("relationship to e should have been preserved") + } +} + func testPostToOneUserUsingUser(t *testing.T) { ctx := context.Background() tx := MustTx(boil.BeginTx(ctx, nil)) @@ -999,7 +1480,7 @@ func testPostsSelect(t *testing.T) { } var ( - postDBTypes = map[string]string{`ID`: `integer`, `Title`: `character varying`, `Description`: `text`, `URL`: `character varying`, `UserID`: `integer`, `CreatedAt`: `timestamp with time zone`, `UpdatedAt`: `timestamp with time zone`} + postDBTypes = map[string]string{`ID`: `integer`, `Title`: `character varying`, `Description`: `text`, `URL`: `character varying`, `UserID`: `integer`, `State`: `enum.postable_state('hidden','visible')`, `CreatedAt`: `timestamp with time zone`, `UpdatedAt`: `timestamp with time zone`} _ = bytes.MinRead ) diff --git a/src/models/psql_suites_test.go b/src/models/psql_suites_test.go index b49f957..90699e5 100644 --- a/src/models/psql_suites_test.go +++ b/src/models/psql_suites_test.go @@ -6,9 +6,13 @@ package models import "testing" func TestUpsert(t *testing.T) { + t.Run("Comments", testCommentsUpsert) + t.Run("Posts", testPostsUpsert) t.Run("Tags", testTagsUpsert) t.Run("Users", testUsersUpsert) + + t.Run("Votes", testVotesUpsert) } diff --git a/src/models/tags.go b/src/models/tags.go index 707aa59..1a517c1 100644 --- a/src/models/tags.go +++ b/src/models/tags.go @@ -635,7 +635,7 @@ func (tagL) LoadPosts(ctx context.Context, e boil.ContextExecutor, singular bool } query := NewQuery( - qm.Select("\"posts\".\"id\", \"posts\".\"title\", \"posts\".\"description\", \"posts\".\"url\", \"posts\".\"user_id\", \"posts\".\"created_at\", \"posts\".\"updated_at\", \"a\".\"tag_id\""), + qm.Select("\"posts\".\"id\", \"posts\".\"title\", \"posts\".\"description\", \"posts\".\"url\", \"posts\".\"user_id\", \"posts\".\"state\", \"posts\".\"created_at\", \"posts\".\"updated_at\", \"a\".\"tag_id\""), qm.From("\"posts\""), qm.InnerJoin("\"post_tags\" as \"a\" on \"posts\".\"id\" = \"a\".\"post_id\""), qm.WhereIn("\"a\".\"tag_id\" in ?", argsSlice...), @@ -656,7 +656,7 @@ func (tagL) LoadPosts(ctx context.Context, e boil.ContextExecutor, singular bool one := new(Post) var localJoinCol int - err = results.Scan(&one.ID, &one.Title, &one.Description, &one.URL, &one.UserID, &one.CreatedAt, &one.UpdatedAt, &localJoinCol) + err = results.Scan(&one.ID, &one.Title, &one.Description, &one.URL, &one.UserID, &one.State, &one.CreatedAt, &one.UpdatedAt, &localJoinCol) if err != nil { return errors.Wrap(err, "failed to scan eager loaded results for posts") } diff --git a/src/models/users.go b/src/models/users.go index bdb6a31..8155a5d 100644 --- a/src/models/users.go +++ b/src/models/users.go @@ -87,17 +87,20 @@ var UserWhere = struct { // UserRels is where relationship names are stored. var UserRels = struct { - Posts string - Tags string + Comments string + Posts string + Tags string }{ - Posts: "Posts", - Tags: "Tags", + Comments: "Comments", + Posts: "Posts", + Tags: "Tags", } // userR is where relationships are stored. type userR struct { - Posts PostSlice `boil:"Posts" json:"Posts" toml:"Posts" yaml:"Posts"` - Tags TagSlice `boil:"Tags" json:"Tags" toml:"Tags" yaml:"Tags"` + Comments CommentSlice `boil:"Comments" json:"Comments" toml:"Comments" yaml:"Comments"` + Posts PostSlice `boil:"Posts" json:"Posts" toml:"Posts" yaml:"Posts"` + Tags TagSlice `boil:"Tags" json:"Tags" toml:"Tags" yaml:"Tags"` } // NewStruct creates a new relationship struct @@ -105,6 +108,13 @@ func (*userR) NewStruct() *userR { return &userR{} } +func (r *userR) GetComments() CommentSlice { + if r == nil { + return nil + } + return r.Comments +} + func (r *userR) GetPosts() PostSlice { if r == nil { return nil @@ -435,6 +445,20 @@ func (q userQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, return count > 0, nil } +// Comments retrieves all the comment's Comments with an executor. +func (o *User) Comments(mods ...qm.QueryMod) commentQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"comments\".\"user_id\"=?", o.ID), + ) + + return Comments(queryMods...) +} + // Posts retrieves all the post's Posts with an executor. func (o *User) Posts(mods ...qm.QueryMod) postQuery { var queryMods []qm.QueryMod @@ -463,6 +487,119 @@ func (o *User) Tags(mods ...qm.QueryMod) tagQuery { return Tags(queryMods...) } +// LoadComments allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (userL) LoadComments(ctx context.Context, e boil.ContextExecutor, singular bool, maybeUser interface{}, mods queries.Applicator) error { + var slice []*User + var object *User + + if singular { + var ok bool + object, ok = maybeUser.(*User) + if !ok { + object = new(User) + ok = queries.SetFromEmbeddedStruct(&object, &maybeUser) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeUser)) + } + } + } else { + s, ok := maybeUser.(*[]*User) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeUser) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeUser)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &userR{} + } + args[object.ID] = struct{}{} + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &userR{} + } + args[obj.ID] = struct{}{} + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`comments`), + qm.WhereIn(`comments.user_id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load comments") + } + + var resultSlice []*Comment + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice comments") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on comments") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for comments") + } + + if len(commentAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.Comments = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.User = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if local.ID == foreign.UserID { + local.R.Comments = append(local.R.Comments, foreign) + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.User = local + break + } + } + } + + return nil +} + // LoadPosts allows an eager lookup of values, cached into the // loaded structs of the objects. This is for a 1-M or N-M relationship. func (userL) LoadPosts(ctx context.Context, e boil.ContextExecutor, singular bool, maybeUser interface{}, mods queries.Applicator) error { @@ -689,6 +826,59 @@ func (userL) LoadTags(ctx context.Context, e boil.ContextExecutor, singular bool return nil } +// AddComments adds the given related objects to the existing relationships +// of the user, optionally inserting them as new records. +// Appends related to o.R.Comments. +// Sets related.R.User appropriately. +func (o *User) AddComments(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*Comment) error { + var err error + for _, rel := range related { + if insert { + rel.UserID = o.ID + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"comments\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"user_id"}), + strmangle.WhereClause("\"", "\"", 2, commentPrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + rel.UserID = o.ID + } + } + + if o.R == nil { + o.R = &userR{ + Comments: related, + } + } else { + o.R.Comments = append(o.R.Comments, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &commentR{ + User: o, + } + } else { + rel.R.User = o + } + } + return nil +} + // AddPosts adds the given related objects to the existing relationships // of the user, optionally inserting them as new records. // Appends related to o.R.Posts. diff --git a/src/models/users_test.go b/src/models/users_test.go index db6ca4c..212c86f 100644 --- a/src/models/users_test.go +++ b/src/models/users_test.go @@ -494,6 +494,84 @@ func testUsersInsertWhitelist(t *testing.T) { } } +func testUserToManyComments(t *testing.T) { + var err error + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a User + var b, c Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, userDBTypes, true, userColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize User struct: %s", err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = randomize.Struct(seed, &b, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Fatal(err) + } + + b.UserID = a.ID + c.UserID = a.ID + + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := a.Comments().All(ctx, tx) + if err != nil { + t.Fatal(err) + } + + bFound, cFound := false, false + for _, v := range check { + if v.UserID == b.UserID { + bFound = true + } + if v.UserID == c.UserID { + cFound = true + } + } + + if !bFound { + t.Error("expected to find b") + } + if !cFound { + t.Error("expected to find c") + } + + slice := UserSlice{&a} + if err = a.L.LoadComments(ctx, tx, false, (*[]*User)(&slice), nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Comments); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + a.R.Comments = nil + if err = a.L.LoadComments(ctx, tx, true, &a, nil); err != nil { + t.Fatal(err) + } + if got := len(a.R.Comments); got != 2 { + t.Error("number of eager loaded records wrong, got:", got) + } + + if t.Failed() { + t.Logf("%#v", check) + } +} + func testUserToManyPosts(t *testing.T) { var err error ctx := context.Background() @@ -650,6 +728,81 @@ func testUserToManyTags(t *testing.T) { } } +func testUserToManyAddOpComments(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a User + var b, c, d, e Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, userDBTypes, false, strmangle.SetComplement(userPrimaryKeyColumns, userColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + foreigners := []*Comment{&b, &c, &d, &e} + for _, x := range foreigners { + if err = randomize.Struct(seed, x, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = c.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + foreignersSplitByInsertion := [][]*Comment{ + {&b, &c}, + {&d, &e}, + } + + for i, x := range foreignersSplitByInsertion { + err = a.AddComments(ctx, tx, i != 0, x...) + if err != nil { + t.Fatal(err) + } + + first := x[0] + second := x[1] + + if a.ID != first.UserID { + t.Error("foreign key was wrong value", a.ID, first.UserID) + } + if a.ID != second.UserID { + t.Error("foreign key was wrong value", a.ID, second.UserID) + } + + if first.R.User != &a { + t.Error("relationship was not added properly to the foreign slice") + } + if second.R.User != &a { + t.Error("relationship was not added properly to the foreign slice") + } + + if a.R.Comments[i*2] != first { + t.Error("relationship struct slice not set to correct value") + } + if a.R.Comments[i*2+1] != second { + t.Error("relationship struct slice not set to correct value") + } + + count, err := a.Comments().Count(ctx, tx) + if err != nil { + t.Fatal(err) + } + if want := int64((i + 1) * 2); count != want { + t.Error("want", want, "got", count) + } + } +} func testUserToManyAddOpPosts(t *testing.T) { var err error diff --git a/src/models/votes.go b/src/models/votes.go new file mode 100644 index 0000000..4ce7fa9 --- /dev/null +++ b/src/models/votes.go @@ -0,0 +1,1439 @@ +// Code generated by SQLBoiler 4.16.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "database/sql" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/friendsofgo/errors" + "github.com/volatiletech/null/v8" + "github.com/volatiletech/sqlboiler/v4/boil" + "github.com/volatiletech/sqlboiler/v4/queries" + "github.com/volatiletech/sqlboiler/v4/queries/qm" + "github.com/volatiletech/sqlboiler/v4/queries/qmhelper" + "github.com/volatiletech/strmangle" +) + +// Vote is an object representing the database table. +type Vote struct { + ID int `boil:"id" json:"id" toml:"id" yaml:"id"` + PostID null.Int `boil:"post_id" json:"post_id,omitempty" toml:"post_id" yaml:"post_id,omitempty"` + CommentID null.Int `boil:"comment_id" json:"comment_id,omitempty" toml:"comment_id" yaml:"comment_id,omitempty"` + UserID int `boil:"user_id" json:"user_id" toml:"user_id" yaml:"user_id"` + Inc int `boil:"inc" json:"inc" toml:"inc" yaml:"inc"` + CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"` + + R *voteR `boil:"-" json:"-" toml:"-" yaml:"-"` + L voteL `boil:"-" json:"-" toml:"-" yaml:"-"` +} + +var VoteColumns = struct { + ID string + PostID string + CommentID string + UserID string + Inc string + CreatedAt string + UpdatedAt string +}{ + ID: "id", + PostID: "post_id", + CommentID: "comment_id", + UserID: "user_id", + Inc: "inc", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +var VoteTableColumns = struct { + ID string + PostID string + CommentID string + UserID string + Inc string + CreatedAt string + UpdatedAt string +}{ + ID: "votes.id", + PostID: "votes.post_id", + CommentID: "votes.comment_id", + UserID: "votes.user_id", + Inc: "votes.inc", + CreatedAt: "votes.created_at", + UpdatedAt: "votes.updated_at", +} + +// Generated where + +var VoteWhere = struct { + ID whereHelperint + PostID whereHelpernull_Int + CommentID whereHelpernull_Int + UserID whereHelperint + Inc whereHelperint + CreatedAt whereHelpertime_Time + UpdatedAt whereHelpertime_Time +}{ + ID: whereHelperint{field: "\"votes\".\"id\""}, + PostID: whereHelpernull_Int{field: "\"votes\".\"post_id\""}, + CommentID: whereHelpernull_Int{field: "\"votes\".\"comment_id\""}, + UserID: whereHelperint{field: "\"votes\".\"user_id\""}, + Inc: whereHelperint{field: "\"votes\".\"inc\""}, + CreatedAt: whereHelpertime_Time{field: "\"votes\".\"created_at\""}, + UpdatedAt: whereHelpertime_Time{field: "\"votes\".\"updated_at\""}, +} + +// VoteRels is where relationship names are stored. +var VoteRels = struct { + Comment string + Post string +}{ + Comment: "Comment", + Post: "Post", +} + +// voteR is where relationships are stored. +type voteR struct { + Comment *Comment `boil:"Comment" json:"Comment" toml:"Comment" yaml:"Comment"` + Post *Post `boil:"Post" json:"Post" toml:"Post" yaml:"Post"` +} + +// NewStruct creates a new relationship struct +func (*voteR) NewStruct() *voteR { + return &voteR{} +} + +func (r *voteR) GetComment() *Comment { + if r == nil { + return nil + } + return r.Comment +} + +func (r *voteR) GetPost() *Post { + if r == nil { + return nil + } + return r.Post +} + +// voteL is where Load methods for each relationship are stored. +type voteL struct{} + +var ( + voteAllColumns = []string{"id", "post_id", "comment_id", "user_id", "inc", "created_at", "updated_at"} + voteColumnsWithoutDefault = []string{"user_id", "inc"} + voteColumnsWithDefault = []string{"id", "post_id", "comment_id", "created_at", "updated_at"} + votePrimaryKeyColumns = []string{"id"} + voteGeneratedColumns = []string{} +) + +type ( + // VoteSlice is an alias for a slice of pointers to Vote. + // This should almost always be used instead of []Vote. + VoteSlice []*Vote + // VoteHook is the signature for custom Vote hook methods + VoteHook func(context.Context, boil.ContextExecutor, *Vote) error + + voteQuery struct { + *queries.Query + } +) + +// Cache for insert, update and upsert +var ( + voteType = reflect.TypeOf(&Vote{}) + voteMapping = queries.MakeStructMapping(voteType) + votePrimaryKeyMapping, _ = queries.BindMapping(voteType, voteMapping, votePrimaryKeyColumns) + voteInsertCacheMut sync.RWMutex + voteInsertCache = make(map[string]insertCache) + voteUpdateCacheMut sync.RWMutex + voteUpdateCache = make(map[string]updateCache) + voteUpsertCacheMut sync.RWMutex + voteUpsertCache = make(map[string]insertCache) +) + +var ( + // Force time package dependency for automated UpdatedAt/CreatedAt. + _ = time.Second + // Force qmhelper dependency for where clause generation (which doesn't + // always happen) + _ = qmhelper.Where +) + +var voteAfterSelectMu sync.Mutex +var voteAfterSelectHooks []VoteHook + +var voteBeforeInsertMu sync.Mutex +var voteBeforeInsertHooks []VoteHook +var voteAfterInsertMu sync.Mutex +var voteAfterInsertHooks []VoteHook + +var voteBeforeUpdateMu sync.Mutex +var voteBeforeUpdateHooks []VoteHook +var voteAfterUpdateMu sync.Mutex +var voteAfterUpdateHooks []VoteHook + +var voteBeforeDeleteMu sync.Mutex +var voteBeforeDeleteHooks []VoteHook +var voteAfterDeleteMu sync.Mutex +var voteAfterDeleteHooks []VoteHook + +var voteBeforeUpsertMu sync.Mutex +var voteBeforeUpsertHooks []VoteHook +var voteAfterUpsertMu sync.Mutex +var voteAfterUpsertHooks []VoteHook + +// doAfterSelectHooks executes all "after Select" hooks. +func (o *Vote) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteAfterSelectHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeInsertHooks executes all "before insert" hooks. +func (o *Vote) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteBeforeInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterInsertHooks executes all "after Insert" hooks. +func (o *Vote) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteAfterInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpdateHooks executes all "before Update" hooks. +func (o *Vote) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteBeforeUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpdateHooks executes all "after Update" hooks. +func (o *Vote) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteAfterUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeDeleteHooks executes all "before Delete" hooks. +func (o *Vote) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteBeforeDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterDeleteHooks executes all "after Delete" hooks. +func (o *Vote) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteAfterDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpsertHooks executes all "before Upsert" hooks. +func (o *Vote) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteBeforeUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpsertHooks executes all "after Upsert" hooks. +func (o *Vote) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range voteAfterUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// AddVoteHook registers your hook function for all future operations. +func AddVoteHook(hookPoint boil.HookPoint, voteHook VoteHook) { + switch hookPoint { + case boil.AfterSelectHook: + voteAfterSelectMu.Lock() + voteAfterSelectHooks = append(voteAfterSelectHooks, voteHook) + voteAfterSelectMu.Unlock() + case boil.BeforeInsertHook: + voteBeforeInsertMu.Lock() + voteBeforeInsertHooks = append(voteBeforeInsertHooks, voteHook) + voteBeforeInsertMu.Unlock() + case boil.AfterInsertHook: + voteAfterInsertMu.Lock() + voteAfterInsertHooks = append(voteAfterInsertHooks, voteHook) + voteAfterInsertMu.Unlock() + case boil.BeforeUpdateHook: + voteBeforeUpdateMu.Lock() + voteBeforeUpdateHooks = append(voteBeforeUpdateHooks, voteHook) + voteBeforeUpdateMu.Unlock() + case boil.AfterUpdateHook: + voteAfterUpdateMu.Lock() + voteAfterUpdateHooks = append(voteAfterUpdateHooks, voteHook) + voteAfterUpdateMu.Unlock() + case boil.BeforeDeleteHook: + voteBeforeDeleteMu.Lock() + voteBeforeDeleteHooks = append(voteBeforeDeleteHooks, voteHook) + voteBeforeDeleteMu.Unlock() + case boil.AfterDeleteHook: + voteAfterDeleteMu.Lock() + voteAfterDeleteHooks = append(voteAfterDeleteHooks, voteHook) + voteAfterDeleteMu.Unlock() + case boil.BeforeUpsertHook: + voteBeforeUpsertMu.Lock() + voteBeforeUpsertHooks = append(voteBeforeUpsertHooks, voteHook) + voteBeforeUpsertMu.Unlock() + case boil.AfterUpsertHook: + voteAfterUpsertMu.Lock() + voteAfterUpsertHooks = append(voteAfterUpsertHooks, voteHook) + voteAfterUpsertMu.Unlock() + } +} + +// One returns a single vote record from the query. +func (q voteQuery) One(ctx context.Context, exec boil.ContextExecutor) (*Vote, error) { + o := &Vote{} + + queries.SetLimit(q.Query, 1) + + err := q.Bind(ctx, exec, o) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "models: failed to execute a one query for votes") + } + + if err := o.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + + return o, nil +} + +// All returns all Vote records from the query. +func (q voteQuery) All(ctx context.Context, exec boil.ContextExecutor) (VoteSlice, error) { + var o []*Vote + + err := q.Bind(ctx, exec, &o) + if err != nil { + return nil, errors.Wrap(err, "models: failed to assign all query results to Vote slice") + } + + if len(voteAfterSelectHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + } + } + + return o, nil +} + +// Count returns the count of all Vote records in the query. +func (q voteQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return 0, errors.Wrap(err, "models: failed to count votes rows") + } + + return count, nil +} + +// Exists checks if the row exists in the table. +func (q voteQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + queries.SetLimit(q.Query, 1) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return false, errors.Wrap(err, "models: failed to check if votes exists") + } + + return count > 0, nil +} + +// Comment pointed to by the foreign key. +func (o *Vote) Comment(mods ...qm.QueryMod) commentQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.CommentID), + } + + queryMods = append(queryMods, mods...) + + return Comments(queryMods...) +} + +// Post pointed to by the foreign key. +func (o *Vote) Post(mods ...qm.QueryMod) postQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.PostID), + } + + queryMods = append(queryMods, mods...) + + return Posts(queryMods...) +} + +// LoadComment allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (voteL) LoadComment(ctx context.Context, e boil.ContextExecutor, singular bool, maybeVote interface{}, mods queries.Applicator) error { + var slice []*Vote + var object *Vote + + if singular { + var ok bool + object, ok = maybeVote.(*Vote) + if !ok { + object = new(Vote) + ok = queries.SetFromEmbeddedStruct(&object, &maybeVote) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeVote)) + } + } + } else { + s, ok := maybeVote.(*[]*Vote) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeVote) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeVote)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &voteR{} + } + if !queries.IsNil(object.CommentID) { + args[object.CommentID] = struct{}{} + } + + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &voteR{} + } + + if !queries.IsNil(obj.CommentID) { + args[obj.CommentID] = struct{}{} + } + + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`comments`), + qm.WhereIn(`comments.id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Comment") + } + + var resultSlice []*Comment + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Comment") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for comments") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for comments") + } + + if len(commentAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.Comment = foreign + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.Votes = append(foreign.R.Votes, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if queries.Equal(local.CommentID, foreign.ID) { + local.R.Comment = foreign + if foreign.R == nil { + foreign.R = &commentR{} + } + foreign.R.Votes = append(foreign.R.Votes, local) + break + } + } + } + + return nil +} + +// LoadPost allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (voteL) LoadPost(ctx context.Context, e boil.ContextExecutor, singular bool, maybeVote interface{}, mods queries.Applicator) error { + var slice []*Vote + var object *Vote + + if singular { + var ok bool + object, ok = maybeVote.(*Vote) + if !ok { + object = new(Vote) + ok = queries.SetFromEmbeddedStruct(&object, &maybeVote) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeVote)) + } + } + } else { + s, ok := maybeVote.(*[]*Vote) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeVote) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeVote)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &voteR{} + } + if !queries.IsNil(object.PostID) { + args[object.PostID] = struct{}{} + } + + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &voteR{} + } + + if !queries.IsNil(obj.PostID) { + args[obj.PostID] = struct{}{} + } + + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`posts`), + qm.WhereIn(`posts.id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Post") + } + + var resultSlice []*Post + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Post") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for posts") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for posts") + } + + if len(postAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.Post = foreign + if foreign.R == nil { + foreign.R = &postR{} + } + foreign.R.Votes = append(foreign.R.Votes, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if queries.Equal(local.PostID, foreign.ID) { + local.R.Post = foreign + if foreign.R == nil { + foreign.R = &postR{} + } + foreign.R.Votes = append(foreign.R.Votes, local) + break + } + } + } + + return nil +} + +// SetComment of the vote to the related item. +// Sets o.R.Comment to related. +// Adds o to related.R.Votes. +func (o *Vote) SetComment(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Comment) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"votes\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"comment_id"}), + strmangle.WhereClause("\"", "\"", 2, votePrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + queries.Assign(&o.CommentID, related.ID) + if o.R == nil { + o.R = &voteR{ + Comment: related, + } + } else { + o.R.Comment = related + } + + if related.R == nil { + related.R = &commentR{ + Votes: VoteSlice{o}, + } + } else { + related.R.Votes = append(related.R.Votes, o) + } + + return nil +} + +// RemoveComment relationship. +// Sets o.R.Comment to nil. +// Removes o from all passed in related items' relationships struct. +func (o *Vote) RemoveComment(ctx context.Context, exec boil.ContextExecutor, related *Comment) error { + var err error + + queries.SetScanner(&o.CommentID, nil) + if _, err = o.Update(ctx, exec, boil.Whitelist("comment_id")); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + if o.R != nil { + o.R.Comment = nil + } + if related == nil || related.R == nil { + return nil + } + + for i, ri := range related.R.Votes { + if queries.Equal(o.CommentID, ri.CommentID) { + continue + } + + ln := len(related.R.Votes) + if ln > 1 && i < ln-1 { + related.R.Votes[i] = related.R.Votes[ln-1] + } + related.R.Votes = related.R.Votes[:ln-1] + break + } + return nil +} + +// SetPost of the vote to the related item. +// Sets o.R.Post to related. +// Adds o to related.R.Votes. +func (o *Vote) SetPost(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Post) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"votes\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"post_id"}), + strmangle.WhereClause("\"", "\"", 2, votePrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.ID} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + queries.Assign(&o.PostID, related.ID) + if o.R == nil { + o.R = &voteR{ + Post: related, + } + } else { + o.R.Post = related + } + + if related.R == nil { + related.R = &postR{ + Votes: VoteSlice{o}, + } + } else { + related.R.Votes = append(related.R.Votes, o) + } + + return nil +} + +// RemovePost relationship. +// Sets o.R.Post to nil. +// Removes o from all passed in related items' relationships struct. +func (o *Vote) RemovePost(ctx context.Context, exec boil.ContextExecutor, related *Post) error { + var err error + + queries.SetScanner(&o.PostID, nil) + if _, err = o.Update(ctx, exec, boil.Whitelist("post_id")); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + if o.R != nil { + o.R.Post = nil + } + if related == nil || related.R == nil { + return nil + } + + for i, ri := range related.R.Votes { + if queries.Equal(o.PostID, ri.PostID) { + continue + } + + ln := len(related.R.Votes) + if ln > 1 && i < ln-1 { + related.R.Votes[i] = related.R.Votes[ln-1] + } + related.R.Votes = related.R.Votes[:ln-1] + break + } + return nil +} + +// Votes retrieves all the records using an executor. +func Votes(mods ...qm.QueryMod) voteQuery { + mods = append(mods, qm.From("\"votes\"")) + q := NewQuery(mods...) + if len(queries.GetSelect(q)) == 0 { + queries.SetSelect(q, []string{"\"votes\".*"}) + } + + return voteQuery{q} +} + +// FindVote retrieves a single record by ID with an executor. +// If selectCols is empty Find will return all columns. +func FindVote(ctx context.Context, exec boil.ContextExecutor, iD int, selectCols ...string) (*Vote, error) { + voteObj := &Vote{} + + sel := "*" + if len(selectCols) > 0 { + sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",") + } + query := fmt.Sprintf( + "select %s from \"votes\" where \"id\"=$1", sel, + ) + + q := queries.Raw(query, iD) + + err := q.Bind(ctx, exec, voteObj) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "models: unable to select from votes") + } + + if err = voteObj.doAfterSelectHooks(ctx, exec); err != nil { + return voteObj, err + } + + return voteObj, nil +} + +// Insert a single record using an executor. +// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts. +func (o *Vote) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error { + if o == nil { + return errors.New("models: no votes provided for insertion") + } + + var err error + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + if o.CreatedAt.IsZero() { + o.CreatedAt = currTime + } + if o.UpdatedAt.IsZero() { + o.UpdatedAt = currTime + } + } + + if err := o.doBeforeInsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(voteColumnsWithDefault, o) + + key := makeCacheKey(columns, nzDefaults) + voteInsertCacheMut.RLock() + cache, cached := voteInsertCache[key] + voteInsertCacheMut.RUnlock() + + if !cached { + wl, returnColumns := columns.InsertColumnSet( + voteAllColumns, + voteColumnsWithDefault, + voteColumnsWithoutDefault, + nzDefaults, + ) + + cache.valueMapping, err = queries.BindMapping(voteType, voteMapping, wl) + if err != nil { + return err + } + cache.retMapping, err = queries.BindMapping(voteType, voteMapping, returnColumns) + if err != nil { + return err + } + if len(wl) != 0 { + cache.query = fmt.Sprintf("INSERT INTO \"votes\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1)) + } else { + cache.query = "INSERT INTO \"votes\" %sDEFAULT VALUES%s" + } + + var queryOutput, queryReturning string + + if len(cache.retMapping) != 0 { + queryReturning = fmt.Sprintf(" RETURNING \"%s\"", strings.Join(returnColumns, "\",\"")) + } + + cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, vals) + } + + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + + if err != nil { + return errors.Wrap(err, "models: unable to insert into votes") + } + + if !cached { + voteInsertCacheMut.Lock() + voteInsertCache[key] = cache + voteInsertCacheMut.Unlock() + } + + return o.doAfterInsertHooks(ctx, exec) +} + +// Update uses an executor to update the Vote. +// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates. +// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records. +func (o *Vote) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) { + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + o.UpdatedAt = currTime + } + + var err error + if err = o.doBeforeUpdateHooks(ctx, exec); err != nil { + return 0, err + } + key := makeCacheKey(columns, nil) + voteUpdateCacheMut.RLock() + cache, cached := voteUpdateCache[key] + voteUpdateCacheMut.RUnlock() + + if !cached { + wl := columns.UpdateColumnSet( + voteAllColumns, + votePrimaryKeyColumns, + ) + + if !columns.IsWhitelist() { + wl = strmangle.SetComplement(wl, []string{"created_at"}) + } + if len(wl) == 0 { + return 0, errors.New("models: unable to update votes, could not build whitelist") + } + + cache.query = fmt.Sprintf("UPDATE \"votes\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, wl), + strmangle.WhereClause("\"", "\"", len(wl)+1, votePrimaryKeyColumns), + ) + cache.valueMapping, err = queries.BindMapping(voteType, voteMapping, append(wl, votePrimaryKeyColumns...)) + if err != nil { + return 0, err + } + } + + values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, values) + } + var result sql.Result + result, err = exec.ExecContext(ctx, cache.query, values...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update votes row") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by update for votes") + } + + if !cached { + voteUpdateCacheMut.Lock() + voteUpdateCache[key] = cache + voteUpdateCacheMut.Unlock() + } + + return rowsAff, o.doAfterUpdateHooks(ctx, exec) +} + +// UpdateAll updates all rows with the specified column values. +func (q voteQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + queries.SetUpdate(q.Query, cols) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update all for votes") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: unable to retrieve rows affected for votes") + } + + return rowsAff, nil +} + +// UpdateAll updates all rows with the specified column values, using an executor. +func (o VoteSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + ln := int64(len(o)) + if ln == 0 { + return 0, nil + } + + if len(cols) == 0 { + return 0, errors.New("models: update all requires at least one column argument") + } + + colNames := make([]string, len(cols)) + args := make([]interface{}, len(cols)) + + i := 0 + for name, value := range cols { + colNames[i] = name + args[i] = value + i++ + } + + // Append all of the primary key values for each column + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), votePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := fmt.Sprintf("UPDATE \"votes\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, colNames), + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), len(colNames)+1, votePrimaryKeyColumns, len(o))) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args...) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update all in vote slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: unable to retrieve rows affected all in update all vote") + } + return rowsAff, nil +} + +// Upsert attempts an insert using an executor, and does an update or ignore on conflict. +// See boil.Columns documentation for how to properly use updateColumns and insertColumns. +func (o *Vote) Upsert(ctx context.Context, exec boil.ContextExecutor, updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns, opts ...UpsertOptionFunc) error { + if o == nil { + return errors.New("models: no votes provided for upsert") + } + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + if o.CreatedAt.IsZero() { + o.CreatedAt = currTime + } + o.UpdatedAt = currTime + } + + if err := o.doBeforeUpsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(voteColumnsWithDefault, o) + + // Build cache key in-line uglily - mysql vs psql problems + buf := strmangle.GetBuffer() + if updateOnConflict { + buf.WriteByte('t') + } else { + buf.WriteByte('f') + } + buf.WriteByte('.') + for _, c := range conflictColumns { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(updateColumns.Kind)) + for _, c := range updateColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(insertColumns.Kind)) + for _, c := range insertColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + for _, c := range nzDefaults { + buf.WriteString(c) + } + key := buf.String() + strmangle.PutBuffer(buf) + + voteUpsertCacheMut.RLock() + cache, cached := voteUpsertCache[key] + voteUpsertCacheMut.RUnlock() + + var err error + + if !cached { + insert, _ := insertColumns.InsertColumnSet( + voteAllColumns, + voteColumnsWithDefault, + voteColumnsWithoutDefault, + nzDefaults, + ) + + update := updateColumns.UpdateColumnSet( + voteAllColumns, + votePrimaryKeyColumns, + ) + + if updateOnConflict && len(update) == 0 { + return errors.New("models: unable to upsert votes, could not build update column list") + } + + ret := strmangle.SetComplement(voteAllColumns, strmangle.SetIntersect(insert, update)) + + conflict := conflictColumns + if len(conflict) == 0 && updateOnConflict && len(update) != 0 { + if len(votePrimaryKeyColumns) == 0 { + return errors.New("models: unable to upsert votes, could not build conflict column list") + } + + conflict = make([]string, len(votePrimaryKeyColumns)) + copy(conflict, votePrimaryKeyColumns) + } + cache.query = buildUpsertQueryPostgres(dialect, "\"votes\"", updateOnConflict, ret, update, conflict, insert, opts...) + + cache.valueMapping, err = queries.BindMapping(voteType, voteMapping, insert) + if err != nil { + return err + } + if len(ret) != 0 { + cache.retMapping, err = queries.BindMapping(voteType, voteMapping, ret) + if err != nil { + return err + } + } + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + var returns []interface{} + if len(cache.retMapping) != 0 { + returns = queries.PtrsFromMapping(value, cache.retMapping) + } + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, vals) + } + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(returns...) + if errors.Is(err, sql.ErrNoRows) { + err = nil // Postgres doesn't return anything when there's no update + } + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + if err != nil { + return errors.Wrap(err, "models: unable to upsert votes") + } + + if !cached { + voteUpsertCacheMut.Lock() + voteUpsertCache[key] = cache + voteUpsertCacheMut.Unlock() + } + + return o.doAfterUpsertHooks(ctx, exec) +} + +// Delete deletes a single Vote record with an executor. +// Delete will match against the primary key column to find the record to delete. +func (o *Vote) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if o == nil { + return 0, errors.New("models: no Vote provided for delete") + } + + if err := o.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), votePrimaryKeyMapping) + sql := "DELETE FROM \"votes\" WHERE \"id\"=$1" + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args...) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete from votes") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by delete for votes") + } + + if err := o.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + return rowsAff, nil +} + +// DeleteAll deletes all matching rows. +func (q voteQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if q.Query == nil { + return 0, errors.New("models: no voteQuery provided for delete all") + } + + queries.SetDelete(q.Query) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete all from votes") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by deleteall for votes") + } + + return rowsAff, nil +} + +// DeleteAll deletes all rows in the slice, using an executor. +func (o VoteSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if len(o) == 0 { + return 0, nil + } + + if len(voteBeforeDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + var args []interface{} + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), votePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "DELETE FROM \"votes\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, votePrimaryKeyColumns, len(o)) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete all from vote slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by deleteall for votes") + } + + if len(voteAfterDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + return rowsAff, nil +} + +// Reload refetches the object from the database +// using the primary keys with an executor. +func (o *Vote) Reload(ctx context.Context, exec boil.ContextExecutor) error { + ret, err := FindVote(ctx, exec, o.ID) + if err != nil { + return err + } + + *o = *ret + return nil +} + +// ReloadAll refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *VoteSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error { + if o == nil || len(*o) == 0 { + return nil + } + + slice := VoteSlice{} + var args []interface{} + for _, obj := range *o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), votePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "SELECT \"votes\".* FROM \"votes\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, votePrimaryKeyColumns, len(*o)) + + q := queries.Raw(sql, args...) + + err := q.Bind(ctx, exec, &slice) + if err != nil { + return errors.Wrap(err, "models: unable to reload all in VoteSlice") + } + + *o = slice + + return nil +} + +// VoteExists checks if the Vote row exists. +func VoteExists(ctx context.Context, exec boil.ContextExecutor, iD int) (bool, error) { + var exists bool + sql := "select exists(select 1 from \"votes\" where \"id\"=$1 limit 1)" + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, iD) + } + row := exec.QueryRowContext(ctx, sql, iD) + + err := row.Scan(&exists) + if err != nil { + return false, errors.Wrap(err, "models: unable to check if votes exists") + } + + return exists, nil +} + +// Exists checks if the Vote row exists. +func (o *Vote) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + return VoteExists(ctx, exec, o.ID) +} diff --git a/src/models/votes_test.go b/src/models/votes_test.go new file mode 100644 index 0000000..c7f4f51 --- /dev/null +++ b/src/models/votes_test.go @@ -0,0 +1,1072 @@ +// Code generated by SQLBoiler 4.16.1 (https://github.com/volatiletech/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "bytes" + "context" + "reflect" + "testing" + + "github.com/volatiletech/randomize" + "github.com/volatiletech/sqlboiler/v4/boil" + "github.com/volatiletech/sqlboiler/v4/queries" + "github.com/volatiletech/strmangle" +) + +var ( + // Relationships sometimes use the reflection helper queries.Equal/queries.Assign + // so force a package dependency in case they don't. + _ = queries.Equal +) + +func testVotes(t *testing.T) { + t.Parallel() + + query := Votes() + + if query.Query == nil { + t.Error("expected a query, got nothing") + } +} + +func testVotesDelete(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := o.Delete(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testVotesQueryDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if rowsAff, err := Votes().DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testVotesSliceDeleteAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := VoteSlice{o} + + if rowsAff, err := slice.DeleteAll(ctx, tx); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only have deleted one row, but affected:", rowsAff) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 0 { + t.Error("want zero records, got:", count) + } +} + +func testVotesExists(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + e, err := VoteExists(ctx, tx, o.ID) + if err != nil { + t.Errorf("Unable to check if Vote exists: %s", err) + } + if !e { + t.Errorf("Expected VoteExists to return true, but got false.") + } +} + +func testVotesFind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + voteFound, err := FindVote(ctx, tx, o.ID) + if err != nil { + t.Error(err) + } + + if voteFound == nil { + t.Error("want a record, got nil") + } +} + +func testVotesBind(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = Votes().Bind(ctx, tx, o); err != nil { + t.Error(err) + } +} + +func testVotesOne(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if x, err := Votes().One(ctx, tx); err != nil { + t.Error(err) + } else if x == nil { + t.Error("expected to get a non nil record") + } +} + +func testVotesAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + voteOne := &Vote{} + voteTwo := &Vote{} + if err = randomize.Struct(seed, voteOne, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + if err = randomize.Struct(seed, voteTwo, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = voteOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = voteTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Votes().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 2 { + t.Error("want 2 records, got:", len(slice)) + } +} + +func testVotesCount(t *testing.T) { + t.Parallel() + + var err error + seed := randomize.NewSeed() + voteOne := &Vote{} + voteTwo := &Vote{} + if err = randomize.Struct(seed, voteOne, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + if err = randomize.Struct(seed, voteTwo, voteDBTypes, false, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = voteOne.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + if err = voteTwo.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 2 { + t.Error("want 2 records, got:", count) + } +} + +func voteBeforeInsertHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteAfterInsertHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteAfterSelectHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteBeforeUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteAfterUpdateHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteBeforeDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteAfterDeleteHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteBeforeUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func voteAfterUpsertHook(ctx context.Context, e boil.ContextExecutor, o *Vote) error { + *o = Vote{} + return nil +} + +func testVotesHooks(t *testing.T) { + t.Parallel() + + var err error + + ctx := context.Background() + empty := &Vote{} + o := &Vote{} + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, o, voteDBTypes, false); err != nil { + t.Errorf("Unable to randomize Vote object: %s", err) + } + + AddVoteHook(boil.BeforeInsertHook, voteBeforeInsertHook) + if err = o.doBeforeInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeInsertHook function to empty object, but got: %#v", o) + } + voteBeforeInsertHooks = []VoteHook{} + + AddVoteHook(boil.AfterInsertHook, voteAfterInsertHook) + if err = o.doAfterInsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterInsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterInsertHook function to empty object, but got: %#v", o) + } + voteAfterInsertHooks = []VoteHook{} + + AddVoteHook(boil.AfterSelectHook, voteAfterSelectHook) + if err = o.doAfterSelectHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterSelectHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterSelectHook function to empty object, but got: %#v", o) + } + voteAfterSelectHooks = []VoteHook{} + + AddVoteHook(boil.BeforeUpdateHook, voteBeforeUpdateHook) + if err = o.doBeforeUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpdateHook function to empty object, but got: %#v", o) + } + voteBeforeUpdateHooks = []VoteHook{} + + AddVoteHook(boil.AfterUpdateHook, voteAfterUpdateHook) + if err = o.doAfterUpdateHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpdateHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpdateHook function to empty object, but got: %#v", o) + } + voteAfterUpdateHooks = []VoteHook{} + + AddVoteHook(boil.BeforeDeleteHook, voteBeforeDeleteHook) + if err = o.doBeforeDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeDeleteHook function to empty object, but got: %#v", o) + } + voteBeforeDeleteHooks = []VoteHook{} + + AddVoteHook(boil.AfterDeleteHook, voteAfterDeleteHook) + if err = o.doAfterDeleteHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterDeleteHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterDeleteHook function to empty object, but got: %#v", o) + } + voteAfterDeleteHooks = []VoteHook{} + + AddVoteHook(boil.BeforeUpsertHook, voteBeforeUpsertHook) + if err = o.doBeforeUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doBeforeUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected BeforeUpsertHook function to empty object, but got: %#v", o) + } + voteBeforeUpsertHooks = []VoteHook{} + + AddVoteHook(boil.AfterUpsertHook, voteAfterUpsertHook) + if err = o.doAfterUpsertHooks(ctx, nil); err != nil { + t.Errorf("Unable to execute doAfterUpsertHooks: %s", err) + } + if !reflect.DeepEqual(o, empty) { + t.Errorf("Expected AfterUpsertHook function to empty object, but got: %#v", o) + } + voteAfterUpsertHooks = []VoteHook{} +} + +func testVotesInsert(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testVotesInsertWhitelist(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Whitelist(voteColumnsWithoutDefault...)); err != nil { + t.Error(err) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } +} + +func testVoteToOneCommentUsingComment(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Vote + var foreign Comment + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, commentDBTypes, false, commentColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Comment struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + queries.Assign(&local.CommentID, foreign.ID) + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.Comment().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if !queries.Equal(check.ID, foreign.ID) { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + ranAfterSelectHook := false + AddCommentHook(boil.AfterSelectHook, func(ctx context.Context, e boil.ContextExecutor, o *Comment) error { + ranAfterSelectHook = true + return nil + }) + + slice := VoteSlice{&local} + if err = local.L.LoadComment(ctx, tx, false, (*[]*Vote)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.Comment == nil { + t.Error("struct should have been eager loaded") + } + + local.R.Comment = nil + if err = local.L.LoadComment(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.Comment == nil { + t.Error("struct should have been eager loaded") + } + + if !ranAfterSelectHook { + t.Error("failed to run AfterSelect hook for relationship") + } +} + +func testVoteToOnePostUsingPost(t *testing.T) { + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var local Vote + var foreign Post + + seed := randomize.NewSeed() + if err := randomize.Struct(seed, &local, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + if err := randomize.Struct(seed, &foreign, postDBTypes, false, postColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Post struct: %s", err) + } + + if err := foreign.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + queries.Assign(&local.PostID, foreign.ID) + if err := local.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + check, err := local.Post().One(ctx, tx) + if err != nil { + t.Fatal(err) + } + + if !queries.Equal(check.ID, foreign.ID) { + t.Errorf("want: %v, got %v", foreign.ID, check.ID) + } + + ranAfterSelectHook := false + AddPostHook(boil.AfterSelectHook, func(ctx context.Context, e boil.ContextExecutor, o *Post) error { + ranAfterSelectHook = true + return nil + }) + + slice := VoteSlice{&local} + if err = local.L.LoadPost(ctx, tx, false, (*[]*Vote)(&slice), nil); err != nil { + t.Fatal(err) + } + if local.R.Post == nil { + t.Error("struct should have been eager loaded") + } + + local.R.Post = nil + if err = local.L.LoadPost(ctx, tx, true, &local, nil); err != nil { + t.Fatal(err) + } + if local.R.Post == nil { + t.Error("struct should have been eager loaded") + } + + if !ranAfterSelectHook { + t.Error("failed to run AfterSelect hook for relationship") + } +} + +func testVoteToOneSetOpCommentUsingComment(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Vote + var b, c Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Comment{&b, &c} { + err = a.SetComment(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.Comment != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.Votes[0] != &a { + t.Error("failed to append to foreign relationship struct") + } + if !queries.Equal(a.CommentID, x.ID) { + t.Error("foreign key was wrong value", a.CommentID) + } + + zero := reflect.Zero(reflect.TypeOf(a.CommentID)) + reflect.Indirect(reflect.ValueOf(&a.CommentID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if !queries.Equal(a.CommentID, x.ID) { + t.Error("foreign key was wrong value", a.CommentID, x.ID) + } + } +} + +func testVoteToOneRemoveOpCommentUsingComment(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Vote + var b Comment + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, commentDBTypes, false, strmangle.SetComplement(commentPrimaryKeyColumns, commentColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err = a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = a.SetComment(ctx, tx, true, &b); err != nil { + t.Fatal(err) + } + + if err = a.RemoveComment(ctx, tx, &b); err != nil { + t.Error("failed to remove relationship") + } + + count, err := a.Comment().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 0 { + t.Error("want no relationships remaining") + } + + if a.R.Comment != nil { + t.Error("R struct entry should be nil") + } + + if !queries.IsValuerNil(a.CommentID) { + t.Error("foreign key value should be nil") + } + + if len(b.R.Votes) != 0 { + t.Error("failed to remove a from b's relationships") + } +} + +func testVoteToOneSetOpPostUsingPost(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Vote + var b, c Post + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &c, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err := a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + if err = b.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + for i, x := range []*Post{&b, &c} { + err = a.SetPost(ctx, tx, i != 0, x) + if err != nil { + t.Fatal(err) + } + + if a.R.Post != x { + t.Error("relationship struct not set to correct value") + } + + if x.R.Votes[0] != &a { + t.Error("failed to append to foreign relationship struct") + } + if !queries.Equal(a.PostID, x.ID) { + t.Error("foreign key was wrong value", a.PostID) + } + + zero := reflect.Zero(reflect.TypeOf(a.PostID)) + reflect.Indirect(reflect.ValueOf(&a.PostID)).Set(zero) + + if err = a.Reload(ctx, tx); err != nil { + t.Fatal("failed to reload", err) + } + + if !queries.Equal(a.PostID, x.ID) { + t.Error("foreign key was wrong value", a.PostID, x.ID) + } + } +} + +func testVoteToOneRemoveOpPostUsingPost(t *testing.T) { + var err error + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + + var a Vote + var b Post + + seed := randomize.NewSeed() + if err = randomize.Struct(seed, &a, voteDBTypes, false, strmangle.SetComplement(votePrimaryKeyColumns, voteColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + if err = randomize.Struct(seed, &b, postDBTypes, false, strmangle.SetComplement(postPrimaryKeyColumns, postColumnsWithoutDefault)...); err != nil { + t.Fatal(err) + } + + if err = a.Insert(ctx, tx, boil.Infer()); err != nil { + t.Fatal(err) + } + + if err = a.SetPost(ctx, tx, true, &b); err != nil { + t.Fatal(err) + } + + if err = a.RemovePost(ctx, tx, &b); err != nil { + t.Error("failed to remove relationship") + } + + count, err := a.Post().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 0 { + t.Error("want no relationships remaining") + } + + if a.R.Post != nil { + t.Error("R struct entry should be nil") + } + + if !queries.IsValuerNil(a.PostID) { + t.Error("foreign key value should be nil") + } + + if len(b.R.Votes) != 0 { + t.Error("failed to remove a from b's relationships") + } +} + +func testVotesReload(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + if err = o.Reload(ctx, tx); err != nil { + t.Error(err) + } +} + +func testVotesReloadAll(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice := VoteSlice{o} + + if err = slice.ReloadAll(ctx, tx); err != nil { + t.Error(err) + } +} + +func testVotesSelect(t *testing.T) { + t.Parallel() + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + slice, err := Votes().All(ctx, tx) + if err != nil { + t.Error(err) + } + + if len(slice) != 1 { + t.Error("want one record, got:", len(slice)) + } +} + +var ( + voteDBTypes = map[string]string{`ID`: `integer`, `PostID`: `integer`, `CommentID`: `integer`, `UserID`: `integer`, `Inc`: `integer`, `CreatedAt`: `timestamp with time zone`, `UpdatedAt`: `timestamp with time zone`} + _ = bytes.MinRead +) + +func testVotesUpdate(t *testing.T) { + t.Parallel() + + if 0 == len(votePrimaryKeyColumns) { + t.Skip("Skipping table with no primary key columns") + } + if len(voteAllColumns) == len(votePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, voteDBTypes, true, votePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + if rowsAff, err := o.Update(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("should only affect one row but affected", rowsAff) + } +} + +func testVotesSliceUpdateAll(t *testing.T) { + t.Parallel() + + if len(voteAllColumns) == len(votePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + o := &Vote{} + if err = randomize.Struct(seed, o, voteDBTypes, true, voteColumnsWithDefault...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Insert(ctx, tx, boil.Infer()); err != nil { + t.Error(err) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + + if count != 1 { + t.Error("want one record, got:", count) + } + + if err = randomize.Struct(seed, o, voteDBTypes, true, votePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + // Remove Primary keys and unique columns from what we plan to update + var fields []string + if strmangle.StringSliceMatch(voteAllColumns, votePrimaryKeyColumns) { + fields = voteAllColumns + } else { + fields = strmangle.SetComplement( + voteAllColumns, + votePrimaryKeyColumns, + ) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + typ := reflect.TypeOf(o).Elem() + n := typ.NumField() + + updateMap := M{} + for _, col := range fields { + for i := 0; i < n; i++ { + f := typ.Field(i) + if f.Tag.Get("boil") == col { + updateMap[col] = value.Field(i).Interface() + } + } + } + + slice := VoteSlice{o} + if rowsAff, err := slice.UpdateAll(ctx, tx, updateMap); err != nil { + t.Error(err) + } else if rowsAff != 1 { + t.Error("wanted one record updated but got", rowsAff) + } +} + +func testVotesUpsert(t *testing.T) { + t.Parallel() + + if len(voteAllColumns) == len(votePrimaryKeyColumns) { + t.Skip("Skipping table with only primary key columns") + } + + seed := randomize.NewSeed() + var err error + // Attempt the INSERT side of an UPSERT + o := Vote{} + if err = randomize.Struct(seed, &o, voteDBTypes, true); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + ctx := context.Background() + tx := MustTx(boil.BeginTx(ctx, nil)) + defer func() { _ = tx.Rollback() }() + if err = o.Upsert(ctx, tx, false, nil, boil.Infer(), boil.Infer()); err != nil { + t.Errorf("Unable to upsert Vote: %s", err) + } + + count, err := Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 1 { + t.Error("want one record, got:", count) + } + + // Attempt the UPDATE side of an UPSERT + if err = randomize.Struct(seed, &o, voteDBTypes, false, votePrimaryKeyColumns...); err != nil { + t.Errorf("Unable to randomize Vote struct: %s", err) + } + + if err = o.Upsert(ctx, tx, true, nil, boil.Infer(), boil.Infer()); err != nil { + t.Errorf("Unable to upsert Vote: %s", err) + } + + count, err = Votes().Count(ctx, tx) + if err != nil { + t.Error(err) + } + if count != 1 { + t.Error("want one record, got:", count) + } +} diff --git a/src/post/hooks.go b/src/post/hooks.go new file mode 100644 index 0000000..16a2df0 --- /dev/null +++ b/src/post/hooks.go @@ -0,0 +1,39 @@ +package post + +import ( + "context" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/go-ozzo/ozzo-validation/v4/is" + "github.com/volatiletech/sqlboiler/v4/boil" + "gitlab.com/alexkavon/newsstand/src/models" +) + +func InitInsertHooks() { + models.AddPostHook(boil.BeforeInsertHook, validateNewPostHook) +} + +func validateNewPostHook(ctx context.Context, exec boil.ContextExecutor, p *models.Post) error { + err := validation.ValidateStruct(p, + validation.Field(&p.Title, validation.Required, validation.Length(10, 80)), + validation.Field(&p.Description, validation.Max(5000)), + validation.Field(&p.URL, validation.Length(3, 255), is.URL), + ) + if err != nil { + return err + } + + return nil +} + +func checkDescriptionLength() { + // check if post/comment description is <= 5000 characters +} + +func stripMarkdown() { + // strip of specific tags or all tags +} + +func checkBlacklist() { + // check if URL is on blacklist +} diff --git a/src/post/routes.go b/src/post/routes.go index 7714920..9726d05 100644 --- a/src/post/routes.go +++ b/src/post/routes.go @@ -14,6 +14,10 @@ import ( "gitlab.com/alexkavon/newsstand/src/sessions" ) +func init() { + InitInsertHooks() +} + var Routes = server.Routes{ server.Route{ Name: "Create", diff --git a/src/user/hooks.go b/src/user/hooks.go index c7b7632..21eaaa3 100644 --- a/src/user/hooks.go +++ b/src/user/hooks.go @@ -8,13 +8,13 @@ import ( "gitlab.com/alexkavon/newsstand/src/models" ) -func InitHooks() { - models.AddUserHook(boil.BeforeInsertHook, validateNew) +func InitInsertHooks() { + models.AddUserHook(boil.BeforeInsertHook, validateNewHook) // should always be last - models.AddUserHook(boil.BeforeInsertHook, hashSecretBeforeInsert) + models.AddUserHook(boil.BeforeInsertHook, hashSecretHook) } -func validateNew(ctx context.Context, exec boil.ContextExecutor, u *models.User) error { +func validateNewHook(ctx context.Context, exec boil.ContextExecutor, u *models.User) error { // validate user err := validation.ValidateStruct(u, validation.Field(&u.Username, validation.Required, validation.Length(3, 50)), @@ -27,7 +27,7 @@ func validateNew(ctx context.Context, exec boil.ContextExecutor, u *models.User) return nil } -func hashSecretBeforeInsert(ctx context.Context, exec boil.ContextExecutor, u *models.User) error { +func hashSecretHook(ctx context.Context, exec boil.ContextExecutor, u *models.User) error { hashed, err := hashSecret(u.Secret) if err != nil { return err diff --git a/src/user/routes.go b/src/user/routes.go index eaf4582..06a5296 100644 --- a/src/user/routes.go +++ b/src/user/routes.go @@ -11,7 +11,7 @@ import ( ) func init() { - InitHooks() + InitInsertHooks() } var Routes = server.Routes{ |
