Skip to content

Avoiding Code Duplication with the Select Builder

Vinícius Garcia edited this page Jul 4, 2022 · 1 revision

The Select Generator Feature

There are good reasons not to use SELECT * queries the most important of them is that you might end up loading more information than you are actually going to use putting more pressure on your database for no good reason.

To prevent that KSQL has a feature specifically for building the SELECT part of the query using the tags from the input struct. Using it is very simple and it works with all the 3 Query* functions:

Querying a single user:

var user User
err = db.QueryOne(ctx, &user, "FROM users WHERE id = ?", userID)
if err != nil {
	panic(err.Error())
}

Querying a page of users:

var users []User
err = db.Query(ctx, &users, "FROM users WHERE type = ? ORDER BY id LIMIT ? OFFSET ?", "Cristina", limit, offset)
if err != nil {
	panic(err.Error())
}

Querying all the users, or any potentially big number of users, from the database (not usual, but supported):

err = db.QueryChunks(ctx, ksql.ChunkParser{
	Query:     "FROM users WHERE type = ?",
	Params:    []interface{}{usersType},
	ChunkSize: 100,
	ForEachChunk: func(users []User) error {
		err := sendUsersSomewhere(users)
		if err != nil {
			// This will abort the QueryChunks loop and return this error
			return err
		}
		return nil
	},
})
if err != nil {
	panic(err.Error())
}

The implementation of this feature is actually simple internally:

First, we check if the query starts with the word FROM, if it does then we just get the KSQL tags from the struct and then use it for building the SELECT statement.

The SELECT statement is then cached so we don't have to build it again the next time making this process very efficient.