partial table_json_kv support

This commit is contained in:
Pavel Merzlyakov 2023-09-08 17:08:46 +03:00
parent 50f0a5b57a
commit 2684a2c663
3 changed files with 452 additions and 356 deletions

View File

@ -196,7 +196,7 @@ function add_twig_filters(\Twig\Environment $twig)
{
$type = $type->getValue();
}
$pkey = explode(',', $type->getToken('table_pkey'));
$pkey = table_pkey_fields($type);
$fields = [];
foreach ($pkey as $fieldName) {
$fields[] = $type->getField($fieldName);
@ -204,6 +204,116 @@ function add_twig_filters(\Twig\Environment $twig)
return $fields;
}
));
$twig->addFilter(new TwigFilter(
'raw_fields',
function(\mtgMetaStruct $struct): array {
$json_fields = table_json_fields($struct);
return array_filter(
$struct->getFields(),
fn(\mtgMetaField $field): bool => !in_array($field->getName(), $json_fields),
);
}
));
$twig->addFilter(new TwigFilter(
'raw_nonpk_fields',
function(\mtgMetaStruct $struct): array {
$pkey = table_pkey_fields($struct);
$json_fields = table_json_fields($struct);
return array_filter(
$struct->getFields(),
fn(\mtgMetaField $field): bool => !in_array($field->getName(), $pkey) && !in_array($field->getName(), $json_fields),
);
}
));
$twig->addFilter(new TwigFilter(
'json_fields',
function(\mtgMetaStruct $struct): array {
$json_fields = table_json_fields($struct);
return array_map(
fn(string $field): \mtgMetaField => $struct->getField($field),
$json_fields,
);
}
));
$twig->addFilter(new TwigFilter(
'table_columns',
function(\mtgMetaStruct $struct): array {
$json_fields = table_json_fields($struct);
$columns = array_reduce(
$struct->getFields(),
function(array $carry, \mtgMetaField $field) use ($json_fields): array {
if(in_array($field->getName(), $json_fields))
{
return $carry;
}
$carry[] = $field->getName();
return $carry;
},
[]
);
if(count($json_fields) > 0)
{
$columns[] = 'kv';
}
return $columns;
}
));
$twig->addFilter(new TwigFilter(
'table_nopk_columns',
function(\mtgMetaStruct $struct): array {
$pkey = table_pkey_fields($struct);
$json_fields = table_json_fields($struct);
$columns = array_reduce(
$struct->getFields(),
function(array $carry, \mtgMetaField $field) use ($pkey, $json_fields): array {
if(in_array($field->getName(), $pkey) || in_array($field->getName(), $json_fields))
{
return $carry;
}
$carry[] = $field->getName();
return $carry;
},
[]
);
if(count($json_fields) > 0)
{
$columns[] = 'kv';
}
return $columns;
}
));
$twig->addFilter(new TwigFilter(
'table_fields',
function(\mtgMetaStruct $struct): array {
$json_fields = table_json_fields($struct);
$fields = array_reduce(
$struct->getFields(),
function(array $carry, \mtgMetaField $field) use ($json_fields): array {
if(in_array($field->getName(), $json_fields))
{
return $carry;
}
$carry[] = snake2camel($field->getName());
return $carry;
},
[]
);
if(count($json_fields) > 0)
{
$fields[] = json_field_name($struct);
}
return $fields;
}
));
}
function add_twig_functions(\Twig\Environment $twig)
@ -241,18 +351,17 @@ function add_twig_functions(\Twig\Environment $twig)
$twig->addFunction(new TwigFunction(
'table_pkey',
function(\mtgMetaStruct $struct): array {
$pkey = explode(',', $struct->getToken('table_pkey'));
$fields = [];
foreach ($pkey as $fieldName) {
$fields[] = $struct->getField($fieldName);
}
return $fields;
$pkey = table_pkey_fields($struct);
return array_map(
fn(string $field): \mtgMetaField => $struct->getField($field),
$pkey,
);
}
));
$twig->addFunction(new TwigFunction(
'table_fields',
function(\mtgMetaStruct $struct): array {
$pkey = explode(',', $struct->getToken('table_pkey'));
$pkey = table_pkey_fields($struct);
return array_filter(
$struct->getFields(),
fn(\mtgMetaField $field): bool => !in_array($field->getName(), $pkey),
@ -350,3 +459,36 @@ function parse_meta_field(string $str, \mtgMetaInfo $meta): \mtgMetaField
list($name, $type) = explode('|', $str);
return new \mtgMetaField($name, new \mtgTypeRef(new \mtgBuiltinType($type)));
}
function table_pkey_fields(\mtgMetaStruct $struct): array
{
if(!$struct->hasToken('table_pkey'))
{
return [];
}
$pkey = $struct->getToken('table_pkey');
if(empty($pkey))
{
throw new Exception('`table_pkey` token is empty');
}
return explode(',', $pkey);
}
function table_json_fields(\mtgMetaStruct $struct): array
{
if(!$struct->hasToken('table_json_kv'))
{
return [];
}
$json_kv = $struct->getToken('table_json_kv');
if(empty($json_kv))
{
throw new Exception('`table_json_kv` token is empty');
}
return explode(',', $struct->getToken('table_json_kv'));
}
function json_field_name(\mtgMetaStruct $struct): string
{
return $struct->getName() . 'JsonValues';
}

View File

@ -67,8 +67,8 @@ func New{{ req_name }}() *{{ req_name }} {
}
{{ struct_macros.reset_method(r.req, req_name) }}
{{ struct_macros.meta_read(r.req, req_name) }}
{{ struct_macros.meta_write(r.req, req_name) }}
{{ struct_macros.read_methods(r.req, req_name) }}
{{ struct_macros.write_methods(r.req, req_name) }}
type {{ rsp_name }} struct {
{%~ for f in r.rsp.fields %}
@ -83,6 +83,6 @@ func New{{ rsp_name }}() *{{ rsp_name }} {
}
{{ struct_macros.reset_method(r.rsp, rsp_name) }}
{{ struct_macros.meta_read(r.rsp, rsp_name) }}
{{ struct_macros.meta_write(r.rsp, rsp_name) }}
{{ struct_macros.read_methods(r.rsp, rsp_name) }}
{{ struct_macros.write_methods(r.rsp, rsp_name) }}
{% endmacro rpc %}

View File

@ -1,122 +1,71 @@
{% macro struct(s) %}
{% if has_token(s, 'table_json_kv') %}
{{ _self.struct_json_kv(s) }}
{% else %}
{{ _self.struct_common(s) }}
{% if has_token(s, 'table') %}
{{ _self.struct_table(s) }}
{% endif %}
{% endif %}
{% if has_token(s, 'data_root') %}
{{ _self.root_set_pk(s) }}
{{ _self.root_save(s) }}
{{ _self.root_delete(s) }}
{{ _self.root_save_diff(s) }}
{{ _self.root_delete_diff(s) }}
{{ _self.root_load(s) }}
{% endif %}
{% endmacro struct %}
{% macro struct_json_kv(s) %}
{% set pkey = table_pkey(s) %}
{% set nopkey = ['kv'] %}
{% set json_fields = table_fields(s) %}
{% set json_fields_type = s.name ~ 'Values' %}
{% set table_name = token(s, 'table') %}
{% set insert_columns = pkey|map(f => f.name)|merge(nopkey) %}
{% set insert_fields = pkey|map(f => f|fname)|merge([json_fields_type]) %}
{% set insert_column_expr = insert_columns|map(c => "`#{c}`")|join(',') %}
{% set insert_values_expr = arr_fill('?', insert_columns|length)|join(',') %}
{% set insert_update_expr = nopkey|map(c => "`#{c}`=VALUES(`#{c}`)")|join(',') %}
{% set update_columns = nopkey %}
{% set select_fields = insert_fields %}
{% set select_column_expr = insert_column_expr %}
{% set select_where_expr = pkey|map(f => "`#{f.name}` = ?")|join(' AND ') %}
{% set select_by = pkey|first %}
{% set delete_by = select_by %}
{% set delete_where_expr = select_where_expr %}
{% set pkey_column_expr = pkey|map(f => "`#{f.name}`")|join(',') %}
{% set pkey_values_expr = arr_fill('?', pkey|length)|join(',') %}
{% set raw_fields = s|raw_fields %}
{% set json_fields = s|json_fields %}
{% set json_fields_type = s.name ~ 'JsonValues' %}
type {{ s.name }} struct {
{%~ for f in pkey %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{%~ endfor %}
{% if s.parent %}
{{ s.parent.name }}
{% endif %}
{% for f in raw_fields %}
{{ f|fname }} {{ f.type|go_type(f.tokens) }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{% endfor %}
{% if json_fields|length > 0 %}
{{ json_fields_type }}
}
type {{ json_fields_type }} struct{
{%~ for f in json_fields %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{%~ endfor %}
changedFields meta.ChangedFields
{% endif %}
{% if has_token(s, 'bitfields') %}
fieldsMask meta.FieldsMask
{% endif %}
{% if has_token(s, 'table') %}
changedFields meta.ChangedFields
{% endif %}
}
{{ _self.common_methods(s.name, s.classid) }}
{{ _self.reset_method(s) }}
{{ _self.read_methods(s) }}
{{ _self.write_methods(s) }}
{% if has_token(s, 'bitfields') %}
{{ _self.bitfields_methods(s.name) }}
{% endif %}
{% if has_token(s, 'table') %}
{{ _self.table_methods(s) }}
{% endif %}
{% if has_token(s, 'data_root') %}
{{ _self.data_root_methods(s) }}
{% endif %}
{% if json_fields|length > 0 %}
type {{ json_fields_type }} struct{
{%~ for f in json_fields %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{%~ endfor %}
}
{{ _self.json_sql_impl(json_fields_type) }}
{{ _self.struct_methods(s.name, s.classid) }}
{{ _self.reset_method(s) }}
{{ _self.meta_read(s) }}
{{ _self.meta_write(s) }}
{% if has_token(s, 'bitfields') %}
{{ _self.bitfields_methods(s.name) }}
{# {{ _self.json_set_expr(json_fields_type, json_fields) }} #}
{% endif %}
{{ _self.table_save(_context) }}
{{ _self.table_load(_context) }}
{{ _self.table_delete(_context) }}
{{ _self.table_delete_diff(_context) }}
{{ _self.changed_fields(json_fields_type, json_fields) }}
{{ _self.json_set_expr(json_fields_type, json_fields) }}
func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error {
if rec.changedFields.Empty() {
return nil
}
var builder strings.Builder
builder.Grow({{ 56 + table_name|length + insert_column_expr|length + insert_values_expr|length }})
builder.WriteString("INSERT INTO `{{ table_name }}` ({{ insert_column_expr }}) VALUES({{ insert_values_expr }}) ON DUPLICATE KEY UPDATE `kv`=")
if err := rec.WriteJsonSetExpr(&builder); err != nil {
return err
}
_, saveErr := dbe.ExecContext(ctx,
builder.String(),
{% for f in insert_fields -%}
rec.{{ f }},
{% endfor -%}
)
return errors.WithStack(saveErr)
}
{{ _self.table_save_coll_diff(s.name) }}
{% endmacro struct_json_kv %}
{% endmacro struct %}
{% macro struct_table(s) %}
{% macro table_methods(s) %}
{% set pkey = table_pkey(s) %}
{% set nopkey = table_fields(s) %}
{% set raw_fields = s|raw_fields %}
{% set raw_nonpk_fields = s|raw_nonpk_fields %}
{% set json_fields = s|json_fields %}
{% set table_name = token(s, 'table') %}
{% set insert_columns = s.fields|map(f => f.name) %}
{% set insert_fields = s.fields|map(f => f|fname) %}
{% set insert_column_expr = s.fields|map(f => f.name|quote)|join(',') %}
{% set insert_columns = s|table_columns %}
{% set insert_fields = s|table_fields %}
{% set insert_column_expr = insert_columns|map(c => c|quote)|join(',') %}
{% set insert_values_expr = arr_fill('?', insert_columns|length)|join(',') %}
{% set insert_update_expr = nopkey|map(f => "`#{f.name}`=VALUES(`#{f.name}`)")|join(',') %}
{% set update_columns = nopkey|map(f => f.name) %}
{% set insert_update_expr = s|table_nopk_columns|map(c => "`#{c}`=VALUES(`#{c}`)")|join(',') %}
{% set select_fields = insert_fields %}
{% set select_column_expr = insert_column_expr %}
{% set select_where_expr = pkey|map(f => "`#{f.name}` = ?")|join(' AND ') %}
@ -126,179 +75,12 @@ func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name
{% set pkey_column_expr = pkey|map(f => "`#{f.name}`")|join(',') %}
{% set pkey_values_expr = arr_fill('?', pkey|length)|join(',') %}
{{ _self.changed_fields(s.name, nopkey) }}
{# {{ _self.struct_identifier(s.name, pkey) }} #}
{{ _self.changed_fields_methods(s.name, nopkey) }}
{{ _self.table_save(_context) }}
{{ _self.table_load(_context) }}
{{ _self.table_delete(_context) }}
{{ _self.table_delete_diff(_context) }}
func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error {
if rec.changedFields.Empty() {
return nil
}
var queryBuilder strings.Builder
queryBuilder.Grow({{ 52 + table_name|length + insert_column_expr|length + insert_values_expr|length + insert_update_expr|length }})
queryBuilder.WriteString("INSERT INTO `{{ table_name }}` ({{ pkey_column_expr }}")
var valuesBuilder strings.Builder
valuesBuilder.Grow({{ 10 + insert_values_expr|length }})
valuesBuilder.WriteString(" VALUES ({{ pkey_values_expr }}")
var updateBuilder strings.Builder
updateBuilder.Grow({{ 25 + insert_update_expr|length }})
updateBuilder.WriteString(" ON DUPLICATE KEY UPDATE ")
values := make([]any, 0, 10)
{% for f in pkey %}
values = append(values, rec.{{ f|fname }})
{% endfor %}
initUpdateLen := updateBuilder.Len()
{% for f in nopkey %}
if rec.{{ f|fname }}Changed() {
queryBuilder.WriteString(",`{{ f.name }}`")
if updateBuilder.Len() > initUpdateLen {
updateBuilder.WriteRune(',')
}
updateBuilder.WriteString("`{{ f.name }}`=VALUES(`{{ f.name }}`)")
valuesBuilder.WriteString(",?")
values = append(values, rec.{{ f|fname }})
}
{% endfor %}
valuesBuilder.WriteRune(')')
queryBuilder.WriteRune(')')
queryBuilder.WriteString(valuesBuilder.String())
queryBuilder.WriteString(updateBuilder.String())
_, saveErr := dbe.ExecContext(ctx, queryBuilder.String(), values...)
return errors.Wrap(saveErr, queryBuilder.String())
}
{{ _self.table_save_coll_diff(s.name) }}
{% endmacro struct_table %}
{% macro root_set_pk(s) %}
{% set set_field = meta_field(token(s, 'data_root')) %}
func (s *{{ s.name }}) Set{{ set_field|fname }}({{ set_field|varname }} {{ set_field.type|go_type }}) {
{%~ for f in s.fields|filter(f => not has_token(f, 'db_skip')) %}
{%~ if f.type is array %}
{% set pkey = table_pkey(f.type.value) %}
{% set field_name = pkey|first|fname %}
for i := range s.{{ f|fname }} {
s.{{ f|fname }}[i].{{ field_name }} = {{ set_field|varname }}
}
{%~ else %}
{% set pkey = table_pkey(f.type) %}
{% set field_name = pkey|first|fname %}
s.{{ f|fname }}.{{ field_name }} = {{ set_field|varname }}
{%~ endif %}
{%~ endfor %}
}
{% endmacro root_set_pk %}
{% macro root_save(s) %}
func Save{{ s.name }}(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error {
{%~ for f in s.fields|filter(f => not has_token(f, 'db_skip')) %}
{%~ if f.type is array %}
if err := Save{{ f.type.value.name }}Collection(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ else %}
if err := Save{{ f.type.name }}(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ endif %}
{%~ endfor %}
return nil
}
{% endmacro root_save %}
{% macro root_save_diff(s) %}
func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error {
{%~ for f in s.fields|filter(f => not has_token(f, 'db_skip')) %}
{%~ if f.type is array %}
if err := Save{{ f.type.value.name }}CollectionDiff(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ else %}
if err := Save{{ f.type.name }}Diff(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ endif %}
{%~ endfor %}
return nil
}
{% endmacro root_save_diff %}
{% macro root_delete(s) %}
{% set delete_by = meta_field(token(s, 'data_root')) %}
func Delete{{ s.name }}(ctx context.Context, dbe metadb.Execer, {{ delete_by|varname }} {{ delete_by.type|go_type }}) error {
{%~ for f in s.fields|filter(f => not has_token(f, 'db_skip')) %}
{%~ if f.type is array %}
if err := Delete{{ f.type.value.name }}Collection(ctx, dbe, {{ delete_by|varname }}); err != nil {
return err
}
{%~ elseif f.type is struct %}
if _, err := Delete{{ f.type.name }}(ctx, dbe, {{ delete_by|varname }}); err != nil {
return err
}
{%~ else %}
if err := Delete{{ f.type.name }}(ctx, dbe, {{ delete_by|varname }}); err != nil {
return err
}
{%~ endif %}
{%~ endfor %}
return nil
}
{% endmacro root_delete %}
{% macro root_delete_diff(s) %}
func Delete{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, ids {{ s.name }}RemovedIds) error {
{%~ for f in s.fields|filter(f => not has_token(f, 'db_skip') and f.type is array) %}
if err := Delete{{ f.type.value.name }}CollectionById(ctx, dbe, ids.{{ f|fname }}); err != nil {
return err
}
{%~ endfor %}
return nil
}
{% endmacro root_delete_diff %}
{% macro root_load(s) %}
{% set load_by = meta_field(token(s, 'data_root')) %}
func Load{{ s.name }}(ctx context.Context, dbq metadb.Querier, {{ load_by|varname }} {{ load_by.type|go_type }}) ({{ s.name }}, error) {
var s {{ s.name }}
{%~ for f in s.fields|filter(f => not has_token(f, 'db_skip')) %}
{%~ if f.type is array %}
{{ f|varname }}, err := Load{{ f.type.value.name }}Collection(ctx, dbq, {{ load_by|varname }})
{%~ else %}
{{ f|varname }}, err := Load{{ f.type.name }}(ctx, dbq, {{ load_by|varname }})
{%~ endif %}
if err != nil {
return {{ s.name }}{}, err
}
s.{{ f|fname }} = {{ f|varname }}
{%~ endfor %}
return s, nil
}
{% endmacro root_load %}
{% endmacro table_methods %}
{% macro table_save(ctx) %}
@ -321,7 +103,7 @@ func Save{{ ctx.s.name }}Collection(ctx context.Context, dbe metadb.Execer, recs
}
var builder strings.Builder
builder.Grow({{ 50 + ctx.table_name|length + ctx.insert_column_expr|length + ctx.insert_update_expr|length }}+len(recs)*{{ ctx.insert_values_expr|length + 2 }}-1)
builder.Grow({{ 50 + ctx.table_name|length + ctx.insert_column_expr|length + ctx.insert_update_expr|length }}+len(recs)*{{ ctx.insert_values_expr|length + 3 }}-1)
values := make([]any, 0, len(recs)*{{ ctx.insert_fields|length }})
@ -340,9 +122,123 @@ func Save{{ ctx.s.name }}Collection(ctx context.Context, dbe metadb.Execer, recs
}
builder.WriteString(" ON DUPLICATE KEY UPDATE {{ ctx.insert_update_expr }}")
fmt.Println(builder.String())
_, saveErr := dbe.ExecContext(ctx, builder.String(), values...)
return errors.WithStack(saveErr)
}
func Save{{ ctx.s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ ctx.s.name }}) error {
if rec.changedFields.Empty() {
return nil
}
var queryBuilder strings.Builder
queryBuilder.Grow({{ 52 + ctx.table_name|length + ctx.insert_column_expr|length + ctx.insert_values_expr|length + ctx.insert_update_expr|length }})
queryBuilder.WriteString("INSERT INTO `{{ ctx.table_name }}` ({{ ctx.pkey_column_expr }}")
var valuesBuilder strings.Builder
valuesBuilder.Grow({{ 10 + ctx.insert_values_expr|length }})
valuesBuilder.WriteString(" VALUES ({{ ctx.pkey_values_expr }}")
var updateBuilder strings.Builder
updateBuilder.Grow({{ 25 + ctx.insert_update_expr|length }})
updateBuilder.WriteString(" ON DUPLICATE KEY UPDATE ")
values := make([]any, 0, 10)
{% for f in ctx.pkey %}
values = append(values, rec.{{ f|fname }})
{% endfor %}
initUpdateLen := updateBuilder.Len()
{% for f in ctx.raw_nonpk_fields %}
if rec.{{ f|fname }}Changed() {
queryBuilder.WriteString(",`{{ f.name }}`")
valuesBuilder.WriteString(",?")
if updateBuilder.Len() > initUpdateLen {
updateBuilder.WriteRune(',')
}
updateBuilder.WriteString("`{{ f.name }}`=VALUES(`{{ f.name }}`)")
values = append(values, rec.{{ f|fname }})
}
{% endfor %}
{% if has_token(ctx.s, 'table_json_kv') %}
var jsonBuilder strings.Builder
jsonBuilder.Grow(255)
{% for f in ctx.json_fields %}
{% set fname = f|fname %}
if rec.{{ f|fname }}Changed() {
{%~ if f.type is builtin %}
jsonBuilder.WriteString(",'$.{{ f|alias }}',?")
values = append(values, rec.{{ f|fname }})
{%~ else %}
jsonBuilder.WriteString(",'$.{{ f|alias }}',")
jsonBytes, err := json.Marshal(rec.{{ fname }})
if err != nil {
return errors.WithStack(err)
}
jsonBuilder.WriteString("CAST(")
jsonBuilder.WriteString(strconv.Quote(string(jsonBytes)))
jsonBuilder.WriteString(" AS JSON)")
{# {%~ if f.type is string %}
jsonBuilder.WriteString(strconv.Quote(rec.{{ fname }}))
{%~ elseif f.type is bool %}
jsonBuilder.WriteString(strconv.FormatBool(rec.{{ fname }}))
{%~ elseif f.type is uint %}
jsonBuilder.WriteString(strconv.FormatUint(uint64(rec.{{ fname }}), 10))
{%~ elseif f.type is int %}
jsonBuilder.WriteString(strconv.FormatInt(int64(rec.{{ fname }}), 10))
{%~ else %}
jsonBytes, err := json.Marshal(rec.{{ fname }})
if err != nil {
return errors.WithStack(err)
}
jsonBuilder.WriteString("CAST(")
jsonBuilder.WriteString(strconv.Quote(string(jsonBytes)))
jsonBuilder.WriteString(" AS JSON)") #}
{%~ endif %}
}
{% endfor %}
if jsonBuilder.Len() > 0 {
queryBuilder.WriteString(",`kv`")
valuesBuilder.WriteString(",?")
if updateBuilder.Len() > initUpdateLen {
updateBuilder.WriteRune(',')
}
updateBuilder.WriteString("`kv`=JSON_SET(`kv`")
updateBuilder.WriteString(jsonBuilder.String())
updateBuilder.WriteRune(')')
values = append(values, rec.{{ ctx.s.name }}JsonValues)
}
{% endif %}
valuesBuilder.WriteRune(')')
queryBuilder.WriteRune(')')
queryBuilder.WriteString(valuesBuilder.String())
queryBuilder.WriteString(updateBuilder.String())
fmt.Println(queryBuilder.String())
_, saveErr := dbe.ExecContext(ctx, queryBuilder.String(), values...)
return errors.Wrap(saveErr, queryBuilder.String())
}
func Save{{ ctx.s.name }}CollectionDiff(ctx context.Context, dbe metadb.Execer, recs []{{ ctx.s.name }}) error {
for _, rec := range recs {
if err := Save{{ ctx.s.name }}Diff(ctx, dbe, rec); err != nil {
return err
}
}
return nil
}
{% endmacro table_save %}
@ -455,22 +351,7 @@ func Delete{{ ctx.s.name }}Collection(
return errors.WithStack(err)
}
{% endif %}
{% endmacro table_delete %}
{% macro table_save_coll_diff(struct_name) %}
func Save{{ struct_name }}CollectionDiff(ctx context.Context, dbe metadb.Execer, recs []{{ struct_name }}) error {
for _, rec := range recs {
if err := Save{{ struct_name }}Diff(ctx, dbe, rec); err != nil {
return err
}
}
return nil
}
{% endmacro table_save_coll_diff %}
{% macro table_delete_diff(ctx) %}
func Delete{{ ctx.s.name }}ById(
ctx context.Context,
dbe metadb.Execer,
@ -527,12 +408,11 @@ func Delete{{ ctx.s.name }}CollectionById(
_, delErr := dbe.ExecContext(ctx, builder.String(), values...)
return errors.WithStack(delErr)
}
{% endmacro table_delete_diff %}
{% endmacro table_delete %}
{% macro changed_fields(type_name, fields) %}
{% macro changed_fields_methods(type_name, fields) %}
{% for f in fields %}
func (s {{ type_name }}) {{ f|fname }}Changed() bool {
return s.changedFields.Changed("{{ f|alias }}")
}
@ -541,7 +421,7 @@ func (s *{{ type_name }}) Set{{ f|fname }}Changed() {
s.changedFields.SetChanged("{{ f|alias }}")
}
{% endfor %}
{% endmacro changed_fields %}
{% endmacro changed_fields_methods %}
{% macro json_sql_impl(type_name) %}
@ -642,7 +522,7 @@ func (s *{{ name|default(o.name) }}) Reset() {
{% endmacro reset_method %}
{% macro meta_read(s, name) %}
{% macro read_methods(s, name) %}
{% set fields_len = s.fields|length %}
func (s *{{ name|default(s.name) }}) Read(reader meta.Reader) error {
@ -702,7 +582,7 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
return nil
}
{% endmacro meta_read %}
{% endmacro read_methods %}
{% macro meta_read_field(type, fname, alias, tokens, has_table_token) %}
@ -785,7 +665,7 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
{% endmacro meta_read_field %}
{% macro meta_write(o, name) %}
{% macro write_methods(o, name) %}
func (s *{{ name|default(o.name) }}) Write(writer meta.Writer) error {
if err := writer.BeginContainer({{ get_all_fields(o)|length }}, ""); err != nil {
return err
@ -813,7 +693,7 @@ func (s *{{ name|default(o.name) }}) WriteFields(writer meta.Writer) error {
func (s *{{ name|default(o.name) }}) FieldsCount() int {
return {{ get_all_fields(o)|length }}
}
{% endmacro meta_write %}
{% endmacro write_methods %}
{% macro meta_write_field(type, fname, alias, tokens) %}
@ -857,55 +737,7 @@ func (s *{{ name|default(o.name) }}) FieldsCount() int {
{% endmacro meta_write_field %}
{% macro struct_diff_removed(s) %}
type {{ s.name }} struct {
{% for f in s.parent.fields %}
{{ f|fname }} {{ f.type|go_type }}Id `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{% endfor %}
}
{% endmacro struct_diff_removed %}
{% macro struct_identifier(name, pkey) %}
type {{ name }}Id struct {
{% for f in pkey %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{% endfor %}
}
{% endmacro struct_identifier %}
{% macro struct_common(s) %}
type {{ s.name }} struct {
{% if s.parent %}
{{ s.parent.name }}
{% endif %}
{% for f in s.fields %}
{{ f|fname }} {{ f.type|go_type(f.tokens) }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{% endfor %}
{% if has_token(s, 'bitfields') %}
fieldsMask meta.FieldsMask
{% endif %}
{% if has_token(s, 'table') %}
changedFields meta.ChangedFields
{% endif %}
}
{{ _self.struct_methods(s.name, s.classid) }}
{{ _self.reset_method(s) }}
{{ _self.meta_read(s) }}
{{ _self.meta_write(s) }}
{% if has_token(s, 'bitfields') %}
{{ _self.bitfields_methods(s.name) }}
{% endif %}
{% endmacro struct_common %}
{% macro struct_methods(name, classid) %}
{% macro common_methods(name, classid) %}
func New{{ name }}() *{{ name }} {
s := new({{ name }})
s.Reset()
@ -940,7 +772,7 @@ func Ptr{{ name }}(s meta.Struct) *{{ name }} {
}
return ptr.Ptr{{ name }}()
}
{% endmacro struct_methods %}
{% endmacro common_methods %}
{% macro bitfields_methods(name) %}
@ -960,3 +792,125 @@ func (s *{{ name }}) FieldsMask() meta.FieldsMask {
return s.fieldsMask
}
{% endmacro bitfields_methods %}
{% macro data_root_methods(s) %}
{% set root_field = meta_field(token(s, 'data_root')) %}
{% set fields = s.fields|filter(f => not has_token(f, 'db_skip')) %}
{{ _self.root_set_pk(_context) }}
{{ _self.root_save(_context) }}
{{ _self.root_load(_context) }}
{{ _self.root_delete(_context) }}
{% endmacro %}
{% macro root_set_pk(ctx) %}
{% set s = ctx.s %}
{% set set_field = ctx.root_field %}
func (s *{{ s.name }}) Set{{ set_field|fname }}({{ set_field|varname }} {{ set_field.type|go_type }}) {
{%~ for f in ctx.fields %}
{%~ if f.type is array %}
{% set pkey = table_pkey(f.type.value) %}
{% set field_name = pkey|first|fname %}
for i := range s.{{ f|fname }} {
s.{{ f|fname }}[i].{{ field_name }} = {{ set_field|varname }}
}
{%~ else %}
{% set pkey = table_pkey(f.type) %}
{% set field_name = pkey|first|fname %}
s.{{ f|fname }}.{{ field_name }} = {{ set_field|varname }}
{%~ endif %}
{%~ endfor %}
}
{% endmacro root_set_pk %}
{% macro root_save(ctx) %}
{% set s = ctx.s %}
func Save{{ s.name }}(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error {
{%~ for f in ctx.fields %}
{%~ if f.type is array %}
if err := Save{{ f.type.value.name }}Collection(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ else %}
if err := Save{{ f.type.name }}(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ endif %}
{%~ endfor %}
return nil
}
func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error {
{%~ for f in ctx.fields %}
{%~ if f.type is array %}
if err := Save{{ f.type.value.name }}CollectionDiff(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ else %}
if err := Save{{ f.type.name }}Diff(ctx, dbe, rec.{{ f|fname }}); err != nil {
return err
}
{%~ endif %}
{%~ endfor %}
return nil
}
{% endmacro root_save %}
{% macro root_load(ctx) %}
{% set s = ctx.s %}
{% set load_by = ctx.root_field %}
func Load{{ s.name }}(ctx context.Context, dbq metadb.Querier, {{ load_by|varname }} {{ load_by.type|go_type }}) ({{ s.name }}, error) {
var s {{ s.name }}
{%~ for f in ctx.fields %}
{%~ if f.type is array %}
{{ f|varname }}, err := Load{{ f.type.value.name }}Collection(ctx, dbq, {{ load_by|varname }})
{%~ else %}
{{ f|varname }}, err := Load{{ f.type.name }}(ctx, dbq, {{ load_by|varname }})
{%~ endif %}
if err != nil {
return {{ s.name }}{}, err
}
s.{{ f|fname }} = {{ f|varname }}
{%~ endfor %}
return s, nil
}
{% endmacro root_load %}
{% macro root_delete(ctx) %}
{% set s = ctx.s %}
{% set delete_by = ctx.root_field %}
func Delete{{ s.name }}(ctx context.Context, dbe metadb.Execer, {{ delete_by|varname }} {{ delete_by.type|go_type }}) error {
{%~ for f in ctx.fields %}
{%~ if f.type is array %}
if err := Delete{{ f.type.value.name }}Collection(ctx, dbe, {{ delete_by|varname }}); err != nil {
return err
}
{%~ elseif f.type is struct %}
if _, err := Delete{{ f.type.name }}(ctx, dbe, {{ delete_by|varname }}); err != nil {
return err
}
{%~ else %}
if err := Delete{{ f.type.name }}(ctx, dbe, {{ delete_by|varname }}); err != nil {
return err
}
{%~ endif %}
{%~ endfor %}
return nil
}
func Delete{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, ids {{ s.name }}RemovedIds) error {
{%~ for f in ctx.fields|filter(f => f.type is array) %}
if err := Delete{{ f.type.value.name }}CollectionById(ctx, dbe, ids.{{ f|fname }}); err != nil {
return err
}
{%~ endfor %}
return nil
}
{% endmacro root_delete %}