diff --git a/.gitignore b/.gitignore index 5b90e79..f3b4020 100644 --- a/.gitignore +++ b/.gitignore @@ -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/* \ No newline at end of file diff --git a/lazy.go b/lazy.go index 4a7bcc4..db5bc7e 100644 --- a/lazy.go +++ b/lazy.go @@ -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 + } +}