Backend @ NewStore
@JanPantel
I [...] think that's one of the "beauties" of Go: it only does what you type -- there's almost no magic involved.
At first I was disappointed with the feature set of IDEs, but now there is Gogland
While I still sometimes long for more advanced language features, I'm always glad when seeing other's code and understanding it immediately. As I read more existing code than writing new, it pays off hugely for me
Using repository-like interfaces makes me think about the interface first.
[In other languages] it feels like I'm just writing helpers to hide the database handling part.
So it feels like my interfaces are more well thought when I write GO code.
var user User
err := db.Find("users", 1).Scan(&user)iUser, err := db.Find(User{}, 1)
user := iUser.(*User)
var users []*User
q.Condition(
qbs.NewCondition(
"last_name = ?", "Doe",
).Or(
"age < ?", 12,
),
).Limit(2).
OrderByDesc("age").
FindAll(&users)var users []User
orm.Where(
"last_name = ? OR age < ?", "Doe", 12,
).Limit(2).OrderBy("age").FindAll(&users)type Product struct {
ID string `db:"id"`
Name string `db:"name"`
}
func (p *Product) TableName() string {
return "product"
}type Product struct {
/* ... */
CategoryID string
}SELECT category_i_d FROM products;is the tendency of software architects to create a system so customizable as to become a replica, and often a poor replica, of the software development platform they are using.
Using repository-like interfaces makes me think about the interface first.
db.Query("SELECT bar FROM foo WHERE id = $1", id)rows.Scan(&record.ID)stmt, err := tx.Prepare("INSERT INTO foo VALUES ($1)")
if err != nil {
log.Fatal(err)
}
for i := 0; i < 10; i++ {
_, err = stmt.Exec(i)
if err != nil {
log.Fatal(err)
}
}
if err := stmt.Close(); err != nil {
log.Fatal(err)
}ATTENTION
stmt, err := txn.Prepare(pq.CopyIn("users", "name", "age"))
if err != nil {
log.Fatal(err)
}
for _, user := range users {
_, err = stmt.Exec(user.Name, int64(user.Age))
if err != nil {
log.Fatal(err)
}
}
_, err = stmt.Exec()
if err != nil {
log.Fatal(err)
}
err = stmt.Close()
if err != nil {
log.Fatal(err)
}var infos []string
rows, err := db.Query(
"SELECT infos FROM myTable WHERE id = 'foobar';",
)
// ...
err := rows.Scan(pq.Array(&infos))db.Exec(
"INSERT INTO myTable (infos) VALUES ($1);",
pq.StringArray(infos),
)rows, err := repo.db.Query(
"SELECT infos FROM myTable WHERE id = any($1::text[]);",
pq.StringArray(ids),
)Store
Stock items
Allocations
CREATE OR REPLACE VIEW unallocated_stock_items AS (
SELECT items.* FROM stock_items AS items
LEFT OUTER JOIN allocations AS alloc
ON alloc.stock_item_id = items.id
WHERE alloc.stock_item_id IS NULL
);SELECT (
(SELECT COUNT(si.*) FROM unallocated_stock_items AS si
WHERE si.product_id = $1 AND si.store_location_id = $2)
-
(SELECT COUNT(res.*) FROM reservations AS res
WHERE res.product_id = $1 AND res.store_location_id = $2)
);SELECT (SUM(quantity) > 0) AS available FROM atp
WHERE product_id = $1
GROUP BY product_id
LIMIT 1;CREATE OR REPLACE FUNCTION archive_deleted_allocations()
RETURNS trigger AS $$
BEGIN
INSERT INTO allocations_archive VALUES ((OLD).*);
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER archive_deleted_allocations
BEFORE DELETE ON allocations
FOR EACH ROW EXECUTE PROCEDURE archive_deleted_allocations();CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS trigger AS $$
BEGIN
NEW.updated_at = (NOW() AT TIME ZONE 'UTC');
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER atp_updated_at_trigger
BEFORE UPDATE ON atp
FOR EACH ROW EXECUTE PROCEDURE update_updated_at();