Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetConnection.java @ 514:443780d71bae onclient
More renaming. user registers MonetUploadHandler which is handed an Upload
author | Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com> |
---|---|
date | Mon, 23 Aug 2021 09:42:58 +0200 (2021-08-23) |
parents | bd860e850fe1 |
children | 7bbcff2c775b |
comparison
equal
deleted
inserted
replaced
513:d771bfdd5288 | 514:443780d71bae |
---|---|
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V. | 6 * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V. |
7 */ | 7 */ |
8 | 8 |
9 package org.monetdb.jdbc; | 9 package org.monetdb.jdbc; |
10 | 10 |
11 import java.io.File; | 11 import java.io.*; |
12 import java.io.IOException; | |
13 import java.net.SocketException; | 12 import java.net.SocketException; |
14 import java.net.SocketTimeoutException; | 13 import java.net.SocketTimeoutException; |
14 import java.nio.charset.StandardCharsets; | |
15 import java.sql.CallableStatement; | 15 import java.sql.CallableStatement; |
16 import java.sql.Connection; | 16 import java.sql.Connection; |
17 import java.sql.DatabaseMetaData; | 17 import java.sql.DatabaseMetaData; |
18 import java.sql.PreparedStatement; | 18 import java.sql.PreparedStatement; |
19 import java.sql.ResultSet; | 19 import java.sql.ResultSet; |
150 | 150 |
151 /** A cache to reduce the number of DatabaseMetaData objects created by getMetaData() to maximum 1 per connection */ | 151 /** A cache to reduce the number of DatabaseMetaData objects created by getMetaData() to maximum 1 per connection */ |
152 private DatabaseMetaData dbmd; | 152 private DatabaseMetaData dbmd; |
153 | 153 |
154 /** Handlers for ON CLIENT requests */ | 154 /** Handlers for ON CLIENT requests */ |
155 private MonetUploader uploader; | 155 private MonetUploadHandler uploader; |
156 private MonetDownloader downloader; | 156 private MonetDownloadHandler downloader; |
157 | 157 |
158 /** | 158 /** |
159 * Constructor of a Connection for MonetDB. At this moment the | 159 * Constructor of a Connection for MonetDB. At this moment the |
160 * current implementation limits itself to storing the given host, | 160 * current implementation limits itself to storing the given host, |
161 * database, username and password for later use by the | 161 * database, username and password for later use by the |
1198 } | 1198 } |
1199 | 1199 |
1200 /** | 1200 /** |
1201 * Registers a MonetUploader to support for example COPY ON CLIENT | 1201 * Registers a MonetUploader to support for example COPY ON CLIENT |
1202 * | 1202 * |
1203 * @param uploader the handler to register, or null to deregister | 1203 * @param uploadHandler the handler to register, or null to deregister |
1204 */ | 1204 */ |
1205 public void setUploader(MonetUploader uploader) { | 1205 public void setUploadHandler(MonetUploadHandler uploadHandler) { |
1206 this.uploader = uploader; | 1206 this.uploader = uploadHandler; |
1207 } | 1207 } |
1208 | 1208 |
1209 /** | 1209 /** |
1210 * Returns the currently registerered MonetUploader, or null | 1210 * Returns the currently registerered MonetUploader, or null |
1211 */ | 1211 */ |
1212 public MonetUploader getUploader() { | 1212 public MonetUploadHandler getUploadHandler() { |
1213 return uploader; | 1213 return uploader; |
1214 } | 1214 } |
1215 /** | 1215 /** |
1216 * Registers a MonetDownloader to support for example COPY ON CLIENT | 1216 * Registers a MonetDownloader to support for example COPY ON CLIENT |
1217 * | 1217 * |
1218 * @param downloader the handler to register, or null to deregister | 1218 * @param downloadHandler the handler to register, or null to deregister |
1219 */ | 1219 */ |
1220 public void setDownloader(MonetDownloader downloader) { | 1220 public void setDownloadHandler(MonetDownloadHandler downloadHandler) { |
1221 this.downloader = downloader; | 1221 this.downloader = downloadHandler; |
1222 } | 1222 } |
1223 | 1223 |
1224 /** | 1224 /** |
1225 * Returns the currently registerered MonetDownloadHandler handler, or null | 1225 * Returns the currently registerered MonetDownloadHandler handler, or null |
1226 */ | 1226 */ |
1227 public MonetDownloader getDownloader() { | 1227 public MonetDownloadHandler getDownloadHandler() { |
1228 return downloader; | 1228 return downloader; |
1229 } | 1229 } |
1230 | 1230 |
1231 /** | 1231 /** |
1232 * Returns a string identifying this Connection to the MonetDB server. | 1232 * Returns a string identifying this Connection to the MonetDB server. |
3230 private String handleUpload(String path, boolean textMode, int offset) throws IOException { | 3230 private String handleUpload(String path, boolean textMode, int offset) throws IOException { |
3231 if (uploader == null) { | 3231 if (uploader == null) { |
3232 return "No file upload handler has been registered with the JDBC driver"; | 3232 return "No file upload handler has been registered with the JDBC driver"; |
3233 } | 3233 } |
3234 | 3234 |
3235 MonetUploadHandle handle = new MonetUploadHandle(server); | 3235 Upload handle = new Upload(server); |
3236 boolean wasFaking = server.setInsertFakePrompts(false); | 3236 boolean wasFaking = server.setInsertFakePrompts(false); |
3237 try { | 3237 try { |
3238 uploader.handleUpload(handle, path, textMode, offset); | 3238 uploader.handleUpload(handle, path, textMode, offset); |
3239 if (!handle.hasBeenUsed()) { | 3239 if (!handle.hasBeenUsed()) { |
3240 String message = String.format("Call to %s.handleUpload for path '%s' sent neither data nor an error message", | 3240 String message = String.format("Call to %s.handleUpload for path '%s' sent neither data nor an error message", |
3251 private String handleDownload(String path) throws IOException { | 3251 private String handleDownload(String path) throws IOException { |
3252 if (downloader == null) { | 3252 if (downloader == null) { |
3253 return "No file download handler has been registered with the JDBC driver"; | 3253 return "No file download handler has been registered with the JDBC driver"; |
3254 } | 3254 } |
3255 | 3255 |
3256 MonetDownloadHandle handle = new MonetDownloadHandle(server); | 3256 Download handle = new Download(server); |
3257 downloader.handleDownload(handle, path, true); | 3257 downloader.handleDownload(handle, path, true); |
3258 if (!handle.hasBeenUsed()) { | 3258 if (!handle.hasBeenUsed()) { |
3259 String message = String.format("Call to %s.handleDownload for path '%s' sent neither data nor an error message", | 3259 String message = String.format("Call to %s.handleDownload for path '%s' sent neither data nor an error message", |
3260 downloader.getClass().getCanonicalName(), path); | 3260 downloader.getClass().getCanonicalName(), path); |
3261 throw new IOException(message); | 3261 throw new IOException(message); |
3262 } | 3262 } |
3263 handle.close(); | 3263 handle.close(); |
3264 return handle.getError(); | 3264 return handle.getError(); |
3265 } | 3265 } |
3266 | |
3267 public static class Upload { | |
3268 private final MapiSocket server; | |
3269 private PrintStream print = null; | |
3270 private String error = null; | |
3271 | |
3272 Upload(MapiSocket server) { | |
3273 this.server = server; | |
3274 } | |
3275 | |
3276 public void sendError(String errorMessage) throws IOException { | |
3277 if (error != null) { | |
3278 throw new IOException("another error has already been sent: " + error); | |
3279 } | |
3280 error = errorMessage; | |
3281 } | |
3282 | |
3283 public PrintStream getStream() throws IOException { | |
3284 if (error != null) { | |
3285 throw new IOException("Cannot send data after an error has been sent"); | |
3286 } | |
3287 if (print == null) { | |
3288 try { | |
3289 MapiSocket.UploadStream up = server.uploadStream(); | |
3290 print = new PrintStream(up, false, "UTF-8"); | |
3291 up.write('\n'); | |
3292 } catch (UnsupportedEncodingException e) { | |
3293 throw new RuntimeException("The system is guaranteed to support the UTF-8 encoding but apparently it doesn't", e); | |
3294 } | |
3295 } | |
3296 return print; | |
3297 } | |
3298 | |
3299 public boolean hasBeenUsed() { | |
3300 return print != null || error != null; | |
3301 } | |
3302 | |
3303 public String getError() { | |
3304 return error; | |
3305 } | |
3306 | |
3307 public void uploadFrom(InputStream inputStream) throws IOException { | |
3308 OutputStream s = getStream(); | |
3309 byte[] buffer = new byte[64 * 1024]; | |
3310 while (true) { | |
3311 int nread = inputStream.read(buffer); | |
3312 if (nread < 0) { | |
3313 break; | |
3314 } | |
3315 s.write(buffer, 0, nread); | |
3316 } | |
3317 } | |
3318 | |
3319 public void uploadFrom(BufferedReader reader, int offset) throws IOException { | |
3320 // we're 1-based but also accept 0 | |
3321 if (offset > 0) { | |
3322 offset -= 1; | |
3323 } | |
3324 | |
3325 for (int i = 0; i < offset; i++) { | |
3326 String line = reader.readLine(); | |
3327 if (line == null) { | |
3328 return; | |
3329 } | |
3330 } | |
3331 | |
3332 uploadFrom(reader); | |
3333 } | |
3334 | |
3335 public void uploadFrom(BufferedReader reader) throws IOException { | |
3336 OutputStream s = getStream(); | |
3337 OutputStreamWriter writer = new OutputStreamWriter(s, StandardCharsets.UTF_8); | |
3338 char[] buffer = new char[64 * 1024]; | |
3339 while (true) { | |
3340 int nread = reader.read(buffer, 0, buffer.length); | |
3341 if (nread < 0) { | |
3342 break; | |
3343 } | |
3344 writer.write(buffer, 0, nread); | |
3345 writer.close(); | |
3346 } | |
3347 } | |
3348 | |
3349 public void close() { | |
3350 if (print != null) { | |
3351 print.close(); | |
3352 } | |
3353 } | |
3354 } | |
3355 | |
3356 public static class Download { | |
3357 private final MapiSocket server; | |
3358 private MapiSocket.DownloadStream stream = null; | |
3359 private String error = null; | |
3360 | |
3361 boolean closed = false; | |
3362 | |
3363 Download(MapiSocket server) { | |
3364 this.server = server; | |
3365 } | |
3366 | |
3367 public void sendError(String errorMessage) throws IOException { | |
3368 if (error != null) { | |
3369 throw new IOException("another error has already been sent: " + error); | |
3370 } | |
3371 error = errorMessage; | |
3372 } | |
3373 | |
3374 public InputStream getStream() throws IOException { | |
3375 if (error != null) { | |
3376 throw new IOException("cannot receive data after error has been sent"); | |
3377 } | |
3378 if (stream == null) { | |
3379 stream = server.downloadStream(); | |
3380 server.getOutputStream().flush(); | |
3381 } | |
3382 return stream; | |
3383 } | |
3384 public boolean hasBeenUsed() { | |
3385 return error != null || stream != null; | |
3386 } | |
3387 | |
3388 public String getError() { | |
3389 return error; | |
3390 } | |
3391 public void close() throws IOException { | |
3392 if (closed) { | |
3393 return; | |
3394 } | |
3395 if (stream != null) { | |
3396 stream.close(); | |
3397 } | |
3398 closed = true; | |
3399 } | |
3400 | |
3401 } | |
3266 } | 3402 } |