From 4f50b471c77ff33a5b1447170afcdd9956f8c35e Mon Sep 17 00:00:00 2001 From: KarnerTh Date: Fri, 1 Jul 2022 17:17:04 +0200 Subject: [PATCH] Sub query returns multiple entries (#9) * added debug flag and log messages * fix subquery issue for postgres; show column name in constraint * add test case for multiple pks * added new tables to get columns integration test * fix subquery for mysql * add flag for omitting the constraint labels * cleanup; updated changelog for new version --- Makefile | 2 +- analyzer/analyzer.go | 25 +++++++++++-- changelog.md | 13 +++++++ cmd/root.go | 12 +++++- config/config.go | 12 ++++++ database/database_integration_test.go | 33 +++++++++++++++- database/mysql.go | 8 +++- database/postgres.go | 54 ++++++++++++++------------- database/result.go | 1 + diagram/diagram.go | 17 +++++++-- diagram/diagram_data.go | 7 ++-- diagram/erd_template.gommd | 2 +- exampleRunConfig.yaml | 2 + go.mod | 2 + go.sum | 2 + mocks/MermerdConfig.go | 28 ++++++++++++++ readme.md | 12 ++++-- test/db-table-setup.sql | 16 ++++++++ 18 files changed, 203 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index a4b6829..00a7510 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -GIT_TAG := $(shell git describe --tags `git rev-list --tags --max-count=1`) +GIT_TAG := $(shell git describe --tags --abbrev=0) test_target := "./..." .PHONY: test-coverage diff --git a/analyzer/analyzer.go b/analyzer/analyzer.go index 8550770..998c86b 100644 --- a/analyzer/analyzer.go +++ b/analyzer/analyzer.go @@ -2,7 +2,8 @@ package analyzer import ( "errors" - + "github.com/sirupsen/logrus" + "github.com/KarnerTh/mermerd/config" "github.com/KarnerTh/mermerd/database" "github.com/KarnerTh/mermerd/util" @@ -81,11 +82,13 @@ func (a analyzer) GetSchema(db database.Connector) (string, error) { a.loadingSpinner.Start("Getting schemas") schemas, err := db.GetSchemas() a.loadingSpinner.Stop() - if err != nil { + logrus.Error("Getting schemas failed", " | ", err) return "", err } + logrus.WithField("count", len(schemas)).Info("Got schemas") + switch len(schemas) { case 0: return "", errors.New("no schemas available") @@ -103,10 +106,13 @@ func (a analyzer) GetTables(db database.Connector, selectedSchema string) ([]str a.loadingSpinner.Start("Getting tables") tables, err := db.GetTables(selectedSchema) + a.loadingSpinner.Stop() if err != nil { + logrus.Error("Getting tables failed", " | ", err) return nil, err } - a.loadingSpinner.Stop() + + logrus.WithField("count", len(tables)).Info("Got tables") if a.config.UseAllTables() { return tables, nil @@ -121,16 +127,29 @@ func (a analyzer) GetColumnsAndConstraints(db database.Connector, selectedTables for _, table := range selectedTables { columns, err := db.GetColumns(table) if err != nil { + logrus.Error("Getting columns failed", " | ", err) return nil, err } constraints, err := db.GetConstraints(table) if err != nil { + logrus.Error("Getting constraints failed", " | ", err) return nil, err } tableResults = append(tableResults, database.TableResult{TableName: table, Columns: columns, Constraints: constraints}) } a.loadingSpinner.Stop() + columnCount, constraintCount := getTableResultStats(tableResults) + logrus.WithFields(logrus.Fields{"columns": columnCount, "constraints": constraintCount}).Info("Got columns and constraints constraints") return tableResults, nil } + +func getTableResultStats(tableResults []database.TableResult) (columnCount int, constraintCount int) { + for _, tableResult := range tableResults { + columnCount += len(tableResult.Columns) + constraintCount += len(tableResult.Constraints) + } + + return columnCount, constraintCount +} diff --git a/changelog.md b/changelog.md index 6de0c31..02ef4ae 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (after version 0.0.5). +## [0.2.0] - 2022-06-01 +### Added +- A `--debug` flag/config to show debug information +- A `--omitConstraintLabels` flag/config to toggle the new constraint labels + +### Changed +- The column name is now displayed as the constraint label (can be switched off) + +### Fixed +- Sub query for constraints returned multiple items ([Issue #8](https://github.com/KarnerTh/mermerd/issues/8)) + ## [0.1.0] - 2022-04-15 ### Added - Mermerd is available via the go tools @@ -55,6 +66,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (after version 0.0 ### Added - Initial release of mermerd +[0.2.0]: https://github.com/KarnerTh/mermerd/releases/tag/v0.2.0 + [0.1.0]: https://github.com/KarnerTh/mermerd/releases/tag/v0.1.0 [0.0.5]: https://github.com/KarnerTh/mermerd/releases/tag/v0.0.5 diff --git a/cmd/root.go b/cmd/root.go index 4b841ef..2c46bb9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,9 +2,11 @@ package cmd import ( "fmt" + "io/ioutil" "os" "github.com/fatih/color" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -29,16 +31,18 @@ var rootCmd = &cobra.Command{ analyzer := analyzer.NewAnalyzer(config, connectorFactory, questioner) diagram := diagram.NewDiagram(config) + if !config.Debug() { + logrus.SetOutput(ioutil.Discard) + } + result, err := analyzer.Analyze() if err != nil { - fmt.Println(err.Error()) util.ShowError() os.Exit(1) } err = diagram.Create(result) if err != nil { - fmt.Println(err.Error()) util.ShowError() os.Exit(1) } @@ -59,6 +63,8 @@ func init() { rootCmd.Flags().StringVar(&runConfig, "runConfig", "", "run configuration (replaces global configuration)") rootCmd.Flags().Bool(config.ShowAllConstraintsKey, false, "show all constraints, even though the table of the resulting constraint was not selected") rootCmd.Flags().Bool(config.UseAllTablesKey, false, "use all available tables") + rootCmd.Flags().Bool(config.DebugKey, false, "show debug logs") + rootCmd.Flags().Bool(config.OmitConstraintLabelsKey, false, "omit the constraint labels") rootCmd.Flags().BoolP(config.EncloseWithMermaidBackticksKey, "e", false, "enclose output with mermaid backticks (needed for e.g. in markdown viewer)") rootCmd.Flags().StringP(config.ConnectionStringKey, "c", "", "connection string that should be used") rootCmd.Flags().StringP(config.SchemaKey, "s", "", "schema that should be used") @@ -66,6 +72,8 @@ func init() { bindFlagToViper(config.ShowAllConstraintsKey) bindFlagToViper(config.UseAllTablesKey) + bindFlagToViper(config.DebugKey) + bindFlagToViper(config.OmitConstraintLabelsKey) bindFlagToViper(config.EncloseWithMermaidBackticksKey) bindFlagToViper(config.ConnectionStringKey) bindFlagToViper(config.SchemaKey) diff --git a/config/config.go b/config/config.go index b059f39..aae53b3 100644 --- a/config/config.go +++ b/config/config.go @@ -11,6 +11,8 @@ const ( ConnectionStringSuggestionsKey = "connectionStringSuggestions" OutputFileNameKey = "outputFileName" EncloseWithMermaidBackticksKey = "encloseWithMermaidBackticks" + DebugKey = "debug" + OmitConstraintLabelsKey = "omitConstraintLabels" ) type config struct{} @@ -24,6 +26,8 @@ type MermerdConfig interface { ConnectionStringSuggestions() []string SelectedTables() []string EncloseWithMermaidBackticks() bool + Debug() bool + OmitConstraintLabels() bool } func NewConfig() MermerdConfig { @@ -61,3 +65,11 @@ func (c config) SelectedTables() []string { func (c config) EncloseWithMermaidBackticks() bool { return viper.GetBool(EncloseWithMermaidBackticksKey) } + +func (c config) Debug() bool { + return viper.GetBool(DebugKey) +} + +func (c config) OmitConstraintLabels() bool { + return viper.GetBool(OmitConstraintLabelsKey) +} diff --git a/database/database_integration_test.go b/database/database_integration_test.go index 2311fe5..c3ca66d 100644 --- a/database/database_integration_test.go +++ b/database/database_integration_test.go @@ -71,7 +71,15 @@ func TestDatabaseIntegrations(t *testing.T) { tables, err := connector.GetTables(schema) // Assert - expectedResult := []string{"article", "article_detail", "article_comment", "label", "article_label"} + expectedResult := []string{ + "article", + "article_detail", + "article_comment", + "label", + "article_label", + "test_1_a", + "test_1_b", + } assert.Nil(t, err) assert.ElementsMatch(t, expectedResult, tables) }) @@ -87,6 +95,8 @@ func TestDatabaseIntegrations(t *testing.T) { {tableName: "article_comment", expectedColumns: []string{"id", "article_id", "comment"}}, {tableName: "label", expectedColumns: []string{"id", "label"}}, {tableName: "article_label", expectedColumns: []string{"article_id", "label_id"}}, + {tableName: "test_1_a", expectedColumns: []string{"id", "xid"}}, + {tableName: "test_1_b", expectedColumns: []string{"aid", "bid"}}, } for index, testCase := range testCases { @@ -156,12 +166,33 @@ func TestDatabaseIntegrations(t *testing.T) { for _, item := range constraintResults { if item.FkTable == fkTableName { constraint = &item + break } } assert.NotNil(t, constraint) assert.True(t, constraint.IsPrimary) assert.True(t, constraint.HasMultiplePK) }) + + // Multiple primary keys (https://github.com/KarnerTh/mermerd/issues/8) + t.Run("Test 1 (Issue #8)", func(t *testing.T) { + // Arrange + pkTableName := "test_1_b" + + // Act + constraintResults, err := connector.GetConstraints(pkTableName) + + // Assert + assert.Nil(t, err) + assert.NotNil(t, constraintResults) + assert.Len(t, constraintResults, 2) + assert.True(t, constraintResults[0].IsPrimary) + assert.True(t, constraintResults[0].HasMultiplePK) + assert.Equal(t, constraintResults[0].ColumnName, "aid") + assert.True(t, constraintResults[1].IsPrimary) + assert.True(t, constraintResults[1].HasMultiplePK) + assert.Equal(t, constraintResults[1].ColumnName, "bid") + }) }) }) } diff --git a/database/mysql.go b/database/mysql.go index 7c33a2e..27b9dc5 100644 --- a/database/mysql.go +++ b/database/mysql.go @@ -109,13 +109,14 @@ func (c mySqlConnector) GetConstraints(tableName string) ([]ConstraintResult, er select c.TABLE_NAME, c.REFERENCED_TABLE_NAME, c.CONSTRAINT_NAME, + kcu.COLUMN_NAME, ( select kc2.CONSTRAINT_NAME is not null "isPrimary" from information_schema.KEY_COLUMN_USAGE kc left join information_schema.KEY_COLUMN_USAGE kc2 ON kc.COLUMN_NAME = kc2.COLUMN_NAME AND kc2.CONSTRAINT_NAME = 'PRIMARY' AND kc2.TABLE_NAME = kc.TABLE_NAME - where kc.CONSTRAINT_NAME = c.CONSTRAINT_NAME + where kc.CONSTRAINT_NAME = c.CONSTRAINT_NAME and kc.COLUMN_NAME = kcu.COLUMN_NAME ) "isPrimary", ( select COUNT(*) > 1 @@ -124,6 +125,7 @@ func (c mySqlConnector) GetConstraints(tableName string) ([]ConstraintResult, er and kc.CONSTRAINT_NAME = 'PRIMARY' ) "hasMultiplePk" from information_schema.REFERENTIAL_CONSTRAINTS c + inner join information_schema.KEY_COLUMN_USAGE kcu on c.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME where c.TABLE_NAME = ? or c.REFERENCED_TABLE_NAME = ? `, tableName, tableName) if err != nil { @@ -133,9 +135,11 @@ func (c mySqlConnector) GetConstraints(tableName string) ([]ConstraintResult, er var constraints []ConstraintResult for rows.Next() { var constraint ConstraintResult - err = rows.Scan(&constraint.FkTable, + err = rows.Scan( + &constraint.FkTable, &constraint.PkTable, &constraint.ConstraintName, + &constraint.ColumnName, &constraint.IsPrimary, &constraint.HasMultiplePK, ) diff --git a/database/postgres.go b/database/postgres.go index 4ffe133..6511ceb 100644 --- a/database/postgres.go +++ b/database/postgres.go @@ -106,32 +106,33 @@ func (c postgresConnector) GetColumns(tableName string) ([]ColumnResult, error) func (c postgresConnector) GetConstraints(tableName string) ([]ConstraintResult, error) { rows, err := c.db.Query(` - select distinct fk.table_name, - pk.table_name, - c.constraint_name, - coalesce( - (select tc.constraint_type is not null "isPrimary" - from information_schema.key_column_usage kc - inner join information_schema.key_column_usage kc2 - ON kc2.column_name = kc.column_name and kc2.table_name = kc.table_name - inner join information_schema.table_constraints tc - on kc2.constraint_name = tc.constraint_name and - tc.constraint_type = 'PRIMARY KEY' - where kc.constraint_name = c.constraint_name) - , false) "isPrimary", - ( - select COUNT(*) > 1 "hasMultiplePk" - from information_schema.table_constraints tc - -- one constraint can have multiple columns - inner join information_schema.key_column_usage kc - on kc.constraint_name = tc.constraint_name - where tc.table_name = fk.table_name - and tc.constraint_type = 'PRIMARY KEY' - ) - from information_schema.referential_constraints c - inner join information_schema.table_constraints fk on c.constraint_name = fk.constraint_name - inner join information_schema.table_constraints pk on c.unique_constraint_name = pk.constraint_name - where fk.table_name = $1 or pk.table_name = $1 + select fk.table_name, + pk.table_name, + c.constraint_name, + kcu.column_name, + coalesce( + (select tc.constraint_type is not null "isPrimary" + from information_schema.key_column_usage kc + inner join information_schema.key_column_usage kc2 + ON kc2.column_name = kc.column_name and kc2.table_name = kc.table_name + inner join information_schema.table_constraints tc + on kc2.constraint_name = tc.constraint_name and + tc.constraint_type = 'PRIMARY KEY' + where kc.constraint_name = c.constraint_name + and kc.column_name = kcu.column_name) + , false) "isPrimary", + (select COUNT(*) > 1 "hasMultiplePk" + from information_schema.table_constraints tc + -- one constraint can have multiple columns + inner join information_schema.key_column_usage kc + on kc.constraint_name = tc.constraint_name + where tc.table_name = fk.table_name + and tc.constraint_type = 'PRIMARY KEY') + from information_schema.referential_constraints c + inner join information_schema.table_constraints fk on c.constraint_name = fk.constraint_name + inner join information_schema.table_constraints pk on c.unique_constraint_name = pk.constraint_name + inner join information_schema.key_column_usage kcu on c.constraint_name = kcu.constraint_name + where fk.table_name = $1 or pk.table_name = $1; `, tableName) if err != nil { return nil, err @@ -144,6 +145,7 @@ func (c postgresConnector) GetConstraints(tableName string) ([]ConstraintResult, &constraint.FkTable, &constraint.PkTable, &constraint.ConstraintName, + &constraint.ColumnName, &constraint.IsPrimary, &constraint.HasMultiplePK, ) diff --git a/database/result.go b/database/result.go index a99c2de..b1415f1 100644 --- a/database/result.go +++ b/database/result.go @@ -20,6 +20,7 @@ type ConstraintResult struct { FkTable string PkTable string ConstraintName string + ColumnName string IsPrimary bool HasMultiplePK bool } diff --git a/diagram/diagram.go b/diagram/diagram.go index c15b906..c8442bf 100644 --- a/diagram/diagram.go +++ b/diagram/diagram.go @@ -4,6 +4,8 @@ import ( "os" "text/template" + "github.com/sirupsen/logrus" + "github.com/KarnerTh/mermerd/config" "github.com/KarnerTh/mermerd/database" ) @@ -23,6 +25,7 @@ func NewDiagram(config config.MermerdConfig) Diagram { func (d diagram) Create(result *database.Result) error { f, err := os.Create(d.config.OutputFileName()) if err != nil { + logrus.Error("Could not create output file", " | ", err) return err } @@ -30,6 +33,7 @@ func (d diagram) Create(result *database.Result) error { tmpl, err := template.ParseFiles("diagram/erd_template.gommd") if err != nil { + logrus.Error("Could not load template file", " | ", err) return err } @@ -59,10 +63,16 @@ func (d diagram) Create(result *database.Result) error { continue } + constraintLabel := constraint.ColumnName + if d.config.OmitConstraintLabels() { + constraintLabel = "" + } + constraints = append(constraints, ErdConstraintData{ - PkTableName: constraint.PkTable, - FkTableName: constraint.FkTable, - Relation: getRelation(constraint), + PkTableName: constraint.PkTable, + FkTableName: constraint.FkTable, + Relation: getRelation(constraint), + ConstraintLabel: constraintLabel, }) } @@ -73,6 +83,7 @@ func (d diagram) Create(result *database.Result) error { } if err = tmpl.Execute(f, diagramData); err != nil { + logrus.Error("Could not create diagram", " | ", err) return err } return nil diff --git a/diagram/diagram_data.go b/diagram/diagram_data.go index e20a354..5c13654 100644 --- a/diagram/diagram_data.go +++ b/diagram/diagram_data.go @@ -24,7 +24,8 @@ type ErdColumnData struct { } type ErdConstraintData struct { - PkTableName string - FkTableName string - Relation ErdRelationType + PkTableName string + FkTableName string + Relation ErdRelationType + ConstraintLabel string } diff --git a/diagram/erd_template.gommd b/diagram/erd_template.gommd index 302152f..85a801f 100644 --- a/diagram/erd_template.gommd +++ b/diagram/erd_template.gommd @@ -9,6 +9,6 @@ erDiagram {{end -}} {{range .Constraints}} - {{.FkTableName}} {{.Relation}} {{.PkTableName}} : "" + {{.FkTableName}} {{.Relation}} {{.PkTableName}} : "{{.ConstraintLabel}}" {{- end}} {{if .EncloseWithMermaidBackticks}}```{{end -}} diff --git a/exampleRunConfig.yaml b/exampleRunConfig.yaml index 465fb34..dde3d7d 100644 --- a/exampleRunConfig.yaml +++ b/exampleRunConfig.yaml @@ -12,3 +12,5 @@ selectedTables: showAllConstraints: true outputFileName: "my-db.mmd" encloseWithMermaidBackticks: false +debug: false +omitConstraintLabels: false diff --git a/go.mod b/go.mod index aca14fa..caf660e 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/fatih/color v1.13.0 github.com/go-sql-driver/mysql v1.6.0 github.com/jackc/pgx/v4 v4.16.1 + github.com/sirupsen/logrus v1.4.2 github.com/spf13/cobra v1.4.0 github.com/spf13/viper v1.11.0 github.com/stretchr/testify v1.7.1 @@ -26,6 +27,7 @@ require ( github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect github.com/jackc/pgtype v1.11.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect diff --git a/go.sum b/go.sum index 9e6250a..c1b6a86 100644 --- a/go.sum +++ b/go.sum @@ -205,6 +205,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -259,6 +260,7 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= diff --git a/mocks/MermerdConfig.go b/mocks/MermerdConfig.go index 776568b..06dc710 100644 --- a/mocks/MermerdConfig.go +++ b/mocks/MermerdConfig.go @@ -39,6 +39,20 @@ func (_m *MermerdConfig) ConnectionStringSuggestions() []string { return r0 } +// Debug provides a mock function with given fields: +func (_m *MermerdConfig) Debug() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // EncloseWithMermaidBackticks provides a mock function with given fields: func (_m *MermerdConfig) EncloseWithMermaidBackticks() bool { ret := _m.Called() @@ -53,6 +67,20 @@ func (_m *MermerdConfig) EncloseWithMermaidBackticks() bool { return r0 } +// OmitConstraintLabels provides a mock function with given fields: +func (_m *MermerdConfig) OmitConstraintLabels() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // OutputFileName provides a mock function with given fields: func (_m *MermerdConfig) OutputFileName() string { ret := _m.Called() diff --git a/readme.md b/readme.md index dc36237..da41791 100644 --- a/readme.md +++ b/readme.md @@ -65,8 +65,10 @@ via `mermerd -h` ``` -c, --connectionString string connection string that should be used + --debug show debug logs -e, --encloseWithMermaidBackticks enclose output with mermaid backticks (needed for e.g. in markdown viewer) -h, --help help for mermerd + --omitConstraintLabels omit the constraint labels -o, --outputFileName string output file name (default "result.mmd") --runConfig string run configuration (replaces global configuration) -s, --schema string schema that should be used @@ -88,6 +90,8 @@ provide connection string suggestions for the cli. showAllConstraints: true encloseWithMermaidBackticks: true outputFileName: "my-db.mmd" +debug: false +omitConstraintLabels: false # These connection strings are available as suggestions in the cli (use tab to access) connectionStringSuggestions: @@ -102,7 +106,7 @@ shown below) and start mermerd via `mermerd --runConfig yourRunConfig.yaml` ```yaml # Connection properties -connectionString: "postgresql://user:password@localhost:5432/dvdrental" +connectionString: "postgresql://user:password@localhost:5432/yourDb" schema: "public" # Define what tables should be used @@ -116,6 +120,8 @@ selectedTables: showAllConstraints: true encloseWithMermaidBackticks: true outputFileName: "my-db.mmd" +debug: true +omitConstraintLabels: true ``` ## Example usages @@ -131,10 +137,10 @@ mermerd --showAllConstraints mermerd --runConfig yourRunConfig.yaml # specify all connection properties so that only the table selection is done via the interactive cli -mermerd -c "postgresql://user:password@localhost:5432/dvdrental" -s public +mermerd -c "postgresql://user:password@localhost:5432/yourDb" -s public # same as previous one, but use all available tables without interaction -mermerd -c "postgresql://user:password@localhost:5432/dvdrental" -s public --useAllTables +mermerd -c "postgresql://user:password@localhost:5432/yourDb" -s public --useAllTables ``` ## Connection strings diff --git a/test/db-table-setup.sql b/test/db-table-setup.sql index d08585b..57806c3 100644 --- a/test/db-table-setup.sql +++ b/test/db-table-setup.sql @@ -44,3 +44,19 @@ alter table article_label add constraint fk_article_label_label_id foreign key (label_id) references label (id); alter table article_label add primary key (article_id, label_id); + +-- Test case for https://github.com/KarnerTh/mermerd/issues/8 +CREATE TABLE test_1_a +( + id int, + xid int, + PRIMARY KEY (id, xid) +); + +CREATE TABLE test_1_b +( + aid int, + bid int, + PRIMARY KEY (aid, bid), + FOREIGN KEY (aid, bid) REFERENCES test_1_a (id, xid) +); \ No newline at end of file