@@ -56,95 +56,44 @@ protected boolean supportsExplain() {
56
56
@ Override
57
57
String removeCommentsAndTrimInternal (String sql ) {
58
58
Preconditions .checkNotNull (sql );
59
- String currentTag = null ;
60
- boolean isInQuoted = false ;
61
59
boolean isInSingleLineComment = false ;
62
60
int multiLineCommentLevel = 0 ;
63
- char startQuote = 0 ;
64
- boolean lastCharWasEscapeChar = false ;
65
61
StringBuilder res = new StringBuilder (sql .length ());
66
62
int index = 0 ;
67
63
while (index < sql .length ()) {
68
64
char c = sql .charAt (index );
69
- if (isInQuoted ) {
70
- if ((c == '\n' || c == '\r' ) && startQuote != DOLLAR ) {
71
- throw SpannerExceptionFactory .newSpannerException (
72
- ErrorCode .INVALID_ARGUMENT , "SQL statement contains an unclosed literal: " + sql );
73
- } else if (c == startQuote ) {
74
- if (c == DOLLAR ) {
75
- // Check if this is the end of the current dollar quoted string.
76
- String tag = parseDollarQuotedString (sql , index + 1 );
77
- if (tag != null && tag .equals (currentTag )) {
78
- index += tag .length () + 1 ;
79
- res .append (c );
80
- res .append (tag );
81
- isInQuoted = false ;
82
- startQuote = 0 ;
83
- }
84
- } else if (lastCharWasEscapeChar ) {
85
- lastCharWasEscapeChar = false ;
86
- } else if (sql .length () > index + 1 && sql .charAt (index + 1 ) == startQuote ) {
87
- // This is an escaped quote (e.g. 'foo''bar')
88
- res .append (c );
89
- index ++;
90
- } else {
91
- isInQuoted = false ;
92
- startQuote = 0 ;
93
- }
94
- } else if (c == '\\' ) {
95
- lastCharWasEscapeChar = true ;
96
- } else {
97
- lastCharWasEscapeChar = false ;
65
+ if (isInSingleLineComment ) {
66
+ if (c == '\n' ) {
67
+ isInSingleLineComment = false ;
68
+ // Include the line feed in the result.
69
+ res .append (c );
70
+ }
71
+ } else if (multiLineCommentLevel > 0 ) {
72
+ if (sql .length () > index + 1 && c == ASTERISK && sql .charAt (index + 1 ) == SLASH ) {
73
+ multiLineCommentLevel --;
74
+ index ++;
75
+ } else if (sql .length () > index + 1 && c == SLASH && sql .charAt (index + 1 ) == ASTERISK ) {
76
+ multiLineCommentLevel ++;
77
+ index ++;
98
78
}
99
- res .append (c );
100
79
} else {
101
- // We are not in a quoted string.
102
- if (isInSingleLineComment ) {
103
- if (c == '\n' ) {
104
- isInSingleLineComment = false ;
105
- // Include the line feed in the result.
106
- res .append (c );
107
- }
108
- } else if (multiLineCommentLevel > 0 ) {
109
- if (sql .length () > index + 1 && c == ASTERIKS && sql .charAt (index + 1 ) == SLASH ) {
110
- multiLineCommentLevel --;
111
- index ++;
112
- } else if (sql .length () > index + 1 && c == SLASH && sql .charAt (index + 1 ) == ASTERIKS ) {
113
- multiLineCommentLevel ++;
114
- index ++;
115
- }
80
+ // Check for -- which indicates the start of a single-line comment.
81
+ if (sql .length () > index + 1 && c == HYPHEN && sql .charAt (index + 1 ) == HYPHEN ) {
82
+ // This is a single line comment.
83
+ isInSingleLineComment = true ;
84
+ index += 2 ;
85
+ continue ;
86
+ } else if (sql .length () > index + 1 && c == SLASH && sql .charAt (index + 1 ) == ASTERISK ) {
87
+ multiLineCommentLevel ++;
88
+ index += 2 ;
89
+ continue ;
116
90
} else {
117
- // Check for -- which indicates the start of a single-line comment.
118
- if (sql .length () > index + 1 && c == HYPHEN && sql .charAt (index + 1 ) == HYPHEN ) {
119
- // This is a single line comment.
120
- isInSingleLineComment = true ;
121
- } else if (sql .length () > index + 1 && c == SLASH && sql .charAt (index + 1 ) == ASTERIKS ) {
122
- multiLineCommentLevel ++;
123
- index ++;
124
- } else {
125
- if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE ) {
126
- isInQuoted = true ;
127
- startQuote = c ;
128
- } else if (c == DOLLAR ) {
129
- currentTag = parseDollarQuotedString (sql , index + 1 );
130
- if (currentTag != null ) {
131
- isInQuoted = true ;
132
- startQuote = DOLLAR ;
133
- index += currentTag .length () + 1 ;
134
- res .append (c );
135
- res .append (currentTag );
136
- }
137
- }
138
- res .append (c );
139
- }
91
+ index = skip (sql , index , res );
92
+ continue ;
140
93
}
141
94
}
142
95
index ++;
143
96
}
144
- if (isInQuoted ) {
145
- throw SpannerExceptionFactory .newSpannerException (
146
- ErrorCode .INVALID_ARGUMENT , "SQL statement contains an unclosed literal: " + sql );
147
- }
148
97
if (multiLineCommentLevel > 0 ) {
149
98
throw SpannerExceptionFactory .newSpannerException (
150
99
ErrorCode .INVALID_ARGUMENT ,
@@ -184,73 +133,78 @@ String removeStatementHint(String sql) {
184
133
ParametersInfo convertPositionalParametersToNamedParametersInternal (char paramChar , String sql ) {
185
134
Preconditions .checkNotNull (sql );
186
135
final String namedParamPrefix = "$" ;
187
- String currentTag = null ;
188
- boolean isInQuoted = false ;
189
- char startQuote = 0 ;
190
- boolean lastCharWasEscapeChar = false ;
191
136
StringBuilder named = new StringBuilder (sql .length () + countOccurrencesOf (paramChar , sql ));
192
137
int index = 0 ;
193
138
int paramIndex = 1 ;
194
139
while (index < sql .length ()) {
195
140
char c = sql .charAt (index );
196
- if (isInQuoted ) {
197
- if ((c == '\n' || c == '\r' ) && startQuote != DOLLAR ) {
198
- throw SpannerExceptionFactory .newSpannerException (
199
- ErrorCode .INVALID_ARGUMENT , "SQL statement contains an unclosed literal: " + sql );
200
- } else if (c == startQuote ) {
201
- if (c == DOLLAR ) {
202
- // Check if this is the end of the current dollar quoted string.
203
- String tag = parseDollarQuotedString (sql , index + 1 );
204
- if (tag != null && tag .equals (currentTag )) {
205
- index += tag .length () + 1 ;
206
- named .append (c );
207
- named .append (tag );
208
- isInQuoted = false ;
209
- startQuote = 0 ;
210
- }
211
- } else if (lastCharWasEscapeChar ) {
212
- lastCharWasEscapeChar = false ;
213
- } else if (sql .length () > index + 1 && sql .charAt (index + 1 ) == startQuote ) {
214
- // This is an escaped quote (e.g. 'foo''bar')
215
- named .append (c );
216
- index ++;
217
- } else {
218
- isInQuoted = false ;
219
- startQuote = 0 ;
141
+ if (c == paramChar ) {
142
+ named .append (namedParamPrefix ).append (paramIndex );
143
+ paramIndex ++;
144
+ index ++;
145
+ } else {
146
+ index = skip (sql , index , named );
147
+ }
148
+ }
149
+ return new ParametersInfo (paramIndex - 1 , named .toString ());
150
+ }
151
+
152
+ private int skip (String sql , int currentIndex , StringBuilder result ) {
153
+ char currentChar = sql .charAt (currentIndex );
154
+ if (currentChar == SINGLE_QUOTE || currentChar == DOUBLE_QUOTE ) {
155
+ result .append (currentChar );
156
+ return skipQuoted (sql , currentIndex , currentChar , result );
157
+ } else if (currentChar == DOLLAR ) {
158
+ String dollarTag = parseDollarQuotedString (sql , currentIndex + 1 );
159
+ if (dollarTag != null ) {
160
+ result .append (currentChar ).append (dollarTag ).append (currentChar );
161
+ return skipQuoted (
162
+ sql , currentIndex + dollarTag .length () + 1 , currentChar , dollarTag , result );
163
+ }
164
+ }
165
+
166
+ result .append (currentChar );
167
+ return currentIndex + 1 ;
168
+ }
169
+
170
+ private int skipQuoted (String sql , int startIndex , char startQuote , StringBuilder result ) {
171
+ return skipQuoted (sql , startIndex , startQuote , null , result );
172
+ }
173
+
174
+ private int skipQuoted (
175
+ String sql , int startIndex , char startQuote , String dollarTag , StringBuilder result ) {
176
+ boolean lastCharWasEscapeChar = false ;
177
+ int currentIndex = startIndex + 1 ;
178
+ while (currentIndex < sql .length ()) {
179
+ char currentChar = sql .charAt (currentIndex );
180
+ if (currentChar == startQuote ) {
181
+ if (currentChar == DOLLAR ) {
182
+ // Check if this is the end of the current dollar quoted string.
183
+ String tag = parseDollarQuotedString (sql , currentIndex + 1 );
184
+ if (tag != null && tag .equals (dollarTag )) {
185
+ result .append (currentChar ).append (tag ).append (currentChar );
186
+ return currentIndex + tag .length () + 2 ;
220
187
}
221
- } else if (c == '\\' ) {
222
- lastCharWasEscapeChar = true ;
223
- } else {
188
+ } else if (lastCharWasEscapeChar ) {
224
189
lastCharWasEscapeChar = false ;
225
- }
226
- named .append (c );
227
- } else {
228
- if (c == paramChar ) {
229
- named .append (namedParamPrefix + paramIndex );
230
- paramIndex ++;
190
+ } else if (sql .length () > currentIndex + 1 && sql .charAt (currentIndex + 1 ) == startQuote ) {
191
+ // This is an escaped quote (e.g. 'foo''bar')
192
+ result .append (currentChar ).append (currentChar );
193
+ currentIndex += 2 ;
194
+ continue ;
231
195
} else {
232
- if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE ) {
233
- isInQuoted = true ;
234
- startQuote = c ;
235
- } else if (c == DOLLAR ) {
236
- currentTag = parseDollarQuotedString (sql , index + 1 );
237
- if (currentTag != null ) {
238
- isInQuoted = true ;
239
- startQuote = DOLLAR ;
240
- index += currentTag .length () + 1 ;
241
- named .append (c );
242
- named .append (currentTag );
243
- }
244
- }
245
- named .append (c );
196
+ result .append (currentChar );
197
+ return currentIndex + 1 ;
246
198
}
199
+ } else if (currentChar == '\\' ) {
200
+ lastCharWasEscapeChar = true ;
201
+ } else {
202
+ lastCharWasEscapeChar = false ;
247
203
}
248
- index ++;
249
- }
250
- if (isInQuoted ) {
251
- throw SpannerExceptionFactory .newSpannerException (
252
- ErrorCode .INVALID_ARGUMENT , "SQL statement contains an unclosed literal: " + sql );
204
+ currentIndex ++;
205
+ result .append (currentChar );
253
206
}
254
- return new ParametersInfo (paramIndex - 1 , named .toString ());
207
+ throw SpannerExceptionFactory .newSpannerException (
208
+ ErrorCode .INVALID_ARGUMENT , "SQL statement contains an unclosed literal: " + sql );
255
209
}
256
210
}
0 commit comments