From 1f02dfb847183983ecaac17c6d410b449478c4af Mon Sep 17 00:00:00 2001 From: Elise DUBILLOT Date: Tue, 25 Jul 2023 14:11:56 +0200 Subject: [PATCH] add rule limit-db-query-results --- CHANGELOG.md | 25 ++++---- eslint-plugin/README.md | 18 +++--- .../docs/rules/limit-db-query-results.md | 23 +++++++ .../lib/rules/limit-db-query-results.js | 55 ++++++++++++++++ .../tests/lib/rules/limit-db-query-results.js | 62 +++++++++++++++++++ 5 files changed, 159 insertions(+), 24 deletions(-) create mode 100644 eslint-plugin/docs/rules/limit-db-query-results.md create mode 100644 eslint-plugin/lib/rules/limit-db-query-results.js create mode 100644 eslint-plugin/tests/lib/rules/limit-db-query-results.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c4df01..83dbd03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [#19](https://github.com/green-code-initiative/ecoCode-javascript/pull/19) add rule `@ecocode/no-empty-image-src-attribute` +- [#18](https://github.com/green-code-initiative/ecoCode-javascript/pull/18) add rule `@ecocode/limit-db-query-results` - [#14](https://github.com/green-code-initiative/ecoCode-javascript/pull/14) Create SonarQube plugin - [#12](https://github.com/green-code-initiative/ecoCode-javascript/issues/12) Pack ESLint plugin into SonarQube plugin - [#16](https://github.com/green-code-initiative/ecoCode-javascript/pull/16) Use centralized rules specifications @@ -24,25 +25,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add support for TypeScript rules with **typescript-eslint** -- Add rule `@ecocode/avoid-high-accuracy-geolocation` -- Add rule `@ecocode/no-import-all-from-library` -- Add rule `@ecocode/no-multiple-style-changes` -- Add rule `@ecocode/prefer-collections-with-pagination` +- Add support for TypeScript rules with **typescript-eslint** +- Add rule `@ecocode/avoid-high-accuracy-geolocation` +- Add rule `@ecocode/no-import-all-from-library` +- Add rule `@ecocode/no-multiple-style-changes` +- Add rule `@ecocode/prefer-collections-with-pagination` ## [0.1.0] - 2023-03-24 ### Added -- First alpha version of the ESLint plugin 🚀 -- Add rule `@ecocode/no-multiple-access-dom-element` -- Create tooling script to generate SonarQube rules -- Setup mocha and nyc for tests and coverage -- Setup basic coding style tools -- Write complete contributing guide +- First alpha version of the ESLint plugin 🚀 +- Add rule `@ecocode/no-multiple-access-dom-element` +- Create tooling script to generate SonarQube rules +- Setup mocha and nyc for tests and coverage +- Setup basic coding style tools +- Write complete contributing guide [Unreleased]: https://github.com/green-code-initiative/ecoCode-linter/compare/eslint-plugin/0.2.0...HEAD - [0.2.0]: https://github.com/green-code-initiative/ecoCode-linter/compare/eslint-plugin/0.1.0...eslint-plugin/0.2.0 - [0.1.0]: https://github.com/green-code-initiative/ecoCode-linter/compare/6d305511db82bf8faa4833528641535e605dbacf...eslint-plugin/0.1.0 diff --git a/eslint-plugin/README.md b/eslint-plugin/README.md index 768adb9..4041abb 100644 --- a/eslint-plugin/README.md +++ b/eslint-plugin/README.md @@ -1,5 +1,4 @@ -![Logo](https://github.com/green-code-initiative/ecoCode/blob/main/docs/resources/logo-large.png?raw=true) -====================================== +# ![Logo](https://github.com/green-code-initiative/ecoCode/blob/main/docs/resources/logo-large.png?raw=true) An ESLint plugin which provides JavaScript and TypeScript rules of the ecoCode project. @@ -7,8 +6,7 @@ An ESLint plugin which provides JavaScript and TypeScript rules of the ecoCode p > ⚠️ This plugin is in a very early stage and need improvements. Any contribution will be appreciated. -🚀 Getting started ------------------- +## 🚀 Getting started ### Installation @@ -48,17 +46,17 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c } ``` -🔨 Rules --------- +## 🔨 Rules ⚠️ Configurations set to warn in.\ ✅ Set in the `recommended` configuration. -| Name | Description | ⚠️ | -| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :- | +| Name | Description | ⚠️ | +| :------------------------------------------------------------------------------------- | :--------------------------------------------------------- | :-- | | [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md) | Avoid using high accuracy geolocation in web applications. | ✅ | +| [limit-db-query-results](docs/rules/limit-db-query-results.md) | Should limit the number of returns for a SQL query | ✅ | | [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md) | Disallow usage of image with empty source attribute | ✅ | | [no-import-all-from-library](docs/rules/no-import-all-from-library.md) | Should not import all from library | ✅ | | [no-multiple-access-dom-element](docs/rules/no-multiple-access-dom-element.md) | Disallow multiple access of same DOM element. | ✅ | @@ -67,8 +65,6 @@ Add `@ecocode` to the `plugins` section of your `.eslintrc`, followed by rules c - -🛒 Distribution ---------------- +## 🛒 Distribution You can follow changelog on [GitHub Releases page](https://github.com/green-code-initiative/ecoCode-linter/releases). diff --git a/eslint-plugin/docs/rules/limit-db-query-results.md b/eslint-plugin/docs/rules/limit-db-query-results.md new file mode 100644 index 0000000..4626876 --- /dev/null +++ b/eslint-plugin/docs/rules/limit-db-query-results.md @@ -0,0 +1,23 @@ +# Should limit the number of returns for a SQL query (`@ecocode/limit-db-query-results`) + +⚠️ This rule _warns_ in the ✅ `recommended` config. + + + +## Rule Details + +This rule aims at reducing CPU consumption by limiting the number of returns for a single SQL query. + +## Examples + +Examples of **non compliant** code for this rule: + +```js +const query = "SELECT * FROM clients"; +``` + +Examples of **compliant** code for this rule: + +```js +const query = "SELECT columns FROM table_name FETCH FIRST number ROWS ONLY"; +``` diff --git a/eslint-plugin/lib/rules/limit-db-query-results.js b/eslint-plugin/lib/rules/limit-db-query-results.js new file mode 100644 index 0000000..9a7b2e7 --- /dev/null +++ b/eslint-plugin/lib/rules/limit-db-query-results.js @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2023 Green Code Initiative + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +"use strict"; + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: "suggestion", + docs: { + description: "Should limit the number of returns for a SQL query", + category: "eco-design", + recommended: "warn", + }, + messages: { + LimitTheNumberOfReturns: + "Try and limit the number of data returned for a single query (by using the LIMIT keyword for example)", + }, + schema: [], + }, + create(context) { + //list of limiting clauses to check against + const limitingClauses = ["LIMIT", "TOP", "ROW_NUMBER", "FETCH FIRST"]; + return { + Literal: function (node) { + if (typeof node.value == "string") { + const query = node.value.toUpperCase(); + if ( + query.includes("SELECT") && + query.includes("FROM") && + !limitingClauses.some((clause) => query.includes(clause)) + ) { + context.report({ + node: node, + messageId: "LimitTheNumberOfReturns", + }); + } + } + }, + }; + }, +}; diff --git a/eslint-plugin/tests/lib/rules/limit-db-query-results.js b/eslint-plugin/tests/lib/rules/limit-db-query-results.js new file mode 100644 index 0000000..6658c42 --- /dev/null +++ b/eslint-plugin/tests/lib/rules/limit-db-query-results.js @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2023 Green Code Initiative + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +"use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/limit-db-query-results"), + RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 6, + sourceType: "module", + }, +}); +const expectedError = { + messageId: "LimitTheNumberOfReturns", + type: "Literal", +}; + +ruleTester.run("limit-db-query-results", rule, { + valid: [ + ` + const query = "SELECT * FROM customers LIMIT 10;"; + `, + ` + const query = "SELECT TOP 5 * FROM products;"; + `, + ` + const query = "SELECT * FROM orders FETCH FIRST 20 ROWS ONLY;"; + `, + ` + const query = "WITH numbered_customers AS (SELECT *, ROW_NUMBER() OVER (ORDER BY customer_id) AS row_num FROM customers) SELECT * FROM numbered_customers WHERE row_num <= 50;"; + `, + ], + + invalid: [ + { + code: `const query = "SELECT * FROM bikes;";`, + errors: [expectedError], + }, + ], +});