1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-19 21:29:42 +02:00

SQL Server provider basics

This commit is contained in:
Harvey Kandola 2019-03-27 15:09:48 -04:00
parent deb579d8ad
commit 80aab3ce99
4 changed files with 74 additions and 25 deletions

View file

@ -27,11 +27,12 @@ All you need to provide is PostgreSQL or any MySQL variant.
- Windows - Windows
- macOS - macOS
Heck, Documize will probably run just fine on a Raspberry Pi 3. Heck, Documize will probably run just fine on a Raspberry Pi.
## Database Support ## Database Support
- PostgreSQL (v9.6+) - PostgreSQL (v9.6+)
- Microsoft SQL Server (2016+)
- MySQL (v5.7.10+ and v8.0.12+) - MySQL (v5.7.10+ and v8.0.12+)
- Percona (v5.7.16-10+) - Percona (v5.7.16-10+)
- MariaDB (10.3.0+) - MariaDB (10.3.0+)

View file

@ -122,6 +122,7 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
} }
// ValidateToken finds and validates authentication token. // ValidateToken finds and validates authentication token.
// TODO: remove
func (h *Handler) ValidateToken(w http.ResponseWriter, r *http.Request) { func (h *Handler) ValidateToken(w http.ResponseWriter, r *http.Request) {
// TODO should this go after token validation? // TODO should this go after token validation?
if s := r.URL.Query().Get("section"); s != "" { if s := r.URL.Query().Get("section"); s != "" {

View file

@ -53,6 +53,7 @@ type SQLServerProvider struct {
// //
// Driver for Golang: https://github.com/denisenkom/go-mssqldb // Driver for Golang: https://github.com/denisenkom/go-mssqldb
// Docker Linux testing: https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017 // Docker Linux testing: https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-2017
// docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Passw0rd' -p 1433:1433 --name sql1 -d mcr.microsoft.com/mssql/server:2017-latest
func SetSQLServerProvider(r *env.Runtime, s *store.Store) { func SetSQLServerProvider(r *env.Runtime, s *store.Store) {
// Set up provider specific details. // Set up provider specific details.
r.StoreProvider = SQLServerProvider{ r.StoreProvider = SQLServerProvider{
@ -212,12 +213,17 @@ func (p SQLServerProvider) MakeConnectionString() string {
return p.ConnectionString return p.ConnectionString
} }
// QueryMeta is how to extract version number, collation, character set from database provider. // QueryMeta is how to extract version number, version related comment,
// character set and collation from database provider.
func (p SQLServerProvider) QueryMeta() string { func (p SQLServerProvider) QueryMeta() string {
// SELECT version() as vstring, current_setting('server_version_num') as vnumber, pg_encoding_to_char(encoding) AS charset FROM pg_database WHERE datname = 'documize'; return fmt.Sprintf(`
SELECT
return fmt.Sprintf(`SELECT cast(current_setting('server_version_num') AS TEXT) AS version, version() AS comment, pg_encoding_to_char(encoding) AS charset, '' AS collation CAST(SERVERPROPERTY('productversion') AS VARCHAR) AS version,
FROM pg_database WHERE datname = '%s'`, p.DatabaseName()) @@VERSION AS comment,
collation_name AS collation,
'' AS charset
FROM sys.databases
WHERE name='%s'`, p.DatabaseName())
} }
// QueryRecordVersionUpgrade returns database specific insert statement // QueryRecordVersionUpgrade returns database specific insert statement
@ -239,7 +245,7 @@ func (p SQLServerProvider) QueryRecordVersionUpgradeLegacy(version int) string {
// QueryGetDatabaseVersion returns the schema version number. // QueryGetDatabaseVersion returns the schema version number.
func (p SQLServerProvider) QueryGetDatabaseVersion() string { func (p SQLServerProvider) QueryGetDatabaseVersion() string {
return "SELECT c_config -> 'database' FROM dmz_config WHERE c_key = 'META';" return "SELECT JSON_VALUE(c_config, '$.database') FROM dmz_config WHERE c_key = 'META';"
} }
// QueryGetDatabaseVersionLegacy returns the schema version number before The Great Schema Migration (v25, MySQL). // QueryGetDatabaseVersionLegacy returns the schema version number before The Great Schema Migration (v25, MySQL).
@ -250,56 +256,60 @@ func (p SQLServerProvider) QueryGetDatabaseVersionLegacy() string {
// QueryTableList returns a list tables in Documize database. // QueryTableList returns a list tables in Documize database.
func (p SQLServerProvider) QueryTableList() string { func (p SQLServerProvider) QueryTableList() string {
return fmt.Sprintf(`select table_name return fmt.Sprintf(`SELECT TABLE_NAME
FROM information_schema.tables FROM %s.INFORMATION_SCHEMA.TABLES`, p.DatabaseName())
WHERE table_type='BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema') AND table_catalog='%s'`, p.DatabaseName())
} }
// QueryDateInterval returns provider specific interval style // QueryDateInterval returns provider specific interval style
// date SQL. // date SQL.
func (p SQLServerProvider) QueryDateInterval(days int64) string { func (p SQLServerProvider) QueryDateInterval(days int64) string {
return fmt.Sprintf("DATE(NOW()) - INTERVAL '%d day'", days) return fmt.Sprintf("DATEADD(DAY, -%d, GETDATE())", days)
} }
// JSONEmpty returns empty SQL JSON object. // JSONEmpty returns empty SQL JSON object.
// Typically used as 2nd parameter to COALESCE(). // Typically used as 2nd parameter to COALESCE().
func (p SQLServerProvider) JSONEmpty() string { func (p SQLServerProvider) JSONEmpty() string {
return "'{}'::json" return "'{}'"
} }
// JSONGetValue returns JSON attribute selection syntax. // JSONGetValue returns JSON attribute selection syntax.
// Typically used in SELECT <my_json_field> query. // Typically used in SELECT <my_json_field> query.
func (p SQLServerProvider) JSONGetValue(column, attribute string) string { func (p SQLServerProvider) JSONGetValue(column, attribute string) string {
if len(attribute) > 0 { if len(attribute) > 0 {
return fmt.Sprintf("%s -> '%s'", column, attribute) return fmt.Sprintf("JSON_VALUE(%s, '$.%s'", column, attribute)
} }
return fmt.Sprintf("%s", column) return fmt.Sprintf("JSON_QUERY(%s)", column)
} }
// VerfiyVersion checks to see if actual database meets // VerfiyVersion checks to see if actual database meets
// minimum version requirements.`` // minimum version requirements.
//
// See: http://sqlserverbuilds.blogspot.com
func (p SQLServerProvider) VerfiyVersion(dbVersion string) (bool, string) { func (p SQLServerProvider) VerfiyVersion(dbVersion string) (bool, string) {
// All versions supported.
if strings.HasPrefix(dbVersion, "13.") ||
strings.HasPrefix(dbVersion, "14.") ||
strings.HasPrefix(dbVersion, "15.") {
return true, "" return true, ""
} }
// VerfiyCharacterCollation needs to ensure utf8. return false, "Microsoft SQL Server 2016, 2017 or 2019 is required"
func (p SQLServerProvider) VerfiyCharacterCollation(charset, collation string) (charOK bool, requirements string) {
if strings.ToLower(charset) != "utf8" {
return false, fmt.Sprintf("PostgreSQL character set needs to be utf8, found %s", charset)
} }
// Collation check ignored. // VerfiyCharacterCollation needs to ensure utf8.
// https://www.red-gate.com/simple-talk/sql/sql-development/questions-sql-server-collations-shy-ask/
func (p SQLServerProvider) VerfiyCharacterCollation(charset, collation string) (charOK bool, requirements string) {
// Collation & characters check ignored.
return true, "" return true, ""
} }
// ConvertTimestamp returns SQL function to correctly convert // ConvertTimestamp returns SQL function to correctly convert
// ISO 8601 format (e.g. '2016-09-08T06:37:23Z') to SQL specific // ISO 8601 format (e.g. '2016-09-08T06:37:23Z') to SQL specific
// timestamp value (e.g. 2016-09-08 06:37:23). // timestamp value (e.g. 2016-09-08 06:37:23).
// Must use ? for parameter placeholder character as DB layer //
// We must use ? for parameter placeholder character as DB layer
// will convert to database specific parameter placeholder character. // will convert to database specific parameter placeholder character.
func (p SQLServerProvider) ConvertTimestamp() (statement string) { func (p SQLServerProvider) ConvertTimestamp() (statement string) {
return `to_timestamp(?,'YYYY-MM-DD HH24:MI:SS')` return `convert(varchar, ?, 13)`
} }

View file

@ -49,3 +49,40 @@ func TestSQLServerProviderDatabaseNameWithParams(t *testing.T) {
t.Log(r.StoreProvider.MakeConnectionString()) t.Log(r.StoreProvider.MakeConnectionString())
} }
func TestSQLServerVersion(t *testing.T) {
r := env.Runtime{}
s := store.Store{}
r.Flags.DBType = "sqlserver"
r.Flags.DBConn = "sqlserver://username:password@host:port?database=Test2Documize&some=param"
SetSQLServerProvider(&r, &s)
version := "15.0.1300.359"
ok, msg := r.StoreProvider.VerfiyVersion(version)
if !ok {
t.Errorf("2019 check failed: %s", msg)
}
t.Log(version)
version = "14.0.3048.4"
ok, msg = r.StoreProvider.VerfiyVersion(version)
if !ok {
t.Errorf("2017 check failed: %s", msg)
}
t.Log(version)
version = "13.0.1601.5"
ok, msg = r.StoreProvider.VerfiyVersion(version)
if !ok {
t.Errorf("2016 check failed: %s", msg)
}
t.Log(version)
version = "12.0.6214.1"
ok, msg = r.StoreProvider.VerfiyVersion(version)
if ok {
t.Errorf("unsupported release check failed: %s", msg)
}
t.Log(version)
}