Executing statements

In the expression API documentation above, there is only documentation for generating sql & bindings from helper functions. Now, we'll be dealing with executing statements using qb engine.

Executing Inserts, Upserts, Updates & Deletes

The following table & qb initializations are assumed;

package main

import (
	"fmt"
	"github.com/aacanakin/qb"
)

func main() {
	db, _ := qb.New("mysql", "root:@tcp(localhost:3306)/qb_test?charset=utf8")
	defer db.Close()

	users := qb.Table(
		"user",
		qb.Column("id", qb.Varchar().Size(36)),
		qb.Column("email", qb.Varchar().Unique().NotNull()),
		qb.Column("name", qb.Varchar().NotNull()),
		qb.PrimaryKey("id"),
	)

	metadata := qb.MetaData(db.Dialect())
	metadata.AddTable(users)
	err := metadata.CreateAll(db.Engine())
	checkErr(err)
  defer metadata.DropAll(db.Engine())
  
  // insert examples here
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

A simple insert statement can be executed by the following;

ins := users.
		Insert().
		Values(map[string]interface{}{
			"id":    "f82cdc-4d21-473b-a175-cbc3f9119eda",
			"email": "[email protected]",
			"name":  "Al Pacino",
		}).
		Build(db.Dialect())

res, err := db.Engine().Exec(ins)
checkErr(err)

insertId, err := res.LastInsertId()
checkErr(err)

rowsAffected, err := res.RowsAffected()
checkErr(err)

fmt.Printf("insertId: %d\n", insertId)
fmt.Printf("rowsAffected: %d\n", rowsAffected)

The output would be the following;

insertId: 0
rowsAffected: 1

The Update, Upsert & Delete statements are executed using Exec functions just the same with Insert.

You can use Exec() in any sql statements that inserts or updates data. Sqlite & mysql works fine in LastInsertId() & RowsAffected() functions. However, due to the driver implementation of postgres, the driver satisfies the exec interface but does give meaningless results.

❗️

Postgres driver does not support LastInsertId() & RowsAffected()

Therefore, there is an optional Returning clause just for postgres to keep retrieving results. Here's the following example shows how to retrieve by returning clause;

package main

import (
	"fmt"
	"github.com/aacanakin/qb"
)

func main() {
	db, _ := qb.New("postgres", "user=postgres dbname=qb_test sslmode=disable")
	defer db.Close()

	db.Dialect().SetEscaping(true)

	users := qb.Table(
		"user",
		qb.Column("id", qb.Varchar().Size(36)),
		qb.Column("email", qb.Varchar().Unique().NotNull()),
		qb.Column("name", qb.Varchar().NotNull()),
		qb.PrimaryKey("id"),
	)

	metadata := qb.MetaData(db.Dialect())
	metadata.AddTable(users)
	err := metadata.CreateAll(db.Engine())
	defer metadata.DropAll(db.Engine())
	checkErr(err)

	ins := users.
		Insert().
		Values(map[string]interface{}{
			"id":    "f82cdc-4d21-473b-a175-cbc3f9119eda",
			"email": "[email protected]",
			"name":  "Al Pacino",
		}).
		Returning(users.C("id")).
		Build(db.Dialect())

	var id string
	db.Engine().QueryRow(ins).Scan(&id)
	checkErr(err)
	fmt.Printf("id: %s\n", id)
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

This outputs the following;

id: f82cdc-4d21-473b-a175-cbc3f9119eda

The Returning clause is available for Insert(), Upsert(), Update() & Delete() functions.

Executing selects

The select executor functions are Query(), QueryRow(), Get() & Select().

Select using Query() & QueryRow()

Selects can be executed using Query() & QueryRow() functions as the following;

sel := users.
	Select(users.C("id")).
	Where(users.C("email").Eq("[email protected]")).
	Build(db.Dialect())

var id string
db.Engine().QueryRow(sel).Scan(&id)
fmt.Println("id:", id)

Output is;

id: f82cdc-4d21-473b-a175-cbc3f9119eda

The Query function can also be used in the following example;

sel := users.
		Select(users.C("id")).
		Where(users.C("email").Eq("[email protected]")).
		Build(db.Dialect())

ids := []string{}
rows, err := db.Engine().Query(sel)
checkErr(err)
for rows.Next() {
	var id string
	err = rows.Scan(&id)
	checkErr(err)
	ids = append(ids, id)
}
fmt.Println("ids:", ids)

Output is;

ids: [f82cdc-4d21-473b-a175-cbc3f9119eda]

Therefore, Query() function can be used to extract multiple rows from db.

Select using Get() & Select()

Get() & Select() functions of Engine is for mapping results to queries. Check out the following example with Get();

sel := users.
	Select(users.C("id")).
	Where(users.C("email").Eq("[email protected]")).
	Build(db.Dialect())

type User struct {
	ID string
}

var user User
err = db.Engine().Get(sel, &user)
checkErr(err)

fmt.Printf("User%+v\n", user)

Output is;

User{ID:f82cdc-4d21-473b-a175-cbc3f9119eda}

The same example can be done by using Select() & user slice;

sel := users.
		Select(users.C("id")).
		Where(users.C("email").Eq("[email protected]")).
		Build(db.Dialect())

type User struct {
	ID string
}

var selUsers []User
err = db.Engine().Select(sel, &selUsers)
checkErr(err)

fmt.Printf("Users%+v\n", selUsers)

As you might notice, Select() can be used for mapping result sets to multiple structs.

🚧

Joins are not "Select() & Get()"able

Currently, Select() & Get() functions can be used only while retrieving result sets from a single table. This issue will be addressed in 0.3 milestone of qb.