-
Notifications
You must be signed in to change notification settings - Fork 318
/
Copy pathsqlite3.go
107 lines (101 loc) · 3.01 KB
/
sqlite3.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package loader
import (
"context"
"regexp"
"strings"
"github.com/xo/xo/models"
"github.com/xo/xo/templates/gotpl"
)
func init() {
Register(&Loader{
Driver: "sqlite3",
Kind: map[Kind]string{
KindTable: "table",
KindView: "view",
},
ParamN: func(int) string {
return "?"
},
MaskFunc: func() string {
return "?"
},
Schema: models.Sqlite3Schema,
GoType: Sqlite3GoType,
Tables: models.Sqlite3Tables,
TableColumns: models.Sqlite3TableColumns,
TableSequences: models.Sqlite3TableSequences,
TableForeignKeys: models.Sqlite3TableForeignKeys,
TableIndexes: models.Sqlite3TableIndexes,
IndexColumns: models.Sqlite3IndexColumns,
QueryColumns: Sqlite3QueryColumns,
})
}
// unsignedRE is the unsigned regexp.
var unsignedRE = regexp.MustCompile(`\s*unsigned\*`)
// Sqlite3GoType parse a sqlite3 type into a Go type based on the column
// definition.
func Sqlite3GoType(ctx context.Context, typ string, nullable bool) (string, string, int, error) {
// extract precision
typ, prec, _, err := parsePrec(typ)
if err != nil {
return "", "", 0, err
}
unsigned := false
if unsignedRE.MatchString(typ) {
unsigned = true
unsignedRE.ReplaceAllString(typ, "")
}
var goType, zero string
switch typ {
case "bool", "boolean":
goType, zero = "bool", "false"
if nullable {
goType, zero = "sql.NullBool", "sql.NullBool{}"
}
case "int", "integer", "tinyint", "smallint", "mediumint":
goType, zero = gotpl.Int32(ctx), "0"
if nullable {
goType, zero = "sql.NullInt64", "sql.NullInt64{}"
}
case "bigint":
goType, zero = "int64", "0"
if nullable {
goType, zero = "sql.NullInt64", "sql.NullInt64{}"
}
case "numeric", "real", "double", "float", "decimal":
goType, zero = "float64", "0.0"
if nullable {
goType, zero = "sql.NullFloat64", "sql.NullFloat64{}"
}
case "blob":
goType, zero = "[]byte", "nil"
case "timestamp", "datetime", "date", "timestamp with timezone", "time with timezone", "time without timezone", "timestamp without timezone":
goType, zero = "Time", "Time{}"
if nullable {
goType, zero = "*Time", "nil"
}
default:
// case "varchar", "character", "varying character", "nchar", "native character", "nvarchar", "text", "clob", "time":
goType, zero = "string", `""`
if nullable {
goType, zero = "sql.NullString", "sql.NullString{}"
}
}
// if unsigned ...
if intRE.MatchString(goType) && unsigned && goType == gotpl.Int32(ctx) {
goType, zero = gotpl.Uint32(ctx), "0"
}
return goType, zero, prec, nil
}
// Sqlite3QueryColumns parses a sqlite3 query and generates a type for it.
func Sqlite3QueryColumns(ctx context.Context, db models.DB, _ string, inspect []string) ([]*models.Column, error) {
// create temporary view xoid
xoid := "_xo_" + randomID()
viewq := `CREATE TEMPORARY VIEW ` + xoid + ` AS ` + strings.Join(inspect, "\n")
models.Logf(viewq)
if _, err := db.ExecContext(ctx, viewq); err != nil {
return nil, err
}
// load column information
return models.Sqlite3TableColumns(ctx, db, "", xoid)
}