From 61e3dadd372cf119a12a659c8cb2ece7e7b4c791 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Fri, 25 Mar 2022 12:36:39 +0100 Subject: [PATCH 01/36] Add subroutines --- output/md/md.go | 33 ++++++++++++++++++--- output/md/templates/index.md.tmpl | 7 +++++ output/yaml/yaml_test.go | 5 ++-- schema/json.go | 41 +++++++++++++++++++-------- schema/schema.go | 21 ++++++++++---- testdata/yaml_test_schema.yaml.golden | 1 + 6 files changed, 84 insertions(+), 24 deletions(-) diff --git a/output/md/md.go b/output/md/md.go index 7cf52c268..a22c187db 100644 --- a/output/md/md.go +++ b/output/md/md.go @@ -478,16 +478,41 @@ func (m *Md) makeSchemaTemplateData(s *schema.Schema) map[string]interface{} { tablesData = m.addNumberToTable(tablesData) } + tablesSubroutineData := [][]string{} + tablesSubroutineHeader := []string{ + m.config.MergedDict.Lookup("Name"), + m.config.MergedDict.Lookup("ReturnType"), + m.config.MergedDict.Lookup("Arguments"), + m.config.MergedDict.Lookup("Type"), + } + tablesSubroutineHeaderLine := []string{"----", "-------", "-------", "----"} + tablesSubroutineData = append(tablesSubroutineData, + tablesSubroutineHeader, + tablesSubroutineHeaderLine, + ) + + for _, t := range s.Subroutines { + data := []string{ + t.Name, + t.ReturnType, + t.Arguments, + t.Type, + } + tablesSubroutineData = append(tablesSubroutineData, data) + } + if adjust { return map[string]interface{}{ - "Schema": s, - "Tables": adjustTable(tablesData), + "Schema": s, + "Tables": adjustTable(tablesData), + "Subroutines": adjustTable(tablesSubroutineData), } } return map[string]interface{}{ - "Schema": s, - "Tables": tablesData, + "Schema": s, + "Tables": tablesData, + "Subroutines": tablesSubroutineData, } } diff --git a/output/md/templates/index.md.tmpl b/output/md/templates/index.md.tmpl index 777f07d2a..1d0cf7c6d 100644 --- a/output/md/templates/index.md.tmpl +++ b/output/md/templates/index.md.tmpl @@ -17,6 +17,13 @@ {{ range $t := .Tables }} |{{ range $d := $t }} {{ $d | nl2br }} |{{ end }} {{- end -}} +{{- if .Schema.Subroutines }} + +## {{ "Subroutines" | lookup }} +{{ range $t := .Subroutines }} +|{{ range $d := $t }} {{ $d | nl2br }} |{{ end }} +{{- end -}} +{{- end -}} {{- if .er }} ## {{ "Relations" | lookup }} diff --git a/output/yaml/yaml_test.go b/output/yaml/yaml_test.go index d5bb09339..9554a98ff 100644 --- a/output/yaml/yaml_test.go +++ b/output/yaml/yaml_test.go @@ -92,7 +92,7 @@ func newTestSchema() *schema.Schema { Comment: "table a", Columns: []*schema.Column{ ca, - &schema.Column{ + { Name: "a2", Type: "datetime", Comment: "column a2", @@ -110,7 +110,7 @@ func newTestSchema() *schema.Schema { Comment: "table b", Columns: []*schema.Column{ cb, - &schema.Column{ + { Name: "b2", Comment: "column b2", Type: "text", @@ -136,6 +136,7 @@ func newTestSchema() *schema.Schema { Relations: []*schema.Relation{ r, }, + Subroutines: []*schema.Subroutine{}, Driver: &schema.Driver{ Name: "testdriver", DatabaseVersion: "1.0.0", diff --git a/schema/json.go b/schema/json.go index 4aaad0261..e3d624b67 100644 --- a/schema/json.go +++ b/schema/json.go @@ -13,19 +13,36 @@ func (s Schema) MarshalJSON() ([]byte, error) { s.Relations = []*Relation{} } return json.Marshal(&struct { - Name string `json:"name"` - Desc string `json:"desc"` - Tables []*Table `json:"tables"` - Relations []*Relation `json:"relations"` - Driver *Driver `json:"driver"` - Labels Labels `json:"labels,omitempty"` + Name string `json:"name"` + Desc string `json:"desc"` + Tables []*Table `json:"tables"` + Relations []*Relation `json:"relations"` + Subroutines []*Subroutine `json:"subroutines"` + Driver *Driver `json:"driver"` + Labels Labels `json:"labels,omitempty"` }{ - Name: s.Name, - Desc: s.Desc, - Tables: s.Tables, - Relations: s.Relations, - Driver: s.Driver, - Labels: s.Labels, + Name: s.Name, + Desc: s.Desc, + Tables: s.Tables, + Relations: s.Relations, + Driver: s.Driver, + Subroutines: s.Subroutines, + Labels: s.Labels, + }) +} + +// MarshalJSON return custom JSON byte +func (d Subroutine) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + Name string `json:"name"` + ReturnType string `json:"return_type"` + Arguments string `json:"arguments"` + Type string `json:"type"` + }{ + Name: d.Name, + ReturnType: d.ReturnType, + Arguments: d.Arguments, + Type: d.Type, }) } diff --git a/schema/schema.go b/schema/schema.go index 396b7d6e0..f95564eda 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -102,6 +102,14 @@ type DriverMeta struct { Dict *dict.Dict `json:"dict,omitempty"` } +// Subroutine is the struct for tbls stored procedure/function information +type Subroutine struct { + Name string `json:"name"` + ReturnType string `json:"return_type" yaml:"returnType"` + Arguments string `json:"arguments"` + Type string `json:"type"` +} + // Driver is the struct for tbls driver information type Driver struct { Name string `json:"name"` @@ -111,12 +119,13 @@ type Driver struct { // Schema is the struct for database schema type Schema struct { - Name string `json:"name"` - Desc string `json:"desc"` - Tables []*Table `json:"tables"` - Relations []*Relation `json:"relations"` - Driver *Driver `json:"driver"` - Labels Labels `json:"labels,omitempty"` + Name string `json:"name"` + Desc string `json:"desc"` + Tables []*Table `json:"tables"` + Relations []*Relation `json:"relations"` + Subroutines []*Subroutine `json:"subroutines"` + Driver *Driver `json:"driver"` + Labels Labels `json:"labels,omitempty"` } func (s *Schema) NormalizeTableName(name string) string { diff --git a/testdata/yaml_test_schema.yaml.golden b/testdata/yaml_test_schema.yaml.golden index 71031fe79..2d92c4b44 100644 --- a/testdata/yaml_test_schema.yaml.golden +++ b/testdata/yaml_test_schema.yaml.golden @@ -46,6 +46,7 @@ relations: - b def: "" virtual: false +subroutines: [] driver: name: testdriver databaseVersion: 1.0.0 From 0f454948bd02d77a8c08d07178ac616bc0ae2c23 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 28 Mar 2022 15:35:44 +0200 Subject: [PATCH 02/36] Add mysql functions and stored procedures --- drivers/mysql/mysql.go | 58 +++++++++++++++++++++++++++ testdata/ddl/mysql.sql | 34 ++++++++++++++++ testdata/json_test_schema.json.golden | 1 + 3 files changed, 93 insertions(+) diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index fffc335a5..da667c76c 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -418,6 +418,12 @@ WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position` tables = append(tables, table) } + subroutines, err := m.getSubroutines() + if err != nil { + return err + } + s.Subroutines = subroutines + s.Tables = tables // Relations @@ -473,6 +479,58 @@ WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position` return nil } +const querySubroutines = `select r.routine_schema as database_name, +r.routine_name, +r.routine_type as type, +r.data_type as return_type, +r.routine_definition as definition, +group_concat(CONCAT(p.parameter_name, ' ', p.data_type) separator '; ') as parameter +from information_schema.routines r +left join information_schema.parameters p + on p.specific_schema = r.routine_schema + and p.specific_name = r.specific_name +where routine_schema not in ('sys', 'information_schema', + 'mysql', 'performance_schema') +group by r.routine_schema, r.routine_name, +r.routine_type, r.data_type, r.routine_definition` + +func (m *Mysql) getSubroutines() ([]*schema.Subroutine, error) { + subroutines := []*schema.Subroutine{} + subroutinesResult, err := m.db.Query(querySubroutines) + if err != nil { + return nil, errors.WithStack(err) + } + defer subroutinesResult.Close() + + for subroutinesResult.Next() { + var ( + databaseName string + name string + typeValue string + returnType string + definition string + arguments sql.NullString + ) + err := subroutinesResult.Scan(&databaseName, &name, &typeValue, &returnType, &definition, &arguments) + if err != nil { + return subroutines, errors.WithStack(err) + } + subroutine := &schema.Subroutine{ + Name: name, + Type: typeValue, + ReturnType: returnType, + Arguments: arguments.String, + } + + subroutines = append(subroutines, subroutine) + } + return subroutines, nil +} + +func fullTableName(owner string, tableName string) string { + return fmt.Sprintf("%s.%s", owner, tableName) +} + // Info return schema.Driver func (m *Mysql) Info() (*schema.Driver, error) { var v string diff --git a/testdata/ddl/mysql.sql b/testdata/ddl/mysql.sql index 42605b4fd..96ce0b5a2 100644 --- a/testdata/ddl/mysql.sql +++ b/testdata/ddl/mysql.sql @@ -8,6 +8,8 @@ DROP TABLE IF EXISTS comments; DROP TABLE IF EXISTS posts; DROP TABLE IF EXISTS user_options; DROP TABLE IF EXISTS users; +DROP PROCEDURE IF EXISTS GetAllComments; +DROP FUNCTION IF EXISTS CustomerLevel; CREATE TABLE users ( id int PRIMARY KEY AUTO_INCREMENT, @@ -101,3 +103,35 @@ CREATE TABLE `hyphen-table` ( CREATE TRIGGER update_posts_updated BEFORE UPDATE ON posts FOR EACH ROW SET NEW.updated = CURRENT_TIMESTAMP(); + +DELIMITER // + +CREATE PROCEDURE GetAllComments() +BEGIN + SELECT * FROM comments; +END // + +DELIMITER ; + +DELIMITER $$ + +CREATE FUNCTION CustomerLevel( + credit DECIMAL(10,2) +) +RETURNS VARCHAR(20) +DETERMINISTIC +BEGIN + DECLARE customerLevel VARCHAR(20); + + IF credit > 50000 THEN + SET customerLevel = 'PLATINUM'; + ELSEIF (credit >= 50000 AND + credit <= 10000) THEN + SET customerLevel = 'GOLD'; + ELSEIF credit < 10000 THEN + SET customerLevel = 'SILVER'; + END IF; + -- return the customer level + RETURN (customerLevel); +END$$ +DELIMITER ; diff --git a/testdata/json_test_schema.json.golden b/testdata/json_test_schema.json.golden index 0b52f4e52..0eecdafc3 100644 --- a/testdata/json_test_schema.json.golden +++ b/testdata/json_test_schema.json.golden @@ -67,6 +67,7 @@ "virtual": false } ], + "subroutines": null, "driver": { "name": "testdriver", "database_version": "1.0.0", From ece3f06f58e2d6f3b31a115e72ca01972a9bffce Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 28 Mar 2022 17:21:54 +0200 Subject: [PATCH 03/36] skip description --- drivers/mysql/mysql.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index da667c76c..a2b0a7ae6 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -483,7 +483,6 @@ const querySubroutines = `select r.routine_schema as database_name, r.routine_name, r.routine_type as type, r.data_type as return_type, -r.routine_definition as definition, group_concat(CONCAT(p.parameter_name, ' ', p.data_type) separator '; ') as parameter from information_schema.routines r left join information_schema.parameters p @@ -508,10 +507,9 @@ func (m *Mysql) getSubroutines() ([]*schema.Subroutine, error) { name string typeValue string returnType string - definition string arguments sql.NullString ) - err := subroutinesResult.Scan(&databaseName, &name, &typeValue, &returnType, &definition, &arguments) + err := subroutinesResult.Scan(&databaseName, &name, &typeValue, &returnType, &arguments) if err != nil { return subroutines, errors.WithStack(err) } From 6c67c3c7720ba1ead8eac08e599e78722daeb020 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 28 Mar 2022 17:41:51 +0200 Subject: [PATCH 04/36] update ddl --- testdata/ddl/mysql.sql | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/testdata/ddl/mysql.sql b/testdata/ddl/mysql.sql index 96ce0b5a2..617273846 100644 --- a/testdata/ddl/mysql.sql +++ b/testdata/ddl/mysql.sql @@ -105,16 +105,13 @@ CREATE TRIGGER update_posts_updated BEFORE UPDATE ON posts SET NEW.updated = CURRENT_TIMESTAMP(); DELIMITER // - CREATE PROCEDURE GetAllComments() BEGIN SELECT * FROM comments; -END // - +END// DELIMITER ; DELIMITER $$ - CREATE FUNCTION CustomerLevel( credit DECIMAL(10,2) ) From 72dd13f1000c25ab53274b4435b44143f0e50c40 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 28 Mar 2022 18:52:30 +0200 Subject: [PATCH 05/36] Init mysql db by docker --- Makefile | 1 - docker-compose.yml | 2 ++ testdata/ddl/{ => mysql}/mysql.sql | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename testdata/ddl/{ => mysql}/mysql.sql (100%) diff --git a/Makefile b/Makefile index b482c0f2b..abbbe7aab 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,6 @@ db: db_sqlite usql pg://postgres:pgpass@localhost:55432/testdb?sslmode=disable -f testdata/ddl/postgres95.sql usql pg://postgres:pgpass@localhost:55413/testdb?sslmode=disable -f testdata/ddl/postgres.sql usql my://root:mypass@localhost:33306/testdb -f testdata/ddl/mysql56.sql - usql my://root:mypass@localhost:33308/testdb -f testdata/ddl/mysql.sql usql my://root:mypass@localhost:33308/testdb -c "CREATE DATABASE IF NOT EXISTS relations;" usql my://root:mypass@localhost:33308/relations -f testdata/ddl/detect_relations.sql usql my://root:mypass@localhost:33308/testdb -c "CREATE DATABASE IF NOT EXISTS relations_singular;" diff --git a/docker-compose.yml b/docker-compose.yml index d98e04cae..4e2c3704f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,6 +35,8 @@ services: environment: - MYSQL_DATABASE=testdb - MYSQL_ROOT_PASSWORD=mypass + volumes: + - ./docker-entrypoint-initdb.d/:/testdata/ddl/mysql/ mariadb: image: mariadb:10.5 restart: always diff --git a/testdata/ddl/mysql.sql b/testdata/ddl/mysql/mysql.sql similarity index 100% rename from testdata/ddl/mysql.sql rename to testdata/ddl/mysql/mysql.sql From b848eb1eab422ef9257af0127333e3bad64d1115 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 28 Mar 2022 19:15:16 +0200 Subject: [PATCH 06/36] fix volume command --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4e2c3704f..7a713e30b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,7 +36,7 @@ services: - MYSQL_DATABASE=testdb - MYSQL_ROOT_PASSWORD=mypass volumes: - - ./docker-entrypoint-initdb.d/:/testdata/ddl/mysql/ + - ./testdata/ddl/mysql:/docker-entrypoint-initdb.d mariadb: image: mariadb:10.5 restart: always From 82af43adbbbded2386975d55cf5cdfb167c59acd Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 19:01:54 +0200 Subject: [PATCH 07/36] fix test --- sample/mysql/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sample/mysql/README.md b/sample/mysql/README.md index cefe7375d..fe2f071bb 100644 --- a/sample/mysql/README.md +++ b/sample/mysql/README.md @@ -22,6 +22,13 @@ Sample database document. | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | [users](users.md) | 6 | Users table | BASE TABLE | | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.svg) From 5826c8272be0d033261dfbc5d5bc45209b45e93a Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 19:59:19 +0200 Subject: [PATCH 08/36] fix initial incoding --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 7a713e30b..504d65af4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,6 +35,7 @@ services: environment: - MYSQL_DATABASE=testdb - MYSQL_ROOT_PASSWORD=mypass + - LANG=C.UTF-8 volumes: - ./testdata/ddl/mysql:/docker-entrypoint-initdb.d mariadb: From 866f61bbf1e420df609b5da48b1d4d4d63348494 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 20:15:38 +0200 Subject: [PATCH 09/36] fix test --- sample/detect_relations/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sample/detect_relations/README.md b/sample/detect_relations/README.md index 08da2f375..a7aef048b 100644 --- a/sample/detect_relations/README.md +++ b/sample/detect_relations/README.md @@ -22,6 +22,13 @@ Sample database document. | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | [users](users.md) | 6 | Users table | BASE TABLE | | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.svg) From d4f1ee96553e61a9a22d9294968eaf23ce4ab6e8 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 20:29:46 +0200 Subject: [PATCH 10/36] fix tests --- sample/detect_relations_singular/README.md | 7 +++++++ sample/dict/README.md | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/sample/detect_relations_singular/README.md b/sample/detect_relations_singular/README.md index 85bdd8fdd..1b9ab2fa8 100644 --- a/sample/detect_relations_singular/README.md +++ b/sample/detect_relations_singular/README.md @@ -22,6 +22,13 @@ Sample database document. | [user](user.md) | 6 | User table | BASE TABLE | | | [user_option](user_option.md) | 4 | User option table | BASE TABLE | | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.svg) diff --git a/sample/dict/README.md b/sample/dict/README.md index f4fb28499..d41b64ad7 100644 --- a/sample/dict/README.md +++ b/sample/dict/README.md @@ -14,6 +14,13 @@ | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | [users](users.md) | 6 | Users table | BASE TABLE | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## ER図 ![er](schema.svg) From 650fc55c4520f5f07b5be48dd4b8e1cfd7f379f9 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 20:40:45 +0200 Subject: [PATCH 11/36] update --- sample/png/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sample/png/README.md b/sample/png/README.md index 884c9591c..8adaceeae 100644 --- a/sample/png/README.md +++ b/sample/png/README.md @@ -22,6 +22,13 @@ Sample database document. | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | [users](users.md) | 6 | Users table | BASE TABLE | | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.png) From a84723499c658fb337392df69651b939260d3a1c Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 20:51:17 +0200 Subject: [PATCH 12/36] fix test --- sample/exclude/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sample/exclude/README.md b/sample/exclude/README.md index 8cce79818..f22aa9e62 100644 --- a/sample/exclude/README.md +++ b/sample/exclude/README.md @@ -12,6 +12,13 @@ | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | [users](users.md) | 6 | Users table | BASE TABLE | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.svg) From d39df8e9e5f6daf67f0a016cb2910ac07a1b992b Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 21:51:02 +0200 Subject: [PATCH 13/36] fix tests --- sample/font/README.md | 7 +++++++ sample/number/README.md | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/sample/font/README.md b/sample/font/README.md index 04e438389..19a596791 100644 --- a/sample/font/README.md +++ b/sample/font/README.md @@ -18,6 +18,13 @@ | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | [users](users.md) | 6 | Users table | BASE TABLE | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.png) diff --git a/sample/number/README.md b/sample/number/README.md index de03d1b18..dedfb0d3e 100644 --- a/sample/number/README.md +++ b/sample/number/README.md @@ -22,6 +22,13 @@ Sample database document. | 8 | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | 9 | [users](users.md) | 6 | Users table | BASE TABLE | | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | + ## Relations ![er](schema.svg) From a7e86763d6a278ef948e825d37193eecc3833233 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 21:58:49 +0200 Subject: [PATCH 14/36] fix test --- sample/dict/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sample/dict/README.md b/sample/dict/README.md index d41b64ad7..4749f2137 100644 --- a/sample/dict/README.md +++ b/sample/dict/README.md @@ -16,10 +16,10 @@ ## Subroutines -| Name | ReturnType | Arguments | Type | -| ---- | ------- | ------- | ---- | -| CustomerLevel | varchar | credit decimal | FUNCTION | -| GetAllComments | | | PROCEDURE | +| 名前 | ReturnType | Arguments | タイプ | +| -------------- | ---------- | -------------- | --------- | +| CustomerLevel | varchar | credit decimal | FUNCTION | +| GetAllComments | | | PROCEDURE | ## ER図 From a50671ef7e4b84a28a61ec77dc8a983e87b53813 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Wed, 30 Mar 2022 23:47:23 +0200 Subject: [PATCH 15/36] Add subroutines to postgre --- drivers/postgres/postgres.go | 52 ++++++++++++++++++++++++++++++++++++ sample/adjust/README.md | 17 ++++++++++++ sample/postgres/README.md | 17 ++++++++++++ sample/postgres95/README.md | 17 ++++++++++++ testdata/ddl/postgres.sql | 10 +++++++ 5 files changed, 113 insertions(+) diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index fc492af32..21b40db72 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -296,6 +296,12 @@ ORDER BY tgrelid tables = append(tables, table) } + subroutines, err := p.getSubroutines() + if err != nil { + return err + } + s.Subroutines = subroutines + s.Tables = tables // Relations @@ -364,6 +370,52 @@ ORDER BY tgrelid return nil } +const querySubroutines = `select n.nspname as schema_name, +p.proname as specific_name, +case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end as type_value, +t.typname as return_type, +pg_get_function_arguments(p.oid) as arguments +from pg_proc p +left join pg_namespace n on p.pronamespace = n.oid +left join pg_type t on t.oid = p.prorettype +where n.nspname not in ('pg_catalog', 'information_schema')` + +func (p *Postgres) getSubroutines() ([]*schema.Subroutine, error) { + subroutines := []*schema.Subroutine{} + subroutinesResult, err := p.db.Query(querySubroutines) + if err != nil { + return nil, errors.WithStack(err) + } + defer subroutinesResult.Close() + + for subroutinesResult.Next() { + var ( + schemaName string + name string + typeValue string + returnType string + arguments sql.NullString + ) + err := subroutinesResult.Scan(&schemaName, &name, &typeValue, &returnType, &arguments) + if err != nil { + return subroutines, errors.WithStack(err) + } + subroutine := &schema.Subroutine{ + Name: fullTableName(schemaName, name), + Type: typeValue, + ReturnType: returnType, + Arguments: arguments.String, + } + + subroutines = append(subroutines, subroutine) + } + return subroutines, nil +} + +func fullTableName(owner string, tableName string) string { + return fmt.Sprintf("%s.%s", owner, tableName) +} + // Info return schema.Driver func (p *Postgres) Info() (*schema.Driver, error) { var v string diff --git a/sample/adjust/README.md b/sample/adjust/README.md index 87eaeeffb..8d0ff3f99 100644 --- a/sample/adjust/README.md +++ b/sample/adjust/README.md @@ -25,6 +25,23 @@ Sample PostgreSQL database document. | [time.hyphenated-table](time.hyphenated-table.md) | 1 | | BASE TABLE | | [time.referencing](time.referencing.md) | 3 | | BASE TABLE | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| public.uuid_nil | uuid | | FUNCTION | +| public.uuid_ns_dns | uuid | | FUNCTION | +| public.uuid_ns_url | uuid | | FUNCTION | +| public.uuid_ns_oid | uuid | | FUNCTION | +| public.uuid_ns_x500 | uuid | | FUNCTION | +| public.uuid_generate_v1 | uuid | | FUNCTION | +| public.uuid_generate_v1mc | uuid | | FUNCTION | +| public.uuid_generate_v3 | uuid | namespace uuid, name text | FUNCTION | +| public.uuid_generate_v4 | uuid | | FUNCTION | +| public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | +| public.update_updated | trigger | | FUNCTION | +| public.reset_comment | void | comment_id integer | PROCEDURE | + ## Relations ![er](schema.svg) diff --git a/sample/postgres/README.md b/sample/postgres/README.md index 6371b8f7b..057d84222 100644 --- a/sample/postgres/README.md +++ b/sample/postgres/README.md @@ -25,6 +25,23 @@ Sample PostgreSQL database document. | [time.hyphenated-table](time.hyphenated-table.md) | 1 | | BASE TABLE | | [time.referencing](time.referencing.md) | 3 | | BASE TABLE | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| public.uuid_nil | uuid | | FUNCTION | +| public.uuid_ns_dns | uuid | | FUNCTION | +| public.uuid_ns_url | uuid | | FUNCTION | +| public.uuid_ns_oid | uuid | | FUNCTION | +| public.uuid_ns_x500 | uuid | | FUNCTION | +| public.uuid_generate_v1 | uuid | | FUNCTION | +| public.uuid_generate_v1mc | uuid | | FUNCTION | +| public.uuid_generate_v3 | uuid | namespace uuid, name text | FUNCTION | +| public.uuid_generate_v4 | uuid | | FUNCTION | +| public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | +| public.update_updated | trigger | | FUNCTION | +| public.reset_comment | void | comment_id integer | PROCEDURE | + ## Relations ![er](schema.svg) diff --git a/sample/postgres95/README.md b/sample/postgres95/README.md index 0252257db..38c52bd4d 100644 --- a/sample/postgres95/README.md +++ b/sample/postgres95/README.md @@ -25,6 +25,23 @@ Sample PostgreSQL database document. | [time.hyphenated-table](time.hyphenated-table.md) | 1 | | BASE TABLE | | [time.referencing](time.referencing.md) | 3 | | BASE TABLE | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| public.uuid_nil | uuid | | FUNCTION | +| public.uuid_ns_dns | uuid | | FUNCTION | +| public.uuid_ns_url | uuid | | FUNCTION | +| public.uuid_ns_oid | uuid | | FUNCTION | +| public.uuid_ns_x500 | uuid | | FUNCTION | +| public.uuid_generate_v1 | uuid | | FUNCTION | +| public.uuid_generate_v1mc | uuid | | FUNCTION | +| public.uuid_generate_v3 | uuid | namespace uuid, name text | FUNCTION | +| public.uuid_generate_v4 | uuid | | FUNCTION | +| public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | +| public.update_updated | trigger | | FUNCTION | +| public.reset_comment | void | comment_id integer | PROCEDURE | + ## Relations ![er](schema.svg) diff --git a/testdata/ddl/postgres.sql b/testdata/ddl/postgres.sql index a2c853a83..05281e4e4 100644 --- a/testdata/ddl/postgres.sql +++ b/testdata/ddl/postgres.sql @@ -219,3 +219,13 @@ CREATE TABLE time.referencing ( CONSTRAINT referencing_bar_id FOREIGN KEY(bar_id) REFERENCES time.bar(id), CONSTRAINT referencing_ht_id FOREIGN KEY(ht_id) REFERENCES time."hyphenated-table"(id) ); + +CREATE OR REPLACE PROCEDURE reset_comment (comment_id int) AS ' + begin + update comments + set comment = "updated" + where id = comment_id; + + commit; + end; +' LANGUAGE plpgsql; From 4ff661fb622f4052d036aa2780d7113551415448 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Thu, 31 Mar 2022 00:01:26 +0200 Subject: [PATCH 16/36] fix tests --- drivers/postgres/postgres.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index 21b40db72..832a200a5 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -372,7 +372,7 @@ ORDER BY tgrelid const querySubroutines = `select n.nspname as schema_name, p.proname as specific_name, -case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end as type_value, +case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end, t.typname as return_type, pg_get_function_arguments(p.oid) as arguments from pg_proc p From 86baeefab1693e05d38e008262109445daae4413 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Thu, 31 Mar 2022 00:50:25 +0200 Subject: [PATCH 17/36] procedure support --- drivers/postgres/postgres.go | 61 ++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index 832a200a5..6ee82e8a3 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -370,9 +370,9 @@ ORDER BY tgrelid return nil } -const querySubroutines = `select n.nspname as schema_name, +const querySubroutinesFunctions = `select n.nspname as schema_name, p.proname as specific_name, -case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end, +TEXT 'PROCEDURE', t.typname as return_type, pg_get_function_arguments(p.oid) as arguments from pg_proc p @@ -380,9 +380,64 @@ left join pg_namespace n on p.pronamespace = n.oid left join pg_type t on t.oid = p.prorettype where n.nspname not in ('pg_catalog', 'information_schema')` +const querySubroutinesStoredProcedures = `select n.nspname as schema_name, +p.proname as specific_name, +TEXT 'PROCEDURE', +t.typname as return_type, +pg_get_function_arguments(p.oid) as arguments +from pg_proc p +left join pg_namespace n on p.pronamespace = n.oid +left join pg_type t on t.oid = p.prorettype +where n.nspname not in ('pg_catalog', 'information_schema')` + +const queryStoredProcedureSupported = `SELECT column_name +FROM information_schema.columns +WHERE table_name='pg_proc' and column_name='prokind';` + +func (p *Postgres) isProceduresSupported() (bool, error) { + result, err := p.db.Query(queryStoredProcedureSupported) + if err != nil { + return false, errors.WithStack(err) + } + defer result.Close() + + for result.Next() { + var ( + name sql.NullString + ) + err := result.Scan(&name) + if err != nil { + return false, errors.WithStack(err) + } + return true, nil + } + return false, nil +} + func (p *Postgres) getSubroutines() ([]*schema.Subroutine, error) { subroutines := []*schema.Subroutine{} - subroutinesResult, err := p.db.Query(querySubroutines) + functions, err := p.getSubroutinesByQuery(querySubroutinesFunctions) + if err != nil { + return nil, errors.WithStack(err) + } + subroutines = append(subroutines, functions...) + storedProcedureSupported, err := p.isProceduresSupported() + if err != nil { + return nil, errors.WithStack(err) + } + if storedProcedureSupported { + procedures, err := p.getSubroutinesByQuery(querySubroutinesStoredProcedures) + if err != nil { + return nil, errors.WithStack(err) + } + subroutines = append(subroutines, procedures...) + } + return subroutines, nil +} + +func (p *Postgres) getSubroutinesByQuery(query string) ([]*schema.Subroutine, error) { + subroutines := []*schema.Subroutine{} + subroutinesResult, err := p.db.Query(query) if err != nil { return nil, errors.WithStack(err) } From 437714c24693b28802840d11a5d4cbf3818bfef1 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Thu, 31 Mar 2022 01:01:41 +0200 Subject: [PATCH 18/36] fix tests --- drivers/postgres/postgres.go | 2 +- sample/postgres95/README.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index 6ee82e8a3..a3a579198 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -372,7 +372,7 @@ ORDER BY tgrelid const querySubroutinesFunctions = `select n.nspname as schema_name, p.proname as specific_name, -TEXT 'PROCEDURE', +TEXT 'FUNCTION', t.typname as return_type, pg_get_function_arguments(p.oid) as arguments from pg_proc p diff --git a/sample/postgres95/README.md b/sample/postgres95/README.md index 38c52bd4d..8d8ed02ec 100644 --- a/sample/postgres95/README.md +++ b/sample/postgres95/README.md @@ -40,7 +40,6 @@ Sample PostgreSQL database document. | public.uuid_generate_v4 | uuid | | FUNCTION | | public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | | public.update_updated | trigger | | FUNCTION | -| public.reset_comment | void | comment_id integer | PROCEDURE | ## Relations From 439ec3f96d9887b2b4fe058d5f2a75631f17caf7 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Thu, 31 Mar 2022 14:13:41 +0200 Subject: [PATCH 19/36] Support protgresql 9.5 --- drivers/postgres/postgres.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index a3a579198..0cb8d9e41 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -370,7 +370,7 @@ ORDER BY tgrelid return nil } -const querySubroutinesFunctions = `select n.nspname as schema_name, +const querySubroutines95 = `select n.nspname as schema_name, p.proname as specific_name, TEXT 'FUNCTION', t.typname as return_type, @@ -380,9 +380,9 @@ left join pg_namespace n on p.pronamespace = n.oid left join pg_type t on t.oid = p.prorettype where n.nspname not in ('pg_catalog', 'information_schema')` -const querySubroutinesStoredProcedures = `select n.nspname as schema_name, +const querySubroutines = `select n.nspname as schema_name, p.proname as specific_name, -TEXT 'PROCEDURE', +case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end, t.typname as return_type, pg_get_function_arguments(p.oid) as arguments from pg_proc p @@ -415,22 +415,21 @@ func (p *Postgres) isProceduresSupported() (bool, error) { } func (p *Postgres) getSubroutines() ([]*schema.Subroutine, error) { - subroutines := []*schema.Subroutine{} - functions, err := p.getSubroutinesByQuery(querySubroutinesFunctions) - if err != nil { - return nil, errors.WithStack(err) - } - subroutines = append(subroutines, functions...) + var subroutines []*schema.Subroutine storedProcedureSupported, err := p.isProceduresSupported() if err != nil { return nil, errors.WithStack(err) } if storedProcedureSupported { - procedures, err := p.getSubroutinesByQuery(querySubroutinesStoredProcedures) + subroutines, err = p.getSubroutinesByQuery(querySubroutines) + if err != nil { + return nil, errors.WithStack(err) + } + } else { + subroutines, err = p.getSubroutinesByQuery(querySubroutines95) if err != nil { return nil, errors.WithStack(err) } - subroutines = append(subroutines, procedures...) } return subroutines, nil } From 6c56672b6e20d961fb14b886a6348e27b5ec4a96 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Thu, 31 Mar 2022 14:22:57 +0200 Subject: [PATCH 20/36] fix test --- sample/adjust/README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sample/adjust/README.md b/sample/adjust/README.md index 8d0ff3f99..7ffe2eb43 100644 --- a/sample/adjust/README.md +++ b/sample/adjust/README.md @@ -27,20 +27,20 @@ Sample PostgreSQL database document. ## Subroutines -| Name | ReturnType | Arguments | Type | -| ---- | ------- | ------- | ---- | -| public.uuid_nil | uuid | | FUNCTION | -| public.uuid_ns_dns | uuid | | FUNCTION | -| public.uuid_ns_url | uuid | | FUNCTION | -| public.uuid_ns_oid | uuid | | FUNCTION | -| public.uuid_ns_x500 | uuid | | FUNCTION | -| public.uuid_generate_v1 | uuid | | FUNCTION | -| public.uuid_generate_v1mc | uuid | | FUNCTION | -| public.uuid_generate_v3 | uuid | namespace uuid, name text | FUNCTION | -| public.uuid_generate_v4 | uuid | | FUNCTION | -| public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | -| public.update_updated | trigger | | FUNCTION | -| public.reset_comment | void | comment_id integer | PROCEDURE | +| Name | ReturnType | Arguments | Type | +| ------------------------- | ---------- | ------------------------- | --------- | +| public.uuid_nil | uuid | | FUNCTION | +| public.uuid_ns_dns | uuid | | FUNCTION | +| public.uuid_ns_url | uuid | | FUNCTION | +| public.uuid_ns_oid | uuid | | FUNCTION | +| public.uuid_ns_x500 | uuid | | FUNCTION | +| public.uuid_generate_v1 | uuid | | FUNCTION | +| public.uuid_generate_v1mc | uuid | | FUNCTION | +| public.uuid_generate_v3 | uuid | namespace uuid, name text | FUNCTION | +| public.uuid_generate_v4 | uuid | | FUNCTION | +| public.uuid_generate_v5 | uuid | namespace uuid, name text | FUNCTION | +| public.update_updated | trigger | | FUNCTION | +| public.reset_comment | void | comment_id integer | PROCEDURE | ## Relations From d96e84e28ee890172f5d0049c3d396e986b107a0 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Thu, 31 Mar 2022 16:14:08 +0200 Subject: [PATCH 21/36] Add stored procedures to mssql --- drivers/mssql/mssql.go | 68 ++++++++++++++++++++++++++++++++++++++++++ sample/mssql/README.md | 7 +++++ testdata/ddl/mssql.sql | 16 ++++++++++ 3 files changed, 91 insertions(+) diff --git a/drivers/mssql/mssql.go b/drivers/mssql/mssql.go index b1382de45..84d2b8893 100644 --- a/drivers/mssql/mssql.go +++ b/drivers/mssql/mssql.go @@ -402,6 +402,12 @@ ORDER BY i.index_id tables = append(tables, table) } + subroutines, err := m.getSubroutines() + if err != nil { + return err + } + s.Subroutines = subroutines + s.Tables = tables // relations @@ -459,6 +465,68 @@ ORDER BY i.index_id return nil } +const query = `select schema_name(obj.schema_id) as schema_name, + obj.name as name, + case type + when 'FN' then 'SQL scalar function' + when 'TF' then 'SQL table-valued-function' + when 'IF' then 'SQL inline table-valued function' + when 'P' then 'SQL Stored Procedure' + when 'X' then 'Extended stored procedure' + end as type, + TYPE_NAME(ret.user_type_id) as return_type, + substring(par.parameters, 0, len(par.parameters)) as parameters +from sys.objects obj +join sys.sql_modules mod +on mod.object_id = obj.object_id +cross apply (select p.name + ' ' + TYPE_NAME(p.user_type_id) + ', ' + from sys.parameters p + where p.object_id = obj.object_id + and p.parameter_id != 0 + for xml path ('') ) par (parameters) +left join sys.parameters ret + on obj.object_id = ret.object_id + and ret.parameter_id = 0 +where obj.type in ('FN', 'TF', 'IF', 'P', 'X') +order by schema_name, + name;` + +func (m *Mssql) getSubroutines() ([]*schema.Subroutine, error) { + subroutines := []*schema.Subroutine{} + subroutinesResult, err := m.db.Query(query) + if err != nil { + return nil, errors.WithStack(err) + } + defer subroutinesResult.Close() + + for subroutinesResult.Next() { + var ( + schemaName string + name string + typeValue string + returnType sql.NullString + arguments sql.NullString + ) + err := subroutinesResult.Scan(&schemaName, &name, &typeValue, &returnType, &arguments) + if err != nil { + return subroutines, errors.WithStack(err) + } + subroutine := &schema.Subroutine{ + Name: fullTableName(schemaName, name), + Type: typeValue, + ReturnType: returnType.String, + Arguments: arguments.String, + } + + subroutines = append(subroutines, subroutine) + } + return subroutines, nil +} + +func fullTableName(owner string, tableName string) string { + return fmt.Sprintf("%s.%s", owner, tableName) +} + func (m *Mssql) Info() (*schema.Driver, error) { var v string row := m.db.QueryRow(`SELECT @@VERSION`) diff --git a/sample/mssql/README.md b/sample/mssql/README.md index 040e06ca0..2f3268f09 100644 --- a/sample/mssql/README.md +++ b/sample/mssql/README.md @@ -23,6 +23,13 @@ Sample database document. | [hyphen-table](hyphen-table.md) | 3 | | BASIC TABLE | | | [administrator.blogs](administrator.blogs.md) | 6 | admin blogs | BASIC TABLE | | +## Subroutines + +| Name | ReturnType | Arguments | Type | +| ---- | ------- | ------- | ---- | +| dbo.get_user | | @userid int | SQL inline table-valued function | +| dbo.What_DB_is_that | | @ID int | SQL Stored Procedure | + ## Relations ![er](schema.svg) diff --git a/testdata/ddl/mssql.sql b/testdata/ddl/mssql.sql index cae7e8eb3..df80e2e4c 100644 --- a/testdata/ddl/mssql.sql +++ b/testdata/ddl/mssql.sql @@ -12,6 +12,8 @@ DROP TYPE IF EXISTS post_types; DROP TABLE IF EXISTS user_options; DROP TABLE IF EXISTS users; DROP SCHEMA IF EXISTS administrator; +DROP FUNCTION IF EXISTS get_user; +DROP PROC IF EXISTS What_DB_is_that; CREATE TABLE users ( id int NOT NULL IDENTITY(1,1) PRIMARY KEY, @@ -165,3 +167,17 @@ BEGIN UPDATE users SET updated = GETDATE() WHERE id = ( SELECT user_id FROM deleted) END; + +CREATE FUNCTION get_user (@userid int) +RETURNS TABLE +AS +RETURN +( + SELECT u.username, u.email + FROM users AS u + WHERE u.id = @userid +); + +CREATE PROC What_DB_is_that @ID INT +AS +SELECT DB_NAME(@ID) AS ThatDB; From afc6f0dfe3154900105a2ea46a4a7d68d648618d Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Fri, 1 Apr 2022 14:29:12 +0200 Subject: [PATCH 22/36] rename subroutines in output --- drivers/mssql/mssql.go | 9 +++++++++ drivers/mysql/mysql.go | 9 +++++++++ drivers/postgres/postgres.go | 10 +++++++++- sample/adjust/README.md | 2 +- sample/detect_relations/README.md | 2 +- sample/detect_relations_singular/README.md | 2 +- sample/dict/README.md | 2 +- sample/exclude/README.md | 2 +- sample/font/README.md | 2 +- sample/mssql/README.md | 2 +- sample/mysql/README.md | 2 +- sample/number/README.md | 2 +- sample/png/README.md | 2 +- sample/postgres/README.md | 2 +- sample/postgres95/README.md | 2 +- 15 files changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/mssql/mssql.go b/drivers/mssql/mssql.go index 84d2b8893..5ba79383b 100644 --- a/drivers/mssql/mssql.go +++ b/drivers/mssql/mssql.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/k1LoW/tbls/ddl" + "github.com/k1LoW/tbls/dict" "github.com/k1LoW/tbls/schema" "github.com/pkg/errors" ) @@ -535,9 +536,17 @@ func (m *Mssql) Info() (*schema.Driver, error) { return nil, err } + dct := dict.New() + dct.Merge(map[string]string{ + "Subroutines": "Stored procedures and functions", + }) + d := &schema.Driver{ Name: "sqlserver", DatabaseVersion: v, + Meta: &schema.DriverMeta{ + Dict: &dct, + }, } return d, nil } diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index a2b0a7ae6..d08ded215 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -8,6 +8,7 @@ import ( "github.com/aquasecurity/go-version/pkg/version" "github.com/k1LoW/tbls/ddl" + "github.com/k1LoW/tbls/dict" "github.com/k1LoW/tbls/drivers" "github.com/k1LoW/tbls/schema" "github.com/pkg/errors" @@ -543,9 +544,17 @@ func (m *Mysql) Info() (*schema.Driver, error) { name = "mariadb" } + dct := dict.New() + dct.Merge(map[string]string{ + "Subroutines": "Stored procedures and functions", + }) + d := &schema.Driver{ Name: name, DatabaseVersion: v, + Meta: &schema.DriverMeta{ + Dict: &dct, + }, } return d, nil } diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index 0cb8d9e41..f28e64514 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -8,6 +8,7 @@ import ( "github.com/aquasecurity/go-version/pkg/version" "github.com/k1LoW/tbls/ddl" + "github.com/k1LoW/tbls/dict" "github.com/k1LoW/tbls/schema" "github.com/lib/pq" "github.com/pkg/errors" @@ -484,10 +485,17 @@ func (p *Postgres) Info() (*schema.Driver, error) { name = "redshift" } + dct := dict.New() + dct.Merge(map[string]string{ + "Subroutines": "Stored procedures and functions", + }) + d := &schema.Driver{ Name: name, DatabaseVersion: v, - Meta: &schema.DriverMeta{}, + Meta: &schema.DriverMeta{ + Dict: &dct, + }, } return d, nil } diff --git a/sample/adjust/README.md b/sample/adjust/README.md index 7ffe2eb43..9b2e2ac39 100644 --- a/sample/adjust/README.md +++ b/sample/adjust/README.md @@ -25,7 +25,7 @@ Sample PostgreSQL database document. | [time.hyphenated-table](time.hyphenated-table.md) | 1 | | BASE TABLE | | [time.referencing](time.referencing.md) | 3 | | BASE TABLE | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ------------------------- | ---------- | ------------------------- | --------- | diff --git a/sample/detect_relations/README.md b/sample/detect_relations/README.md index a7aef048b..689a6a5d1 100644 --- a/sample/detect_relations/README.md +++ b/sample/detect_relations/README.md @@ -22,7 +22,7 @@ Sample database document. | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | [users](users.md) | 6 | Users table | BASE TABLE | | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/detect_relations_singular/README.md b/sample/detect_relations_singular/README.md index 1b9ab2fa8..e0cf4061c 100644 --- a/sample/detect_relations_singular/README.md +++ b/sample/detect_relations_singular/README.md @@ -22,7 +22,7 @@ Sample database document. | [user](user.md) | 6 | User table | BASE TABLE | | | [user_option](user_option.md) | 4 | User option table | BASE TABLE | | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/dict/README.md b/sample/dict/README.md index 4749f2137..a3d72c263 100644 --- a/sample/dict/README.md +++ b/sample/dict/README.md @@ -14,7 +14,7 @@ | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | [users](users.md) | 6 | Users table | BASE TABLE | -## Subroutines +## Stored procedures and functions | 名前 | ReturnType | Arguments | タイプ | | -------------- | ---------- | -------------- | --------- | diff --git a/sample/exclude/README.md b/sample/exclude/README.md index f22aa9e62..5df44b1c4 100644 --- a/sample/exclude/README.md +++ b/sample/exclude/README.md @@ -12,7 +12,7 @@ | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | [users](users.md) | 6 | Users table | BASE TABLE | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/font/README.md b/sample/font/README.md index 19a596791..b529dbb94 100644 --- a/sample/font/README.md +++ b/sample/font/README.md @@ -18,7 +18,7 @@ | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | [users](users.md) | 6 | Users table | BASE TABLE | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/mssql/README.md b/sample/mssql/README.md index 2f3268f09..ff70a5d9f 100644 --- a/sample/mssql/README.md +++ b/sample/mssql/README.md @@ -23,7 +23,7 @@ Sample database document. | [hyphen-table](hyphen-table.md) | 3 | | BASIC TABLE | | | [administrator.blogs](administrator.blogs.md) | 6 | admin blogs | BASIC TABLE | | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/mysql/README.md b/sample/mysql/README.md index fe2f071bb..5694dd1d4 100644 --- a/sample/mysql/README.md +++ b/sample/mysql/README.md @@ -22,7 +22,7 @@ Sample database document. | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | [users](users.md) | 6 | Users table | BASE TABLE | | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/number/README.md b/sample/number/README.md index dedfb0d3e..28e67c6ef 100644 --- a/sample/number/README.md +++ b/sample/number/README.md @@ -22,7 +22,7 @@ Sample database document. | 8 | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | 9 | [users](users.md) | 6 | Users table | BASE TABLE | | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/png/README.md b/sample/png/README.md index 8adaceeae..8529bf06d 100644 --- a/sample/png/README.md +++ b/sample/png/README.md @@ -22,7 +22,7 @@ Sample database document. | [user_options](user_options.md) | 4 | User options table | BASE TABLE | | | [users](users.md) | 6 | Users table | BASE TABLE | | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/postgres/README.md b/sample/postgres/README.md index 057d84222..740854d6d 100644 --- a/sample/postgres/README.md +++ b/sample/postgres/README.md @@ -25,7 +25,7 @@ Sample PostgreSQL database document. | [time.hyphenated-table](time.hyphenated-table.md) | 1 | | BASE TABLE | | [time.referencing](time.referencing.md) | 3 | | BASE TABLE | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | diff --git a/sample/postgres95/README.md b/sample/postgres95/README.md index 8d8ed02ec..35eec5feb 100644 --- a/sample/postgres95/README.md +++ b/sample/postgres95/README.md @@ -25,7 +25,7 @@ Sample PostgreSQL database document. | [time.hyphenated-table](time.hyphenated-table.md) | 1 | | BASE TABLE | | [time.referencing](time.referencing.md) | 3 | | BASE TABLE | -## Subroutines +## Stored procedures and functions | Name | ReturnType | Arguments | Type | | ---- | ------- | ------- | ---- | From 569f959e2155bd0747c27959c4b7bcf4587daa4e Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 21:22:02 -0500 Subject: [PATCH 23/36] rename subroutine to function --- drivers/mssql/mssql.go | 26 ++++++++--------- drivers/mysql/mysql.go | 28 +++++++++---------- drivers/postgres/postgres.go | 40 +++++++++++++-------------- output/md/md.go | 14 +++++----- output/yaml/yaml_test.go | 2 +- schema/json.go | 30 ++++++++++---------- schema/schema.go | 18 ++++++------ testdata/json_test_schema.json.golden | 2 +- testdata/yaml_test_schema.yaml.golden | 2 +- 9 files changed, 81 insertions(+), 81 deletions(-) diff --git a/drivers/mssql/mssql.go b/drivers/mssql/mssql.go index 5ba79383b..f753c3f8f 100644 --- a/drivers/mssql/mssql.go +++ b/drivers/mssql/mssql.go @@ -403,11 +403,11 @@ ORDER BY i.index_id tables = append(tables, table) } - subroutines, err := m.getSubroutines() + functions, err := m.getFunctions() if err != nil { return err } - s.Subroutines = subroutines + s.Functions = functions s.Tables = tables @@ -492,15 +492,15 @@ where obj.type in ('FN', 'TF', 'IF', 'P', 'X') order by schema_name, name;` -func (m *Mssql) getSubroutines() ([]*schema.Subroutine, error) { - subroutines := []*schema.Subroutine{} - subroutinesResult, err := m.db.Query(query) +func (m *Mssql) getFunctions() ([]*schema.Function, error) { + functions := []*schema.Function{} + functionsResult, err := m.db.Query(query) if err != nil { return nil, errors.WithStack(err) } - defer subroutinesResult.Close() + defer functionsResult.Close() - for subroutinesResult.Next() { + for functionsResult.Next() { var ( schemaName string name string @@ -508,20 +508,20 @@ func (m *Mssql) getSubroutines() ([]*schema.Subroutine, error) { returnType sql.NullString arguments sql.NullString ) - err := subroutinesResult.Scan(&schemaName, &name, &typeValue, &returnType, &arguments) + err := functionsResult.Scan(&schemaName, &name, &typeValue, &returnType, &arguments) if err != nil { - return subroutines, errors.WithStack(err) + return functions, errors.WithStack(err) } - subroutine := &schema.Subroutine{ + function := &schema.Function{ Name: fullTableName(schemaName, name), Type: typeValue, ReturnType: returnType.String, Arguments: arguments.String, } - subroutines = append(subroutines, subroutine) + functions = append(functions, function) } - return subroutines, nil + return functions, nil } func fullTableName(owner string, tableName string) string { @@ -538,7 +538,7 @@ func (m *Mssql) Info() (*schema.Driver, error) { dct := dict.New() dct.Merge(map[string]string{ - "Subroutines": "Stored procedures and functions", + "Functions": "Stored procedures and functions", }) d := &schema.Driver{ diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index d08ded215..1b130688f 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -419,11 +419,11 @@ WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position` tables = append(tables, table) } - subroutines, err := m.getSubroutines() + functions, err := m.getFunctions() if err != nil { return err } - s.Subroutines = subroutines + s.Functions = functions s.Tables = tables @@ -480,7 +480,7 @@ WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position` return nil } -const querySubroutines = `select r.routine_schema as database_name, +const queryFunctions = `select r.routine_schema as database_name, r.routine_name, r.routine_type as type, r.data_type as return_type, @@ -494,15 +494,15 @@ where routine_schema not in ('sys', 'information_schema', group by r.routine_schema, r.routine_name, r.routine_type, r.data_type, r.routine_definition` -func (m *Mysql) getSubroutines() ([]*schema.Subroutine, error) { - subroutines := []*schema.Subroutine{} - subroutinesResult, err := m.db.Query(querySubroutines) +func (m *Mysql) getFunctions() ([]*schema.Function, error) { + functions := []*schema.Function{} + functionsResult, err := m.db.Query(queryFunctions) if err != nil { return nil, errors.WithStack(err) } - defer subroutinesResult.Close() + defer functionsResult.Close() - for subroutinesResult.Next() { + for functionsResult.Next() { var ( databaseName string name string @@ -510,20 +510,20 @@ func (m *Mysql) getSubroutines() ([]*schema.Subroutine, error) { returnType string arguments sql.NullString ) - err := subroutinesResult.Scan(&databaseName, &name, &typeValue, &returnType, &arguments) + err := functionsResult.Scan(&databaseName, &name, &typeValue, &returnType, &arguments) if err != nil { - return subroutines, errors.WithStack(err) + return functions, errors.WithStack(err) } - subroutine := &schema.Subroutine{ + subroutine := &schema.Function{ Name: name, Type: typeValue, ReturnType: returnType, Arguments: arguments.String, } - subroutines = append(subroutines, subroutine) + functions = append(functions, subroutine) } - return subroutines, nil + return functions, nil } func fullTableName(owner string, tableName string) string { @@ -546,7 +546,7 @@ func (m *Mysql) Info() (*schema.Driver, error) { dct := dict.New() dct.Merge(map[string]string{ - "Subroutines": "Stored procedures and functions", + "Functions": "Stored procedures and functions", }) d := &schema.Driver{ diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index f28e64514..09c62f18c 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -297,11 +297,11 @@ ORDER BY tgrelid tables = append(tables, table) } - subroutines, err := p.getSubroutines() + functions, err := p.getFunctions() if err != nil { return err } - s.Subroutines = subroutines + s.Functions = functions s.Tables = tables @@ -371,7 +371,7 @@ ORDER BY tgrelid return nil } -const querySubroutines95 = `select n.nspname as schema_name, +const queryFunctions95 = `select n.nspname as schema_name, p.proname as specific_name, TEXT 'FUNCTION', t.typname as return_type, @@ -381,7 +381,7 @@ left join pg_namespace n on p.pronamespace = n.oid left join pg_type t on t.oid = p.prorettype where n.nspname not in ('pg_catalog', 'information_schema')` -const querySubroutines = `select n.nspname as schema_name, +const queryFunctions = `select n.nspname as schema_name, p.proname as specific_name, case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end, t.typname as return_type, @@ -415,35 +415,35 @@ func (p *Postgres) isProceduresSupported() (bool, error) { return false, nil } -func (p *Postgres) getSubroutines() ([]*schema.Subroutine, error) { - var subroutines []*schema.Subroutine +func (p *Postgres) getFunctions() ([]*schema.Function, error) { + var functions []*schema.Function storedProcedureSupported, err := p.isProceduresSupported() if err != nil { return nil, errors.WithStack(err) } if storedProcedureSupported { - subroutines, err = p.getSubroutinesByQuery(querySubroutines) + functions, err = p.getFunctionsByQuery(queryFunctions) if err != nil { return nil, errors.WithStack(err) } } else { - subroutines, err = p.getSubroutinesByQuery(querySubroutines95) + functions, err = p.getFunctionsByQuery(queryFunctions95) if err != nil { return nil, errors.WithStack(err) } } - return subroutines, nil + return functions, nil } -func (p *Postgres) getSubroutinesByQuery(query string) ([]*schema.Subroutine, error) { - subroutines := []*schema.Subroutine{} - subroutinesResult, err := p.db.Query(query) +func (p *Postgres) getFunctionsByQuery(query string) ([]*schema.Function, error) { + functions := []*schema.Function{} + functionsResult, err := p.db.Query(query) if err != nil { return nil, errors.WithStack(err) } - defer subroutinesResult.Close() + defer functionsResult.Close() - for subroutinesResult.Next() { + for functionsResult.Next() { var ( schemaName string name string @@ -451,20 +451,20 @@ func (p *Postgres) getSubroutinesByQuery(query string) ([]*schema.Subroutine, er returnType string arguments sql.NullString ) - err := subroutinesResult.Scan(&schemaName, &name, &typeValue, &returnType, &arguments) + err := functionsResult.Scan(&schemaName, &name, &typeValue, &returnType, &arguments) if err != nil { - return subroutines, errors.WithStack(err) + return functions, errors.WithStack(err) } - subroutine := &schema.Subroutine{ + function := &schema.Function{ Name: fullTableName(schemaName, name), Type: typeValue, ReturnType: returnType, Arguments: arguments.String, } - subroutines = append(subroutines, subroutine) + functions = append(functions, function) } - return subroutines, nil + return functions, nil } func fullTableName(owner string, tableName string) string { @@ -487,7 +487,7 @@ func (p *Postgres) Info() (*schema.Driver, error) { dct := dict.New() dct.Merge(map[string]string{ - "Subroutines": "Stored procedures and functions", + "Functions": "Stored procedures and functions", }) d := &schema.Driver{ diff --git a/output/md/md.go b/output/md/md.go index a22c187db..316641e21 100644 --- a/output/md/md.go +++ b/output/md/md.go @@ -491,7 +491,7 @@ func (m *Md) makeSchemaTemplateData(s *schema.Schema) map[string]interface{} { tablesSubroutineHeaderLine, ) - for _, t := range s.Subroutines { + for _, t := range s.Functions { data := []string{ t.Name, t.ReturnType, @@ -503,16 +503,16 @@ func (m *Md) makeSchemaTemplateData(s *schema.Schema) map[string]interface{} { if adjust { return map[string]interface{}{ - "Schema": s, - "Tables": adjustTable(tablesData), - "Subroutines": adjustTable(tablesSubroutineData), + "Schema": s, + "Tables": adjustTable(tablesData), + "Functions": adjustTable(tablesSubroutineData), } } return map[string]interface{}{ - "Schema": s, - "Tables": tablesData, - "Subroutines": tablesSubroutineData, + "Schema": s, + "Tables": tablesData, + "Functions": tablesSubroutineData, } } diff --git a/output/yaml/yaml_test.go b/output/yaml/yaml_test.go index 9554a98ff..d72183c5a 100644 --- a/output/yaml/yaml_test.go +++ b/output/yaml/yaml_test.go @@ -136,7 +136,7 @@ func newTestSchema() *schema.Schema { Relations: []*schema.Relation{ r, }, - Subroutines: []*schema.Subroutine{}, + Functions: []*schema.Function{}, Driver: &schema.Driver{ Name: "testdriver", DatabaseVersion: "1.0.0", diff --git a/schema/json.go b/schema/json.go index e3d624b67..3f8d54ea6 100644 --- a/schema/json.go +++ b/schema/json.go @@ -13,26 +13,26 @@ func (s Schema) MarshalJSON() ([]byte, error) { s.Relations = []*Relation{} } return json.Marshal(&struct { - Name string `json:"name"` - Desc string `json:"desc"` - Tables []*Table `json:"tables"` - Relations []*Relation `json:"relations"` - Subroutines []*Subroutine `json:"subroutines"` - Driver *Driver `json:"driver"` - Labels Labels `json:"labels,omitempty"` + Name string `json:"name"` + Desc string `json:"desc"` + Tables []*Table `json:"tables"` + Relations []*Relation `json:"relations"` + Functions []*Function `json:"functions"` + Driver *Driver `json:"driver"` + Labels Labels `json:"labels,omitempty"` }{ - Name: s.Name, - Desc: s.Desc, - Tables: s.Tables, - Relations: s.Relations, - Driver: s.Driver, - Subroutines: s.Subroutines, - Labels: s.Labels, + Name: s.Name, + Desc: s.Desc, + Tables: s.Tables, + Relations: s.Relations, + Driver: s.Driver, + Functions: s.Functions, + Labels: s.Labels, }) } // MarshalJSON return custom JSON byte -func (d Subroutine) MarshalJSON() ([]byte, error) { +func (d Function) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Name string `json:"name"` ReturnType string `json:"return_type"` diff --git a/schema/schema.go b/schema/schema.go index f95564eda..911b491cc 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -102,8 +102,8 @@ type DriverMeta struct { Dict *dict.Dict `json:"dict,omitempty"` } -// Subroutine is the struct for tbls stored procedure/function information -type Subroutine struct { +// Function is the struct for tbls stored procedure/function information +type Function struct { Name string `json:"name"` ReturnType string `json:"return_type" yaml:"returnType"` Arguments string `json:"arguments"` @@ -119,13 +119,13 @@ type Driver struct { // Schema is the struct for database schema type Schema struct { - Name string `json:"name"` - Desc string `json:"desc"` - Tables []*Table `json:"tables"` - Relations []*Relation `json:"relations"` - Subroutines []*Subroutine `json:"subroutines"` - Driver *Driver `json:"driver"` - Labels Labels `json:"labels,omitempty"` + Name string `json:"name"` + Desc string `json:"desc"` + Tables []*Table `json:"tables"` + Relations []*Relation `json:"relations"` + Functions []*Function `json:"functions"` + Driver *Driver `json:"driver"` + Labels Labels `json:"labels,omitempty"` } func (s *Schema) NormalizeTableName(name string) string { diff --git a/testdata/json_test_schema.json.golden b/testdata/json_test_schema.json.golden index 0eecdafc3..5f82a5a1a 100644 --- a/testdata/json_test_schema.json.golden +++ b/testdata/json_test_schema.json.golden @@ -67,7 +67,7 @@ "virtual": false } ], - "subroutines": null, + "functions": null, "driver": { "name": "testdriver", "database_version": "1.0.0", diff --git a/testdata/yaml_test_schema.yaml.golden b/testdata/yaml_test_schema.yaml.golden index 2d92c4b44..e10ce96e4 100644 --- a/testdata/yaml_test_schema.yaml.golden +++ b/testdata/yaml_test_schema.yaml.golden @@ -46,7 +46,7 @@ relations: - b def: "" virtual: false -subroutines: [] +functions: [] driver: name: testdriver databaseVersion: 1.0.0 From 8e115655f1aea69816eec59400b42f462ae8b6ec Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 21:37:52 -0500 Subject: [PATCH 24/36] build for custom branch --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd3d80f71..280a09ffc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - sp_and_functions pull_request: jobs: From f0a2289b0c6398cb58c6e3f9e09b057abbc14cea Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 21:43:57 -0500 Subject: [PATCH 25/36] non null result for json test schema --- output/json/json_test.go | 5 +++-- testdata/json_test_schema.json.golden | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/output/json/json_test.go b/output/json/json_test.go index ba116e1e0..851faba12 100644 --- a/output/json/json_test.go +++ b/output/json/json_test.go @@ -92,7 +92,7 @@ func newTestSchema() *schema.Schema { Comment: "table a", Columns: []*schema.Column{ ca, - &schema.Column{ + { Name: "a2", Type: "datetime", Comment: "column a2", @@ -110,7 +110,7 @@ func newTestSchema() *schema.Schema { Comment: "table b", Columns: []*schema.Column{ cb, - &schema.Column{ + { Name: "b2", Comment: "column b2", Type: "text", @@ -136,6 +136,7 @@ func newTestSchema() *schema.Schema { Relations: []*schema.Relation{ r, }, + Functions: []*schema.Function{}, Driver: &schema.Driver{ Name: "testdriver", DatabaseVersion: "1.0.0", diff --git a/testdata/json_test_schema.json.golden b/testdata/json_test_schema.json.golden index 5f82a5a1a..ed7eda750 100644 --- a/testdata/json_test_schema.json.golden +++ b/testdata/json_test_schema.json.golden @@ -67,7 +67,7 @@ "virtual": false } ], - "functions": null, + "functions": [], "driver": { "name": "testdriver", "database_version": "1.0.0", From 55d046a52e4ec53c8dc8230c822bd51e0a14828a Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 21:47:50 -0500 Subject: [PATCH 26/36] fix template --- output/md/templates/index.md.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/output/md/templates/index.md.tmpl b/output/md/templates/index.md.tmpl index 1d0cf7c6d..f26f97f09 100644 --- a/output/md/templates/index.md.tmpl +++ b/output/md/templates/index.md.tmpl @@ -17,10 +17,10 @@ {{ range $t := .Tables }} |{{ range $d := $t }} {{ $d | nl2br }} |{{ end }} {{- end -}} -{{- if .Schema.Subroutines }} +{{- if .Schema.Functions }} -## {{ "Subroutines" | lookup }} -{{ range $t := .Subroutines }} +## {{ "Functions" | lookup }} +{{ range $t := .Functions }} |{{ range $d := $t }} {{ $d | nl2br }} |{{ end }} {{- end -}} {{- end -}} From e47d996d6407e7ef66f61af8b8468cba327f921f Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 21:58:57 -0500 Subject: [PATCH 27/36] change reserver words style and small refactor --- drivers/mssql/mssql.go | 47 ++++++++++++++++++------------------ drivers/mysql/mysql.go | 31 +++++++++--------------- drivers/postgres/postgres.go | 36 +++++++++++++-------------- 3 files changed, 52 insertions(+), 62 deletions(-) diff --git a/drivers/mssql/mssql.go b/drivers/mssql/mssql.go index f753c3f8f..cdedee6fd 100644 --- a/drivers/mssql/mssql.go +++ b/drivers/mssql/mssql.go @@ -466,31 +466,30 @@ ORDER BY i.index_id return nil } -const query = `select schema_name(obj.schema_id) as schema_name, +const query = `SELECT SCHEMA_NAME(obj.schema_id) AS schema_name, obj.name as name, - case type - when 'FN' then 'SQL scalar function' - when 'TF' then 'SQL table-valued-function' - when 'IF' then 'SQL inline table-valued function' - when 'P' then 'SQL Stored Procedure' - when 'X' then 'Extended stored procedure' - end as type, - TYPE_NAME(ret.user_type_id) as return_type, - substring(par.parameters, 0, len(par.parameters)) as parameters -from sys.objects obj -join sys.sql_modules mod -on mod.object_id = obj.object_id -cross apply (select p.name + ' ' + TYPE_NAME(p.user_type_id) + ', ' - from sys.parameters p - where p.object_id = obj.object_id - and p.parameter_id != 0 - for xml path ('') ) par (parameters) -left join sys.parameters ret - on obj.object_id = ret.object_id - and ret.parameter_id = 0 -where obj.type in ('FN', 'TF', 'IF', 'P', 'X') -order by schema_name, - name;` + CASE type + WHEN 'FN' THEN 'SQL scalar function' + WHEN 'TF' THEN 'SQL table-valued-function' + WHEN 'IF' THEN 'SQL inline table-valued function' + WHEN 'P' THEN 'SQL Stored Procedure' + WHEN 'X' THEN 'Extended stored procedure' + END AS type, + TYPE_NAME(ret.user_type_id) AS return_type, + SUBSTRING(par.parameters, 0, LEN(par.parameters)) AS parameters +FROM sys.objects obj +JOIN sys.sql_modules mod +ON mod.object_id = obj.object_id +CROSS APPLY (select p.name + ' ' + TYPE_NAME(p.user_type_id) + ', ' + FROM sys.parameters p + WHERE p.object_id = obj.object_id + AND p.parameter_id != 0 + FOR XML PATH ('') ) par (parameters) +LEFT JOIN sys.parameters ret + ON obj.object_id = ret.object_id + AND ret.parameter_id = 0 +WHERE obj.type in ('FN', 'TF', 'IF', 'P', 'X') +OREDER BY schema_name, name;` func (m *Mssql) getFunctions() ([]*schema.Function, error) { functions := []*schema.Function{} diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index 1b130688f..bde720826 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -480,19 +480,17 @@ WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position` return nil } -const queryFunctions = `select r.routine_schema as database_name, +const queryFunctions = `SELECT r.routine_schema as database_name, r.routine_name, -r.routine_type as type, -r.data_type as return_type, -group_concat(CONCAT(p.parameter_name, ' ', p.data_type) separator '; ') as parameter -from information_schema.routines r -left join information_schema.parameters p - on p.specific_schema = r.routine_schema - and p.specific_name = r.specific_name -where routine_schema not in ('sys', 'information_schema', - 'mysql', 'performance_schema') -group by r.routine_schema, r.routine_name, -r.routine_type, r.data_type, r.routine_definition` +r.routine_type AS type, +r.data_type AS return_type, +GROUP_CONCAT(CONCAT(p.parameter_name, ' ', p.data_type) SEPARATOR '; ') AAS parameter +FROM information_schema.routines r +LEFT JOIN information_schema.parameters p + ON p.specific_schema = r.routine_schema + AND p.specific_name = r.specific_name +WHERE routine_schema NOT IN ('sys', 'information_schema', 'mysql', 'performance_schema') +GROUP BY r.routine_schema, r.routine_name, r.routine_type, r.data_type, r.routine_definition` func (m *Mysql) getFunctions() ([]*schema.Function, error) { functions := []*schema.Function{} @@ -526,10 +524,6 @@ func (m *Mysql) getFunctions() ([]*schema.Function, error) { return functions, nil } -func fullTableName(owner string, tableName string) string { - return fmt.Sprintf("%s.%s", owner, tableName) -} - // Info return schema.Driver func (m *Mysql) Info() (*schema.Driver, error) { var v string @@ -574,8 +568,5 @@ SELECT table_name, table_type, table_comment FROM information_schema.tables WHER } func convertColumnNullable(str string) bool { - if str == "NO" { - return false - } - return true + return str != "NO" } diff --git a/drivers/postgres/postgres.go b/drivers/postgres/postgres.go index 09c62f18c..2dc5c9ee3 100644 --- a/drivers/postgres/postgres.go +++ b/drivers/postgres/postgres.go @@ -371,25 +371,25 @@ ORDER BY tgrelid return nil } -const queryFunctions95 = `select n.nspname as schema_name, -p.proname as specific_name, +const queryFunctions95 = `SELECT n.nspname AS schema_name, +p.proname AS specific_name, TEXT 'FUNCTION', -t.typname as return_type, -pg_get_function_arguments(p.oid) as arguments +t.typname AS return_type, +pg_get_function_arguments(p.oid) AS arguments from pg_proc p -left join pg_namespace n on p.pronamespace = n.oid -left join pg_type t on t.oid = p.prorettype -where n.nspname not in ('pg_catalog', 'information_schema')` - -const queryFunctions = `select n.nspname as schema_name, -p.proname as specific_name, -case when p.prokind = 'p' then TEXT 'PROCEDURE' else case when p.prokind = 'f' then TEXT 'FUNCTION' else p.prokind end end, -t.typname as return_type, -pg_get_function_arguments(p.oid) as arguments -from pg_proc p -left join pg_namespace n on p.pronamespace = n.oid -left join pg_type t on t.oid = p.prorettype -where n.nspname not in ('pg_catalog', 'information_schema')` +LEFT JOIN pg_namespace n ON p.pronamespace = n.oid +LEFT JOIN pg_type t ON t.oid = p.prorettype +WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')` + +const queryFunctions = `SELECT n.nspname AS schema_name, +p.proname AS specific_name, +CASE WHEN p.prokind = 'p' THEN TEXT 'PROCEDURE' ELSE CASE WHEN p.prokind = 'f' THEN TEXT 'FUNCTION' ELSE p.prokind END END, +t.typname AS return_type, +pg_get_function_arguments(p.oid) AS arguments +FROM pg_proc p +LEFT JOIN pg_namespace n ON p.pronamespace = n.oid +LEFT JOIN pg_type t ON t.oid = p.prorettype +WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')` const queryStoredProcedureSupported = `SELECT column_name FROM information_schema.columns @@ -402,7 +402,7 @@ func (p *Postgres) isProceduresSupported() (bool, error) { } defer result.Close() - for result.Next() { + if result.Next() { var ( name sql.NullString ) From faa445f5a7c00445a23cf3855ad164a52f8ae750 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 22:08:53 -0500 Subject: [PATCH 28/36] fix query --- drivers/mysql/mysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mysql/mysql.go b/drivers/mysql/mysql.go index bde720826..434c379b3 100644 --- a/drivers/mysql/mysql.go +++ b/drivers/mysql/mysql.go @@ -484,7 +484,7 @@ const queryFunctions = `SELECT r.routine_schema as database_name, r.routine_name, r.routine_type AS type, r.data_type AS return_type, -GROUP_CONCAT(CONCAT(p.parameter_name, ' ', p.data_type) SEPARATOR '; ') AAS parameter +GROUP_CONCAT(CONCAT(p.parameter_name, ' ', p.data_type) SEPARATOR '; ') AS parameter FROM information_schema.routines r LEFT JOIN information_schema.parameters p ON p.specific_schema = r.routine_schema From 588ced15fb2a3a1f817eed1bfb2f7fb15dfca45e Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 22:17:29 -0500 Subject: [PATCH 29/36] fix query --- drivers/mssql/mssql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mssql/mssql.go b/drivers/mssql/mssql.go index cdedee6fd..0f5fafb0c 100644 --- a/drivers/mssql/mssql.go +++ b/drivers/mssql/mssql.go @@ -489,7 +489,7 @@ LEFT JOIN sys.parameters ret ON obj.object_id = ret.object_id AND ret.parameter_id = 0 WHERE obj.type in ('FN', 'TF', 'IF', 'P', 'X') -OREDER BY schema_name, name;` +ORDER BY schema_name, name;` func (m *Mssql) getFunctions() ([]*schema.Function, error) { functions := []*schema.Function{} From 7cb71c1a3e3bfb6d62bf935d3a694f26f962a043 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 22:28:43 -0500 Subject: [PATCH 30/36] fix missing keywords --- drivers/mssql/mssql.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mssql/mssql.go b/drivers/mssql/mssql.go index 0f5fafb0c..3de3b558f 100644 --- a/drivers/mssql/mssql.go +++ b/drivers/mssql/mssql.go @@ -480,7 +480,7 @@ const query = `SELECT SCHEMA_NAME(obj.schema_id) AS schema_name, FROM sys.objects obj JOIN sys.sql_modules mod ON mod.object_id = obj.object_id -CROSS APPLY (select p.name + ' ' + TYPE_NAME(p.user_type_id) + ', ' +CROSS APPLY (SELECT p.name + ' ' + TYPE_NAME(p.user_type_id) + ', ' FROM sys.parameters p WHERE p.object_id = obj.object_id AND p.parameter_id != 0 @@ -488,7 +488,7 @@ CROSS APPLY (select p.name + ' ' + TYPE_NAME(p.user_type_id) + ', ' LEFT JOIN sys.parameters ret ON obj.object_id = ret.object_id AND ret.parameter_id = 0 -WHERE obj.type in ('FN', 'TF', 'IF', 'P', 'X') +WHERE obj.type IN ('FN', 'TF', 'IF', 'P', 'X') ORDER BY schema_name, name;` func (m *Mssql) getFunctions() ([]*schema.Function, error) { From c4b02730fb40b241db219d7db9f148f411a2b16a Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 22:36:08 -0500 Subject: [PATCH 31/36] fix conflicts --- testdata/ddl/mssql.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testdata/ddl/mssql.sql b/testdata/ddl/mssql.sql index df80e2e4c..7654d2933 100644 --- a/testdata/ddl/mssql.sql +++ b/testdata/ddl/mssql.sql @@ -13,7 +13,7 @@ DROP TABLE IF EXISTS user_options; DROP TABLE IF EXISTS users; DROP SCHEMA IF EXISTS administrator; DROP FUNCTION IF EXISTS get_user; -DROP PROC IF EXISTS What_DB_is_that; +DROP PROC IF EXISTS "name with spaces"; CREATE TABLE users ( id int NOT NULL IDENTITY(1,1) PRIMARY KEY, @@ -178,6 +178,6 @@ RETURN WHERE u.id = @userid ); -CREATE PROC What_DB_is_that @ID INT +CREATE PROC "name with spaces" @ID INT AS SELECT DB_NAME(@ID) AS ThatDB; From 315231c7450b4b50e11c60840c910bcc2ebfc74a Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 22:37:45 -0500 Subject: [PATCH 32/36] fix conflicts --- testdata/ddl/mssql.sql | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/testdata/ddl/mssql.sql b/testdata/ddl/mssql.sql index 7654d2933..67d33714c 100644 --- a/testdata/ddl/mssql.sql +++ b/testdata/ddl/mssql.sql @@ -12,7 +12,6 @@ DROP TYPE IF EXISTS post_types; DROP TABLE IF EXISTS user_options; DROP TABLE IF EXISTS users; DROP SCHEMA IF EXISTS administrator; -DROP FUNCTION IF EXISTS get_user; DROP PROC IF EXISTS "name with spaces"; CREATE TABLE users ( @@ -168,16 +167,6 @@ BEGIN WHERE id = ( SELECT user_id FROM deleted) END; -CREATE FUNCTION get_user (@userid int) -RETURNS TABLE -AS -RETURN -( - SELECT u.username, u.email - FROM users AS u - WHERE u.id = @userid -); - CREATE PROC "name with spaces" @ID INT AS SELECT DB_NAME(@ID) AS ThatDB; From 412f8d96c639e69b2820dae3fe6167a033b2a8f1 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 22:51:59 -0500 Subject: [PATCH 33/36] Revert "fix conflicts" This reverts commit 315231c7450b4b50e11c60840c910bcc2ebfc74a. --- testdata/ddl/mssql.sql | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/testdata/ddl/mssql.sql b/testdata/ddl/mssql.sql index 39aafa990..fef547430 100644 --- a/testdata/ddl/mssql.sql +++ b/testdata/ddl/mssql.sql @@ -12,8 +12,9 @@ DROP TYPE IF EXISTS post_types; DROP TABLE IF EXISTS user_options; DROP TABLE IF EXISTS users; DROP SCHEMA IF EXISTS administrator; -DROP VIEW IF EXISTS "name with spaces"; - +DROP VIEW IF EXISTS "view name with spaces"; +DROP FUNCTION IF EXISTS get_user; +DROP PROC IF EXISTS "name with spaces"; CREATE TABLE users ( id int NOT NULL IDENTITY(1,1) PRIMARY KEY, @@ -168,7 +169,21 @@ BEGIN WHERE id = ( SELECT user_id FROM deleted) END; -CREATE VIEW "name with spaces" AS ( +CREATE VIEW "view name with spaces" AS ( SELECT TOP 1 p.title FROM posts AS p ); + +CREATE FUNCTION get_user (@userid int) +RETURNS TABLE +AS +RETURN +( + SELECT u.username, u.email + FROM users AS u + WHERE u.id = @userid +); + +CREATE PROC "name with spaces" @ID INT +AS +SELECT DB_NAME(@ID) AS ThatDB; From 6e82de9f80a7bcb659c92453904d4b85a873c448 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 23:01:57 -0500 Subject: [PATCH 34/36] fix build --- testdata/ddl/mssql.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testdata/ddl/mssql.sql b/testdata/ddl/mssql.sql index fef547430..f588eb419 100644 --- a/testdata/ddl/mssql.sql +++ b/testdata/ddl/mssql.sql @@ -12,9 +12,9 @@ DROP TYPE IF EXISTS post_types; DROP TABLE IF EXISTS user_options; DROP TABLE IF EXISTS users; DROP SCHEMA IF EXISTS administrator; -DROP VIEW IF EXISTS "view name with spaces"; +DROP VIEW IF EXISTS "name with spaces"; DROP FUNCTION IF EXISTS get_user; -DROP PROC IF EXISTS "name with spaces"; +DROP PROC IF EXISTS What_DB_is_that; CREATE TABLE users ( id int NOT NULL IDENTITY(1,1) PRIMARY KEY, @@ -184,6 +184,6 @@ RETURN WHERE u.id = @userid ); -CREATE PROC "name with spaces" @ID INT +CREATE PROC What_DB_is_that @ID INT AS SELECT DB_NAME(@ID) AS ThatDB; From 77a078a728361c645fc47deee8c5d368918dcef9 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 23:12:56 -0500 Subject: [PATCH 35/36] fix tests --- testdata/ddl/mssql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/ddl/mssql.sql b/testdata/ddl/mssql.sql index f588eb419..984c4d8d6 100644 --- a/testdata/ddl/mssql.sql +++ b/testdata/ddl/mssql.sql @@ -169,7 +169,7 @@ BEGIN WHERE id = ( SELECT user_id FROM deleted) END; -CREATE VIEW "view name with spaces" AS ( +CREATE VIEW "name with spaces" AS ( SELECT TOP 1 p.title FROM posts AS p ); From 86694de51c47ebacbd31be14c12baff251e90876 Mon Sep 17 00:00:00 2001 From: Yauhen Pyl Date: Mon, 25 Apr 2022 23:22:15 -0500 Subject: [PATCH 36/36] remove personal check --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca50167d3..ac548df40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,6 @@ on: push: branches: - main - - sp_and_functions pull_request: jobs: