Mercurial > hg > monetdb-java
changeset 558:ebf65f416da9 onclient
Many improvements to the example code
author | Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com> |
---|---|
date | Thu, 16 Sep 2021 15:12:49 +0200 (2021-09-16) |
parents | ce2b616ed22e |
children | 7f10d662a788 |
files | example/OnClientExample.java |
diffstat | 1 files changed, 57 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/example/OnClientExample.java +++ b/example/OnClientExample.java @@ -24,13 +24,21 @@ public class OnClientExample { int status; try { // Ideally this would not be hardcoded.. - final String dbUrl = "jdbc:monetdb://localhost:55000/banana"; + final String dbUrl = "jdbc:monetdb://localhost:50000/demo"; + final String userName = "monetdb"; + final String password = "monetdb"; final String uploadDir = "/home/jvr/mydata"; final boolean filesAreUtf8 = false; - final String userName = "monetdb"; - final String password = "monetdb"; + String[] queries = { + "DROP TABLE IF EXISTS mytable", + "CREATE TABLE mytable(i INT, t TEXT)", + "COPY INTO mytable FROM 'generated.csv' ON CLIENT", + "COPY 20 RECORDS OFFSET 5 INTO mytable FROM 'generated.csv' ON CLIENT", + "COPY INTO mytable FROM 'nonexistentfilethatdoesnotexist.csv' ON CLIENT", + "SELECT COUNT(*) FROM mytable", + }; - status = run(dbUrl, userName, password, uploadDir, filesAreUtf8); + status = run(dbUrl, userName, password, uploadDir, filesAreUtf8, queries); } catch (Exception e) { status = 1; @@ -39,7 +47,7 @@ public class OnClientExample { System.exit(status); } - private static int run(String dbUrl, String userName, String password, String uploadDir, boolean filesAreUtf8) throws ClassNotFoundException, SQLException { + private static int run(String dbUrl, String userName, String password, String uploadDir, boolean filesAreUtf8, String[] queries) throws ClassNotFoundException, SQLException { int status = 0; // Connect @@ -50,29 +58,20 @@ public class OnClientExample { MyUploader handler = new MyUploader(uploadDir, filesAreUtf8); conn.unwrap(MonetConnection.class).setUploadHandler(handler); - // Run some SQL statements involving ON CLIENT - String[] queries = { - "DROP TABLE IF EXISTS bar", - "CREATE TABLE bar(i INT, t TEXT)", - "COPY INTO bar FROM 'generated.csv' ON CLIENT", - "COPY INTO bar FROM 'file.csv' ON CLIENT", - // following statement will run even if file.csv does not exist - "SELECT COUNT(*) FROM bar", - }; Statement stmt = conn.createStatement(); for (String q : queries) { System.out.println(q); try { - stmt.execute(q); - ResultSet rs = stmt.getResultSet(); - if (rs == null) { - System.out.printf(" OK, %d rows updated%n", stmt.getUpdateCount()); - } else { + boolean hasResultSet = stmt.execute(q); + if (hasResultSet) { + ResultSet rs = stmt.getResultSet(); long count = 0; while (rs.next()) { count++; } System.out.printf(" OK, returned %d rows%n", count); + } else { + System.out.printf(" OK, updated %d rows%n", stmt.getUpdateCount()); } } catch (SQLNonTransientException e) { throw e; @@ -80,6 +79,7 @@ public class OnClientExample { System.out.println(" => SQL ERROR " + e.getMessage()); status = 1; } + } return status; @@ -89,6 +89,7 @@ public class OnClientExample { private static class MyUploader implements UploadHandler { private final Path uploadDir; private final boolean filesAreUtf8; + private boolean stopUploading = false; public MyUploader(String uploadDir, boolean filesAreUtf8) { this.uploadDir = FileSystems.getDefault().getPath(uploadDir).normalize(); @@ -96,39 +97,47 @@ public class OnClientExample { } @Override - public void handleUpload(MonetConnection.Upload handle, String name, boolean textMode, long linesToSkip) throws IOException { + public void uploadCancelled() { + System.out.println(" CANCELLATION CALLBACK: server cancelled the upload"); + stopUploading = true; + } - // COPY OFFSET line numbers are 1-based but 0 is also allowed. - // Compute the number of lines to skip + @Override + public void handleUpload(MonetConnection.Upload handle, String name, boolean textMode, long linesToSkip) throws IOException { // We can upload data read from the file system but also make up our own data if (name.equals("generated.csv")) { - uploadGenerated(handle, linesToSkip); + uploadGeneratedData(handle, linesToSkip); return; } // Validate the path, demonstrating two ways of dealing with errors Path path = securityCheck(name); if (path == null || !Files.exists(path)) { - // This makes the COPY command fail but keeps the connection alive. - // Can only be used if we haven't sent any data yet + // This makes the COPY command fail but keeps the connection + // alive. Can only be used if we haven't sent any data yet handle.sendError("Invalid path"); return; } if (!Files.isReadable(path)) { - // As opposed to handle.sendError(), throwing an IOException ends the whole connection. + // As opposed to handle.sendError(), we can throw an IOException + // at any time. Unfortunately, the file upload protocol does not + // provide a way to indicate to the server that the data sent so + // far is incomplete, so for the time being throwing an + // IOException from {@handleUpload} terminates the connection. throw new IOException("Unreadable: " + path); } boolean binary = !textMode; if (binary) { - uploadBinary(handle, path); + uploadAsBinary(handle, path); } else if (linesToSkip == 0 && filesAreUtf8) { - // Avoid unnecessary character set conversions by pretending it's binary - uploadBinary(handle, path); + // Avoid unnecessary UTF-8 -> Java String -> UTF-8 conversions + // by pretending the data is binary. + uploadAsBinary(handle, path); } else { // Charset and skip handling really necessary - uploadTextFile(handle, path, linesToSkip); + uploadAsText(handle, path, linesToSkip); } } @@ -141,15 +150,29 @@ public class OnClientExample { } } - private void uploadGenerated(MonetConnection.Upload handle, long toSkip) throws IOException { + private void uploadGeneratedData(MonetConnection.Upload handle, long toSkip) throws IOException { + // Set the chunk size to a tiny amount so we can demonstrate + // cancellation handling. The default chunk size is one megabyte. + // DO NOT DO THIS IN PRODUCTION! + handle.setChunkSize(50); + + // Make up some data and upload it. PrintStream stream = handle.getStream(); - for (long i = toSkip + 1; i <= 100; i++) { + long n = 100; + System.out.printf(" HANDLER: uploading %d generated lines, numbered %d to %d%n", n - toSkip, toSkip +1, n); + long i; + for (i = toSkip + 1; i <= n; i++) { + if (stopUploading) { + System.out.printf(" HANDLER: at line %d we noticed the server asked us to stop sending%n", i); + break; + } stream.printf("%d|the number is %d%n", i, i); } + System.out.println(" HANDLER: done uploading"); stream.close(); } - private void uploadTextFile(MonetConnection.Upload handle, Path path, long toSkip) throws IOException { + private void uploadAsText(MonetConnection.Upload handle, Path path, long toSkip) throws IOException { BufferedReader reader = Files.newBufferedReader(path);// Converts from system encoding to Java text for (long i = 0; i < toSkip; i++) { reader.readLine(); @@ -157,7 +180,7 @@ public class OnClientExample { handle.uploadFrom(reader); // Converts from Java text to UTF-8 as required by MonetDB } - private void uploadBinary(MonetConnection.Upload handle, Path path) throws IOException { + private void uploadAsBinary(MonetConnection.Upload handle, Path path) throws IOException { // No charset conversion whatsoever.. // Use this for binary data or when you are certain the file is UTF-8 encoded. InputStream stream = Files.newInputStream(path);