{"id":15003333,"url":"https://github.com/kawansoft/aceql-http-client-jdbc-driver","last_synced_at":"2025-08-16T18:12:40.606Z","repository":{"id":39947164,"uuid":"95659993","full_name":"kawansoft/aceql-http-client-jdbc-driver","owner":"kawansoft","description":"Java JDBC Driver for easy access of remote SQL databases managed with AceQL HTTP","archived":false,"fork":false,"pushed_at":"2024-10-03T18:43:11.000Z","size":1792,"stargazers_count":26,"open_issues_count":3,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-14T07:40:59.829Z","etag":null,"topics":["aceql-http","android","api-client","http-client","java","java-client-sdk","jdbc-api","jdbc-call","jdbc-connector","jdbc-driver","jdbc-drivers","ms-sql-server","remote-database","sdk","sdk-java","sql","sql-databases"],"latest_commit_sha":null,"homepage":"https://www.aceql.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kawansoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["kawansoft"]}},"created_at":"2017-06-28T11:04:16.000Z","updated_at":"2024-08-12T15:21:32.000Z","dependencies_parsed_at":"2024-07-25T10:44:51.414Z","dependency_job_id":"bfb5c663-64b7-48be-921b-2ec4ddd5a49f","html_url":"https://github.com/kawansoft/aceql-http-client-jdbc-driver","commit_stats":null,"previous_names":["kawansoft/aceql-http-client-sdk"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kawansoft%2Faceql-http-client-jdbc-driver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kawansoft%2Faceql-http-client-jdbc-driver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kawansoft%2Faceql-http-client-jdbc-driver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kawansoft%2Faceql-http-client-jdbc-driver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kawansoft","download_url":"https://codeload.github.com/kawansoft/aceql-http-client-jdbc-driver/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222189597,"owners_count":16946004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aceql-http","android","api-client","http-client","java","java-client-sdk","jdbc-api","jdbc-call","jdbc-connector","jdbc-driver","jdbc-drivers","ms-sql-server","remote-database","sdk","sdk-java","sql","sql-databases"],"created_at":"2024-09-24T18:58:00.799Z","updated_at":"2024-10-30T09:08:07.035Z","avatar_url":"https://github.com/kawansoft.png","language":"Java","funding_links":["https://github.com/sponsors/kawansoft"],"categories":[],"sub_categories":[],"readme":"![GitHub top language](https://img.shields.io/github/languages/top/kawansoft/aceql-http-client-jdbc-driver) ![GitHub issues](https://img.shields.io/github/issues/kawansoft/aceql-http-client-jdbc-driver) \r\n![GitHub](https://img.shields.io/github/license/kawansoft/aceql-http-client-jdbc-driver) ![Maven Central](https://img.shields.io/maven-central/v/com.aceql/aceql-http-client-jdbc-driver)\r\n![GitHub last commit (branch)](https://img.shields.io/github/last-commit/kawansoft/aceql-http-client-jdbc-driver/master)\r\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/1768a87595f74c9391933a85b90dc20c)](https://www.codacy.com/gh/kawansoft/aceql-http-client-jdbc-driver/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=kawansoft/aceql-http-client-jdbc-driver\u0026amp;utm_campaign=Badge_Grade)\r\n![GitHub contributors](https://img.shields.io/github/contributors/kawansoft/aceql-http-client-jdbc-driver)\r\n\r\n\r\n# AceQL HTTP \r\n\r\n## AceQL Client JDBC Driver v9.4 - User Guide\r\n\r\n## August 12, 2024\r\n\r\n\u003cimg src=\"https://docs.aceql.com/img/AceQL-Schema-min.jpg\" alt=\"AceQL Draw\"/\u003e\r\n\r\n* [Fundamentals](#fundamentals)\r\n   * [Technical operating environment](#technical-operating-environment)\r\n   * [AceQL Server side compatibility](#aceql-server-side-compatibility)\r\n      * [Main features](#main-features)\r\n   * [Installation](#installation)\r\n      * [Maven](#maven)\r\n      * [Single Jar](#single-jar)\r\n   * [Android Project settings](#android-project-settings)\r\n   * [Data transport](#data-transport)\r\n      * [Transport format](#transport-format)\r\n      * [Content streaming and memory management](#content-streaming-and-memory-management)\r\n   * [Best practices for fast response time](#best-practices-for-fast-response-time)\r\n* [Using the AceQL Client JDBC Driver](#using-the-aceql-client-jdbc-driver)\r\n   * [Connection creation](#connection-creation)\r\n   * [Using a Proxy](#using-a-proxy)\r\n   * [Handling Exceptions](#handling-exceptions)\r\n      * [The error type](#the-error-type)\r\n      * [Most common AceQL Server messages](#most-common-aceql-server-messages)\r\n      * [HTTP Status Codes](#http-status-codes)\r\n   * [Data types](#data-types)\r\n   * [SQL Transactions and Connections modifiers](#sql-transactions-and-connections-modifiers)\r\n   * [Using Stored Procedures](#using-stored-procedures)\r\n      * [Using Oracle Database stored procedures with SELECT calls](#using-oracle-database-stored-procedures-with-select-calls)\r\n   * [Batch management](#batch-management)\r\n   * [BLOB management](#blob-management)\r\n      * [Standard syntax](#standard-syntax)\r\n         * [BLOB creation with standard syntax](#blob-creation-with-standard-syntax)\r\n         * [BLOB reading with standard syntax](#blob-reading-with-standard-syntax)\r\n      * [Advanced syntax with streaming techniques](#advanced-syntax-with-streaming-techniques)\r\n         * [BLOB creation with stream syntax](#blob-creation-with-stream-syntax)\r\n         * [BLOB reading with stream syntax](#blob-reading-with-stream-syntax)\r\n         * [Using Progress Bars with Blobs](#using-progress-bars-with-blobs)\r\n   * [HTTP session options](#http-session-options)\r\n   * [Using the AceQL Metadata Query API](#using-the-aceql-metadata-query-api)\r\n      * [Downloading database schema into a file](#downloading-database-schema-into-a-file)\r\n      * [Accessing remote database main properties](#accessing-remote-database-main-properties)\r\n      * [Getting Details of Tables and Columns](#getting-details-of-tables-and-columns)\r\n   * [Using the native JDBC Metadata Query API](#using-the-native-jdbc-metadata-query-api)\r\n      * [Code Sample](#code-sample)\r\n      * [Using Database viewers with the AceQL Client JDBC Driver](#using-database-viewers-with-the-aceql-client-jdbc-driver)\r\n      * [Disabling JDBC MetaData calls when not required](#disabling-jdbc-metadata-calls-when-not-required)\r\n   * [Using outer authentication without a password and with an AceQL Session ID](#using-outer-authentication-without-a-password-and-with-an-aceql-session-id)\r\n   * [Passing request headers for validation on server side](#passing-request-headers-for-validation-on-server-side)\r\n* [Limitations](#limitations)\r\n\r\n\r\n# Fundamentals \r\n\r\nThis document describes how to use the AceQL Client JDBC Driver and gives some details about how it operates with the server side.\r\n\r\nThe AceQL Client JDBC Driver allows users to wrap the [AceQL HTTP APIs](https://github.com/kawansoft/aceql-http/blob/master/aceql-http-user-guide-api.md) and eliminate the tedious work of handling communication errors and parsing JSON results.\r\n\r\nAndroid and Java Desktop application developers can access remote SQL databases and/or SQL databases in the cloud, simply by including standard JDBC calls in their code, just like they would for a local database.\r\n\r\nThe AceQL Server operation is described in [AceQL HTTP Server Installation and Configuration Guide](https://github.com/kawansoft/aceql-http/blob/master/README.md), whose content is sometimes referred in this User Guide. \r\n\r\n## Technical operating environment \r\n\r\nThe AceQL Client JDBC Driver is entirely written in Java, and functions identically with Microsoft Windows, Linux, and all versions of UNIX supporting Java 8+.\r\n\r\nThe only required third party installation is a recent JVM:\r\n\r\n| OS                                  | **JVM (Java Virtual Machine)** |\r\n| ----------------------------------- | ------------------------------ |\r\n| Android                             | Android 4.1+                   |\r\n| Windows, UNIX/Linux, OS X  / mac OS | Java 8+                        |\r\n\r\n## AceQL Server side compatibility\r\n\r\nThe Client JDBC Driver version is compatible with AceQL HTTP server side v12.2+  \r\n\r\n### Main features\r\n\r\n| AceQL Client JDBC Driver v9.4\u003cbr\u003eMain Features               |\r\n| :----------------------------------------------------------- |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;Works as a real [JDBC Driver](https://docs.oracle.com/javase/tutorial/jdbc/basics/connecting.html) \u003cbr/\u003ePlug \u0026 play without editing your app source code. |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;Main SQL types\u003cbr/\u003e`Boolean`, `Integer`, `Short`, `Double`, `Float`, `BigDecimal`, `Long`, `String`, `Date`, `Time`, `Timestamp` |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;Connection  through HTTP Proxy |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;SQL Transactions\u003cbr/\u003e`Connection.commit()`, `Connection.rollback()`, `Connection.setAutocomit(boolean autoCommit)`.\u003cbr/\u003e[Savepoints](https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html#set_roll_back_savepoints) are also fully supported: |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003eBatch methods for `Statement` \u003cbr\u003eand `PreparedStatement` |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;Open Source Databases\u003cbr/\u003eMySQL, PostgreSQL, MariaDB |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;MS SQL Server |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;Oracle Database |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;[BLOB](https://docs.oracle.com/javase/tutorial/jdbc/basics/blob.html) Type - Size up to 4GB |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;IBM DB2 Database |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;[Array](https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Array.html) Type |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;[Stored Procedures](https://docs.oracle.com/javase/tutorial/jdbc/basics/storedprocedures.html) |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;JDBC API Metadata\u003cbr/\u003e`Connection.getMetadata()`, `ResultSet.getMetaData()` |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e\u0026nbsp;JDBC Clients Tools \u0026 GUI \u003cbr/\u003e[DBeaver](https://dbeaver.io/), [DbVisualizer](https://www.dbvis.com/), [JetBrains DataGrip](https://www.jetbrains.com/datagrip/), [RazorSQL](https://razorsql.com/), [SQuirreL SQL](http://squirrel-sql.sourceforge.net/) |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e [Allows outer authentication without a password](#using-outer-authentication-without-a-password-and-with-an-aceql-session-id) |\r\n| \u003cimg src=\"https://download.aceql.com/images/check_20.png\" alt=\"check!\"/\u003e [Allows passing request headers for validation on server](#passing-request-headers-for-validation-on-server-side) |\r\n\r\n## Installation\r\n\r\n### Maven\r\n\r\n```xml\r\n\u003cdependency\u003e\r\n    \u003cgroupId\u003ecom.aceql\u003c/groupId\u003e\r\n    \u003cartifactId\u003eaceql-http-client-jdbc-driver\u003c/artifactId\u003e\r\n    \u003cversion\u003e9.4\u003c/version\u003e\r\n\u003c/dependency\u003e\r\n```\r\n### Single Jar \r\n\r\nFor non Maven users: a single jar with all dependencies is available on the [download page](https://www.aceql.com/aceql-download-page.html).\r\n\r\n## Android Project settings\r\n\r\n Add the following 3 lines to your `AndroidManifest.xml`:\r\n\r\n```xml\r\n\u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\r\n\u003cuses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" /\u003e\r\n\u003cuses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" /\u003e\r\n```\r\n\r\nA full Android project sample is available on GitHub: [aceql-http-client-android-sample](https://github.com/kawansoft/aceql-http-client-android-sample).\r\n\r\n## Data transport  \r\n\r\n### Transport format \r\n\r\nAceQL transfers the least possible amount of meta-information:\r\n\r\n- Request parameters are  transported in UTF-8 format.\r\n- JSON format is used for data  and class transport (using `javax.json` package).\r\n\r\n### Content streaming and memory management \r\n\r\nAll requests are streamed: \r\n\r\n- Output requests (from the client side) are streamed directly from the socket to the server to avoid     buffering any content body.\r\n- Input responses (for the client side) are streamed directly from the socket to the server to efficiently read the response body.\r\n\r\nLarge content (ResultSet, …) is transferred using files. It is never loaded in memory. Streaming techniques are always used to read and write this content.\r\n\r\n## Best practices for fast response time\r\n\r\nEvery HTTP exchange between the client and server side is time-consuming, because the HTTP call is synchronous and waits for the server's response\r\n\r\nTry to avoid coding JDBC calls inside loops, as this can reduce execution speed. Each JDBC call will send an HTTP request and wait for the response from the server. Always use  batch commands (`Statement.executeBatch()`,...)   when you have many rows to INSERT or UPDATE.\r\n\r\nNote that AceQL is optimized as much as possible:\r\n\r\n- A SELECT call returning a huge Result Set will not consume memory on the server or client side:  AceQL uses input stream and output stream I/O for `ResultSet` transfer.\r\n- Result Set retrieval is as fast as possible:  \r\n  - The `ResultSet` creation is done once on the server by the `executeQuery()`.\r\n  - The rows are all dumped at once on the servlet output stream by the server.\r\n  - The client side gets the `ResultSet` content as a file.\r\n  - All `ResultSet` navigation commands are executed locally on the client side by navigating through the file:  `next()`, `prev(`), `first()`, `last()`, etc. \r\n  \r\n- **It is highly recommended to always use  batch commands  when you have many rows to INSERT or UPDATE.**\r\n\r\n\r\n\r\n## *[Advertisement] 📢*\r\n\r\n## *Transform Your Development with ChatMotor API! 🚀*\r\n\r\n[ChatMotor](https://www.chatmotor.ai/) API is designed to make your development life easier by handling the complexities of OpenAI and ChatGPT:\r\n\r\n- 🌟 **Seamless Integration**: No need to learn the intricacies of OpenAI APIs and their limitations. ChatMotor handles chunking, HTTP errors, and retry management.\r\n- 📄 **Excel Handling**: Allow your end user to easily process and manipulate large Excel files using simple prompts. Much easier for them than endless VBA or painful Python coding.\r\n- 📝 **Unlimited Input Sizes**: Seamlessly handle prompts that exceed 4096 tokens with automatic sequencing and parallel task threading for speed, allowing you to treat large inputs without dwelling on the details.\r\n- 🎙️ **Hassle-Free Transcriptions**: Simply provide the audio files for transcription, regardless of format and size. ChatMotor handles everything, including gigantic files, and delivers a clean, formatted text file.\r\n- 🌐 **Advanced Translation**: Handle documents of any size with ease. Just pass them to the API, and it will manage everything, delivering accurate and fast results.\r\n\r\n**✨ Faster and Easier Delivery for Your End User: Save Time, Reduce Complexity, and Focus on What Matters!**\r\n\r\n👉 Explore [**ChatMotor**](https://www.chatmotor.ai) and revolutionize your development workflow!\r\n\r\n---\r\n\r\n# Using the AceQL Client JDBC Driver\r\n\r\nWe will use the same `sampledb` database for all our code samples. \r\n\r\nThe schema is available here: [sampledb.txt](https://docs.aceql.com/rest/soft_java_client/9.4/src/sampledb.txt). \r\n\r\n## Connection creation\r\n\r\nUsage of the AceQL Client JDBC Driver is straightforward: it just requires to create a `Connection` as you would do with any other JDBC Driver. There \r\n\r\nThe  `Connection` to the remote database is created using the standard [DriverManager.getConnection(String url, Properties info)](https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html#getConnection-java.lang.String-java.util.Properties-) JDBC method and passing the URL of the `ServerSqlManager` Servlet of your server configuration:\r\n\r\n```java\r\n    // The URL of the AceQL Server servlet\r\n    // Port number is the port number used to start the Web Server:\r\n    String url = \"https://www.acme.com:9443/aceql\";\r\n\r\n    // The remote database to use:\r\n    String database = \"sampledb\";\r\n\r\n    // (user, password) for authentication on server side.\r\n    String user = \"MyUsername\";\r\n    String password = \"MySecret\";\r\n\r\n    // Register Driver\r\n    DriverManager.registerDriver(new AceQLDriver());\r\n    Class.forName(AceQLDriver.class.getName());\r\n\r\n    Properties info = new Properties();\r\n    info.put(\"user\", user);\r\n    info.put(\"password\", password);\r\n    info.put(\"database\", database);\r\n\r\n    Connection connection = DriverManager.getConnection(url, info);\r\n```\r\nFrom now on, you can use the connection to execute updates and queries on the remote database, using standard and unmodified JDBC calls. \r\n\r\n## Using a Proxy\r\n\r\nCommunication via a proxy server is done using dedicated `properties`.  Proxy authentication is supported.\r\n\r\n| Property Name   | Property Value                                               | Remarks                                                      |\r\n| --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |\r\n| `proxyType`     | The proxy type.  `DIRECT`, `HTTP` or `SOCKS`. Defaults to `DIRECT`. | if `DIRECT`, no proxy will be used.                          |\r\n| `proxyHostname` | The hostname of the proxy. Defaults to `null`.               | Mandatory value if `proxyType` is not `DIRECT`.              |\r\n| `proxyPort`     | The proxy port. Defaults to `0`.                             | Property must be set as a String.                            |\r\n| `proxyUsername` | The username for an authenticated proxy. Defaults to `null`. | The proxy in use is an authenticated proxy if value is not `null`. |\r\n| `proxyPassword` | The password for an authenticated proxy. Defaults to `null`. | Must be not `null` if `proxyUsername` is set.                |\r\n\r\nSample code:\r\n\r\n```java\r\n    // Proxy info. Port number is passed as a String\r\n    info.put(\"proxyType\", \"HTTP\");\r\n    info.put(\"proxyHostname\", \"localhost\");\r\n    info.put(\"proxyPort\", \"8081\"); \r\n    info.put(\"proxyUsername\", \"myProxyUsername\");\r\n    info.put(\"proxyPassword\", \"myProxyPassword\");\r\n\r\n    // Attempt to establish a connection to the remote database \r\n    // using an HTTP Proxy:\r\n    Connection connection = DriverManager.getConnection(url, info);\r\n```\r\n\r\n## Handling Exceptions\r\n\r\nExcept for `NullPointerException`, exceptions thrown are always an instance of [AceQLException.](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/AceQLConnection.html)\r\n\r\nThe `AceQLException` contains 5 pieces of information :\r\n\r\n| Info             | Description                              |\r\n| ---------------- | ---------------------------------------- |\r\n| Reason           | The error message. Retrieved with `getMessage()`. |\r\n| Error Type       | See below for description. Retrieved with `getErrorCode()`. |\r\n| Cause            | The `Throwable` cause, if any. Retrieved with `getCause()`. |\r\n| Http Status Code | See below for description. Retrieved with `getHttpStatusCode(`). |\r\n| Server Exception | The Exception Stack Trace thrown on the server  side, if any.  \u003cbr /\u003eRetrieved with `getRemoteStackTrace()`. |\r\n\r\n### The error type\r\n\r\nThe error type allows users to get the type of error and where the error occurred. It is retrieved with `AceQLException.getErrorCode()`:\r\n\r\n| Error Type  Value | Description                              |\r\n| ----------------- | ---------------------------------------- |\r\n| 0                 | The error occurred locally on the client  side.  See `getHttpStatusCode()` for more info.  Typical cases: no Internet connection, proxy  authentication required. |\r\n| 1                 | The error is due to a JDBC Exception.  It was raised by the remote JDBC Driver and  is rerouted by AceQL as is.  The JDBC error message is accessible via `getMessage()`  Typical case: an error in the SQL statement.   Examples: wrong table or column name. |\r\n| 2                 | The error was raised by the AceQL Server.  It means that the AceQL Server expected a  value or parameter that was not sent by the client side.  Typical cases: misspelling in URL parameter,  missing required request parameters,   JDBC Connection expiration, etc.  The detailed error message is accessible via `getMessage()`.   See below for the most common AceQL Server  error messages. |\r\n| 3                 | The AceQL Server forbids the execution of the  SQL statement for a security reason.  For security reasons, `getMessage()` gives  access to voluntarily vague details. |\r\n| 4                 | The AceQL Server is on failure and raised an  unexpected Java Exception.  The stack track is included and accessible  via `getRemoteStackTrace()`. |\r\n\r\n### Most common AceQL Server messages\r\n\r\n| AceQL  Sever Error Messages   (AceQLException.getErrorCode()  = 2) |\r\n| :----------------------------------------------------------- |\r\n| AceQL  main servlet not found in path                        |\r\n| An error  occurred during Blob download                      |\r\n| An error  occurred during Blob upload                        |\r\n| Blob  directory defined in `DatabaseConfigurator.getBlobDirectory()` does not exist |\r\n| Connection  is invalidated (probably expired).               |\r\n| Database  does not exist                                     |\r\n| Invalid  blob_id. Cannot be used to create a file            |\r\n| Invalid  blob_id. No Blob corresponding to blob_id           |\r\n| Invalid  session_id.                                         |\r\n| Invalid  username or password.                               |\r\n| No action  found in request.                                 |\r\n| Unable to  get a `Connection`.                               |\r\n| Unknown  SQL action or not supported by software             |\r\n\r\n### HTTP Status Codes\r\n\r\nThe HTTP Status Code is accessible with `AceQLException.getHttpStatusCode()`.\r\n\r\nThe HTTP Status Code is 200 (OK) on successful completion calls.\r\n\r\nWhen an error occurs: \r\n\r\n- If the error type is 0, the HTTP Status Code is returned by the client side and may take all possible values in a malformed HTTP call.\r\n\r\n- If the error type is \u003e 0, the HTTP Status Code can take one the following values returned by server side:\r\n\r\n\r\n| HTTP  Status  Code          | Description                              |\r\n| --------------------------- | ---------------------------------------- |\r\n| 400 (BAD REQUEST)           | Missing element in URL path.\u003cbr\u003eMissing request parameters.\u003cbr\u003eAll JDBC errors raised by the remote JDBC Driver. |\r\n| 401 (UNAUTHORIZED)          | Invalid username or password in connect.\u003cbr /\u003eInvalid session_id.\u003cbr /\u003eThe AceQL Server forbade the execution of the SQL statement for  security reasons. |\r\n| 404 (NOT_FOUND)             | BLOB directory does not exist on server.\u003cbr /\u003eBLOB file not found on server. |\r\n| 500 (INTERNAL_SERVER_ERROR) | The AceQL Server is on failure and  raised an unexpected Java Exception. |\r\n\r\n## Data types \r\n\r\nThe main JDBC data types for columns are supported: \r\n\r\nBoolean, Blob, Integer, Short, Double, Float, BigDecimal, Long,String, Date, Time, Timestamp, and Array.  \r\n\r\n## SQL Transactions and Connections modifiers\r\n\r\nThe AceQL Client JDBC Driver support SQL transactions with:\r\n\r\n- `Connection.commit()`\r\n- `Connection.rollback()`\r\n- Connection.`setAutoCommit(boolean autoCommit)`\r\n\r\nThe following Connections modifiers calls are supported in this version:\r\n\r\n- `Connection.setHoldability(int holdability)`\r\n\r\n- `Connection.setTransactionIsolation(int level)`\r\n\r\n- `Connection.setReadOnly(boolean readOnly)`\r\n\r\n## Using Stored Procedures\r\n\r\nStored procedures are supported through the native unmodified JDBC syntax. Database product dialects are not supported, as the AceQL JDBC Driver uses only the common JDBC syntax for stored procedures.\r\n\r\n### Using Oracle Database stored procedures with SELECT calls\r\n\r\nOracle Database stored procedures with SELECT calls are supported starting AceQL HTTP server version 12.0.\r\n\r\nAssuming this Oracle Database stored procedure that executes a SELECT call:\r\n\r\n```plsql\r\n-- ORACLE_SELECT_CUSTOMER stored procedure\r\n-- Executes a SELECT on customer table with \r\n-- customer_id as IN parameter\r\ncreate or replace PROCEDURE ORACLE_SELECT_CUSTOMER \r\n    (p_customer_id NUMBER, p_rc OUT sys_refcursor) AS \r\nBEGIN\r\n    OPEN p_rc\r\n    For select customer_id from customer where customer_id \u003e p_customer_id;\r\nEND ORACLE_SELECT_CUSTOMER;\r\n```\r\n\r\nThe JDBC syntax with a Connection using the Oracle JDBC Driver is:\r\n\r\n```java\r\n// Calling the ORACLE_SELECT_CUSTOMER store procedure\r\n// Native Oracle JDBC syntax using an Oracle JDBC Driver:\r\nCallableStatement callableStatement \r\n    = connection.prepareCall(\"{ call ORACLE_SELECT_CUSTOMER(?, ?) }\");\r\ncallableStatement.setInt(1, 2);\r\ncallableStatement.registerOutParameter(2, OracleTypes.CURSOR);\r\ncallableStatement.executeQuery();\r\n\r\nResultSet rs= (ResultSet) callableStatement.getObject(2);\r\n\r\nwhile (rs.next()) {\r\n    System.out.println(rs.getInt(1));\r\n}\r\n```\r\n\r\nBut the JDBC syntax with a Connection using the AceQL JDBC Driver is simplified and does not use `OracleTypes.CURSOR` nor the `(ResultSet) callableStatement.getObject()` cast:\r\n\r\n```java\r\n// Calling the ORACLE_SELECT_CUSTOMER stored procedure.\r\n// JDBC syntax using the AceQL JDBC Driver\r\nCallableStatement callableStatement \r\n    = connection.prepareCall(\"{ call ORACLE_SELECT_CUSTOMER(?, ?) }\");\r\ncallableStatement.setInt(1, 2);\r\nResultSet rs = callableStatement.executeQuery();\r\n\r\nwhile (rs.next()) {\r\n    System.out.println(rs.getInt(1));\r\n}\r\n```\r\n\r\n## Batch management\r\n\r\n[Statement.executeBatch()](https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#executeBatch--)  is supported.  `Statement` and `PreparedStatement` implementations are both supported.\r\n\r\nBatch commands processing is optimized in order to run as fast as possible and consume fewer possible resources:\r\n\r\n- All batch commands \u0026 parameters are send using only one upload at the start of the `Statement.executeBatch()`  processing. \r\n- The upload of the batch commands \u0026 parameters  is done using streaming techniques on the client-side. The incoming reading is also done in streaming on the server side.\r\n- Transactions are supported, so as usual, it's much faster to run in autocommit off.\r\n\r\n**It is highly recommended to always use  batch commands  when you have many rows to INSERT or UPDATE.**\r\n\r\nNote that batch commands are supported with AceQL HTTP Server version 8.0 or higher on server side.\r\n\r\n## BLOB management\r\n\r\nThe AceQL Client JDBC Driver supports BLOB creation and reading. Methods are implemented using streaming techniques to always keep memory consumption low on server side.\r\n\r\nTrivial or unrelated code is skipped with `//...` comments and `null` values are not tested in the sample codes for the sake of clarity.\r\n\r\n### Standard syntax\r\n\r\n#### BLOB creation with standard syntax\r\n\r\n```java\r\n    // BLOB Creation \r\n    // 1) Syntax with PreparedStatement.setBytes\r\n    String sql = \"insert into orderlog values (?, ?, ?, ?, ?, ?, ?, ?, ?)\";\r\n    File file = createMyBlobFile();\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    byte[] bytes = Files.readAllBytes(file.toPath());\r\n    preparedStatement.setBytes(parameterIndex, bytes);\r\n    //...\r\n    preparedStatement.executeUpdate();\r\n```\r\n\r\n```java\r\n    // BLOB Creation \r\n    // 2) Syntax with PreparedStatement.setBlob\r\n    String sql = \"insert into orderlog values (?, ?, ?, ?, ?, ?, ?, ?, ?)\";\r\n    File file = createMyBlobFile();\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    Blob blob = connection.createBlob();\r\n    byte[] bytes = Files.readAllBytes(file.toPath());\r\n    blob.setBytes(1, bytes);\r\n    preparedStatement.setBlob(parameterIndex, blob);\r\n    //...\r\n    preparedStatement.executeUpdate();\r\n```\r\n\r\n#### BLOB reading with standard syntax\r\n```java\r\n    // BLOB Reading\r\n    // 1) Syntax with ResultSet.getBytes\r\n    String sql = \"select * from orderlog where customer_id = ? and item_id = ?\";\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    ResultSet rs = preparedStatement.executeQuery();\r\n    if (rs.next()) {\r\n        //...\r\n        File file = myAppCreateBlobFile();\r\n        byte[] bytes = rs.getBytes(columnIndex);\r\n        InputStream in = new ByteArrayInputStream(bytes);\r\n        Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);\r\n    }\r\n```\r\n```java\r\n    // BLOB Reading\r\n    // 2) Syntax with ResultSet.getBlob\r\n    String sql = \"select * from orderlog where customer_id = ? and item_id = ?\";\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    ResultSet rs = preparedStatement.executeQuery();\r\n    if (rs.next()) {\r\n        //...\r\n        File file = myAppCreateBlobFile();\r\n        Blob blob = rs.getBlob(columnIndex);\r\n        byte[] bytes = blob.getBytes(1, (int)blob.length());\r\n        InputStream in = new ByteArrayInputStream(bytes);\r\n        Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);\r\n    }\r\n```\r\n### Advanced syntax with streaming techniques\r\n\r\nThe advanced syntax allows keeping memory consumption low on server side while uploading very large files (\u003e 2 Gb).\r\n\r\n#### BLOB creation with stream syntax\r\n\r\n```java\r\n    // BLOB Creation \r\n    // 1) Stream syntax with PreparedStatement.setBytes\r\n    String sql = \"insert into orderlog values (?, ?, ?, ?, ?, ?, ?, ?, ?)\";\r\n    File file = myAppCreateBlobFile();\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    InputStream in = new FileInputStream(file); // Stream will be closed by the Driver\r\n    preparedStatement.setBinaryStream(parameterIndex, in, file.length());\r\n    //...\r\n    preparedStatement.executeUpdate();\r\n```\r\n\r\n```java\r\n    // BLOB Creation\r\n    // 2) Stream syntax with PreparedStatement.setBlob\r\n    String sql = \"insert into orderlog values (?, ?, ?, ?, ?, ?, ?, ?, ?)\";\r\n    File file = myAppCreateBlobFile();\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    Blob blob = connection.createBlob();\r\n    OutputStream out = blob.setBinaryStream(1);\r\n    Files.copy(file.toPath(), out);\r\n    preparedStatement.setBlob(parameterIndex, blob);\r\n    //...\r\n    preparedStatement.executeUpdate();\r\n```\r\n\r\n#### BLOB reading with stream syntax\r\n\r\n```java\r\n    // BLOB Reading\r\n    // 1) Stream syntax with ResultSet.getBinaryStream\r\n    String sql = \"select * from orderlog where customer_id = ? and item_id = ?\";\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    ResultSet rs = preparedStatement.executeQuery();\r\n    if (rs.next()) {\r\n        //...\r\n        File file = myAppCreateBlobFile();\r\n        try (InputStream in = rs.getBinaryStream(columnIndex);) {\r\n            Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);\r\n        }\r\n    }\r\n```\r\n```java\r\n    // BLOB Reading\r\n    // 2) Stream syntax with ResultSet.getBlob\r\n    String sql = \"select * from orderlog where customer_id = ? and item_id = ?\";\r\n    PreparedStatement preparedStatement = connection.prepareStatement(sql);\r\n    //...\r\n    ResultSet rs = preparedStatement.executeQuery();\r\n    if (rs.next()) {\r\n        //...\r\n        File file = myAppCreateBlobFile();\r\n        Blob blob = rs.getBlob(columnIndex);\r\n        try (InputStream in = blob.getBinaryStream()) {\r\n            Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);\r\n        }\r\n    }\r\n```\r\n#### Using Progress Bars with Blobs\r\n\r\nUsing Progress Bar when inserting Blobs in a background engine requires two atomic variables:\r\n\r\n- An `AtomicInteger` that represents the Blob transfer progress between 0 and 100.\r\n\r\n- An `AtomicBoolean` that says if the end user has cancelled the Blob transfer. \r\n\r\n\r\nThe atomic variables values will be shared by AceQL download/upload processes and by the Progress Monitor.\r\n\r\nThe values are to be initialized and passed to `AceQLConnection` before the JDBC actions with the static setters:\r\n\r\n- [AceQLConnection.setProgress(AtomicInteger progress)](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/AceQLConnection.html#setProgress(java.util.concurrent.atomic.AtomicInteger))\r\n- [AceQLConnection.setCancelled(AtomicBoolean cancelled)](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/AceQLConnection.html#setCancelled(java.util.concurrent.atomic.AtomicBoolean))\r\n\r\n\r\nValues will then be updated and read:\r\n\r\n- Progress value will be updated by the `AceQLConnection`.\r\n\r\n- Canceled value will be updated to true if user cancels the task, and `AceQLConnection` will thus interrupt the Blob/Clob transfer.\r\n\r\n\r\nRemember to always set the progress value to 100 at end of a successful or failed operation in order to close the Progress Monitor.\r\n\r\n**Example:** \r\n\r\nThe first step is to declare the 2 atomic variables: \r\n\r\n```java\r\n    /** Progress value between 0 and 100. Will be used by progress monitor. */\r\n    private AtomicInteger progress = new AtomicInteger();\r\n\r\n    /** Says if user has cancelled the Blob/Clob upload or download */\r\n    private AtomicBoolean cancelled = new AtomicBoolean();\r\n```\r\n\r\nThe atomic variables will be passed to the `AceQLConnection` with their setter:\r\n\r\n```java\r\n    /**\r\n     * SQL insert with BLOB column\r\n     */\r\n    private void doInsert() {\r\n        try {\r\n            // BEGIN MODIFY WITH YOUR VALUES\r\n            String url = \"http://localhost:9090/aceql\";\r\n            String database = \"sampledb\";\r\n            String username = \"username\";\r\n            String password = \"password\";\r\n            String myFolder = \"c:\\\\myFolder\";\r\n            File imageFile = new File(System.getProperty(\"user.home\") \r\n                + File.separator + \"image_1.jpg\");\r\n            // END MODIFY WITH YOUR VALUES\r\n\r\n            // Register Driver \r\n            DriverManager.registerDriver(new AceQLDriverPro());\r\n            Class.forName(AceQLDriverPro.class.getName());\r\n\r\n            Properties info = new Properties();\r\n            info.put(\"user\", username);\r\n            info.put(\"password\", password);\r\n            info.put(\"database\", database);\r\n            info.put(\"licenseKeyFolder\", myFolder);\r\n\r\n            // Open a connection\r\n            Connection connection = DriverManager.getConnection(url, info);\r\n\r\n            // Pass the mutable \u0026 sharable progress and canceled to the\r\n            // underlying RemoteConnection.\r\n            // - progress value will be updated by the RemoteConnection and\r\n            // retrieved by SwingWorker to increment the progress.\r\n            // - cancelled value will be updated to true if user cancels the\r\n            // task and RemoteConnection will interrupt the Blob upload.\r\n\r\n            ((AceQLConnection) connection).setProgress(progress);\r\n            ((AceQLConnection) connection).setCancelled(cancelled);\r\n\r\n            // Now run our insert\r\n            BlobExample blobExample = new BlobExample(connection);\r\n            // Delete if duplicate\r\n            blobExample.deleteOrderlog(1, 1);\r\n           \tblobExample.insertOrderWithImage(1, 1, \"description\", \r\n\t\t    \tnew BigDecimal(\"99.99\"), imageFile);\r\n            System.out.println(\"Blob upload done.\");\r\n\r\n        } catch (Exception e) {\r\n            if (e instanceof SQLException \u0026\u0026 e.getCause() != null \r\n                \u0026\u0026 e.getCause() instanceof InterruptedException) {\r\n                System.out.println(e.getMessage());\r\n                return;\r\n            }\r\n            e.printStackTrace();\r\n        } finally {\r\n            // Always set progress to maximum/end value\r\n            // to close the progress monitor\r\n            progress.set(100);\r\n        }\r\n    }\r\n\r\n```\r\n\r\nAssuming hat you want to display a progress indicator using `SwingWorker`, you would start the preceding code as a Thread. To update the progress bar, the `SwingWorker.doInBackground()` method would be overridden as follows: \r\n\r\n```java\r\n\t@Override\r\n\tpublic Void doInBackground() {\r\n\t    cancelled.set(false);\r\n\t    progress.set(0);\r\n\t    \r\n\t    setProgress(0);\r\n\t    \r\n\t    while (progress.get() \u003c 100) {\r\n            try {\r\n                Thread.sleep(50);\r\n            } catch (InterruptedException ignore) {\r\n            }\r\n\r\n            if (isCancelled()) {\r\n                // If end user cancels the task, say it to mutable \r\n                    // \u0026 shareable cancelled. \r\n                    //cancelled will be read by AceQLConnection to\r\n                // interrupt blob upload\r\n                cancelled.set(true);\r\n                break;\r\n            }\r\n\r\n            // Get the progress value between 0 and 100 that\r\n            // is updated by doInsert in background thread\r\n            setProgress(Math.min(progress.get(), 100));\r\n\t    }\r\n\r\n\t    return null;\r\n\t}\r\n```\r\n\r\nA complete example is available in [SqlProgressMonitorDemo.java](https://docs.aceql.com/rest/soft_java_client/9.4/src/SqlProgressMonitorDemo.java) and [BlobExample.java](https://docs.aceql.com/rest/soft_java_client/9.4/src/BlobExample.java) \r\n\r\n## HTTP session options \r\n\r\nYou can set the http timeout values with the properties to pass at `Connection` creation:\r\n\r\n| Property Name    | Property value                                               |\r\n| ---------------- | ------------------------------------------------------------ |\r\n| `connectTimeout` | Timeout value, in milliseconds, to be used when opening a communications link to the remote server. If the timeout expires before the connection can be established, a j`ava.net.SocketTimeoutException` is raised. A timeout of zero is interpreted as an infinite timeout. Defaults to `0` |\r\n| `readTimeout`    | Read timeout to a specified timeout, in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. If the timeout expires before there is data available for read, a java.net.`SocketTimeoutException` is raised. A timeout of zero is interpreted as an infinite timeout. Defaults to `0`. |\r\n\r\n## Using the AceQL Metadata Query API \r\n\r\nThe AceQL Metadata Query API is an helper API that allows:\r\n\r\n- downloading a remote database schema\r\n  in HTML or text format,\r\n- to get a remote database main properties,\r\n- to get the list of tables, \r\n- to get the details of each table. \r\n\r\nIt also allows wrapping remote tables, columns, indexes, etc. into easy to use provided Java classes: `Table`, `Index`, `Column`, etc.\r\n\r\nFirst step is to get an instance of `RemoteDatabaseMetaData`:\r\n\r\n```java\r\n    RemoteDatabaseMetaData remoteDatabaseMetaData = \r\n        ((AceQLConnection) connection).getRemoteDatabaseMetaData();\r\n```\r\n\r\n### Downloading database schema into a file\r\n\r\nDownloading a schema into a Java `File` is done through the method. See the `RemoteDatabaseMetaData` [javadoc](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/metadata/RemoteDatabaseMetaData.html).\r\n\r\n```java\r\n    File file = new File(\"db_schema.out.html\");\r\n    remoteDatabaseMetaData.dbSchemaDownload(file);\r\n```\r\n\r\nSee an example of the built HTML schema:  [db_schema.out.html](https://docs.aceql.com/rest/soft_java_client/9.4/src/db_schema.out.html)\r\n\r\n### Accessing remote database main properties\r\n\r\nThe [JdbcDatabaseMetaData](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/metadata/JdbcDatabaseMetaData.html) class wraps instance the main value retrieved by a remote JDBC call to `Connection.getMetaData`(): \r\n\r\n```java\r\n    JdbcDatabaseMetaData jdbcDatabaseMetaData = remoteDatabaseMetaData.getJdbcDatabaseMetaData();\r\n    System.out.println(\"Major Version: \" + jdbcDatabaseMetaData.getDatabaseMajorVersion());\r\n    System.out.println(\"Minor Version: \" + jdbcDatabaseMetaData.getDatabaseMinorVersion());\r\n    System.out.println(\"isReadOnly   : \" + jdbcDatabaseMetaData.isReadOnly());\r\n```\r\n\r\n### Getting Details of Tables and Columns\r\n\r\nSee the [javadoc](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/metadata/package-summary.html) of the `com.aceql.jdbc.commons.metadata` package: \r\n\r\n```java\r\n    System.out.println(\"Get the table names:\");\r\n    List\u003cString\u003e tableNames = remoteDatabaseMetaData.getTableNames();\r\n\r\n    System.out.println(\"Print the details of each table:\");\r\n    for (String tableName : tableNames) {\r\n        System.out.println();\r\n        Table table = remoteDatabaseMetaData.getTable(tableName);\r\n\r\n        System.out.println();\r\n        System.out.println(\"Columns      : \" + table.getColumns());\r\n        System.out.println(\"Indexes      : \" + table.getIndexes());\r\n        System.out.println(\"Primary Keys : \" + table.getPrimaryKeys());\r\n        System.out.println(\"Exported Keys: \" + table.getExportedforeignKeys());\r\n        System.out.println(\"Imported Keys: \" + table.getImportedforeignKeys());\r\n    }\r\n```\r\n\r\n## Using the native JDBC Metadata Query API\r\n\r\n### Code Sample\r\n\r\nStandard JDBC [DatabaseMetadata](https://docs.aceql.com/rest/soft_java_client/9.4/javadoc/com/aceql/jdbc/commons/metadata/JdbcDatabaseMetaData.html)  and [ResultSetMetadata](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSetMetaData.html) calls are fully supported.\r\n\r\n`DatabaseMetaData` example:\r\n\r\n```java\r\n    // connection is an AceQL Connection\r\n    Connection connection = DriverManager.getConnection(url, info);\r\n\r\n    // Retrieves DatabaseMetaData\r\n    String schema = null;\r\n    String catalog = null;\r\n\r\n    DatabaseMetaData databaseMetaData = connection.getMetaData();\r\n    ResultSet rs = databaseMetaData.getColumns(schema, catalog, null, null);\r\n\r\n    while (rs.next()) {\r\n        String tableCat = rs.getString(\"TABLE_CAT\");\r\n        String tableShem = rs.getString(\"TABLE_SCHEM\");\r\n        String tableName = rs.getString(\"TABLE_NAME\");\r\n        String colName = rs.getString(\"COLUMN_NAME\");\r\n        String dataType = rs.getString(\"DATA_TYPE\");\r\n\r\n        System.out.println(\"TABLE_CAT  : \" + tableCat);\r\n        System.out.println(\"TABLE_SCHEM: \" + tableShem);\r\n        System.out.println(\"TABLE_NAME : \" + tableName);\r\n        System.out.println(\"COLUMN_NAME: \" + colName);\r\n        System.out.println(\"DATA_TYPE  : \" + dataType);\r\n    }\r\n    rs.close();\r\n```\r\n\r\n`ResultSetMetaData` example:\r\n\r\n```java\r\n    // connection is an AceQL Connection\r\n    Connection connection = DriverManager.getConnection(url, info);\r\n\r\n    String sql = \"select * from customer where customer_id = 1\";\r\n    Statement statement = connection.createStatement();\r\n    statement.execute(sql);\r\n\r\n    ResultSet rs = statement.getResultSet();\r\n\r\n    // Retrieves the number, types and properties of this ResultSet object's columns.\r\n    ResultSetMetaData resultSetMetaData = rs.getMetaData();\r\n\r\n    int count = resultSetMetaData.getColumnCount();\r\n    System.out.println(\"resultSetMetaData.getColumnCount(): \" + count);\r\n\r\n    for (int i = 1; i \u003c count + 1; i++) {\r\n        System.out.println();\r\n        System.out.println(\"Column name     : \" + resultSetMetaData.getColumnName(i));\r\n        System.out.println(\"Column label    : \" + resultSetMetaData.getColumnLabel(i));\r\n        System.out.println(\"Column type     : \" + resultSetMetaData.getColumnType(i));\r\n        System.out.println(\"Column type name: \" + resultSetMetaData.getColumnTypeName(i));\r\n    }\r\n```\r\n\r\n### Using Database viewers with the AceQL Client JDBC Driver\r\n\r\nThe following JDBC Database viewers are supported :\r\n\r\n[DBeaver](https://dbeaver.io/), [DbVisualizer](https://www.dbvis.com/), [JetBrains DataGrip](https://www.jetbrains.com/datagrip/), [RazorSQL](https://razorsql.com/), [SQuirreL SQL](http://squirrel-sql.sourceforge.net/)\r\n\r\nThese snapshots show usage of a remote AceQL Connection in DBeaver:\r\n\r\n\u003cimg src=\"https://download.aceql.com/img/dbeaver_metadata.png\" alt=\"DBeaver MetaData\"/\u003e\r\n\r\n\r\n\r\n\u003cimg src=\"https://download.aceql.com/img/dbeaver_select.png\" alt=\"DbVisualizer MetaData\"/\u003e\r\n\r\n### Disabling JDBC MetaData calls when not required\r\n\r\n`MetaData` data is automatically downloaded along with the `ResultSet` content. This default setting allows faster usage with database viewers (by eliminating separated server calls.)\r\n\r\nIf your application never calls `ResultSet.getMetaData()`, it's better to disallow the default behavior by passing the `resultSetMetaDataPolicy` property set to `off` value:\r\n\r\n```java\r\n    // Do not download the metadata along with ResultSet content:\r\n    info.put(\"resultSetMetaDataPolicy \", \"off\"); \r\n    Connection connection = DriverManager.getConnection(url, info);\r\n```\r\n\r\n## Using outer authentication without a password and with an AceQL Session ID\r\n\r\nSome working environments (Intranet, etc.) require that the client user authenticates himself *without* a password. Thus, it is not possible for this users to authenticate though the AceQL Client JDBC Driver.\r\n\r\nIn this case, you may use directly the native HTTP [login](https://github.com/kawansoft/aceql-http/blob/master/aceql-http-user-guide-api.md#login) API to authenticate the users and retrieve the `session_id` returned by the API.\r\n\r\nThe `session_id` value will be passed to the dedicated `sessionId` property:\r\n\r\n```java\r\n    Properties info = new Properties();\r\n    info.put(\"user\", user);\r\n    info.put(\"database\", database);\r\n    info.put(\"licenseKeyFolder\", \"c:\\\\myFolder\"); \r\n\r\n    String sessionId = getMySessionIdFromApiLogin();\r\n    info.put(\"sessionId\", sessionId); \r\n\r\n    Connection connection = DriverManager.getConnection(url, info);\r\n```\r\n\r\n## Passing request headers for validation on server side\r\n\r\nYou may pass any request headers to the AceQL server side for a validation process: just prefix the header name with the `request-property-` prefix and pass it as as a property to `DriverManager.getConnection(url, info)`. \r\n\r\nExample code that passes two request headers `token-1` \u0026 `token-2`:\r\n\r\n```java\r\n    info.put(\"request-property-token-1\", \"value_of_token_1\");\r\n    info.put(\"request-property-token-2\", \"value_of_token_2\");\r\n\r\n    Connection connection = DriverManager.getConnection(url, info);\r\n```\r\nThe request headers will be intercepted on the server side by the `validate` method of your Java class that implements the [RequestHeadersAuthenticator](https://docs.aceql.com/rest/soft/11.0/javadoc/org/kawanfw/sql/api/server/auth/headers/RequestHeadersAuthenticator.html) interface.\r\n\r\nSee also the Headers Authentication sub-section in the [aceql-server.properties](https://docs.aceql.com/rest/soft/11.0/src/aceql-server.properties) file for details about declaring your `RequestHeadersAuthenticator` concrete implementation on server side.\r\n\r\n# Limitations \r\n\r\nThe following JDBC features are not supported nor implemented in this version. They will be added in future versions: \r\n\r\n\r\n- `ROWID` are not supported.\r\n- Auto-generated keys are not supported.\r\n- Some Advanced data types:   `Struct`, `NClob`, `SQLXML` and `Typemaps`.\r\n- Some Statement methods: `getWarnings`, `isPoolable`/`setPoolable`, `getMoreResults`, `setCursorName`.\r\n- Updatable Result Set.\r\n- `RowSet` Objects.\r\n\r\n_________","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkawansoft%2Faceql-http-client-jdbc-driver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkawansoft%2Faceql-http-client-jdbc-driver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkawansoft%2Faceql-http-client-jdbc-driver/lists"}