storj / dbx

A neat codegen-based database wrapper written in Go
Apache License 2.0
24 stars 3 forks source link

use generics to reduce query boilerplate #5

Open egonelbre opened 1 year ago

egonelbre commented 1 year ago

The generated code has a significant amount of boilerplate which can be reduced by using generics.

For example:

    defer mon.Task()(&ctx)(&err)

    var __embed_stmt = __sqlbundle_Literal("SELECT bucket_storage_tallies.bucket_name, bucket_storage_tallies.project_id, bucket_storage_tallies.interval_start, bucket_storage_tallies.total_bytes, bucket_storage_tallies.inline, bucket_storage_tallies.remote, bucket_storage_tallies.total_segments_count, bucket_storage_tallies.remote_segments_count, bucket_storage_tallies.inline_segments_count, bucket_storage_tallies.object_count, bucket_storage_tallies.metadata_size FROM bucket_storage_tallies ORDER BY bucket_storage_tallies.interval_start DESC")

    var __values []interface{}

    var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
    obj.logStmt(__stmt, __values...)

    for {
        rows, err = func() (rows []*BucketStorageTally, err error) {
            __rows, err := obj.driver.QueryContext(ctx, __stmt, __values...)
            if err != nil {
                return nil, err
            }
            defer __rows.Close()

            for __rows.Next() {
                bucket_storage_tally := &BucketStorageTally{}
                err = __rows.Scan(&bucket_storage_tally.BucketName, &bucket_storage_tally.ProjectId, &bucket_storage_tally.IntervalStart, &bucket_storage_tally.TotalBytes, &bucket_storage_tally.Inline, &bucket_storage_tally.Remote, &bucket_storage_tally.TotalSegmentsCount, &bucket_storage_tally.RemoteSegmentsCount, &bucket_storage_tally.InlineSegmentsCount, &bucket_storage_tally.ObjectCount, &bucket_storage_tally.MetadataSize)
                if err != nil {
                    return nil, err
                }
                rows = append(rows, bucket_storage_tally)
            }
            if err := __rows.Err(); err != nil {
                return nil, err
            }
            return rows, nil
        }()
        if err != nil {
            if obj.shouldRetry(err) {
                continue
            }
            return nil, obj.makeErr(err)
        }
        return rows, nil
    }

Could be replaced by generated code like:

    defer mon.Task()(&ctx)(&err)
    var __values []interface{}
    return queryAll(obj,
        "SELECT bucket_storage_tallies.bucket_name, bucket_storage_tallies.project_id, bucket_storage_tallies.interval_start, bucket_storage_tallies.total_bytes, bucket_storage_tallies.inline, bucket_storage_tallies.remote, bucket_storage_tallies.total_segments_count, bucket_storage_tallies.remote_segments_count, bucket_storage_tallies.inline_segments_count, bucket_storage_tallies.object_count, bucket_storage_tallies.metadata_size FROM bucket_storage_tallies ORDER BY bucket_storage_tallies.interval_start DESC",
        values,
        func(r *BucketStorageTally) []any {
            return []any{&bucket_storage_tally.BucketName, &bucket_storage_tally.ProjectId, &bucket_storage_tally.IntervalStart, &bucket_storage_tally.TotalBytes, &bucket_storage_tally.Inline, &bucket_storage_tally.Remote, &bucket_storage_tally.TotalSegmentsCount, &bucket_storage_tally.RemoteSegmentsCount, &bucket_storage_tally.InlineSegmentsCount, &bucket_storage_tally.ObjectCount, &bucket_storage_tally.MetadataSize}
        }
    )
zeebo commented 1 year ago

this seems great. it should only require changing the template files, so we could even try it outside of the repo first.