Skip to content

Commit 61ac4f4

Browse files
committed
Separated the pattern and template logic, improved performance
1 parent 14dd79b commit 61ac4f4

File tree

15 files changed

+128
-288
lines changed

15 files changed

+128
-288
lines changed

CHANGELOG.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12-
- Field `template` in the `string` data type now not only specifies the pattern,
13-
but also allows you to use the values of any columns of the generated model.
12+
- The `template` field in the `string` data type is now used to generate template strings
13+
with the ability to use the values of any columns of the generated model.
1414

1515
### Breaking changes
1616

17-
- The old version of string template in `type_params` of `string` type is no longer supported,
18-
`{{ "pattern_expression" | pattern }}` should be used instead.
17+
- Using `template` field to specify a string pattern like `Aa0#` is no longer supported,
18+
`pattern` should be used instead.
1919

2020
## [0.0.1](https://github.com/tarantool/sdvg/compare/36d0930..0.0.1) - 2025-07-21
2121

doc/en/usage.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,11 @@ Structure `models[*].columns[*].type_params` for data type `string`:
158158
- `min_length`: Minimum string length. Default is `1`.
159159
- `max_length`: Maximum string length. Default is `32`.
160160
- `logical_type`: Logical type of string. Supported values: `first_name`, `last_name`, `phone`, `text`.
161-
- `template`: Template for string generation. Allows you to use the values of any columns of the generated model and
162-
specify the pattern of the string using the `pattern` function. Information about the functions
163-
available in template strings is described at the end of this section.
161+
- `template`: Template for string generation. Allows you to use the values of any columns of the generated model.
162+
Information about the functions available in template strings is described at the end of this section.
163+
Cannot coexist with `ordered`, `distinct_percentage` or `distinct_count`.
164+
- `pattern`: Pattern for string generation. The `A` symbol is any capital letter, the `a` symbol is any small letter,
165+
symbol `0` is any digit, the `#` symbol is any character, and the other characters remain as they are.
164166
- `locale`: Locale for generated strings. Supported values: `ru`, `en`. Default is `en`.
165167
- `without_large_letters`: Flag indicating if uppercase letters should be excluded from the string.
166168
- `without_small_letters`: Flag indicating if lowercase letters should be excluded from the string.
@@ -253,20 +255,16 @@ Function calls:
253255
- direct call: `{{ upper .name }}`.
254256
- using pipe: `{{ .name | upper }}`.
255257

256-
In addition to standard functions, the project provides `5` custom functions:
258+
In addition to standard functions, the project provides `4` custom functions:
257259

258-
- `pattern`: allows you to create a string pattern using special characters.
259-
The `A` symbol is any capital letter, the `a` symbol is any small letter,
260-
symbol `0` is any digit, the `#` symbol is any character, and the other characters remain as they are.
261-
The function is available only in the `template` field of the `string` data type.
262260
- `upper`: converts the string to upper case.
263261
- `lower`: converts the string to lower case.
264262
- `len`: returns the length of the element.
265263
- `json`: converts the element to a JSON string.
266264

267265
Usage restrictions:
268266

269-
The `pattern`, `lower`, and `upper` functions are available only in the `template` field of the `string` data type.
267+
The `lower`, and `upper` functions are available only in the `template` field of the `string` data type.
270268
The `len` and `json` functions are available only in the `format_template` field of the output parameters.
271269

272270
#### Examples of data generation configuration
@@ -334,7 +332,7 @@ models:
334332
- name: passport
335333
type: string
336334
type_params:
337-
template: '{{ "AA 00 000 000" | pattern }}'
335+
pattern: AA 00 000 000
338336
distinct_percentage: 1
339337
ordered: true
340338
- name: email

doc/ru/usage.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,11 @@ open_ai:
164164
- `min_length`: Минимальная длина строки. По умолчанию `1`.
165165
- `max_length`: Максимальная длина строки. По умолчанию `32`.
166166
- `logical_type`: Логический тип строки. Поддерживаемые значения: `first_name`, `last_name`, `phone`, `text`.
167-
- `template`: Шаблон для генерации строки. Позволяет использовать значения любых столбов генерируемой модели и
168-
задавать паттерн строки с помощью функции `pattern`. Информация о том, как использовать шаблонные строки,
169-
описана в конце данного раздела.
167+
- `template`: Шаблон для генерации строки. Позволяет использовать значения любых столбов генерируемой модели.
168+
Информация о том, как использовать шаблонные строки, описана в конце данного раздела.
169+
Не работает совместно с `ordered`, `distinct_percentage` или `distinct_count`.
170+
- `pattern`: Паттерн для генерации строки. Символ `A` - любая большая буква, символ `a` - любая маленькая буква,
171+
символ `0` - любая цифра, символ `#` - любой символ, а остальные символы остаются как есть.
170172
- `locale`: Локаль для генерации строк. Поддерживаемые значения: `ru`, `en`. По умолчанию `en`.
171173
- `without_large_letters`: Флаг, указывающий, исключать ли большие буквы из строки.
172174
- `without_small_letters`: Флаг, указывающий, исключать ли маленькие буквы из строки.
@@ -259,19 +261,16 @@ open_ai:
259261
- прямой вызов: `{{ upper .name }}`.
260262
- с помощью pipe: `{{ .name | upper }}`.
261263

262-
В проекте помимо стандартных функций доступны `5` пользовательских:
264+
В проекте помимо стандартных функций доступны `4` пользовательских:
263265

264-
- `pattern`: позволяет создать паттерн строки при помощи специальных символов.
265-
Символ `A` - любая большая буква, символ `a` - любая маленькая буква,
266-
символ `0` - любая цифра, символ `#` - любой символ, а остальные символы остаются как есть.
267266
- `upper`: преобразует строку в верхний регистр.
268267
- `lower`: преобразует строку в нижний регистр.
269268
- `len`: возвращает длину элемента.
270269
- `json`: преобразует элемент в JSON строку.
271270

272271
Ограничения по использованию:
273272

274-
Функции `pattern`, `lower`, и `upper` доступны только в поле `template` типа данных `string`.
273+
Функции `lower`, и `upper` доступны только в поле `template` типа данных `string`.
275274
Функции `len` и `json` доступны только в поле `format_template` параметров вывода.
276275

277276
#### Примеры конфигурации генерации данных
@@ -339,7 +338,7 @@ models:
339338
- name: passport
340339
type: string
341340
type_params:
342-
template: '{{ "AA 00 000 000" | pattern }}'
341+
pattern: AA 00 000 000
343342
distinct_percentage: 1
344343
ordered: true
345344
- name: email

internal/generator/common/utils.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,7 @@ func ExtractValuesFromTemplate(template string) []string {
367367
values := make([]string, 0, len(matches))
368368

369369
for _, match := range matches {
370-
expr := match[0]
371-
val := match[1]
372-
373-
if strings.Contains(expr, "(") && strings.Contains(expr, ")") {
374-
continue
375-
}
376-
377-
values = append(values, val)
370+
values = append(values, match[1])
378371
}
379372

380373
return values

internal/generator/models/generator_model.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,16 @@ func (p *Params) Validate() []error {
426426
errs = append(errs, datetimeParamsErrs...)
427427
}
428428

429+
if p.StringParams != nil && p.StringParams.Template != "" {
430+
if common.Any(
431+
p.Ordered,
432+
p.DistinctPercentage != 0,
433+
p.DistinctCount != 0,
434+
) {
435+
errs = append(errs, errors.New("forbidden to use string template with distinct params or ordered"))
436+
}
437+
}
438+
429439
// must be called only after parsing, filling defaults and validation of TypeParams.
430440
if p.Values != nil {
431441
if err := p.PostProcess(); err != nil {
@@ -674,6 +684,7 @@ type ColumnStringParams struct {
674684
Locale string `backup:"true" json:"locale" yaml:"locale"`
675685
LogicalType string `backup:"true" json:"logical_type" yaml:"logical_type"`
676686
Template string `backup:"true" json:"template" yaml:"template"`
687+
Pattern string `backup:"true" json:"pattern" yaml:"pattern"`
677688
WithoutLargeLetters bool `backup:"true" json:"without_large_letters" yaml:"without_large_letters"`
678689
WithoutSmallLetters bool `backup:"true" json:"without_small_letters" yaml:"without_small_letters"`
679690
WithoutNumbers bool `backup:"true" json:"without_numbers" yaml:"without_numbers"`
@@ -703,6 +714,10 @@ func (p *ColumnStringParams) FillDefaults() {
703714
func (p *ColumnStringParams) Validate() []error {
704715
var errs []error
705716

717+
if p.Template != "" && p.Pattern != "" {
718+
errs = append(errs, errors.Errorf("forbidden to use template and pattern at the same time"))
719+
}
720+
706721
if p.MinLength > p.MaxLength {
707722
errs = append(errs, errors.Errorf(
708723
"min length (%v) should be less than or equal to max length (%v)",

internal/generator/usecase/general/generator/generator.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type ColumnGenerator struct {
2828
}
2929

3030
func NewColumnGenerator(
31-
baseSeed uint64, distinctValuesCountByColumn map[string]uint64,
31+
baseSeed uint64,
3232
modelName string, model *models.Model, column *models.Column,
3333
dataModelName string, dataModel *models.Model, dataColumn *models.Column,
3434
) (*ColumnGenerator, error) {
@@ -54,7 +54,7 @@ func NewColumnGenerator(
5454
rangeRowsCount := uint64(math.Ceil(float64(rowsCount) * dataRange.RangePercentage))
5555

5656
gen, err := newRangeGenerator(
57-
column, columnSeed, distinctValuesCountByColumn,
57+
column, columnSeed,
5858
dataModel, dataColumn, dataColumnSeed,
5959
dataRange, rangeRowsOffset, rangeRowsCount,
6060
)
@@ -93,7 +93,7 @@ func (cg *ColumnGenerator) SkipRows(count uint64) {
9393

9494
//nolint:cyclop
9595
func newRangeGenerator(
96-
column *models.Column, columnSeed uint64, distinctValuesCountByColumn map[string]uint64,
96+
column *models.Column, columnSeed uint64,
9797
dataModel *models.Model, dataColumn *models.Column, dataColumnSeed uint64,
9898
dataRange *models.Params, rangeRowsOffset, rangeRowsCount uint64,
9999
) (*rangeGenerator, error) {
@@ -139,7 +139,7 @@ func newRangeGenerator(
139139
distinctValuesCount = dataRange.DistinctCount
140140
}
141141

142-
generatorValuesCount := valueGenerator.ValuesCount(distinctValuesCountByColumn)
142+
generatorValuesCount := valueGenerator.ValuesCount()
143143

144144
if float64(distinctValuesCount) > generatorValuesCount {
145145
if dataRange.DistinctPercentage != 0 || dataRange.DistinctCount != 0 {
@@ -149,10 +149,6 @@ func newRangeGenerator(
149149
distinctValuesCount = uint64(generatorValuesCount)
150150
}
151151

152-
if distinctValuesCountByColumn != nil {
153-
distinctValuesCountByColumn[column.Name] += distinctValuesCount
154-
}
155-
156152
rangeOrdered := dataRange.Ordered
157153
orderSeed := dataColumnSeed
158154

internal/generator/usecase/general/generator/value/datetime.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (g *DateTimeGenerator) Value(number float64, _ map[string]any) (any, error)
4949
return value, nil
5050
}
5151

52-
func (g *DateTimeGenerator) ValuesCount(_ map[string]uint64) float64 {
52+
func (g *DateTimeGenerator) ValuesCount() float64 {
5353
fromSec := g.From.Unix()
5454
toSec := g.To.Unix()
5555

internal/generator/usecase/general/generator/value/enum.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ func (g *EnumGenerator) Value(number float64, _ map[string]any) (any, error) {
3737
return g.Values[idx], nil
3838
}
3939

40-
func (g *EnumGenerator) ValuesCount(_ map[string]uint64) float64 {
40+
func (g *EnumGenerator) ValuesCount() float64 {
4141
return float64(len(g.Values))
4242
}

internal/generator/usecase/general/generator/value/float.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ func (g *FloatGenerator) Value(number float64, _ map[string]any) (any, error) {
3636
return value, nil
3737
}
3838

39-
func (g *FloatGenerator) ValuesCount(_ map[string]uint64) float64 {
39+
func (g *FloatGenerator) ValuesCount() float64 {
4040
return math.Inf(1)
4141
}

internal/generator/usecase/general/generator/value/integer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ func (g *IntegerGenerator) Value(number float64, _ map[string]any) (any, error)
3737
}
3838
}
3939

40-
func (g *IntegerGenerator) ValuesCount(_ map[string]uint64) float64 {
40+
func (g *IntegerGenerator) ValuesCount() float64 {
4141
return float64(uint64(g.To-g.From)) + 1
4242
}

0 commit comments

Comments
 (0)