sqlx icon indicating copy to clipboard operation
sqlx copied to clipboard

unable to use scan with nested structs

Open zeynepuyyanik opened this issue 4 years ago • 4 comments

Let's assume that, I have two structs,


type Customer struct {
   Id int `json:"id" db:"id"`
   Name string `json:"name" db:"name"`
   Adress Adress `json:"adress" db:"adress"`
}

type Adress struct {
   Street string `json:"street" db:"street"`
   City Adress `json:"city" db:"city"`
}

customer := models.Customer{}
err := db.Get( &customer , "select * from users where id=$1 and name=$2", id, name )

but this scan throws an error as: missing destination name street in *models.Customer

Am I doing something wrong? As you can see I already updated the db corresponding of the value. I doubled check so case sensitivity shouldn't be a problem. Or is it not possible using sqlx?

zeynepuyyanik avatar Jun 21 '21 10:06 zeynepuyyanik

type Customer struct {
	Id   int    `json:"id" db:"id"`
	Name string `json:"name" db:"name"`
	Adress
}

type Adress struct {
	Street string  `json:"street" db:"street"`
	City   *Adress `json:"city" db:"city"`
}

You should try to embed the structs instead of adding it as another field as shown above. If that does not work please share the table description or a sample result

sarathsp06 avatar Jul 10 '21 17:07 sarathsp06

I have the same problem, and it works for me when I embed the struct instead:

type Availability struct {
  From time.Time `db:"available_from"`
  Until time.Time `db:"available_until"`
}

type Room struct {
  ...
  Availability
}

But it breaks the naming:

fmt.Printf("Available from: %v, until: %\n", Room.From, Room.Until)

I want:

type Room struct {
  Available Availability
}

fmt.Printf("Available from: %v, until: %\n", Room.Available.From, Room.Available.Until)

jomag avatar Oct 19 '21 12:10 jomag

@zeynepuyyanik you can make your structure work by using select street as "address.street" from users...

ntbosscher avatar Jan 20 '23 15:01 ntbosscher

@zeynepuyyanik you can make your structure work by using select street as "address.street" from users...

@ntbosscher the inconvenient of doing select street as "address.street" from users... is that it forces you to explicitly map each column to the corresponding field, which is verbose for the default use case.

Two things come to mind. Either we use the leaf name as column name after ensuring that there is no duplicate or we use a path separator that is column name compatible, like "_" and name our database column with the full path.

The other solution would be to use separate struct for the database layer (DTO) and do the mapping in Go.

emeka avatar Jan 20 '25 16:01 emeka