How to get corresponding fields when selecting specific columns? - go

Here is the code:
// User Model
type User struct {
UserID int `db:"user_id"`
UserNme string `db:"user_nme"`
UserEmail string `db:"user_email"`
UserAddressID sql.NullInt64 `db:"user_address_id"`
}
func (ur *userRepository) FindAll() ([]models.User, error) {
var users []models.User
query := "select user_nme from users"
err := ur.Db.Select(&users, query)
if err != nil {
return nil, err
}
return users, nil
}
Result:
&[]models.User{models.User{UserID:0, UserNme:"Jay Durgan", UserEmail:"", UserAddressID:sql.NullInt64{Int64:0, Valid:false}}, models.User{UserID:0, UserNme:"Arne Balistreri", UserEmail:"", UserAddressID:sql.NullInt64{Int64:0, Valid:false}}, models.User{UserID:0, UserNme:"Greg Willms", UserEmail:"", UserAddressID:sql.NullInt64{Int64:0, Valid:false}}, models.User{UserID:0, UserNme:"Lady Aisha McLaughlin", UserEmail:"", UserAddressID:sql.NullInt64{Int64:0, Valid:false}}, models.User{UserID:0, UserNme:"Mrs. Phoebe Boyle", UserEmail:"", UserAddressID:sql.NullInt64{Int64:0, Valid:false}}}%
As you can see, I didn't query user_id, user_email and user_address_id columns, but the result give me these fields with zero value.
So, is there a way only get the fields correspond to the queried columns?
Beside, I don't want to write it like this: &user.userNme, &user.xxx, &user.xxx which means write each field and populate it. It's too verbose.
Expected result is: {UserNme: "Jay Durgan"}...

By using struct, you can't.
The other fields will still be there with it's zero value. The fields are property of the struct so whether you need it or not, whether it stored retrieved value from db operation or not, all the fields will still be there.
The only solution for your case is by using map, so only value of correspondent fields will be retrieved.
var users []map[string]interface{}
query := "select user_nme from users"
err := ur.Db.Select(&users, query)
if err != nil {
return nil, err
}
Result:
&[]map[string]interface{}{map[string]interface{}{UserNme:"Jay Durgan"}, ...}

You can try this
func (ur *userRepository) FindAll() ([]models.User, error) {
users := []models.User{}.UserNme
query := "select user_nme from users"
err := ur.Db.Select(&users, query)
if err != nil {
return nil, err
}
return users, nil
}
Also you can follow this link
http://go-database-sql.org/retrieving.html

Related

go-pg how to select also entity from related table?

type Book struct {
tableName struct{} `pg:"book" json:"-"`
Id int `pg:"id,pk" json:"id"`
Author int `pg:"author_id,notnull" json:"-"`
Author *Author `pg:"fk:author_id" json:"author,omitempty"`
}
I want select book and author in one query.
If I try this:
var r []model.Book
_, err := dao.FusedDb.Query(&r, `SELECT * FROM book b INNER JOIN author a on a.id = b.author_id`)
I get an error
pg: can't find column=name in model=Book (try discard_unknown_columns)
I wrote down a piece of code that I always use when I've to deal with this scenario. First, let me show the code and then I'll comment on the relevant parts:
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
type Book struct {
gorm.Model
Title string
Description string
AuthorID uint
Author Author
}
type Author struct {
gorm.Model
FirstName string
LastName string
Books []Book
}
type Result struct {
BookId int
AuthorId int
Title string
FirstName string
LastName string
}
func main() {
conn, err := sql.Open("postgres", "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable")
if err != nil {
panic(err)
}
defer conn.Close()
// query
var result []Result
rows, err := conn.Query("select b.id, a.id, b.title, a.first_name, a.last_name from authors a inner join books b on a.id = b.author_id")
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var record Result
if err := rows.Scan(&record.BookId, &record.AuthorId, &record.Title, &record.FirstName, &record.LastName); err != nil {
panic(err)
}
result = append(result, record)
}
if err := rows.Err(); err != nil {
panic(err)
}
fmt.Printf("%v", result)
}
Structs definition
The Book and Author structs represent the tables defined in my database. Result is used to hold the fetched records through the query specified below.
The query
The query is pretty straightforward. We only used the method Query on the SQL client opened at the beginning of the main function. Then, we've to defer a call to the method Close on the rows variable to clean up.
Scanning
The for makes sure that we scan all of the rows retrieved with the Query method. To understand if there are other rows to fetch we use the method Next that returns a bool value indicating whether or not there are other rows to scan.
In the body of the for we declare a loop-scoped variable to hold the current record. Thanks to the Scan method we'll be able to assign each column to the relative field of the struct.
Lastly, we've to check for any error by invoking the method Err on the rows variable and handle it.
Let me know if this clarifies your question, thanks!

golang: convert row sql to object

Hello I am using pgx to use my postgres, and I have doubts as to how I can transform a row in the database into an aggregate
I am using entities and value objects
without value object it seems easy using marshal, but using value object I think it is not a good idea to have fields exported and then my question comes in, how can I convert my line into a struct of my aggregate
my aggregrate :
type Email struct {
address string
}
type Password struct {
value string
}
type Name struct {
firstName string
lastName string
}
type Person struct {
Id string
Name valueObject.Name
Email valueObject.Email
Password valueObject.Password
Created time.Time
Updated time.Time
}
func NewPerson(name valueObject.Name, email valueObject.Email, password valueObject.Password) *Person {
id := uuid.New()
return &Person{
Id: id.String(),
Name: name,
Email: email,
Password: password,
Created: time.Now(),
Updated: time.Now(),
}
}
all my value objects have a method to get the private value through a function simulating a get, I didn’t put the rest of the code of my value objects so it wouldn’t get big
func to get all rows from table:
func (r *personRepository) GetAll() (persons []*entities.Person, err error) {
qry := `select id, first_name, last_name, email, password created_at, updated_at from persons`
rows, err := r.conn.Query(context.Background(), qry)
return nil, fmt.Errorf("err")
}
If someone can give me a glimpse of how I can pass this line from the bank to a struct of my aggregate using this value object
You can use something like this (not yet tested and need optimization):
func (r *personRepository) GetAll() (persons []*entities.Person, err error) {
qry := `select id, first_name, last_name, email, password, created_at, updated_at from persons`
rows, err := r.conn.Query(context.Background(), qry)
var items []*entities.Person
if err != nil {
// No result found with the query.
if err == pgx.ErrNoRows {
return items, nil
}
// Error happened
log.Printf("can't get list person: %v\n", err)
return items, err
}
defer rows.Close()
for rows.Next() {
// Build item Person for earch row.
// must be the same with the query column position.
var id, firstName, lastName, email, password string
var createdAt, updatedAt time.Time
err = rows.Scan(&id, &firstName, &lastName, &email,
&createdAt, updatedAt)
if err != nil {
log.Printf("Failed to build item: %v\n", err)
return items, err
}
item := &entities.Person{
Id: id,
FirstName: firstName,
// fill other value
}
// Add item to the list.
items = append(items, item)
}
return items, nil
}
Don't forget to add the comma after text password in your query.
I am using entities and value objects without value object it seems easy using marshal,
Sorry, I don't know about the value object in your question.

How can I do conditional actions in SQLX

I have database store function:
func (p *ProductsRep) FindAll(PageNumber int, PaginationSize int, Query string) []*postgresmodels.Product {
Also I have SQL query look like this:
SELECT * FROM table_name.
Then I want to concat conditional action like WHERE some_value=3 if some value (in this case Query) exists then I want to get SELECT * FROM table_name WHERE some_value=3.
I tried to use fmt.Sprintf to concat, or strings.Join, or bytes.Buffer.WriteString. But everytime I getting this error:
I replace real value for understanding:
pq: column "Some value" does not exist.
How can I do "adaptive" queries, which depends on inputed function values.
I believe you are trying to query rows in the database by using parameters.
You need to make sure you don't pass this data in as RAW values, due to the potential risk of SQL injection. You can make queries by using store procedures
You can use the function Query to pass in your query with your parameters. In the example case this is $1. If you wanted to you could add $2, $3... etc depending on how many parameters you wanted to query
Here is two examples
Postgres
using "github.com/jackc/pgx/v4" driver
ctx := context.Background()
type Bar struct {
ID int64
SomeValue string
}
rows, err := conn.Query(ctx, `SELECT * FROM main WHERE some_value=$1`, "foo")
if err != nil {
fmt.Println("ERRO")
panic(err) // handle error
}
defer rows.Close()
var items []Bar
for rows.Next() {
var someValue string
var id int64
if err := rows.Scan(&id, &someValue); err != nil {
log.Fatal(err) // handle error
}
item := Bar{
ID: id,
SomeValue: someValue,
}
items = append(items, item)
}
fmt.Println(items)
MySQL Driver
https://golang.org/pkg/database/sql/#DB.QueryRow
type Bar struct {
ID int64
SomeValue string
}
rows, err := conn.Query(`SELECT * FROM main WHERE some_value=$1`, "foo")
if err != nil {
fmt.Println("ERRO")
panic(err) // handle error
}
defer rows.Close()
var items []Bar
for rows.Next() {
var someValue string
var id int64
if err := rows.Scan(&id, &someValue); err != nil {
log.Fatal(err) // handle error
}
item := Bar{
ID: id,
SomeValue: someValue,
}
items = append(items, item)
}
fmt.Println(items)

Gorm query returning only a single row

We're trying to use Gorm with mysql 8 to much frustration.
I have the following tables (simplified for brevity here)
type StoragePool struct {
gorm.Model
PoolId string `json:"id" gorm:"column:poolid;size:40;unique;not null"`
Volumes []Volume `json:"volumes" gorm:"foreignkey:StorageId;association_foreignkey:PoolId"`
}
type Volume struct {
gorm.Model
StorageId string `json:"storageid" gorm:"column:storageid;size:40"`
}
Data insertions seem to work fine. Both tables get populated and no constraints are violated.
A query that expects a single record seems to work fine:
poolRecord := &StoragePool{}
if err := tx.Where("poolid = ?", pool.PoolId).First(&StoragePool{}).Scan(poolRecord).Error; err != nil {
return err
}
This query only returns a single row. When I perform this exact query as raw SQL outside of go, it returns all 31 records I expect.
var poolVolumes []Volume
if err := tx.Where("storageid = ?", pool.PoolId).Find(&Volume{}).Scan(&poolVolumes).Error; err != nil {
return err
}
log.Debugf("found %d volumes belonging to %q [%s]", len(poolVolumes), pool.Name, pool.PoolId)
According to the docs, that second sql statement is the equivalent of "SELECT * FROM VOLUMES WHERE STORAGEID = 'poolid'". That is not the behavior I am getting.
Anyone have any ideas what I'm doing wrong here?
I rarely use an ORM while coding with go, but following the doc from gorm, it seems like you are doing it the wrong way.
Scan is used for scanning result into another struct, like this:
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result)
The correct way to get query results into a slice of structs should be:
var poolVolumes []Volume
if err := tx.Where("storageid = ?", pool.PoolId).Find(&poolVolumes).Error; err != nil {
return err
}

Would I be better by using a prepared statement here?

I still struggle understanding the benefits of prepared statement in Go / psql.
Let's assume I have a struct
type Brand struct {
Id int `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Issued_at *time.Time `json:"issued_at,omitempty"`
}
And some table brands, where id is a unique field. Now I want to retrieve the element from that table using and id.
I can write the following function using QueryRow.
func GetBrand1(id int) (Brand, error) {
brand := Brand{}
if err := Db.QueryRow("SELECT name, issued_at FROM brands WHERE id = $1", id).Scan(&brand.Name, &brand.Issued_at); err != nil {
if err == sql.ErrNoRows {
return brand, nil
}
return brand, err
}
brand.Id = id
return brand, nil
}
and I can do the same (I hope it is the same) using prepared statement:
func GetBrand2(id int) (Brand, error) {
brand := Brand{}
stmt, err := Db.Prepare("SELECT name, issued_at FROM brands WHERE id = $1")
if err != nil {
return brand, err
}
defer stmt.Close()
rows, err := stmt.Query(id)
if err != nil {
return brand, err
}
defer rows.Close()
for rows.Next() {
rows.Scan(&brand.Name, &brand.Issued_at)
brand.Id = id
return brand, err
}
if err = rows.Err(); err != nil {
return brand, err
}
return brand, err
}
Now in my application I am planning to execute GetBrand* function many times (with different parameters). Will is one of this implementations is more preferable to another (in terms of sql-requests/memory/anything). Or may be they both suck and I would be better doing something else.
I have read this and a followed up link and I saw that:
db.Query() actually prepares, executes, and closes a prepared
statement. That’s three round-trips to the database. If you’re not
careful, you can triple the number of database interactions your
application makes
but I think that prepared statement in the second case will be removed at the end of the function.
In both of those examples, there's roughly the same database overhead. If you're going to use a statement a lot, prepare it once in a wider scope so it's reusable.
You would only be making one round trip to the database with that pattern.
If you're ever using databases in conjunction with user input, you should always prepare the statement beforehand.
If not, you run a risk of DB Insertion (SQL Insertion ex).

Resources