Skip to content

Instantly share code, notes, and snippets.

@hitalos
Last active January 31, 2019 16:07
Show Gist options
  • Save hitalos/c37b4a5928ebe4fc7fd210b875415085 to your computer and use it in GitHub Desktop.
Save hitalos/c37b4a5928ebe4fc7fd210b875415085 to your computer and use it in GitHub Desktop.
Exemplo de uso da função `StructScan` do pacote sqlx
DROP TABLE IF EXISTS items;
DROP TABLE IF EXISTS categories;
DROP TABLE IF EXISTS menus;
CREATE TABLE IF NOT EXISTS menus (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL UNIQUE,
description VARCHAR
);
CREATE TABLE IF NOT EXISTS categories (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL UNIQUE,
menu_id INTEGER NOT NULL,
CONSTRAINT fk_menu FOREIGN KEY (menu_id)
REFERENCES menus (id) MATCH SIMPLE
ON UPDATE RESTRICT
ON DELETE RESTRICT
);
CREATE TABLE IF NOT EXISTS items (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL UNIQUE,
description VARCHAR,
category_id INTEGER,
CONSTRAINT fk_category FOREIGN KEY (category_id)
REFERENCES categories (id) MATCH SIMPLE
ON UPDATE RESTRICT
ON DELETE RESTRICT
);
TRUNCATE TABLE items CASCADE;
TRUNCATE TABLE categories CASCADE;
TRUNCATE TABLE menus CASCADE;
INSERT INTO menus (name, description) VALUES
('Comidas', 'Coisas de mastigar'),
('Bebidas', 'Coisas de beber'),
('Sobremesas', 'Coisas de engordar')
;
INSERT INTO categories (name, menu_id) VALUES
('Massas', (SELECT id FROM menus WHERE name = 'Comidas')),
('Risotos', (SELECT id FROM menus WHERE name = 'Comidas')),
('Caldos', (SELECT id FROM menus WHERE name = 'Comidas')),
('Sucos', (SELECT id FROM menus WHERE name = 'Bebidas')),
('Refrigerantes', (SELECT id FROM menus WHERE name = 'Bebidas')),
('Drinks e coquetéis', (SELECT id FROM menus WHERE name = 'Bebidas')),
('Doces', (SELECT id FROM menus WHERE name = 'Sobremesas')),
('Sorvetes', (SELECT id FROM menus WHERE name = 'Sobremesas'))
;
INSERT INTO items (name, category_id) VALUES
('Lasanha', (SELECT id FROM categories WHERE name = 'Massas')),
('Nhoque', (SELECT id FROM categories WHERE name = 'Massas')),
('Ravioli', (SELECT id FROM categories WHERE name = 'Massas')),
('Camarão', (SELECT id FROM categories WHERE name = 'Risotos')),
('Funghi', (SELECT id FROM categories WHERE name = 'Risotos')),
('Caldo verde', (SELECT id FROM categories WHERE name = 'Caldos')),
('Canja', (SELECT id FROM categories WHERE name = 'Caldos')),
('Limão', (SELECT id FROM categories WHERE name = 'Sucos')),
('Laranja', (SELECT id FROM categories WHERE name = 'Sucos')),
('Soda', (SELECT id FROM categories WHERE name = 'Refrigerantes')),
('Capeta', (SELECT id FROM categories WHERE name = 'Drinks e coquetéis')),
('Caipirosca', (SELECT id FROM categories WHERE name = 'Drinks e coquetéis')),
('Leite', (SELECT id FROM categories WHERE name = 'Doces')),
('Mamão', (SELECT id FROM categories WHERE name = 'Doces')),
('Coco', (SELECT id FROM categories WHERE name = 'Sorvetes')),
('Chocolate', (SELECT id FROM categories WHERE name = 'Sorvetes'))
;
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"time"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
type defaultModel struct {
ID uint64 `db:"id" json:"id,omitempty"`
Name string `db:"name" json:"name"`
Timestamps
}
type Timestamps struct {
CreatedAt *time.Time `db:"createdAt,omitempty" json:"createdAt,omitempty"`
DeletedAt *time.Time `db:"deletedAt,omitempty" json:"deletedAt,omitempty"`
}
type Menu struct {
defaultModel
Description *string `db:"description" json:"description,omitempty"`
}
type Category struct {
defaultModel
Description *string `db:"description" json:"description,omitempty"`
Menu Menu `db:"menu" json:"menu"`
}
type Item struct {
defaultModel
Description *string `db:"description" json:"description,omitempty"`
Category Category `db:"category" json:"category,omitempty"`
}
func listItems(db *sqlx.DB) ([]Item, error) {
query := `SELECT
categories.id AS "category.id",
categories.name AS "category.name",
menus.id AS "category.menu.id",
menus.name AS "category.menu.name",
items.id,
items.name,
items.description
FROM
menus INNER JOIN categories ON menus.id = categories.menu_id
INNER JOIN items ON items.category_id = categories.id
ORDER BY
items.name`
rows, err := db.Queryx(query)
if err != nil {
return nil, err
}
items := []Item{}
for rows.Next() {
item := new(Item)
if err := rows.StructScan(item); err != nil {
log.Println(err)
return nil, err
}
items = append(items, *item)
}
if err := rows.Close(); err != nil {
log.Println(err)
return nil, err
}
return items, nil
}
func main() {
dsn := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_NAME"))
db, err := sqlx.Open("postgres", dsn)
if err != nil {
log.Fatalln(err)
}
defer db.Close()
items, err := listItems(db)
if err != nil {
log.Fatalln(err)
}
enc := json.NewEncoder(os.Stdin)
enc.SetIndent("", " ")
if err := enc.Encode(items); err != nil {
log.Fatalln(err)
}
}
@crgimenes
Copy link

O exemplo esta muito bom mas usando SQLX podemos diminuir ligeiramente o tamanho da função listItens usando a função db.Select ;)

func listItems(db *sqlx.DB) ([]Item, error) {
	query := `SELECT
		categories.id AS "category.id",
		categories.name AS "category.name",
		menus.id AS "category.menu.id",
		menus.name AS "category.menu.name",
		items.id,
		items.name,
		items.description
	FROM
		menus INNER JOIN categories ON menus.id = categories.menu_id
		INNER JOIN items ON items.category_id = categories.id
	ORDER BY
		items.name`

	items := []Item{}
	err := db.Select(&items, query)
	return items, err
}

@hitalos
Copy link
Author

hitalos commented Jan 31, 2019

Genial! Diminui bastante!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment