golang ORM name of table - postgresql

I have some code to create the table in Postgres DB
import (
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
)
type Table struct {
Id int `gorm:"primary_key"`
Name string `gorm:"type:varchar(100)"`
Addr string `gorm:"type:varchar(100)"`
}
func main() {
db, _ := gorm.Open("postgres", "user=postgres password=poilo777 dbname=mydb sslmode=disable")
defer db.Close()
db.CreateTable(&Table{})
user := &Table{Name: "ololo", Addr: "pololo"}
there are 2 problems, i faced:
1) in database created a table "tables" instead of "Table"
2) how can I insert data in existing another tables? (for example "users")

1) You can set Table's table name to be table
func (Table) TableName() string {
return "table"
}
Another way is to set singularTable true, then Table's default table name will be table instead of tables. But it will affect all tables the same.
set db.SingularTable(true)
2) In ORM you should define your table object. Here is a struct called Table. Gorm will create a new table called tables in database unless you want to overwrite table's name you can follow step 1.

By default, the golang Postgres Client will implicitly use the pluralized version of your struct name[1]. For example
type Student struct {
FirstName string
LastName string
}
// will create a table name `students`
You can override it like the following, depending on what you are using
GORM
// Set User's table name to be `profiles`
func (Student) TableName() string {
return "college_students"
}
GO-PQ
type Student struct {
tableName struct{} `pg:"college_students,alias:g"``
}
https://gorm.io/docs/conventions.html#Pluralized-Table-Name

My solving of this problem:
db.Table("my_table").CreateTable(&Table{})
user := &Table{Name: "ololo", Addr: "pololo"}
db.Table("my_table").Create(user)
This code creates table my_table as I wanted

Related

Correct way to access data from postgresql using go-pgsql in GoLang

I've been reading the GoLang go-pgsql documentation in order to figure out how to access data with nested objects, but I have so far been unsuccessful.
Here's the description of what I am trying to achieve:
I have two models ClimateQuestions and Steps:
type ClimateQuestions struct {
tableName struct{} `pg:"climatequestions"`
Id int `json:"id" pg:",pk"`
Title string `json:"title"`
Steps []*Steps `pg:"rel:has-many"`
}
type Steps struct {
tableName struct{} `pg:"steps"`
Id int `json:"id"`
Label string `json:"label"`
Number int `json:"number"`
QuestionId int `json:"question_id"`
}
and here is how they're defined in the database:
CREATE TABLE climatequestions (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
CREATE TABLE steps (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
value DOUBLE PRECISION NOT NULL,
question_id INT REFERENCES climatequestions(id)
);
And a relationship between these models is this: For every climate question, there can be many steps. I have denoted this by adding a field in ClimateQuestions struct called Steps with rel:has-many.
Now, from the database, I would like to obtain all the climate questions, and within each of them, I want an array of steps data.
My first method to achieve this has been the following:
var climateQuestions []model.ClimateQuestions
err := db.Model(&climateQuestions).Select()
This partially works in that it returns all the data relevant for climate questions, but it does not add the nested steps data. Here is the JSON format of what is returned:
[{"id":1,"title":"first question?","Steps":null},{"id":2,"title":"second question?","Steps":null}]
Any ideas as to how I may achieve this?
Because you have custom join foreign key, you need to add tag pg:"rel:has-many,join_fk:question_id" in ClimateQuestions.Steps
In struct Steps, you need to tell pg which field it is.
You forgot to call Relation function
this is the correct struct
type ClimateQuestions struct {
tableName struct{} `pg:"climatequestions"`
Id int `json:"id" pg:",pk"`
Title string `json:"title"`
Steps []*Steps `pg:"rel:has-many,join_fk:question_id"`
}
type Steps struct {
tableName struct{} `pg:"steps"`
Id int `json:"id"`
Label string `json:"label" pg:"title"`
Number int `json:"number" pg:"value"`
QuestionId int `json:"question_id"`
}
this is how you should exec db.
var climateQuestions []ClimateQuestions
err := db.Model(&climateQuestions).Relation("Steps").Select()
if err != nil {
panic(err.Error())
}
for _, v := range climateQuestions {
fmt.Printf("%#v\n", v)
for _, v1 := range v.Steps {
fmt.Printf("%#v\n", v1)
}
fmt.Println("")
}

Using go's sqlx to insert record in postgres table with automatic ID generation

I am using sqlx to create a go api.
I want to insert a record in a table named day.
The corresponding go struct is the following
type Day struct {
ID string `db:"id" json:"id"`
Dateday string `db:"dateday" json:"dateday"`
Nameday string `db:"nameday" json:"nameday"`
Holyday bool `db:"holyday" json:"holyday"`
}
In an endpoint for Day creation, will be receiving all fields but the ID via a post request
What method should I use to interact with my db so as to:
a) create the record
b) not need to pass the ID myself and instruct postgres to auto-generate the field.
The table creation statement is the following:
CREATE TABLE IF NOT EXISTS "day" (
"id" SERIAL PRIMARY KEY,
"dateday" date NOT NULL,
"nameday" varchar(10) NOT NULL,
"holyday" boolean NOT NULL
);
I would suggest to override the MarshalJSON method as mentioned below:
func (r Day) MarshalJSON() ([]byte, error) {
root := make(map[string]interface{})
root["dateday"] = r.Dateday
root["nameday"] = r.Nameday
root["holyday"] = r.Holyday
return json.Marshal(root)
}
Ref: https://golang.org/pkg/encoding/json/#example__customMarshalJSON

Convert a postgres row into golang struct with array field

I am having postgres db table as
CREATE TABLE foo (
name varchar(50),
types varchar(50)[],
role varchar[10]
);
and corresponding struct in go:
type Foo struct {
Name string `db:"name"`
Types []string `db:"types"`
Role string `db:"role"`
}
I want to fetch db rows into my struct. Right now I am able to do this by using:
var foo Foo
query := `SELECT name, types, roles FROM foo LIMIT 1`
err = dbConn.QueryRow(query).Scan(&foo.Name, pq.Array(&foo.Types), &foo.Role)
But I want to achieve the same using direct mapping. Something like:
var foo []Foo
query := `SELECT name, types, roles FROM foo`
dbWrapper.err = dbConn.Select(&foo, query)
Above snippet gives me error because of Types being pq array. Is it possible to directly map pq array as a part of struct?
Thanks to https://stackoverflow.com/a/44385791/10138004, I am able to solve this pq driver for sqlx (https://godoc.org/github.com/lib/pq) itself by replacing []string with pq.StringArray.
So, updated struct looks like:
type Foo struct {
Name string `db:"name"`
Types pq.StringArray `db:"types"` //this is what changed.
Role string `db:"role"`
}
and direct mapping is working like a charm now
var foo []Foo
query := `SELECT name, types, roles FROM foo`
dbWrapper.err = dbConn.Select(&foo, query)
You can use pg-go lib for that. Please look at pg.Model(). It's possible to pass an entire struct to it.

How to dynamically set table name for every query in go-pg?

I have a bunch of similar temp tables which I am trying to query using go-pg's ORM. I can't find a way to dynamically change the queried table during a select:
import "gopkg.in/pg.v4"
type MyModel struct {
TableName struct{} `sql:"temp_table1"`
Id int64
Name string
}
var mymodels []MyModel
err := db.Model(&mymodels).Column("mymodel.id", "mymodel.name").Select()
This will query temp_table1 as defined in the model's TableName. Is there a way to pass table name as a parameter so I can query temp_table_X?
(I can just not use ORM and go with raw db.Query(), but I wanted to see if there is a way to use ORM).
Got an answer on github:
err := db.Model().TableExpr("temp_table_999 AS mymodel").Column("mymodel.id", "mymodel.name").Select(&mymodels)
Seems you can specify the table directly: db.Model(&mymodels).Table('temp_table1').Column("mymodel.id", "mymodel.name").Select()

Golang: gorm use Find(&model) for non gorm migrate table

There is table customer_account (postgres) which one was migrate from YII2.
DDL:
CREATE TABLE public.test_table (
id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('test_table_id_seq'::regclass),
data JSONB
);
In go project i try to get value from this table.
type TableGo struct {
Id int
Data string `gorm:"type:jsonb"`
}
table := TableGo{}
db.Where("id = ?", 75).Find(&table)
println(table.Data)
But there is (pq: relation "table_gos" does not exist)
How i can link structure which table without db.AutoMigrate(&TableGo{})?
I think table name in your migration script is wrong. Because it is not in GORM convention. If you want to use that name,you can use following method in your model for custom table name.
func (m *Model) TableName() string {
return "custom_table_name"
}
Found the solution:
func(TableGo) TableName() string {
return "account_status"
}