new/null-types #2

Merged
jake merged 10 commits from new/null-types into main 2026-01-23 19:59:06 +00:00
2 changed files with 92 additions and 11 deletions

8
.gitignore vendored
View File

@@ -15,13 +15,7 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# env file
.env
cmd/*

95
lazy.go
View File

@@ -1,12 +1,14 @@
package lazy
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"math/rand/v2"
"reflect"
"regexp"
"time"
"github.com/jmoiron/sqlx"
)
@@ -15,8 +17,15 @@ const (
DB_TAG = "db" //tag used to parse sql fields in example struct
LAZY_TAG = "lazy" //tag label for KEY_VALUE
KEY_VALUE = "key" //tag value for LAZY_TAG
//bind values
BindQuestion Binds = 1
BindDollar Binds = 2
BindNamed Binds = 3
BindAt Binds = 4
)
type Binds int
// mock data generated based on config
type Mock struct {
Query string
@@ -30,6 +39,7 @@ type Config struct {
Example any
Keys []any //length of keys must = RowCount, if set
RowCount int
BindType Binds
}
// generates mock data based on configuration to be used for sqlmock
@@ -81,7 +91,6 @@ func RandomGenerate(m Config) (*Mock, error) {
continue
}
//generate random values
nv := kindToRandom(field)
if nv == nil {
return nil, fmt.Errorf("could not match type: %s", retType.Name())
@@ -93,7 +102,7 @@ func RandomGenerate(m Config) (*Mock, error) {
return &Mock{
//sql is rebound and escaped for sqlmock.ExpectQuery
Query: sqlx.Rebind(sqlx.AT, regexp.QuoteMeta(m.Query)),
Query: sqlx.Rebind(int(m.BindType), regexp.QuoteMeta(m.Query)),
Columns: columns,
Rows: rows,
}, nil
@@ -101,6 +110,71 @@ func RandomGenerate(m Config) (*Mock, error) {
// converts basic reflect Kind's to psuedo-random data, slices are given a random amount of entries
func kindToRandom(field reflect.StructField) any {
//this isn't ideal, but since the sql types are structs they were being filled in a weird
//manner. For now we check those types first, and will clean this up later.
switch field.Type {
case reflect.TypeOf(sql.NullTime{}):
var temp sql.NullTime
if !isNull() {
temp.Valid = true
temp.Time = time.Now()
}
return temp
case reflect.TypeOf(sql.NullInt16{}):
var temp sql.NullInt16
if isNull() {
temp.Valid = false
} else {
temp.Valid = true
temp.Int16 = int16(rand.Int())
}
return temp
case reflect.TypeOf(sql.NullInt32{}):
var temp sql.NullInt32
if isNull() {
temp.Valid = false
} else {
temp.Valid = true
temp.Int32 = rand.Int32()
}
return temp
case reflect.TypeOf(sql.NullInt64{}):
var temp sql.NullInt64
if isNull() {
temp.Valid = false
} else {
temp.Valid = true
temp.Int64 = rand.Int64()
}
return temp
case reflect.TypeOf(sql.NullBool{}):
var temp sql.NullBool
if isNull() {
temp.Valid = false
} else {
temp.Valid = true
temp.Bool = (rand.Int()%2 == 0)
}
return temp
case reflect.TypeOf(sql.NullFloat64{}):
var temp sql.NullFloat64
if isNull() {
temp.Valid = false
} else {
temp.Valid = true
temp.Float64 = rand.Float64()
}
return temp
case reflect.TypeOf(sql.NullString{}):
var temp sql.NullString
if isNull() {
temp.Valid = false
} else {
temp.Valid = true
temp.String = fmt.Sprintf("random %d", rand.Int())
}
return temp
}
kind := field.Type.Kind()
switch kind {
case reflect.Int:
@@ -114,9 +188,11 @@ func kindToRandom(field reflect.StructField) any {
case reflect.Float64:
return rand.Float64()
case reflect.String:
return fmt.Sprintf("%d", rand.Int())
return fmt.Sprintf("random %d", rand.Int())
case reflect.Bool:
return rand.Int()%2 == 0
case reflect.TypeOf(time.Time{}).Kind():
return time.Now()
case reflect.Array:
underlying := field.Type.Elem().Kind()
count := reflect.ValueOf(field).Len() //fill entire length
@@ -201,7 +277,7 @@ func kindToRandom(field reflect.StructField) any {
case reflect.String:
var strslice []string
for x := 0; x < count; x++ {
strslice = append(strslice, fmt.Sprintf("%d", rand.Int()))
strslice = append(strslice, fmt.Sprintf("random %d", rand.Int()))
}
return strslice
case reflect.Bool:
@@ -215,3 +291,14 @@ func kindToRandom(field reflect.StructField) any {
return nil
}
// a quick and dirty rng function to determine if nulltypes are null or
// if we will generate a random value
func isNull() bool {
x := rand.IntN(2)
if x%2 == 0 {
return true
} else {
return false
}
}