Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ _testmain.go
*.exe
*.test
*.prof
.vscode/
db2struct
~/
93 changes: 7 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,88 +1,9 @@
# db2struct [![Build Status](https://travis-ci.org/Shelnutt2/db2struct.svg?branch=master)](https://travis-ci.org/Shelnutt2/db2struct) [![Coverage Status](https://coveralls.io/repos/github/Shelnutt2/db2struct/badge.svg?branch=1-add-coveralls-support)](https://coveralls.io/github/Shelnutt2/db2struct?branch=1-add-coveralls-support) [![GoDoc](https://godoc.org/github.com/Shelnutt2/db2struct?status.svg)](https://godoc.org/github.com/Shelnutt2/db2struct)
# 使用说明
# 调用命令 sh build.sh 编译
# 请设置环境变量(数据库密码) IMPORT_DB_PWD
# 修改配置,请修改run.sh 中的create参数等

The db2struct package produces a usable golang struct from a given database table for use in a .go file.
# create 表名 结构体名字

By reading details from the database about the column structure, db2struct generates a go compatible struct type
with the required column names, data types, and annotations.

Generated datatypes include support for nullable columns [sql.NullX types](https://golang.org/pkg/database/sql/#NullBool) or [guregu null.X types](https://github.com/guregu/null)
and the expected basic built in go types.

Db2Struct is based/inspired by the work of ChimeraCoder's gojson package
[gojson](https://github.com/ChimeraCoder/gojson)



## Usage

```BASH
go get github.com/Shelnutt2/db2struct/cmd/db2struct
db2struct --host localhost -d test -t test_table --package myGoPackage --struct testTable -p --user testUser
```

## Example

MySQL table named users with four columns: id (int), user_name (varchar(255)), number_of_logins (int(11),nullable), and LAST_NAME (varchar(255), nullable)

Example below uses guregu's null package, but without the option it procuded the sql.NullInt64 and so on.
```BASH
db2struct --host localhost -d example.com -t users --package example --struct user -p --user exampleUser --guregu --gorm
```

Output:
```GOLANG

package example

type User struct {
ID int `gorm:"column:id"`
UserName string `gorm:"column:user_name"`
NumberOfLogins null.Int `gorm:"column:number_of_logins"`
LastName null.String `gorm:"column:LAST_NAME"`
}
```

## Supported Databases

Currently Supported
- MariaDB
- MySQL

Planned Support
- PostgreSQL
- Oracle
- Microsoft SQL Server

### MariaDB/MySQL

Structures are created by querying the INFORMATION_SCHEMA.Columns table and then formatting the types, column names,
and metadata to create a usable go compatible struct type.

#### Supported Datatypes

Currently only a limited number of MariaDB/MySQL datatypes are supported. Initial support includes:
- tinyint (sql.NullInt64 or null.Int)
- int (sql.NullInt64 or null.Int)
- smallint (sql.NullInt64 or null.Int)
- mediumint (sql.NullInt64 or null.Int)
- bigint (sql.NullInt64 or null.Int)
- decimal (sql.NullFloat64 or null.Float)
- float (sql.NullFloat64 or null.Float)
- double (sql.NullFloat64 or null.Float)
- datetime (null.Time)
- time (null.Time)
- date (null.Time)
- timestamp (null.Time)
- var (sql.String or null.String)
- enum (sql.String or null.String)
- varchar (sql.String or null.String)
- longtext (sql.String or null.String)
- mediumtext (sql.String or null.String)
- text (sql.String or null.String)
- tinytext (sql.String or null.String)
- binary
- blob
- longblob
- mediumblob
- varbinary
- json
# 保存run.sh后执行命令:
# sh run.sh 生成model文件
29 changes: 29 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

#!/bin/bash -e

name="db2struct"
start_seconds=$(date +%s);

#export CGO_ENABLED="0"
export GO111MODULE=on
go build -o $name cmd/db2struct/main.go

if [ $? -ne 0 ];then
end_seconds=$(date +%s);
echo
echo "---> build time: "$((end_seconds-start_seconds))"s, build error!!!"
echo
exit 1
else
end_seconds=$(date +%s);
echo
ls -lt |grep $name
echo
echo "Build Success,took "$((end_seconds-start_seconds))"s"
echo
exit 0
fi




91 changes: 62 additions & 29 deletions cmd/db2struct/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"log"
"os"
"strconv"

Expand All @@ -21,6 +22,8 @@ var mariadbUser = goopt.String([]string{"-u", "--user"}, "user", "user to connec
var verbose = goopt.Flag([]string{"-v", "--verbose"}, []string{}, "Enable verbose output", "")
var packageName = goopt.String([]string{"--package"}, "", "name to set for package")
var structName = goopt.String([]string{"--struct"}, "", "name to set for struct")
var projectName = goopt.String([]string{"--project"}, "", "name to set projectName")
var tableNote = goopt.String([]string{"--note"}, "", "table note 表-中文名")

var jsonAnnotation = goopt.Flag([]string{"--json"}, []string{"--no-json"}, "Add json annotations (default)", "Disable json annotations")
var gormAnnotation = goopt.Flag([]string{"--gorm"}, []string{}, "Add gorm annotations (tags)", "")
Expand All @@ -45,6 +48,8 @@ func init() {

func main() {

log.SetFlags(log.Lshortfile | log.LstdFlags)

// Username is required
if mariadbUser == nil || *mariadbUser == "user" {
fmt.Println("Username is required! Add it with --user=name")
Expand All @@ -62,7 +67,7 @@ func main() {
stringPass := string(pass)
mariadbPassword = &stringPass
if err != nil {
fmt.Println("Error reading password: " + err.Error())
log.Println("Error reading password: " + err.Error())
return
}
} else if mariadbPassword == nil {
Expand All @@ -71,23 +76,16 @@ func main() {
}

if *verbose {
fmt.Println("Connecting to mysql server " + mariadbHost + ":" + strconv.Itoa(*mariadbPort))
log.Println("Connecting to mysql server " + mariadbHost + ":" + strconv.Itoa(*mariadbPort))
}

if mariadbDatabase == nil || *mariadbDatabase == "" {
fmt.Println("Database can not be null")
log.Println("Database can not be null")
return
}

if mariadbTable == nil || *mariadbTable == "" {
fmt.Println("Table can not be null")
return
}

columnDataTypes, err := db2struct.GetColumnsFromMysqlTable(*mariadbUser, *mariadbPassword, mariadbHost, *mariadbPort, *mariadbDatabase, *mariadbTable)

if err != nil {
fmt.Println("Error in selecting column data information from mysql information schema")
log.Println("Table can not be null")
return
}

Expand All @@ -99,32 +97,67 @@ func main() {
if packageName == nil || *packageName == "" {
*packageName = "newpackage"
}

dp := db2struct.DBParam{
MariadbUser: *mariadbUser,
MariadbPassword: *mariadbPassword,
MariadbHost: mariadbHost,
MariadbPort: *mariadbPort,
MariadbDatabase: *mariadbDatabase,
MariadbTable: *mariadbTable,
}

tp := db2struct.TableParam{
TableName: *mariadbTable,
StructName: *structName,
PkgName: *packageName,
JsonAnnotation: *jsonAnnotation,
GormAnnotation: *gormAnnotation,
GureguTypes: *gureguTypes,
TableNote: *tableNote,
ProjectName: *projectName,
}

StartCreate(&tp, &dp)

}

func getMariadbPassword(password string) error {
mariadbPassword = new(string)
*mariadbPassword = password
return nil
}

func StartCreate(tp *db2struct.TableParam, dp *db2struct.DBParam) error {

columnDataTypes, err := db2struct.GetColumnsFromMysqlTable(dp)
if err != nil {
log.Println("Error in selecting column data information from mysql information schema")
return err
}

// Generate struct string based on columnDataTypes
struc, err := db2struct.Generate(*columnDataTypes, *mariadbTable, *structName, *packageName, *jsonAnnotation, *gormAnnotation, *gureguTypes)
struc, err := db2struct.Generate(*columnDataTypes, tp)

if err != nil {
fmt.Println("Error in creating struct from json: " + err.Error())
return
log.Println("Error in creating struct from json: " + err.Error())
return err
}
var saveFile string
if targetFile != nil && *targetFile != "" {
file, err := os.OpenFile(*targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
saveFile = *targetFile + "/model/" + tp.TableName + ".go"
length, err := db2struct.AutoSaveFile(saveFile, string(struc))
if err != nil {
fmt.Println("Open File fail: " + err.Error())
return
}
length, err := file.WriteString(string(struc))
if err != nil {
fmt.Println("Save File fail: " + err.Error())
return
log.Println("open err: ", err)
return err
}
fmt.Printf("wrote %d bytes\n", length)
} else {
fmt.Println(string(struc))
log.Printf("wrote %d bytes\n", length)
}
}
fmt.Println(string(struc))
fmt.Println("")
fmt.Println("======================================")
fmt.Println("save model file to ", saveFile)
fmt.Println("")

func getMariadbPassword(password string) error {
mariadbPassword = new(string)
*mariadbPassword = password
return nil
}
17 changes: 12 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
module github.com/Shelnutt2/db2struct
module hktk1001/db2struct
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert the mod files (go.mod and go.sum), the changes here look like they are only from your fork?


go 1.12
go 1.15

require (
github.com/Shelnutt2/db2struct v1.0.1
github.com/droundy/goopt v0.0.0-20170604162106-0b8effe182da
github.com/go-sql-driver/mysql v1.4.1
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
github.com/gin-gonic/gin v1.6.3
github.com/go-sql-driver/mysql v1.5.0
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c
github.com/jinzhu/gorm v1.9.16
github.com/prometheus/common v0.19.0
github.com/smartystreets/goconvey v1.6.4
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect
)

replace github.com/Shelnutt2/db2struct => ../db2struct
Loading