Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Nullxxxx fields with "pgx/v5" and json.Marshal on left join #2839

Unanswered
polderudo asked this question in Q&A
Discussion options

Version

1.22.0

What happened?

Using postgres and "pgx/v5" is there any way to specify that any Nullxxx types should json.Marshal to null or the coresponding underlying type?

Doing a left join on the provided example, the status can be null, therefore we get a NullTestStatus type.
Question is, if it's possible to specify, that this should be either null or the string itself on marshaling (without using emit_pointers_for_null_types=true of course).

Relevant log output

Will output:
Select:
{"id":1,"status":"none"}
Select via left join:
[{"field1":11,"status":{"test_status":"none","valid":true}},{"field1":22,"status":{"test_status":"new","valid":true}},{"field1":33,"status":{"test_status":"","valid":false}}]
Select via join:
[{"field1":11,"status":"none"},{"field1":22,"status":"new"}]

Database schema

create type test_status as enum('none', 'new');
CREATE TABLE test1
(
 id int not null,
 status test_status not null default 'none'
);
CREATE TABLE test2
(
 field1 int not null,
 test1_status_id int null
);
insert into test1 values(1, 'none');
insert into test1 values(2, 'new');
insert into test2 values(11, 1);
insert into test2 values(22, 2);
insert into test2 values(33, null);

SQL queries

-- name: Test1 :one
select * from test1 where id=$1;
-- name: Test2 :many
select t2.field1, t1.status from test2 t2 left join test1 t1 on t1.id=t2.test1_status_id;
-- name: Test3 :many
select t2.field1, t1.status from test2 t2 join test1 t1 on t1.id=t2.test1_status_id;

Configuration

func TestNulls(t *testing.T) {
srv, err := core_testing.Init(false)
if err != nil {
panic(err)
}
q := models.New(db.DB)
t1, _ := q.Test1(srv.Ctx, 1)
a, _ := json.Marshal(t1)
fmt.Println(string(a))
t2, err := q.Test2(srv.Ctx)
if err != nil {
panic(err)
}
b, _ := json.Marshal(t2)
fmt.Println(string(b))
t3, err := q.Test3(srv.Ctx)
if err != nil {
panic(err)
}
c, _ := json.Marshal(t3)
fmt.Println(string(c))
}
Will output:
{"id":1,"status":"none"}
[{"field1":11,"status":{"test_status":"none","valid":true}},{"field1":22,"status":{"test_status":"new","valid":true}},{"field1":33,"status":{"test_status":"","valid":false}}]
[{"field1":11,"status":"none"},{"field1":22,"status":"new"}]

Playground URL

No response

What operating system are you using?

macOS

What database engines are you using?

PostgreSQL

What type of code are you generating?

Go

You must be logged in to vote

Replies: 3 comments 1 reply

Comment options

The Null*** fields are part of the sql package so I'm not sure it falls under the purview of sqlc anyway. But the simple workaround is to make those types part of the Marshaller interface yourself. Eg:

func (x sql.NullString) Marshall() ([]byte, error) {
 if !x.Valid {
 return null, nil
 }
 return []byte(x.String), nil
}

I have not tested it by any means :) but I'm guessing that's the way to go as probably the people behind sql package won't want to get too opinionated on how people would want to encode null fields.

You must be logged in to vote
0 replies
Comment options

Hello Andrei, yes, thats how we use it right now:

func (f *NullTestStatus) MarshalJSON() ([]byte, error) {
	if f.Valid {
		return json.Marshal(f.TestStatus)
	}
	return json.Marshal(nil)
}

But of course would be nicer to have that automatictly generated.

You must be logged in to vote
0 replies
Comment options

@andrei-dascalu is right, this isn't a default that we'd like to dictate as it's outside the purview of sqlc itself.

You must be logged in to vote
1 reply
Comment options

Not dictate, but configureable. The functions could go to a json.go file eg. I belive null is a much more reasonable value for an null field than a struct, at least if you give that data to an api. But than again that's just my opinion.
Although I don't know if that is easily doable on the generation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
Converted from issue

This discussion was converted from issue #2817 on October 12, 2023 18:50.

AltStyle によって変換されたページ (->オリジナル) /