Exemplo n.º 1
0
// GenerateSettings generates settings for the ddl package
func GenerateSettings(genName string, moduleName string, s *schema.Schema) schema.Generator {
	settings, ok := s.Generators.Get(genName)
	if !ok {
		settings = schema.Generator{}
	}
	settings.SetNX("databaseName", stringext.ToFieldName(moduleName))
	settings.SetNX("schemaName", stringext.ToFieldName(moduleName))
	settings.SetNX("tableName", stringext.ToFieldName(s.Title))
	settings.SetNX("roleName", stringext.ToFieldName(moduleName))

	// convert []interface to []string
	grants := settings.GetWithDefault("grants", []string{"ALL"})
	grantsI, ok := grants.([]interface{})
	grantsS := make([]string, 0)

	if ok {
		for _, t := range grantsI {
			grantsS = append(grantsS, t.(string))
		}
	} else {
		grantsS = grants.([]string)
	}

	settings.Set("grants", grantsS)

	return settings
}
Exemplo n.º 2
0
func TestSequence(t *testing.T) {
	s := &schema.Schema{}
	if err := json.Unmarshal([]byte(testdata.TestDataFull), s); err != nil {
		t.Fatal(err.Error())
	}

	s = s.Resolve(s)
	moduleName := strings.ToLower(s.Title)
	settings := GenerateSettings(GeneratorName, moduleName, s)

	index := 0
	for _, def := range s.Definitions {

		// schema should have our generator
		if !def.Generators.Has(GeneratorName) {
			continue
		}

		settingsDef := SetDefaultSettings(GeneratorName, settings, def)
		settingsDef.Set("tableName", stringext.ToFieldName(def.Title))

		sts, err := DefineSequence(settingsDef, def)
		if err != nil {
			t.Fatal(err.Error())
		}

		common.TestEquals(t, expectedSequences[index], string(sts))
		index++
	}
}
Exemplo n.º 3
0
// Generate generates the basic CRUD statements for the models
func (g *Generator) Generate(req *common.Req, res *common.Res) error {
	context := req.Context

	if context == nil || context.Config == nil || !common.IsIn(GeneratorName, context.Config.Generators...) {
		return nil
	}

	if req.Schema == nil {
		if req.SchemaStr == "" {
			return errors.New("both schema and string schema is not set")
		}

		s := &schema.Schema{}
		if err := json.Unmarshal([]byte(req.SchemaStr), s); err != nil {
			return err
		}

		req.Schema = s.Resolve(nil)
	}

	if req.Schema.Title == "" {
		return errors.New("Title should be set")
	}

	outputs := make([]common.Output, 0)

	moduleName := stringext.ToFieldName(req.Schema.Title)

	settings := GenerateSettings(GeneratorName, moduleName, req.Schema)
	settings.SetNX("rootPathPrefix", "db")
	rootPathPrefix := settings.Get("rootPathPrefix").(string)
	fullPathPrefix := req.Context.Config.Target + rootPathPrefix + "/"
	settings.Set("fullPathPrefix", fullPathPrefix)

	for _, name := range schema.SortedKeys(req.Schema.Definitions) {
		def := req.Schema.Definitions[name]

		// schema should have our generator
		if !def.Generators.Has(GeneratorName) {
			continue
		}

		settingsDef := SetDefaultSettings(GeneratorName, settings, def)
		settingsDef.Set("tableName", stringext.ToFieldName(def.Title))

		//
		// generate roles
		//
		role, err := DefineRole(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: role,
			Path: fmt.Sprintf(
				"%s/001-%s_roles.sql",
				fullPathPrefix,
				settingsDef.Get("databaseName").(string),
			),
			DoNotFormat: true,
		})

		//
		// generate database
		//
		db, err := DefineDatabase(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: db,
			Path: fmt.Sprintf(
				"%s/002-%s_database.sql",
				fullPathPrefix,
				settingsDef.Get("databaseName").(string),
			),
			DoNotFormat: true,
		})

		//
		// generate extenstions
		//
		extenstions, err := DefineExtensions(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: extenstions,
			Path: fmt.Sprintf(
				"%s/003-%s_extensions.sql",
				fullPathPrefix,
				settingsDef.Get("databaseName").(string)),
			DoNotFormat: true,
		})

		//
		// generate schema
		//
		sc, err := DefineSchema(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: sc,
			Path: fmt.Sprintf(
				"%s/%s/004-schema.sql",
				fullPathPrefix,
				settingsDef.Get("schemaName").(string),
			),
			DoNotFormat: true,
		})

		//
		// generate sequences
		//
		sequence, err := DefineSequence(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: sequence,
			Path: fmt.Sprintf(
				"%s/%s/005-%s-sequence.sql",
				fullPathPrefix,
				settingsDef.Get("schemaName").(string),
				settingsDef.Get("tableName").(string),
			),
			DoNotFormat: true,
		})

		//
		// generate types
		//
		types, err := DefineTypes(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: types,
			Path: fmt.Sprintf(
				"%s/%s/006-%s-types.sql",
				fullPathPrefix,
				settingsDef.Get("schemaName").(string),
				settingsDef.Get("tableName").(string),
			),
			DoNotFormat: true,
		})

		//
		// generate tables
		//
		table, err := DefineTable(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: table,
			Path: fmt.Sprintf(
				"%s/%s/007-%s-table.sql",
				fullPathPrefix,
				settingsDef.Get("schemaName").(string),
				settingsDef.Get("tableName").(string),
			),
			DoNotFormat: true,
		})

		//
		// generate constraints
		//
		constraints, err := DefineConstraints(settingsDef, def)
		if err != nil {
			return err
		}

		outputs = append(outputs, common.Output{
			Content: constraints,
			Path: fmt.Sprintf(
				"%s/%s/008-%s-constraints.sql",
				fullPathPrefix,
				settingsDef.Get("schemaName").(string),
				settingsDef.Get("tableName").(string),
			),
			DoNotFormat: true,
		})
	}

	res.Output = outputs
	return nil
}
Exemplo n.º 4
0
// DefineConstraints creates constraints definition for tables
func DefineConstraints(settings schema.Generator, s *schema.Schema) ([]byte, error) {
	primaryKeyConstraint := ""
	primaryKey := settings.Get("primaryKey")
	if primaryKey != nil {
		pmi := primaryKey.([]interface{})
		if len(pmi) > 0 {
			sl := make([]string, len(pmi))
			for i, pm := range pmi {
				sl[i] = stringext.ToFieldName(pm.(string))
			}

			primaryKeyConstraint = fmt.Sprintf(
				"ALTER TABLE %q.%q ADD PRIMARY KEY (%q) NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
				settings.Get("schemaName"),
				settings.Get("tableName"),
				strings.Join(sl, ", "),
			)
			primaryKeyConstraint = fmt.Sprintf("-------------------------------\n--  Primary key structure for table %s\n-- ----------------------------\n%s",
				settings.Get("tableName"),
				primaryKeyConstraint,
			)
		}
	}

	uniqueKeyConstraints := ""
	uniqueKeys := settings.Get("uniqueKeys")
	if uniqueKeys != nil {
		ukci := uniqueKeys.([]interface{})
		if len(ukci) > 0 {
			for _, ukc := range ukci {
				ukcs := ukc.([]interface{})
				ukcsps := make([]string, len(ukcs))
				for i, ukc := range ukcs {
					ukcsps[i] = stringext.ToFieldName(ukc.(string))
				}
				keyName := fmt.Sprintf(
					"%s_%s_%s",
					stringext.ToFieldName("key"),
					stringext.ToFieldName(settings.Get("tableName").(string)),
					strings.Join(ukcsps, "_"),
				)
				uniqueKeyConstraints += fmt.Sprintf(
					"ALTER TABLE %q.%q ADD CONSTRAINT %q UNIQUE (\"%s\") NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
					settings.Get("schemaName"),
					settings.Get("tableName"),
					keyName,
					strings.Join(ukcsps, "\", \""),
				)

			}
			uniqueKeyConstraints = fmt.Sprintf("-------------------------------\n--  Unique key structure for table %s\n-- ----------------------------\n%s",
				settings.Get("tableName"),
				uniqueKeyConstraints,
			)

		}
	}

	foreignKeyConstraints := ""
	foreignKeys := settings.Get("foreignKeys")
	if foreignKeys != nil {
		fkci := foreignKeys.([]interface{})
		if len(fkci) > 0 {
			for _, fkc := range fkci {
				fkcs := fkc.([]interface{})
				localField := stringext.ToFieldName(fkcs[0].(string))
				refFields := strings.Split(fkcs[1].(string), ".")
				if len(refFields) != 3 {
					return nil, fmt.Errorf("need schemaName.tableName.fieldName")
				}
				keyName := fmt.Sprintf(
					"%s_%s_%s",
					stringext.ToFieldName("fkey"),
					stringext.ToFieldName(settings.Get("tableName").(string)),
					localField,
				)

				foreignKeyConstraints += fmt.Sprintf(
					"ALTER TABLE %q.%q ADD CONSTRAINT %q FOREIGN KEY (\"%s\") REFERENCES %s.%s (%s) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
					settings.Get("schemaName"),
					settings.Get("tableName"),
					keyName,
					localField,
					stringext.ToFieldName(refFields[0]), // first item schema name
					stringext.ToFieldName(refFields[1]), // second item table name
					stringext.ToFieldName(refFields[2]), // third item field name

				)

				foreignKeyConstraints = fmt.Sprintf("-------------------------------\n--  Foreign keys structure for table %s\n-- ----------------------------\n%s",
					settings.Get("tableName"),
					foreignKeyConstraints,
				)
			}
		}
	}

	return clean([]byte(primaryKeyConstraint + uniqueKeyConstraints + foreignKeyConstraints)), nil
}
Exemplo n.º 5
0
// GenerateSQLField creates a definition line for a given coloumn
func GenerateSQLField(settings schema.Generator, s *schema.Schema) (res string) {
	propertyName := s.Title
	schemaName := settings.Get("schemaName").(string)
	tableName := settings.Get("tableName").(string)

	property := s

	fieldName := stringext.ToFieldName(propertyName) // transpiled version of property
	if property.Title != "" {
		fieldName = stringext.ToFieldName(property.Title)
	}

	fieldType := "" // will hold the type for coloumn

	switch strings.ToLower(property.Type.(string)) {
	case "boolean":
		fieldType = "BOOLEAN"
	case "string":
		switch property.Format {
		case "date-time":
			fieldType = "TIMESTAMP (6) WITH TIME ZONE"
		case "UUID":
			fieldType = "UUID"
		default:
			typeName := "TEXT"
			if property.MaxLength > 0 {
				// if schema defines a max length, no need to use text
				typeName = fmt.Sprintf("VARCHAR (%d)", property.MaxLength)
			}

			fieldType = fmt.Sprintf("%s COLLATE \"default\"", typeName)
		}
	case "number":
		fieldType = "NUMERIC"

		switch property.Format {
		case "int64", "uint64":
			fieldType = "BIGINT"
		case "integer", "int", "int32", "uint", "uint32":
			fieldType = "INTEGER"
		case "int8", "uint8", "int16", "uint16":
			fieldType = "SMALLINT"
		case "float32", "float64":
			fieldType = "NUMERIC"
		}
	case "any":
		panic("should specify type")
	case "array":
		panic("array not supported")
	case "object", "config":
		// TODO implement embedded struct table creation
		res = ""
	case "null":
		res = ""
	case "error":
		res = ""
	case "custom":
		res = ""
	default:
		panic("unknown field")
	}

	// override if it is an enum field
	if len(property.Enum) > 0 {
		fieldType = fmt.Sprintf(
			"%q.\"%s_%s_enum\"",
			schemaName,
			stringext.ToFieldName(tableName),
			stringext.ToFieldName(propertyName),
		)
	}

	res = fmt.Sprintf(
		"%q %s %s %s %s,",
		// first, name comes
		fieldName,
		// then type of the coloumn
		fieldType,
		//  generate default value if exists
		generateDefaultValue(schemaName, fieldName, tableName, property),
		// generate not null statement, if required
		generateNotNull(s, propertyName),
		// generate validators
		generateCheckStatements(tableName, fieldName, property),
	)

	return res
}