Skip to content

Commit dbf9dfa

Browse files
committed
add routines command
- it loads procedures from database and saves them to file for later use
1 parent 2dc8723 commit dbf9dfa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+171
-58
lines changed

.editorconfig

100644100755
File mode changed.

.github/workflows/go.yml

100644100755
File mode changed.

.github/workflows/release.yml

100644100755
File mode changed.

.gitignore

100644100755
File mode changed.

.idea/.gitignore

100644100755
File mode changed.

.idea/dataSources.xml

100644100755
File mode changed.

.idea/db-gen.iml

100644100755
File mode changed.

.idea/inspectionProfiles/Project_Default.xml

100644100755
File mode changed.

.idea/markdown.xml

100644100755
File mode changed.

.idea/modules.xml

100644100755
File mode changed.

.idea/sqldialects.xml

100644100755
File mode changed.

.idea/vcs.xml

100644100755
File mode changed.

CHANGELOG.md

100644100755
File mode changed.

README.md

100644100755
File mode changed.

cmd/generate.go

100644100755
Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,31 @@ import (
99
"log"
1010
)
1111

12+
const (
13+
keyDebug = "debug"
14+
keyConnectionString = "connectionString"
15+
keyConfig = "config"
16+
)
17+
1218
var generateCmd = &cobra.Command{
1319
Use: "generate",
1420
Short: "Generate code",
1521
Long: "Generate code for calling database stored procedures",
1622
Run: func(cmd *cobra.Command, args []string) {
17-
configLocation := viper.GetString("config")
23+
common.BindBoolFlag(cmd, keyDebug)
24+
common.BindStringFlag(cmd, keyConnectionString)
25+
common.BindStringFlag(cmd, keyConfig)
1826

19-
_, err := dbGen.ReadConfig(configLocation)
27+
_, err := dbGen.ReadConfig(viper.GetString(keyConfig))
2028
if err != nil {
21-
dbGen.Exit("configuration error: %s", err)
29+
common.Exit("configuration error: %s", err)
2230
}
2331

2432
viper.AutomaticEnv() // read in environment variables that match
2533

2634
err = doGenerate()
2735
if err != nil {
28-
dbGen.Exit(err.Error())
36+
common.Exit(err.Error())
2937
}
3038
},
3139
}
@@ -34,10 +42,9 @@ func init() {
3442
rootCmd.AddCommand(generateCmd)
3543

3644
// set cli flags
37-
common.ConfigurationBool(generateCmd, "debug", "d", false, "Print debug logs and create debug files")
38-
common.ConfigurationString(generateCmd, "connectionString", "s", "", "Connection string used to connect to database")
39-
common.ConfigurationString(generateCmd, "config", "c", "", "Path to configuration file")
40-
45+
common.DefineBoolFlag(generateCmd, keyDebug, "d", false, "Print debug logs and create debug files")
46+
common.DefineStringFlag(generateCmd, keyConnectionString, "s", "", "Connection string used to connect to database")
47+
common.DefineStringFlag(generateCmd, keyConfig, "c", "", "Path to configuration file")
4148
}
4249

4350
func doGenerate() error {
@@ -65,7 +72,7 @@ func doGenerate() error {
6572

6673
if config.Debug {
6774
common.LogDebug("Saving to debug file...")
68-
err = dbGen.SaveToTempFile(routines, "dbRoutines")
75+
err = common.SaveToTempFile(routines, "dbRoutines")
6976
if err != nil {
7077
return fmt.Errorf("error saving debug file: %s", err)
7178
}
@@ -80,7 +87,7 @@ func doGenerate() error {
8087

8188
if config.Debug {
8289
common.LogDebug("Saving to debug file...")
83-
err = dbGen.SaveToTempFile(processedFunctions, "mapped")
90+
err = common.SaveToTempFile(processedFunctions, "mapped")
8491
if err != nil {
8592
return fmt.Errorf("error saving debug file: %s", err)
8693
}

cmd/getRoutines.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"github.com/keenmate/db-gen/common"
6+
dbGen "github.com/keenmate/db-gen/src"
7+
"github.com/spf13/cobra"
8+
"github.com/spf13/viper"
9+
"log"
10+
)
11+
12+
var getRoutinesCmd = &cobra.Command{
13+
Use: "routines [out]",
14+
Short: "Get routines",
15+
Long: "Get routines from database to generate later",
16+
Run: func(cmd *cobra.Command, args []string) {
17+
common.BindBoolFlag(cmd, keyDebug)
18+
common.BindStringFlag(cmd, keyConnectionString)
19+
common.BindStringFlag(cmd, keyConfig)
20+
21+
configLocation := viper.GetString("config")
22+
23+
_, err := dbGen.ReadConfig(configLocation)
24+
if err != nil {
25+
common.Exit("configuration error: %s", err)
26+
}
27+
28+
log.Printf("arguments: %s", args)
29+
30+
viper.AutomaticEnv() // read in environment variables that match
31+
32+
err = doGetRoutines()
33+
34+
if err != nil {
35+
common.Exit(err.Error())
36+
}
37+
},
38+
}
39+
40+
func init() {
41+
rootCmd.AddCommand(getRoutinesCmd)
42+
43+
// set cli flags
44+
common.DefineBoolFlag(getRoutinesCmd, keyDebug, "d", false, "Print debug logs and create debug files")
45+
common.DefineStringFlag(getRoutinesCmd, keyConnectionString, "s", "", "Connection string used to connect to database")
46+
common.DefineStringFlag(getRoutinesCmd, keyConfig, "c", "", "Path to configuration file")
47+
}
48+
49+
func doGetRoutines() error {
50+
log.Printf("Getting configurations...")
51+
52+
config, err := dbGen.GetAndValidateConfig()
53+
if err != nil {
54+
return fmt.Errorf("error getting config %s", err)
55+
}
56+
57+
common.LogDebug("Debug logging is enabled")
58+
59+
log.Printf("Connecting to database...")
60+
conn, err := dbGen.Connect(config.ConnectionString)
61+
if err != nil {
62+
return fmt.Errorf("error connecting to database: %s", err)
63+
}
64+
65+
log.Printf("Getting routines...")
66+
routines, err := dbGen.GetRoutines(conn, config)
67+
if err != nil {
68+
return fmt.Errorf("error getting routines: %s", err)
69+
}
70+
71+
log.Printf("Saving %d routines...", len(routines))
72+
73+
// TODO show what routines changed
74+
75+
err = common.SaveAsJson(config.RoutinesFile, routines)
76+
if err != nil {
77+
return fmt.Errorf("error saving routines: %s", err)
78+
}
79+
log.Printf("File saved at %s", config.RoutinesFile)
80+
81+
return nil
82+
}

cmd/root.go

100644100755
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var rootCmd = &cobra.Command{
1414
Short: "Code generator for stored procedures and functions",
1515
Long: `DB-GEN by KEEN|MATE
1616
---------
17-
TODO better description
17+
For more information, see github.com/keenmate/db-gen
1818
`,
1919
}
2020

@@ -42,7 +42,6 @@ func init() {
4242

4343
}
4444

45-
// initConfig reads in config file and ENV variables if set.
4645
func initConfig() {
4746

4847
}

cmd/version.go

100644100755
File mode changed.

common/configuration.go

100644100755
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@ import (
55
"github.com/spf13/viper"
66
)
77

8-
func ConfigurationString(command *cobra.Command, key string, shorthand string, defaultValue string, usage string) {
8+
func DefineStringFlag(command *cobra.Command, key string, shorthand string, defaultValue string, usage string) {
99
command.Flags().StringP(key, shorthand, defaultValue, usage)
10-
_ = viper.BindPFlag(key, command.Flags().Lookup(key))
1110
}
12-
func ConfigurationBool(command *cobra.Command, key string, shorthand string, defaultValue bool, usage string) {
11+
12+
func DefineBoolFlag(command *cobra.Command, key string, shorthand string, defaultValue bool, usage string) {
1313
command.Flags().BoolP(key, shorthand, defaultValue, usage)
14+
}
15+
16+
// Due to bug/design flaw in viper, we need to bind flags only after we run function
17+
18+
func BindStringFlag(command *cobra.Command, key string) {
19+
_ = viper.BindPFlag(key, command.Flags().Lookup(key))
20+
}
21+
22+
func BindBoolFlag(command *cobra.Command, key string) {
1423
_ = viper.BindPFlag(key, command.Flags().Lookup(key))
1524
}

src/debugging.go renamed to common/debug.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
package dbGen
1+
package common
22

33
import (
44
"encoding/json"
5-
"github.com/keenmate/db-gen/common"
65
"os"
76
"path/filepath"
87
"time"
@@ -23,7 +22,7 @@ func SaveToTempFile(content interface{}, fileNamePrefix string) (err error) {
2322
}
2423

2524
filename := filepath.Join(tempFolder, time.Now().Format("2006-01-02-15-04-05")+"-"+fileNamePrefix+".json")
26-
common.LogDebug("Temp file saved: %s", filename)
25+
LogDebug("Temp file saved: %s", filename)
2726

2827
err = os.WriteFile(filename, saveJson, 0777)
2928
if err != nil {

common/fs.go

100644100755
Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
package common
22

33
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
47
"os"
58
"path/filepath"
69
)
710

811
func PathExists(path string) bool {
9-
if _, err := os.Stat(path); os.IsNotExist(err) {
12+
// this doesnt work work if some part of path does not exist
13+
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
14+
return false
15+
}
16+
return true
17+
}
18+
19+
func FileIsReadable(path string) bool {
20+
_, err := os.Stat(path)
21+
if err != nil {
1022
return false
1123
}
1224
return true
@@ -30,3 +42,20 @@ func RemoveContents(dir string) error {
3042
}
3143
return nil
3244
}
45+
46+
func SaveAsJson(path string, data interface{}) error {
47+
LogDebug("Saving data as json to %s", path)
48+
49+
// intent is not necessary, but will make our life easier
50+
saveJson, err := json.MarshalIndent(data, "", " ")
51+
if err != nil {
52+
return fmt.Errorf("converting data to json: %s", err)
53+
}
54+
55+
err = os.WriteFile(path, saveJson, 0777)
56+
if err != nil {
57+
return fmt.Errorf("writing file: %s", err)
58+
}
59+
60+
return nil
61+
}

common/helpers.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package common
2+
3+
import (
4+
"os"
5+
)
6+
7+
func Exit(template string, args ...any) {
8+
LogError(colorRed+template+colorReset, args...)
9+
os.Exit(1)
10+
}
11+
12+
func Contains[T comparable](s []T, e T) bool {
13+
for _, a := range s {
14+
if a == e {
15+
return true
16+
}
17+
}
18+
return false
19+
}

common/log.go

100644100755
File mode changed.

database/testing-db.sql

100644100755
File mode changed.

go.mod

100644100755
File mode changed.

go.sum

100644100755
File mode changed.

main.go

100644100755
File mode changed.

src/config.go

100644100755
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Config struct {
3030
GeneratedFileCase string `mapstructure:"GeneratedFileCase"`
3131
Debug bool `mapstructure:"Debug"`
3232
ClearOutputFolder bool `mapstructure:"ClearOutputFolder"`
33+
RoutinesFile string `mapstructure:"RoutinesFile"`
3334
Generate []SchemaConfig `mapstructure:"Generate"`
3435
Mappings []Mapping `mapstructure:"Mappings"`
3536
}
@@ -72,6 +73,7 @@ func GetAndValidateConfig() (*Config, error) {
7273
ClearOutputFolder: false,
7374
Generate: nil,
7475
Mappings: nil,
76+
RoutinesFile: "./db-gen-routines.json",
7577
}
7678

7779
err := viper.Unmarshal(config)
@@ -91,9 +93,10 @@ func GetAndValidateConfig() (*Config, error) {
9193
config.DbContextTemplate = joinIfRelative(config.PathBase, config.DbContextTemplate)
9294
config.ModelTemplate = joinIfRelative(config.PathBase, config.ModelTemplate)
9395
config.OutputFolder = joinIfRelative(config.PathBase, config.OutputFolder)
96+
config.RoutinesFile = joinIfRelative(config.PathBase, config.RoutinesFile)
9497
config.GeneratedFileCase = strings.ToLower(config.GeneratedFileCase)
9598

96-
if !contains(ValidCaseNormalized, config.GeneratedFileCase) {
99+
if !common.Contains(ValidCaseNormalized, config.GeneratedFileCase) {
97100
return nil, fmt.Errorf(" '%s' is not valid case (maybe GeneratedFileCase is missing)", config.GeneratedFileCase)
98101
}
99102

@@ -142,6 +145,8 @@ func ReadConfig(configLocation string) (string, error) {
142145
return configLocation, nil
143146
}
144147

148+
common.LogDebug("No configuration file set, trying default locations")
149+
145150
for _, defaultConfigPath := range defaultConfigPaths {
146151
fileExists, err := TryReadConfigFile(defaultConfigPath)
147152
if fileExists {
@@ -188,7 +193,8 @@ func TryReadLocalConfig(configLocation string) (bool, error) {
188193
func TryReadConfigFile(configPath string) (bool, error) {
189194
common.LogDebug("Trying to read config file: %s", configPath)
190195

191-
if !common.PathExists(configPath) {
196+
// TODO this could hide some usefull errors, maybe log the reason in debug mode
197+
if !common.FileIsReadable(configPath) {
192198
return false, nil
193199
}
194200

src/database.go

100644100755
File mode changed.

src/generator-functions.go

100644100755
File mode changed.

src/generator.go

100644100755
File mode changed.

src/helpers.go

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/preprocessor.go

100644100755
File mode changed.

src/types.go

100644100755
File mode changed.

src/version.go

100644100755
File mode changed.

testing/db-gen.json

100644100755
File mode changed.
File renamed without changes.

testing/templates/dbcontext.gotmpl

100644100755
File mode changed.

testing/templates/model.gotmpl

100644100755
File mode changed.

testing/templates/processor.gotmpl

100644100755
File mode changed.

version.txt

100644100755
File mode changed.

0 commit comments

Comments
 (0)