agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
83 lines (73 loc) • 3.38 kB
JavaScript
/**
* @file Detect N+1 query patterns
* @description Single responsibility: Identify N+1 query anti-patterns in code
*/
const { iterateLines, isLoopPattern, hasEarlyExit } = require('../../../utils/patternDetector');
function detectNPlusOneQueries(lines, filePath) {
const issues = [];
iterateLines(lines, (line, lineNumber, trimmed, i) => {
// Look for loops that might contain database queries
if (isLoopPattern(trimmed)) {
// Check for database operations in loop body
for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
const innerLine = lines[j].trim();
// Database query patterns - focus on actual database/API operations
const dbPatterns = [
/\bModel\.\w+\s*\(/, // ORM model operations (with word boundary)
/\bdb\.\w+\s*\(/, // Database operations
/collection\.\w+\s*\(/, // MongoDB operations
/\.query\s*\(\s*['"`]/, // Direct SQL queries with quotes
/SELECT.*FROM.*WHERE/i, // Full SQL SELECT statements
/axios\.\w+\s*\(['"]/, // Axios HTTP calls
/fetch\s*\(\s*['"`]http/,// Fetch HTTP calls
/prisma\.\w+\.\w+\s*\(/, // Prisma ORM
/sequelize\.query\s*\(/, // Sequelize queries
/mongoose\.\w+\s*\(/ // Mongoose operations
];
const hasDbOperation = dbPatterns.some(pattern => pattern.test(innerLine));
if (hasDbOperation) {
// Determine severity based on pattern
const isDirectQuery = /SELECT.*FROM|\.query\s*\(/i.test(innerLine);
const isFind = /\.find\s*\(|\.findOne\s*\(/.test(innerLine);
issues.push({
type: 'n_plus_one_query',
severity: isDirectQuery ? 'CRITICAL' : 'HIGH',
category: 'Database',
location: `${filePath}:${j + 1}`,
line: j + 1,
code: innerLine,
description: 'Database query in loop - classic N+1 query problem',
summary: 'N+1 query pattern detected',
recommendation: isFind ? 'Use populate/include for eager loading or batch queries' :
'Collect IDs and use IN clause or batch operations',
effort: 3,
impact: '80-95% database performance improvement',
estimatedSavings: '80-95% query time reduction'
});
break; // Only report first occurrence per loop
}
}
}
// Nested loops with database operations (even worse)
if (/for\s*\(.*{.*for\s*\(|\.forEach.*{.*\.forEach/.test(line.replace(/\n/g, ' '))) {
if (/\.find\s*\(|\.query\s*\(|SELECT.*FROM/i.test(trimmed)) {
issues.push({
type: 'nested_query_loops',
severity: 'CRITICAL',
category: 'Database',
location: `${filePath}:${lineNumber}`,
line: lineNumber,
code: trimmed,
description: 'Nested loops with database queries - exponential query growth',
summary: 'Nested database query loops',
recommendation: 'Redesign to use batch operations or denormalize data',
effort: 4,
impact: '95-99% database performance improvement',
estimatedSavings: '95-99% query reduction'
});
}
}
});
return issues;
}
module.exports = detectNPlusOneQueries;