Skip to content

Commit

Permalink
Merge pull request #9 from profe-ajedrez/dev
Browse files Browse the repository at this point in the history
[FEAT] Applying feats and fixes to v2
  • Loading branch information
profe-ajedrez authored Oct 29, 2024
2 parents af2a2c9 + d91b684 commit 5b03067
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 52 deletions.
29 changes: 28 additions & 1 deletion .github/workflows/tester.yml → .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,32 @@ jobs:
with:
go-version: '1.22'

- name: Build
run: go install

- name: Test
run: go test -v ./...
run: |
go test -v ./... -coverprofile coverage.out -coverpkg ./...
go tool cover -func coverage.out -o coverage.out # Replaces coverage.out with the analysis of coverage.out
- name: Go Coverage Badge
uses: tj-actions/coverage-badge-go@v1
if: ${{ runner.os == 'Linux' }} # Runs this on only one of the ci builds.
with:
green: 80
filename: coverage.out

- uses: stefanzweifel/git-auto-commit-action@v4
id: auto-commit-action
with:
commit_message: Apply Code Coverage Badge
skip_fetch: true
skip_checkout: true
file_pattern: ./README.md

- name: Push Changes
if: steps.auto-commit-action.outputs.changes_detected == 'true'
uses: ad-m/github-push-action@master
with:
github_token: ${{ github.token }}
branch: ${{ github.ref }}

53 changes: 34 additions & 19 deletions delete.go
Original file line number Diff line number Diff line change
@@ -1,95 +1,110 @@
package obreron

type DeleteStament struct {
// DeleteStm represents a DELETE SQL statement builder.
// It provides a fluent interface for constructing DELETE queries.
type DeleteStm struct {
*stament
}

func Delete() *DeleteStament {
d := &DeleteStament{
stament: pool.New().(*stament),
func Delete() *DeleteStm {
d := &DeleteStm{
stament: pool.Get().(*stament),
}

d.add(deleteS, "DELETE", "")

return d
}

func (dst *DeleteStament) From(source string) *DeleteStament {
func (dst *DeleteStm) From(source string) *DeleteStm {
dst.add(fromS, "FROM", source)
return dst
}

func (dst *DeleteStament) Where(cond string, p ...any) *DeleteStament {
func (dst *DeleteStm) Where(cond string, p ...any) *DeleteStm {
dst.where(cond, p...)
return dst
}

func (dst *DeleteStament) Y() *DeleteStament {
func (dst *DeleteStm) Y() *DeleteStm {
dst.clause("AND", "")
return dst
}

func (dst *DeleteStament) And(expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) And(expr string, p ...any) *DeleteStm {
dst.clause("AND", expr, p...)
return dst
}

func (dst *DeleteStament) AndIf(cond bool, expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) AndIf(cond bool, expr string, p ...any) *DeleteStm {
if cond {
dst.clause("AND", expr, p...)
}
return dst
}

func (dst *DeleteStament) Or(expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) Or(expr string, p ...any) *DeleteStm {
dst.clause("OR", expr, p...)
return dst
}

func (dst *DeleteStament) OrIf(cond bool, expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) OrIf(cond bool, expr string, p ...any) *DeleteStm {
if cond {
dst.clause("OR", expr, p...)
}
return dst
}

func (dst *DeleteStament) Like(expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) Like(expr string, p ...any) *DeleteStm {
dst.clause("LIKE", expr, p...)
return dst
}

func (dst *DeleteStament) LikeIf(cond bool, expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) LikeIf(cond bool, expr string, p ...any) *DeleteStm {
if cond {
dst.Like(expr, p...)
}
return dst
}

func (dst *DeleteStament) In(value, expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) In(value, expr string, p ...any) *DeleteStm {
dst.clause(value+" IN ("+expr+")", "", p...)
return dst
}

func (dst *DeleteStament) Close() {
// InArgs adds an IN clause to the statement with automatically generated positional parameters.
// Example:
//
// Delete().From("users").Where("active = ?", true).InArgs("id", 1, 2, 3)
//
// Generates: DELETE FROM users WHERE active = ? AND id IN (?, ?, ?)
func (dst *DeleteStm) InArgs(value string, p ...any) *DeleteStm {
dst.stament.inArgs(value, p...)
return dst
}

// Close releases the statement back to the pool.
// After calling Close, the statement should not be used.
func (dst *DeleteStm) Close() {
closeStament(dst.stament)
}

func (dst *DeleteStament) OrderBy(expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) OrderBy(expr string, p ...any) *DeleteStm {
dst.add(limitS, "ORDER BY", expr, p...)
return dst
}

func (dst *DeleteStament) Limit(limit int) *DeleteStament {
func (dst *DeleteStm) Limit(limit int) *DeleteStm {
dst.add(limitS, "LIMIT", "?", limit)
return dst
}

func (dst *DeleteStament) Clause(clause, expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) Clause(clause, expr string, p ...any) *DeleteStm {
dst.add(dst.lastPos, clause, expr, p...)
return dst
}

func (dst *DeleteStament) ClauseIf(cond bool, clause, expr string, p ...any) *DeleteStament {
func (dst *DeleteStm) ClauseIf(cond bool, clause, expr string, p ...any) *DeleteStm {
if cond {
dst.Clause(clause, expr, p...)
}
Expand Down
53 changes: 52 additions & 1 deletion insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,59 @@ import (
"unsafe"
)

// InsertStament represents an insert stament
type InsertStament struct {
*stament
withSelect bool
}

// Insert Returns an insert stament
//
// # Example
//
// ins := Insert().Into("client").Col("name", "'some name'").Col("value", "'[email protected]'").ColIf(true, "data", "'some data'").ColIf(false, "info", 12)
//
// query, p := ins.Build()
//
// r, err := db.Exec(q, p...)
func Insert() *InsertStament {
i := &InsertStament{pool.New().(*stament), false}
i := &InsertStament{pool.Get().(*stament), false}
i.add(insertS, "INSERT", "")

i.firstCol = true

return i
}

// Ignore adds Ignore clause to the insert stament
//
// # Example
//
// ins := Insert().Ignore().Into("client").Col("name, value", "'some name'", "'[email protected]'")
//
// query, p := ins.Build()
//
// r, err := db.Exec(q, p...)
func (in *InsertStament) Ignore() *InsertStament {
in.add(insertS, "IGNORE", "")
return in
}

// Into adds into clause to the insert stament
func (in *InsertStament) Into(table string) *InsertStament {
in.add(insertS, "INTO", table)
return in
}

// Col adds columns and values to the insert clause
//
// # Example
//
// ins := insInsert().Col("name, value", "'some name'", "'[email protected]'").Into("client")
//
// query, p := ins.Build()
//
// r, err := db.Exec(q, p...)
func (in *InsertStament) Col(col string, p ...any) *InsertStament {

if !in.firstCol {
Expand All @@ -57,13 +86,33 @@ func (in *InsertStament) Col(col string, p ...any) *InsertStament {
return in
}

// ColIf adds columns and values to the insert clause when the cond parameter is true
//
// # Example
//
// ins := insInsert().ColIf(true, "name, value", "'some name'", "'[email protected]'").Into("client")
//
// query, p := ins.Build()
//
// r, err := db.Exec(q, p...)
func (in *InsertStament) ColIf(cond bool, col string, p ...any) *InsertStament {
if cond {
return in.Col(col, p...)
}
return in
}

// ColSelect is a helper method used to build insert select... staments
//
// # Example
//
// ins := Insert().Into("courses").ColSelectIf(true, "name, location, gid", Select().Col("name, location, 1").From("courses").Where("cid = 2")).ColSelectIf(false, "last_name, last_location, grid", Select().Col("last_name, last_location, 11").From("courses").Where("cid = 2"))
//
// query, p := ins.Build()
//
// r, err := db.Exec(q, p...)
//
// Produces: INSERT INTO courses ( name, location, gid ) SELECT name, location, 1 FROM courses WHERE cid = 2
func (in *InsertStament) ColSelect(col string, expr *SelectStm) *InsertStament {
in.firstCol = true
in.add(colsS, "(", col)
Expand All @@ -85,6 +134,7 @@ func (in *InsertStament) Clause(clause, expr string, p ...any) *InsertStament {
return in
}

// Build returns the query and the parameters as to be used by *sql.DB.query or *sql.DB.Exec
func (in *InsertStament) Build() (string, []any) {
b := bytes.Buffer{}

Expand Down Expand Up @@ -177,6 +227,7 @@ func posParams(i int, in *InsertStament, b *bytes.Buffer, buf []byte) {
}
}

// Close free resources used by the stament
func (in *InsertStament) Close() {
closeStament(in.stament)
}
29 changes: 29 additions & 0 deletions obreron.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package obreron
import (
"bytes"
"slices"
"strings"
"sync"
"unsafe"
)
Expand All @@ -14,6 +15,10 @@ var pool = &sync.Pool{
}

func closeStament(st *stament) {
if st == nil {
return
}

for i := range st.p {
st.p[i] = nil
}
Expand All @@ -27,6 +32,8 @@ func closeStament(st *stament) {
st.buff.Reset()

pool.Put(st)

st = nil
}

type segment struct {
Expand All @@ -47,6 +54,28 @@ func (st *stament) clause(clause, expr string, p ...any) {
st.add(st.lastPos, clause, expr, p...)
}

func (st *stament) inArgs(value string, p ...any) {

if len(p) == 0 {
st.clause(value+" IN ()", "")
return
}

if len(p) == 1 {
st.clause(value+" IN (?)", "", p...)
return
}

l := len(p)
var builder strings.Builder
builder.Grow(l * 2) // Pre-allocate capacity, fool!
builder.WriteString("?")
for i := 1; i < l; i++ {
builder.WriteString(", ?")
}
st.clause(value+" IN ("+builder.String()+")", "", p...)
}

func (st *stament) where(cond string, p ...any) {
if !st.whereAdded {
st.add(whereS, "WHERE", cond, p...)
Expand Down
Loading

0 comments on commit 5b03067

Please sign in to comment.