diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index bcb997c..cc14422 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -1,92 +1,99 @@ -# This workflow will build a golang project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go - -name: "Create Release" - -on: - workflow_dispatch: - inputs: - version: - description: 'What release version should be created?' - required: true - type: choice - default: 'patch' - options: - - 'patch' - - 'minor' - - 'major' - -concurrency: - group: 'create-release' - cancel-in-progress: false - -permissions: - contents: write - pull-requests: write - issues: write - discussions: write - -jobs: - release: - name: Create Release - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: actions/setup-go@v5 - with: - go-version: ${{ vars.GO_VERSION }} - cache-dependency-path: "**/*.sum" - - - name: Install Mage - run: go install github.com/magefile/mage@latest - - - name: Run Mage - run: | - mage build - mage tools - - - name: Create Changelog - run: | - wget "https://github.com/clog-tool/clog-cli/releases/download/v0.9.3/clog-v0.9.3-x86_64-unknown-linux-gnu.tar.gz" - tar xvzf clog-v0.9.3-x86_64-unknown-linux-gnu.tar.gz - ./clog -c ./.clog.toml --${{ github.event.inputs.version }} - - - name: Copy Changelog to Environment - run: | - echo 'CHANGELOG<> $GITHUB_ENV - cat changelog.md >> $GITHUB_ENV - echo 'EOF' >> $GITHUB_ENV - - - name: Get the new version - id: get_version - run: | - # Get the current version through the changelog file - version=$(cat changelog.md | grep "###" | head -n 1 | cut -d ' ' -f 2) - echo "VERSION=$version" >> $GITHUB_ENV - - - name: Create tag - uses: actions/github-script@v7 - with: - script: | - github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: 'refs/tags/${{ env.VERSION }}', - sha: context.sha - }) - - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - name: ${{ env.VERSION }} - body: ${{ env.CHANGELOG }} - tag_name: ${{ env.VERSION }} - draft: false - prerelease: false - generate_release_notes: false - make_latest: true - files: "bin/*" +# This workflow will build a golang project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go + +name: "Create Release" + +on: + workflow_dispatch: + inputs: + version: + description: 'What release version should be created?' + required: true + type: choice + default: 'patch' + options: + - 'patch' + - 'minor' + - 'major' + +concurrency: + group: 'create-release' + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + issues: write + discussions: write + +jobs: + release: + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: ${{ vars.GO_VERSION }} + cache-dependency-path: "**/*.sum" + + - name: Install Mage + run: go install github.com/magefile/mage@latest + + - name: Run Mage + uses: magefile/mage-action@v3 + with: + version: latest + args: build + + - name: Run Mage + uses: magefile/mage-action@v3 + with: + version: latest + args: tools + + - name: Create Changelog + run: | + wget "https://github.com/clog-tool/clog-cli/releases/download/v0.9.3/clog-v0.9.3-x86_64-unknown-linux-gnu.tar.gz" + tar xvzf clog-v0.9.3-x86_64-unknown-linux-gnu.tar.gz + ./clog -c ./.clog.toml --${{ github.event.inputs.version }} + + - name: Copy Changelog to Environment + run: | + echo 'CHANGELOG<> $GITHUB_ENV + cat changelog.md >> $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + + - name: Get the new version + id: get_version + run: | + # Get the current version through the changelog file + version=$(cat changelog.md | grep "###" | head -n 1 | cut -d ' ' -f 2) + echo "VERSION=$version" >> $GITHUB_ENV + + - name: Create tag + uses: actions/github-script@v7 + with: + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/tags/${{ env.VERSION }}', + sha: context.sha + }) + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + name: ${{ env.VERSION }} + body: ${{ env.CHANGELOG }} + tag_name: ${{ env.VERSION }} + draft: false + prerelease: false + generate_release_notes: false + make_latest: true + files: "bin/*" diff --git a/pkg/generation/template_helpers.go b/pkg/generation/template_helpers.go index 068e20b..4677f6b 100644 --- a/pkg/generation/template_helpers.go +++ b/pkg/generation/template_helpers.go @@ -186,7 +186,7 @@ func getType(col *entities.Column) string { return "int64" case "int": if col.Nullable { - return "usql.NullInt64" + return "usql.NullInt" } if col.Unsigned { return "uint" @@ -216,7 +216,7 @@ func getType(col *entities.Column) string { return "int16" case "mediumint": if col.Nullable { - return "usql.NullInt64" + return "usql.NullInt32" } if col.Unsigned { return "uint32" diff --git a/usql/types.go b/usql/types.go index 14213b3..1acd7d4 100644 --- a/usql/types.go +++ b/usql/types.go @@ -93,6 +93,158 @@ func NewNullFloat64(f float64) *NullFloat64 { return &NullFloat64{NullFloat64: sql.NullFloat64{Float64: f, Valid: true}} } +// NullInt represents a nullable int type which supports json Marshaler, sql Scanner, and sql driver Valuer interfaces. +type NullInt struct { + sql.NullInt64 +} + +// MarshalJSON implements the json.Marshaler interface for a NullInt. +func (r NullInt) MarshalJSON() ([]byte, error) { + if r.Valid { + return json.Marshal(r.Int64) + } + + return json.Marshal(nil) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for a NullInt. +func (r *NullInt) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, null) { + r.Int64 = 0 + r.Valid = false + + return nil + } + + if err := json.Unmarshal(data, &r.Int64); err != nil { + return err + } + r.Valid = true + + return nil +} + +func (r NullInt) Val() int { + return int(r.Int64) +} + +// RedisArg implements redis.Argument. +// +// The caller should explicitly check the Valid field when putting NullString +// values into Redis. If this is not done it can lead to confusion as RedisScan +// on this type will treat an empty non-nil string as valid. +func (r NullInt) RedisArg() interface{} { + return r.Int64 +} + +// RedisScan implements redis.Scanner. +func (r *NullInt) RedisScan(src interface{}) error { + if src == nil { + r.Int64, r.Valid = 0, false + return nil + } + + var err error + switch src := src.(type) { + case []byte: + r.Int64, err = strconv.ParseInt(string(src), 10, 64) + case string: + r.Int64, err = strconv.ParseInt(src, 10, 64) + default: + return fmt.Errorf("unexpected type: %T", src) + } + + if err != nil { + return err + } + r.Valid = true + + return nil +} + +// NewNullInt returns a valid new NullInt for a given int value. +func NewNullInt(i int) *NullInt { + return &NullInt{NullInt64: sql.NullInt64{Int64: int64(i), Valid: true}} +} + +// NullInt32 represents a nullable int32 type which supports json Marshaler, sql Scanner, and sql driver Valuer interfaces. +type NullInt32 struct { + sql.NullInt32 +} + +// MarshalJSON implements the json.Marshaler interface for a NullInt32. +func (r NullInt32) MarshalJSON() ([]byte, error) { + if r.Valid { + return json.Marshal(r.Int32) + } + + return json.Marshal(nil) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for a NullInt32. +func (r *NullInt32) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, null) { + r.Int32 = 0 + r.Valid = false + + return nil + } + + if err := json.Unmarshal(data, &r.Int32); err != nil { + return err + } + r.Valid = true + + return nil +} + +func (r NullInt32) Val() int32 { + return r.Int32 +} + +// RedisArg implements redis.Argument. +// +// The caller should explicitly check the Valid field when putting NullString +// values into Redis. If this is not done it can lead to confusion as RedisScan +// on this type will treat an empty non-nil string as valid. +func (r NullInt32) RedisArg() interface{} { + return r.Int32 +} + +// RedisScan implements redis.Scanner. +func (r *NullInt32) RedisScan(src interface{}) error { + if src == nil { + r.Int32, r.Valid = 0, false + return nil + } + + var ( + i64 int64 + err error + ) + switch src := src.(type) { + case []byte: + i64, err = strconv.ParseInt(string(src), 10, 32) + case string: + i64, err = strconv.ParseInt(src, 10, 32) + default: + return fmt.Errorf("unexpected type: %T", src) + } + + if err != nil { + return err + } + r.Int32 = int32(i64) + r.Valid = true + + return nil +} + +// NewNullInt32 returns a valid new NullInt32 for a given int32 value. +func NewNullInt32(i int32) *NullInt32 { + return &NullInt32{NullInt32: sql.NullInt32{Int32: i, Valid: true}} +} + // NullInt64 represents a nullable int64 type which supports json Marshaler, sql Scanner, and sql driver Valuer interfaces. type NullInt64 struct { sql.NullInt64