From 750fc5c183e3ff0ed16c99cf5b67e711aec58731 Mon Sep 17 00:00:00 2001 From: FrancoLiberali Date: Fri, 12 Jan 2024 21:46:17 -0300 Subject: [PATCH] add docs of new cqllint detections --- cqllint/pkg/analyzer/analyzer.go | 2 +- .../pkg/analyzer/testdata/src/repeated/set.go | 2 +- docs/cql/concepts.rst | 2 +- docs/cql/cqllint.rst | 81 +++++++++++++++++-- docs/cql/tutorial.rst | 3 +- docs/cql/type_safety.rst | 2 +- 6 files changed, 80 insertions(+), 12 deletions(-) diff --git a/cqllint/pkg/analyzer/analyzer.go b/cqllint/pkg/analyzer/analyzer.go index 9faf12b..6bbd32b 100644 --- a/cqllint/pkg/analyzer/analyzer.go +++ b/cqllint/pkg/analyzer/analyzer.go @@ -155,7 +155,7 @@ func findRepeatedFields(call *ast.CallExpr, selectorExpr *ast.SelectorExpr) { if comparedFieldName == fieldName { passG.Reportf( comparedField.Sel.NamePos, - "%s is set to the same value", + "%s is set to itself", comparedFieldName, ) } diff --git a/cqllint/pkg/analyzer/testdata/src/repeated/set.go b/cqllint/pkg/analyzer/testdata/src/repeated/set.go index 20b2d18..99640a1 100644 --- a/cqllint/pkg/analyzer/testdata/src/repeated/set.go +++ b/cqllint/pkg/analyzer/testdata/src/repeated/set.go @@ -71,6 +71,6 @@ func testSetDynamicSameValue() { db, conditions.Product.Int.Is().Eq(0), ).Set( - conditions.Product.Int.Set().Dynamic(conditions.Product.Int.Value()), // want "conditions.Product.Int is set to the same value" + conditions.Product.Int.Set().Dynamic(conditions.Product.Int.Value()), // want "conditions.Product.Int is set to itself" ) } diff --git a/docs/cql/concepts.rst b/docs/cql/concepts.rst index 923ea56..1e4b409 100644 --- a/docs/cql/concepts.rst +++ b/docs/cql/concepts.rst @@ -132,7 +132,7 @@ The set of conditions that are received by the `cql.Query`, `cql.Update` and `cql.Delete` methods form the cql compiled query system. It is so named because the conditions will verify at compile time that the query to be executed is correct. -For details visit :ref:`cql/query:conditions` and :doc:`/cql/compile_time_safety`. +For details visit :ref:`cql/query:conditions` and :doc:`/cql/type_safety`. Conditions generation ---------------------------- diff --git a/docs/cql/cqllint.rst b/docs/cql/cqllint.rst index fcafac5..7af3cd7 100644 --- a/docs/cql/cqllint.rst +++ b/docs/cql/cqllint.rst @@ -7,11 +7,12 @@ cqllint 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 :ref:`cql/type_safety:Runtime errors`). -cqllint analyses the Go code written to detect these cases and fix them without the need to execute the query. +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 error cql.ErrFieldModelNotConcerned is detected. + 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. @@ -45,10 +46,13 @@ or using `go vet`: go vet -vettool=$(which cqllint) ./... -Example ----------------------------- +Errors +------------------------------- + +ErrFieldModelNotConcerned +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The simplest example of an error case is trying to make a comparison +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: .. code-block:: go @@ -75,4 +79,69 @@ 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. \ No newline at end of file +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: + +.. code-block:: go + :caption: example.go + :class: with-errors + :emphasize-lines: 5,6 + :linenos: + + _, err := cql.Update[models.Brand]( + db, + conditions.Brand.Name.Is().Eq("nike"), + ).Set( + conditions.Brand.Name.Set().Eq("adidas"), + conditions.Brand.Name.Set().Eq("puma"), + ) + +If we execute this query we will obtain an error of type `cql.ErrFieldIsRepeated` with the following message: + +.. code-block:: none + + field is repeated; field: models.Brand.Name; method: Set + +Now, if we run cqllint we will see the following report: + +.. code-block:: none + + $ 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: + +.. code-block:: go + :caption: example.go + :class: with-errors + :emphasize-lines: 5 + :linenos: + + _, err := cql.Update[models.Brand]( + db, + conditions.Brand.Name.Is().Eq("nike"), + ).Set( + conditions.Brand.Name.Set().Dynamic(conditions.Brand.Name.Value()), + ) + +If we run cqllint we will see the following report: + +.. code-block:: none + + $ cqllint ./... + example.go:5: conditions.Brand.Name is set to itself \ No newline at end of file diff --git a/docs/cql/tutorial.rst b/docs/cql/tutorial.rst index 9780d4b..179e60b 100644 --- a/docs/cql/tutorial.rst +++ b/docs/cql/tutorial.rst @@ -178,8 +178,7 @@ We can run this tutorial with `make tutorial_4` and we will obtain the following As you can see, again we get only the Paris in France. -In this tutorial we have used a condition that performs a join, -for more details you can read :ref:`cql/query:Use of the conditions`. +In this tutorial we have used a condition that performs a join. Tutorial 5: preloading ------------------------------- diff --git a/docs/cql/type_safety.rst b/docs/cql/type_safety.rst index a913cbe..c1ce1a0 100644 --- a/docs/cql/type_safety.rst +++ b/docs/cql/type_safety.rst @@ -191,7 +191,7 @@ there are still some possible cases that generate the following run-time errors: to the rest of the query (not joined). - cql.ErrJoinMustBeSelected: generated when you try to use a model that is included (joined) more than once in the query without selecting which one you want to use (see :ref:`cql/advanced_query:select join`). -- cql.ErrFieldIsRepeated: generated when a field is repeated inside a Set call (see :doc:`/cql/update`). +- cql.ErrFieldIsRepeated **(1)**: generated when a field is repeated inside a Set call (see :doc:`/cql/update`). - cql.ErrOnlyPreloadsAllowed: generated when trying to use conditions within a preload of collections (see :ref:`cql/advanced_query:collections`). - cql.ErrUnsupportedByDatabase: generated when an attempt is made to use a method or function that is not supported by the database engine used. - cql.ErrOrderByMustBeCalled: generated when in MySQL you try to do a delete/update with Limit but without using OrderBy.