MCPcopy Create free account
hub / github.com/bytebase/dbhub / countParameters

Function countParameters

src/utils/parameter-mapper.ts:91–144  ·  view source on GitHub ↗
(statement: string)

Source from the content-addressed store, hash-verified

89 * @throws Error if numbered/named parameters are not sequential starting from 1
90 */
91export function countParameters(statement: string): number {
92 const style = detectParameterStyle(statement);
93 // Strip comments and strings to avoid matching parameters inside them
94 const cleanedSQL = stripCommentsAndStrings(statement);
95
96 switch (style) {
97 case "numbered": {
98 // Extract all $N parameters and get unique indices
99 const matches = cleanedSQL.match(/\$\d+/g);
100 if (!matches) return 0;
101 const numbers = matches.map((m) => parseInt(m.slice(1), 10));
102 const uniqueIndices = Array.from(new Set(numbers)).sort((a, b) => a - b);
103
104 // Validate parameters are sequential starting from 1
105 const maxIndex = Math.max(...uniqueIndices);
106 for (let i = 1; i <= maxIndex; i++) {
107 if (!uniqueIndices.includes(i)) {
108 throw new Error(
109 `Non-sequential numbered parameters detected. Found placeholders: ${uniqueIndices.map(n => `$${n}`).join(', ')}. ` +
110 `Parameters must be sequential starting from $1 (missing $${i}).`
111 );
112 }
113 }
114
115 return maxIndex;
116 }
117 case "named": {
118 // Extract all @pN parameters and get unique indices
119 const matches = cleanedSQL.match(/@p\d+/g);
120 if (!matches) return 0;
121 const numbers = matches.map((m) => parseInt(m.slice(2), 10));
122 const uniqueIndices = Array.from(new Set(numbers)).sort((a, b) => a - b);
123
124 // Validate parameters are sequential starting from 1
125 const maxIndex = Math.max(...uniqueIndices);
126 for (let i = 1; i <= maxIndex; i++) {
127 if (!uniqueIndices.includes(i)) {
128 throw new Error(
129 `Non-sequential named parameters detected. Found placeholders: ${uniqueIndices.map(n => `@p${n}`).join(', ')}. ` +
130 `Parameters must be sequential starting from @p1 (missing @p${i}).`
131 );
132 }
133 }
134
135 return maxIndex;
136 }
137 case "positional": {
138 // Count question marks (positional parameters don't have this issue)
139 return (cleanedSQL.match(/\?/g) || []).length;
140 }
141 default:
142 return 0;
143 }
144}
145
146/**
147 * Validate that parameter definitions match the SQL statement

Callers 2

validateParametersFunction · 0.85

Calls 2

detectParameterStyleFunction · 0.85
stripCommentsAndStringsFunction · 0.85

Tested by

no test coverage detected