Skip to content
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `template` field in the `string` data type is now used to generate template strings
with the ability to use the values of any columns of the generated model.

- In the `format_template` field of the output parameters, the variable `ColumnNames` is now available.

### Breaking changes

- Using `template` field to specify a string pattern like `Aa0#` is no longer supported,
`pattern` should be used instead.

- The `Rows` variable in the `format_template` filed of the output parameters is now a two-dimensional array,
not a map.

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

### Added
Expand Down
61 changes: 25 additions & 36 deletions doc/en/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,44 +192,23 @@ Structure `output.params` for format `http`:
- `batch_size`: Number of data records sent in one request. Default is `1000`.
- `workers_count`: Number of threads for writing data. Default is `1`. *Experimental field.*
- `headers`: HTTP request headers specified as a dictionary. Default is none.
- `format_template`: Template-based format for sending data, configured using Golang templates.
There are 2 fields available for use in `format_template`:
- `format_template`: Template-based format for sending data, configured using templates.
There are 3 fields available for use in `format_template`:
* `ModelName` - name of the model.
* `Rows` - array of records, where each element is a dictionary representing a data row.
Dictionary keys correspond to column names, and values correspond to data in those columns.

You can read about the available functions and the use of template strings at the end of this section.

Example value for the `format_template` field:

```yaml
format_template: |
{
"table_name": "{{ .ModelName }}",
"meta": {
"rows_count": {{ len .Rows }}
},
"rows": [
{{- range $i, $row := .Rows }}
{{- if $i}},{{ end }}
{
"id": {{ index $row "id" }},
"username": "{{ index $row "name" }}"
}
{{- end }}
]
}
```
* `ColumnNames` - array of column names.
* `Rows` - a two-dimensional array, where each outer element represents a table row,
and the inner element contains values of this row in the same order as `ColumnNames`.

Default value for the `format_template` field:

```yaml
format_template: |
{
"table_name": {{ .ModelName }},
"rows": {{ json .Rows }}
"rows": {{ rowsJson .ColumnNames .Rows }}
}
```

You can read about the available functions and the use of template strings at the end of this section.

Structure of `output.params` for `tcs` format:

Expand All @@ -251,17 +230,27 @@ Function calls:
- direct call: `{{ upper .name }}`.
- using pipe: `{{ .name | upper }}`.

In addition to standard functions, the project provides `4` custom functions:
The following is a list of additional functions available in certain template fields:

In the `template` field of `string` data type:

- `upper`: converts the string to upper case.
- `lower`: converts the string to lower case.
- `len`: returns the length of the element.
- `json`: converts the element to a JSON string.

Usage restrictions:
In the `format_template` field of the output parameters:

The `lower`, and `upper` functions are available only in the `template` field of the `string` data type.
The `len` and `json` functions are available only in the `format_template` field of the output parameters.
- `len`: returns the length of the element.
- `json`: converts the element to a JSON string.
- `rowsJson`: converts an array of column names (`ColumnNames`) and a two-dimensional array of rows (`Rows`)
into a JSON array whose elements are objects of the form:
```
{
"columnName1": value1,
"columnName2": value2,
...
}
```
where each object corresponds to one row of the table.

#### Examples of data generation configuration

Expand Down Expand Up @@ -413,7 +402,7 @@ output:
"meta": {
"rows_count": {{ len .Rows }}
},
"rows": {{ json .Rows }}
"rows": {{ rowsJson .ColumnNames .Rows }}
}

models:
Expand Down
63 changes: 26 additions & 37 deletions doc/ru/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,44 +198,23 @@ open_ai:
- `batch_size`: Размер отправляемого в одном запросе массива данных. По умолчанию `1000`.
- `workers_count`: Количество потоков для записи данных. По умолчанию `1`. *Является экспериментальным полем.*
- `headers`: Заголовки http запроса, указываются в формате словаря. По умолчанию отсутствуют.
- `format_template`: Формат отправляемых данных, конфигурируемый с помощью шаблонов Golang.
Для использования в `format_template` доступно 2 поля:
- `format_template`: Формат отправляемых данных, конфигурируемый с помощью шаблонов.
Для использования в `format_template` доступно 3 поля:
* `ModelName` - имя модели.
* `Rows` - массив записей, где каждый элемент является словарем, который представляет собой строку данных.
Ключи словаря соответствуют названиям столбцов, а значения — данным в этих столбцах.

О доступных функциях и использовании шаблонных строк можно прочитать в конце данного раздела.

Пример значения поля `format_template`:

```yaml
format_template: |
{
"table_name": "{{ .ModelName }}",
"meta": {
"rows_count": {{ len .Rows }}
},
"rows": [
{{- range $i, $row := .Rows }}
{{- if $i}},{{ end }}
{
"id": {{ index $row "id" }},
"username": "{{ index $row "name" }}"
}
{{- end }}
]
}
```
* `ColumnNames` - массив имён колонок.
* `Rows` - двумерный массив, где каждый внешний элемент представляет строку таблицы,
а внутренний содержит значения этой строки в том же порядке, что и `ColumnNames`.

Значение поля `format_template` по умолчанию:

```yaml
format_template: |
{
"table_name": {{ .ModelName }},
"rows": {{ json .Rows }}
"table_name": "{{ .ModelName }}",
"rows": {{ rowsJson .ColumnNames .Rows }}
}
```

О доступных функциях и использовании шаблонных строк можно прочитать в конце данного раздела.

Структура `output.params` для формата `tcs`:

Expand All @@ -257,17 +236,27 @@ open_ai:
- прямой вызов: `{{ upper .name }}`.
- с помощью pipe: `{{ .name | upper }}`.

В проекте помимо стандартных функций доступны `4` пользовательских:
Ниже приведён список дополнительных функций, доступных в определённых полях шаблонов:

В поле `template` типа данных `string`:

- `upper`: преобразует строку в верхний регистр.
- `lower`: преобразует строку в нижний регистр.
- `len`: возвращает длину элемента.
- `json`: преобразует элемент в JSON строку.

Ограничения по использованию:
В поле `format_template` параметров вывода:

Функции `lower`, и `upper` доступны только в поле `template` типа данных `string`.
Функции `len` и `json` доступны только в поле `format_template` параметров вывода.
- `len`: возвращает длину элемента.
- `json`: преобразует элемент в JSON строку.
- `rowsJson`: преобразует массив имён колонок (`ColumnNames`) и двумерный массив строк (`Rows`)
в JSON-массив, элементами которого являются объекты вида:
```
{
"columnName1": value1,
"columnName2": value2,
...
}
```
где каждый объект соответствует одной строке таблицы.

#### Примеры конфигурации генерации данных

Expand Down Expand Up @@ -419,7 +408,7 @@ output:
"meta": {
"rows_count": {{ len .Rows }}
},
"rows": {{ json .Rows }}
"rows": {{ rowsJson .ColumnNames .Rows }}
}

models:
Expand Down
2 changes: 1 addition & 1 deletion internal/generator/models/generator_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
const (
DefaultOutputDir = "output"
DefaultOutputType = "csv"
defaultFormatTemplate = `{ "table_name": "{{ .ModelName }}", "rows": {{ json .Rows }} }`
defaultFormatTemplate = `{ "table_name": "{{ .ModelName }}", "rows": {{ rowsJson .ColumnNames .Rows }} }`
tcsTimeoutHeader = "x-tcs-timeout_ms"
ParquetDateTimeMillisFormat = "millis"
ParquetDateTimeMicrosFormat = "micros"
Expand Down
51 changes: 51 additions & 0 deletions internal/generator/output/general/writer/http/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package http

import (
"encoding/json"
"fmt"
"reflect"
"strings"
)

func toJSON(v any) (string, error) {
data, err := json.Marshal(v)

return string(data), err
}

func length(v any) int {
return reflect.ValueOf(v).Len()
}

func rowsJSON(columnNames []string, rows [][]any) (string, error) {
var sb strings.Builder

sb.WriteByte('[')

for i, row := range rows {
if i > 0 {
sb.WriteByte(',')
}

sb.WriteByte('{')

for j, columnName := range columnNames {
if j > 0 {
sb.WriteByte(',')
}

value, err := toJSON(row[j])
if err != nil {
return "", err
}

fmt.Fprintf(&sb, `"%s":%s`, columnName, value)
}

sb.WriteByte('}')
}

sb.WriteByte(']')

return sb.String(), nil
}
Loading