# Orm

Connects schemadriver with dsn, loads schema info for generating ORM struct and codes.

# Usage

# Annotation

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

# Exact Arguments

# schema

Specify database schema to loads.

  • Use , to separate multi value.

Example: +zz:orm:my_database,my_database2

# Optional Arguments

# filename

Generate target filepath, default: ./zzgen.orm.go.

Example: +zz:orm:schema:filename=./models/

# driver

Specify schemadriver.

This driver is not sql.Driver, but it is the interface for plugin loading different kind of database schema. External extension interface could be loaded from .so.

default: mysql.

Example: +zz:orm:schema:driver=sqlite

# type

Specify type mapping from database type to golang type, format as: ${database DATA_TYPE}=${Golang type}

Example: +zz:orm:schema:type=varchar=MyString

  • Use , to join multi types.

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

The priority of type matching would be controlled by schemadriver implement.

  • Use * to specify Nullable type.

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

# table

Specify database tables to generates from, default: * for all tables.

  • Use , to join multi tables.

Example: +zz:orm:schema:table=user,car,order

# password

Generally, developer would use orm to generate code in local develop environment, And database in this case mostly were installed and exported as default connection.

So schemadriver should provide a default dsn template for default database connection.

For example: mysql use root:${pwd}@tcp(localhost:3306)/.

Users could provide password only and complete all configuration to access the schema source database.

We suggest to use this plugin as example:

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

# dsn

You could also provide full dsn url to access.

If you have letter : in argument, you should use \ to argument escape.

Example:

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

# Examples

Example Project (opens new window) Example SQL (opens new window)

package orm01

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

Execute gozz run -p "orm:password=***" ./, and it generates file zzgen.orm.go and template file.

// 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
		}
	}
}
Last Updated: 10/27/2023, 12:58:51 PM