SONARPLSQL-805 S3921: Update RSPEC to mention data dictionary (#4544)

This commit is contained in:
Sebastien Marichal 2024-11-27 14:11:29 +01:00 committed by GitHub
parent d04661341c
commit 0a7e283d1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 146 additions and 93 deletions

View File

@ -1,42 +1,54 @@
== Why is this an issue?
Any insert which omits a value for a ``++NOT NULL++`` column in a database table will be automatically rejected by the database unless a default value has been specified for the column.
Any insert which omits a value for a `NOT NULL` column in a database table will be automatically rejected by the database unless a default value has been specified for the column.
include::../../../shared_content/plsql/data_dictionary.adoc[]
*Noteworthy*
== How to fix it
This rule raises issues only when a *Data Dictionary* is provided during the analysis. See https://docs.sonarqube.org/latest/analysis/languages/plsql/
Ensure that all `NOT NULL` columns have a value specified in the `INSERT` statement.
=== Noncompliant code example
=== Code examples
With the table ``++MY_TABLE++`` having a ``++NOT NULL++`` column ``++N2++`` without default value and a ``++NOT NULL++`` column ``++N3++`` with default value:
Given the following table:
[source,sql]
----
INSERT INTO MY_TABLE -- Noncompliant; N2 value omitted
(
CREATE TABLE MY_TABLE (
N1 NUMBER NOT NULL,
N2 VARCHAR2(50) NOT NULL,
N3 VARCHAR2(50) DEFAULT 'Default Value'
);
----
==== Noncompliant code example
[source,sql,diff-id=1,diff-type=noncompliant]
----
INSERT INTO MY_TABLE -- Noncompliant; N2 value omitted
(
N1
)
VALUES
(
)
VALUES
(
1
)
)
----
=== Compliant solution
[source,sql]
[source,sql,diff-id=1,diff-type=compliant]
----
INSERT INTO MY_TABLE -- Compliant even though N3 value not supplied
(
INSERT INTO MY_TABLE -- Compliant; N3 has a default value
(
N1,
N2
)
VALUES
(
)
VALUES
(
1,
'Paul'
)
)
----
ifdef::env-github,rspecator-view[]

View File

@ -1,15 +0,0 @@
=== Compliant solution
[source,text]
----
SELECT *
FROM my_table
WHERE NOT EXISTS (SELECT 1 FROM another_table WHERE nullable_column = my_table.my_column)
----
[source,text]
----
SELECT *
FROM my_table
WHERE my_column NOT IN (SELECT nullable_column FROM another_table WHERE nullable_column IS NOT NULL)
----

30
rules/S3641/how.adoc Normal file
View File

@ -0,0 +1,30 @@
== How to fix it
Use `NOT EXISTS` or `IS NOT NULL` instead of `NOT IN` when the subquery may return `NULL` values.
=== Code examples
==== Noncompliant code example
[source,sql]
----
SELECT *
FROM my_table
WHERE my_column NOT IN (SELECT nullable_column FROM another_table) -- Noncompliant; "nullable_column" may contain 'NULL' value and the whole SELECT query will return nothing
----
==== Compliant solution
[source,sql]
----
SELECT *
FROM my_table
WHERE NOT EXISTS (SELECT 1 FROM another_table WHERE nullable_column = my_table.my_column)
----
[source,sql]
----
SELECT *
FROM my_table
WHERE my_column NOT IN (SELECT nullable_column FROM another_table WHERE nullable_column IS NOT NULL)
----

View File

@ -1,8 +0,0 @@
=== Noncompliant code example
[source,text]
----
SELECT *
FROM my_table
WHERE my_column NOT IN (SELECT nullable_column FROM another_table) -- Noncompliant; "nullable_column" may contain 'NULL' value and the whole SELECT query will return nothing
----

View File

@ -1,17 +1,12 @@
== Why is this an issue?
A WHERE clause condition that uses NOT IN with a subquery will have unexpected results if that subquery returns NULL. On the other hand NOT EXISTS subqueries work reliably under the same conditions.
A `WHERE` clause condition that uses `NOT IN` with a subquery will have unexpected results if that subquery returns `NULL`. On the other hand `NOT EXISTS` subqueries work reliably under the same conditions.
This rule raises an issue when NOT IN is used with a subquery where the selected column is nullable.
This rule raises an issue when `NOT IN` is used with a subquery where the selected column is nullable.
include::../../../shared_content/plsql/data_dictionary.adoc[]
*Noteworthy*
This rule raises issues only when a *Data Dictionary* is provided during the analysis. See https://docs.sonarqube.org/latest/analysis/languages/plsql/
include::../noncompliant.adoc[]
include::../compliant.adoc[]
include::../how.adoc[]
ifdef::env-github,rspecator-view[]

View File

@ -5,9 +5,7 @@ A ``++WHERE++`` clause condition that uses ``++NOT IN++`` with a subquery will h
This rule raises an issue when ``++NOT IN++`` is used with a subquery. This rule doesn't check if the selected column is a nullable column because the rules engine has no information about the table definition. It's up to the developer to review manually if the column is nullable.
include::../noncompliant.adoc[]
include::../compliant.adoc[]
include::../how.adoc[]
ifdef::env-github,rspecator-view[]

View File

@ -1,27 +1,45 @@
== Why is this an issue?
``++WHERE++`` clause conditions that reinforce or contradict the definitions of their columns are useless; they are always either unconditionally true or unconditionally false. For instance, there's no point in including ``++AND column IS NOT NULL++`` if the column is defined as non-null.
Conditions in the `WHERE` clause that either reinforce or contradict the definitions of their columns are redundant, as they are always either unconditionally true or unconditionally false. For example, including `AND column IS NOT NULL` is unnecessary if the column is already defined as non-null.
include::../../../shared_content/plsql/data_dictionary.adoc[]
*Noteworthy*
== How to fix it
This rule raises issues only when a *Data Dictionary* is provided during the analysis. See https://docs.sonarqube.org/latest/analysis/languages/plsql/
Ensure that the conditions in the `WHERE` clause are not always true or false.
=== Noncompliant code example
=== Code examples
Given the following table:
[source,sql]
----
CREATE TABLE product
(id INT,
name VARCHAR(6) NOT NULL,
mfg_name VARCHAR(6),
mfg_id INT
...
CREATE TABLE Product
(
Id INT,
Name VARCHAR(6),
Price INT NOT NULL
)
----
SELECT name, price
FROM product
WHERE name is not null -- Noncompliant; always true. This column is NOT NULL
AND mfg_name = 'Too long name' -- Noncompliant; always false. This column can contain only 6 characters
==== Noncompliant code example
[source,sql,diff-id=1,diff-type=noncompliant]
----
SELECT Name, Price FROM Product
WHERE
Name = 'Too long name' -- Noncompliant; always false. This column can contain only 6 characters
AND Price IS NOT NULL -- Noncompliant; always true. This column is NOT NULL
----
==== Compliant solution
[source,sql,diff-id=1,diff-type=compliant]
----
SELECT Name, Price FROM Product
WHERE
Name = 'Name'
----
ifdef::env-github,rspecator-view[]

View File

@ -2,41 +2,61 @@
Trying to assign a large character value to a smaller variable or column will raise an error.
=== Noncompliant code example
include::../../../shared_content/plsql/data_dictionary.adoc[]
[source,sql]
== How to fix it
Ensure that the size of the variable or column is large enough to hold the value.
=== Code examples
==== Noncompliant code example
[source,sql,diff-id=1,diff-type=noncompliant]
----
create table persons (id number, name varchar2(4));
CREATE TABLE Persons
(
Id NUMBER,
Name VARCHAR2(4)
);
insert into persons (id, name) values (1, 'Alice'); -- Noncompliant, raises ORA-12899
INSERT INTO Persons (Id, Name) VALUES (1, 'Alice'); -- Noncompliant, raises ORA-12899
create or replace procedure sp1
is
foo varchar2(2);
begin
select name into foo from persons where id = 1; -- Noncompliant, may raise ORA-06502
end;
CREATE OR REPLACE PROCEDURE sp1
IS
foo VARCHAR2(2);
BEGIN
SELECT Name INTO foo FROM Persons WHERE Id = 1; -- Noncompliant, may raise ORA-06502
END;
----
=== Compliant solution
==== Compliant solution
[source,sql]
[source,sql,diff-id=1,diff-type=compliant]
----
create table persons (id number, name varchar2(8));
CREATE TABLE Persons
(
Id NUMBER,
Name VARCHAR2(8)
);
insert into persons (id, name) values (1, 'Alice');
INSERT INTO Persons (Id, Name) VALUES (1, 'Alice');
create or replace procedure sp1
is
foo varchar2(8);
begin
select name into foo from persons where id = 1;
end;
CREATE OR REPLACE PROCEDURE sp1
IS
foo VARCHAR2(8);
BEGIN
SELECT Name INTO foo FROM Persons WHERE Id = 1;
END;
----
== Resources
=== Documentation
* CWE - https://cwe.mitre.org/data/definitions/704[CWE-704 - Incorrect Type Conversion or Cast]
* Oracle Database - https://docs.oracle.com/en/error-help/db/ora-12899[ORA-12899]
* Oracle Database - https://docs.oracle.com/en/error-help/db/ora-06502[ORA-06502]
ifdef::env-github,rspecator-view[]

View File

@ -0,0 +1,3 @@
=== Noteworthy
This rule raises issues only when a *Data Dictionary* is provided during the analysis. See{nbsp}https://docs.sonarqube.org/latest/analysis/languages/plsql/