Skip to content

Commit dcf1a6c

Browse files
authored
Support SELECT * in MySQL (#529)
* Add MySQL support for select star * Remove trailing semicolon
1 parent 8f46216 commit dcf1a6c

File tree

12 files changed

+262
-22
lines changed

12 files changed

+262
-22
lines changed

internal/compiler/go_type.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ func (r *Result) goInnerType(col *Column, settings config.CombinedSettings) stri
3333
}
3434
}
3535

36+
// TODO: Extend the engine interface to handle types
37+
switch settings.Package.Engine {
38+
case config.EngineMySQL, config.EngineXDolphin:
39+
return r.mysqlType(col, settings)
40+
case config.EnginePostgreSQL:
41+
return r.postgresType(col, settings)
42+
case config.EngineXLemon:
43+
return r.postgresType(col, settings)
44+
default:
45+
return "interface{}"
46+
}
47+
}
48+
49+
func (r *Result) postgresType(col *Column, settings config.CombinedSettings) string {
50+
columnType := col.DataType
51+
notNull := col.NotNull || col.IsArray
52+
3653
switch columnType {
3754
case "serial", "pg_catalog.serial4":
3855
if notNull {
@@ -186,3 +203,65 @@ func (r *Result) goInnerType(col *Column, settings config.CombinedSettings) stri
186203
return "interface{}"
187204
}
188205
}
206+
207+
func (r *Result) mysqlType(col *Column, settings config.CombinedSettings) string {
208+
columnType := col.DataType
209+
notNull := col.NotNull || col.IsArray
210+
211+
switch columnType {
212+
213+
case "varchar", "text", "char", "tinytext", "mediumtext", "longtext":
214+
if notNull {
215+
return "string"
216+
}
217+
return "sql.NullString"
218+
219+
case "int", "integer", "smallint", "mediumint", "year":
220+
if notNull {
221+
return "int32"
222+
}
223+
return "sql.NullInt32"
224+
225+
case "bigint":
226+
if notNull {
227+
return "int64"
228+
}
229+
return "sql.NullInt64"
230+
231+
case "blob", "binary", "varbinary", "tinyblob", "mediumblob", "longblob":
232+
return "[]byte"
233+
234+
case "double", "double precision", "real":
235+
if notNull {
236+
return "float64"
237+
}
238+
return "sql.NullFloat64"
239+
240+
case "decimal", "dec", "fixed":
241+
if notNull {
242+
return "string"
243+
}
244+
return "sql.NullString"
245+
246+
case "enum":
247+
// TODO: Proper Enum support
248+
return "string"
249+
250+
case "date", "timestamp", "datetime", "time":
251+
if notNull {
252+
return "time.Time"
253+
}
254+
return "sql.NullTime"
255+
256+
case "boolean", "bool", "tinyint":
257+
if notNull {
258+
return "bool"
259+
}
260+
return "sql.NullBool"
261+
262+
default:
263+
log.Printf("unknown MySQL type: %s\n", columnType)
264+
return "interface{}"
265+
266+
}
267+
}

internal/dolphin/convert.go

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ func convertCreateTableStmt(n *pcast.CreateTableStmt) ast.Node {
6262
IfNotExists: n.IfNotExists,
6363
}
6464
for _, def := range n.Cols {
65+
var vals *ast.List
66+
if len(def.Tp.Elems) > 0 {
67+
vals = &ast.List{}
68+
for i := range def.Tp.Elems {
69+
vals.Items = append(vals.Items, &ast.String{
70+
Str: def.Tp.Elems[i],
71+
})
72+
}
73+
}
6574
create.Cols = append(create.Cols, &ast.ColumnDef{
6675
Colname: def.Name.String(),
6776
TypeName: &ast.TypeName{Name: types.TypeStr(def.Tp.Tp)},
@@ -79,30 +88,64 @@ func convertDropTableStmt(n *pcast.DropTableStmt) ast.Node {
7988
return drop
8089
}
8190

82-
func convertSelectStmt(n *pcast.SelectStmt) ast.Node {
91+
func convertFieldList(n *pcast.FieldList) *ast.List {
92+
fields := make([]ast.Node, len(n.Fields))
93+
for i := range n.Fields {
94+
fields[i] = convertSelectField(n.Fields[i])
95+
}
96+
return &ast.List{Items: fields}
97+
}
98+
99+
func convertSelectField(n *pcast.SelectField) *pg.ResTarget {
100+
var val ast.Node
101+
if n.WildCard != nil {
102+
val = convertWildCardField(n.WildCard)
103+
} else {
104+
val = convert(n.Expr)
105+
}
106+
var name *string
107+
if n.AsName.O != "" {
108+
name = &n.AsName.O
109+
}
110+
return &pg.ResTarget{
111+
// TODO: Populate Indirection field
112+
Name: name,
113+
Val: val,
114+
Location: n.Offset,
115+
}
116+
}
117+
118+
func convertSelectStmt(n *pcast.SelectStmt) *pg.SelectStmt {
119+
return &pg.SelectStmt{
120+
TargetList: convertFieldList(n.Fields),
121+
FromClause: convertTableRefsClause(n.From),
122+
}
123+
}
124+
125+
func convertTableRefsClause(n *pcast.TableRefsClause) *ast.List {
83126
var tables []ast.Node
84-
visit(n.From, func(n pcast.Node) {
127+
visit(n, func(n pcast.Node) {
85128
name, ok := n.(*pcast.TableName)
86129
if !ok {
87130
return
88131
}
89-
tables = append(tables, parseTableName(name))
90-
})
91-
var cols []ast.Node
92-
visit(n.Fields, func(n pcast.Node) {
93-
col, ok := n.(*pcast.ColumnName)
94-
if !ok {
95-
return
96-
}
97-
cols = append(cols, &ast.ResTarget{
98-
Val: &ast.ColumnRef{
99-
Name: col.Name.String(),
100-
},
132+
schema := name.Schema.String()
133+
rel := name.Name.String()
134+
tables = append(tables, &pg.RangeVar{
135+
Schemaname: &schema,
136+
Relname: &rel,
101137
})
102138
})
103-
return &pg.SelectStmt{
104-
FromClause: &ast.List{Items: tables},
105-
TargetList: &ast.List{Items: cols},
139+
return &ast.List{Items: tables}
140+
}
141+
142+
func convertWildCardField(n *pcast.WildCardField) *pg.ColumnRef {
143+
return &pg.ColumnRef{
144+
Fields: &ast.List{
145+
Items: []ast.Node{
146+
&pg.A_Star{},
147+
},
148+
},
106149
}
107150
}
108151

internal/dolphin/parse.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) {
7373
Raw: &ast.RawStmt{
7474
Stmt: out,
7575
StmtLocation: loc,
76-
StmtLen: len(text),
76+
StmtLen: len(text) - 1, // Subtract one to remove semicolon
7777
},
7878
})
7979
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"experimental_parser_only": true
3+
}

internal/endtoend/testdata/dolphin_select_star/go/db.go

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/dolphin_select_star/go/models.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/dolphin_select_star/go/query.sql.go

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/* name: GetAll :many */
2+
SELECT * FROM users;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CREATE TABLE users (
2+
id integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
3+
first_name varchar(255) NOT NULL,
4+
last_name varchar(255),
5+
age integer NOT NULL
6+
) ENGINE=InnoDB;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"name": "querytest",
6+
"path": "go",
7+
"schema": "schema.sql",
8+
"queries": "query.sql",
9+
"engine": "_dolphin",
10+
"emit_json_tags": true
11+
}
12+
]
13+
}

0 commit comments

Comments
 (0)