Skip to content

Commit

Permalink
look for local configuration with .local postfix
Browse files Browse the repository at this point in the history
  • Loading branch information
ZelvaMan committed Mar 21, 2024
1 parent 3edce90 commit 0beb945
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 25 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# CHANGELOG

## 0.3.4

### New features
- local config can have both `.local` postfix


## 0.3.1

Expand Down
54 changes: 37 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# db-gen - Language agnostic database function calls code generator for Enterprise use

db-gen is a universal tool for generation of function calls to PostgreSQL database.
db-gen is a universal tool for generation of function calls to PostgreSQL database.

## Is this tool an ORM framework?

No, this tool is not an ORM framework in sense of C# Entity Framework, Elixir Ecto, PHP Doctrine and so on. In our experience, these full ORM tools are not worth it, they are usually clumsy, generate inefficient SQL code and lead programmers to dead ends.
Typical example of inefficent database use is when you want a multi step processing of imported data. Instead of one bulk copy and a single database call to process the data, you have to split your logic to multiple database calls. It's slower, more work and usually less safe.
No, this tool is not an ORM framework in sense of C# Entity Framework, Elixir Ecto, PHP Doctrine and so on. In our experience, these full ORM tools are not
worth it, they are usually clumsy, generate inefficient SQL code and lead programmers to dead ends.
Typical example of inefficent database use is when you want a multi step processing of imported data. Instead of one bulk copy and a single database call to
process the data, you have to split your logic to multiple database calls. It's slower, more work and usually less safe.

That's why we use stored functions/procedures in PostgreSQL and this tool just generates code that calls these functions/procedures and retrieves the data.

## What issues this tool tries to address?

- consistency of generation over years
- in-house templates, in-house configuration
- customization based on your needs
Expand All @@ -19,26 +22,34 @@ Don't let the "Enterprise use" discourage you, there is no reason for not to use

## Consistency of generation over years

We all know what kind of world we live in. Tool that was available yesterday, won't be available tomorrow. Tool that was working with yesterday's framework, won't be working with tomorrow's.

We all know what kind of world we live in. Tool that was available yesterday, won't be available tomorrow. Tool that was working with yesterday's framework,
won't be working with tomorrow's.

This is NOT sustainable in enterprise development.

It's not like every application is constantly being updated and pushed to the latest version of every package. We have application that are untouched for years and years because of budget reasons. Why update them when they are running, right?
We used LLBLGen on several projects, but after just a few years we are unable to do that anymore, .NET framework was replace with another .NET framework and all is lost.

That's why this tool goes a different way. It's a small executable package that can be easily stored to the repository with your code. It will generate the same code today, tomorrow and in 5 years, and you won't have to search for it on internet.
It's not like every application is constantly being updated and pushed to the latest version of every package. We have application that are untouched for years
and years because of budget reasons. Why update them when they are running, right?
We used LLBLGen on several projects, but after just a few years we are unable to do that anymore, .NET framework was replace with another .NET framework and all
is lost.

That's why this tool goes a different way. It's a small executable package that can be easily stored to the repository with your code. It will generate the same
code today, tomorrow and in 5 years, and you won't have to search for it on internet.

## In-house templates, In-house configuration

All configuration, including templates used for code generation are part of the repository. Nothing depends on some service in internet, or a tool installation. Everything is under your control, versioned, easily updateable.
All configuration, including templates used for code generation are part of the repository. Nothing depends on some service in internet, or a tool installation.
Everything is under your control, versioned, easily updateable.

## Customization based on your needs

Since everything is under your control, as mentioned above, you can use whatever language, database package, logger and so on. Just update the template and you are done.
Since everything is under your control, as mentioned above, you can use whatever language, database package, logger and so on. Just update the template and you
are done.

## Offline use

In Enterprise development, it is often the case that your internet connection is limited, or there is none, in case of security sensitive projects you might not have internet at all. In case of digital nomads, you might be currently working in K2 2nd base camp. In all these cases you are covered, db-gen is self-contained executable, it needs nothing else than configuration and templates.
In Enterprise development, it is often the case that your internet connection is limited, or there is none, in case of security sensitive projects you might not
have internet at all. In case of digital nomads, you might be currently working in K2 2nd base camp. In all these cases you are covered, db-gen is
self-contained executable, it needs nothing else than configuration and templates.

## Known Limitations

Expand All @@ -60,11 +71,20 @@ ConnectionString can be also set with `--connectionString "postgresql://usernmae
### Local configuration

For some secret or user-specific configuration, you can use local config.
Db-gen looks for file with prefix `local.` or `.local.` to loaded configuration.
The file can override any settings specified in the configuration file
Db-gen looks for file with prefix `local.` or `.local.` to loaded configuration
or with postfix `.local`.

So if we load config at `./testing/db-gen.json`
it will look at

- `testing\local.db-gen.json`
- `testing\.local.db-gen.json`
- `testing\db-gen.local`
- `testing\db-gen.json.local`

The loaded configuration will override the values set in normal config file.

For example, if you load configuration from `./db-gen/config.json` it will check fi `./db-gen/local.config.json` exists
and if it does, it will load it.
The local config file is not required.

### Configuration overview

Expand Down
36 changes: 28 additions & 8 deletions src/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (

var defaultConfigPaths = []string{"./db-gen.json", "./db-gen/db-gen.json", "./db-gen/config.json"}

var possibleLocalPrefixes = []string{"local.", ".local."}
var localPrefixes = []string{"local.", ".local."}
var localPostfixes = []string{".local"}

type Config struct {
PathBase string //for now just using config folder
Expand Down Expand Up @@ -112,6 +113,8 @@ func joinIfRelative(basePath string, joiningPath string) string {
}

func ReadConfig(configLocation string) (string, error) {
// TODO refactor out duplicit code

// explicitly set configuration
if configLocation != "" {
fileExists, err := TryReadConfigFile(configLocation)
Expand Down Expand Up @@ -168,17 +171,13 @@ func ReadConfig(configLocation string) (string, error) {
}

func TryReadLocalConfig(configLocation string) (bool, error) {
folder := filepath.Dir(configLocation)
baseConfigFile := filepath.Base(configLocation)

common.LogDebug("Checking if local config exists")

for _, prefix := range possibleLocalPrefixes {
localConfigLocation := filepath.Join(folder, prefix+baseConfigFile)
exists, err := TryReadConfigFile(localConfigLocation)
for _, path := range getPossibleLocalConfigs(configLocation) {
exists, err := TryReadConfigFile(path)

if exists {
common.LogDebug("Local config at %s loaded", localConfigLocation)
common.LogDebug("Local config at %s loaded", path)
return exists, err
}
}
Expand Down Expand Up @@ -209,3 +208,24 @@ func TryReadConfigFile(configPath string) (bool, error) {

return true, nil
}

func getPossibleLocalConfigs(configLocation string) []string {
paths := make([]string, 0)

directory := filepath.Dir(configLocation)
file := filepath.Base(configLocation)
fileWithoutExtension := strings.TrimSuffix(file, filepath.Ext(configLocation))

// prefixes
for _, prefix := range localPrefixes {
paths = append(paths, filepath.Join(directory, prefix+file))
}

// postfixes
for _, postfix := range localPostfixes {
paths = append(paths, filepath.Join(directory, fileWithoutExtension+postfix))
paths = append(paths, filepath.Join(directory, file+postfix))
}

return paths
}
File renamed without changes.

0 comments on commit 0beb945

Please sign in to comment.