Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetConnection.java @ 700:940e266eeccd
Refactor BufferedMCLReader
It used to inherit from BufferedReader but there is no reason for that.
Also, it used to have a method readLine() which
- returned the line read
- stored the linetype
In the new setup we have a method advance() which reads
a line and stores both it and its type.
This makes the code more regular and makes it possible to
peek ahead without consuming.
author | Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com> |
---|---|
date | Thu, 08 Dec 2022 15:59:17 +0100 (2022-12-08) |
parents | 68422d7f3961 |
children | f89882b07614 |
comparison
equal
deleted
inserted
replaced
699:0ff364f569a1 | 700:940e266eeccd |
---|---|
341 server.setSoTimeout(sockTimeout); | 341 server.setSoTimeout(sockTimeout); |
342 | 342 |
343 in = server.getReader(); | 343 in = server.getReader(); |
344 out = server.getWriter(); | 344 out = server.getWriter(); |
345 | 345 |
346 final String error = in.waitForPrompt(); | 346 final String error = in.discardRemainder(); |
347 if (error != null) | 347 if (error != null) |
348 throw new SQLNonTransientConnectionException((error.length() > 6) ? error.substring(6) : error, "08001"); | 348 throw new SQLNonTransientConnectionException((error.length() > 6) ? error.substring(6) : error, "08001"); |
349 } catch (java.net.UnknownHostException e) { | 349 } catch (java.net.UnknownHostException e) { |
350 throw new SQLNonTransientConnectionException("Unknown Host (" + hostname + "): " + e.getMessage(), "08006"); | 350 throw new SQLNonTransientConnectionException("Unknown Host (" + hostname + "): " + e.getMessage(), "08006"); |
351 } catch (IOException e) { | 351 } catch (IOException e) { |
2136 try { | 2136 try { |
2137 if (usequeryTempl) | 2137 if (usequeryTempl) |
2138 out.writeLine(queryTempl[0] + command + queryTempl[1]); | 2138 out.writeLine(queryTempl[0] + command + queryTempl[1]); |
2139 else | 2139 else |
2140 out.writeLine(commandTempl[0] + command + commandTempl[1]); | 2140 out.writeLine(commandTempl[0] + command + commandTempl[1]); |
2141 final String error = in.waitForPrompt(); | 2141 final String error = in.discardRemainder(); |
2142 if (error != null) | 2142 if (error != null) |
2143 throw new SQLException(error.substring(6), error.substring(0, 5)); | 2143 throw new SQLException(error.substring(6), error.substring(0, 5)); |
2144 } catch (SocketTimeoutException e) { | 2144 } catch (SocketTimeoutException e) { |
2145 close(); // JDBC 4.1 semantics, abort() | 2145 close(); // JDBC 4.1 semantics, abort() |
2146 throw new SQLNonTransientConnectionException("connection timed out", "08M33"); | 2146 throw new SQLNonTransientConnectionException("connection timed out", "08M33"); |
3129 synchronized (server) { | 3129 synchronized (server) { |
3130 // make sure we're ready to send query; read data till we | 3130 // make sure we're ready to send query; read data till we |
3131 // have the prompt it is possible (and most likely) that we | 3131 // have the prompt it is possible (and most likely) that we |
3132 // already have the prompt and do not have to skip any | 3132 // already have the prompt and do not have to skip any |
3133 // lines. Ignore errors from previous result sets. | 3133 // lines. Ignore errors from previous result sets. |
3134 in.waitForPrompt(); | 3134 in.discardRemainder(); |
3135 | 3135 |
3136 // {{{ set reply size | 3136 // {{{ set reply size |
3137 /** | 3137 /** |
3138 * Change the reply size of the server. If the given | 3138 * Change the reply size of the server. If the given |
3139 * value is the same as the current value known to use, | 3139 * value is the same as the current value known to use, |
3156 | 3156 |
3157 // send query to the server | 3157 // send query to the server |
3158 out.writeLine(templ[0] + query + templ[1]); | 3158 out.writeLine(templ[0] + query + templ[1]); |
3159 | 3159 |
3160 // go for new results | 3160 // go for new results |
3161 String tmpLine = in.readLine(); | 3161 in.advance(); |
3162 LineType linetype = in.getLineType(); | |
3163 Response res = null; | 3162 Response res = null; |
3164 while (linetype != LineType.PROMPT) { | 3163 while (in.getLineType() != LineType.PROMPT) { |
3165 // each response should start with a start of header (or error) | 3164 // each response should start with a start of header (or error) |
3166 switch (linetype) { | 3165 switch (in.getLineType()) { |
3167 case SOHEADER: | 3166 case SOHEADER: |
3168 // make the response object, and fill it | 3167 // make the response object, and fill it |
3169 try { | 3168 try { |
3170 switch (sohp.parse(tmpLine)) { | 3169 switch (sohp.parse(in.getLine())) { |
3171 case StartOfHeaderParser.Q_PARSE: | 3170 case StartOfHeaderParser.Q_PARSE: |
3172 throw new MCLParseException("Q_PARSE header not allowed here", 1); | 3171 throw new MCLParseException("Q_PARSE header not allowed here", 1); |
3173 case StartOfHeaderParser.Q_TABLE: | 3172 case StartOfHeaderParser.Q_TABLE: |
3174 case StartOfHeaderParser.Q_PREPARE: { | 3173 case StartOfHeaderParser.Q_PREPARE: { |
3175 final int id = sohp.getNextAsInt(); | 3174 final int id = sohp.getNextAsInt(); |
3226 } // end of switch (sohp.parse(tmpLine)) | 3225 } // end of switch (sohp.parse(tmpLine)) |
3227 } catch (MCLParseException e) { | 3226 } catch (MCLParseException e) { |
3228 final int offset = e.getErrorOffset(); | 3227 final int offset = e.getErrorOffset(); |
3229 error = "M0M10!error while parsing start of header:\n" + | 3228 error = "M0M10!error while parsing start of header:\n" + |
3230 e.getMessage() + | 3229 e.getMessage() + |
3231 " found: '" + tmpLine.charAt(offset) + | 3230 " found: '" + in.getLine().charAt(offset) + |
3232 "' in: \"" + tmpLine + | 3231 "' in: \"" + in.getLine() + |
3233 "\" at pos: " + offset; | 3232 "\" at pos: " + offset; |
3234 // flush all the rest | 3233 // flush all the rest |
3235 in.waitForPrompt(); | 3234 in.discardRemainder(); |
3236 linetype = in.getLineType(); | |
3237 break; | 3235 break; |
3238 } | 3236 } |
3239 | 3237 |
3240 // immediately handle errors after parsing the header (res may be null) | 3238 // immediately handle errors after parsing the header (res may be null) |
3241 if (error != null) { | 3239 if (error != null) { |
3242 in.waitForPrompt(); | 3240 in.discardRemainder(); |
3243 linetype = in.getLineType(); | |
3244 break; | 3241 break; |
3245 } | 3242 } |
3246 | 3243 |
3247 // here we have a res object, which we can start filling | 3244 // here we have a res object, which we can start filling |
3248 while (res.wantsMore()) { | 3245 while (res.wantsMore()) { |
3249 error = res.addLine(in.readLine(), in.getLineType()); | 3246 in.advance(); |
3247 error = res.addLine(in.getLine(), in.getLineType()); | |
3250 if (error != null) { | 3248 if (error != null) { |
3251 // right, some protocol violation, | 3249 // right, some protocol violation, |
3252 // skip the rest of the result | 3250 // skip the rest of the result |
3253 error = "M0M10!" + error; | 3251 error = "M0M10!" + error; |
3254 in.waitForPrompt(); | 3252 in.discardRemainder(); |
3255 linetype = in.getLineType(); | |
3256 break; | 3253 break; |
3257 } | 3254 } |
3258 } | 3255 } |
3259 if (error != null) | 3256 if (error != null) |
3260 break; | 3257 break; |
3264 if (!(res instanceof DataBlockResponse)) | 3261 if (!(res instanceof DataBlockResponse)) |
3265 responses.add(res); | 3262 responses.add(res); |
3266 | 3263 |
3267 // read the next line (can be prompt, new result, error, etc.) | 3264 // read the next line (can be prompt, new result, error, etc.) |
3268 // before we start the loop over | 3265 // before we start the loop over |
3269 tmpLine = in.readLine(); | 3266 in.advance(); |
3270 linetype = in.getLineType(); | |
3271 break; | 3267 break; |
3272 case INFO: | 3268 case INFO: |
3273 addWarning(tmpLine.substring(1), "01000"); | 3269 addWarning(in.getLine().substring(1), "01000"); |
3274 // read the next line (can be prompt, new result, error, etc.) | 3270 // read the next line (can be prompt, new result, error, etc.) |
3275 // before we start the loop over | 3271 // before we start the loop over |
3276 tmpLine = in.readLine(); | 3272 in.advance(); |
3277 linetype = in.getLineType(); | |
3278 break; | 3273 break; |
3279 case FILETRANSFER: | 3274 case FILETRANSFER: |
3280 // Consume the command | 3275 // Consume the command |
3281 final String transferCommand = in.readLine(); | 3276 in.advance(); |
3277 final String transferCommand = in.getLine(); | |
3282 // Consume the fake prompt inserted by MapiSocket. | 3278 // Consume the fake prompt inserted by MapiSocket. |
3283 in.readLine(); | 3279 in.advance(); |
3284 // Handle the request | 3280 // Handle the request |
3285 if (transferCommand != null) | 3281 if (transferCommand != null) |
3286 error = handleTransfer(transferCommand); | 3282 error = handleTransfer(transferCommand); |
3287 else | 3283 else |
3288 error = "Protocol violation, expected transfer command, got nothing"; | 3284 error = "Protocol violation, expected transfer command, got nothing"; |
3289 // Then prepare for the next iteration | 3285 // Then prepare for the next iteration |
3290 if (error != null) { | 3286 if (error != null) { |
3291 out.writeLine(error + "\n"); | 3287 out.writeLine(error + "\n"); |
3292 error = in.waitForPrompt(); | 3288 error = in.discardRemainder(); |
3293 } else { | 3289 } else { |
3294 tmpLine = in.readLine(); | 3290 in.advance(); |
3295 } | 3291 } |
3296 linetype = in.getLineType(); | |
3297 break; | 3292 break; |
3298 default: // Yeah... in Java this is correct! | 3293 default: |
3299 // we have something we don't expect/understand, let's make it an error message | 3294 // we have something we don't expect/understand, let's make it an error message |
3300 tmpLine = "!M0M10!protocol violation, unexpected " + linetype + " line: " + tmpLine; | 3295 String msg = "M0M10!protocol violation, unexpected " + in.getLineType() + " line: " + in.getLine(); |
3301 // don't break; fall through... | 3296 error = in.discardRemainder(msg); |
3297 break; | |
3302 case ERROR: | 3298 case ERROR: |
3303 // read everything till the prompt (should be | 3299 // read everything till the prompt (should be |
3304 // error) we don't know if we ignore some | 3300 // error) we don't know if we ignore some |
3305 // garbage here... but the log should reveal that | 3301 // garbage here... but the log should reveal that |
3306 error = in.waitForPrompt(); | 3302 error = in.discardRemainder(in.getLine().substring(1)); |
3307 linetype = in.getLineType(); | |
3308 if (error != null) { | |
3309 error = tmpLine.substring(1) + "\n" + error; | |
3310 } else { | |
3311 error = tmpLine.substring(1); | |
3312 } | |
3313 break; | 3303 break; |
3314 } // end of switch (linetype) | 3304 } // end of switch (linetype) |
3315 } // end of while (linetype != LineType.PROMPT) | 3305 } // end of while (linetype != LineType.PROMPT) |
3316 } // end of synchronized (server) | 3306 } // end of synchronized (server) |
3317 | 3307 |