As per the example below, I need to get email and firstname and dateofbirth and so on as NullStrings and NullTimes as required, as my User struct is using them. How do I declare variables as NULLs
package entities
import (
"database/sql"
"github.com/go-sql-driver/mysql"
"testing"
"time"
)
var (
email = sql.NullString("mail#gmail.com") << Does not work
hashedPassword = "password"
firstName = "Lee"
lastName = "Brooks"
dateOfBirth = time.Now
height = 1.85
weight = 101.3
)
func privacyConcernedUser() *User {
return &User{
Email: email, << These all complain eg: cannot use Email (type string) as type sql.NullString in field value
HashedPassword: hashedPassword,
FirstName: firstName,
LastName: lastName,
}
}
sql.NullString isn't a drop-in replacement for the string type, you have to some work with it.
package main
import "database/sql"
import "fmt"
type User struct {
Name string
}
func main() {
var nsName sql.NullString
if err := nsName.Scan("User's Name"); err != nil {
panic(err)
}
user := &User{Name: nsName.String}
fmt.Println(user)
}
You can check if the NullString is valid with nsName.Valid.
http://golang.org/pkg/database/sql/#NullString
sql.NullString("mail#gmail.com") << Does not work
Try:
sql.NullString{"mail#gmail.com", true}
see http://golang.org/pkg/database/sql/#NullString
Related
I have a table that represents my user data. There is a field that represents a phone number, and I want to store the hash of that automatically in the database at either update or insert.
so my model is :
type Users struct {
gorm.Model
ID uint `gorm:"autoIncrement;unique" json:"id"`
PhoneNumber string `json:"phone_number"`
HashID string `gorm:"primaryKey" json:"hash_id"`
Name string `gorm:"default:dear user" json:"name"`
Rank uint `json:"rank"`
Score uint `json:"score"`
Image string `json:"image"`
Email string `json:"email"`
Address string `json:"address"`
Birthday string `json:"birthday"`
Biography string `json:"biography"
}
How can I tell the GORM to fill the HashID column with the sha256 hash code of the PhoneNumber column while inserting or updating data?
You need something like this:
package main
import (
"crypto/sha256"
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type Users struct {
gorm.Model
Key string `json:"phone_number"`
Hash string `gorm:"primaryKey" json:"hash_id"`
}
func (u *Users) BeforeCreate(tx *gorm.DB) (err error) {
h := sha256.Sum256([]byte(u.Key))
u.Hash = fmt.Sprintf("%x", h[:])
return nil
}
func (u *Users) BeforeSave(tx *gorm.DB) (err error) {
h := sha256.Sum256([]byte(u.Key))
u.Hash = fmt.Sprintf("%x", h[:])
return nil
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&Users{})
u := Users{Key: "123"}
db.Create(&u)
}
Check https://gorm.io/docs/index.html
With the following Code
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type Person struct {
gorm.Model
FirstName string `json:"firstname"`
LastName string `json:"lastname"`
Addresses []PersonAddressLines `gorm:"many2many:person_addresses;" json:"addresses"`
}
type PersonAddressLines struct {
gorm.Model
AddressLine1 string `json:"address_line1"`
AddressLine2 string `json:"address_line2"`
AddressLine3 string `json:"address_line3"`
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.Migrator().DropTable("people")
db.Migrator().DropTable("person_addresses")
db.Migrator().DropTable("person_address_lines")
// Migrate the schema
err = db.AutoMigrate(&PersonAddressLines{}, &Person{})
if err != nil {
panic("Cannot migrate")
}
fmt.Println(">> Create Person")
// Create
var OriginalPerson = &Person{FirstName: "Sample", LastName: "Person", Addresses: []PersonAddressLines{
{AddressLine1: "1 Some Street", AddressLine2: "Somewhere"},
}}
fmt.Println(">> Reload Person")
db.Debug().Create(&OriginalPerson)
// Load the person again and update
var person Person
db.Preload("Addresses").First(&person, 1) //get the first person..
person.Addresses[0].AddressLine2 = "CHANGED!!!"
fmt.Println(">> Update with New Address")
db.Debug().Save(&person)
fmt.Println (">> New value " + person.Addresses[0].AddressLine2)
// Reload from database is it changed??
fmt.Println(">> Reloading Person again...")
var newPerson Person
db.Preload("Addresses").First(&newPerson, 1) //get the first person..
fmt.Println("Changed Person Value: Expect 'CHANGED!!!' == " + person.Addresses[0].AddressLine2)
fmt.Println("New Person Value: Expect 'CHANGED!!!' == " + newPerson.Addresses[0].AddressLine2)
}
The change to
person.Addresses[0].AddressLine2 = "CHANGED!!!"
Is not being updated in the database. Is this a bug or am I doing something wrong?
I have the same issue with postgres also.
I have different types for a REST API which have some things in common:
All types have Id
All types have Type
All types have Attributes, but Attributes differ
As I would not like to have a big count of unnecessary types I came up with a type format but which does not seem to be scannable by sqlx.
type Pool struct {
Id *string `json:"id" db:"pool_id"`
Type *string `json:"type"`
Attributes struct {
Name *string `json:"name" db:"name"`
Description *string `json:"description" db:"description"`
} `json:"attributes"`
}
type User struct {
Id *string `json:"id" db:"user_id"`
Type *string `json:"type"`
Attributes struct {
FirstName *string `json:"first_name" db:"first_name"`
LastName *string `json:"last_name" db:"last_name"`
} `json:"attributes"`
}
When trying to load the SQL result into the variable I get an error: missing destination name name in *main.Pool
package main
import (
_ "github.com/jmoiron/sqlx"
)
func selectOne() interface{} {
pa := Pool{}
err := dbx.Get(&pa, "SELECT * FROM pools LIMIT 1")
if err != nil {
panic(err)
}
return pa
}
As name is present I do not see why this does not work. Any advice how to solve this is highly appreciated!
package main
import (
_ "github.com/jmoiron/sqlx"
)
func selectOne() interface{} {
pa := Pool{}
err := dbx.Get(&pa, `SELECT p.id, p.type, a.name AS "attributes.name" FROM pools p left join attributes a on a.p LIMIT 1`)
if err != nil {
panic(err)
}
return pa
}
I am usin jinzhu GORM package for connecting to the DB, etc.
This is my code
package pizzas
import (
"github.com/jinzhu/gorm"
"github.com/gin-gonic/gin"
"speedy-gonzales/db"
"net/http"
)
type Pizza struct {
gorm.Model
Name string `gorm:"not null"`
Image string `sql:"type:text"`
PSizesAndPrices []PizzaPriceSize
}
type PizzaPriceSize struct {
gorm.Model
SizeTitle string `gorm:"column:size_title;type:varchar(50);not null'"`
PriceEur int `gorm:"column:price_eur"`
PriceBam int `gorm:"column:price_bam"`
PizzaID uint `gorm:"index"`
}
func (PizzaPriceSize) TableName() string {
return "pizza_price_sizes"
}
func FetchPizzasWithSizes(c *gin.Context) {
var pizza_model []Pizza
var p_sizes_prices_model []PizzaPriceSize
dB := db.DbConnect()
dB.Debug().Model(&pizza_model).Related(&p_sizes_prices_model)
c.JSON(http.StatusOK, gin.H{
"status": http.StatusOK,
"message": p_sizes_prices_model,
})
return
}
When I run the app this is what I get from debug console:
SELECT * FROM pizza_price_sizes WHERE pizza_price_sizes.deleted_at IS NULL AND ((pizza_id = '0'))
My question is how can I pass pizza_id to this query?
Take a look at this snip found at here
import (
"encoding/xml"
"fmt"
"os"
)
func main() {
type Address struct {
City, State string
}
type Person struct {
XMLName xml.Name `xml:"person"`
Id int `xml:"id,attr"`
FirstName string `xml:"name>first"`
LastName string `xml:"name>last"`
Age int `xml:"age"`
Height float32 `xml:"height,omitempty"`
Married bool
Address
Comment string `xml:",comment"`
}
v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
v.Comment = " Need more details. "
v.Address = Address{"Hanga Roa", "Easter Island"}
enc := xml.NewEncoder(os.Stdout)
enc.Indent(" ", " ")
if err := enc.Encode(v); err != nil {
fmt.Printf("error: %v\n", err)
}
}
I can understand in the struct Person, It has a var called Id, which is of type int, but what about the stuff xml:"person" after int? What does it mean? Thanks.
It's a struct tag. Libraries use these to annotate struct fields with extra information; in this case, the module encoding/xml uses these struct tags to denote which tags correspond to the struct fields.
which mean that variable will present in the name of Person example
type sample struct {
dateofbirth string `xml:"dob"`
}
In the above example, the field 'dateofbirth' will present in the name of 'dob' in the XML.
you will see this notation often in go struct.