changeset 577:6ab9168ef8e1 onclient

Added startup argument --csvdir to JdbcClient program to allow explicit enabling and specification where csv data files are to be read from or written to when the COPY ... ON CLIENT command is executed.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 14 Oct 2021 01:31:03 +0200 (2021-10-13)
parents 095e896f9d7a
children 687034945b3f
files onclient.txt release.txt src/main/java/org/monetdb/client/JdbcClient.java
diffstat 3 files changed, 63 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/onclient.txt
+++ b/onclient.txt
@@ -20,8 +20,7 @@ By default, the JDBC driver will refuse 
 	'No file upload handler has been registered with the JDBC driver'
 
 or in JdbcClient:
-	'Error [22000] !HY000!data.csv: No file upload handler has been registered with the JDBC driver;
-	'Error [22000] cannot transfer files from client'
+	'Error [22000] data.csv: No file upload handler has been registered with the JDBC driver'
 
 This is for security reasons.  However, you can register a callback to handle
 these requests from the server:
@@ -30,6 +29,8 @@ these requests from the server:
 	MyUploader handler = new MyUploadHandler();
 	conn.unwrap(MonetConnection.class).setUploadHandler(handler);
 
+or provide the JdbcClient startup argument: --csvdir "/path/to/csvfilesdir"
+
 Here, MyUploadHandler is an implementation of the interface MonetConnection.UploadHandler,
 which looks like this:
 
@@ -83,9 +84,10 @@ is currently no way to signal errors to 
 
 The interface for downloading is similar to that for uploading.
 
-Class org.monetdb.util.FileTransferHandler provides a default implementation of
-both MonetConnection.UploadHandler and MonetConnection.DownloadHandler.  You
-pass it a directory name and a flag indicating whether the contents of that
-directory can be assumed to be UTF-8 encoded. It is intended for situations
-where you do not need to generate or transform data while uploading.
+Class org.monetdb.util.FileTransferHandler provides a default implementation
+of both MonetConnection.UploadHandler and MonetConnection.DownloadHandler for
+reading from and writing to local csv files. You pass the FileTransferHandler
+constructor a directory name and a flag indicating whether the contents of
+the csv files data are UTF-8 encoded. FileTransferHandler is intended for
+situations where you do not need to generate or transform data while uploading.
 
--- a/release.txt
+++ b/release.txt
@@ -185,9 +185,29 @@ The following java.sql.* interfaces are 
   * java.sql.SQLXML
   * java.sql.Struct
 
-Since version VERSION_NUMBER, the MonetDB JDBC driver has support for the
-ON CLIENT clause of the COPY statement. You can register callback to provide
-data when the server asks for it, see onclient.txt for more information.
+
+Since release 3.2 (monetdb-jdbc-3.2.jre8.jar), the MonetDB JDBC driver has
+support for the ON CLIENT clause of the COPY statement. To make use of
+this functionality you must register handlers for upload and download of data.
+The MonetConnection class has been extended with 2 methods:
+ public void setUploadHandler(UploadHandler uploadHandler)
+ public void setDownloadHandler(DownloadHandler downloadHandler)
+The API has been extended with interfaces and utility class:
+ public interface org.monetdb.jdbc.MonetConnection.UploadHandler
+ public interface org.monetdb.jdbc.MonetConnection.DownloadHandler
+ public class org.monetdb.util.FileTransferHandler
+  which implements MonetConnection.UploadHandler, MonetConnection.DownloadHandler
+See onclient.txt for more information on how to use these from Java.
+
+The JdbcClient application has also been extended to support COPY ...
+ON CLIENT functionality. However for security reasons you must provide an
+explicit new startup argument
+  --csvdir "/path/to/csvdatafiles"
+or on MS Windows
+  --csvdir "C:\\path\\to\\csvdatafiles"
+in order to allow the JdbcClient to down/up load data to/from local csv files.
+All csv data in the local files must be UTF-8 encoded and uncompressed.
+
 
 Notes and Tips for Java Programmers using MonetDB JDBC driver:
 - Close JDBC ResultSet, Statement, PreparedStatement, CallableStatement and
@@ -251,3 +271,4 @@ Warning:
 Note: as of Febr 2021 (monetdb-jdbc-3.0.jre8.jar) we compile all
  the java sources to target: Java SE 8 (profile compact2), so
  you need a JRE/JDK JVM of version 8 or higher to use it.
+ 
--- a/src/main/java/org/monetdb/client/JdbcClient.java
+++ b/src/main/java/org/monetdb/client/JdbcClient.java
@@ -67,7 +67,8 @@ public class JdbcClient {	/* cannot (yet
 	 *
 	 * <pre>Usage java -jar jdbcclient.jre8.jar
 	 *		[-h host[:port]] [-p port] [-f file] [-u user]
-	 *		[-l language] [-d database] [-e] [-D [table]] [-X&lt;opt&gt;]
+	 *		[-l language] [-d database] [-e] [-D [table]]
+	 *		[--csvdir /path/to/csvfiles] [-X&lt;opt&gt;]
 	 *		| [--help] | [--version]
 	 * or using long option equivalents --host --port --file --user --language
 	 * --dump --echo --database.
@@ -100,6 +101,8 @@ public class JdbcClient {	/* cannot (yet
 	 * -e --echo     Also outputs the contents of the input file, if any.
 	 * -q --quiet    Suppress printing the welcome header.
 	 * -D --dump     Dumps the given table(s), or the complete database if none given.
+	 * --csvdir      The directory path where csv data files wil be read from or
+	 ^               written to when COPY ... ON CLIENT commands are executed.
 	 * -Xoutput      The output mode when dumping.  Default is sql, xml may be used for
 	 *               an experimental XML output.
 	 * -Xhash        Use the given hash algorithm during challenge response.
@@ -144,6 +147,9 @@ public class JdbcClient {	/* cannot (yet
 				"if connecting to monetdbd).");
 		copts.addOption("l", "language", CmdLineOpts.CAR_ONE, "sql",
 				"Use the given language, defaults to 'sql'.");
+		copts.addOption(null, "csvdir", CmdLineOpts.CAR_ONE, null,
+				"The directory path where csv data files are read or " +
+				"written when using ON CLIENT clause of COPY command.");
 
 		// arguments which have no argument(s)
 		copts.addOption(null, "help", CmdLineOpts.CAR_ZERO, null,
@@ -222,7 +228,8 @@ public class JdbcClient {	/* cannot (yet
 			System.out.print(
 				"Usage java -jar jdbcclient.jre8.jar\n" +
 				"\t\t[-h host[:port]] [-p port] [-f file] [-u user]\n" +
-				"\t\t[-l language] [-d database] [-e] [-D [table]] [-X<opt>]\n" +
+				"\t\t[-l language] [-d database] [-e] [-D [table]]\n" +
+				"\t\t[--csvdir /path/to/csvfiles]] [-X<opt>]\n" +
 				"\t\t| [--help] | [--version]\n" +
 				"or using long option equivalents --host --port --file --user --language\n" +
 				"--dump --echo --database.\n" +
@@ -339,11 +346,27 @@ public class JdbcClient {	/* cannot (yet
 			dbmd = null;
 		}
 
-		// register file data uploadHandler to allow support for: COPY INTO mytable FROM 'data.csv' ON CLIENT;
-		FileTransferHandler FThandler = new FileTransferHandler("", true);
-		con.unwrap(MonetConnection.class).setUploadHandler(FThandler);
-		// register file data downloadHandler to allow support for: COPY select_query INTO 'data.csv' ON CLIENT;
-		con.unwrap(MonetConnection.class).setDownloadHandler(FThandler);
+		oc = copts.getOption("csvdir");
+		if (oc.isPresent()) {
+			final String csvdir = oc.getArgument();
+			if (csvdir != null) {
+				// check if provided csvdir is an existing dir
+				// else a download of data into file will terminate the JDBC connection!!
+				if (java.nio.file.Files.isDirectory(java.nio.file.Paths.get(csvdir))) {
+					final FileTransferHandler FThandler = new FileTransferHandler(csvdir, true);
+
+					// register file data uploadHandler to allow support
+					// for: COPY INTO mytable FROM 'data.csv' ON CLIENT;
+					((MonetConnection) con).setUploadHandler(FThandler);
+
+					// register file data downloadHandler to allow support
+					// for: COPY select_query INTO 'data.csv' ON CLIENT;
+					((MonetConnection) con).setDownloadHandler(FThandler);
+				} else {
+					System.err.println("Warning: provided csvdir \"" + csvdir + "\" does not exist. Ignoring csvdir setting.");
+				}
+			}
+		}
 
 		stmt = con.createStatement();	// is used by processInteractive(), processBatch(), doDump()