Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
ZelvaMan committed May 20, 2024
2 parents 8b1a331 + 83d1526 commit ba0a3ec
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 36 deletions.
12 changes: 1 addition & 11 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package cmd

import (
dbGen "github.com/keenmate/db-gen/dbGen"
"github.com/keenmate/db-gen/dbGen"
"github.com/spf13/cobra"
"os"
)

var cfgFile string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "db-gen",
Expand All @@ -32,14 +30,6 @@ func Execute(versionStringFile string) {

func init() {
cobra.OnInitialize(initConfig)

// Here you will define your generateCmdFlags and configuration settings.
// Cobra supports persistent generateCmdFlags, which, if defined here,
// will be global for your application.

//common.ConfigurationString(rootCmd, "config", "c", "", "Path to configuration file")
//common.ConfigurationBool(rootCmd, "debug", "d", false, "Print debug information")

}

func initConfig() {
Expand Down
2 changes: 1 addition & 1 deletion cmd/routines.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var getRoutinesCmd = &cobra.Command{

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

if args[0] != "" {
if len(args) > 0 && args[0] != "" {
viper.Set("routinesFile", args[0])
}

Expand Down
3 changes: 2 additions & 1 deletion dbGen/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type SchemaConfig struct {
type RoutineMapping struct {
Generate bool
MappedName string `mapstructure:"MappedName"`
DontSelectValue bool `mapstructure:"DontSelectValue"`
DontRetrieveValues bool `mapstructure:"DontRetrieveValues"`
SelectOnlySpecified bool `mapstructure:"SelectOnlySpecified"`
Model map[string]ColumnMapping `mapstructure:"Model"`
Parameters map[string]ParamMapping `mapstructure:"Parameters"`
Expand Down Expand Up @@ -120,6 +120,7 @@ func GetAndValidateConfig() (*Config, error) {
config.ModelTemplate = joinIfRelative(config.PathBase, config.ModelTemplate)
config.OutputFolder = joinIfRelative(config.PathBase, config.OutputFolder)
config.RoutinesFile = joinIfRelative(config.PathBase, config.RoutinesFile)

config.GeneratedFileCase = strings.ToLower(config.GeneratedFileCase)

if !common.Contains(ValidCaseNormalized, config.GeneratedFileCase) {
Expand Down
2 changes: 1 addition & 1 deletion dbGen/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func addParamsToRoutine(conn *common.DbConn, routine *DbRoutine) error {
where specific_schema = $1
and specific_name = $2
union
select c.ordinal_position::int, c.column_name::text, 'OUT', c.udt_name::text, c.column_default is not null
select c.ordinal_position::int, c.column_name::text, 'OUT', c.udt_name::text, c.is_nullable = 'YES'
from information_schema.columns c
where c.table_name = $3
and c.table_schema = coalesce($4, 'public')
Expand Down
39 changes: 24 additions & 15 deletions dbGen/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,32 @@ type effectiveParamMapping struct {
// TODO make configurable
const hiddenSchema = "public"

const fallbackMappingKey = "*"

// this data types represent structured data
var structuredTypes = []string{"record", "USER-DEFINED"}

// data types that represents no return types
var voidTypes = []string{"void"}

var emptyMapping = RoutineMapping{
Generate: true,
MappedName: "",
DontSelectValue: false,
DontRetrieveValues: false,
SelectOnlySpecified: false,
Model: make(map[string]ColumnMapping),
Parameters: make(map[string]ParamMapping),
}

func mapFunctions(routines *[]DbRoutine, globalTypeMappings *map[string]mapping, config *Config) ([]Routine, error) {
func mapRoutines(routines *[]DbRoutine, globalTypeMappings *map[string]mapping, config *Config) ([]Routine, error) {
mappedFunctions := make([]Routine, len(*routines))
schemaConfig := getSchemaConfigMap(config)

for i, routine := range *routines {
common.LogDebug("Mapping %s", routine.RoutineName)
routineMapping := getRoutineMapping(routine, schemaConfig)

returnProperties, err := mapModel(routine, globalTypeMappings, &routineMapping, config)
modelProperties, err := mapModel(routine, globalTypeMappings, &routineMapping, config)
if err != nil {
return nil, fmt.Errorf("processing function %s: %s", routine.RoutineName, err)
}
Expand All @@ -52,36 +57,37 @@ func mapFunctions(routines *[]DbRoutine, globalTypeMappings *map[string]mapping,
return nil, fmt.Errorf("processing function %s: %s", routine.RoutineName, err)
}

// default case for names is UpperCamelcase
functionName := getFunctionName(routine.RoutineName, routine.RoutineSchema, routineMapping.MappedName)
modelName := getModelName(functionName)
processorName := getProcessorName(functionName)

function := &Routine{
mappedRoutine := Routine{
FunctionName: functionName,
DbFullFunctionName: routine.RoutineSchema + "." + routine.RoutineName,
ModelName: modelName,
Parameters: parameters,
ReturnProperties: returnProperties,
ReturnProperties: modelProperties,
ProcessorName: processorName,
HasReturn: len(returnProperties) > 0,
HasReturn: len(modelProperties) > 0,
IsProcedure: routine.FuncType == Procedure,
Schema: routine.RoutineSchema,
DbFunctionName: routine.RoutineName,
}

mappedFunctions[i] = *function
mappedFunctions[i] = mappedRoutine
}

return mappedFunctions, nil
}

func mapModel(routine DbRoutine, globalTypeMappings *map[string]mapping, routineMapping *RoutineMapping, config *Config) ([]Property, error) {

returnParameters := make([]Property, 0)
modelProperties := make([]Property, 0)

//procedures in pg don't have return type
if routine.FuncType == Procedure || slices.Contains(voidTypes, routine.DataType) {
return returnParameters, nil
return modelProperties, nil
}

columns := routine.OutParameters
Expand Down Expand Up @@ -180,6 +186,7 @@ func mapParameters(attributes []DbParameter, typeMappings *map[string]mapping, r

return properties, nil
}

func getRoutineMapping(routine DbRoutine, schemaConfigs map[string]SchemaConfig) RoutineMapping {
schemaConfig, ok := schemaConfigs[routine.RoutineSchema]
if !ok {
Expand All @@ -200,7 +207,7 @@ func getRoutineMapping(routine DbRoutine, schemaConfigs map[string]SchemaConfig)
}

func getColumnMapping(param DbParameter, routineMapping *RoutineMapping, globalMappings *map[string]mapping, config *Config) (bool, *effectiveParamMapping, error) {
if routineMapping.DontSelectValue {
if routineMapping.DontRetrieveValues {
return false, nil, nil
}

Expand Down Expand Up @@ -228,7 +235,7 @@ func getColumnMapping(param DbParameter, routineMapping *RoutineMapping, globalM
}

if explicitMapping.MappedType != "" {
typeMapping, err = handleTypeMappingOverride(explicitMapping.MappedType, "", config)
typeMapping, err = handleTypeMappingOverride(explicitMapping.MappedType, explicitMapping.MappingFunction, config)
if err != nil {
return false, nil, err
}
Expand Down Expand Up @@ -313,11 +320,12 @@ func getProcessorName(functionName string) string {
return strcase.UpperCamelCase(functionName) + "Processor"
}

func getTypeMapping(dbDataType string, mappings *map[string]mapping) (*mapping, error) {
val, isFound := (*mappings)[dbDataType]
// getTypeMapping if explicit mapping doesnt exist, try fallback
func getTypeMapping(dbDataType string, globalTypesMappings *map[string]mapping) (*mapping, error) {
val, specificMappingExists := (*globalTypesMappings)[dbDataType]

if !isFound {
fallbackVal, fallbackExists := (*mappings)["*"]
if !specificMappingExists {
fallbackVal, fallbackExists := (*globalTypesMappings)[fallbackMappingKey]

if !fallbackExists {
return nil, fmt.Errorf("processing for dbType '%s' not found and fallback processing * is not set ", dbDataType)
Expand All @@ -332,6 +340,7 @@ func getTypeMapping(dbDataType string, mappings *map[string]mapping) (*mapping,
return &val, nil
}

// handleTypeMappingOverride used when parsing model and parameters when mappedType is set
func handleTypeMappingOverride(typeOverride string, mappingFunctionOverride string, config *Config) (*mapping, error) {
if mappingFunctionOverride != "" {
return &mapping{
Expand Down
2 changes: 1 addition & 1 deletion dbGen/processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Process(routines []DbRoutine, config *Config) ([]Routine, error) {
common.LogDebug("Got %d type mappings", len(typeMappings))

// Map routines
functions, err := mapFunctions(&filteredRoutines, &typeMappings, config)
functions, err := mapRoutines(&filteredRoutines, &typeMappings, config)

if err != nil {
log.Println("Error while processing functions")
Expand Down
10 changes: 5 additions & 5 deletions dbGen/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ func ParseBuildInformation(versionFileText string) error {
return nil
}

splitted := strings.Split(versionFileText, " ")
parts := strings.Split(versionFileText, " ")

if len(splitted) < 2 {
if len(parts) < 2 {
return fmt.Errorf("error with build, Version file has incorrect format ")
}

info = BuildInformation{
Builder: splitted[0],
Version: splitted[1],
CommitHash: splitted[2],
Builder: parts[0],
Version: parts[1],
CommitHash: parts[2],
}

return nil
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"github.com/keenmate/db-gen/cmd"
)

// due to the way go embed works, we can only embed file from same folder

//go:embed version.txt
var VersionFile string

Expand Down
2 changes: 1 addition & 1 deletion testing/db-gen.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"ignored": false,
"return_custom_type": {
"MappedName": "customName",
"SelectOnlySpecified": true,
"DontRetrieveValues": true,
"Model": {
"__number": {
"MappedType": "int",
Expand Down

0 comments on commit ba0a3ec

Please sign in to comment.