reform icon indicating copy to clipboard operation
reform copied to clipboard

Tag "omitempty" to avoid passing zero values

Open dgellow opened this issue 3 years ago • 1 comments

Is your feature request related to a problem? Please describe.

I have a postgres table with a column of type serial (which is not the primary key, if that matters).

Suppose I have a reform type:

//reform:files
type File struct {
	ID    string `reform:"id,pk"`
	IncID int64  `reform:"inc_id"` // <== column of type 'serial'
}

I then insert it using this way:

record := MyRecord{
  ID: myID,
}
err := db.Insert(&record)

Here I would like the value for inc_id to be ignored during INSERT statements as I would like to use the column default (i.e: the next value of the serial's sequence). Unfortunately when using the Go zero value reform does the insert with the actual value 0. The result in a row with the column set to 0 instead of the result of Postgres' nextval().

Describe the solution you'd like

I would like to be able to mark a field as reform:"inc_id,omitempty", similar to what the official json package does. When the tag "omitempty" is present, reform will not pass the field during calls to Insertor Update.

Given this reform type:

//reform:files
type File struct {
	ID    string `reform:"id,pk"`
	IncID int64  `reform:"inc_id,omitempty"` // <== column of type 'serial'
}

And this insert:

record := MyRecord{
  ID: 123,
}
err := db.Insert(&record)

Something equivalent to the following SQL code should be generated:

INSERT INTO (id) values (123) RETURNING id, inc_id

Describe alternatives you've considered

Other options:

  1. We could use a tag readonly instead, that would specify that the column is never passed during UPDATE or INSERT, but is used for SELECT, without a need for logic based on zero values.

  2. What I would like is currently possible this way:

cols := record.Table().Columns()
i := 0
for i = range cols {
	if cols[i] == "inc_id" {
		break
	}
}
cols = append(cols[:i], cols[i+1:]...)
err := tx.InsertColumns(&record, cols...)

So an alternative that doesn't require to add new tags would be to add a method InsertWithout(&record, "inc_id") that would do the opposite of InsertColumns (insert everything but the specified columns).

dgellow avatar Oct 28 '20 13:10 dgellow

https://github.com/go-reform/reform/issues/146#issuecomment-359029463

readonly tag sounds interesting…

The last option is covered by #100.

AlekSi avatar Feb 02 '22 18:02 AlekSi