Skip to content

DbMap.Select fails when passed only one parameter *time.Time. #431

Description

@yuroyoro

When only one *time.Time is passed to DbMap.Select , it returns an error.
not enough args to execute query: want 1 got 0

If the number of parameters is 2 or more, passing *time.Time works fine.
And only one time.Time (not pointer) works.

It may be caused by maybeExpandNamedQuery does not support pointer of time.Time.

gorp/gorp.go

Line 207 in 80a2f4b

func maybeExpandNamedQuery(m *DbMap, query string, args []interface{}) (string, []interface{}) {

Is it a specification that *time.Time is not supported as a parameter?
I think that Gorp should be able to work with only one *time.Time as well as with more than one parameter.

Here is a reproduction test code to get error.

package main

import (
	"database/sql"
	"log"
	"time"

	"github.com/go-gorp/gorp/v3"
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	// initialize the DbMap
	dbmap := initDb()
	defer dbmap.Db.Close()

	// delete any existing rows
	err := dbmap.TruncateTables()
	checkErr(err, "TruncateTables failed")

	// create two posts
	p1 := newPost("Go 1.1 released!", "Lorem ipsum lorem ipsum")
	p2 := newPost("Go 1.2 released!", "Lorem ipsum lorem ipsum")

	// insert rows - auto increment PKs will be set properly after the insert
	err = dbmap.Insert(&p1, &p2)
	checkErr(err, "Insert failed")

	from := time.Now().Add(-10 * time.Second)
	to := time.Now().Add(10 * time.Second)

	// fetch all rows
	var posts []Post

	// pass two parameters (*time.Time and *time.Time)  -> ok
	_, err = dbmap.Select(&posts, "select * from posts where created_at >= ? and created_at < ?", &from, &to)
	checkErr(err, "Select failed")
	log.Println("Rows filtered by two *time.Time parameters:", len(posts))

	// pass only one parameter that is not pointer (time.Time)  -> ok
	posts = nil
	_, err = dbmap.Select(&posts, "select * from posts where created_at > ?", from)
	checkErr(err, "select failed")
	log.Println("Rows filtered by only one time.Time parameter:", len(posts))

	// pass only one parameter (*time.Time)  -> failed
	posts = nil
	_, err = dbmap.Select(&posts, "select * from posts where created_at > ?", &from)
	checkErr(err, "select failed")
	log.Println("Rows filtered by only one *time.Time parameter:", len(posts))

	log.Println("Done!")
}

type Post struct {
	// db tag lets you specify the column name if it differs from the struct field
	Id        int64     `db:"post_id"`
	CreatedAt time.Time `db:"created_at"`
	Title     string    `db:",size:50"`               // Column size set to 50
	Body      string    `db:"article_body,size:1024"` // Set both column name and size
}

func newPost(title, body string) Post {
	return Post{
		CreatedAt: time.Now(),
		Title:     title,
		Body:      body,
	}
}

func initDb() *gorp.DbMap {
	// connect to db using standard Go database/sql API
	// use whatever database/sql driver you wish
	db, err := sql.Open("sqlite3", "/tmp/post_db.bin")
	checkErr(err, "sql.Open failed")

	// construct a gorp DbMap
	dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}

	// add a table, setting the table name to 'posts' and
	// specifying that the Id property is an auto incrementing PK
	dbmap.AddTableWithName(Post{}, "posts").SetKeys(true, "Id")

	// create the table. in a production system you'd generally
	// use a migration tool, or create the tables via scripts
	err = dbmap.CreateTablesIfNotExists()
	checkErr(err, "Create tables failed")

	return dbmap
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions