GO pg prevent default value - go

Struct sample
type Car struct {
ID uint64
Required bool `pg:"required,notnull"`
Name string `pg:"name"`
}
Migration:
BEGIN;
ALTER TABLE cars ADD COLUMN required BOOLEAN NOT NULL DEFAULT true;
END;
When I create car struct:
car = Car{Name:"Name",Required:false}
When i'm trying to add some new car by writing:
_, err = r.db.Model(&car).Insert()
SQL Query looks like this:
INSERT INTO "cars" ("id", "name", "required") VALUES (DEFAULT, "Name", DEFAULT)
The main problem that car has required field set as false, but when I inserting it - it changes to DEFAULT (true).

Because the value false will be read as a null value. Because null value your data will be change to the default value (TRUE)
You must change the struct to like this
type Car struct {
ID uint64
Required *bool `pg:"required,notnull,default:true"`
Name string `pg:"name"`
}
and define struct like this
required := false
car = Car{Name:"Name", Required: &required}
or you can also use data type sql.NullBool in your struct
type Car struct {
ID uint64
Required sql.NullBool `pg:"required,notnull,default:true"`
Name string `pg:"name"`
}
car = Car{Name:"Name", Required: sql.NullBool{Bool: false, Valid: true}}

Related

GORM: Select fields from two tables while joining

I have products table which has one-to-many relationship with items and brands tables. brands also have one-to-many relationship with items.
I was trying to query products and group them based on product_id and brand_id and it seems to work fine.
The only problem I have right now is that I can't map these fields brandId and BrandName, They always nil. But querying the raw SQL statement it generates the desired result.
Here are my models. Some fields have been omitted for simplicity.
type Brand struct {
ID int `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"index;not null;type:varchar(50);default:null"`
ProductID int `json:"productId"`
Product *Product `json:"product" gorm:"foreignKey:ProductID;"`
}
type Product struct {
ID int `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"index;not null;type:varchar(50);default:null"`
StoreID *int `json:"storeId"`
Store *Store `json:"store" gorm:"foreignKey:StoreID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT;"`
BrandID *int `json:"brandId" gorm:"-"` //SEE THIS
BrandName *string `json:"brandName" gorm:"-"` //SEE THIS TOO
Brands []*Brand `json:"brands" gorm:"constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;"`
}
type Item struct {
ID int `json:"id" gorm:"primaryKey"`
Quantity int `json:"quantity" gorm:"type:integer;not null;unsigned;"`
ProductID int `json:"productId"`
Product *Product `json:"product" gorm:"foreignKey:ProductID;not null;constraint:OnUpdate:RESTRICT,OnDelete:CASCADE;"`
BrandID *int `json:"brandId"`
Brand *Brand `json:"brand" gorm:"foreignKey:BrandID;constraint:OnUpdate:RESTRICT,OnDelete:CASCADE;"`
}
var products []*model.Product
var result *gorm.DB
query := DB.Table("products").
Where(&model.Product{StoreID: &StoreID}).
Joins("INNER JOIN items ON items.product_id = products.id").
Joins("LEFT JOIN brands ON brands.id = items.brand_id").
Where("items.quantity > 0").
Group("products.id, brands.id").
Select("products.*,brands.id AS brand_id, brands.name AS brand_name")
if err := query.Find(&products).Error; err != nil {
panic(err)
}
//Here results contains no brand_id nor brand_name
fmt.Printf("result %+v\n", products)
Here is raw SQL generated by gorm. And work as expected outside gorm
SELECT products.*,brands.id AS brand_id, brands.name AS brand_name
FROM "products"
INNER JOIN items ON items.product_id = products.id
LEFT JOIN brands ON brands.id = items.brand_id
WHERE "products"."store_id" = 2 AND items.quantity > 0
GROUP BY products.id, brands.id
First solution that comes in mind is to use -> instead of - gorm tag.
Like this
BrandID : Int #goTag(key: "gorm", value: "->")
BrandName : String #goTag(key: "gorm", value: "->")
The only drawback with this is that it saves these fields on database.
Any alternative?
has_many
type Brand struct {
ID int `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"index;not null;type:varchar(50);default:null"`
ProductID int `json:"productId"`
}
type Product struct {
ID int `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"index;not null;type:varchar(50);default:null"`
StoreID *int `json:"storeId"`
Store *Store `json:"store" gorm:"foreignKey:StoreID;constraint:OnUpdate:RESTRICT,OnDelete:RESTRICT;"`
Brands []*Brand `json:"brands" gorm:"constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;"`
}
you shouold read BrandId and BrandName in model-Brand but model-Product
Product have many Brands, so it have many BrandID/BrandName, why you defiene just a BrandNameor BrandID?

One to many inserting

I have two models: Order and OrderItem. I need to insert order and item of it from same request, e.g.:
{
"user_id": "1",
"total_price": "200",
"items": [
{
"product_id": 1,
"quantity": 10
},
{
"product_id": 2,
"quantity": 5
},
{
"product_id": 3,
"quantity":3
}
]
}
This is Order and OrderItem model
=========================== Order ===========================
type Order struct {
ID int `boil:"id" json:"id" toml:"id" yaml:"id"`
OrderNumber string `boil:"order_number" json:"order_number" toml:"order_number" yaml:"order_number"`
OrderDate time.Time `boil:"order_date" json:"order_date" toml:"order_date" yaml:"order_date"`
Status string `boil:"status" json:"status" toml:"status" yaml:"status"`
Note string `boil:"note" json:"note" toml:"note" yaml:"note"`
UserID int `boil:"user_id" json:"user_id" toml:"user_id" yaml:"user_id"`
CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"`
UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"`
R *orderR `boil:"-" json:"-" toml:"-" yaml:"-"`
L orderL `boil:"-" json:"-" toml:"-" yaml:"-"`
}
=========================== OrderItem ===========================
type OrderItem struct {
ID int `boil:"id" json:"id" toml:"id" yaml:"id"`
OrderID int `boil:"order_id" json:"order_id" toml:"order_id" yaml:"order_id"`
ProductID int `boil:"product_id" json:"product_id" toml:"product_id" yaml:"product_id"`
ProductPrice float64 `boil:"product_price" json:"product_price" toml:"product_price" yaml:"product_price"`
ProductName string `boil:"product_name" json:"product_name" toml:"product_name" yaml:"product_name"`
Quantity int `boil:"quantity" json:"quantity" toml:"quantity" yaml:"quantity"`
Discount float64 `boil:"discount" json:"discount" toml:"discount" yaml:"discount"`
Note string `boil:"note" json:"note" toml:"note" yaml:"note"`
CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"`
UpdatedAt time.Time `boil:"updated_at" json:"updated_at" toml:"updated_at" yaml:"updated_at"`
R *orderItemR `boil:"-" json:"-" toml:"-" yaml:"-"`
L orderItemL `boil:"-" json:"-" toml:"-" yaml:"-"`
}
What do people usually do? Is there a way to do this quickly with sqlboiler?
I think you needn't to do that, you can insert order model and orderItems model in different requests. This solution provide more option than for client. If you need to update or add new order item into the order, you also need this API to solve it.
Create some models like
type OrderItemInput struct {
ProductId int `json:"product_id"`
Quantity int `json:"quantity"`
}
type OrderInsertInput struct {
UserID int `json:"user_id"`
TotalPrice float64 `json:"total_price"`
Items []OrderItemInput `json:"items"`
}
Create new Order by fields UserId and TotalPrice of OrderInsertInput.
When there was OrderID, we will create OrderItem with each OrderItemInput and the OrderID.

Convert string in struct to []string

I have a struct as below:
type TourData struct {
ArtistID int //artist ID
RelationID string //key for relations
City string
Country string
TourDates []string
}
type MyRelation struct {
ID int `json:"id"`
DatesLocations map[string][]string `json:"datesLocations"`
}
which contains this data from a csv file:
1,nagoya-japan,Nagoya,Japan,
1,penrose-new_zealand,Penrose,New_Zealand,
1,dunedin-new_zealand,Dunedin,New_Zealand,
2,playa_del_carmen-mexico,Playa Del Carmen,Mexico,
2,papeete-french_polynesia,Papeete,French_Polynesia,
MyRelations is populated from an API which contains:
"index": [
{
"id": 1,
"datesLocations": {
"dunedin-new_zealand": [
"10-02-2020"
],
"nagoya-japan": [
"30-01-2019"
],
"penrose-new_zealand": [
"07-02-2020"
]
}
},
{
"id": 2,
"datesLocations": {
"papeete-french_polynesia": [
"16-11-2019"
],
"playa_del_carmen-mexico": [
"05-12-2019",
"06-12-2019",
"07-12-2019",
"08-12-2019",
"09-12-2019"
]
}
}
The dates come from another struct. The code I have used to populate this struct is as below:
var oneRecord TourData
var allRecords []TourData
for _, each := range csvData {
oneRecord.ArtistID, _ = strconv.Atoi(each[0])
oneRecord.RelationID = each[1]
oneRecord.City = each[2]
oneRecord.Country = each[3]
oneRecord.TourDates = Relations.Index[oneRecord.ArtistID-1].DatesLocations[each[1]]
allRecords = append(allRecords, oneRecord)
}
jsondata, err := json.Marshal(allRecords) // convert to JSON
json.Unmarshal(jsondata, &TourThings)
I need to group all the 1s together then the 2s etc. I thought to create another struct, and populate from this one but not having much luck - any ideas?
To clarify I would want say TourData.City to equal:
[Nagoya,Penrose,Dunedin]
[Playa Del Carmen, Papeete]
At the moment if I was to print TourData[0].City I would get Nagoya.
I have tried creating another struct to be populated from the TourData struct with the following fields:
type TourDataArrays struct {
ArtistID int
City []string
Country []string
TourDates [][]string
}
and then populate the struct using the code below:
var tourRecord TourDataArrays
var tourRecords []TourDataArrays
for i := 0; i < len(Relations.Index); i++ {
for j := 0; j < len(allRecords); j++ {
if allRecords[i].ArtistID == i+1 {
tourRecord.City = append(tourRecord.City, allRecords[j].City)
}
}
tourRecords = append(tourRecords, tourRecord)
}
However this is adding all the cities to one array i.e
[Nagoya, Penrose, Dunedin, Playa Del Carmen, Papeete].
If I understand your requirements correctly you needed to declare city as a string array as well. (And Country to go with it).
Check out this solution : https://go.dev/play/p/osgkbfWV3c5
Note I have not deduped country and derived city and country from one field in the Json.

How to use different scalar types for one field in graphQL schema?

I have an input type that says:
input testInput {
a: String
b: String
c: Boolean
}
I have a situation where field c can be either String or Boolean.
How can i implement the field c that will accept both String and Boolean ?
Graphql does not support union of scalar types.
So you can modify it this way
input testInput {
a: String
b: String
c: hybridType
}
type cBoolean {
content: Boolean
}
type cString {
content: String
}
union hybridType = cBoolean | cString

Cassandra read Column

String cqlStatement = "SELECT * FROM local";
for (Row row : session.execute(cqlStatement)) {
System.out.println(row.toString());
}
how to get each Column value from the selected row ?
If you are using cassandra ds-driver the following should work for you.
String cqlStatement = "SELECT * FROM local";
for (Row row : session.execute(cqlStatement))
{
row.getString("columnName"); // for string data type
// row.getBool("columnName"); for boolean data type
// row.getUUID("columnName"); for UUID type
// row.getVarint("columnName"); for int type
// row.getLong("columnName"); for long type
// row.getDate("columnName"); for date type
// row.getBytes("columnName"); for bytes/anonymous type
}

Resources