cqllint

cqllint is a Go linter that checks that cql queries will not generate run-time errors.

While, in most cases, queries created using cql are checked at compile time, there are still some cases that can generate run-time errors (see Runtime errors).

cqllint analyses the Go code written to detect these cases and fix them without the need to execute the query. It also adds other detections that would not generate runtime errors but are possible misuses of cql.

Note

At the moment, only the errors cql.ErrFieldModelNotConcerned and cql.ErrFieldIsRepeated are detected.

We recommend integrating cqllint into your CI so that the use of cql ensures 100% that your queries will be executed correctly.

Installation

For simply installing it, use:

go install github.com/FrancoLiberali/cql/cqllint@latest

Warning

The version of cqllint used must be the same as the version of cql. You can install a specific version using go install github.com/FrancoLiberali/cql/cqllint@vX.Y.Z, where X.Y.Z is the version number.

Execution

cqllint can be used independently by running:

cqllint ./...

or using go vet:

go vet -vettool=$(which cqllint) ./...

Errors

ErrFieldModelNotConcerned

The simplest example this error case is trying to make a comparison with an attribute of a model that is not joined by the query:

example.go
1_, err := cql.Query[models.Brand](
2    db,
3    conditions.Brand.Name.IsDynamic().Eq(conditions.City.Name.Value()),
4).Find()

If we execute this query we will obtain an error of type cql.ErrFieldModelNotConcerned with the following message:

field's model is not concerned by the query (not joined); not concerned model: models.City; operator: Eq; model: models.Brand, field: Name

Now, if we run cqllint we will see the following report:

$ cqllint ./...
example.go:3: models.City is not joined by the query

In this way, we will be able to correct this error without having to execute the query.

ErrFieldIsRepeated

The simplest example this error case is trying to set the value of an attribute twice:

example.go
1_, err := cql.Update[models.Brand](
2    db,
3    conditions.Brand.Name.Is().Eq("nike"),
4).Set(
5    conditions.Brand.Name.Set().Eq("adidas"),
6    conditions.Brand.Name.Set().Eq("puma"),
7)

If we execute this query we will obtain an error of type cql.ErrFieldIsRepeated with the following message:

field is repeated; field: models.Brand.Name; method: Set

Now, if we run cqllint we will see the following report:

$ cqllint ./...
example.go:5: conditions.Brand.Name is repeated
example.go:6: conditions.Brand.Name is repeated

In this way, we will be able to correct this error without having to execute the query.

Misuses

Although some cases would not generate runtime errors, cqllint will detect them as they are possible misuses of cql.

Set the same value

This case occurs when making a Set of exactly the same value:

example.go
1_, err := cql.Update[models.Brand](
2    db,
3    conditions.Brand.Name.Is().Eq("nike"),
4).Set(
5    conditions.Brand.Name.Set().Dynamic(conditions.Brand.Name.Value()),
6)

If we run cqllint we will see the following report:

$ cqllint ./...
example.go:5: conditions.Brand.Name is set to itself