Files
goext/sq/builderUnit_test.go
T
Mikescher 02d6894ec6
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m34s
[🤖] Add Unit-Tests
2026-04-27 16:31:29 +02:00

214 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sq
import (
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
"strings"
"testing"
)
func TestBuildInsertStatementBasic(t *testing.T) {
type r struct {
ID string `db:"id"`
Name string `db:"name"`
}
q := fakeQueryable{}
sqlstr, pp, err := BuildInsertStatement(q, "users", r{ID: "1", Name: "alice"})
tst.AssertNoErr(t, err)
tst.AssertTrue(t, strings.HasPrefix(sqlstr, "INSERT INTO users ("))
tst.AssertTrue(t, strings.Contains(sqlstr, "id"))
tst.AssertTrue(t, strings.Contains(sqlstr, "name"))
tst.AssertEqual(t, 2, len(pp))
values := []any{}
for _, v := range pp {
values = append(values, v)
}
hasID, hasName := false, false
for _, v := range values {
if vs, ok := v.(string); ok {
if vs == "1" {
hasID = true
}
if vs == "alice" {
hasName = true
}
}
}
tst.AssertTrue(t, hasID)
tst.AssertTrue(t, hasName)
}
func TestBuildInsertStatementSkipsUnexported(t *testing.T) {
type r struct {
ID string `db:"id"`
hidden string `db:"hidden"` //nolint:unused
}
q := fakeQueryable{}
sqlstr, pp, err := BuildInsertStatement(q, "users", r{ID: "1"})
tst.AssertNoErr(t, err)
tst.AssertEqual(t, 1, len(pp))
tst.AssertTrue(t, !strings.Contains(sqlstr, "hidden"))
}
func TestBuildInsertStatementSkipsNoTagAndDash(t *testing.T) {
type r struct {
ID string `db:"id"`
Skip1 string `db:"-"`
Skip2 string
}
q := fakeQueryable{}
sqlstr, pp, err := BuildInsertStatement(q, "users", r{ID: "1", Skip1: "x", Skip2: "y"})
tst.AssertNoErr(t, err)
tst.AssertEqual(t, 1, len(pp))
tst.AssertTrue(t, !strings.Contains(sqlstr, "Skip"))
}
func TestBuildInsertStatementNoFields(t *testing.T) {
type r struct {
Skip string
}
q := fakeQueryable{}
_, _, err := BuildInsertStatement(q, "x", r{})
if err == nil {
t.Fatal("expected error for no usable fields")
}
}
func TestBuildInsertStatementNilPointer(t *testing.T) {
type r struct {
ID string `db:"id"`
Note *string `db:"note"`
}
q := fakeQueryable{}
sqlstr, pp, err := BuildInsertStatement(q, "users", r{ID: "1", Note: nil})
tst.AssertNoErr(t, err)
// Only id is parameterized; nil pointer becomes literal NULL
tst.AssertEqual(t, 1, len(pp))
tst.AssertTrue(t, strings.Contains(sqlstr, "NULL"))
}
func TestBuildInsertStatementWithConverter(t *testing.T) {
type r struct {
ID string `db:"id"`
Flag bool `db:"flag"`
}
q := fakeQueryable{converters: []DBTypeConverter{ConverterBoolToBit}}
_, pp, err := BuildInsertStatement(q, "users", r{ID: "1", Flag: true})
tst.AssertNoErr(t, err)
tst.AssertEqual(t, 2, len(pp))
foundOne := false
for _, v := range pp {
if vi, ok := v.(int64); ok && vi == 1 {
foundOne = true
}
}
tst.AssertTrue(t, foundOne)
}
func TestBuildUpdateStatementBasic(t *testing.T) {
type r struct {
ID string `db:"id"`
Name string `db:"name"`
}
q := fakeQueryable{}
sqlstr, pp, err := BuildUpdateStatement(q, "users", r{ID: "1", Name: "alice"}, "id")
tst.AssertNoErr(t, err)
tst.AssertTrue(t, strings.HasPrefix(sqlstr, "UPDATE users SET "))
tst.AssertTrue(t, strings.Contains(sqlstr, "name = :"))
tst.AssertTrue(t, strings.Contains(sqlstr, "(id = :"))
tst.AssertEqual(t, 2, len(pp))
}
func TestBuildUpdateStatementMissingID(t *testing.T) {
type r struct {
Name string `db:"name"`
}
q := fakeQueryable{}
_, _, err := BuildUpdateStatement(q, "users", r{Name: "alice"}, "id")
if err == nil {
t.Fatal("expected error for missing id column")
}
}
func TestBuildUpdateStatementOnlyID(t *testing.T) {
type r struct {
ID string `db:"id"`
}
q := fakeQueryable{}
_, _, err := BuildUpdateStatement(q, "users", r{ID: "1"}, "id")
if err == nil {
t.Fatal("expected error when no SET clauses")
}
}
func TestBuildUpdateStatementNilPointer(t *testing.T) {
type r struct {
ID string `db:"id"`
Note *string `db:"note"`
}
q := fakeQueryable{}
sqlstr, _, err := BuildUpdateStatement(q, "users", r{ID: "1", Note: nil}, "id")
tst.AssertNoErr(t, err)
tst.AssertTrue(t, strings.Contains(sqlstr, "note = NULL"))
}
func TestBuildInsertMultipleStatementBasic(t *testing.T) {
type r struct {
ID string `db:"id"`
Name string `db:"name"`
}
q := fakeQueryable{}
sqlstr, pp, err := BuildInsertMultipleStatement(q, "users", []r{
{ID: "1", Name: "alice"},
{ID: "2", Name: "bob"},
})
tst.AssertNoErr(t, err)
tst.AssertTrue(t, strings.Contains(sqlstr, `INSERT INTO "users"`))
tst.AssertTrue(t, strings.Contains(sqlstr, `"id"`))
tst.AssertTrue(t, strings.Contains(sqlstr, `"name"`))
// 2 rows × 2 fields = 4 placeholders
tst.AssertEqual(t, 4, len(pp))
// Two value tuples should appear -> exactly one "), (" separator
tst.AssertEqual(t, 1, strings.Count(sqlstr, "), ("))
}
func TestBuildInsertMultipleStatementEmpty(t *testing.T) {
type r struct {
ID string `db:"id"`
}
q := fakeQueryable{}
_, _, err := BuildInsertMultipleStatement(q, "x", []r{})
if err == nil {
t.Fatal("expected error for empty input")
}
}
func TestBuildInsertMultipleStatementNilPointer(t *testing.T) {
type r struct {
ID string `db:"id"`
Note *string `db:"note"`
}
q := fakeQueryable{}
sqlstr, _, err := BuildInsertMultipleStatement(q, "users", []r{{ID: "1", Note: nil}})
tst.AssertNoErr(t, err)
tst.AssertTrue(t, strings.Contains(sqlstr, "NULL"))
}