Categorygithub.com/ultraware/qb
modulepackage
2.6.0+incompatible
Repository: https://github.com/ultraware/qb.git
Documentation: pkg.go.dev

# README

qb

qb is a library that allows you to build queries without using strings. This offers some unique advantages:

  • When changing your database queries that refer to old fields or tables won't compile until you update them
  • You can't misspell keywords or fieldnames, this saves a lot of time and many bugs
  • You can use tab completion
  • You can easily port a query to a different database
  • The order of commands in your query does not matter, this makes building queries in parts or adding optional statements easier

Installation

go get git.ultraware.nl/NiseVoid/qb/...

Quick start guide

1. Create a db.json

You can create a db.json manually or use qb-architect to generate it from your database

qb-architect example:

qb-architect -dbms psql host=127.0.0.1 username=qb_test dbname=qb_test > db.json

db.json example:

[
	{
		"name": "TableOne",
		"alias": "one", // optional
		"fields": [
			{
				"name": "Field1",
				"data_type": "int",     // optional
				"read_only": true       // optional
			},
			{
				"name": "Field2",
				"data_type": "varchar", // optional
				"size": 50,             // optional
			},
			{ ... }
		]
	},
	{
		"name": "TableTwo",
		"fields": [
			{"name": "Field1"},
			{"name": "Field2"},
			{"name": "Field3"}
		]
	}
]

2. Run qb-generator

qb-generator db.json tables.go

Recommendations

  • Don't commit qb-generator's generated code to your repo
  • Use a go generate command to run qb-generator

3. Make a qbdb.DB

package main

var db *qbdb.DB

func main() {
	database, err := sql.Open(driver, connectionString)
	if err != nil {
		panic(err)
	}

	db = autoqb.New(database)
}

4. Write queries!

You can now write queries, you can find examples below

Examples

Select

one := model.One()

q := one.Select(one.Field1, one.Field2).
	Where(qc.In(Field1, 1, 2, 3))

rows, err := db.Query(q)
if err != nil {
	panic(err)
}

for rows.Next() {
	f1, f2 := 0, ""
	err := rows.Scan(&f1, &f2)
	if err != nil {
		panic(err)
	}

	fmt.Println(f1, f2)
}

Insert

one := model.One()

q := one.Insert(one.Field1, one.Field2).
	Values(1, "Record 1").
	Values(2, "Record 2").
	Values(4, "Record 4")

_, err := db.Exec(q)
if err != nil {
	panic(err)
}

Update

one := model.One()

q := one.Update().
	Set(one.Field2, "Record 3").
	Where(qc.Eq(one.Field1, 4))

_, err := db.Exec(q)
if err != nil {
	panic(err)
}

Delete

one := model.One()

q := one.Delete(qc.Eq(one.Field1, 4))

_, err := db.Exec(q)
if err != nil {
	panic(err)
}

Prepare

one := model.One()

id := 0
q := one.Select(one.Field1, one.Field2).
	Where(qc.Eq(one.Field1, &id))

stmt, err := db.Prepare()
if err != nil {
	panic(err)
}

for _, v := range []int{1,2,3,4,5} {
	id = v

	row := stmt.QueryRow()

	f1, f2 := 0, ""
	err := row.Scan(&field1, &field2)
	if err != nil {
		panic(err)
	}

	fmt.Println(f1, f2)
}

Subqueries

one := model.One()

sq := one.Select(one.Field1).SubQuery()

q := sq.Select(sq.F[0])

rows, err := db.Query(q)
if err != nil {
	panic(err)
}

for rows.Next() {
	f1 := 0
	err := rows.Scan(&f1)
	if err != nil {
		panic(err)
	}

	fmt.Println(f1)
}

Alternatively, .CTE() can be used instead of .SubQuery() to use a CTE instead of a subquery

Custom functions

func dbfunc(f qb.Field) qb.Field {
    return qf.NewCalculatedField("dbfunc(", f, ")")
}
q := one.Select(dbfunc(one.Field1))

Custom conditions

func dbcond(f qb.Field) qb.Condition {
	return qc.NewCondition("dbcond(", f, ")")
}
q := one.Select(one.Field1).
	Where(dbcond(one.Field1))

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Functions

AliasGenerator returns an incrementing alias for each new Source.
Asc is used to sort in ascending order.
ConcatQuery combines strings and Fields into string.
Default uses a field's default value.
Desc is used to sort in descending order.
Except combines queries with an EXCEPT.
ExceptAll combines queries with an EXCEPT ALL.
GetFuncFrame returns a function.
Intersect combines queries with an INTERSECT.
IntersectAll combines queries with an INTERSECT ALL.
JoinQuery joins fields or values into a string separated by sep.
MakeField returns the value as a Field, no operation performed when the value is already a field.
NewContext returns a new *Context.
NewSelectBuilder retruns a new SelectBuilder.
NewSQLBuilder returns a new SQLBuilder.
NoAlias returns no alias.
Returning creates a RETURNING or OUTPUT query.
Union combines queries with an UNION.
UnionAll combines queries with an UNION ALL.
Value creats a new Field.

# Constants

All defined DataTypes.
All defined DataTypes.
All defined DataTypes.
All defined DataTypes.
All possible join types.
All possible join types.
All possible join types.
All possible join types.
All defined DataTypes.
All defined DataTypes.

# Variables

Values used when building queries.
Values used when building queries.
Values used when building queries.
Values used when building queries.

# Structs

Context contains all the data needed to build parts of a query.
CTE is a type of subqueries.
DeleteBuilder builds a DELETE query.
FieldOrder specifies the order in which fields should be sorted.
InsertBuilder builds an INSERT query.
ReturningBuilder builds a query with a RETURNING statement.
SelectBuilder builds a SELECT query.
SQLBuilder contains data and methods to generate SQL.
SubQuery represents a subquery.
Table represents a table in the database.
TableField represents a field in a table.
UpdateBuilder builds an UPDATE query.

# Interfaces

Alias generates table aliasses.
Driver implements databse-specific features.
Field represents a field in a query.
Query generates SQL.
SelectQuery represents a query that returns data.
Source represents a table or a subquery.
SQL represents an SQL string.

# Type aliases

Condition is used in the Where function.
DataType represents a type in a database.
Join is the type of join.
OverrideMap allows a driver to override functions from qf and qc.