# Orm

通过 dsn 连接数据库 driver ,读取 schema 信息生成 ORM 结构体定义及相关辅助代码。

# 使用

# 注解

+zz:orm:[schema][:options...]

# 注解对象

所有对象

# 必填参数

# schema

要读取的数据库 schema 名,多个可用 , 分隔。

示例: +zz:orm:my_database

# 可选参数

# filename

指定生成的文件路径,默认 ./zzgen.orm.go

示例: +zz:orm:schema:filename=./models/

# driver

指定使用生成 schemadriver,此 driver 不同于 sql.Driver,为本工具独立维护对不同数据库种类的不同类型的生成器。

外部生成器可通过 .so 插件形式加载。

默认 mysql

示例: +zz:orm:schema:driver=sqlite

# type

指定生成时的数据类型映射。 格式 ${数据库DATA_TYPE}=${Golang类型}

示例: +zz:orm:schema:type=varchar=MyString

可以使用 , 连接多个指定类型。

示例: +zz:orm:schema:type=varchar=MyString,varchar(255)=string,int unsign=uint

数据库格式匹配的优先级由不同 schemadriver 自行控制。

若要指定 Nullable 类型,可使用 * 前缀。

示例: +zz:orm:schema:type=*varchar=sql.NullString,*json=*json.RawMessage

# table

指定生成的数据表,默认 * 即选取全部数据表进行生成。

可以使用 , 连接多个表。

示例: +zz:orm:schema:table=user,car,order

# password

通常开发者都是在本地开发环境进行 orm 的生成和基于生成内容进行开发。

因此 driver 会提供一个对应数据库类型默认安装本地连接的 dsn 模版。

mysql 通常为 root:${pwd}@tcp(localhost:3306)/

使用者可以只提供 password,就能通过默认安装地址和用户完成访问。

建议通过以以下方式使用,示例:

read -s pwd && gozz run -p "orm:password=${pwd}" ./

# dsn

如果对数据库连接地址有额外需求,可通过提供完整 dsn 进行访问。

涉及 : 时要使用 \ 进行参数转义

示例:

read -s pwd && gozz run -p "orm:dsn=dev_user\:${pwd}@tcp(192.168.1.2\:3306)/" ./

# 示例

示例项目 (opens new window) 示例SQL (opens new window)

package orm01

// +zz:orm:{{ .Name }}
type employees struct{}

执行 gozz run -p "orm:password=***" ./ 生成 zzgen.orm.go 和模版文件。

// Code generated by gozz:orm github.com/go-zing/gozz. DO NOT EDIT.

package orm01

import (
	"context"
	"database/sql"
	"encoding/json"
	"time"
)

var (
	_ = (*context.Context)(nil)
	_ = (*json.RawMessage)(nil)
	_ = (*time.Time)(nil)
	_ = (*sql.NullString)(nil)
)

var tables = []interface{}{
	CurrentDeptEmp{},
	Departments{},
	DeptEmp{},
	DeptEmpLatestDate{},
	DeptManager{},
	Employees{},
	Salaries{},
	Titles{},
}

// employees.current_dept_emp
// VIEW
const TableCurrentDeptEmp = "current_dept_emp"

type CurrentDeptEmp struct {
	// emp_no : int
	EmpNo int
	// dept_no : char(4)
	DeptNo string
	// from_date : NULLABLE date
	FromDate interface{}
	// to_date : NULLABLE date
	ToDate interface{}
}

func (CurrentDeptEmp) TableName() string { return TableCurrentDeptEmp }

func (m *CurrentDeptEmp) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["dept_no"] = &m.DeptNo
	dst["from_date"] = &m.FromDate
	dst["to_date"] = &m.ToDate
}

type SliceCurrentDeptEmp []CurrentDeptEmp

func (s *SliceCurrentDeptEmp) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, CurrentDeptEmp{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.departments
const TableDepartments = "departments"

type Departments struct {
	// dept_no : char(4)
	DeptNo string
	// dept_name : varchar(40)
	DeptName string
}

func (Departments) TableName() string { return TableDepartments }

func (m *Departments) FieldMapping(dst map[string]interface{}) {
	dst["dept_no"] = &m.DeptNo
	dst["dept_name"] = &m.DeptName
}

type SliceDepartments []Departments

func (s *SliceDepartments) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, Departments{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.dept_emp
const TableDeptEmp = "dept_emp"

type DeptEmp struct {
	// emp_no : int
	EmpNo int
	// dept_no : char(4)
	DeptNo string
	// from_date : date
	FromDate interface{}
	// to_date : date
	ToDate interface{}
}

func (DeptEmp) TableName() string { return TableDeptEmp }

func (m *DeptEmp) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["dept_no"] = &m.DeptNo
	dst["from_date"] = &m.FromDate
	dst["to_date"] = &m.ToDate
}

type SliceDeptEmp []DeptEmp

func (s *SliceDeptEmp) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, DeptEmp{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.dept_emp_latest_date
// VIEW
const TableDeptEmpLatestDate = "dept_emp_latest_date"

type DeptEmpLatestDate struct {
	// emp_no : int
	EmpNo int
	// from_date : NULLABLE date
	FromDate interface{}
	// to_date : NULLABLE date
	ToDate interface{}
}

func (DeptEmpLatestDate) TableName() string { return TableDeptEmpLatestDate }

func (m *DeptEmpLatestDate) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["from_date"] = &m.FromDate
	dst["to_date"] = &m.ToDate
}

type SliceDeptEmpLatestDate []DeptEmpLatestDate

func (s *SliceDeptEmpLatestDate) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, DeptEmpLatestDate{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.dept_manager
const TableDeptManager = "dept_manager"

type DeptManager struct {
	// emp_no : int
	EmpNo int
	// dept_no : char(4)
	DeptNo string
	// from_date : date
	FromDate interface{}
	// to_date : date
	ToDate interface{}
}

func (DeptManager) TableName() string { return TableDeptManager }

func (m *DeptManager) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["dept_no"] = &m.DeptNo
	dst["from_date"] = &m.FromDate
	dst["to_date"] = &m.ToDate
}

type SliceDeptManager []DeptManager

func (s *SliceDeptManager) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, DeptManager{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.employees
const TableEmployees = "employees"

type Employees struct {
	// emp_no : int
	EmpNo int
	// birth_date : date
	BirthDate interface{}
	// first_name : varchar(14)
	FirstName string
	// last_name : varchar(16)
	LastName string
	// gender : enum('M','F')
	Gender string
}

func (Employees) TableName() string { return TableEmployees }

func (m *Employees) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["birth_date"] = &m.BirthDate
	dst["first_name"] = &m.FirstName
	dst["last_name"] = &m.LastName
	dst["gender"] = &m.Gender
}

type SliceEmployees []Employees

func (s *SliceEmployees) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, Employees{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.salaries
const TableSalaries = "salaries"

type Salaries struct {
	// emp_no : int
	EmpNo int
	// salary : int
	Salary int
	// from_date : date
	FromDate interface{}
	// to_date : date
	ToDate interface{}
}

func (Salaries) TableName() string { return TableSalaries }

func (m *Salaries) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["salary"] = &m.Salary
	dst["from_date"] = &m.FromDate
	dst["to_date"] = &m.ToDate
}

type SliceSalaries []Salaries

func (s *SliceSalaries) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, Salaries{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}

// employees.titles
const TableTitles = "titles"

type Titles struct {
	// emp_no : int
	EmpNo int
	// title : varchar(50)
	Title string
	// from_date : date
	FromDate interface{}
	// to_date : NULLABLE date
	ToDate interface{}
}

func (Titles) TableName() string { return TableTitles }

func (m *Titles) FieldMapping(dst map[string]interface{}) {
	dst["emp_no"] = &m.EmpNo
	dst["title"] = &m.Title
	dst["from_date"] = &m.FromDate
	dst["to_date"] = &m.ToDate
}

type SliceTitles []Titles

func (s *SliceTitles) Iterate(f func(interface{}, bool) bool) {
	for i := 0; ; i++ {
		if c := i >= len(*s); !c {
			if !f(&(*s)[i], c) {
				return
			}
		} else if n := append(*s, Titles{}); f(&n[i], c) {
			*s = n
		} else {
			*s = n[:i]
			return
		}
	}
}