diff --git a/db/db.go b/db/db.go index 92d0e70f..c50453a5 100644 --- a/db/db.go +++ b/db/db.go @@ -18,6 +18,7 @@ import ( // Driver is the common interface for database driver type Driver interface { Analyze(*sql.DB, *schema.Schema) error + Info(*sql.DB) (*schema.Driver, error) } // Analyze database @@ -59,6 +60,11 @@ func Analyze(urlstr string) (*schema.Schema, error) { default: return s, errors.WithStack(fmt.Errorf("unsupported driver '%s'", u.Driver)) } + d, err := driver.Info(db) + if err != nil { + return s, err + } + s.Driver = d err = driver.Analyze(db, s) if err != nil { return s, err diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index d76d016f..99c4951a 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -325,6 +325,19 @@ WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position`, s.Name, ta return nil } +// Info return schema.Driver +func (m *Mysql) Info(db *sql.DB) (*schema.Driver, error) { + var v string + row := db.QueryRow(`SELECT version();`) + row.Scan(&v) + + d := &schema.Driver{ + Name: "mysql", + DatabaseVersion: v, + } + return d, nil +} + func convertColumnNullable(str string) bool { if str == "NO" { return false diff --git a/drivers/mysql/mysql_test.go b/drivers/mysql/mysql_test.go index 9b0a44bd..00255c04 100644 --- a/drivers/mysql/mysql_test.go +++ b/drivers/mysql/mysql_test.go @@ -37,3 +37,17 @@ func TestAnalyzeView(t *testing.T) { t.Errorf("actual not empty string.") } } + +func TestInfo(t *testing.T) { + driver := new(Mysql) + d, err := driver.Info(db) + if err != nil { + t.Errorf("%v", err) + } + if d.Name != "mysql" { + t.Errorf("actual %v\nwant %v", d.Name, "mysql") + } + if d.DatabaseVersion == "" { + t.Errorf("actual not empty string.") + } +} diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index 88dee5af..d60f8169 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -325,6 +325,19 @@ ORDER BY ordinal_position return nil } +// Info return schema.Driver +func (p *Postgres) Info(db *sql.DB) (*schema.Driver, error) { + var v string + row := db.QueryRow(`SELECT version();`) + row.Scan(&v) + + d := &schema.Driver{ + Name: "postgres", + DatabaseVersion: v, + } + return d, nil +} + func convertColmunType(t string, udtName string, characterMaximumLength sql.NullInt64) string { switch t { case "USER-DEFINED": diff --git a/drivers/postgres/postgres_test.go b/drivers/postgres/postgres_test.go index f2bf2413..98a48d7a 100644 --- a/drivers/postgres/postgres_test.go +++ b/drivers/postgres/postgres_test.go @@ -37,3 +37,17 @@ func TestAnalyzeView(t *testing.T) { t.Errorf("actual not empty string.") } } + +func TestInfo(t *testing.T) { + driver := new(Postgres) + d, err := driver.Info(db) + if err != nil { + t.Errorf("%v", err) + } + if d.Name != "postgres" { + t.Errorf("actual %v\nwant %v", d.Name, "postgres") + } + if d.DatabaseVersion == "" { + t.Errorf("actual not empty string.") + } +} diff --git a/drivers/sqlite/sqlite.go b/drivers/sqlite/sqlite.go index a881926b..664f2fbc 100644 --- a/drivers/sqlite/sqlite.go +++ b/drivers/sqlite/sqlite.go @@ -6,9 +6,10 @@ import ( "sort" "strings" + "regexp" + "github.com/k1LoW/tbls/schema" "github.com/pkg/errors" - "regexp" ) var reFK = regexp.MustCompile(`FOREIGN KEY \((.+)\) REFERENCES ([^\s]+)\s?\((.+)\)`) @@ -359,6 +360,19 @@ SELECT name, sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = ?; return nil } +// Info return schema.Driver +func (l *Sqlite) Info(db *sql.DB) (*schema.Driver, error) { + var v string + row := db.QueryRow(`SELECT sqlite_version();`) + row.Scan(&v) + + d := &schema.Driver{ + Name: "sqlite", + DatabaseVersion: v, + } + return d, nil +} + func convertColumnNullable(str string) bool { if str == "1" { return false diff --git a/drivers/sqlite/sqlite_test.go b/drivers/sqlite/sqlite_test.go index 1fa59ef7..e5409818 100644 --- a/drivers/sqlite/sqlite_test.go +++ b/drivers/sqlite/sqlite_test.go @@ -43,6 +43,20 @@ func TestAnalyzeView(t *testing.T) { } } +func TestInfo(t *testing.T) { + driver := new(Sqlite) + d, err := driver.Info(db) + if err != nil { + t.Errorf("%v", err) + } + if d.Name != "sqlite" { + t.Errorf("actual %v\nwant %v", d.Name, "sqlite") + } + if d.DatabaseVersion == "" { + t.Errorf("actual not empty string.") + } +} + func TestParseCheckConstraints(t *testing.T) { sql := `CREATE TABLE check_constraints ( id INTEGER PRIMARY KEY AUTOINCREMENT, diff --git a/output/dot/dot_test.go b/output/dot/dot_test.go index 91f7e7ca..a38d1012 100644 --- a/output/dot/dot_test.go +++ b/output/dot/dot_test.go @@ -103,6 +103,10 @@ func newTestSchema() *schema.Schema { Relations: []*schema.Relation{ r, }, + Driver: &schema.Driver{ + Name: "testdriver", + DatabaseVersion: "1.0.0", + }, } return s } diff --git a/output/json/json_test.go b/output/json/json_test.go index 88c5466b..4201f1e1 100644 --- a/output/json/json_test.go +++ b/output/json/json_test.go @@ -96,6 +96,10 @@ func newTestSchema() *schema.Schema { Relations: []*schema.Relation{ r, }, + Driver: &schema.Driver{ + Name: "testdriver", + DatabaseVersion: "1.0.0", + }, } return s } diff --git a/schema/schema.go b/schema/schema.go index d58d008a..21f475fa 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -64,11 +64,18 @@ type Relation struct { IsAdditional bool `json:"is_additional"` } +// Driver is the struct for tbls driver information +type Driver struct { + Name string `json:"name"` + DatabaseVersion string `json:"database_version"` +} + // Schema is the struct for database schema type Schema struct { Name string `json:"name"` Tables []*Table `json:"tables"` Relations []*Relation `json:"relations"` + Driver *Driver `json:"driver"` } // AdditionalData is the struct for table relations from yaml diff --git a/schema/schema_test.go b/schema/schema_test.go index ffa4a773..e967e891 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -256,6 +256,10 @@ func newTestSchema() *Schema { Relations: []*Relation{ r, }, + Driver: &Driver{ + Name: "testdriver", + DatabaseVersion: "1.0.0", + }, } return s } diff --git a/testdata/json_test_schema.json.golden b/testdata/json_test_schema.json.golden index d8d64fe9..a20493b3 100644 --- a/testdata/json_test_schema.json.golden +++ b/testdata/json_test_schema.json.golden @@ -125,5 +125,9 @@ "def": "", "is_additional": false } - ] + ], + "driver": { + "name": "testdriver", + "database_version": "1.0.0" + } } diff --git a/testdata/testdb.json b/testdata/testdb.json index 9398612f..8198a5df 100644 --- a/testdata/testdb.json +++ b/testdata/testdb.json @@ -2271,5 +2271,9 @@ "def": "Additional Relation", "is_additional": true } - ] + ], + "driver": { + "name": "mysql", + "database_version": "5.7.23" + } }