From 04c5376009fb352fda407709c98893f48cfcec6d Mon Sep 17 00:00:00 2001 From: Pavel Merzlyakov Date: Sat, 17 Jun 2023 10:56:23 +0300 Subject: [PATCH] get rid of goqu builder --- tpl/codegen_bundle.twig | 4 +- tpl/macros_struct.twig | 188 +++++++++++++++++++++------------------- 2 files changed, 100 insertions(+), 92 deletions(-) diff --git a/tpl/codegen_bundle.twig b/tpl/codegen_bundle.twig index 119a89e..eca23c2 100644 --- a/tpl/codegen_bundle.twig +++ b/tpl/codegen_bundle.twig @@ -11,11 +11,9 @@ import ( "strconv" "strings" - "git.bit5.ru/backend/meta" + "git.bit5.ru/backend/meta/v2" "git.bit5.ru/backend/versioning" "git.bit5.ru/gomodules/metadb" - "github.com/doug-martin/goqu/v9" - "github.com/doug-martin/goqu/v9/exp" "github.com/go-logr/logr" "github.com/pkg/errors" ) diff --git a/tpl/macros_struct.twig b/tpl/macros_struct.twig index 6d8e2af..f62ff49 100644 --- a/tpl/macros_struct.twig +++ b/tpl/macros_struct.twig @@ -36,6 +36,8 @@ {% 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(',') %} type {{ s.name }} struct { {%~ for f in pkey %} @@ -77,33 +79,25 @@ type {{ json_fields_type }} struct{ {{ _self.json_set_expr(json_fields_type, json_fields) }} func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error { - var b strings.Builder - if err := rec.WriteJsonSetExpr(&b); err != nil { + if rec.changedFields.Empty() { + return nil + } + + var builder strings.Builder + builder.Grow({{ 50 + insert_column_expr|length }}) + + builder.WriteString("INSERT INTO `{{ table_name }}` ({{ insert_column_expr }}) ON DUPLICATE KEY UPDATE `kv`=") + + if err := rec.WriteJsonSetExpr(&builder); err != nil { return err } - ds := metadb.SqlBuilder(). - Insert(goqu.T("{{ table_name }}")). - Cols( - {% for c in insert_columns -%} - goqu.C("{{ c }}"), - {% endfor -%} - ). - Vals(goqu.Vals{ - {% for f in insert_fields -%} - rec.{{ f }}, - {% endfor -%} - }). - OnConflict(goqu.DoUpdate("", - goqu.Record{"kv": goqu.L(b.String())}, - )) - - query, _, err := ds.ToSQL() - if err != nil { - return errors.WithStack(err) - } - - _, saveErr := dbe.ExecContext(ctx, query) + _, saveErr := dbe.ExecContext(ctx, + builder.String(), + {% for f in insert_fields -%} + rec.{{ f }}, + {% endfor -%} + ) return errors.WithStack(saveErr) } @@ -127,6 +121,8 @@ func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name {% 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(',') %} {{ _self.changed_fields(s.name, nopkey) }} @@ -138,37 +134,52 @@ func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name {{ _self.table_delete_diff(_context) }} func Save{{ s.name }}Diff(ctx context.Context, dbe metadb.Execer, rec {{ s.name }}) error { - ds := metadb.SqlBuilder(). - Insert(goqu.T("{{ table_name }}")). - Cols( - {% for f in pkey %} - goqu.C("{{ f.name }}"), - {% endfor %} - ) + 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 }}") - vals := make(goqu.Vals, 0, {{ s.fields|length }}) + 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 %} - vals = append(vals, rec.{{ f|fname }}) + values = append(values, rec.{{ f|fname }}) {% endfor %} - updateRecord := make(goqu.Record, {{ nopkey|length }}) + initUpdateLen := updateBuilder.Len() + {% for f in nopkey %} if rec.{{ f|fname }}Changed() { - ds = ds.ColsAppend(goqu.C("{{ f.name }}")) - vals = append(vals, rec.{{ f|fname }}) - updateRecord["{{ f.name }}"] = goqu.L("VALUES(`{{ f.name }}`)") + 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 %} - ds = ds.Vals(vals).OnConflict(goqu.DoUpdate("", updateRecord)) + valuesBuilder.WriteRune(')') - query, _, err := ds.ToSQL() - if err != nil { - return errors.WithStack(err) - } + queryBuilder.WriteRune(')') + queryBuilder.WriteString(valuesBuilder.String()) + queryBuilder.WriteString(updateBuilder.String()) - _, saveErr := dbe.ExecContext(ctx, query) - return errors.WithStack(saveErr) + _, saveErr := dbe.ExecContext(ctx, queryBuilder.String(), values...) + return errors.Wrap(saveErr, queryBuilder.String()) } {{ _self.table_save_coll_diff(s.name) }} @@ -267,35 +278,27 @@ func Save{{ ctx.s.name }}Collection(ctx context.Context, dbe metadb.Execer, recs return nil } - ds := metadb.SqlBuilder(). - Insert(goqu.T("{{ ctx.table_name }}")). - Cols( - {%~ for c in ctx.insert_columns %} - goqu.C("{{ c }}"), - {%~ endfor %} - ). - OnConflict(goqu.DoUpdate("", - goqu.Record{ - {%~ for c in ctx.update_columns %} - "{{ c }}": goqu.L("VALUES(`{{ c }}`)"), - {%~ endfor %} - }, - )) - - for _, rec := range recs { - ds = ds.Vals(goqu.Vals{ + 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) + + values := make([]any, 0, len(recs)*{{ ctx.insert_fields|length }}) + + builder.WriteString("INSERT INTO `{{ ctx.table_name }}` ({{ ctx.insert_column_expr }}) VALUES ") + for i, rec := range recs { + if i > 0 { + builder.WriteRune(',') + } + builder.WriteString("({{ ctx.insert_values_expr }})") + + values = append(values, {%~ for f in ctx.insert_fields %} rec.{{ f }}, {%~ endfor %} - }) + ) } + builder.WriteString(" ON DUPLICATE KEY UPDATE {{ ctx.insert_update_expr }}") - query, _, err := ds.ToSQL() - if err != nil { - return errors.WithStack(err) - } - - _, saveErr := dbe.ExecContext(ctx, query) + _, saveErr := dbe.ExecContext(ctx, builder.String(), values...) return errors.WithStack(saveErr) } {% endmacro table_save %} @@ -450,7 +453,6 @@ func Delete{{ ctx.s.name }}ById( return rowsAffected > 0, nil } -{% set pkey_values_expr = arr_fill('?', ctx.pkey|length)|join(',') %} func Delete{{ ctx.s.name }}CollectionById( ctx context.Context, dbe metadb.Execer, @@ -460,29 +462,27 @@ func Delete{{ ctx.s.name }}CollectionById( return nil } - tuples := make([]exp.LiteralExpression, 0, len(ids)) - for _, id := range ids { - tuples = append(tuples, goqu.L("({{ pkey_values_expr }})", + var builder strings.Builder + builder.Grow({{ 29 + ctx.table_name|length + ctx.pkey_column_expr|length }}+len(ids)*{{ ctx.pkey_values_expr|length + 2 }}-1) + + values := make([]any, 0, len(ids)*{{ ctx.pkey|length }}) + + builder.WriteString("DELETE FROM `{{ ctx.table_name }}` WHERE ({{ ctx.pkey_column_expr }}) IN (") + for i, id := range ids { + if i > 0 { + builder.WriteRune(',') + } + builder.WriteString("({{ ctx.pkey_values_expr }})") + + values = append(values, {% for f in ctx.pkey %} id.{{ f|fname }}, {% endfor %} - )) + ) } + builder.WriteRune(')') - ds := metadb.SqlBuilder(). - Delete(goqu.T("level_state")). - Where(goqu.L("({{ pkey_values_expr }}) IN ?", - {% for f in ctx.pkey %} - goqu.C("{{ f.name }}"), - {% endfor %} - tuples, - )) - query, _, err := ds.ToSQL() - if err != nil { - return errors.WithStack(err) - } - - _, delErr := dbe.ExecContext(ctx, query) + _, delErr := dbe.ExecContext(ctx, builder.String(), values...) return errors.WithStack(delErr) } {% endmacro table_delete_diff %} @@ -490,9 +490,14 @@ func Delete{{ ctx.s.name }}CollectionById( {% macro changed_fields(type_name, fields) %} {% for f in fields %} + func (s {{ type_name }}) {{ f|fname }}Changed() bool { return s.changedFields.Changed("{{ f|alias }}") } + +func (s *{{ type_name }}) Set{{ f|fname }}Changed() { + s.changedFields.SetChanged("{{ f|alias }}") +} {% endfor %} {% endmacro changed_fields %} @@ -576,11 +581,16 @@ func (s *{{ name|default(o.name) }}) Reset() { {% endfor %} {% if has_token(o, 'bitfields') ~%} - s.fieldsMask = meta.FieldsMask{} + s.fieldsMask.Reset() {%- endif ~%} {% if has_token(o, 'table') %} - s.changedFields.Reset() + if s.changedFields.IsNil() { + s.changedFields = meta.NewChangedFields({{ o.fields|length }}) + } else { + s.changedFields.Reset() + } + {% endif %} } {% endmacro reset_method %}