Skip to content

Commit

Permalink
SONARPLSQL-805 S3921: Update RSPEC to mention data dictionary (#4544)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastien-marichal authored Nov 27, 2024
1 parent d046613 commit 0a7e283
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 96 deletions.
60 changes: 36 additions & 24 deletions rules/S3618/plsql/rule.adoc
Original file line number Diff line number Diff line change
@@ -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
(
N1
)
VALUES
(
1
)
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
(
1
)
----

=== Compliant solution

[source,sql]
[source,sql,diff-id=1,diff-type=compliant]
----
INSERT INTO MY_TABLE -- Compliant even though N3 value not supplied
(
N1,
N2
)
VALUES
(
1,
'Paul'
)
INSERT INTO MY_TABLE -- Compliant; N3 has a default value
(
N1,
N2
)
VALUES
(
1,
'Paul'
)
----

ifdef::env-github,rspecator-view[]
Expand Down
15 changes: 0 additions & 15 deletions rules/S3641/compliant.adoc

This file was deleted.

30 changes: 30 additions & 0 deletions rules/S3641/how.adoc
Original file line number Diff line number Diff line change
@@ -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)
----
8 changes: 0 additions & 8 deletions rules/S3641/noncompliant.adoc

This file was deleted.

13 changes: 4 additions & 9 deletions rules/S3641/plsql/rule.adoc
Original file line number Diff line number Diff line change
@@ -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[]

Expand Down
4 changes: 1 addition & 3 deletions rules/S3641/tsql/rule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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[]

Expand Down
48 changes: 33 additions & 15 deletions rules/S3651/plsql/rule.adoc
Original file line number Diff line number Diff line change
@@ -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
...
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
CREATE TABLE Product
(
Id INT,
Name VARCHAR(6),
Price INT NOT NULL
)
----


==== 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[]
Expand Down
64 changes: 42 additions & 22 deletions rules/S3921/plsql/rule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
----
create table persons (id number, name varchar2(4));
== How to fix it

insert into persons (id, name) values (1, 'Alice'); -- Noncompliant, raises ORA-12899
Ensure that the size of the variable or column is large enough to hold the value.

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;
----
=== Code examples

=== Compliant solution
==== Noncompliant code example

[source,sql]
[source,sql,diff-id=1,diff-type=noncompliant]
----
CREATE TABLE Persons
(
Id NUMBER,
Name VARCHAR2(4)
);
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 table persons (id number, name varchar2(8));

insert into persons (id, name) values (1, 'Alice');
==== Compliant solution

create or replace procedure sp1
is
foo varchar2(8);
begin
select name into foo from persons where id = 1;
end;
[source,sql,diff-id=1,diff-type=compliant]
----
CREATE TABLE Persons
(
Id NUMBER,
Name VARCHAR2(8)
);
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;
----

== 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[]
Expand Down
3 changes: 3 additions & 0 deletions shared_content/plsql/data_dictionary.adoc
Original file line number Diff line number Diff line change
@@ -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/

0 comments on commit 0a7e283

Please sign in to comment.