partial table_json_kv support
This commit is contained in:
parent
50f0a5b57a
commit
2684a2c663
|
@ -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';
|
||||
}
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
Loading…
Reference in New Issue