sqlx scan postgres array into struct
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I'm trying to create a basic commenting api in go. I can't seem to figure out how to scan postgresql arrays into an array of structs within a struct. I think I could probably have Thread.Posts type be jsonb but that seems inelegant since I would have to unmarshall it I think.
sql: Scan error on column index 3, name "posts": unsupported Scan,
storing driver.Value type uint8 into type *models.Post
var threadSchema = `
CREATE TABLE IF NOT EXISTS thread (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
profile_id INTEGER REFERENCES profile (id)
)`
var postSchema = `
CREATE TABLE IF NOT EXISTS post (
id SERIAL PRIMARY KEY,
comment TEXT,
profile_id INTEGER REFERENCES profile (id),
thread_id INTEGER REFERENCES thread (id)
)`
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := Thread{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,array_agg(post.id) AS posts
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY thread.id;
`)
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threads})
}
postgresql go sqlx
add a comment |
I'm trying to create a basic commenting api in go. I can't seem to figure out how to scan postgresql arrays into an array of structs within a struct. I think I could probably have Thread.Posts type be jsonb but that seems inelegant since I would have to unmarshall it I think.
sql: Scan error on column index 3, name "posts": unsupported Scan,
storing driver.Value type uint8 into type *models.Post
var threadSchema = `
CREATE TABLE IF NOT EXISTS thread (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
profile_id INTEGER REFERENCES profile (id)
)`
var postSchema = `
CREATE TABLE IF NOT EXISTS post (
id SERIAL PRIMARY KEY,
comment TEXT,
profile_id INTEGER REFERENCES profile (id),
thread_id INTEGER REFERENCES thread (id)
)`
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := Thread{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,array_agg(post.id) AS posts
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY thread.id;
`)
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threads})
}
postgresql go sqlx
what does the posts column look like, is it an array of json Or just json?
– Saurav Prakash
Jan 4 at 8:02
I added the schemas
– als9xd
Jan 4 at 8:03
You'd need a struct representing a row resulted from theJOIN
or to start using an ORM.
– Havelock
Jan 4 at 8:24
Wouldn't the Thread struct represent theJOIN
?
– als9xd
Jan 4 at 8:26
add a comment |
I'm trying to create a basic commenting api in go. I can't seem to figure out how to scan postgresql arrays into an array of structs within a struct. I think I could probably have Thread.Posts type be jsonb but that seems inelegant since I would have to unmarshall it I think.
sql: Scan error on column index 3, name "posts": unsupported Scan,
storing driver.Value type uint8 into type *models.Post
var threadSchema = `
CREATE TABLE IF NOT EXISTS thread (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
profile_id INTEGER REFERENCES profile (id)
)`
var postSchema = `
CREATE TABLE IF NOT EXISTS post (
id SERIAL PRIMARY KEY,
comment TEXT,
profile_id INTEGER REFERENCES profile (id),
thread_id INTEGER REFERENCES thread (id)
)`
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := Thread{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,array_agg(post.id) AS posts
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY thread.id;
`)
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threads})
}
postgresql go sqlx
I'm trying to create a basic commenting api in go. I can't seem to figure out how to scan postgresql arrays into an array of structs within a struct. I think I could probably have Thread.Posts type be jsonb but that seems inelegant since I would have to unmarshall it I think.
sql: Scan error on column index 3, name "posts": unsupported Scan,
storing driver.Value type uint8 into type *models.Post
var threadSchema = `
CREATE TABLE IF NOT EXISTS thread (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
profile_id INTEGER REFERENCES profile (id)
)`
var postSchema = `
CREATE TABLE IF NOT EXISTS post (
id SERIAL PRIMARY KEY,
comment TEXT,
profile_id INTEGER REFERENCES profile (id),
thread_id INTEGER REFERENCES thread (id)
)`
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := Thread{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,array_agg(post.id) AS posts
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY thread.id;
`)
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threads})
}
postgresql go sqlx
postgresql go sqlx
edited Jan 4 at 8:03
als9xd
asked Jan 4 at 7:51
als9xdals9xd
351210
351210
what does the posts column look like, is it an array of json Or just json?
– Saurav Prakash
Jan 4 at 8:02
I added the schemas
– als9xd
Jan 4 at 8:03
You'd need a struct representing a row resulted from theJOIN
or to start using an ORM.
– Havelock
Jan 4 at 8:24
Wouldn't the Thread struct represent theJOIN
?
– als9xd
Jan 4 at 8:26
add a comment |
what does the posts column look like, is it an array of json Or just json?
– Saurav Prakash
Jan 4 at 8:02
I added the schemas
– als9xd
Jan 4 at 8:03
You'd need a struct representing a row resulted from theJOIN
or to start using an ORM.
– Havelock
Jan 4 at 8:24
Wouldn't the Thread struct represent theJOIN
?
– als9xd
Jan 4 at 8:26
what does the posts column look like, is it an array of json Or just json?
– Saurav Prakash
Jan 4 at 8:02
what does the posts column look like, is it an array of json Or just json?
– Saurav Prakash
Jan 4 at 8:02
I added the schemas
– als9xd
Jan 4 at 8:03
I added the schemas
– als9xd
Jan 4 at 8:03
You'd need a struct representing a row resulted from the
JOIN
or to start using an ORM.– Havelock
Jan 4 at 8:24
You'd need a struct representing a row resulted from the
JOIN
or to start using an ORM.– Havelock
Jan 4 at 8:24
Wouldn't the Thread struct represent the
JOIN
?– als9xd
Jan 4 at 8:26
Wouldn't the Thread struct represent the
JOIN
?– als9xd
Jan 4 at 8:26
add a comment |
1 Answer
1
active
oldest
votes
First off, you can't do this with sqlx, whether or not you're using Postgres arrays.
Second, your SQL query is simply aggregating Post IDs, not the content of the posts, so there's no way to get the data you want (using Go or otherwise).
So here's what you can do:
Use an anonymous embedded struct, capture all of the Post content in your SQL query, and then merge your duplicated Threads.
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type ThreadDb struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Post
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := ThreadDb{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,post.id,post.comment,post.profile_id,post.thread_id
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY post.id;
`)
thread_map := make(map[string]Thread)
for i, thread := range threads {
if _, ok := thread_map[thread.Id]; ok {
thread_map[thread.Id].Posts = append(thread_map[thread.Id].Posts, thread.Post)
} else {
thread_map[thread.Id] = Thread{thread.Id, thread.Name, thread.ProfileId, Post{thread.Post}}
}
}
var threadSlice string
for k := range thread_map {
threadSlice = append(threadSlice, k)
}
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threadSlice})
}
- Use
GROUP_CONCAT
or similar. I wouldn't recommend unless you plan on having a maximum of about 100 posts per thread.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54034983%2fsqlx-scan-postgres-array-into-struct%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
First off, you can't do this with sqlx, whether or not you're using Postgres arrays.
Second, your SQL query is simply aggregating Post IDs, not the content of the posts, so there's no way to get the data you want (using Go or otherwise).
So here's what you can do:
Use an anonymous embedded struct, capture all of the Post content in your SQL query, and then merge your duplicated Threads.
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type ThreadDb struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Post
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := ThreadDb{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,post.id,post.comment,post.profile_id,post.thread_id
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY post.id;
`)
thread_map := make(map[string]Thread)
for i, thread := range threads {
if _, ok := thread_map[thread.Id]; ok {
thread_map[thread.Id].Posts = append(thread_map[thread.Id].Posts, thread.Post)
} else {
thread_map[thread.Id] = Thread{thread.Id, thread.Name, thread.ProfileId, Post{thread.Post}}
}
}
var threadSlice string
for k := range thread_map {
threadSlice = append(threadSlice, k)
}
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threadSlice})
}
- Use
GROUP_CONCAT
or similar. I wouldn't recommend unless you plan on having a maximum of about 100 posts per thread.
add a comment |
First off, you can't do this with sqlx, whether or not you're using Postgres arrays.
Second, your SQL query is simply aggregating Post IDs, not the content of the posts, so there's no way to get the data you want (using Go or otherwise).
So here's what you can do:
Use an anonymous embedded struct, capture all of the Post content in your SQL query, and then merge your duplicated Threads.
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type ThreadDb struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Post
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := ThreadDb{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,post.id,post.comment,post.profile_id,post.thread_id
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY post.id;
`)
thread_map := make(map[string]Thread)
for i, thread := range threads {
if _, ok := thread_map[thread.Id]; ok {
thread_map[thread.Id].Posts = append(thread_map[thread.Id].Posts, thread.Post)
} else {
thread_map[thread.Id] = Thread{thread.Id, thread.Name, thread.ProfileId, Post{thread.Post}}
}
}
var threadSlice string
for k := range thread_map {
threadSlice = append(threadSlice, k)
}
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threadSlice})
}
- Use
GROUP_CONCAT
or similar. I wouldn't recommend unless you plan on having a maximum of about 100 posts per thread.
add a comment |
First off, you can't do this with sqlx, whether or not you're using Postgres arrays.
Second, your SQL query is simply aggregating Post IDs, not the content of the posts, so there's no way to get the data you want (using Go or otherwise).
So here's what you can do:
Use an anonymous embedded struct, capture all of the Post content in your SQL query, and then merge your duplicated Threads.
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type ThreadDb struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Post
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := ThreadDb{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,post.id,post.comment,post.profile_id,post.thread_id
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY post.id;
`)
thread_map := make(map[string]Thread)
for i, thread := range threads {
if _, ok := thread_map[thread.Id]; ok {
thread_map[thread.Id].Posts = append(thread_map[thread.Id].Posts, thread.Post)
} else {
thread_map[thread.Id] = Thread{thread.Id, thread.Name, thread.ProfileId, Post{thread.Post}}
}
}
var threadSlice string
for k := range thread_map {
threadSlice = append(threadSlice, k)
}
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threadSlice})
}
- Use
GROUP_CONCAT
or similar. I wouldn't recommend unless you plan on having a maximum of about 100 posts per thread.
First off, you can't do this with sqlx, whether or not you're using Postgres arrays.
Second, your SQL query is simply aggregating Post IDs, not the content of the posts, so there's no way to get the data you want (using Go or otherwise).
So here's what you can do:
Use an anonymous embedded struct, capture all of the Post content in your SQL query, and then merge your duplicated Threads.
type Post struct {
Id int `db:"id" json:"id"`
Comment string `db:"comment" json:"comment" binding:"required" form:"comment"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
ThreadId int `db:"thread_id" json:"thread_id" binding:"required" form:"thread_id"`
}
type ThreadDb struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Post
}
type Thread struct {
Id int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required" form:"name"`
ProfileId int `db:"profile_id" json:"profile_id" binding:"required" form:"profile_id"`
Posts Post `db:"posts" json:"posts" form:"posts"`
}
func GetThreads(db *sqlx.DB, c *gin.Context) {
threads := ThreadDb{}
err := db.Select(&threads, `
SELECT thread.id,thread.name,thread.profile_id,post.id,post.comment,post.profile_id,post.thread_id
FROM thread
INNER JOIN post ON thread.id = post.thread_id
GROUP BY post.id;
`)
thread_map := make(map[string]Thread)
for i, thread := range threads {
if _, ok := thread_map[thread.Id]; ok {
thread_map[thread.Id].Posts = append(thread_map[thread.Id].Posts, thread.Post)
} else {
thread_map[thread.Id] = Thread{thread.Id, thread.Name, thread.ProfileId, Post{thread.Post}}
}
}
var threadSlice string
for k := range thread_map {
threadSlice = append(threadSlice, k)
}
if err != nil {
log.Fatal(err)
}
c.JSON(http.StatusOK, gin.H{"data": threadSlice})
}
- Use
GROUP_CONCAT
or similar. I wouldn't recommend unless you plan on having a maximum of about 100 posts per thread.
answered Jan 4 at 8:39
qualversequalverse
76139
76139
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54034983%2fsqlx-scan-postgres-array-into-struct%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
what does the posts column look like, is it an array of json Or just json?
– Saurav Prakash
Jan 4 at 8:02
I added the schemas
– als9xd
Jan 4 at 8:03
You'd need a struct representing a row resulted from the
JOIN
or to start using an ORM.– Havelock
Jan 4 at 8:24
Wouldn't the Thread struct represent the
JOIN
?– als9xd
Jan 4 at 8:26