Builder for single query in saving collections

This commit is contained in:
Sergey Polygalin 2023-12-17 17:13:33 +03:00
parent a915af9640
commit a643fd99f2
2 changed files with 73 additions and 2 deletions

View File

@ -35,10 +35,26 @@ var _ = strings.Clone
{{ enum_macros.enum(u.object) }}
{% endfor %}
type queryDiffBuilder struct {
query *strings.Builder
values *strings.Builder
update *strings.Builder
rawValues []any
}
func NewQueryDiffBuilder() queryDiffBuilder {
return queryDiffBuilder{
query: &strings.Builder{},
values: &strings.Builder{},
update: &strings.Builder{},
}
}
{% for u in structs %}
{{ struct_macros.struct(u.object) }}
{% endfor %}
func CreateById(classId uint32) (meta.Struct, error) {
switch classId {
{% for u in structs %}

View File

@ -215,11 +215,66 @@ func Save{{ ctx.s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ ctx
}
func Save{{ ctx.s.name }}CollectionDiff(ctx context.Context, dbe metadb.Execer, recs []{{ ctx.s.name }}) error {
byFieldsKey := map[string]queryDiffBuilder{}
for _, rec := range recs {
if err := Save{{ ctx.s.name }}Diff(ctx, dbe, rec); err != nil {
return err
if rec.changedFields.Empty() {
continue
}
key := rec.changedFields.GetFieldsKey()
if _, ok := byFieldsKey[key]; !ok {
builder := NewQueryDiffBuilder()
builder.query.WriteString("INSERT INTO `{{ ctx.table_name }}` ({{ ctx.pkey_column_expr }}")
builder.update.WriteString(" ON DUPLICATE KEY UPDATE {{ ctx.pkey_update_expr }}")
builder.values.WriteString(" VALUES ")
{% if ctx.raw_nonpk_fields|length > 0 %}
{% for f in ctx.raw_nonpk_fields %}
if rec.{{ f|fname }}Changed() {
builder.query.WriteString(",`{{ f.name }}`")
builder.update.WriteString(",`{{ f.name }}`=VALUES(`{{ f.name }}`)")
}
{% endfor %}
{% endif %}
byFieldsKey[key] = builder
}
builder := byFieldsKey[key]
builder.values.WriteString("({{ ctx.pkey_values_expr }}")
{% for f in ctx.pkey %}
builder.rawValues = append(builder.rawValues, rec.{{ f|fname }})
{% endfor %}
{% if ctx.raw_nonpk_fields|length > 0 %}
{% for f in ctx.raw_nonpk_fields %}
if rec.{{ f|fname }}Changed() {
builder.values.WriteString(",?")
builder.rawValues = append(builder.rawValues, rec.{{ f|fname }})
}
{% endfor %}
{% endif %}
builder.values.WriteRune(')')
builder.values.WriteRune(',')
}
for _, builder := range byFieldsKey {
var index int = 1
if len(builder.rawValues) > 1 {
index = 2
}
queryBuilder := builder.query
builder.query.WriteRune(')')
queryBuilder.WriteString(builder.values.String()[0 : len(builder.values.String())-index])
queryBuilder.WriteString(builder.update.String())
_, saveErr := dbe.ExecContext(ctx, queryBuilder.String(), builder.rawValues...)
return errors.Wrap(saveErr, queryBuilder.String())
}
return nil
}
{% endmacro table_save %}