UNPKG

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
/** * @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;