Skip to content

Auto-generate SELECT fields based on struct type#41

Open
wdiahu wants to merge 1 commit intoelgris:masterfrom
wdiahu:feature_select_from_struct
Open

Auto-generate SELECT fields based on struct type#41
wdiahu wants to merge 1 commit intoelgris:masterfrom
wdiahu:feature_select_from_struct

Conversation

@wdiahu
Copy link

@wdiahu wdiahu commented Oct 30, 2025

  • PR Title

    Auto-generate SELECT fields based on struct type

    PR Body

    1. Motivation

    When developing the DAO layer with the current library, it is often necessary to query different fields of the same table. With the existing approach, I have to manually write SELECT field1, field2... statements, which leads to the following issues:

    • High risk of bugs caused by field name typos (especially when the table structure changes);
    • Reduced development efficiency due to repetitive writing of similar SQL snippets.

    Therefore, I propose adding a new utility method API that automatically generates SELECT field lists based on a given struct (or struct pointer). It uses reflection to extract exported fields of the struct (or specified tags such as db), reducing the cost of manual SQL writing while improving code maintainability.

    2. Implementation

    The newly added feature mainly includes the following parts:

    • Added a new method to StatementBuilderType, which generates SELECT fields by parsing struct fields via reflection. It supports extracting field names or specified tags (e.g., db:"column_name");
    • Caching mechanism: Caches the results of struct field parsing to avoid performance overhead from repeated reflection;
    • Added necessary unit tests.

    Example Usage:

    type User struct {
        ID   int    `db:"user_id"`
        Name string `db:"user_name"`
    }
    // Generates "SELECT user_id, user_name FROM foo"
    sql := SelectFromStruct(User{}).From("foo")

    3. Compatibility

    This modification is fully backward-compatible:

    • It does not alter the behavior of any existing APIs; only new methods are added;
    • The caching mechanism is exclusive to the new feature and will not interfere with existing logic.

    4. Functional Testing

    The following test cases have been added:

    • Basic test: Verifies correct generation of field lists for regular structs (without tags);
    • Tag test: Ensures correct extraction of tag values (e.g., db tags) as field names for structs with tags;
    • Pointer test: Supports passing struct pointers as parameters;
    • Performance test: Validates the optimization of reflection performance by the caching mechanism;
    • Boundary test: Handles empty structs and non-struct inputs (returns reasonable errors).

    5. Performance Testing

    goarch: arm64

    pkg: github.com/elgris/sqrl

    cpu: Apple M2

    Test Case Operations (Higher Better) Time per Op (ns/op, Lower Better) Memory Allocated per Op (B/op, Lower Better) Allocations per Op (allocs/op, Lower Better)
    Benchmark_SelectStruct 5.24M 206.6 624 10
    Benchmark_Select 8.20M 145.3 304 9

    6. Additional Notes (Optional)

    Add supplementary details if necessary (e.g., design trade-offs, future extension directions):

    • For performance considerations, the field cache does not have an expiration time. In the future, we may consider introducing an eviction mechanism to prevent excessive memory usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant