diff --git a/dialects/dialect.go b/dialects/dialect.go index e75ffbfa..325836b4 100644 --- a/dialects/dialect.go +++ b/dialects/dialect.go @@ -44,7 +44,7 @@ type Dialect interface { URI() *URI SQLType(*schemas.Column) string FormatBytes(b []byte) string - Version(ctx context.Context, queryer core.Queryer) (string, error) + Version(ctx context.Context, queryer core.Queryer) (*schemas.Version, error) IsReserved(string) bool Quoter() schemas.Quoter diff --git a/dialects/mssql.go b/dialects/mssql.go index 5e55ce3e..7e922e62 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -253,24 +253,29 @@ func (db *mssql) SetParams(params map[string]string) { } } -func (db *mssql) Version(ctx context.Context, queryer core.Queryer) (string, error) { - rows, err := queryer.QueryContext(ctx, "SELECT @@VERSION") +func (db *mssql) Version(ctx context.Context, queryer core.Queryer) (*schemas.Version, error) { + rows, err := queryer.QueryContext(ctx, + "SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel') AS ProductLevel, SERVERPROPERTY ('edition') AS ProductEdition") if err != nil { - return "", err + return nil, err } defer rows.Close() - var version string + var version, level, edition string if !rows.Next() { - return "", errors.New("unknow version") + return nil, errors.New("unknow version") } - if err := rows.Scan(&version); err != nil { - return "", err + if err := rows.Scan(&version, &level, &edition); err != nil { + return nil, err } // MSSQL: Microsoft SQL Server 2017 (RTM-CU13) (KB4466404) - 14.0.3048.4 (X64) Nov 30 2018 12:57:58 Copyright (C) 2017 Microsoft Corporation Developer Edition (64-bit) on Linux (Ubuntu 16.04.5 LTS) - return version, nil + return &schemas.Version{ + Number: version, + Level: level, + Edition: edition, + }, nil } func (db *mssql) SQLType(c *schemas.Column) string { diff --git a/dialects/mysql.go b/dialects/mysql.go index e8b845fa..670c3928 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -188,25 +188,42 @@ func (db *mysql) Init(uri *URI) error { return db.Base.Init(db, uri) } -func (db *mysql) Version(ctx context.Context, queryer core.Queryer) (string, error) { - rows, err := queryer.QueryContext(ctx, "SELECT VERSION()") +func (db *mysql) Version(ctx context.Context, queryer core.Queryer) (*schemas.Version, error) { + rows, err := queryer.QueryContext(ctx, "SELECT @@VERSION") if err != nil { - return "", err + return nil, err } defer rows.Close() var version string if !rows.Next() { - return "", errors.New("Unknow version") + return nil, errors.New("Unknow version") } if err := rows.Scan(&version); err != nil { - return "", err + return nil, err } - // TiDB: 5.7.25-TiDB-v3.0.3 + if strings.HasPrefix(version, "TiDB:") { + // TiDB: 5.7.25-TiDB-v3.0.3 + fields := strings.Split(strings.TrimPrefix(version, "TiDB: "), "-") + return &schemas.Version{ + Number: strings.TrimPrefix(fields[2], "v"), + Level: fields[0], + Edition: fields[1], + }, nil + } - return version, nil + fields := strings.SplitN(version, "-", 2) + var edition string + if len(fields) == 2 { + edition = fields[1] + } + + return &schemas.Version{ + Number: fields[0], + Edition: edition, + }, nil } func (db *mysql) SetParams(params map[string]string) { diff --git a/dialects/oracle.go b/dialects/oracle.go index 525609f5..0b06c4c6 100644 --- a/dialects/oracle.go +++ b/dialects/oracle.go @@ -515,22 +515,24 @@ func (db *oracle) Init(uri *URI) error { return db.Base.Init(db, uri) } -func (db *oracle) Version(ctx context.Context, queryer core.Queryer) (string, error) { +func (db *oracle) Version(ctx context.Context, queryer core.Queryer) (*schemas.Version, error) { rows, err := queryer.QueryContext(ctx, "select * from v$version where banner like 'Oracle%'") if err != nil { - return "", err + return nil, err } defer rows.Close() var version string if !rows.Next() { - return "", errors.New("unknow version") + return nil, errors.New("unknow version") } if err := rows.Scan(&version); err != nil { - return "", err + return nil, err } - return version, nil + return &schemas.Version{ + Number: version, + }, nil } func (db *oracle) SQLType(c *schemas.Column) string { diff --git a/dialects/postgres.go b/dialects/postgres.go index 11ae48e2..bd1c89bd 100644 --- a/dialects/postgres.go +++ b/dialects/postgres.go @@ -788,32 +788,39 @@ func (db *postgres) Init(uri *URI) error { return db.Base.Init(db, uri) } -func (db *postgres) Version(ctx context.Context, queryer core.Queryer) (string, error) { +func (db *postgres) Version(ctx context.Context, queryer core.Queryer) (*schemas.Version, error) { rows, err := queryer.QueryContext(ctx, "SELECT version()") if err != nil { - return "", err + return nil, err } defer rows.Close() var version string if !rows.Next() { - return "", errors.New("Unknow version") + return nil, errors.New("Unknow version") } if err := rows.Scan(&version); err != nil { - return "", err + return nil, err } - // Postgress: 9.5.22 on x86_64-pc-linux-gnu (Debian 9.5.22-1.pgdg90+1), compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit + // Postgres: 9.5.22 on x86_64-pc-linux-gnu (Debian 9.5.22-1.pgdg90+1), compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit // CockroachDB CCL v19.2.4 (x86_64-unknown-linux-gnu, built if strings.HasPrefix(version, "CockroachDB") { - - } else { - versions := strings.Split(version, " ") - version = versions[0] + versions := strings.Split(strings.TrimPrefix(version, "CockroachDB CCL "), " ") + return &schemas.Version{ + Number: strings.TrimPrefix(versions[0], "v"), + Edition: "CockroachDB", + }, nil + } else if strings.HasPrefix(version, "Postgres:") { + versions := strings.Split(strings.TrimPrefix(version, "Postgres: "), " ") + return &schemas.Version{ + Number: versions[0], + Edition: "Postgres", + }, nil } - return version, nil + return nil, errors.New("unknow database version") } func (db *postgres) getSchema() string { diff --git a/dialects/sqlite3.go b/dialects/sqlite3.go index a666fe72..8d32ec09 100644 --- a/dialects/sqlite3.go +++ b/dialects/sqlite3.go @@ -160,22 +160,24 @@ func (db *sqlite3) Init(uri *URI) error { return db.Base.Init(db, uri) } -func (db *sqlite3) Version(ctx context.Context, queryer core.Queryer) (string, error) { +func (db *sqlite3) Version(ctx context.Context, queryer core.Queryer) (*schemas.Version, error) { rows, err := queryer.QueryContext(ctx, "SELECT sqlite_version()") if err != nil { - return "", err + return nil, err } defer rows.Close() var version string if !rows.Next() { - return "", errors.New("Unknow version") + return nil, errors.New("Unknow version") } if err := rows.Scan(&version); err != nil { - return "", err + return nil, err } - return version, nil + return &schemas.Version{ + Number: version, + }, nil } func (db *sqlite3) SetQuotePolicy(quotePolicy QuotePolicy) { diff --git a/engine.go b/engine.go index 14726638..649ec1a2 100644 --- a/engine.go +++ b/engine.go @@ -926,7 +926,7 @@ func (engine *Engine) Having(conditions string) *Session { } // DBVersion returns the database version -func (engine *Engine) DBVersion() (string, error) { +func (engine *Engine) DBVersion() (*schemas.Version, error) { return engine.dialect.Version(engine.defaultContext, engine.db) } diff --git a/integrations/engine_test.go b/integrations/engine_test.go index d01dc7e8..9b70f9b5 100644 --- a/integrations/engine_test.go +++ b/integrations/engine_test.go @@ -207,5 +207,5 @@ func TestDBVersion(t *testing.T) { version, err := testEngine.DBVersion() assert.NoError(t, err) - fmt.Println(testEngine.Dialect().URI().DBType, "version", version) + fmt.Println(testEngine.Dialect().URI().DBType, "version is", version) } diff --git a/interface.go b/interface.go index 45d54905..d31323ff 100644 --- a/interface.go +++ b/interface.go @@ -79,11 +79,11 @@ type EngineInterface interface { Before(func(interface{})) *Session Charset(charset string) *Session - DBVersion() (string, error) ClearCache(...interface{}) error Context(context.Context) *Session CreateTables(...interface{}) error DBMetas() ([]*schemas.Table, error) + DBVersion() (*schemas.Version, error) Dialect() dialects.Dialect DriverName() string DropTables(...interface{}) error diff --git a/schemas/version.go b/schemas/version.go new file mode 100644 index 00000000..ba789679 --- /dev/null +++ b/schemas/version.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package schemas + +// Version represents a database version +type Version struct { + Number string // the version number which could be compared + Level string + Edition string +}