{"id":34171283,"url":"https://github.com/huangjunwen/sqlw-mysql","last_synced_at":"2026-03-11T02:03:36.515Z","repository":{"id":57496033,"uuid":"135366771","full_name":"huangjunwen/sqlw-mysql","owner":"huangjunwen","description":"Wrapper code (or any text source) generator for MySQL databases and queries","archived":false,"fork":false,"pushed_at":"2023-01-17T23:55:33.000Z","size":373,"stargazers_count":49,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-14T03:34:07.719Z","etag":null,"topics":["code-generator","golang","graphviz","mysql","orm","sql"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/huangjunwen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-30T00:26:29.000Z","updated_at":"2025-07-26T22:06:37.000Z","dependencies_parsed_at":"2022-08-28T20:20:26.657Z","dependency_job_id":null,"html_url":"https://github.com/huangjunwen/sqlw-mysql","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/huangjunwen/sqlw-mysql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huangjunwen%2Fsqlw-mysql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huangjunwen%2Fsqlw-mysql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huangjunwen%2Fsqlw-mysql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huangjunwen%2Fsqlw-mysql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/huangjunwen","download_url":"https://codeload.github.com/huangjunwen/sqlw-mysql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huangjunwen%2Fsqlw-mysql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30367810,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-generator","golang","graphviz","mysql","orm","sql"],"created_at":"2025-12-15T11:14:43.653Z","updated_at":"2026-03-11T02:03:36.507Z","avatar_url":"https://github.com/huangjunwen.png","language":"Go","readme":"# SQL wrapper code generator for MySQL \n\n[![Go Report Card](https://goreportcard.com/badge/github.com/huangjunwen/sqlw-mysql)](https://goreportcard.com/report/github.com/huangjunwen/sqlw-mysql) \n[![Build Status](https://travis-ci.org/huangjunwen/sqlw-mysql.svg?branch=master)](https://travis-ci.org/huangjunwen/sqlw-mysql) \n[![codecov](https://codecov.io/gh/huangjunwen/sqlw-mysql/branch/master/graph/badge.svg)](https://codecov.io/gh/huangjunwen/sqlw-mysql)\n\n`sqlw-mysql` is a CLI tool to generate go wrapper code (or any text source) for your MySQL database and queries.\n\n## Table of Contents\n\n- [Install](#install)\n- [Design/Goals/Features](#designgoalsfeatures)\n- [Motivation](#motivation)\n- [Quickstart](#quickstart)\n- [Statement XML](#statement-xml)\n  - [Directives](#directives)\n    - [Arg directive](#arg-directive)\n    - [Vars directive](#vars-directive)\n    - [Replace directive](#replace-directive)\n    - [Bind directive](#bind-directive)\n    - [Text directive](#text-directive)\n    - [Wildcard directive](#wildcard-directive)\n      - [How wildcard directive works](#how-wildcard-directive-works)\n- [Template](#template)\n  - [Default template](#default-template)\n  - [Graphviz template](#graphviz-template)\n- [Command line options](#command-line-options)\n- [Licence](#licence)\n\n## Install\n\n``` bash\n$ GO111MODULE=on go get -u github.com/huangjunwen/sqlw-mysql\n```\n\n## Design/Goals/Features\n\n- Not an `ORM`, but provide similar features.\n- Database first, `sqlw-mysql` generate wrapper code for your database tables.\n- Use XML as DSL to describe query statements, `sqlw-mysql` generate wrapper code for them.\n- Should be work for all kinds of queries, from simple ones to complex ones.\n- Highly customizable template. Can be used to generate wrapper code but also any text source.\n- Extensible DSL (through directives).\n\n## Motivation\n\nSee my blog post for this project (in Chinese): [写了一个 MySQL 数据表和查询的 go 代码生成器](https://huangjunwen.github.io/posts/2018/sqlw-mysql/)\n\n## Quickstart\n\nLet's start with a small example. (See [here](https://github.com/huangjunwen/sqlw-mysql/tree/master/examples/quickstart) for complete source code)\n\nSuppose you have a database with two tables: `user` and `employee`; An `employee` must be a `user`, but a `user` need not to be an `employee`; Each `employee` must have a superior except those top dogs.\n\n``` sql\nCREATE TABLE `user` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `name` varchar(64) NOT NULL,\n  `female` tinyint(1) DEFAULT NULL,\n  `birthday` datetime DEFAULT NULL,\n  PRIMARY KEY (`id`)\n);\n\nCREATE TABLE `employee` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `employee_sn` char(32) NOT NULL,\n  `user_id` int(11) NOT NULL,\n  `superior_id` int(11) DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `employee_sn` (`employee_sn`),\n  UNIQUE KEY `user_id` (`user_id`),\n  KEY `superior_id` (`superior_id`),\n  CONSTRAINT `fk_superior` FOREIGN KEY (`superior_id`) REFERENCES `employee` (`id`),\n  CONSTRAINT `fk_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)\n);\n```\n\n\nNow run `sqlw-mysql`. You will see a `models` directory is created with several source files generated:\n\n``` bash\n$ sqlw-mysql -dsn \"user:passwd@tcp(host:port)/db?parseTime=true\"\n$ ls ./models\n... table_user.go ... table_employee.go\n\n```\n\nEspecially, a `table_\u003ctable name\u003e.go` is generated for each table containing structs/methods for some common single table operations:\n\n``` go\n// ./models/table_user.go\n\n// User represents a row of table `user`.\ntype User struct {\n  Id       int32     `json:\"id\" db:\"id\"`\n  Name     string    `json:\"name\" db:\"name\"`\n  Female   null.Bool `json:\"female\" db:\"female\"`\n  Birthday null.Time `json:\"birthday\" db:\"birthday\"`\n}\n\nfunc (tr *User) Insert(ctx context.Context, e Execer) error {\n  // ...\n}\n\nfunc (tr *User) Reload(ctx context.Context, q Queryer) error {\n  // ...\n}\n```\n\nBut eventually, you will need more complex quries. For example if you want to query all `user` and its associated `employee` (e.g. `one2one` relationship), then you can write a statement XML like this:\n\n``` xml\n\u003c!-- ./stmts/user.xml --\u003e\n\n\u003cstmt name=\"AllUserEmployees\"\u003e\n  SELECT\n    \u003cwc table=\"user\" /\u003e,\n    CAST(DATEDIFF(NOW(), birthday)/365 AS UNSIGNED) AS age,\n    \u003cwc table=\"employee\" as=\"empl\" /\u003e\n  FROM\n    user LEFT JOIN employee AS empl ON user.id=empl.user_id\n\u003c/stmt\u003e\n```\n\nA statement XML contains SQL statement with special directives embeded in. Here you can see two `\u003cwc table=\"table_name\"\u003e` directives, which are roughly equal to expanded `table_name.*`. \n\n_See [Statement XML](#statement_xml) for detail._\n\nNow run `sqlw-mysql` again with the statement XML directory:\n\n``` bash\n$ sqlw-mysql -dsn \"user:passwd@tcp(host:port)/db?parseTime=true\" -stmt ./stmts\n$ ls ./models\n... table_user.go ... table_employee.go ... stmt_user.go\n\n```\n\nA new file `stmt_user.go` is generated from `user.xml`:\n\n``` go\n// ./models/stmt_user.go\n\n// AllUserEmployeesResult is the result of AllUserEmployees.\ntype AllUserEmployeesResult struct {\n  User       *User\n  Age        null.Uint64\n  Empl       *Employee\n  nxNullUser nxNullUser\n  nxNullEmpl nxNullEmployee\n}\n\n// AllUserEmployeesResultSlice is slice of AllUserEmployeesResult.\ntype AllUserEmployeesResultSlice []*AllUserEmployeesResult\n\n// ...\nfunc AllUserEmployees(ctx context.Context, q Queryer) (AllUserEmployeesResultSlice, error) {\n  // ...\n}\n\n```\n\nNotice that `User` and `Empl` fields in result struct are generated from those `\u003cwc\u003e` directives. `sqlw-mysql` is smart enough to figure out their correct positions. _See [here](#how-wildcard-directive-works) for detail._\n\nNow you can use the newly created function to iterate through all `user` and `employee`:\n\n``` go\nslice, err := models.AllUserEmployees(ctx, tx)\nif err != nil {\n  log.Fatal(err)\n}\n\nfor _, result := range slice {\n  user := result.User\n  empl := result.Empl\n\n  if empl.Valid() {\n    log.Printf(\"User %+q (age %d) is an employee, sn: %+q\\n\", user.Name, result.Age.Uint64, empl.EmployeeSn)\n  } else {\n    log.Printf(\"User %+q (age %d) is not an employee\\n\", user.Name, result.Age.Uint64)\n  }\n}\n```\n\nAnother example, if you want to find subordinates of some employees (e.g. `one2many` relationship):\n\n``` xml\n\u003c!-- ./stmts/user.xml --\u003e\n\n\u003cstmt name=\"SubordinatesBySuperiors\"\u003e\n  \u003ca name=\"id\" type=\"...int\" /\u003e\n  \u003cv in_query=\"1\" /\u003e\n  SELECT\n    \u003cwc table=\"employee\" as=\"superior\" /\u003e,\n    \u003cwc table=\"employee\" as=\"subordinate\" /\u003e\n  FROM\n    employee AS superior LEFT JOIN employee AS subordinate ON subordinate.superior_id=superior.id\n  WHERE\n    superior.id IN (\u003cb name=\"id\"/\u003e)\n\u003c/stmt\u003e\n```\n\nBrief explanation about new directives:\n- `\u003ca\u003e` specifies an argument of the generated function.\n- `\u003cv\u003e` specifies arbitary variables that the template can use. `in_query=\"1\"` tells the template that the SQL use `IN` operator.\n- `\u003cb\u003e` argument binding.\n\n_See [Directives](#directives) for detail._\n\nAfter re-running the command, the following code is generated:\n\n``` go\n// ./models/stmt_user.go\n\n// SubordinatesBySuperiorsResult is the result of SubordinatesBySuperiors.\ntype SubordinatesBySuperiorsResult struct {\n  Superior          *Employee\n  Subordinate       *Employee\n  nxNullSuperior    nxNullEmployee\n  nxNullSubordinate nxNullEmployee\n}\n\n// SubordinatesBySuperiorsResultSlice is slice of SubordinatesBySuperiorsResult.\ntype SubordinatesBySuperiorsResultSlice []*SubordinatesBySuperiorsResult\n\n// ...\nfunc SubordinatesBySuperiors(ctx context.Context, q Queryer, id ...int) (SubordinatesBySuperiorsResultSlice, error) {\n  // ...\n}\n```\n\nThen, you can iterate the result like:\n\n``` go\nslice, err := models.SubordinatesBySuperiors(ctx, tx, 1, 2, 3, 4, 5, 6, 7)\nif err != nil {\n  log.Fatal(err)\n}\n\nsuperiors, groups := slice.GroupBySuperior()\nfor i, superior := range superiors {\n  subordinates := groups[i].DistinctSubordinate()\n\n  if len(subordinates) == 0 {\n    log.Printf(\"Employee %+q has no subordinate.\\n\", superior.EmployeeSn)\n  } else {\n    log.Printf(\"Employee %+q has the following subordinates:\\n\", superior.EmployeeSn)\n    for _, subordinate := range subordinates {\n      log.Printf(\"\\t%+q\\n\", subordinate.EmployeeSn)\n    }\n  }\n}\n```\n\nIn fact, `sqlw-mysql` doesn't care about what kind of relationships between result fields. It just generate helper methods such as `GroupByXXX`/`DistinctXXX` for these fields, thus it works for all kinds of relationships.\n\n\n## Statement XML\n\n`sqlw-mysql` use XML as DSL to describe quries, since XML is suitable for mixed content: raw SQL query and special directives. \n\nThe simplest one is a `\u003cstmt\u003e` element with `name` attribute, without any directive, like this:\n\n``` xml\n\u003cstmt name=\"One\"\u003e\n  SELECT 1\n\u003c/stmt\u003e\n```\n\nBut this is not very useful, sometimes we want to add meta data to it, sometimes we want to reduce verbosity ...\n\nThat's why we need directives:\n\n### Directives\n\nDirective represents a fragment of SQL query, usually declared by an XML element. `sqlw-mysql` processes directives in several passes:\n\n- The first pass all directives should generate fragments that form a valid SQL statement (e.g. `SELECT * FROM user WHERE id=1`). This SQL statement is then used to determine statement type, to obtain result column information by querying the database if it's a SELECT. \n- The second pass all directives should generate fragments that form a text statement for template renderring (e.g. `SELECT * FROM user WHERE id=:id`). It's no need to be a valid SQL statement, it's up to the template to decide how to use this text.\n- Some directives may run extra pass.\n\nThe following are a list of current builtin directives. In future new directives may be added. And should be easy enough to implement one: impelemnts a go interface.\n\n#### Arg directive\n\n- Name: `\u003carg\u003e`/`\u003ca\u003e`\n- Example: `\u003ca name=\"id\" type=\"int\" /\u003e`\n- First pass result: `\"\"`\n- Second pass result: `\"\"`\n\nDeclare a wrapper function argument's name and type. Always returns empty string.\n\n#### Vars directive\n\n- Name: `\u003cvars\u003e`/`\u003cv\u003e`\n- Example: `\u003cv flag1=\"true\" flag2=\"true\" /\u003e`\n- First pass result: `\"\"`\n- Second pass result: `\"\"`\n\nDeclare arbitary key/value pairs (XML attributes) for template to use. Always returns empty string.\n\n#### Replace directive\n\n- Name: `\u003crepl\u003e`/`\u003cr\u003e`\n- Example: `\u003cr by=\":id\"\u003e1\u003c/r\u003e`\n- First pass result: `\"1\"`\n- Second pass result: `\":id\"`\n\nReturns the inner text for the first pass and returns the value in `by` attribute for the second pass.\n\n### Bind directive\n\n- Name: `\u003cbind\u003e`/`\u003cb\u003e`\n- Example: `\u003cb name=\"id\" /\u003e` or `\u003cb name=\"limit\"\u003e10\u003c/b\u003e`\n- First pass result: `\"NULL\"` or inner text of `\u003cb\u003e` element.\n- Second pass result: `\":id\"`\n\n`\u003cb name=\"xxx\" /\u003e` is equivalent to `\u003cr by=\":xxx\"\u003eNULL\u003c/r\u003e` and `\u003cb name=\"xxx\"\u003eval\u003c/b\u003e` is equivalent to `\u003cr by=\":xxx\"\u003eval\u003c/r\u003e`. And the bind name must be an argument name.\n\nNOTE: `NULL` is not allowed in some clause in MySQL. For example: \n\n```sql\nSELECT * FROM user LIMIT NULL  -- Invalid\n```\n\nThus if you want to bind an argument in the `LIMIT` clause, you have to write a number explicitly:\n\n```sql\nLIMIT \u003cb name=\"limit\"\u003e1\u003c/b\u003e\n```\n\n#### Text directive\n\n- Name: `\u003ctext\u003e`/`\u003ct\u003e`\n- Example: `\u003ct\u003e{{ if ne .id 0 }}\u003c/t\u003e`\n- First pass result: `\"\"`\n- Second pass result: `\"{{ if ne .id 0 }}\"`\n\n`\u003ct\u003einnerText\u003c/t\u003e` is equivalent to `\u003cr by=\"innerText\"\u003e\u003c/r\u003e`.\n\n#### Wildcard directive\n\n- Name: `\u003cwc\u003e`\n- Example: `\u003cwc table=\"employee\" as=\"empl\" /\u003e`\n- First pass result: ```\"`empl`.`id`, ..., `empl`.`superior_id`\"```\n- Second pass result: ```\"`empl`.`id`, ..., `empl`.`superior_id`\"```\n\nReturns the expanded column list of the table. It runs an extra pass to determine fields positions, see [here](#how-wildcard-directive-works) for detail.\n\n##### How wildcard directive works\n\n`\u003cwc\u003e` (wildcard) directive serves several purposes:\n\n- Reduce verbosity, also it's a 'safer' version of `table.*` (It expands all columns of the table).\n- Figure out the positions of these expanded columns so that template can make use of.\n\nIn the extra pass of `\u003cwc\u003e` directives, special marker columns are added before and after each `\u003cwc\u003e` directive, for example:\n\n``` xml\n  SELECT NOW(), \u003cwc table=\"user\" /\u003e, NOW() FROM user\n```\n\nwill be expanded to something like:\n\n```\n  SELECT NOW(), 1 AS wc456958346a616564_0_s, `user`.`id`, ..., `user`.`birthday`, 1 AS wc456958346a616564_0_e, NOW() FROM user\n```\n\nBy finding these marker column name in the result columns, `sqlw-mysql` can determine their positions.\n\nThis even works for subquery:\n\n``` xml\n  SELECT * FROM (SELECT \u003cwc table=\"user\" /\u003e FROM user) AS u\n```\n\nAnd if you only selects a single column (or a few columns) like:\n\n``` xml\n  SELECT birthday FROM (SELECT \u003cwc table=\"user\" /\u003e FROM user) AS u\n```\n\nThen the wildcard directive is ignored since you're not selecting all columns of the table.\n\n## Template\n\n`sqlw-mysql` itself only provides information extracted from database/DSL. Most features are in fact implemented in template. A template is a directory looks like:\n\n``` bash\n$ tree default\ndefault\n├── interface.go.tmpl\n├── manifest.json\n├── meta.go.tmpl\n├── meta_test.go.tmpl\n├── scan_type_map.json\n├── stmt_{{.StmtXMLName}}.go.tmpl\n├── table_{{.Table.TableName}}.go.tmpl\n└── util.go.tmpl\n```\n\nA `manifest.json` contains lists of templates to render and other customizable information:\n\n``` json\n{\n  \"scanTypeMap\": \"scan_type_map.json\",\n  \"perRun\": [\n    \"interface.go.tmpl\",\n    \"meta.go.tmpl\",\n    \"util.go.tmpl\",\n    \"meta_test.go.tmpl\"\n  ],\n  \"perTable\": [\n    \"table_{{.Table.TableName}}.go.tmpl\"\n  ],\n  \"perStmtXML\": [\n    \"stmt_{{.StmtXMLName}}.go.tmpl\"\n  ]\n}\n```\n\n`manifest[\"scanTypeMap\"]` is used to map database type (key) to go scan type (value, `value[0]` is for *NOT* nullable type and `value[1]` is for nullable type):\n\n``` json\n{\n  \"bool\":      [\"bool\", \"null.Bool\"],\n  \"int8\":      [\"int8\", \"null.Int8\"],\n  \"uint8\":     [\"uint8\", \"null.Uint8\"],\n  \"int16\":     [\"int16\", \"null.Int16\"],\n  \"uint16\":    [\"uint16\", \"null.Uint16\"],\n  \"int32\":     [\"int32\", \"null.Int32\"],\n  \"uint32\":    [\"uint32\", \"null.Uint32\"],\n  \"int64\":     [\"int64\", \"null.Int64\"],\n  \"uint64\":    [\"uint64\", \"null.Uint64\"],\n  \"float32\":   [\"float32\", \"null.Float32\"],\n  \"float64\":   [\"float64\", \"null.Float64\"],\n  \"time\":      [\"time.Time\", \"null.Time\"],\n  \"decimal\":   [\"string\", \"null.String\"],\n  \"bit\":       [\"string\", \"null.String\"],\n  \"json\":      [\"string\", \"null.String\"],\n  \"string\":    [\"string\", \"null.String\"]\n}\n```\n\n`manifest[\"perRun\"]` list templates to render once per run. `manifest[\"perTable\"]` list templates to render once per database table. `manifest[\"perStmtXML\"]` list templates to render once per statement xml file. \n\n`sqlw-mysql` templates can use functions provided by [sprig](https://github.com/Masterminds/sprig/), checkout [func.go](https://github.com/huangjunwen/sqlw-mysql/blob/master/render/func.go) to see the full list of supported functions.\n\n\n### Default template\n\nIf no custom template specified, or `-tmpl @default` is given, then the default template is used.\n\nGenreated code depends on these external libraries:\n- [sqlx](https://github.com/jmoiron/sqlx).\n- [sqlboiler](https://github.com/volatiletech/sqlboiler)'s [null-extended](https://github.com/volatiletech/null) package.\n\nFor statement XML, the default template accept these `\u003cvars\u003e`:\n\n| Name | Example | Note |\n|------|---------|------|\n| `use_template` | `use_template=\"1\"` | If presented, then the statement text is treated as a go [template](https://godoc.org/text/template) |\n| `in_query` | `in_query=\"1\"` | If presented, then statement will do an \"IN\" expansion, see http://jmoiron.github.io/sqlx/#inQueries |\n| `return` | `return=\"one\"` | For SELECT statement only, by default the generated function returns a slice, if `return=\"one\"`, then returns a single item instead |\n\nAn example of `use_template`:\n\n``` xml\n\u003cstmt name=\"UsersByCond\"\u003e\n  \u003cv use_template=\"1\" /\u003e\n  \u003ca name=\"id\" type=\"int\" /\u003e\n  \u003ca name=\"name\" type=\"string\" /\u003e\n  \u003ca name=\"birthday\" type=\"time.Time\" /\u003e\n  \u003ca name=\"limit\" type=\"int\" /\u003e\n  SELECT\n    \u003cwc table=\"user\" /\u003e\n  FROM\n    user\n  WHERE\n    \u003ct\u003e{{ if ne .id 0 }}\u003c/t\u003e\n      id=\u003cb name=\"id\"/\u003e AND\n    \u003ct\u003e{{ end }}\u003c/t\u003e\n\n    \u003ct\u003e{{ if ne (len .name) 0 }}\u003c/t\u003e\n      name=\u003cb name=\"name\"/\u003e AND\n    \u003ct\u003e{{ end }}\u003c/t\u003e\n\n    \u003ct\u003e{{ if not .birthday.IsZero }}\u003c/t\u003e\n      birthday=\u003cb name=\"birthday\"/\u003e AND\n    \u003ct\u003e{{ end }}\u003c/t\u003e\n    1\n  LIMIT \u003cb name=\"limit\"\u003e10\u003c/b\u003e\n\u003c/stmt\u003e\n```\n\nThen the generated statement will be treated as a go template and will be renderred before normal execution. This is useful when you have many `WHERE` condtions combination.\n\nIf enviroment `\"CAMEL_JSON_KEY\"` is given, than json tags of structs generated will be use lower camel case such as `\"createdAt\"`.\n\n### Graphviz template\n\n`sqlw-mysql` can be used to generate other text source as well. For example running with `-tmpl @graphviz` a `.dot` file will be generated containing tables and their relationships, which can be convert to a diagram like this:\n\n![db.png](https://raw.githubusercontent.com/huangjunwen/sqlw-mysql/master/examples/quick-start/db.png)\n\n## Command line options\n\n``` bash\n$ sqlw-mysql -h\nUsage of sqlw-mysql:\n  -blacklist value\n    \t(Optional) Comma separated table names not to render.\n  -dsn string\n    \t(Required) Data source name. e.g. \"user:passwd@tcp(host:port)/db?parseTime=true\"\n  -out string\n    \t(Optional) Output directory for generated code. (default \"models\")\n  -pkg string\n    \t(Optional) Alternative package name of the generated code.\n  -stmt string\n    \t(Optional) Statement xmls directory.\n  -tmpl string\n    \t(Optional) Custom templates directory. Or use '@name' to use the named builtin template.\n  -whitelist value\n    \t(Optional) Comma separated table names to render.\n```\n\n\n\n## Licence\n\nMIT\n\nAuthor: huangjunwen (kassarar@gmail.com)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuangjunwen%2Fsqlw-mysql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhuangjunwen%2Fsqlw-mysql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuangjunwen%2Fsqlw-mysql/lists"}